8 from SearchDialogBase
import SearchDialogBase
12 engine
= SearchEngine
.get(root
)
13 if not hasattr(engine
, "_replacedialog"):
14 engine
._replacedialog
= ReplaceDialog(root
, engine
)
15 dialog
= engine
._replacedialog
18 class ReplaceDialog(SearchDialogBase
):
20 title
= "Replace Dialog"
23 def __init__(self
, root
, engine
):
24 SearchDialogBase
.__init
__(self
, root
, engine
)
25 self
.replvar
= StringVar(root
)
28 SearchDialogBase
.open(self
, text
)
30 first
= text
.index("sel.first")
34 last
= text
.index("sel.last")
37 first
= first
or text
.index("insert")
39 self
.show_hit(first
, last
)
42 def create_entries(self
):
43 SearchDialogBase
.create_entries(self
)
44 self
.replent
= self
.make_entry("Replace with:", self
.replvar
)
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
)
53 def find_it(self
, event
=None):
56 def replace_it(self
, event
=None):
57 if self
.do_find(self
.ok
):
60 def default_command(self
, event
=None):
61 if self
.do_find(self
.ok
):
65 def replace_all(self
, event
=None):
66 prog
= self
.engine
.getprog()
69 repl
= self
.replvar
.get()
71 res
= self
.engine
.search_text(text
, prog
)
75 text
.tag_remove("sel", "1.0", "end")
76 text
.tag_remove("hit", "1.0", "end")
79 if self
.engine
.iswrap():
84 # XXX ought to replace circular instead of top-to-bottom when wrapping
85 text
.undo_block_start()
87 res
= self
.engine
.search_forward(text
, prog
, line
, col
, 0, ok
)
91 chars
= text
.get("%d.0" % line
, "%d.0" % (line
+1))
93 new
= self
._expand
(m
, repl
)
95 first
= "%d.%d" % (line
, i
)
96 last
= "%d.%d" % (line
, j
)
98 text
.mark_set("insert", last
)
100 text
.mark_set("insert", first
)
102 text
.delete(first
, last
)
104 text
.insert(first
, new
)
107 text
.undo_block_stop()
109 self
.show_hit(first
, last
)
112 def do_find(self
, ok
=0):
113 if not self
.engine
.getprog():
116 res
= self
.engine
.search_text(text
, None, ok
)
122 first
= "%d.%d" % (line
, i
)
123 last
= "%d.%d" % (line
, j
)
124 self
.show_hit(first
, last
)
128 def do_replace(self
):
129 prog
= self
.engine
.getprog()
134 first
= pos
= text
.index("sel.first")
135 last
= text
.index("sel.last")
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
)
145 new
= self
._expand
(m
, self
.replvar
.get())
146 text
.mark_set("insert", first
)
147 text
.undo_block_start()
149 text
.delete(first
, last
)
151 text
.insert(first
, new
)
152 text
.undo_block_stop()
153 self
.show_hit(first
, text
.index("insert"))
157 def _expand(self
, m
, template
):
158 # XXX This code depends on internals of the regular expression
159 # engine! There's no standard API to do a substitution when you
160 # have already found the match. One should be added.
161 # The solution here is designed to be backwards compatible
162 # with previous Python versions, e.g. 1.5.2.
163 # XXX This dynamic test should be done only once.
164 if getattr(re
, "engine", "pre") == "pre":
165 return re
.pcre_expand(m
, template
)
167 # XXX This import should be avoidable...
169 # XXX This parses the template over and over...
170 ptemplate
= sre_parse
.parse_template(template
, m
.re
)
171 return sre_parse
.expand_template(ptemplate
, m
)
173 def show_hit(self
, first
, last
):
175 text
.mark_set("insert", first
)
176 text
.tag_remove("sel", "1.0", "end")
177 text
.tag_add("sel", first
, last
)
178 text
.tag_remove("hit", "1.0", "end")
180 text
.tag_add("hit", first
)
182 text
.tag_add("hit", first
, last
)
184 text
.update_idletasks()
186 def close(self
, event
=None):
187 SearchDialogBase
.close(self
, event
)
188 self
.text
.tag_remove("hit", "1.0", "end")