mirror of
https://github.com/AdaCore/cpython.git
synced 2026-02-12 12:57:15 -08:00
The test for re.engine was misfiring because re.engine is no longer
defined and the default was "pre" instead of "sre". Give up on 1.5.2
compatibility, hardcode the sre solution. However, this XXX comment
still applies, AFAIK:
# XXX This code depends on internals of the regular expression
# engine! There's no standard API to do a substitution when you
# have already found the match. One should be added.
182 lines
5.5 KiB
Python
182 lines
5.5 KiB
Python
import string
|
|
import os
|
|
import re
|
|
import fnmatch
|
|
from Tkinter import *
|
|
import tkMessageBox
|
|
import SearchEngine
|
|
from SearchDialogBase import SearchDialogBase
|
|
import sre_parse
|
|
|
|
def replace(text):
|
|
root = text._root()
|
|
engine = SearchEngine.get(root)
|
|
if not hasattr(engine, "_replacedialog"):
|
|
engine._replacedialog = ReplaceDialog(root, engine)
|
|
dialog = engine._replacedialog
|
|
dialog.open(text)
|
|
|
|
class ReplaceDialog(SearchDialogBase):
|
|
|
|
title = "Replace Dialog"
|
|
icon = "Replace"
|
|
|
|
def __init__(self, root, engine):
|
|
SearchDialogBase.__init__(self, root, engine)
|
|
self.replvar = StringVar(root)
|
|
|
|
def open(self, text):
|
|
SearchDialogBase.open(self, text)
|
|
try:
|
|
first = text.index("sel.first")
|
|
except TclError:
|
|
first = None
|
|
try:
|
|
last = text.index("sel.last")
|
|
except TclError:
|
|
last = None
|
|
first = first or text.index("insert")
|
|
last = last or first
|
|
self.show_hit(first, last)
|
|
self.ok = 1
|
|
|
|
def create_entries(self):
|
|
SearchDialogBase.create_entries(self)
|
|
self.replent = self.make_entry("Replace with:", self.replvar)
|
|
|
|
def create_command_buttons(self):
|
|
SearchDialogBase.create_command_buttons(self)
|
|
self.make_button("Find", self.find_it)
|
|
self.make_button("Replace", self.replace_it)
|
|
self.make_button("Replace+Find", self.default_command, 1)
|
|
self.make_button("Replace All", self.replace_all)
|
|
|
|
def find_it(self, event=None):
|
|
self.do_find(0)
|
|
|
|
def replace_it(self, event=None):
|
|
if self.do_find(self.ok):
|
|
self.do_replace()
|
|
|
|
def default_command(self, event=None):
|
|
if self.do_find(self.ok):
|
|
self.do_replace()
|
|
self.do_find(0)
|
|
|
|
def replace_all(self, event=None):
|
|
prog = self.engine.getprog()
|
|
if not prog:
|
|
return
|
|
repl = self.replvar.get()
|
|
text = self.text
|
|
res = self.engine.search_text(text, prog)
|
|
if not res:
|
|
text.bell()
|
|
return
|
|
text.tag_remove("sel", "1.0", "end")
|
|
text.tag_remove("hit", "1.0", "end")
|
|
line = res[0]
|
|
col = res[1].start()
|
|
if self.engine.iswrap():
|
|
line = 1
|
|
col = 0
|
|
ok = 1
|
|
first = last = None
|
|
# XXX ought to replace circular instead of top-to-bottom when wrapping
|
|
text.undo_block_start()
|
|
while 1:
|
|
res = self.engine.search_forward(text, prog, line, col, 0, ok)
|
|
if not res:
|
|
break
|
|
line, m = res
|
|
chars = text.get("%d.0" % line, "%d.0" % (line+1))
|
|
orig = m.group()
|
|
new = self._expand(m, repl)
|
|
i, j = m.span()
|
|
first = "%d.%d" % (line, i)
|
|
last = "%d.%d" % (line, j)
|
|
if new == orig:
|
|
text.mark_set("insert", last)
|
|
else:
|
|
text.mark_set("insert", first)
|
|
if first != last:
|
|
text.delete(first, last)
|
|
if new:
|
|
text.insert(first, new)
|
|
col = i + len(new)
|
|
ok = 0
|
|
text.undo_block_stop()
|
|
if first and last:
|
|
self.show_hit(first, last)
|
|
self.close()
|
|
|
|
def do_find(self, ok=0):
|
|
if not self.engine.getprog():
|
|
return 0
|
|
text = self.text
|
|
res = self.engine.search_text(text, None, ok)
|
|
if not res:
|
|
text.bell()
|
|
return 0
|
|
line, m = res
|
|
i, j = m.span()
|
|
first = "%d.%d" % (line, i)
|
|
last = "%d.%d" % (line, j)
|
|
self.show_hit(first, last)
|
|
self.ok = 1
|
|
return 1
|
|
|
|
def do_replace(self):
|
|
prog = self.engine.getprog()
|
|
if not prog:
|
|
return 0
|
|
text = self.text
|
|
try:
|
|
first = pos = text.index("sel.first")
|
|
last = text.index("sel.last")
|
|
except TclError:
|
|
pos = None
|
|
if not pos:
|
|
first = last = pos = text.index("insert")
|
|
line, col = SearchEngine.get_line_col(pos)
|
|
chars = text.get("%d.0" % line, "%d.0" % (line+1))
|
|
m = prog.match(chars, col)
|
|
if not prog:
|
|
return 0
|
|
new = self._expand(m, self.replvar.get())
|
|
text.mark_set("insert", first)
|
|
text.undo_block_start()
|
|
if m.group():
|
|
text.delete(first, last)
|
|
if new:
|
|
text.insert(first, new)
|
|
text.undo_block_stop()
|
|
self.show_hit(first, text.index("insert"))
|
|
self.ok = 0
|
|
return 1
|
|
|
|
def _expand(self, m, template):
|
|
# XXX This code depends on internals of the regular expression
|
|
# engine! There's no standard API to do a substitution when you
|
|
# have already found the match. One should be added.
|
|
# XXX This parses the template over and over...
|
|
ptemplate = sre_parse.parse_template(template, m.re)
|
|
return sre_parse.expand_template(ptemplate, m)
|
|
|
|
def show_hit(self, first, last):
|
|
text = self.text
|
|
text.mark_set("insert", first)
|
|
text.tag_remove("sel", "1.0", "end")
|
|
text.tag_add("sel", first, last)
|
|
text.tag_remove("hit", "1.0", "end")
|
|
if first == last:
|
|
text.tag_add("hit", first)
|
|
else:
|
|
text.tag_add("hit", first, last)
|
|
text.see("insert")
|
|
text.update_idletasks()
|
|
|
|
def close(self, event=None):
|
|
SearchDialogBase.close(self, event)
|
|
self.text.tag_remove("hit", "1.0", "end")
|