def run_loop(user_data, state_map, formats, text): state = user_data.state i = 0 fix_offsets = is_wide_build and utf16_length(text) != len(text) seen_states = defaultdict(set) while i < len(text): orig_i = i seen_states[i].add(state.parse) fmt = state_map[state.parse](state, text, i, formats, user_data) for num, f in fmt: if num > 0: if fix_offsets: # We need to map offsets/lengths from UCS-4 to UTF-16 in # which non-BMP characters are two code points wide yield utf16_length(text[:i]), utf16_length(text[i:i + num]), f else: yield i, num, f i += num if orig_i == i and state.parse in seen_states[i]: # Something went wrong in the syntax highlighter print( 'Syntax highlighter returned a zero length format, parse state:', state.parse) break
def do_test(self): selections = [] self.match_locs = [] class Pos: python: int = 0 qt: int = 0 if self.regex_valid(): text = str(self.preview.toPlainText()) regex = str(self.regex.text()) cursor = QTextCursor(self.preview.document()) extsel = QTextEdit.ExtraSelection() extsel.cursor = cursor extsel.format.setBackground(QBrush(Qt.GlobalColor.yellow)) with suppress(Exception): prev = Pos() for match in compile_regular_expression(regex).finditer(text): es = QTextEdit.ExtraSelection(extsel) qtchars_to_start = utf16_length( text[prev.python:match.start()]) qt_pos = prev.qt + qtchars_to_start prev.python = match.end() prev.qt = qt_pos + utf16_length(match.group()) es.cursor.setPosition(qt_pos, QTextCursor.MoveMode.MoveAnchor) es.cursor.setPosition(prev.qt, QTextCursor.MoveMode.KeepAnchor) selections.append(es) self.match_locs.append((qt_pos, prev.qt)) self.preview.setExtraSelections(selections) if self.match_locs: self.next.setEnabled(True) self.previous.setEnabled(True) self.occurrences.setText(str(len(self.match_locs)))
def add_tag(tag): a = QTextEdit.ExtraSelection() a.cursor, a.format = editor.textCursor(), editor.match_paren_format a.cursor.setPosition(tag.start_block.position()), a.cursor.movePosition(a.cursor.EndOfBlock, a.cursor.KeepAnchor) text = unicode(a.cursor.selectedText()) start_pos = utf16_length(text[:tag.start_offset]) a.cursor.setPosition(tag.end_block.position()), a.cursor.movePosition(a.cursor.EndOfBlock, a.cursor.KeepAnchor) text = unicode(a.cursor.selectedText()) end_pos = utf16_length(text[:tag.end_offset + 1]) a.cursor.setPosition(tag.start_block.position() + start_pos) a.cursor.setPosition(tag.end_block.position() + end_pos, a.cursor.KeepAnchor) ans.append(a)
def run_loop(user_data, state_map, formats, text): state = user_data.state i = 0 fix_offsets = is_wide_build and utf16_length(text) != len(text) seen_states = defaultdict(set) while i < len(text): orig_i = i seen_states[i].add(state.parse) fmt = state_map[state.parse](state, text, i, formats, user_data) for num, f in fmt: if num > 0: if fix_offsets: # We need to map offsets/lengths from UCS-4 to UTF-16 in # which non-BMP characters are two code points wide yield utf16_length(text[:i]), utf16_length(text[i:i+num]), f else: yield i, num, f i += num if orig_i == i and state.parse in seen_states[i]: # Something went wrong in the syntax highlighter print ('Syntax highlighter returned a zero length format, parse state:', state.parse) break
def show_context_menu(self, pos): m = QMenu(self) a = m.addAction c = self.editor.cursorForPosition(pos) r = self.editor.syntax_range_for_cursor(c) if r is not None and r.format.property(SPELL_PROPERTY).toBool(): word = self.editor.text_for_range(c.block(), r) locale = self.editor.spellcheck_locale_for_cursor(c) orig_pos = c.position() c.setPosition(orig_pos - utf16_length(word)) found = False self.editor.setTextCursor(c) if self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False): found = True fc = self.editor.textCursor() if fc.position() < c.position(): self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False) if found: suggestions = dictionaries.suggestions(word, locale)[:7] if suggestions: for suggestion in suggestions: ac = m.addAction(suggestion, partial(self.editor.simple_replace, suggestion)) f = ac.font() f.setBold(True), ac.setFont(f) m.addSeparator() m.addAction(actions['spell-next']) m.addAction(_('Ignore this word'), partial(self._nuke_word, None, word, locale)) dics = dictionaries.active_user_dictionaries if len(dics) > 0: if len(dics) == 1: m.addAction(_('Add this word to the dictionary: {0}').format(dics[0].name), partial( self._nuke_word, dics[0].name, word, locale)) else: ac = m.addAction(_('Add this word to the dictionary')) dmenu = QMenu(m) ac.setMenu(dmenu) for dic in dics: dmenu.addAction(dic.name, partial(self._nuke_word, dic.name, word, locale)) m.addSeparator() for x in ('undo', 'redo'): a(actions['editor-%s' % x]) m.addSeparator() for x in ('cut', 'copy', 'paste'): a(actions['editor-' + x]) m.addSeparator() m.addAction(_('&Select all'), self.editor.select_all) m.addAction(actions['mark-selected-text']) if self.syntax == 'html': m.addAction(actions['multisplit']) m.exec_(self.editor.mapToGlobal(pos))
def show_context_menu(self, pos): m = QMenu(self) a = m.addAction c = self.editor.cursorForPosition(pos) origc = QTextCursor(c) current_cursor = self.editor.textCursor() r = origr = self.editor.syntax_range_for_cursor(c) if ( r is None or not r.format.property(SPELL_PROPERTY) ) and c.positionInBlock() > 0 and not current_cursor.hasSelection(): c.setPosition(c.position() - 1) r = self.editor.syntax_range_for_cursor(c) if r is not None and r.format.property(SPELL_PROPERTY): word = self.editor.text_for_range(c.block(), r) locale = self.editor.spellcheck_locale_for_cursor(c) orig_pos = c.position() c.setPosition(orig_pos - utf16_length(word)) found = False self.editor.setTextCursor(c) if self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False): found = True fc = self.editor.textCursor() if fc.position() < c.position(): self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False) spell_cursor = self.editor.textCursor() if current_cursor.hasSelection(): # Restore the current cursor so that any selection is preserved # for the change case actions self.editor.setTextCursor(current_cursor) if found: suggestions = dictionaries.suggestions(word, locale)[:7] if suggestions: for suggestion in suggestions: ac = m.addAction( suggestion, partial(self.editor.simple_replace, suggestion, cursor=spell_cursor)) f = ac.font() f.setBold(True), ac.setFont(f) m.addSeparator() m.addAction(actions['spell-next']) m.addAction(_('Ignore this word'), partial(self._nuke_word, None, word, locale)) dics = dictionaries.active_user_dictionaries if len(dics) > 0: if len(dics) == 1: m.addAction( _('Add this word to the dictionary: {0}').format( dics[0].name), partial(self._nuke_word, dics[0].name, word, locale)) else: ac = m.addAction(_('Add this word to the dictionary')) dmenu = QMenu(m) ac.setMenu(dmenu) for dic in dics: dmenu.addAction( dic.name, partial(self._nuke_word, dic.name, word, locale)) m.addSeparator() if origr is not None and origr.format.property(LINK_PROPERTY): href = self.editor.text_for_range(origc.block(), origr) m.addAction( _('Open %s') % href, partial(self.link_clicked.emit, href)) if origr is not None and (origr.format.property(TAG_NAME_PROPERTY) or origr.format.property(CSS_PROPERTY)): word = self.editor.text_for_range(origc.block(), origr) item_type = 'tag_name' if origr.format.property( TAG_NAME_PROPERTY) else 'css_property' url = help_url(word, item_type, self.editor.highlighter.doc_name, extra_data=current_container().opf_version) if url is not None: m.addAction( _('Show help for: %s') % word, partial(open_url, url)) for x in ('undo', 'redo'): ac = actions['editor-%s' % x] if ac.isEnabled(): a(ac) m.addSeparator() for x in ('cut', 'copy', 'paste'): ac = actions['editor-' + x] if ac.isEnabled(): a(ac) m.addSeparator() m.addAction(_('&Select all'), self.editor.select_all) if self.selected_text or self.has_marked_text: update_mark_text_action(self) m.addAction(actions['mark-selected-text']) if self.syntax != 'css' and actions['editor-cut'].isEnabled(): cm = QMenu(_('Change &case'), m) for ac in 'upper lower swap title capitalize'.split(): cm.addAction(actions['transform-case-' + ac]) m.addMenu(cm) if self.syntax == 'html': m.addAction(actions['multisplit']) m.exec_(self.editor.viewport().mapToGlobal(pos))
def show_context_menu(self, pos): m = QMenu(self) a = m.addAction c = self.editor.cursorForPosition(pos) origc = QTextCursor(c) current_cursor = self.editor.textCursor() r = origr = self.editor.syntax_range_for_cursor(c) if (r is None or not r.format.property(SPELL_PROPERTY)) and c.positionInBlock() > 0 and not current_cursor.hasSelection(): c.setPosition(c.position() - 1) r = self.editor.syntax_range_for_cursor(c) if r is not None and r.format.property(SPELL_PROPERTY): word = self.editor.text_for_range(c.block(), r) locale = self.editor.spellcheck_locale_for_cursor(c) orig_pos = c.position() c.setPosition(orig_pos - utf16_length(word)) found = False self.editor.setTextCursor(c) if self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False): found = True fc = self.editor.textCursor() if fc.position() < c.position(): self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False) spell_cursor = self.editor.textCursor() if current_cursor.hasSelection(): # Restore the current cursor so that any selection is preserved # for the change case actions self.editor.setTextCursor(current_cursor) if found: suggestions = dictionaries.suggestions(word, locale)[:7] if suggestions: for suggestion in suggestions: ac = m.addAction(suggestion, partial(self.editor.simple_replace, suggestion, cursor=spell_cursor)) f = ac.font() f.setBold(True), ac.setFont(f) m.addSeparator() m.addAction(actions['spell-next']) m.addAction(_('Ignore this word'), partial(self._nuke_word, None, word, locale)) dics = dictionaries.active_user_dictionaries if len(dics) > 0: if len(dics) == 1: m.addAction(_('Add this word to the dictionary: {0}').format(dics[0].name), partial( self._nuke_word, dics[0].name, word, locale)) else: ac = m.addAction(_('Add this word to the dictionary')) dmenu = QMenu(m) ac.setMenu(dmenu) for dic in dics: dmenu.addAction(dic.name, partial(self._nuke_word, dic.name, word, locale)) m.addSeparator() if origr is not None and origr.format.property(LINK_PROPERTY): href = self.editor.text_for_range(origc.block(), origr) m.addAction(_('Open %s') % href, partial(self.link_clicked.emit, href)) if origr is not None and (origr.format.property(TAG_NAME_PROPERTY) or origr.format.property(CSS_PROPERTY)): word = self.editor.text_for_range(origc.block(), origr) item_type = 'tag_name' if origr.format.property(TAG_NAME_PROPERTY) else 'css_property' url = help_url(word, item_type, self.editor.highlighter.doc_name, extra_data=current_container().opf_version) if url is not None: m.addAction(_('Show help for: %s') % word, partial(open_url, url)) for x in ('undo', 'redo'): ac = actions['editor-%s' % x] if ac.isEnabled(): a(ac) m.addSeparator() for x in ('cut', 'copy', 'paste'): ac = actions['editor-' + x] if ac.isEnabled(): a(ac) m.addSeparator() m.addAction(_('&Select all'), self.editor.select_all) if self.selected_text or self.has_marked_text: update_mark_text_action(self) m.addAction(actions['mark-selected-text']) if self.syntax != 'css' and actions['editor-cut'].isEnabled(): cm = QMenu(_('Change &case'), m) for ac in 'upper lower swap title capitalize'.split(): cm.addAction(actions['transform-case-' + ac]) m.addMenu(cm) if self.syntax == 'html': m.addAction(actions['multisplit']) m.exec_(self.editor.viewport().mapToGlobal(pos))
def show_context_menu(self, pos): m = QMenu(self) a = m.addAction c = self.editor.cursorForPosition(pos) fmt = self.editor.syntax_format_for_cursor(c) spell = fmt.property( SPELL_PROPERTY).toPyObject() if fmt is not None else None if spell is not None: word, locale = spell orig_pos = c.position() c.setPosition(orig_pos - utf16_length(word)) found = False self.editor.setTextCursor(c) if self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False): found = True fc = self.editor.textCursor() if fc.position() < c.position(): self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False) if found: suggestions = dictionaries.suggestions(word, locale)[:7] if suggestions: for suggestion in suggestions: ac = m.addAction( suggestion, partial(self.editor.simple_replace, suggestion)) f = ac.font() f.setBold(True), ac.setFont(f) m.addSeparator() m.addAction(actions['spell-next']) m.addAction(_('Ignore this word'), partial(self._nuke_word, None, word, locale)) dics = dictionaries.active_user_dictionaries if len(dics) > 0: if len(dics) == 1: m.addAction( _('Add this word to the dictionary: {0}').format( dics[0].name), partial(self._nuke_word, dics[0].name, word, locale)) else: ac = m.addAction(_('Add this word to the dictionary')) dmenu = QMenu(m) ac.setMenu(dmenu) for dic in dics: dmenu.addAction( dic.name, partial(self._nuke_word, dic.name, word, locale)) m.addSeparator() for x in ('undo', 'redo'): a(actions['editor-%s' % x]) m.addSeparator() for x in ('cut', 'copy', 'paste'): a(actions['editor-' + x]) m.addSeparator() m.addAction(_('&Select all'), self.editor.select_all) m.addAction(actions['mark-selected-text']) if self.syntax == 'html': m.addAction(actions['multisplit']) m.exec_(self.editor.mapToGlobal(pos))