Enable use of snippets in the search/replace panel and the saved searches dialog

This commit is contained in:
Kovid Goyal 2015-01-08 21:19:09 +05:30
parent 3a30197900
commit a4a8625783
3 changed files with 49 additions and 6 deletions

View File

@ -326,9 +326,9 @@ def expand_template(editor, trigger, template):
c.endEditBlock() c.endEditBlock()
return tl return tl
def find_matching_snip(text, syntax): def find_matching_snip(text, syntax=None):
for key, snip in snippets().iteritems(): for key, snip in snippets().iteritems():
if text.endswith(key.trigger) and syntax in key.syntaxes: if text.endswith(key.trigger) and (syntax in key.syntaxes or syntax is None):
return snip, key.trigger return snip, key.trigger
return None, None return None, None
@ -393,7 +393,6 @@ class SnippetManager(QObject):
return False return False
# }}} # }}}
# Config {{{ # Config {{{
class EditSnippet(QWidget): class EditSnippet(QWidget):

View File

@ -84,6 +84,7 @@ class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent=None): def __init__(self, parent=None):
QPlainTextEdit.__init__(self, parent) QPlainTextEdit.__init__(self, parent)
self.selectionChanged.connect(self.selection_changed) self.selectionChanged.connect(self.selection_changed)
self.syntax = None
def toPlainText(self): def toPlainText(self):
# QPlainTextEdit's toPlainText implementation replaces nbsp with normal # QPlainTextEdit's toPlainText implementation replaces nbsp with normal

View File

@ -14,7 +14,7 @@ from PyQt5.Qt import (
QWidget, QToolBar, Qt, QHBoxLayout, QSize, QIcon, QGridLayout, QLabel, QTimer, QWidget, QToolBar, Qt, QHBoxLayout, QSize, QIcon, QGridLayout, QLabel, QTimer,
QPushButton, pyqtSignal, QComboBox, QCheckBox, QSizePolicy, QVBoxLayout, QFont, QPushButton, pyqtSignal, QComboBox, QCheckBox, QSizePolicy, QVBoxLayout, QFont,
QLineEdit, QToolButton, QListView, QFrame, QApplication, QStyledItemDelegate, QLineEdit, QToolButton, QListView, QFrame, QApplication, QStyledItemDelegate,
QAbstractListModel, QPlainTextEdit, QModelIndex, QMenu, QItemSelection, QStackedLayout) QAbstractListModel, QModelIndex, QMenu, QItemSelection, QStackedLayout)
import regex import regex
@ -26,6 +26,8 @@ from calibre.gui2.tweak_book import tprefs, editors, current_container
from calibre.gui2.tweak_book.function_replace import ( from calibre.gui2.tweak_book.function_replace import (
FunctionBox, functions as replace_functions, FunctionEditor, remove_function, Function) FunctionBox, functions as replace_functions, FunctionEditor, remove_function, Function)
from calibre.gui2.tweak_book.widgets import BusyCursor from calibre.gui2.tweak_book.widgets import BusyCursor
from calibre.gui2.tweak_book.editor.text import PlainTextEdit
from calibre.gui2.tweak_book.editor.snippets import find_matching_snip, parse_template, string_length, SnippetManager
from calibre.utils.icu import primary_contains from calibre.utils.icu import primary_contains
@ -51,12 +53,42 @@ class AnimatablePushButton(QPushButton):
self.setDown(False) self.setDown(False)
self.update() self.update()
class TextEdit(PlainTextEdit):
def __init__(self, text, parent=None):
PlainTextEdit.__init__(self, parent)
if text:
self.setPlainText(text)
self.snippet_manager = SnippetManager(self)
def keyPressEvent(self, ev):
if self.snippet_manager.handle_key_press(ev):
return
PlainTextEdit.keyPressEvent(self, ev)
class PushButton(AnimatablePushButton): class PushButton(AnimatablePushButton):
def __init__(self, text, action, parent): def __init__(self, text, action, parent):
AnimatablePushButton.__init__(self, text, parent) AnimatablePushButton.__init__(self, text, parent)
self.clicked.connect(lambda : parent.search_triggered.emit(action)) self.clicked.connect(lambda : parent.search_triggered.emit(action))
def expand_template(line_edit):
pos = line_edit.cursorPosition()
text = line_edit.text()[:pos]
if text:
snip, trigger = find_matching_snip(text)
if snip is None:
error_dialog(line_edit, _('No snippet found'), _(
'No matching snippet was found'), show=True)
return False
text, tab_stops = parse_template(snip['template'])
ft = line_edit.text()
l = string_length(trigger)
line_edit.setText(ft[:pos - l] + text + ft[pos:])
line_edit.setCursorPosition(pos - l + string_length(text))
return True
return False
class HistoryBox(HistoryComboBox): class HistoryBox(HistoryComboBox):
max_history_items = 100 max_history_items = 100
@ -67,6 +99,17 @@ class HistoryBox(HistoryComboBox):
HistoryComboBox.__init__(self, parent) HistoryComboBox.__init__(self, parent)
self.disable_popup = tprefs['disable_completion_popup_for_search'] self.disable_popup = tprefs['disable_completion_popup_for_search']
self.clear_msg = clear_msg self.clear_msg = clear_msg
self.ignore_snip_expansion = False
def event(self, ev):
if ev.type() in (ev.ShortcutOverride, ev.KeyPress) and ev.key() == Qt.Key_Tab and ev.modifiers() & Qt.CTRL:
if not self.ignore_snip_expansion:
self.ignore_snip_expansion = True
expand_template(self.lineEdit())
QTimer.singleShot(100, lambda : setattr(self, 'ignore_snip_expansion', False))
ev.accept()
return True
return HistoryComboBox.event(self, ev)
def contextMenuEvent(self, event): def contextMenuEvent(self, event):
menu = self.lineEdit().createStandardContextMenu() menu = self.lineEdit().createStandardContextMenu()
@ -551,12 +594,12 @@ class EditSearch(QFrame): # {{{
h.addWidget(la), h.addWidget(n) h.addWidget(la), h.addWidget(n)
l.addLayout(h) l.addLayout(h)
self.find = f = QPlainTextEdit('', self) self.find = f = TextEdit('', self)
self.la2 = la = QLabel(_('&Find:')) self.la2 = la = QLabel(_('&Find:'))
la.setBuddy(f) la.setBuddy(f)
l.addWidget(la), l.addWidget(f) l.addWidget(la), l.addWidget(f)
self.replace = r = QPlainTextEdit('', self) self.replace = r = TextEdit('', self)
self.la3 = la = QLabel(_('&Replace:')) self.la3 = la = QLabel(_('&Replace:'))
la.setBuddy(r) la.setBuddy(r)
l.addWidget(la), l.addWidget(r) l.addWidget(la), l.addWidget(r)