예제 #1
0
def toggleBlock():
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList, False)

    if idx != -1:
        # Get current value
        v = BLOCK_START_SEARCH_RE.search(str(document.line(blocksList[idx][0]))).group(1)
        # Toggle it!
        if v in ('0', 'false'):
            newValue = '1'
        elif v in ('1', 'true'):
            newValue = '0'
        else:
            return

        # Replace string
        document.startEditing()                                 # Start edit transaction
        document.removeLine(blocksList[idx][0])
        # TODO Do not lose formatting!
        document.insertLine(blocksList[idx][0], "#if " + newValue)
        document.endEditing()                                   # End transaction
    else:
        ui.popup("Oops", "It seems cursor positioned out of any #if0/#if1 block", "face-sad")
예제 #2
0
def changeParagraphWidth(step):
    view = kate.activeView()
    doc = kate.activeDocument()
    pos = view.cursorPosition()

    originRange, isBlock = getParagraphRange(doc, pos)
    if originRange.isEmpty():
        ui.popup("Sorry", "can't detect commented paragraph at cursor...",
                 "face-sad")
        return  # Dunno what to do on empty range!

    indent = common.getCurrentLineIndentation(view)  # detect current align
    # Processing:
    # 0) split text into left stripped lines
    originalText = view.document().text(originRange)
    lines = [line.lstrip() for line in originalText.split('\n')]
    # 1) detect comment style
    comment = [c.strip() for c in lines[0].split(' ')][0]
    # 2) strip leading comments (and possible left spaces) from each line
    lines = [line[len(comment):].lstrip() for line in lines]
    # 3) get a desired width of the current paragraph
    if step == -1:
        # 3.1) For shrink it is really simple: we just want to fit last word
        # to the next line, and it is enough to specify max(line size) - 1
        newSize = len(max(lines, key=len)) - 1
    elif step == 1:
        # 3.2) To extend paragraph we just want to append a first word from the next
        # after longest line.
        currentMax = 0
        prevLineWasLongest = False
        delta = 0
        for line in lines:
            # 3.2.1) if current maximum was changed on prevoius iteration,
            # get length of a first word on a line
            if prevLineWasLongest:
                # NOTE +1 for one space
                delta = len([word.strip() for word in line.split(' ')][0]) + 1
            # 3.2.2) is current line longer than we've seen before?
            lineSize = len(line)
            prevLineWasLongest = bool(currentMax < lineSize)
            if prevLineWasLongest:
                currentMax = lineSize
        newSize = currentMax + delta
    else:
        assert (not "Incorrect step specified")

    # 4) wrap the text
    res = textwrap.wrap(' '.join(lines), newSize, break_long_words=False)
    # 5) form a text from the result list
    align = ' ' * indent + comment + ' '
    text = align + ('\n' + align).join(res) + '\n'

    # Return text only if smth really changed
    if originalText != text:  # Update document only if smth really has changed
        doc.startEditing()  # Start edit transaction:
        doc.removeText(originRange)  # Remove the origin range
        doc.insertText(originRange.start(), text)  # Insert modified text
        view.setCursorPosition(originRange.start(
        ))  # Move cursor to the start of the origin range
        doc.endEditing()  # End transaction
예제 #3
0
def test():
    doc = kate.activeDocument()
    view = kate.activeView()
    ui.popup(
        text="Current document MIME type: <b>" + doc.mimeType() + "</b><br/>hl: <b>" + doc.highlightingMode() + "</b>"
      , caption="Some document info: file type"
      , iconName="face-wink"
      )
예제 #4
0
파일: decorators.py 프로젝트: sewaiper/kate
 def comment_char_checker(dummy, document):
     doc_type = document.highlightingMode()
     result = common.isKnownCommentStyle(doc_type)
     if not result:
         ui.popup(
             "Oops!", "Don't know how comments look like for " +
             doc_type + " documents!", "face-uncertain")
     return result
예제 #5
0
파일: decorators.py 프로젝트: sewaiper/kate
 def doc_type_checker(doc_types, document):
     doc_type = document.highlightingMode()
     if doc_type not in doc_types:
         ui.popup(
             "Alert", "This action have no sense for " + doc_type +
             " documents!", "face-wink")
         return False
     return True
