summaryrefslogtreecommitdiffstats
path: root/Demo/tkinter/guido/regexdemo.py
blob: 89c9ee5576be7262de62eef8c1dbfcf164d1f65e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""Basic regular expression demostration facility.

This displays a window with two type-in boxes.  In the top box, you enter a 
regular expression.  In the bottom box, you enter a string.  The first 
match in the string of the regular expression is highlighted with a yellow 
background (or red if the match is empty -- then the character at the match 
is highlighted).  The highlighting is continuously updated.  At the bottom 
are a number of checkboxes which control the regular expression syntax used 
(see the regex_syntax module for descriptions).  When there's no match, or 
when the regular expression is syntactically incorrect, an error message is
displayed.

"""

from Tkinter import *
import regex
import regex_syntax

class RegexDemo:
	
	def __init__(self, master):
		self.master = master
		self.topframe = Frame(self.master)
		self.topframe.pack(fill=X)
		self.promptdisplay = Label(self.topframe, text="Enter a string:")
		self.promptdisplay.pack(side=LEFT)
		self.statusdisplay = Label(self.topframe, text="", anchor=W)
		self.statusdisplay.pack(side=LEFT, fill=X)
		self.regexdisplay = Entry(self.master)
		self.regexdisplay.pack(fill=X)
		self.regexdisplay.focus_set()
		self.labeldisplay = Label(self.master, anchor=W,
			text="Enter a string:")
		self.labeldisplay.pack(fill=X)
		self.labeldisplay.pack(fill=X)
		self.stringdisplay = Text(self.master, width=60, height=4)
		self.stringdisplay.pack(fill=BOTH, expand=1)
		self.stringdisplay.tag_configure("hit", background="yellow")
		self.addoptions()
		self.regexdisplay.bind('<Key>', self.recompile)
		self.stringdisplay.bind('<Key>', self.reevaluate)
		self.compiled = None
		self.recompile()
		btags = self.regexdisplay.bindtags()
		self.regexdisplay.bindtags(btags[1:] + btags[:1])
		btags = self.stringdisplay.bindtags()
		self.stringdisplay.bindtags(btags[1:] + btags[:1])
	
	def addoptions(self):
		self.frames = []
		self.boxes = []
		self.vars = []
		for name in (	'RE_NO_BK_PARENS',
				'RE_NO_BK_VBAR',
				'RE_BK_PLUS_QM',
				'RE_TIGHT_VBAR',
				'RE_NEWLINE_OR',
				'RE_CONTEXT_INDEP_OPS'):
			if len(self.boxes) % 3 == 0:
				frame = Frame(self.master)
				frame.pack(fill=X)
				self.frames.append(frame)
			val = getattr(regex_syntax, name)
			var = IntVar()
			box = Checkbutton(frame,
				variable=var, text=name,
				offvalue=0, onvalue=val,
				command=self.newsyntax)
			box.pack(side=LEFT)
			self.boxes.append(box)
			self.vars.append(var)
	
	def newsyntax(self):
		syntax = 0
		for var in self.vars:
			syntax = syntax | var.get()
		regex.set_syntax(syntax)
		self.recompile()
	
	def recompile(self, event=None):
		try:
			self.compiled = regex.compile(self.regexdisplay.get())
			self.statusdisplay.config(text="")
		except regex.error, msg:
			self.compiled = None
			self.statusdisplay.config(text="regex.error: %s" % str(msg))
		self.reevaluate()
	
	def reevaluate(self, event=None):
		try:
			self.stringdisplay.tag_remove("hit", "1.0", END)
		except TclError:
			pass
		if not self.compiled:
			return
		text = self.stringdisplay.get("1.0", END)
		i = self.compiled.search(text)
		if i < 0:
			self.statusdisplay.config(text="(no match)")
		else:
			self.statusdisplay.config(text="")
			regs = self.compiled.regs
			first, last = regs[0]
			if last == first:
				last = first+1
				self.stringdisplay.tag_configure("hit",
					background="red")
			else:
				self.stringdisplay.tag_configure("hit",
					background="yellow")
			pfirst = "1.0 + %d chars" % first
			plast = "1.0 + %d chars" % last
			self.stringdisplay.tag_add("hit", pfirst, plast)
			self.stringdisplay.yview_pickplace(pfirst)



# Main function, run when invoked as a stand-alone Python program.

def main():
    root = Tk()
    demo = RegexDemo(root)
    root.protocol('WM_DELETE_WINDOW', root.quit)
    root.mainloop()

if __name__ == '__main__':
    main()