Edit Book: Add keyboard shortcuts to jumpt to opening and closing tags (Ctrl+{ and Ctrl+})

This commit is contained in:
Kovid Goyal 2017-04-16 11:04:56 +05:30
parent 89eb3a59a4
commit d387cac871
2 changed files with 28 additions and 2 deletions

View File

@ -837,3 +837,12 @@ text. The editor allows you to insert a snippet with only a few key strokes.
The snippets are very powerful, with many features, such as placeholders you The snippets are very powerful, with many features, such as placeholders you
can jump between, automatic mirroring of repeated text and so on. can jump between, automatic mirroring of repeated text and so on.
For more information, see :doc:`snippets`. For more information, see :doc:`snippets`.
Matching tags
^^^^^^^^^^^^^^^^^^^^^^^^^^^
When editing HTML or XML files, the closest tag containing the current cursor
position is automatically highlighted. You can jump to either the opening tag
or the closing tag using the keyboard shortcuts, :kbd:`Ctrl+{` and
:kbd:`Ctrl+}`.

View File

@ -311,7 +311,7 @@ class Smarts(NullSmarts):
Smarts.self_closing_pat = re.compile(r'/\s*>') Smarts.self_closing_pat = re.compile(r'/\s*>')
Smarts.complete_attr_pat = re.compile(r'''([a-zA-Z0-9_-]+)\s*=\s*(?:'([^']*)|"([^"]*))$''') Smarts.complete_attr_pat = re.compile(r'''([a-zA-Z0-9_-]+)\s*=\s*(?:'([^']*)|"([^"]*))$''')
NullSmarts.__init__(self, *args, **kwargs) NullSmarts.__init__(self, *args, **kwargs)
self.last_matched_tag = None self.last_matched_tag = self.last_matched_closing_tag = None
def get_extra_selections(self, editor): def get_extra_selections(self, editor):
ans = [] ans = []
@ -332,13 +332,24 @@ class Smarts(NullSmarts):
c = editor.textCursor() c = editor.textCursor()
block, offset = c.block(), c.positionInBlock() block, offset = c.block(), c.positionInBlock()
tag = self.last_matched_tag = find_closest_containing_tag(block, offset, max_tags=2000) tag = self.last_matched_tag = find_closest_containing_tag(block, offset, max_tags=2000)
self.last_matched_closing_tag = None
if tag is not None: if tag is not None:
add_tag(tag) add_tag(tag)
tag = find_closing_tag(tag, max_tags=4000) tag = self.last_matched_closing_tag = find_closing_tag(tag, max_tags=4000)
if tag is not None: if tag is not None:
add_tag(tag) add_tag(tag)
return ans return ans
def jump_to_enclosing_tag(self, editor, start=True):
editor.highlighter.join()
tag = self.last_matched_tag if start else self.last_matched_closing_tag
if tag is None:
return False
c = editor.textCursor()
c.setPosition(tag.start_block.position() + tag.start_offset + (1 if start else 2))
editor.setTextCursor(c)
return True
def rename_block_tag(self, editor, new_name): def rename_block_tag(self, editor, new_name):
editor.highlighter.join() editor.highlighter.join()
c = editor.textCursor() c = editor.textCursor()
@ -621,6 +632,12 @@ class Smarts(NullSmarts):
if key == Qt.Key_Backspace and smart_backspace(editor, ev): if key == Qt.Key_Backspace and smart_backspace(editor, ev):
return True return True
if key in (Qt.Key_BraceLeft, Qt.Key_BraceRight):
mods = ev.modifiers()
if int(mods & Qt.ControlModifier):
if self.jump_to_enclosing_tag(editor, key == Qt.Key_BraceLeft):
return True
return False return False
def replace_possible_entity(self, editor): def replace_possible_entity(self, editor):