mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Implement navigation to rules defined in stylesheets
This commit is contained in:
parent
d993534dfc
commit
4febe3c455
@ -25,3 +25,6 @@ class NullSmarts(object):
|
|||||||
|
|
||||||
def goto_sourceline(self, editor, sourceline, tags, attribute=None):
|
def goto_sourceline(self, editor, sourceline, tags, attribute=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_inner_HTML(self, editor):
|
||||||
|
return None
|
||||||
|
31
src/calibre/gui2/tweak_book/editor/smart/css.py
Normal file
31
src/calibre/gui2/tweak_book/editor/smart/css.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
|
from calibre.gui2.tweak_book.editor.smart import NullSmarts
|
||||||
|
|
||||||
|
def find_rule(raw, rule_address):
|
||||||
|
import tinycss
|
||||||
|
parser = tinycss.make_parser()
|
||||||
|
sheet = parser.parse_stylesheet(raw)
|
||||||
|
rules = sheet.rules
|
||||||
|
ans = None, None
|
||||||
|
while rule_address:
|
||||||
|
try:
|
||||||
|
r = rules[rule_address[0]]
|
||||||
|
except IndexError:
|
||||||
|
return None, None
|
||||||
|
else:
|
||||||
|
ans = r.line, r.column
|
||||||
|
rule_address = rule_address[1:]
|
||||||
|
if rule_address:
|
||||||
|
rules = getattr(r, 'rules', ())
|
||||||
|
return ans
|
||||||
|
|
||||||
|
class CSSSmarts(NullSmarts):
|
||||||
|
pass
|
||||||
|
|
@ -383,3 +383,27 @@ class HTMLSmarts(NullSmarts):
|
|||||||
editor.setTextCursor(c)
|
editor.setTextCursor(c)
|
||||||
return found_tag
|
return found_tag
|
||||||
|
|
||||||
|
def get_inner_HTML(self, editor):
|
||||||
|
''' Select the inner HTML of the current tag. Return a cursor with the
|
||||||
|
inner HTML selected or None. '''
|
||||||
|
c = editor.textCursor()
|
||||||
|
block = c.block()
|
||||||
|
offset = c.position() - block.position()
|
||||||
|
nblock, boundary = next_tag_boundary(block, offset)
|
||||||
|
if boundary.is_start:
|
||||||
|
# We are within the contents of a tag already
|
||||||
|
tag = find_closest_containing_tag(block, offset)
|
||||||
|
else:
|
||||||
|
# We are inside a tag definition < | >
|
||||||
|
if boundary.self_closing:
|
||||||
|
return None # self closing tags have no inner html
|
||||||
|
tag = find_closest_containing_tag(nblock, boundary.offset + 1)
|
||||||
|
if tag is None:
|
||||||
|
return None
|
||||||
|
ctag = find_closing_tag(tag)
|
||||||
|
if ctag is None:
|
||||||
|
return None
|
||||||
|
c.setPosition(tag.end_block.position() + tag.end_offset + 1)
|
||||||
|
c.setPosition(ctag.start_block.position() + ctag.start_offset, c.KeepAnchor)
|
||||||
|
return c
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ from calibre.gui2.tweak_book.editor.syntax.html import HTMLHighlighter, XMLHighl
|
|||||||
from calibre.gui2.tweak_book.editor.syntax.css import CSSHighlighter
|
from calibre.gui2.tweak_book.editor.syntax.css import CSSHighlighter
|
||||||
from calibre.gui2.tweak_book.editor.smart import NullSmarts
|
from calibre.gui2.tweak_book.editor.smart import NullSmarts
|
||||||
from calibre.gui2.tweak_book.editor.smart.html import HTMLSmarts
|
from calibre.gui2.tweak_book.editor.smart.html import HTMLSmarts
|
||||||
|
from calibre.gui2.tweak_book.editor.smart.css import CSSSmarts
|
||||||
from calibre.spell.break_iterator import index_of
|
from calibre.spell.break_iterator import index_of
|
||||||
from calibre.utils.icu import safe_chr, string_length
|
from calibre.utils.icu import safe_chr, string_length
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ class TextEdit(PlainTextEdit):
|
|||||||
self.highlighter = get_highlighter(syntax)()
|
self.highlighter = get_highlighter(syntax)()
|
||||||
self.highlighter.apply_theme(self.theme)
|
self.highlighter.apply_theme(self.theme)
|
||||||
self.highlighter.set_document(self.document())
|
self.highlighter.set_document(self.document())
|
||||||
sclass = {'html':HTMLSmarts, 'xml':HTMLSmarts}.get(syntax, None)
|
sclass = {'html':HTMLSmarts, 'xml':HTMLSmarts, 'css':CSSSmarts}.get(syntax, None)
|
||||||
if sclass is not None:
|
if sclass is not None:
|
||||||
self.smarts = sclass(self)
|
self.smarts = sclass(self)
|
||||||
self.setPlainText(unicodedata.normalize('NFC', text))
|
self.setPlainText(unicodedata.normalize('NFC', text))
|
||||||
@ -755,3 +756,31 @@ class TextEdit(PlainTextEdit):
|
|||||||
def goto_sourceline(self, sourceline, tags, attribute=None):
|
def goto_sourceline(self, sourceline, tags, attribute=None):
|
||||||
return self.smarts.goto_sourceline(self, sourceline, tags, attribute=attribute)
|
return self.smarts.goto_sourceline(self, sourceline, tags, attribute=attribute)
|
||||||
|
|
||||||
|
def get_tag_contents(self):
|
||||||
|
c = self.smarts.get_inner_HTML(self)
|
||||||
|
if c is not None:
|
||||||
|
return self.selected_text_from_cursor(c)
|
||||||
|
|
||||||
|
def goto_css_rule(self, rule_address, sourceline_address=None):
|
||||||
|
from calibre.gui2.tweak_book.editor.smart.css import find_rule
|
||||||
|
block = None
|
||||||
|
if self.syntax == 'css':
|
||||||
|
raw = unicode(self.toPlainText())
|
||||||
|
line, col = find_rule(raw, rule_address)
|
||||||
|
if line is not None:
|
||||||
|
block = self.document().findBlockByNumber(line - 1)
|
||||||
|
elif sourceline_address is not None:
|
||||||
|
sourceline, tags = sourceline_address
|
||||||
|
if self.goto_sourceline(sourceline, tags):
|
||||||
|
c = self.textCursor()
|
||||||
|
c.setPosition(c.position() + 1)
|
||||||
|
self.setTextCursor(c)
|
||||||
|
raw = self.get_tag_contents()
|
||||||
|
line, col = find_rule(raw, rule_address)
|
||||||
|
if line is not None:
|
||||||
|
block = self.document().findBlockByNumber(c.blockNumber() + line - 1)
|
||||||
|
|
||||||
|
if block is not None and block.isValid():
|
||||||
|
c = self.textCursor()
|
||||||
|
c.setPosition(block.position() + col)
|
||||||
|
self.setTextCursor(c)
|
||||||
|
@ -406,6 +406,12 @@ class Editor(QMainWindow):
|
|||||||
def goto_sourceline(self, *args, **kwargs):
|
def goto_sourceline(self, *args, **kwargs):
|
||||||
return self.editor.goto_sourceline(*args, **kwargs)
|
return self.editor.goto_sourceline(*args, **kwargs)
|
||||||
|
|
||||||
|
def goto_css_rule(self, *args, **kwargs):
|
||||||
|
return self.editor.goto_css_rule(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_tag_contents(self, *args, **kwargs):
|
||||||
|
return self.editor.get_tag_contents(*args, **kwargs)
|
||||||
|
|
||||||
def _nuke_word(self, dic, word, locale):
|
def _nuke_word(self, dic, word, locale):
|
||||||
if dic is None:
|
if dic is None:
|
||||||
dictionaries.ignore_word(word, locale)
|
dictionaries.ignore_word(word, locale)
|
||||||
|
@ -412,4 +412,8 @@ class LiveCSS(QWidget):
|
|||||||
if data['type'] == 'inline':
|
if data['type'] == 'inline':
|
||||||
sourceline, tags = data['sourceline_address']
|
sourceline, tags = data['sourceline_address']
|
||||||
editor.goto_sourceline(sourceline, tags, attribute='style')
|
editor.goto_sourceline(sourceline, tags, attribute='style')
|
||||||
|
elif data['type'] == 'sheet':
|
||||||
|
editor.goto_css_rule(data['rule_address'])
|
||||||
|
elif data['type'] == 'elem':
|
||||||
|
editor.goto_css_rule(data['rule_address'], sourceline_address=data['sourceline_address'])
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user