예제 #6
0
def changeParagraphWidth(step):
    view = kate.activeView()
    doc = kate.activeDocument()
    pos = view.cursorPosition()

    originRange, isBlock = getParagraphRange(doc, pos)
    if originRange.isEmpty():
        ui.popup("Sorry", "can't detect commented paragraph at cursor...", "face-sad")
        return                                              # Dunno what to do on empty range!

    indent = getCurrentLineIndentation(view)                # detect current align
    # Processing:
    # 0) split text into left stripped lines
    originalText = view.document().text(originRange)
    lines = [line.lstrip() for line in originalText.split('\n')]
    # 1) detect comment style
    comment = [c.strip() for c in lines[0].split(' ')][0]
    # 2) strip leading comments (and possible left spaces) from each line
    lines = [line[len(comment):].lstrip() for line in lines]
    # 3) get a desired width of the current paragraph
    if step == -1:
        # 3.1) For shrink it is really simple: we just want to fit last word
        # to the next line, and it is enough to specify max(line size) - 1
        newSize = len(max(lines, key=len)) - 1
    elif step == 1:
        # 3.2) To extend paragraph we just want to append a first word from the next
        # after longest line.
        currentMax = 0
        prevLineWasLongest = False
        delta = 0
        for line in lines:
            # 3.2.1) if current maximum was changed on prevoius iteration,
            # get length of a first word on a line
            if prevLineWasLongest:
                # NOTE +1 for one space
                delta = len([word.strip() for word in line.split(' ')][0]) + 1
            # 3.2.2) is current line longer than we've seen before?
            lineSize = len(line)
            prevLineWasLongest = bool(currentMax < lineSize)
            if prevLineWasLongest:
                currentMax = lineSize
        newSize = currentMax + delta
    else:
        assert(not "Incorrect step specified")

    # 4) wrap the text
    res = textwrap.wrap(' '.join(lines), newSize, break_long_words=False)
    # 5) form a text from the result list
    align = ' ' * indent + comment + ' '
    text = align + ('\n' + align).join(res) + '\n'

    # Return text only if smth really changed
    if originalText != text:                                # Update document only if smth really has changed
        doc.startEditing()                                  # Start edit transaction:
        doc.removeText(originRange)                         # Remove the origin range
        doc.insertText(originRange.start(), text)           # Insert modified text
        view.setCursorPosition(originRange.start())         # Move cursor to the start of the origin range
        doc.endEditing()                                    # End transaction
예제 #7
0
 def doc_type_checker(doc_types, document):
     doc_type = document.highlightingMode()
     if doc_type not in doc_types:
         ui.popup(
             "Alert"
           , "This action have no sense for " + doc_type + " documents!"
           , "face-wink"
           )
         return False
     return True
예제 #8
0
 def comment_char_checker(dummy, document):
     doc_type = document.highlightingMode()
     result = common.isKnownCommentStyle(doc_type)
     if not result:
         ui.popup(
             "Oops!"
           , "Don't know how comments look like for " + doc_type + " documents!"
           , "face-uncertain"
           )
     return result
예제 #9
0
파일: decorators.py 프로젝트: sewaiper/kate
 def selection_mode_checker(selectionMode, document):
     view = document.activeView()
     result = selectionMode == view.blockSelection()
     if not result:
         if selectionMode:
             mode = 'block'
         else:
             mode = 'normal'
         ui.popup("Oops!",
                  "This operation is for %s selection mode!" % mode,
                  "face-sad")
     return result
예제 #10
0
파일: decorators.py 프로젝트: sewaiper/kate
 def has_selection_checker(selectionState, document):
     view = document.activeView()
     result = selectionState == view.selection()
     print("*** has_selection: result=%s" % repr(result))
     if not result:
         if not selectionState:
             should = "n't"
         else:
             should = ''
         ui.popup(
             "Oops!",
             "Document should%s have selection to perform this operation"
             % should, "face-sad")
     return result
예제 #11
0
 def selection_mode_checker(selectionMode, document):
     view = document.activeView()
     result = selectionMode == view.blockSelection()
     if not result:
         if selectionMode:
             mode = 'block'
         else:
             mode = 'normal'
         ui.popup(
             "Oops!"
           , "This operation is for %s selection mode!" % mode
           , "face-sad"
           )
     return result
예제 #12
0
def selectBlock():
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList)

    if idx != -1:
        r = KTextEditor.Range(blocksList[idx][0], 0, blocksList[idx][1] + 1, 0)
        view.setSelection(r)
    else:
        ui.popup("Oops", "It seems cursor positioned out of any #if0/#if1 block", "face-sad")
