Edit Book: Live CSS: Improve detection of which tag the cursor is inside when there are multiple tags on the same line. See #1350495 (Private bug)

This commit is contained in:
Kovid Goyal 2014-07-31 11:06:51 +05:30
parent 609609e688
commit b6a82bf657
4 changed files with 57 additions and 11 deletions

View File

@ -384,12 +384,14 @@ class HTMLSmarts(NullSmarts):
return False
def cursor_position_with_sourceline(self, cursor):
''' Return the tag containing the current cursor as a source line
def cursor_position_with_sourceline(self, cursor, for_position_sync=True):
''' Return the tag just before the current cursor as a source line
number and a list of tags defined on that line upto and including the
containing tag. '''
containing tag. If ``for_position_sync`` is False then the tag
*containing* the cursor is returned instead of the tag just before the
cursor. '''
block = cursor.block()
offset = cursor.position() - block.position()
offset = cursor.positionInBlock()
nblock, boundary = next_tag_boundary(block, offset, forward=False)
if boundary is None:
return None, None
@ -412,8 +414,52 @@ class HTMLSmarts(NullSmarts):
ud = start_block.userData()
if ud is None:
return None, None
all_tags = [t.name for t in ud.tags if (t.is_start and not t.closing and t.offset <= start_offset)]
return sourceline, all_tags
if for_position_sync:
return sourceline, [
t.name for t in ud.tags if (t.is_start and not t.closing and t.offset <= start_offset)]
# We discard self-closing as well as tags that are both opened and
# closed from the end of the list of tags as we want the tag that
# contains the cursor, not the last tag before the cursor
class Tag(object):
__slots__ = 'name', 'is_closed'
def __init__(self, name, is_closed):
self.name = name
self.is_closed = is_closed
def __repr__(self):
return '<%s%s>' % (self.name, ('/' if self.is_closed else ''))
if cursor.block().blockNumber() == start_block.blockNumber():
offset = cursor.positionInBlock()
tag_stack = []
in_tag = None
for t in ud.tags:
if t.offset < offset:
if t.is_start:
if t.closing:
# </tag
for tag in reversed(tag_stack):
is_match = not tag.is_closed and tag.name == t.name
tag.is_closed = True
if is_match:
break
else:
# <tag
in_tag = t.name
else:
# tag>
if in_tag is not None:
tag_stack.append(Tag(in_tag, t.self_closing))
in_tag = None
all_tags = []
found_open = False
for tag in reversed(tag_stack):
if not tag.is_closed:
found_open = True
if found_open:
all_tags.append(tag.name)
return sourceline, list(reversed(all_tags))
def goto_sourceline(self, editor, sourceline, tags, attribute=None):
''' Move the cursor to the tag identified by sourceline and tags (a

View File

@ -790,8 +790,8 @@ class TextEdit(PlainTextEdit):
if hasattr(self.smarts, 'rename_block_tag'):
self.smarts.rename_block_tag(self, new_name)
def current_tag(self):
return self.smarts.cursor_position_with_sourceline(self.textCursor())
def current_tag(self, for_position_sync=True):
return self.smarts.cursor_position_with_sourceline(self.textCursor(), for_position_sync=for_position_sync)
def goto_sourceline(self, sourceline, tags, attribute=None):
return self.smarts.goto_sourceline(self, sourceline, tags, attribute=attribute)

View File

@ -138,8 +138,8 @@ class Editor(QMainWindow):
self.editor.go_to_line(val)
return property(fget=fget, fset=fset)
def current_tag(self):
return self.editor.current_tag()
def current_tag(self, for_position_sync=True):
return self.editor.current_tag(for_position_sync=for_position_sync)
@property
def number_of_lines(self):

View File

@ -481,7 +481,7 @@ class LiveCSS(QWidget):
if self.update_timer.isActive() or (ed is None and editor_name is not None):
return QTimer.singleShot(100, self.update_data)
if ed is not None:
sourceline, tags = ed.current_tag()
sourceline, tags = ed.current_tag(for_position_sync=False)
if self.refresh_needed or self.now_showing != (editor_name, sourceline, tags):
self.show_data(editor_name, sourceline, tags)