def navigateToMatch(self, index): """Jump to the selected entry.""" (fileName, icon, text, nextLine, column, fileAndLine) = self.matchesModel.read(index) if not nextLine: return # # Add a history record for the current point. # cursor = kate.activeView().cursorPosition() currentLine = cursor.line() document = kate.activeDocument() self.historyModel.add( document.localFilePath(), "arrow-right", document.line(currentLine), currentLine, cursor.column(), "{}:{}".format(document.documentName(), currentLine + 1)) # # Navigate to the point in the file. # document = kate.documentManager.openUrl(KUrl.fromPath(fileName)) kate.mainInterfaceWindow().activateView(document) point = KTextEditor.Cursor(nextLine, column) kate.activeView().setCursorPosition(point) # # Add this new point to the history. # self.historyModel.add(fileName, icon, text, nextLine, column, fileAndLine)
def navigateToMatch(self, index): """Jump to the selected entry.""" (fileName, icon, text, nextLine, column, fileAndLine) = self.matchesModel.read(index) if not nextLine: return # # Add a history record for the current point. # cursor = kate.activeView().cursorPosition() currentLine = cursor.line() document = kate.activeDocument() self.historyModel.add( document.url().toLocalFile(), "arrow-right", document.line(currentLine), currentLine, cursor.column(), "{}:{}".format(document.documentName(), currentLine + 1), ) # # Navigate to the point in the file. # document = kate.documentManager.openUrl(KUrl.fromPath(fileName)) kate.mainInterfaceWindow().activateView(document) point = KTextEditor.Cursor(nextLine, column) kate.activeView().setCursorPosition(point) # # Add this new point to the history. # self.historyModel.add(fileName, icon, text, nextLine, column, fileAndLine) self.historyWidget.resizeColumnsToContents()
def navigateToHistory(self, index): """Jump to the selected entry.""" (fileName, icon, text, line, column, fileAndLine) = self.historyModel.read(index) # # Navigate to the original point in the file. # document = kate.documentManager.openUrl(KUrl.fromPath(fileName)) kate.mainInterfaceWindow().activateView(document) point = KTextEditor.Cursor(line, column) kate.activeView().setCursorPosition(point)
def lookup(): global searchBar if show(): if kate.activeView().selection(): selectedText = kate.activeView().selectionText() else: selectedText = wordAtCursor(kate.activeDocument(), kate.activeView()) searchBar.token.insertItem(0, selectedText) searchBar.token.setCurrentIndex(1) searchBar.token.setEditText(selectedText) return searchBar.literalSearch() return None
def lookup(): """Lookup the currently selected token. Find the token, filter the results. """ global searchBar if show(): if kate.activeView().selection(): selectedText = kate.activeView().selectionText() else: selectedText = wordAtCursor(kate.activeDocument(), kate.activeView()) searchBar.token.insertItem(0, selectedText) searchBar.token.setCurrentIndex(1) searchBar.token.setEditText(selectedText) return searchBar.literalSearch() return None
def processLine(line, commentCh): result = [] column = kate.configuration[COMMENT_START_POS] # Split line before and after a comment (before, comment, after) = line.partition(commentCh) before_s = before.rstrip() # Is there a comment on a line? if bool(comment): # Is there is any text before inline comment position? if bool(before_s): # Yes! Is text before not longer than desired comment position if len(before_s) < (kate.configuration[COMMENT_START_POS] + 1): # Yep, just reformat the line... result.append(before_s + (' ' * (kate.configuration[COMMENT_START_POS] - len(before_s))) + commentCh + after.rstrip()) else: # Move comment to the line above column = len(before) - len(before.lstrip()) # NOTE Try to fix Doxygen comment on the fly: '///<' or '//!<' --> '///' if after[1] == '<' and (after[0] == '!' or after[0] == '/'): after = '/' + after[2:] result.append(' ' * column + commentCh + after.rstrip()) result.append(before_s) else: # No! The line contains only whitespaces... # Is comment after or 'close before' to inline comment position? if len(before) > (kate.configuration[COMMENT_START_POS] / 6): # Align comment to desired position... result.append(' ' * kate.configuration[COMMENT_START_POS] + commentCh + after.rstrip()) else: # TODO Align comment to closest to div 4 position... result.append(line.rstrip()) else: # There is no comments... What about any text? if bool(before_s): # Is it longer that inline comment position? if len(before_s) > (kate.configuration[COMMENT_START_POS]): column = len(before) - len(before.lstrip()) result.append(' ' * column + commentCh + ' ') result.append(before_s) else: result.append(before_s + ' ' * (kate.configuration[COMMENT_START_POS] - len(before_s)) + commentCh + ' ') # Check for preprocessor directives #else/#endif and try to append # corresponding #if condition as a comment for current line if bool(BLOCK_ELSE_ENDIF_MATCH_RE.search(before_s)): document = kate.activeDocument() view = kate.activeView() # Make list of ranges of #if*/#endif blocks blocksList = buildIfEndifMap(document) # Locate an index of a block where cursor currently positioned (check commented block too) idx = locateBlock(view.cursorPosition().line(), blocksList, True) # Get #if condition (if block located) if idx != -1: # TODO Need to strip possible comment! matchObj = BLOCK_START_GET_COND_RE.search(document.line(blocksList[idx][0])) if bool(matchObj): result[-1] += matchObj.group(4) else: # No text! Just add a comment... result.append(' ' * kate.configuration[COMMENT_START_POS] + commentCh + ' ') return (result, column + len(commentCh) + 1)
def comment_block(): '''Wrap selected text (or current line) into a #if0/#endif block''' view = kate.activeView() # This operation have no sense for partly selected lines common.extendSelectionToWholeLine(view) start = -1 end = -1 if view.selection(): sr = view.selectionRange() start = sr.start().line() end = sr.end().line() + 1 else: start = view.cursorPosition().line() end = start + 2 # Do it! document = kate.activeDocument() if start != -1 and end != -1: document.startEditing() # Start edit transaction document.insertLine(start, '#if 0') document.insertLine(end, '#endif') view.removeSelection() document.endEditing() # End transaction
def setSelectionFromCurrentPosition(start, end, pos=None): view = kate.activeView() pos = pos or view.cursorPosition() cursor1 = KTextEditor.Cursor(pos.line() + start[0], pos.column() + start[1]) cursor2 = KTextEditor.Cursor(pos.line() + end[0], pos.column() + end[1]) view.setSelection(KTextEditor.Range(cursor1, cursor2)) view.setCursorPosition(cursor1)
def insertHelpItemIntoCurrentDocument(self,item, column): if item is not None and item.type() == cmake_help_parser.help_category.HELP_ITEM and column == 0: view = kate.activeView() document = kate.activeDocument() document.startEditing() document.insertText(view.cursorPosition(), item.text(0)) document.endEditing()
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)
def _dispatch(self): kate.kDebug('@KeySequenceTracker: collected key sequence "{}"'.format(self.sequence)) view = kate.activeView() cursor = view.cursorPosition() word_range = KTextEditor.Range( cursor.line() , cursor.column() - len(self.sequence) - 2 , cursor.line() , cursor.column() ) document = view.document() assert('Sanity check' and view is not None) mimeType = document.mimeType() expansions = getExpansionsFor(mimeType) if not hasattr(dynamic, 'registered_handlers') or mimeType not in dynamic.registered_handlers: return assert('Sanity check' and isinstance(dynamic.registered_handlers[mimeType], list)) for func in dynamic.registered_handlers[mimeType]: assert('Sanity check' and inspect.isfunction(func) and hasattr(func, 'match_regex')) match = func.match_regex.search(self.sequence) if match is not None: result = func(self.sequence, match) self._inject_expand_result(document, result, word_range, func) return
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")
def insertIntoCurrentDocument(self, item, column): if item is not None and column == 0: view = kate.activeView() document = kate.activeDocument() document.startEditing() document.insertText(view.cursorPosition(), item.text(0)) document.endEditing()
def tryOpen(): view = kate.activeView() assert('View expected to be valid' and view is not None) assert('This action supposed to select some text before' and view.selection()) doc = view.document() doc_url = doc.url() new_url = KUrl(_try_make_url_from_text(view.selectionText())) kate.kDebug('Current document URI: {}'.format(repr(doc_url))) # 0) Make sure it is valid if not new_url.isValid(): kate.ui.popup( i18nc('@title:window', 'Error') , i18nc('@info:tooltip', "Selected text doesn't looks like a valid URI") , 'dialog-error' ) return # 1) Is it have some schema? and current document is not 'Untitled'... if new_url.isRelative() and not doc_url.isEmpty(): # Replace filename from the doc_url w/ the current selection new_url = doc_url.upUrl() new_url.addPath(view.selectionText()) kate.kDebug('Trying URI: {}'.format(repr(new_url))) # Ok, try to open it finally _try_open_show_error(new_url)
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)
def viewChanged(): ''' Calls the function when the view changes. To access the new active view, use kate.activeView() ''' global completionModel if completionModel: completionInterface = kate.activeView().codeCompletionInterface() completionInterface.registerCompletionModel(completionModel)
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
def commentBlock(): '''Wrap selected text (or current line) into a #if0/#endif block''' view = kate.activeView() # This operation have no sense for partly selected lines common.extendSelectionToWholeLine(view) start = -1 end = -1 if view.selection(): sr = view.selectionRange() start = sr.start().line() end = sr.end().line() + 1 else: start = view.cursorPosition().line() end = start + 2 # Do it! document = kate.activeDocument() if start != -1 and end != -1: document.startEditing() # Start edit transaction document.insertLine(start, "#if 0") document.insertLine(end, "#endif") view.removeSelection() document.endEditing() # End transaction
def _moveCursorTFirstError(line, column=None): try: column = column or 0 cursor = KTextEditor.Cursor(line - 1, column - 1) view = kate.activeView() view.setCursorPosition(cursor) except KeyError: pass
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" )
def moveCursorTFirstError(line, column=None): try: column = column or 0 cursor = KTextEditor.Cursor(line - 1, column - 1) view = kate.activeView() view.setCursorPosition(cursor) except KeyError: pass
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
def createSignalAutocompleteCMake(view=None, *args, **kwargs): try: view = view or kate.activeView() if view: kate.kDebug('CMake Helper Plugin: Registering completer') cci = view.codeCompletionInterface() cci.registerCompletionModel(_cmake_completion_model) except: kate.kDebug('CMake Helper Plugin: Unable to get an active view')
def viewChanged(): """ Calls the function when the view changes. To access the new active view, use kate.activeView() """ global completionModel if completionModel: view = kate.activeView() if view: completionInterface = view.codeCompletionInterface() completionInterface.registerCompletionModel(completionModel)
def create_frame(pattern_str='', title='', name_field=''): currentDocument = kate.activeDocument() view = kate.activeView() class_name, ok = QtGui.QInputDialog.getText(view, title, name_field) if ok: class_model = class_name.replace('Form', '') text = pattern_str % {'class_name': class_name, 'class_model': class_model} currentDocument.insertText(view.cursorPosition(), text)
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: kate.ui.popup( i18nc('@title:window', 'Alert') , i18nc( '@info:tooltip' , 'Failed to parse C++ expression:<nl/><message>%1</message>', error ) , 'dialog-information' ) return if r.isEmpty(): # Is range empty? kate.ui.popup( i18nc('@title:window', 'Alert') , i18nc( '@info:tooltip' , 'Failed to parse C++ expression:<nl/><message>%1</message>' , i18nc('@info:tooltip', "Did not find anything to format") ) , 'dialog-information' ) 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: kate.ui.popup( i18nc('@title:window', 'Alert') , i18nc( '@info:tooltip' , 'Failed to parse C++ expression:<nl/><message>%1</message>', error ) , 'dialog-information' ) 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)
def init_jquery_autocomplete(view=None): global jquery_ccm if not SETTING_JQUERY_AUTOCOMPLETE.lookup(): return if jquery_ccm is None: jquery_ccm = StaticJQueryCompletionModel(kate.application) jquery_ccm.modelReset.connect(reset) view = view or kate.activeView() cci = view.codeCompletionInterface() cci.registerCompletionModel(jquery_ccm)
def killRestOfLine(): doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() endPosition = KTextEditor.Cursor(pos.line(), doc.lineLength(pos.line())) killRange = KTextEditor.Range(pos, endPosition) doc.startEditing() doc.removeText(killRange) doc.endEditing()
def commentar(): ''' Append or align an inlined comment at position 60 for the current line or the selection. Move cursor to the start of a comment, if nothing has changed. If there wasn't any comment aside of #else/#endif put corresponding #if condition as default comment text ''' document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() commentCh = common.getCommentStyleForDoc(document) if view.selection(): # If selected smth on a single line... common.extendSelectionToWholeLine(view) selectedText = view.selectionText().split('\n') if not bool(selectedText[-1]): selectedText = selectedText[0:-1] insertionText = [] firstColumn = -1 for textLine in selectedText: (currentLine, column) = processLine(textLine, commentCh) if firstColumn == -1: firstColumn = column insertionText += currentLine # Modify current document if bool(insertionText): document.startEditing() document.removeText(view.selectionRange()) pos = view.cursorPosition() document.insertText(pos, '\n'.join(insertionText) + '\n') pos.setColumn(firstColumn) view.setCursorPosition(pos) view.removeSelection() document.endEditing() else: (text, column) = processLine(document.line(pos.line()), commentCh) # Apply result (if smth really has changed) originalText = document.line(pos.line()) if bool(text) and (len(text) != 1 or originalText != text[0]): document.startEditing() # Start edit transaction: document.removeLine(pos.line()) # Remove current line # insert resulting text line by line... pos.setColumn(0) document.insertText(pos, '\n'.join(text) + '\n') document.endEditing() # End transaction # Move cursor to desired position pos.setColumn(column) view.setCursorPosition(pos)
def inline_comment(): ''' Append or align an inlined comment at position 60 for the current line or the selection. Move cursor to the start of a comment, if nothing has changed. If there wasn't any comment aside of #else/#endif put corresponding #if condition as default comment text ''' document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() commentCh = common.getCommentStyleForDoc(document) if view.selection(): # If selected smth on a single line... common.extendSelectionToWholeLine(view) selectedText = view.selectionText().split('\n') if not bool(selectedText[-1]): selectedText = selectedText[0:-1] insertionText = [] firstColumn = -1 for textLine in selectedText: (currentLine, column) = processLine(textLine, commentCh) if firstColumn == -1: firstColumn = column insertionText += currentLine # Modify current document if bool(insertionText): document.startEditing() document.removeText(view.selectionRange()) pos = view.cursorPosition() document.insertText(pos, '\n'.join(insertionText) + '\n') pos.setColumn(firstColumn) view.setCursorPosition(pos) view.removeSelection() document.endEditing() else: (text, column) = processLine(document.line(pos.line()), commentCh) # Apply result (if smth really has changed) originalText = document.line(pos.line()) if bool(text) and (len(text) != 1 or originalText != text[0]): document.startEditing() # Start edit transaction: document.removeLine(pos.line()) # Remove current line # insert resulting text line by line... pos.setColumn(0) document.insertText(pos, '\n'.join(text) + '\n') document.endEditing() # End transaction # Move cursor to desired position pos.setColumn(column) view.setCursorPosition(pos)
def _wrapBlockWithChar(openCh, closeCh, indentMultiline = True): '''Wrap a current word or selection (if any) into given open and close chars If current selection is multiline, add one indentation level and put open/close chars on separate lines ''' doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() selectedRange = view.selectionRange() if selectedRange.isEmpty(): # No text selected. Ok, lets wrap a word where cursor positioned wordRange = common.getBoundTextRangeSL( common.CXX_IDENTIFIER_BOUNDARIES , common.CXX_IDENTIFIER_BOUNDARIES , pos , doc ) _wrapRange(wordRange, openCh, closeCh, doc) else: if selectedRange.start().line() == selectedRange.end().line() or indentMultiline == False: # single line selection (or no special indentation required) _wrapRange(selectedRange, openCh, closeCh, doc) # extend current selection selectedRange = KTextEditor.Range( selectedRange.start() , KTextEditor.Cursor( selectedRange.end().line() , selectedRange.end().column() + len(openCh) + len(closeCh) ) ) view.setSelection(selectedRange) else: # Try to extend selection to be started from 0 columns at both ends common.extendSelectionToWholeLine(view) selectedRange = view.selectionRange() # multiline selection # 0) extend selection to capture whole lines gap = ' ' * common.getLineIndentation(selectedRange.start().line(), doc) # TODO Get indent width (and char) from config (get rid of hardcocded '4') text = gap + openCh + '\n' \ + '\n'.join([' ' * 4 + line for line in doc.text(selectedRange).split('\n')[:-1]]) \ + '\n' + gap + closeCh + '\n' doc.startEditing() doc.replaceText(selectedRange, text) doc.endEditing() # extend current selection r = KTextEditor.Range(selectedRange.start().line(), 0, selectedRange.end().line() + 2, 0) view.setSelection(r)
def killRestOfLine(): '''Remove text from cursor position to the end of the current line''' doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() endPosition = KTextEditor.Cursor(pos.line(), doc.lineLength(pos.line())) killRange = KTextEditor.Range(pos, endPosition) doc.startEditing() doc.removeText(killRange) doc.endEditing()
def insertColor(): '''Insert/edit color string using color chooser dialog If cursor positioned in a color string, this action will edit it, otherwise a new color string will be inserted into a document. ''' document = kate.activeDocument() view = kate.activeView() global colorChooserWidget colorChooserWidget.setColors(_collect_colors(document)) colorChooserWidget.moveAround(view.cursorPositionCoordinates())
def create_frame(pattern_str='', title='', name_field=''): currentDocument = kate.activeDocument() view = kate.activeView() class_name, ok = QtGui.QInputDialog.getText(view, title, name_field) if ok: class_name = unicode(class_name) class_model = class_name.replace('Form', '') text = pattern_str % { 'class_name': class_name, 'class_model': class_model } currentDocument.insertText(view.cursorPosition(), text)
def toggleDoxyComment(): document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() # Determine type of current comment line = str(document.line(pos.line())).strip() if line.startswith('///'): turnToBlockComment() elif line.startswith('*') or line.startswith('/*') or line.startswith('*/'): turnFromBlockComment() else: return
def get_prototype_of_current_func(): espaces = ' ' * PYTHON_SPACES number_espaces = PYTHON_SPACES * 2 parentheses = 0 class_name = TEXT_TO_CHANGE function_name = TEXT_TO_CHANGE params = ['self', '*args', '**kwargs'] text_def = '' find_finish_def = False view = kate.activeView() currentDocument = kate.activeDocument() currentPosition = view.cursorPosition() currentLine = currentPosition.line() func_def_espaces = None while currentLine >= 0: text = unicode(currentDocument.line(currentLine)) if find_finish_def: text_def = '%s\n%s' % (text, text_def) else: text_def = text if function_name == TEXT_TO_CHANGE: match_finish = pattern_def_finish.match(text_def) match_init = pattern_def_init.match(text_def) if match_finish and match_init: match = pattern_def.match(text_def) number_espaces = get_number_espaces(currentDocument, currentPosition.line()) if not number_espaces: number_espaces = len(match.groups()[0]) + 1 func_def_espaces = match.groups()[0] espaces = ' ' * number_espaces function_name = match.groups()[1] params = match.groups()[2].split(',') params = [ change_kwargs(param.strip(' \t')) for param in params ] elif match_finish: find_finish_def = True parentheses += text_def.count(")") - text_def.count("(") if find_finish_def and parentheses <= 0: parentheses += text_def.count(")") - text_def.count("(") find_finish_def = False match = pattern_class.match(text) if match: if func_def_espaces: current_spaces = len(text) - len(text.lstrip()) if current_spaces < func_def_espaces: class_name = match.groups()[0] break currentLine = currentLine - 1 return (espaces, class_name, function_name, params)
def zenExpand(): cursor = kate.activeView().cursorPosition() line = str(kate.activeDocument().line( cursor.line() )) abbr = zen_core.find_abbr_in_line( line, cursor.column() ) code = zen_core.expand_abbreviation(abbr[0], 'html', 'xhtml') indentation = find_spaces.match(line).group(0) codelines = code.splitlines() cursor_column = -1 for i, codeline in enumerate(codelines): if i > 0: codeline = indentation + codeline codelines[i] = codeline if cursor_column >= 0: continue cursor_column = codeline.find('|') if cursor_column >= 0: cursor_line = i codelines[cursor_line] = codeline[:cursor_column] + codeline[cursor_column+1:] cursor_column -= len(find_spaces.match(codeline).group(0)) code = "\n".join(codelines) krange = KTextEditor.Range(cursor.line(), abbr[1], cursor.line(), abbr[1]+len(abbr[0])) kate.activeDocument().replaceText(krange, code) if cursor_column >= 0: cursor.setLine(cursor.line() + cursor_line) line = str(kate.activeDocument().line( cursor.line() )) if cursor_line == 0: cursor_column += abbr[1] else: cursor_column += len(find_spaces.match(line).group(0)) cursor.setColumn(cursor_column) kate.activeView().setCursorPosition(cursor)
def _insert_color_into_active_document(self, color): color_str = color.name() # Get it as color string #kate.kDebug('ColorUtils: selected color: {}'.format(color_str)) document = kate.activeDocument() view = kate.activeView() has_selection = view.selection() # Remember current selection state color_range = ColorChooser._get_color_range_under_cursor(view) document.startEditing() document.replaceText(color_range, color_str) # Replace selected/found range w/ a new text document.endEditing() # Select just entered #color, if something was selected before if has_selection: start_pos = color_range.start() view.setSelection(KTextEditor.Range(start_pos, len(color_str)))
def updateInfo(self): text = kate.activeView().selectionText() if text == '': text = kate.activeView().document().text() chars = len(text) spaces = sum([x.isspace() for x in text]) lines = sum([x == '\n' for x in text]) word_count = len(text.split(None)) chars_no_space = chars - spaces try: junk, occurences = re.subn(self.search.text(), '', text) except: occurences = "Invalid" self.chars.setText( str(chars ).ljust(10)) self.lines.setText( str(lines )) self.spaces.setText( str(spaces )) self.word_count.setText( str(word_count )) self.occurences.setText( str(occurences )) self.chars_no_space.setText( str(chars_no_space ))
def insertColor(): ''' Insert/edit #color using color chooser dialog If cursor positioned in a #color 'word', this action will edit it, otherwise a new #color will be inserted into a document. ''' document = kate.activeDocument() view = kate.activeView() cursor = view.cursorPosition() if not view.selection(): # If no selection, try to get a #color under cursor colorRange = common.getBoundTextRangeSL(_LEFT_COLOR_BOUNDARY, _RIGHT_COLOR_BOUNDARY, cursor, document) else: # Some text selected, just use it as input... colorRange = view.selectionRange() if colorRange.isValid(): currentColor = document.text(colorRange) else: currentColor = kate.configuration[_INSERT_COLOR_LCC] color = QtGui.QColor(currentColor) # If no text selected (i.e. user don't want to override selection) # and (guessed) #color string is not valid, entered color will # be inserted at the current cursor position. if not color.isValid(): color = QtGui.QColor(kate.configuration[_INSERT_COLOR_LCC]) if not view.selection(): colorRange = KTextEditor.Range( cursor, cursor) # Will not override the text under cursor... # Choose a #color via dialog result = kdeui.KColorDialog.getColor(color) if result == kdeui.KColorDialog.Accepted: # Is user pressed Ok? colorStr = color.name() # Get it as #color text # Remember for future use kate.configuration[_INSERT_COLOR_LCC] = colorStr document.startEditing() document.replaceText( colorRange, colorStr) # Replace selected/found range w/ a new text document.endEditing() # Select just entered #color, if smth was selected before if view.selection(): startPos = colorRange.start() endPos = KTextEditor.Cursor(startPos.line(), startPos.column() + len(colorStr)) view.setSelection(KTextEditor.Range(startPos, endPos))
def turnFromBlockComment(): document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() if view.selection(): sr = view.selectionRange() start = sr.start().line() end = sr.end().line() else: # Try to detect block comment (/* ... */) r = common.getTextBlockAroundCursor( document, pos, [pred.blockCommentStart, neg(pred.startsWith('*'))], [pred.blockCommentEnd, neg(pred.startsWith('*'))]) start = r.start().line() - 1 end = r.end().line() + 1 # Replace comments insertionText = list() align = None for i in range(start, end): line = str(document.line(i)) sline = line.lstrip() if align == None: align = ' ' * (len(line) - len(sline)) if sline.startswith('/**') or sline.startswith('*/'): continue if sline.startswith('*'): insertionText.append(align + sline.replace('*', '///', 1)) originRange = KTextEditor.Range(start, 0, end, 0) pos.setPosition(start, len(align) + 3) insertPos = KTextEditor.Cursor(start, 0) # Update the document if bool(insertionText): document.startEditing() # Start edit transaction: document.removeText(originRange) # Remove current line # insert resulting text line by line... document.insertText(insertPos, '\n'.join(insertionText) + '\n') # Move cursor to desired position view.setCursorPosition(pos) document.endEditing() # End transaction
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")
def get_prototype_of_current_func(): indent = '\t' parentheses = 0 class_name = TEXT_TO_CHANGE function_name = TEXT_TO_CHANGE params = ['self', '*args', '**kwargs'] text_def = '' find_finish_def = False view = kate.activeView() currentDocument = kate.activeDocument() currentPosition = view.cursorPosition() currentLine = currentPosition.line() func_def_indent = None while currentLine >= 0: text = currentDocument.line(currentLine) if find_finish_def: text_def = '%s\n%s' % (text, text_def) else: text_def = text if function_name == TEXT_TO_CHANGE: match_finish = pattern_def_finish.match(text_def) match_init = pattern_def_init.match(text_def) if match_finish and match_init: match = pattern_def.match(text_def) indent = get_indent(currentDocument, currentPosition.line()) if not indent: indent = match.groups()[0] + '\t' func_def_indent = match.groups()[0] function_name = match.groups()[1] params = match.groups()[2].split(',') params = [ change_kwargs(param.strip(' \t')) for param in params ] elif match_finish: find_finish_def = True parentheses += text_def.count(")") - text_def.count("(") if find_finish_def and parentheses <= 0: parentheses += text_def.count(")") - text_def.count("(") find_finish_def = False match = pattern_class.match(text) if match: if func_def_indent: current_indent = len(text) - len(text.lstrip()) if current_indent < len(func_def_indent): class_name = match.groups()[1] break currentLine = currentLine - 1 return (indent, class_name, function_name, params)
def _wrapBlockWithChar(openCh, closeCh, indentMultiline=True): '''Wrap a current word or selection (if any) into given open and close chars If current selection is multiline, add one indentation level and put open/close chars on separate lines ''' doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() selectedRange = view.selectionRange() if selectedRange.isEmpty(): # No text selected. Ok, lets wrap a word where cursor positioned wordRange = common.getBoundTextRangeSL( common.CXX_IDENTIFIER_BOUNDARIES, common.CXX_IDENTIFIER_BOUNDARIES, pos, doc) _wrapRange(wordRange, openCh, closeCh, doc) else: if selectedRange.start().line() == selectedRange.end().line( ) or indentMultiline == False: # single line selection (or no special indentation required) _wrapRange(selectedRange, openCh, closeCh, doc) # extend current selection selectedRange.end().setColumn(selectedRange.end().column() + len(openCh) + len(closeCh)) view.setSelection(selectedRange) else: # Try to extend selection to be started from 0 columns at both ends common.extendSelectionToWholeLine(view) selectedRange = view.selectionRange() # multiline selection # 0) extend selection to capture whole lines gap = ' ' * common.getLineIndentation(selectedRange.start().line(), doc) # TODO Get indent width (and char) from config (get rid of hardcocded '4') text = gap + openCh + '\n' \ + '\n'.join([' ' * 4 + line for line in doc.text(selectedRange).split('\n')[:-1]]) \ + '\n' + gap + closeCh + '\n' doc.startEditing() doc.replaceText(selectedRange, text) doc.endEditing() # extend current selection r = KTextEditor.Range(selectedRange.start().line(), 0, selectedRange.end().line() + 2, 0) view.setSelection(r)
def createSignalAutocompleteDocument(view=None, *args, **kwargs): # https://launchpad.net/ubuntu/precise/+source/pykde4 # https://launchpad.net/ubuntu/precise/+source/pykde4/4:4.7.97-0ubuntu1/+files/pykde4_4.7.97.orig.tar.bz2 # http://doc.trolltech.com/4.6/qabstractitemmodel.html # http://gitorious.org/kate/kate/blobs/a17eb928f8133528a6194b7e788ab7a425ef5eea/ktexteditor/codecompletionmodel.cpp # http://code.google.com/p/lilykde/source/browse/trunk/frescobaldi/python/frescobaldi_app/mainapp.py#1391 # http://api.kde.org/4.0-api/kdelibs-apidocs/kate/html/katecompletionmodel_8cpp_source.html # https://svn.reviewboard.kde.org/r/1640/diff/?expand=1 if not PYTHON_AUTOCOMPLETE_ENABLED: return view = view or kate.activeView() global pyplete session = get_session() codecompletationmodel.setSession(session) cci = view.codeCompletionInterface() cci.registerCompletionModel(codecompletationmodel)
def insertColor(): """Insert/edit color string using color chooser dialog If cursor positioned in a color string, this action will edit it, otherwise a new color string will be inserted into a document. """ document = kate.activeDocument() view = kate.activeView() cursor = view.cursorPosition() if view.selection(): # Some text selected, just use it as input... color_range = view.selectionRange() else: # If no selection, try to get a #color under cursor color_range = common.getBoundTextRangeSL( common.IDENTIFIER_BOUNDARIES - {'#'}, common.IDENTIFIER_BOUNDARIES, cursor, document) if color_range.isValid(): current_color = document.text(color_range) else: current_color = kate.configuration[_INSERT_COLOR_LCC] color = QColor(current_color) # If no text selected (i.e. user doesn’t want to override selection) # and (guessed) color string is not valid, entered color will # be inserted at the current cursor position. if not color.isValid(): color = QColor(kate.configuration[_INSERT_COLOR_LCC]) if not view.selection(): color_range = KTextEditor.Range( cursor, 0) # Will not override the text under cursor… # Choose a color via dialog result = KColorDialog.getColor(color) if result == KColorDialog.Accepted: # Did user press OK? color_str = color.name() # Get it as color string # Remember for future use kate.configuration[_INSERT_COLOR_LCC] = color_str document.startEditing() document.replaceText( color_range, color_str) # Replace selected/found range w/ a new text document.endEditing() # Select just entered #color, if something was selected before if view.selection(): start_pos = color_range.start() view.setSelection(KTextEditor.Range(start_pos, len(color_str)))
def insertCharFromLineBelow(): '''Add the same char to the current cursor position as at the line below''' doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() if pos.line() == 0: return lineBelow = doc.line(pos.line() + 1) char = lineBelow[pos.column():pos.column() + 1] if not bool(char): return doc.startEditing() doc.insertText(pos, char) doc.endEditing()
def showErrors(message, errors, key_mark, doc, time=10, icon='dialog-warning', key_line='line', key_column='column', max_errors=3, show_popup=True, move_cursor=False): mark_iface = doc.markInterface() messages = {} view = kate.activeView() pos = view.cursorPosition() current_line = pos.line() + 1 current_column = pos.column() + 1 for error in errors: header = False line = error[key_line] column = error.get(key_column, 0) pos = _compress_key(line, column) if not messages.get(line, None): header = True messages[pos] = [] error_message = generateErrorMessage(error, key_line, key_column, header) messages[pos].append(error_message) mark_iface.setMark(line - 1, mark_iface.Error) messages_items = messages.items() messages_items.sort() if move_cursor: first_error, messages_show = getErrorMessagesOrder( messages_items, max_errors, current_line, current_column) line_to_move, column_to_move = _uncompress_key( messages_items[first_error][0]) moveCursorTFirstError(line_to_move, column_to_move) else: first_error, messages_show = getErrorMessagesOrder( messages_items, max_errors) if show_popup: message = '%s\n%s' % (message, '\n'.join(messages_show)) if len(messages_show) < len(errors): message += '\n\nAnd other errors' kate.gui.popup(message, time, icon, minTextWidth=300)
def moveAbove(): '''Move an inlined comment before the current line w/ same indentation level''' document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() commentCh = common.getCommentStyleForDoc(document) insertionText = list() line = document.line(pos.line()) # Split a line before and after a comment (before, comment, after) = str(line).partition(commentCh) before_ls = before.lstrip() column = len(before) - len(before_ls) doxCommentOffset = 0 # Is there is a comment in a line? if bool(comment): # Yeah! It is... Now what about any text?? if bool(before.strip()): if after[0:2] == '/<': after = '/' + after[2:] doxCommentOffset = 1 insertionText.append(' ' * column + comment + after) else: # There is comment alone... Just leave it... return else: # Oops! There is no inline comment... Ok just add new one above. insertionText.append(' ' * column + commentCh) column += len(commentCh) + doxCommentOffset insertionText.append(before.rstrip()) # Update the document if bool(insertionText): document.startEditing() # Start edit transaction: document.removeLine(pos.line()) # Remove current line # insert resulting text line by line... pos.setColumn(0) document.insertText(pos, '\n'.join(insertionText) + '\n') # Move cursor to desired position pos.setColumn(column) view.setCursorPosition(pos) document.endEditing() # End transaction
def turnToBlockComment(): document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() if view.selection(): sr = view.selectionRange() start = sr.start().line() end = sr.end().line() else: r = common.getTextBlockAroundCursor( document, pos, [neg(any_of(pred.startsWith('///'), pred.startsWith('//!')))], [neg(any_of(pred.startsWith('///'), pred.startsWith('//!')))]) start = r.start().line() end = r.end().line() # Replace comments in every line insertionText = list() align = None for i in range(start, end): line = str(document.line(i)) sline = line.lstrip() if align == None: align = ' ' * (len(line) - len(sline)) insertionText.append( align + sline.replace('///', ' *', 1).replace('//!', ' *', 1)) originRange = KTextEditor.Range(start, 0, end, 0) pos.setPosition(start + 1, len(align) + 3) insertPos = KTextEditor.Cursor(start, 0) # Update the document if bool(insertionText): document.startEditing() # Start edit transaction: document.removeText(originRange) # Remove current line # insert resulting text ... document.insertText( insertPos, align + '/**\n' + '\n'.join(insertionText) + '\n' + align + ' */\n') # Move cursor to desired position view.setCursorPosition(pos) document.endEditing() # End transaction
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")
def killLeadOfLine(): ''' Remove text from a start of a line to the current cursor position but keep leading spaces (to avoid breaking indentation) NOTE This function suppose spaces as indentation character! TODO Get indent character from config ''' doc = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() indent = common.getCurrentLineIndentation(view) startPosition = KTextEditor.Cursor(pos.line(), 0) killRange = KTextEditor.Range(startPosition, pos) doc.startEditing() doc.removeText(killRange) doc.insertText(startPosition, ' ' * indent) doc.endEditing()
def toggleDoxyComment(): ''' Turn block of '///' doxygen comments into /** * */ and vise versa ''' document = kate.activeDocument() view = kate.activeView() pos = view.cursorPosition() # Determine type of current comment line = str(document.line(pos.line())).strip() if line.startswith('///'): turnToBlockComment() elif line.startswith('*') or line.startswith('/*') or line.startswith( '*/'): turnFromBlockComment() else: return
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)
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")