blob: e29d4d6f0b4c279acc19311893eaff65ffc938c9 [file] [log] [blame]
Guido van Rossum504b0bf1999-01-02 21:28:54 +00001import string
2import os
3import re
4import fnmatch
5from Tkinter import *
6import tkMessageBox
7import SearchEngine
8from SearchDialogBase import SearchDialogBase
9
10def replace(text):
11 root = text._root()
12 engine = SearchEngine.get(root)
13 if not hasattr(engine, "_replacedialog"):
14 engine._replacedialog = ReplaceDialog(root, engine)
15 dialog = engine._replacedialog
16 dialog.open(text)
17
18class ReplaceDialog(SearchDialogBase):
19
20 title = "Replace Dialog"
21 icon = "Replace"
22
23 def __init__(self, root, engine):
24 SearchDialogBase.__init__(self, root, engine)
25 self.replvar = StringVar(root)
26
27 def open(self, text):
28 SearchDialogBase.open(self, text)
29 try:
30 first = text.index("sel.first")
31 except TclError:
32 first = None
33 try:
34 last = text.index("sel.last")
35 except TclError:
36 last = None
37 first = first or text.index("insert")
38 last = last or first
39 self.show_hit(first, last)
40 self.ok = 1
41
42 def create_entries(self):
43 SearchDialogBase.create_entries(self)
44 self.replent = self.make_entry("Replace with:", self.replvar)
45
46 def create_command_buttons(self):
47 SearchDialogBase.create_command_buttons(self)
48 self.make_button("Find", self.find_it)
49 self.make_button("Replace", self.replace_it)
50 self.make_button("Replace+Find", self.default_command, 1)
51 self.make_button("Replace All", self.replace_all)
52
53 def find_it(self, event=None):
54 self.do_find(0)
55
56 def replace_it(self, event=None):
57 if self.do_find(self.ok):
58 self.do_replace()
59
60 def default_command(self, event=None):
61 if self.do_find(self.ok):
62 self.do_replace()
63 self.do_find(0)
64
65 def replace_all(self, event=None):
66 prog = self.engine.getprog()
67 if not prog:
68 return
69 repl = self.replvar.get()
70 text = self.text
71 res = self.engine.search_text(text, prog)
72 if not res:
73 text.bell()
74 return
75 text.tag_remove("sel", "1.0", "end")
76 text.tag_remove("hit", "1.0", "end")
77 line = res[0]
78 col = res[1].start()
79 if self.engine.iswrap():
80 line = 1
81 col = 0
82 ok = 1
83 first = last = None
84 # XXX ought to replace circular instead of top-to-bottom when wrapping
Guido van Rossumab6a08a1999-06-08 13:06:07 +000085 text.undo_block_start()
Guido van Rossum504b0bf1999-01-02 21:28:54 +000086 while 1:
87 res = self.engine.search_forward(text, prog, line, col, 0, ok)
88 if not res:
89 break
90 line, m = res
91 chars = text.get("%d.0" % line, "%d.0" % (line+1))
92 orig = m.group()
93 new = re.pcre_expand(m, repl)
94 i, j = m.span()
95 first = "%d.%d" % (line, i)
96 last = "%d.%d" % (line, j)
97 if new == orig:
98 text.mark_set("insert", last)
99 else:
100 text.mark_set("insert", first)
101 if first != last:
102 text.delete(first, last)
103 if new:
104 text.insert(first, new)
105 col = i + len(new)
106 ok = 0
Guido van Rossumab6a08a1999-06-08 13:06:07 +0000107 text.undo_block_stop()
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000108 if first and last:
109 self.show_hit(first, last)
110 self.close()
111
112 def do_find(self, ok=0):
113 if not self.engine.getprog():
114 return 0
115 text = self.text
116 res = self.engine.search_text(text, None, ok)
117 if not res:
118 text.bell()
119 return 0
120 line, m = res
121 i, j = m.span()
122 first = "%d.%d" % (line, i)
123 last = "%d.%d" % (line, j)
124 self.show_hit(first, last)
125 self.ok = 1
126 return 1
127
128 def do_replace(self):
129 prog = self.engine.getprog()
130 if not prog:
131 return 0
132 text = self.text
133 try:
134 first = pos = text.index("sel.first")
135 last = text.index("sel.last")
136 except TclError:
137 pos = None
138 if not pos:
139 first = last = pos = text.index("insert")
140 line, col = SearchEngine.get_line_col(pos)
141 chars = text.get("%d.0" % line, "%d.0" % (line+1))
142 m = prog.match(chars, col)
143 if not prog:
144 return 0
145 new = re.pcre_expand(m, self.replvar.get())
146 text.mark_set("insert", first)
Guido van Rossum9745f5a1999-06-08 12:54:56 +0000147 text.undo_block_start()
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000148 if m.group():
149 text.delete(first, last)
150 if new:
151 text.insert(first, new)
Guido van Rossum9745f5a1999-06-08 12:54:56 +0000152 text.undo_block_stop()
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000153 self.show_hit(first, text.index("insert"))
154 self.ok = 0
155 return 1
156
157 def show_hit(self, first, last):
158 text = self.text
159 text.mark_set("insert", first)
160 text.tag_remove("sel", "1.0", "end")
161 text.tag_add("sel", first, last)
162 text.tag_remove("hit", "1.0", "end")
163 if first == last:
164 text.tag_add("hit", first)
165 else:
166 text.tag_add("hit", first, last)
167 text.see("insert")
168 text.update_idletasks()
169
170 def close(self, event=None):
171 SearchDialogBase.close(self, event)
172 self.text.tag_remove("hit", "1.0", "end")