blob: a17354d4b2c15534fcda0fcdc8b3529d3027e7d7 [file] [log] [blame]
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +00001import sys
2import os
3import string
4from Tkinter import *
Guido van Rossum2aeeb551998-10-12 21:01:37 +00005import tkMessageBox
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +00006
Guido van Rossum2aeeb551998-10-12 21:01:37 +00007about_title = "About IDLE"
8about_text = """\
9IDLE 0.1
10
11A not totally unintegrated development environment for Python
12
13by Guido van Rossum
14"""
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +000015
16class EditorWindow:
17
18 from Percolator import Percolator
19 from ColorDelegator import ColorDelegator
20 from UndoDelegator import UndoDelegator
21 from IOBinding import IOBinding
22 from SearchBinding import SearchBinding
23 from AutoIndent import AutoIndent
24 from AutoExpand import AutoExpand
25 import Bindings
Guido van Rossum2aeeb551998-10-12 21:01:37 +000026
27 about_title = about_title
28 about_text = about_text
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +000029
30 def __init__(self, root, filename=None):
Guido van Rossum2aeeb551998-10-12 21:01:37 +000031 self.root = root
32 self.menubar = Menu(root)
33 self.top = top = Toplevel(root, menu=self.menubar)
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +000034 self.vbar = vbar = Scrollbar(top, name='vbar')
35 self.text = text = Text(top, name='text')
36
Guido van Rossum2aeeb551998-10-12 21:01:37 +000037 self.createmenubar()
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +000038 self.Bindings.apply_bindings(text)
39
40 self.top.protocol("WM_DELETE_WINDOW", self.close)
41 self.top.bind("<<close-window>>", self.close_event)
42 self.text.bind("<<center-insert>>", self.center_insert_event)
43
44 vbar['command'] = text.yview
45 vbar.pack(side=RIGHT, fill=Y)
46
47 text['yscrollcommand'] = vbar.set
48 text['background'] = 'white'
49 if sys.platform[:3] == 'win':
50 text['font'] = ("lucida console", 8)
51 text.pack(side=LEFT, fill=BOTH, expand=1)
52 text.focus_set()
53
54 self.auto = auto = self.AutoIndent(text)
55 self.autoex = self.AutoExpand(text)
56 self.per = per = self.Percolator(text)
57 if self.ispythonsource(filename):
58 self.color = color = self.ColorDelegator(); per.insertfilter(color)
59 ##print "Initial colorizer"
60 else:
61 ##print "No initial colorizer"
62 self.color = None
63 self.undo = undo = self.UndoDelegator(); per.insertfilter(undo)
64 self.search = search = self.SearchBinding(undo)
65 self.io = io = self.IOBinding(undo)
66
67 undo.set_saved_change_hook(self.saved_change_hook)
68 io.set_filename_change_hook(self.filename_change_hook)
69
70 if filename:
71 if os.path.exists(filename):
72 io.loadfile(filename)
73 else:
74 io.set_filename(filename)
75
76 self.saved_change_hook()
77
Guido van Rossum2aeeb551998-10-12 21:01:37 +000078 def createmenubar(self):
79 mbar = self.menubar
80
81 self.filemenu = Menu(mbar)
82
83 self.editmenu = Menu(mbar)
84
85 self.helpmenu = Menu(mbar, name="help")
86 self.helpmenu.add_command(label="Help...", command=self.help_dialog)
87 self.helpmenu.add_separator()
88 self.helpmenu.add_command(label="About...", command=self.about_dialog)
89
90 mbar.add_cascade(label="File", menu=self.filemenu)
91 mbar.add_cascade(label="Edit", menu=self.editmenu)
92 mbar.add_cascade(label="Help", menu=self.helpmenu)
93
94 dict = {"file": self.filemenu,
95 "edit": self.editmenu,
96 "help": self.helpmenu}
97 self.Bindings.fill_menus(self.text, dict)
98
99 def about_dialog(self):
100 tkMessageBox.showinfo(self.about_title, self.about_text,
101 master=self.text)
102
103 def help_dialog(self):
104 from HelpWindow import HelpWindow
105 HelpWindow(root=self.root)
106
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +0000107 def gotoline(self, lineno):
108 if lineno is not None and lineno > 0:
109 self.text.mark_set("insert", "%d.0" % lineno)
110 self.text.tag_remove("sel", "1.0", "end")
111 self.text.tag_add("sel", "insert", "insert +1l")
112 self.center()
113
114 def ispythonsource(self, filename):
115 if not filename:
116 return 1
117 if os.path.normcase(filename[-3:]) == ".py":
118 return 1
119 try:
120 f = open(filename)
121 line = f.readline()
122 f.close()
123 except IOError:
124 return 0
125 return line[:2] == '#!' and string.find(line, 'python') >= 0
126
127 close_hook = None
128
129 def set_close_hook(self, close_hook):
130 self.close_hook = close_hook
131
132 def filename_change_hook(self):
133 self.saved_change_hook()
134 if self.ispythonsource(self.io.filename):
135 self.addcolorizer()
136 else:
137 self.rmcolorizer()
138
139 def addcolorizer(self):
140 if self.color:
141 return
142 ##print "Add colorizer"
143 self.per.removefilter(self.undo)
144 self.color = self.ColorDelegator()
145 self.per.insertfilter(self.color)
146 self.per.insertfilter(self.undo)
147
148 def rmcolorizer(self):
149 if not self.color:
150 return
151 ##print "Remove colorizer"
152 self.per.removefilter(self.undo)
153 self.per.removefilter(self.color)
154 self.color = None
155 self.per.insertfilter(self.undo)
156
157 def saved_change_hook(self):
158 if self.io.filename:
159 title = self.io.filename
160 else:
161 title = "(Untitled)"
162 if not self.undo.get_saved():
163 title = title + " *"
164 self.top.wm_title(title)
165
166 def center_insert_event(self, event):
167 self.center()
168
169 def center(self, mark="insert"):
170 insert = float(self.text.index(mark + " linestart"))
171 end = float(self.text.index("end"))
172 if insert > end-insert:
173 self.text.see("1.0")
174 else:
175 self.text.see("end")
176 self.text.see(mark)
177
178 def close_event(self, event):
179 self.close()
180
181 def close(self):
182 self.top.wm_deiconify()
183 self.top.tkraise()
184 reply = self.io.maybesave()
185 if reply != "cancel":
186 if self.color and self.color.colorizing:
187 self.color.close()
188 self.top.bell()
189 return "cancel"
190 if self.close_hook:
191 self.close_hook()
192 if self.color:
193 self.color.close() # Cancel colorization
194 self.top.destroy()
195 return reply
196
197
198def fixwordbreaks(root):
199 tk = root.tk
200 tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded
201 tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]')
202 tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]')
203
204
205def test():
206 root = Tk()
207 fixwordbreaks(root)
208 root.withdraw()
209 if sys.argv[1:]:
210 filename = sys.argv[1]
211 else:
212 filename = None
213 edit = EditorWindow(root, filename)
214 edit.set_close_hook(root.quit)
215 root.mainloop()
216 root.destroy()
217
218if __name__ == '__main__':
219 test()