. +[/LIST] +[/LIST] +''' \ No newline at end of file diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index ca0fc26927..d3c0d8377b 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -43,6 +43,7 @@ from calibre.gui2.auto_add import AutoAdder from calibre.gui2.changes import handle_changes from calibre.gui2.cover_flow import CoverFlowMixin from calibre.gui2.device import DeviceMixin +from calibre.gui2.dialogs.ff_doc_editor import FFDocEditor from calibre.gui2.dialogs.message_box import JobError from calibre.gui2.ebook_download import EbookDownloadMixin from calibre.gui2.email import EmailMixin @@ -329,6 +330,13 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ action=self.alt_esc_action) self.alt_esc_action.triggered.connect(self.clear_additional_restriction) + self.ff_doc_editor_action = QAction(self) + self.addAction(self.ff_doc_editor_action) + self.keyboard.register_shortcut('open ff document editor', + _('Open the template documentation editor'), default_keys=(''), + action=self.ff_doc_editor_action) + self.ff_doc_editor_action.triggered.connect(self.open_ff_doc_editor) + # ###################### Start spare job server ######################## QTimer.singleShot(1000, self.create_spare_pool) @@ -462,6 +470,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ def esc(self, *args): self.search.clear() + def open_ff_doc_editor(self): + FFDocEditor(False).exec() + def focus_current_view(self): view = self.current_view() if view is self.library_view: diff --git a/src/calibre/utils/ffml_processor.py b/src/calibre/utils/ffml_processor.py index cf948bbe95..a8fc7143c9 100644 --- a/src/calibre/utils/ffml_processor.py +++ b/src/calibre/utils/ffml_processor.py @@ -41,10 +41,10 @@ class Node: return self._children def text(self): - return self._text + return self._text.replace('\\', '') def escaped_text(self): - return prepare_string_for_xml(self._text) + return prepare_string_for_xml(self.text()) class BlankLineNode(Node): @@ -248,6 +248,7 @@ class FFMLProcessor: :return: a parse tree for the document """ + self.input_line = 1 self.input = doc self.input_pos = 0 self.document_name = name @@ -404,13 +405,16 @@ class FFMLProcessor: self.document = DocumentNode() self.input = None self.input_pos = 0 - self.input_line = 1 def error(self, message): raise ValueError(f'{message} on line {self.input_line} in "{self.document_name}"') def find(self, for_what): p = self.input.find(for_what, self.input_pos) + if p < 0: + return -1 + while p > 0 and self.input[p-1] == '\\': + p = self.input.find(for_what, p+1) return -1 if p < 0 else p - self.input_pos def move_pos(self, to_where): @@ -450,7 +454,9 @@ class FFMLProcessor: return len(self.input) def get_code_block(self): - self.move_pos(len('[CODE]\n')) + self.move_pos(len('[CODE]')) + if self.text_to(1) == '\n': + self.move_pos(1) end = self.find('[/CODE]') if end < 0: self.error('Missing [/CODE] for block') @@ -469,6 +475,11 @@ class FFMLProcessor: self.move_pos(end + len('``')) return node + def get_escaped_char(self): + node = EscapedCharNode(self.text_to(1)) + self.move_pos(1) + return node + def get_gui_label(self): self.move_pos(len(':guilabel:`')) end = self.find('`')