Finding in the current file works

This commit is contained in:
Kovid Goyal 2013-11-12 12:12:23 +05:30
parent 45b1c409e6
commit dfb16c58a6
4 changed files with 74 additions and 5 deletions

View File

@ -313,6 +313,13 @@ class Boss(QObject):
else:
pass # marked text TODO: Implement this
pat = sp.get_regex(state)
if action == 'find':
found = editor.find(pat)
if found:
return
# TODO: Handle wrapping, depending on state['where']
def save_book(self):
c = current_container()
for name, ed in editors.iteritems():

View File

@ -9,6 +9,7 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import textwrap
from future_builtins import map
import regex
from PyQt4.Qt import (
QPlainTextEdit, QFontDatabase, QToolTip, QPalette, QFont,
QTextEdit, QTextFormat, QWidget, QSize, QPainter, Qt, QRect)
@ -20,6 +21,8 @@ from calibre.gui2.tweak_book.editor.syntax.base import SyntaxHighlighter
from calibre.gui2.tweak_book.editor.syntax.html import HTMLHighlighter, XMLHighlighter
from calibre.gui2.tweak_book.editor.syntax.css import CSSHighlighter
PARAGRAPH_SEPARATOR = '\u2029'
_dff = None
def default_font_family():
global _dff
@ -151,6 +154,40 @@ class TextEdit(QPlainTextEdit):
self.current_search_mark = None
self.update_extra_selections()
def find(self, pat):
reverse = pat.flags & regex.REVERSE
c = self.textCursor()
c.clearSelection()
c.movePosition(c.Start if reverse else c.End, c.KeepAnchor)
raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n')
m = pat.search(raw)
if m is None:
return False
start, end = m.span()
if start == end:
return False
if reverse:
# Put the cursor at the start of the match
start, end = end, start
else:
textpos = c.anchor()
start, end = textpos + start, textpos + end
c.clearSelection()
c.setPosition(start)
c.setPosition(end, c.KeepAnchor)
self.setTextCursor(c)
return True
def replace(self, pat, template):
c = self.textCursor()
raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n')
m = pat.fullmatch(raw)
if m is None:
return False
text = m.expand(template)
c.insertText(text)
return True
# Line numbers and cursor line {{{
def highlight_cursor_line(self):
sel = QTextEdit.ExtraSelection()

View File

@ -70,6 +70,12 @@ class Editor(QMainWindow):
def mark_selected_text(self):
self.editor.mark_selected_text()
def find(self, *args, **kwargs):
return self.editor.find(*args, **kwargs)
def replace(self, *args, **kwargs):
return self.editor.replace(*args, **kwargs)
@property
def has_marked_text(self):
return self.editor.current_search_mark is not None

View File

@ -12,7 +12,7 @@ from PyQt4.Qt import (
import regex
from calibre.gui2.widgets import HistoryLineEdit
from calibre.gui2.widgets2 import HistoryLineEdit2
from calibre.gui2.tweak_book import tprefs
REGEX_FLAGS = regex.VERSION1 | regex.WORD | regex.FULLCASE | regex.MULTILINE | regex.UNICODE
@ -46,15 +46,16 @@ class SearchWidget(QWidget):
self.fl = fl = QLabel(_('&Find:'))
fl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
self.find_text = ft = HistoryLineEdit(self)
self.find_text = ft = HistoryLineEdit2(self)
ft.initialize('tweak_book_find_edit')
ft.returnPressed.connect(lambda : self.search_triggered.emit('find'))
fl.setBuddy(ft)
l.addWidget(fl, 0, 0)
l.addWidget(ft, 0, 1)
self.rl = rl = QLabel(_('&Replace:'))
rl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
self.replace_text = rt = HistoryLineEdit(self)
self.replace_text = rt = HistoryLineEdit2(self)
rt.initialize('tweak_book_replace_edit')
rl.setBuddy(rt)
l.addWidget(rl, 1, 0)
@ -153,7 +154,7 @@ class SearchWidget(QWidget):
@dynamic_property
def find(self):
def fget(self):
return unicode(self.find_text.text()).strip()
return unicode(self.find_text.text())
def fset(self, val):
self.find_text.setText(val)
return property(fget=fget, fset=fset)
@ -161,7 +162,7 @@ class SearchWidget(QWidget):
@dynamic_property
def replace(self):
def fget(self):
return unicode(self.replace_text.text()).strip()
return unicode(self.replace_text.text())
def fset(self, val):
self.replace_text.setText(val)
return property(fget=fget, fset=fset)
@ -227,6 +228,8 @@ class SearchWidget(QWidget):
# }}}
regex_cache = {}
class SearchPanel(QWidget):
search_triggered = pyqtSignal(object)
@ -266,3 +269,19 @@ class SearchPanel(QWidget):
def set_where(self, val):
self.widget.where = val
def get_regex(self, state):
raw = state['find']
if state['mode'] != 'regex':
raw = regex.escape(raw, special_only=True)
flags = REGEX_FLAGS
if not state['case_sensitive']:
flags |= regex.IGNORECASE
if state['mode'] == 'regex' and state['dot_all']:
flags |= regex.DOTALL
if state['direction'] == 'up':
flags |= regex.REVERSE
ans = regex_cache.get((flags, raw), None)
if ans is None:
ans = regex_cache[(flags, raw)] = regex.compile(raw, flags=flags)
return ans