From 1410194a0d084be2e96abea131151ff7a9946577 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 31 Dec 2014 08:39:57 +0530 Subject: [PATCH] Edit Book Function mode: Add builtin functions to change case of text, ignoring HTML tags in the matched text --- manual/function_mode.rst | 7 ++--- src/calibre/ebooks/oeb/polish/utils.py | 6 +++++ .../gui2/tweak_book/function_replace.py | 27 ++++++++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/manual/function_mode.rst b/manual/function_mode.rst index f8c3a79174..d2c8deadf3 100644 --- a/manual/function_mode.rst +++ b/manual/function_mode.rst @@ -28,11 +28,12 @@ Automatically fixing the case of headings in the document Here, we will leverage one of the builtin functions in the editor to automatically change the case of all text inside heading tags to title case:: - Find expression: <[Hh][1-6][^>]*>([^<>]+) + Find expression: <([Hh][1-6])[^>]*>.+? -For the function, simply choose the :guilabel:`Title-case text` builtin +For the function, simply choose the :guilabel:`Title-case text (ignore tags)` builtin function. The will change titles that look like: ``

some TITLE

`` to -``

Some Title

``. +``

Some Title

``. It will work even if there are other HTML tags inside +the heading tags. Your first custom function - smartening hyphens diff --git a/src/calibre/ebooks/oeb/polish/utils.py b/src/calibre/ebooks/oeb/polish/utils.py index 7982bbc163..7013623ea9 100644 --- a/src/calibre/ebooks/oeb/polish/utils.py +++ b/src/calibre/ebooks/oeb/polish/utils.py @@ -198,3 +198,9 @@ def apply_func_to_match_groups(match, func=icu_upper, handle_entities=handle_ent parts.append(match.string[pos:match.end()]) return ''.join(parts) +def apply_func_to_html_text(match, func=icu_upper, handle_entities=handle_entities): + ''' Apply the specified function only to text between HTML tag definitions. ''' + parts = re.split(r'(<[^>]+>)', match.group()) + parts = (x if x.startswith('<') else func(x) for x in parts) + return ''.join(parts) + diff --git a/src/calibre/gui2/tweak_book/function_replace.py b/src/calibre/gui2/tweak_book/function_replace.py index be1368c4c7..69ababc18d 100644 --- a/src/calibre/gui2/tweak_book/function_replace.py +++ b/src/calibre/gui2/tweak_book/function_replace.py @@ -13,7 +13,7 @@ from PyQt5.Qt import ( pyqtSignal, QVBoxLayout, QHBoxLayout, QPlainTextEdit, QLabel, QFontMetrics, QSize, Qt, QApplication, QIcon) -from calibre.ebooks.oeb.polish.utils import apply_func_to_match_groups +from calibre.ebooks.oeb.polish.utils import apply_func_to_match_groups, apply_func_to_html_text from calibre.gui2 import error_dialog from calibre.gui2.complete2 import EditWithComplete from calibre.gui2.tweak_book import dictionaries @@ -319,6 +319,31 @@ def replace_swapcase(match, number, file_name, metadata, dictionaries, data, fun changed.''' return apply_func_to_match_groups(match, swapcase) +@builtin('Upper-case text (ignore tags)', upper, apply_func_to_html_text) +def replace_uppercase_ignore_tags(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs): + '''Make matched text upper case, ignoring the text inside tag definitions.''' + return apply_func_to_html_text(match, upper) + +@builtin('Lower-case text (ignore tags)', lower, apply_func_to_html_text) +def replace_lowercase_ignore_tags(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs): + '''Make matched text lower case, ignoring the text inside tag definitions.''' + return apply_func_to_html_text(match, lower) + +@builtin('Capitalize text (ignore tags)', capitalize, apply_func_to_html_text) +def replace_capitalize_ignore_tags(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs): + '''Capitalize matched text, ignoring the text inside tag definitions.''' + return apply_func_to_html_text(match, capitalize) + +@builtin('Title-case text (ignore tags)', titlecase, apply_func_to_html_text) +def replace_titlecase_ignore_tags(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs): + '''Title-case matched text, ignoring the text inside tag definitions.''' + return apply_func_to_html_text(match, titlecase) + +@builtin('Swap the case of text (ignore tags)', swapcase, apply_func_to_html_text) +def replace_swapcase_ignore_tags(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs): + '''Swap the case of the matched text, ignoring the text inside tag definitions.''' + return apply_func_to_html_text(match, swapcase) + if __name__ == '__main__': app = QApplication([]) FunctionEditor().exec_()