pmacs3/mode/replace.py

163 lines
4.5 KiB
Python
Raw Permalink Normal View History

import re
from method import Method
from mode import Fundamental
import minibuffer, searchutil
2007-07-21 11:40:53 -04:00
subgroup_re = re.compile(r'((?:\\\\)*)\\(0|[1-9][0-9]*)')
class ReplaceOne(Method):
'In a replace command, replace the next occurance'
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
m = w.buffer.method
_replace(m)
_find_next(m, False)
_finish(m, w)
class ReplaceDone(Method):
'In a replace command, replace the next occurance and exit'
def execute(self, w, **vargs):
m = w.buffer.method
_replace(m)
_end(w)
w.set_error("Replace done")
class SkipReplace(Method):
'In a replace command, skip the next occurance'
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
m = w.buffer.method
2007-08-11 10:16:41 -04:00
_find_next(m, True)
2007-07-21 11:40:53 -04:00
_finish(m, w)
class ReplaceAll(Method):
'In a replace command, replace all remaining occurances'
# FIXME: this is super slow
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
m = w.buffer.method
while m.p1 is not None:
_replace(m)
_find_next(m, False)
_end(w)
w.set_error("Replace ended")
class CancelReplace(Method):
'Cancel a currently running replace command'
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
_end(w)
w.set_error("Replace cancelled")
def _find_next(m, move=False):
s = m.before
w = m.old_window
c = w.logical_cursor()
2007-07-21 11:40:53 -04:00
try:
if m.is_literal:
r = re.compile(searchutil.escape_literal(s))
else:
r = re.compile(s)
2007-07-21 11:40:53 -04:00
except:
(m.p1, m.p2) = (None, None)
return False
if move:
newc = searchutil.find_next(r, w, False, start=c.add(1, 0))
else:
newc = searchutil.find_next(r, w, False, start=c.add(0, 0))
2007-07-21 11:40:53 -04:00
if newc:
(m.p1, m.p2, m.match) = newc
2007-07-21 11:40:53 -04:00
return True
else:
(m.p1, m.p2, m.match) = (None, None, None)
2007-07-21 11:40:53 -04:00
return False
def _get_before(m):
if m.match is None:
return m.before
else:
return m.match.group(0)
def _get_after(m):
if m.after is None:
return None
elif m.match is None:
return m.after
def _repl(match):
(pre, num) = (match.group(1), int(match.group(2)))
if num == 0 or m.match.lastindex and num <= m.match.lastindex:
return pre + m.match.group(num)
else:
return match.group(0)
return subgroup_re.sub(_repl, m.after)
2007-07-21 11:40:53 -04:00
def _set_prompt(m):
w = m.old_window
if m.p1 is None:
#w.application.mini_prompt = '%r was not found' % m.before
w.application.mini_prompt = '[%r] %r was not found' % (m.p1, m.before)
2007-07-21 11:40:53 -04:00
return
(x, y) = m.p1.xy()
count = 0
while y < len(w.buffer.lines):
count += w.buffer.lines[y][x:].count(m.before)
y += 1
x = 0
after = _get_after(m)
before = _get_before(m)
2007-07-21 11:40:53 -04:00
if count > 1:
p = 'Replace %r with %r [ynadq] (%d occurances)?' % (before, after, count)
elif count == 1:
p = 'Replace %r with %r [ynadq] (1 occurance)?' % (before, after)
elif count == 0:
p = 'Replace %r with %r [ynadq] (0 occurances)?' % (before, after)
#raise Exception("this can't happen")
else:
raise Exception("this REALLY can't happen")
2007-07-21 11:40:53 -04:00
w.application.mini_prompt = p
def _replace(m):
m.old_window.buffer.delete(m.p1, m.p2)
if m.after:
after = _get_after(m)
m.old_window.buffer.insert_string(m.p1, after)
2007-07-21 11:40:53 -04:00
def _finish(m, w):
if m.p1 is None:
_end(w)
w.set_error("Replace ended")
else:
_set_prompt(m)
def _end(w):
w.application.close_mini_buffer()
w.application.clear_highlighted_ranges('search')
2007-07-21 11:40:53 -04:00
w.buffer.method.old_cursor = None
w.buffer.method.old_window = None
assert not w.application.mini_active
2007-10-19 02:41:33 -04:00
class Replace(Fundamental):
name = 'Replace'
2008-04-18 23:32:08 -04:00
actions = [ReplaceAll, ReplaceDone, ReplaceOne, SkipReplace, CancelReplace]
def __init__(self, w):
Fundamental.__init__(self, w)
2008-04-18 23:32:08 -04:00
self.actions = {}
self.bindings = {}
self.add_bindings('replace-all', ('a', '!',))
self.add_bindings('replace-done', ('d',))
self.add_bindings('replace-one', ('y', 'SPACE',))
self.add_bindings('skip-replace', ('n', 'DELETE',))
2008-06-10 14:29:19 -04:00
self.add_bindings('cancel-replace', ('q', 'RETURN', 'C-]', 'C-n', 'C-p', 'C-a', 'C-e', 'C-f', 'C-b', 'C-g'))
2008-04-18 23:32:08 -04:00
m = w.buffer.method
found = _find_next(m, False)
if not found:
w.set_error('%r was not found' % m.before)
raise minibuffer.MiniBufferError
_set_prompt(m)
2007-10-19 02:41:33 -04:00
install = Replace.install