| import string |
| import os |
| import re |
| import fnmatch |
| from Tkinter import * |
| import tkMessageBox |
| import SearchEngine |
| from SearchDialogBase import SearchDialogBase |
| |
| 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 = re.pcre_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 = re.pcre_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 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") |