예제 #13
0
 def has_selection_checker(selectionState, document):
     view = document.activeView()
     result = selectionState == view.selection()
     print("*** has_selection: result=%s" % repr(result))
     if not result:
         if not selectionState:
             should = "n't"
         else:
             should = ''
         ui.popup(
             "Oops!"
           , "Document should%s have selection to perform this operation" % should
           , "face-sad"
           )
     return result
예제 #14
0
def removeBlock():
    ''' Remove a block of code commented with #if0 or #if1-#else'''
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList, False)

    if idx != -1:
        # Get current value
        v = BLOCK_START_SEARCH_RE.search(str(document.line(
            blocksList[idx][0]))).group(1)
        # Do nothing if it's not a #if0/#if1
        if v not in ('0', 'false', '1', 'true'):
            return

        document.startEditing()  # Start edit transaction
        # What to remove?
        if v in ('0', 'false'):  # Remove `then` part
            if blocksList[idx][2] != -1:  # Is there `#else` part?
                # Yeah! Remove `#endif` line and then from `#if` to `#else` (including)
                document.removeLine(blocksList[idx][1])
                r = KTextEditor.Range(blocksList[idx][0], 0,
                                      blocksList[idx][2] + 1, 0)
            else:
                # No! So just remove whole block
                r = KTextEditor.Range(blocksList[idx][0], 0,
                                      blocksList[idx][1] + 1, 0)
            document.removeText(r)
        else:
            if blocksList[idx][2] != -1:  # Is there `#else` part?
                # Yeah! Remove from `#else` to `#endif` block and then `#if` line
                r = KTextEditor.Range(blocksList[idx][2], 0,
                                      blocksList[idx][1] + 1, 0)
                document.removeText(r)
                document.removeLine(blocksList[idx][0])
            else:
                # No! Ok just remove `#endif` line and then `#if`
                document.removeLine(blocksList[idx][1])
                document.removeLine(blocksList[idx][0])
        document.endEditing()  # End transaction
    else:
        ui.popup("Oops",
                 "It seems cursor positioned out of any #if0/#if1 block",
                 "face-sad")
예제 #15
0
def selectBlock():
    '''Set selection of a current (where cursor positioned) #if0/#endif block'''
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList)

    if idx != -1:
        r = KTextEditor.Range(blocksList[idx][0], 0, blocksList[idx][1] + 1, 0)
        view.setSelection(r)
    else:
        ui.popup("Oops",
                 "It seems cursor positioned out of any #if0/#if1 block",
                 "face-sad")
예제 #16
0
def removeBlock():
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList, False)

    if idx != -1:
        # Get current value
        v = BLOCK_START_SEARCH_RE.search(str(document.line(blocksList[idx][0]))).group(1)
        # Do nothing if it's not a #if0/#if1
        if v not in ('0', 'false', '1', 'true'):
            return

        document.startEditing()                             # Start edit transaction
        # What to remove?
        if v in ('0', 'false'):                             # Remove `then` part
            if blocksList[idx][2] != -1:                    # Is there `#else` part?
                # Yeah! Remove `#endif` line and then from `#if` to `#else` (including)
                document.removeLine(blocksList[idx][1])
                r = KTextEditor.Range(blocksList[idx][0], 0, blocksList[idx][2] + 1, 0)
            else:
                # No! So just remove whole block
                r = KTextEditor.Range(blocksList[idx][0], 0, blocksList[idx][1] + 1, 0)
            print r
            document.removeText(r)
        else:
            if blocksList[idx][2] != -1:                    # Is there `#else` part?
                # Yeah! Remove from `#else` to `#endif` block and then `#if` line
                r = KTextEditor.Range(blocksList[idx][2], 0, blocksList[idx][1] + 1, 0)
                document.removeText(r)
                document.removeLine(blocksList[idx][0])
            else:
                # No! Ok just remove `#endif` line and then `#if`
                document.removeLine(blocksList[idx][1])
                document.removeLine(blocksList[idx][0])
        document.endEditing()                                   # End transaction
    else:
        ui.popup("Oops", "It seems cursor positioned out of any #if0/#if1 block", "face-sad")
예제 #17
0
파일: format.py 프로젝트: sewaiper/kate
def boostUnformat():
    '''Merge everything between '(' and ')' into a single line'''
    document = kate.activeDocument()
    view = kate.activeView()

    try:
        r, nestedRanges, breakPositions = getRangeTopology(',')
    except LookupError as error:
        ui.popup("Failed to parse C++ expression", str(error), "face-sad")
        return

    if r.isEmpty():  # Is range empty?
        ui.popup("Failed to parse C++ expression",
                 "Didn't found anything to format. Sorry", "face-sad")
        return  # Nothing interesting wasn't found...

    # Rescan the range w/ ';' as breaker added if current range is a `for` statement
    if document.line(r.start().line())[0:r.start().column() -
                                       1].rstrip().endswith('for'):
        try:
            r, nestedRanges, breakPositions = getRangeTopology(',;')
        except LookupError as error:
            ui.popup("Failed to parse C++ expression", str(error), "face-sad")
            return

    # Going to unformat a text whithin a selected range
    text = boostUnformatText(r, breakPositions)
