def _on_key_pressed(self, event): txt = event.text() cursor = self.editor.textCursor() from pyqode.qt import QtGui assert isinstance(cursor, QtGui.QTextCursor) if cursor.hasSelection(): # quoting of selected text if event.text() in self.MAPPING.keys(): first = event.text() last = self.MAPPING[event.text()] cursor.insertText(self.SELECTED_QUOTES_FORMATS[event.text()] % (first, cursor.selectedText(), last)) self.editor.setTextCursor(cursor) event.accept() else: self._ignore_post = True return next_char = TextHelper(self.editor).get_right_character() self.logger.debug('next char: %s', next_char) ignore = False if txt and next_char == txt and next_char in self.MAPPING: ignore = True elif event.text() == ')' or event.text() == ']' or event.text() == '}': if next_char == ')' or next_char == ']' or next_char == '}': ignore = True if ignore: event.accept() TextHelper(self.editor).clear_selection() TextHelper(self.editor).move_right()
def test_goto_definition(editor): editor.show() QTest.qWait(1000) panel = get_panel(editor) line = TextHelper(editor).current_line_nbr() panel._on_definition_activated(len(panel._definitions) - 2) assert TextHelper(editor).current_line_nbr() != line
def test_key_pressed(): # " -> "" editor = CodeEdit() editor.modes.append(modes.AutoCompleteMode()) editor.setPlainText('', '', 'utf-8') QTest.keyPress(editor, '"') assert editor.toPlainText() == '""' editor.clear() # if a " already exists, cursor should just move after " and a new " should # not be inserted editor.setPlainText('"', 'text/x-python', 'utf-8') TextHelper(editor).goto_line(0, 0) QTest.keyPress(editor, '"') assert editor.toPlainText() == '"' editor.clear() # if a ) already exists, cursor should just move after ) and a new ) should # not be inserted editor.setPlainText(')', 'text/x-python', 'utf-8') TextHelper(editor).goto_line(0, 0) QTest.keyPress(editor, ')') QTest.qWait(1000) assert editor.toPlainText() == ')' # ] should be inserted ")" -> "])" TextHelper(editor).goto_line(0, 0) QTest.keyPress(editor, ']') QTest.qWait(1000) assert editor.toPlainText() == '])'
def test_autocomplete_double_quotes(editor): code = '''{ "widget": { "debug": "on", "window": { "title": "Sample Konfabulator Widget", "name": "main_window", "width": "height": 500 }, } } ''' editor.setPlainText(code) assert editor.toPlainText() == code TextHelper(editor).goto_line(6, column=16, move=True) QTest.qWait(100) assert TextHelper(editor).current_line_text() == ' "width":' QTest.keyPress(editor, '"') result = ' "width":""' assert TextHelper(editor).current_line_text() == result QTest.qWait(100) TextHelper(editor).goto_line(6, column=len(result), move=True) QTest.keyPress(editor, ',') QTest.keyPress(editor, QtCore.Qt.Key_Return) QTest.qWait(100) QTest.keyPress(editor, '"') QTest.qWait(100) result = ' "":' assert TextHelper(editor).current_line_text() == result
def test_comment_single(editor): editor.setPlainText('import os') QTest.qWait(100) TextHelper(editor).goto_line(0, 0) QTest.qWait(100) mode = get_mode(editor) mode.comment() QTest.qWait(100) assert editor.toPlainText() == '# import os' assert TextHelper(editor).current_line_nbr() == 0
def test_unmatching(editor): mode = get_mode(editor) # for this test we need to load uncorrect code with non matching symbols editor.setPlainText(malformed_symbols_code, 'text/x-python', 'utf-8') TextHelper(editor).goto_line(0, 4) mode.do_symbols_matching() TextHelper(editor).goto_line(1, 4) mode.do_symbols_matching() TextHelper(editor).goto_line(2, 4) mode.do_symbols_matching()
def _on_post_key_pressed(self, event): # if we are in disabled cc, use the parent implementation helper = TextHelper(self.editor) if (event.text() == "(" and helper.current_line_text().lstrip().startswith("def ")): self._handle_fct_def() else: line = TextHelper(self.editor).current_line_text().strip() if not line.endswith(('"""', "'''")): super(PyAutoCompleteMode, self)._on_post_key_pressed(event)
def test_focus_out_event(editor): panel = get_panel(editor) TextHelper(editor).goto_line(0) tc = TextHelper(editor).word_under_mouse_cursor() editor.setTextCursor(tc) panel.on_search() panel.focusOutEvent(QtGui.QFocusEvent(QtCore.QEvent.FocusOut)) assert not panel.hasFocus() # reopen panel for next tests panel.on_search() panel.setFocus()
def test_toggle_button(editor): editor.file.open('test/files/example.json') editor.show() TextHelper(editor).goto_line(6) QTest.qWait(500) panel = editor.panels.get('NavigationPanel') assert len(panel._widgets) == 4 assert panel._widgets[1].text().replace('&', '').lower() == 'window' panel._widgets[1].toggled.emit(True) QTest.qWait(500) assert TextHelper(editor).cursor_position()[0] == 3
def _on_post_key_pressed(self, event): if not event.isAccepted() and not self._ignore_post: txt = event.text() next_char = TextHelper(self.editor).get_right_character() if txt in self.MAPPING: to_insert = self.MAPPING[txt] if (not next_char or next_char in self.MAPPING.keys() or next_char in self.MAPPING.values() or next_char.isspace()): TextHelper(self.editor).insert_text( self.QUOTES_FORMATS[txt] % to_insert) self._ignore_post = False
def test_indent_selection(editor): mode = editor.modes.get(modes.IndenterMode) # select all TextHelper(editor).select_lines() mode.indent() mode.unindent() TextHelper(editor).select_lines(0) mode.indent() mode.unindent() editor.use_spaces_instead_of_tabs = False TextHelper(editor).select_lines() mode.indent() mode.unindent()
def _get_indent(self, cursor): """ Return the indentation text (a series of spaces or tabs) :param cursor: QTextCursor :returns: Tuple (text before new line, text after new line) """ if self.editor.use_spaces_instead_of_tabs: indent = TextHelper(self.editor).line_indent() * ' ' else: indent = TextHelper(self.editor).line_indent() * '\t' return "", indent
def run(self, editor): editor.setPlainText(self.context.input_code) TextHelper(editor).goto_line(self.context.input_line, self.context.input_column) wait = 1 QTest.qWait(wait) QTest.keyPress(editor, QtCore.Qt.Key_Return) QTest.qWait(wait) assert editor.toPlainText() == self.context.expected_code assert TextHelper( editor).current_line_nbr() == self.context.expected_line assert TextHelper( editor).current_column_nbr() == self.context.expected_column
def _on_key_pressed(self, event): txt = event.text() cursor = self.editor.textCursor() from pyqode.qt import QtGui assert isinstance(cursor, QtGui.QTextCursor) if cursor.hasSelection(): # quoting of selected text if event.text() in self.MAPPING.keys(): first = event.text() last = self.MAPPING[event.text()] cursor.insertText( self.SELECTED_QUOTES_FORMATS[event.text()] % ( first, cursor.selectedText(), last)) self.editor.setTextCursor(cursor) event.accept() else: self._ignore_post = True return next_char = TextHelper(self.editor).get_right_character() self.logger.debug('next char: %s', next_char) ignore = False if event.key() == QtCore.Qt.Key_Backspace: # get the character that will get deleted tc = self.editor.textCursor() pos = tc.position() tc.movePosition(tc.Left) tc.movePosition(tc.Right, tc.KeepAnchor) del_char = tc.selectedText() if del_char in self.MAPPING and \ self.MAPPING[del_char] == next_char: tc.beginEditBlock() tc.movePosition(tc.Right, tc.KeepAnchor) tc.insertText('') tc.setPosition(pos - 2) tc.endEditBlock() self.editor.setTextCursor(tc) ignore = True elif txt and next_char == txt and next_char in self.MAPPING: ignore = True elif event.text() == ')' or event.text() == ']' or event.text() == '}': # if typing the same symbol twice, the symbol should not be written # and the cursor moved just after the char # e.g. if you type ) just before ), the cursor will just move after # the existing ) if next_char == event.text(): ignore = True if ignore: event.accept() TextHelper(self.editor).clear_selection() TextHelper(self.editor).move_right()
def test_remove_decoration(editor): helper = TextHelper(editor) TextHelper(editor).goto_line(1, 2) cursor = helper.word_under_cursor(select_whole_word=True) deco = TextDecoration(cursor) deco.set_as_bold() deco.set_as_underlined(QtGui.QColor("#FF0000")) editor.decorations.append(deco) assert editor.decorations.remove(deco) # already removed, return False assert not editor.decorations.remove(deco) assert editor.decorations.append(deco) # keep editor clean for next tests editor.decorations.clear()
def test_mouse_move(editor): panel = get_panel(editor) panel.highlight_caret_scope = False nb_decos = len(editor.decorations) y_pos = TextHelper(editor).line_pos_from_number(8) QTest.mouseMove(panel, QtCore.QPoint(3, y_pos + 5)) QTest.qWait(1000) assert len(editor.decorations) >= 2 y_pos = TextHelper(editor).line_pos_from_number(14) QTest.mouseMove(panel, QtCore.QPoint(3, y_pos + 5)) QTest.qWait(1000) assert len(editor.decorations) >= 4 QTest.mouseMove(panel, QtCore.QPoint(0, 0)) panel.leaveEvent(None) editor.setFocus() panel.highlight_caret_scope = True
def _on_mouse_pressed(self, event): """ mouse pressed callback """ if event.button() == 1 and self._deco: cursor = TextHelper(self.editor).word_under_mouse_cursor() if cursor and cursor.selectedText(): self._timer.request_job( self.word_clicked.emit, cursor)
def _on_item_activated(item, *args): assert isinstance(item, QtWidgets.QTreeWidgetItem) data = item.data(0, QtCore.Qt.UserRole) try: l = data['line'] except TypeError: return # file item or root item start = data['start'] lenght = data['end'] - start if data is not None: # open editor and go to line/column e = editor.open_file(data['path'], data['line'], data['start']) if e is None: return # select text helper = TextHelper(e) try: cursor = helper.select_lines(start=l, end=l) except AttributeError: _logger().debug('failed to select occurent line in editor, not' ' a subclass of QPlainTextEdit') else: assert isinstance(cursor, QtGui.QTextCursor) cursor.movePosition(cursor.StartOfBlock) cursor.movePosition(cursor.Right, cursor.MoveAnchor, start) cursor.movePosition(cursor.Right, cursor.KeepAnchor, lenght) e.setTextCursor(cursor)
def _get_cursor_pos_in_bytes(self, original, encoding): text = TextHelper(self.current_editor).current_line_text() text = text[:original] try: return len(bytes(text, encoding)) except UnicodeDecodeError: return original
def _check_word_cursor(self, tc=None): """ Request a go to assignment. :param tc: Text cursor which contains the text that we must look for its assignment. Can be None to go to the text that is under the text cursor. :type tc: QtGui.QTextCursor """ if not tc: tc = TextHelper(self.editor).word_under_cursor() request_data = { 'code': self.editor.toPlainText(), 'line': tc.blockNumber(), 'column': tc.columnNumber(), 'path': self.editor.file.path, 'encoding': self.editor.file.encoding } try: self.editor.backend.send_request( workers.goto_assignments, request_data, on_receive=self._on_results_available) except NotRunning: pass
def indent_selection(self, cursor): """ Indent selected text :param cursor: QTextCursor """ doc = self.editor.document() tab_len = self.editor.tab_length cursor.beginEditBlock() nb_lines = len(cursor.selection().toPlainText().splitlines()) if (cursor.atBlockStart() and cursor.position() == cursor.selectionEnd()): nb_lines += 1 block = doc.findBlock(cursor.selectionStart()) i = 0 # indent every lines while i < nb_lines: nb_space_to_add = tab_len cursor = QtGui.QTextCursor(block) indentation = TextHelper(self.editor).line_indent(block) if indentation < self.min_column: # align with at least 7th char nb_space_to_add = self.min_column if block.text().strip().startswith('*') and indentation == 0: nb_space_to_add -= 1 cursor.movePosition(cursor.StartOfLine, cursor.MoveAnchor) if self.editor.use_spaces_instead_of_tabs: for _ in range(nb_space_to_add): cursor.insertText(" ") else: cursor.insertText('\t') block = block.next() i += 1 cursor.endEditBlock()
def toggle_fold_trigger(editor, line, panel): y_pos = TextHelper(editor).line_pos_from_number(line) + 5 QTest.mouseMove(panel, QtCore.QPoint(3, y_pos)) QTest.qWait(1000) QTest.mousePress(panel, QtCore.Qt.RightButton, QtCore.Qt.NoModifier, QtCore.QPoint(3, y_pos)) QTest.qWait(1000)
def _search(self): text = self.ui.lineEdit.text() # check the source to use for search (symbols or files). if self.GOTO_SYMBOL_PATTERN.match(text): self.ui.cb_non_project_files.setVisible(False) if self.GOTO_LINE_PATTERN.match(text): self.ui.treeWidget.hide() self.adjustSize() elif editor.get_current_editor(): self.search_symbol() elif self.GOTO_SYMBOL_IN_PROJ_PATTERN.match(text): if self.GOTO_LINE_PATTERN.match(text): self.ui.cb_non_project_files.setVisible(False) self.ui.treeWidget.hide() self.adjustSize() else: self.ui.cb_non_project_files.setVisible(True) self.search_symbol_in_project() else: if not text.startswith(':'): self.ui.cb_non_project_files.setVisible(True) self.search_files() else: self.ui.cb_non_project_files.setVisible(False) # will be used to goto line in the current editor. self.ui.treeWidget.hide() self.adjustSize() e = editor.get_current_editor() try: TextHelper(e).goto_line(self._get_requested_line_nbr() - 1) except (ValueError, AttributeError): _logger().debug('failed to go to line on editor %r', e)
def _on_document_changed(self): def flatten(results): """ Flattens the document structure tree as a simple sequential list. """ ret_val = [] for de in results: ret_val.append(de) for sub_d in de.children: nd = Definition(sub_d.name, sub_d.line, sub_d.column, sub_d.icon) nd.name = " " + nd.name ret_val.append(nd) return ret_val if not self or not self.editor: return mode = self.editor.modes.get('OutlineMode') definitions = flatten(mode.definitions) self.combo_box.clear() if definitions: self.combo_box.addItem(" < Select a symbol >") else: self.combo_box.addItem("No symbols") for d in definitions: try: self.combo_box.addItem(QtGui.QIcon(d.icon), d.name, d) except TypeError: self.combo_box.addItem( QtGui.QIcon.fromTheme(d.icon[0], QtGui.QIcon(d.icon[1])), d.name, d) self._definitions = definitions self._sync_combo_box(TextHelper(self.editor).current_line_nbr())
def sync(self): if not self.sync_with_editor or self._editor is None or \ not self._definitions: return to_select = None previous = None current_line = TextHelper(self._editor).current_line_nbr() for d in self._flattened_defs: if d.line == current_line: to_select = d.tree_item elif d.line > current_line: to_select = d.tree_item if previous is not None: to_select = previous.tree_item previous = d if to_select is not None: break else: if previous: to_select = previous.tree_item if to_select: try: self.setCurrentItem(to_select) except RuntimeError: # RuntimeError: wrapped C/C++ object of type QTreeWidgetItem # has been deleted pass
def extract_variable(self): """ Extracts a variable from the selected statement (if possible). """ api.editor.save_all_editors() self._main_project.validate() editor = api.editor.get_current_editor() if editor is None or not editor.textCursor().hasSelection(): return editor.file.save() if not editor.textCursor().hasSelection(): TextHelper(editor).select_whole_line() start = self._get_real_position(editor.textCursor().selectionStart()) end = self._get_real_position(editor.textCursor().selectionEnd()) preview, replacement = DlgRope.extract_variable(self.main_window) if preview is None and replacement is None: return multiproj = self._has_multiple_projects() other_projects = self._get_other_projects() main_project = self._main_project cursor_position_start = start cursor_position_end = end replacement = replacement self._preview = preview api.tasks.start(_('Refactoring: extract variable'), extract_variable, self._on_changes_available, args=(multiproj, main_project, other_projects, editor.file.path, cursor_position_start, cursor_position_end, replacement), cancellable=True, use_thread=True)
def perform_matched_selection(self, event): """ Performs matched selection. :param event: QMouseEvent """ selected = TextHelper(self.editor).match_select() if selected and event: event.accept()
def _request_highlight(self): if self.editor is not None: sub = TextHelper(self.editor).word_under_cursor( select_whole_word=True).selectedText() if sub != self._sub: self._clear_decos() if len(sub) > 1: self.timer.request_job(self._send_request)
def _on_post_key_pressed(self, event): if not event.isAccepted() and not self._ignore_post: txt = event.text() trav = self.editor.textCursor() assert isinstance(trav, QtGui.QTextCursor) trav.movePosition(trav.Left, trav.MoveAnchor, 2) literal = TextHelper(self.editor).is_comment_or_string(trav) if not literal: next_char = TextHelper(self.editor).get_right_character() if txt in self.MAPPING: to_insert = self.MAPPING[txt] if (not next_char or next_char in list(self.MAPPING.keys()) or next_char in list(self.MAPPING.values()) or next_char.isspace()): TextHelper(self.editor).insert_text( self.QUOTES_FORMATS[txt] % to_insert) self._ignore_post = False
def test_goto_variable(editor): editor.clear() code = "a = 15\nprint(a)" editor.setPlainText(code) mode = get_mode(editor) TextHelper(editor).goto_line(2, len('print(a)') - 2) mode.request_goto() QTest.qWait(5000)