mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More robust implementation of current tag detection for Live CSS. Now uses the same logic as matching tag highlighting.
This commit is contained in:
parent
b9d90fe9b3
commit
df15f6120a
@ -396,79 +396,39 @@ class HTMLSmarts(NullSmarts):
|
|||||||
number and a list of tags defined on that line upto and including the
|
number and a list of tags defined on that line upto and including the
|
||||||
containing tag. If ``for_position_sync`` is False then the tag
|
containing tag. If ``for_position_sync`` is False then the tag
|
||||||
*containing* the cursor is returned instead of the tag just before the
|
*containing* the cursor is returned instead of the tag just before the
|
||||||
cursor. '''
|
cursor. Note that finding the containing tag is relative expensive, so
|
||||||
block = cursor.block()
|
use with care.'''
|
||||||
offset = cursor.positionInBlock()
|
block, offset = cursor.block(), cursor.positionInBlock()
|
||||||
nblock, boundary = next_tag_boundary(block, offset, forward=False)
|
if for_position_sync:
|
||||||
if boundary is None:
|
nblock, boundary = next_tag_boundary(block, offset, forward=False)
|
||||||
return None, None
|
if boundary is None:
|
||||||
in_tag_definition = False
|
return None, None
|
||||||
if boundary.is_start:
|
if boundary.is_start:
|
||||||
# We are inside a tag, use this tag
|
# We are inside a tag, use this tag
|
||||||
start_block, start_offset = nblock, boundary.offset
|
start_block, start_offset = nblock, boundary.offset
|
||||||
in_tag_definition = True
|
else:
|
||||||
|
start_block = None
|
||||||
|
while start_block is None and block.isValid():
|
||||||
|
ud = block.userData()
|
||||||
|
if ud is not None:
|
||||||
|
for boundary in reversed(ud.tags):
|
||||||
|
if boundary.is_start and not boundary.closing and boundary.offset <= offset:
|
||||||
|
start_block, start_offset = block, boundary.offset
|
||||||
|
break
|
||||||
|
block, offset = block.previous(), sys.maxint
|
||||||
else:
|
else:
|
||||||
start_block = None
|
tag = find_closest_containing_tag(block, offset, max_tags=2000)
|
||||||
while start_block is None and block.isValid():
|
if tag is None:
|
||||||
ud = block.userData()
|
return None, None
|
||||||
if ud is not None:
|
start_block, start_offset = tag.start_block, tag.start_offset
|
||||||
for boundary in reversed(ud.tags):
|
|
||||||
if boundary.is_start and not boundary.closing and boundary.offset <= offset:
|
|
||||||
start_block, start_offset = block, boundary.offset
|
|
||||||
break
|
|
||||||
block, offset = block.previous(), sys.maxint
|
|
||||||
if start_block is None:
|
if start_block is None:
|
||||||
return None, None
|
return None, None
|
||||||
sourceline = start_block.blockNumber() + 1 # blockNumber() is zero based
|
sourceline = start_block.blockNumber() + 1 # blockNumber() is zero based
|
||||||
ud = start_block.userData()
|
ud = start_block.userData()
|
||||||
if ud is None:
|
if ud is None:
|
||||||
return None, None
|
return None, None
|
||||||
if for_position_sync or in_tag_definition:
|
return sourceline, [
|
||||||
return sourceline, [
|
t.name for t in ud.tags if (t.is_start and not t.closing and t.offset <= start_offset)]
|
||||||
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):
|
def goto_sourceline(self, editor, sourceline, tags, attribute=None):
|
||||||
''' Move the cursor to the tag identified by sourceline and tags (a
|
''' Move the cursor to the tag identified by sourceline and tags (a
|
||||||
|
Loading…
x
Reference in New Issue
Block a user