예제 #18
0
def boostFormat():
    document = kate.activeDocument()
    view = kate.activeView()

    try:
        r, nestedRanges, breakPositions = getRangeTopology(',')
    except LookupError as error:
        ui.popup("Failed to parse C++ expression", str(error), "face-sad")
        return

    if r.isEmpty():                                         # Is range empty?
        ui.popup(
            "Failed to parse C++ expression"
          , "Didn't found anything to format. Sorry"
          , "face-sad"
          )
        return                                              # Nothing interesting wasn't found...

    # Rescan the range w/ ';' as breaker added if current range is a `for` statement
    if document.line(r.start().line())[0:r.start().column() - 1].rstrip().endswith('for'):
        try:
            r, nestedRanges, breakPositions = getRangeTopology(',;')
        except LookupError as error:
            ui.popup("Failed to parse C++ expression", str(error), "face-sad")
            return

    # Going to unformat a text whithin a selected range
    text = boostUnformatText(r, breakPositions)
예제 #19
0
def toggleBlock():
    ''' Switch a current code block to ON(#if1) or OFF(#if0) state.

        Current means that cursor placed inside of it.
    '''
    document = kate.activeDocument()
    view = kate.activeView()

    # Make list of ranges of #if*/#endif blocks
    blocksList = buildIfEndifMap(document)

    # Locate a block where cursor currently positioned
    idx = locateBlock(view.cursorPosition().line(), blocksList, False)

    if idx != -1:
        # Get current value
        v = BLOCK_START_SEARCH_RE.search(str(document.line(
            blocksList[idx][0]))).group(1)
        # Toggle it!
        if v in ('0', 'false'):
            newValue = '1'
        elif v in ('1', 'true'):
            newValue = '0'
        else:
            return

        # Replace string
        document.startEditing()  # Start edit transaction
        document.removeLine(blocksList[idx][0])
        # TODO Do not lose formatting!
        document.insertLine(blocksList[idx][0], "#if " + newValue)
        document.endEditing()  # End transaction
    else:
        ui.popup("Oops",
                 "It seems cursor positioned out of any #if0/#if1 block",
                 "face-sad")
예제 #20
0
def boostFormat():
    '''Format function's/template's parameters list (or `for`'s) in a boost-like style
       I.e. when 2nd and the rest parameters has leading comma/semicolon
       and closing ')' or '>' on a separate line.
       THIS IS REALLY BETTER TO HAVE SUCH STYLE WHEN U HAVE A LONG PARAMETERS LIST!
    '''
    document = kate.activeDocument()
    view = kate.activeView()

    try:
        r, nestedRanges, breakPositions = getRangeTopology(',')
    except LookupError as error:
        ui.popup("Failed to parse C++ expression", str(error), "face-sad")
        return

    if r.isEmpty():                                         # Is range empty?
        ui.popup(
            "Failed to parse C++ expression"
          , "Didn't found anything to format. Sorry..."
          , "face-sad"
          )
        return                                              # Nothing interesting wasn't found...

    # Rescan the range w/ ';' as breaker added if current range is a `for` statement
    if document.line(r.start().line())[0:r.start().column() - 1].rstrip().endswith('for'):
        try:
            r, nestedRanges, breakPositions = getRangeTopology(',;')
        except LookupError as error:
            ui.popup("Failed to parse C++ expression", str(error), "face-sad")
            return

    # Going to format a text whithin a selected range
    lineStr = document.line(r.start().line())
    lineStrStripped = lineStr.lstrip()
    indent = len(lineStr) - len(lineStrStripped)
    if lineStrStripped.startswith(', '):
        indent += 2
    text = boostFormatText(r, indent, breakPositions)
