mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Allow S&R funcs to specify they would like to be called once after all matches are found
This commit is contained in:
parent
cf42295fc5
commit
47b0baae85
@ -343,7 +343,15 @@ class TextEdit(PlainTextEdit):
|
|||||||
if template is None:
|
if template is None:
|
||||||
count = len(pat.findall(raw))
|
count = len(pat.findall(raw))
|
||||||
else:
|
else:
|
||||||
|
from calibre.gui2.tweak_book.function_replace import Function
|
||||||
|
repl_is_func = isinstance(template, Function)
|
||||||
|
if repl_is_func:
|
||||||
|
template.init_env()
|
||||||
raw, count = pat.subn(template, raw)
|
raw, count = pat.subn(template, raw)
|
||||||
|
if repl_is_func:
|
||||||
|
from calibre.gui2.tweak_book.search import show_function_debug_output
|
||||||
|
show_function_debug_output(template)
|
||||||
|
template.end()
|
||||||
if count > 0:
|
if count > 0:
|
||||||
start_pos = min(c.anchor(), c.position())
|
start_pos = min(c.anchor(), c.position())
|
||||||
c.insertText(raw)
|
c.insertText(raw)
|
||||||
|
@ -11,7 +11,7 @@ from cStringIO import StringIO
|
|||||||
|
|
||||||
from PyQt5.Qt import (
|
from PyQt5.Qt import (
|
||||||
pyqtSignal, QVBoxLayout, QHBoxLayout, QPlainTextEdit, QLabel, QFontMetrics,
|
pyqtSignal, QVBoxLayout, QHBoxLayout, QPlainTextEdit, QLabel, QFontMetrics,
|
||||||
QSize, Qt)
|
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
|
||||||
from calibre.gui2 import error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
@ -89,6 +89,14 @@ class Function(object):
|
|||||||
return json.loads(P('editor-functions.json', data=True, allow_user_override=False))[self.name]
|
return json.loads(P('editor-functions.json', data=True, allow_user_override=False))[self.name]
|
||||||
return self._source
|
return self._source
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
if getattr(self.func, 'call_after_last_match', False):
|
||||||
|
oo, oe, sys.stdout, sys.stderr = sys.stdout, sys.stderr, self.debug_buf, self.debug_buf
|
||||||
|
try:
|
||||||
|
return self.func(None, self.match_index, self.context_name, self.boss.current_metadata, dictionaries, self.data, functions())
|
||||||
|
finally:
|
||||||
|
sys.stdout, sys.stderr = oo, oe
|
||||||
|
|
||||||
class DebugOutput(Dialog):
|
class DebugOutput(Dialog):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -98,13 +106,18 @@ class DebugOutput(Dialog):
|
|||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.l = l = QVBoxLayout(self)
|
self.l = l = QVBoxLayout(self)
|
||||||
self.text = t = QPlainTextEdit(self)
|
self.text = t = QPlainTextEdit(self)
|
||||||
|
self.log_text = ''
|
||||||
l.addWidget(t)
|
l.addWidget(t)
|
||||||
l.addWidget(self.bb)
|
l.addWidget(self.bb)
|
||||||
self.bb.setStandardButtons(self.bb.Close)
|
self.bb.setStandardButtons(self.bb.Close)
|
||||||
|
self.cb = b = self.bb.addButton(_('&Copy to clipboard'), self.bb.ActionRole)
|
||||||
|
b.clicked.connect(self.copy_to_clipboard)
|
||||||
|
b.setIcon(QIcon(I('edit-copy.png')))
|
||||||
|
|
||||||
def show_log(self, name, text):
|
def show_log(self, name, text):
|
||||||
self.setWindowTitle(_('Debug output from %s') % name)
|
self.setWindowTitle(_('Debug output from %s') % name)
|
||||||
self.text.setPlainText(self.windowTitle() + '\n\n' + text)
|
self.text.setPlainText(self.windowTitle() + '\n\n' + text)
|
||||||
|
self.log_text = text
|
||||||
self.show()
|
self.show()
|
||||||
self.raise_()
|
self.raise_()
|
||||||
|
|
||||||
@ -112,6 +125,9 @@ class DebugOutput(Dialog):
|
|||||||
fm = QFontMetrics(self.text.font())
|
fm = QFontMetrics(self.text.font())
|
||||||
return QSize(fm.averageCharWidth() * 120, 400)
|
return QSize(fm.averageCharWidth() * 120, 400)
|
||||||
|
|
||||||
|
def copy_to_clipboard(self):
|
||||||
|
QApplication.instance().clipboard().setText(self.log_text)
|
||||||
|
|
||||||
def builtin_functions():
|
def builtin_functions():
|
||||||
for name, obj in globals().iteritems():
|
for name, obj in globals().iteritems():
|
||||||
if name.startswith('replace_') and callable(obj):
|
if name.startswith('replace_') and callable(obj):
|
||||||
@ -300,7 +316,6 @@ def replace_swapcase(match, number, file_name, metadata, dictionaries, data, fun
|
|||||||
return apply_func_to_match_groups(match, swapcase)
|
return apply_func_to_match_groups(match, swapcase)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from PyQt5.Qt import QApplication
|
|
||||||
app = QApplication([])
|
app = QApplication([])
|
||||||
FunctionEditor().exec_()
|
FunctionEditor().exec_()
|
||||||
del app
|
del app
|
||||||
|
@ -1262,10 +1262,13 @@ def run_search(
|
|||||||
if editor is None:
|
if editor is None:
|
||||||
return no_replace()
|
return no_replace()
|
||||||
for p, repl in searches:
|
for p, repl in searches:
|
||||||
if callable(repl):
|
repl_is_func = isinstance(repl, Function)
|
||||||
|
if repl_is_func:
|
||||||
repl.init_env(current_editor_name)
|
repl.init_env(current_editor_name)
|
||||||
if editor.replace(p, repl, saved_match='gui'):
|
if editor.replace(p, repl, saved_match='gui'):
|
||||||
show_function_debug_output(repl)
|
if repl_is_func:
|
||||||
|
repl.end()
|
||||||
|
show_function_debug_output(repl)
|
||||||
return True
|
return True
|
||||||
return no_replace(_(
|
return no_replace(_(
|
||||||
'Currently selected text does not match the search query.'))
|
'Currently selected text does not match the search query.'))
|
||||||
@ -1296,12 +1299,13 @@ def run_search(
|
|||||||
raw_data[n] = raw
|
raw_data[n] = raw
|
||||||
|
|
||||||
for p, repl in searches:
|
for p, repl in searches:
|
||||||
if callable(repl):
|
repl_is_func = isinstance(repl, Function)
|
||||||
|
if repl_is_func:
|
||||||
repl.init_env()
|
repl.init_env()
|
||||||
for n, syntax in lfiles.iteritems():
|
for n, syntax in lfiles.iteritems():
|
||||||
raw = raw_data[n]
|
raw = raw_data[n]
|
||||||
if replace:
|
if replace:
|
||||||
if callable(repl):
|
if repl_is_func:
|
||||||
repl.context_name = n
|
repl.context_name = n
|
||||||
raw, num = p.subn(repl, raw)
|
raw, num = p.subn(repl, raw)
|
||||||
if num > 0:
|
if num > 0:
|
||||||
@ -1310,7 +1314,9 @@ def run_search(
|
|||||||
else:
|
else:
|
||||||
num = len(p.findall(raw))
|
num = len(p.findall(raw))
|
||||||
count += num
|
count += num
|
||||||
show_function_debug_output(repl)
|
if repl_is_func:
|
||||||
|
repl.end()
|
||||||
|
show_function_debug_output(repl)
|
||||||
|
|
||||||
for n in updates:
|
for n in updates:
|
||||||
raw = raw_data[n]
|
raw = raw_data[n]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user