예제 #21
0
def expandAtCursor():
    """Attempt text expansion on the word at the cursor.
    The expansions available are based firstly on the mimetype of the
    document, for example "text_x-c++src.expand" for "text/x-c++src", and
    secondly on "all.expand".
    """
    document = kate.activeDocument()
    view = document.activeView()
    try:
        word_range, argument_range = wordAndArgumentAtCursorRanges(
            document, view.cursorPosition())
    except ParseError as e:
        kate.popup('Parse error:', e)
        return
    word = document.text(word_range)
    mime = str(document.mimeType())
    expansions = loadExpansions(mime)
    try:
        func = expansions[word]
    except KeyError:
        ui.popup('Error', 'Expansion "%s" not found :(' % word,
                 'dialog-warning')
        return
    arguments = []
    namedArgs = {}
    if argument_range is not None:
        # strip parentheses and split arguments by comma
        preArgs = [
            arg.strip()
            for arg in document.text(argument_range)[1:-1].split(',')
            if bool(arg.strip())
        ]
        print('>> EXPAND: arguments = ' + repr(arguments))
        # form a dictionary from args w/ '=' character, leave others in a list
        for arg in preArgs:
            print('>> EXPAND: current arg = ' + repr(arg))
            if '=' in arg:
                key, value = [item.strip() for item in arg.split('=')]
                print('>> EXPAND: key = ' + repr(key))
                print('>> EXPAND: value = ' + repr(value))
                namedArgs[key] = value
            else:
                arguments.append(arg)
    # Call user expand function w/ parsed arguments and
    # possible w/ named params dict
    try:
        print('>> EXPAND: arguments = ' + repr(arguments))
        print('>> EXPAND: named arguments = ' + repr(namedArgs))
        if len(namedArgs):
            replacement = func(*arguments, **namedArgs)
        else:
            replacement = func(*arguments)
    except Exception as e:
        # remove the top of the exception, it's our code
        try:
            type, value, tb = sys.exc_info()
            sys.last_type = type
            sys.last_value = value
            sys.last_traceback = tb
            tblist = traceback.extract_tb(tb)
            del tblist[:1]
            l = traceback.format_list(tblist)
            if l:
                l.insert(0, 'Traceback (most recent call last):\n')
            l[len(l):] = traceback.format_exception_only(type, value)
        finally:
            tblist = tb = None
        # convert file names in the traceback to links. Nice.
        def replaceAbsolutePathWithLinkCallback(match):
            text = match.group()
            filePath = match.group(1)
            fileName = os.path.basename(filePath)
            text = text.replace(filePath,
                                '<a href="%s">%s</a>' % (filePath, fileName))
            return text

        s = ''.join(l).strip()
        s = re.sub('File "(/[^\n]+)", line',
                   replaceAbsolutePathWithLinkCallback, s)
        ui.popup('Error', '<p style="white-space:pre">%s</p>' % s,
                 'dialog-error')
        return

    #KateDocumentConfig::cfReplaceTabsDyn
    indentCharacters = indentationCharacters(document)
    # convert newlines followed by tab characters to whatever spacing
    # the user... uses.
    for i in range(100):
        if '\n' + (indentCharacters * i) + '\t' in replacement:
            replacement = replacement.replace(
                '\n' + (indentCharacters * i) + '\t',
                '\n' + (indentCharacters * (i + 1)))
    insertPosition = word_range.start()
    line = document.line(insertPosition.line())
    # autoindent: add the line's leading whitespace for each newline
    # in the expansion
    whitespace = ''
    for character in line:
        if character in ' \t':
            whitespace += character
        else:
            break
    replacement = replacement.replace('\n', '\n' + whitespace)
    # is desired cursor position set?
    cursorAdvancement = None
    if '%{cursor}' in replacement:
        cursorAdvancement = replacement.index('%{cursor}')
        # strip around that word
        replacement = replacement[:cursorAdvancement] + replacement[
            cursorAdvancement + 9:]
    # make the removal and insertion an atomic operation
    document.startEditing()
    if argument_range is not None:
        document.removeText(argument_range)
    document.removeText(word_range)
    document.insertText(insertPosition, replacement)
    # end before moving the cursor to avoid a crash
    document.endEditing()

    if cursorAdvancement is not None:
        # TODO The smartInterface isn't available anymore!
        #      But it's successor (movingInterface) isn't available yet in
        #      PyKDE4 <= 4.8.3 (at least) :( -- so, lets move a cursor manually...
        while True:
            currentLength = document.lineLength(insertPosition.line())
            if cursorAdvancement <= currentLength:
                break
            else:
                insertPosition.setLine(insertPosition.line() + 1)
                cursorAdvancement -= currentLength + 1  # NOTE +1 for every \n char
        insertPosition.setColumn(insertPosition.column() + cursorAdvancement)
        view.setCursorPosition(insertPosition)