9 from IdleConf
import idleconf
11 #$ event <<open-window-from-file>>
13 #$ unix <Control-x><Control-f>
15 #$ event <<save-window>>
17 #$ unix <Control-x><Control-s>
19 #$ event <<save-window-as-file>>
21 #$ unix <Control-x><Control-w>
23 #$ event <<save-copy-of-window-as-file>>
25 #$ unix <Control-x><w>
27 #$ event <<print-window>>
29 #$ unix <Control-x><Control-p>
32 from codecs
import BOM_UTF8
34 # only available since Python 2.3
35 BOM_UTF8
= '\xef\xbb\xbf'
37 # Try setting the locale, so that we can find out
38 # what encoding to use
41 locale
.setlocale(locale
.LC_CTYPE
, "")
46 if sys
.platform
== 'win32':
47 # On Windows, we could use "mbcs". However, to give the user
48 # a portable encoding name, we need to find the code page
50 encoding
= locale
.getdefaultlocale()[1]
51 codecs
.lookup(encoding
)
56 # Different things can fail here: the locale module may not be
57 # loaded, it may not offer nl_langinfo, or CODESET, or the
58 # resulting codeset may be unknown to Python. We ignore all
59 # these problems, falling back to ASCII
60 encoding
= locale
.nl_langinfo(locale
.CODESET
)
61 codecs
.lookup(encoding
)
62 except (NameError, AttributeError, LookupError):
63 # Try getdefaultlocale well: it parses environment variables,
64 # which may give a clue. Unfortunately, getdefaultlocale has
65 # bugs that can cause ValueError.
67 encoding
= locale
.getdefaultlocale()[1]
68 codecs
.lookup(encoding
)
69 except (ValueError, LookupError):
72 encoding
= encoding
.lower()
74 coding_re
= re
.compile("coding[:=]\s*([-\w_.]+)")
77 """Return the encoding declaration according to PEP 263.
78 Raise LookupError if the encoding is declared but unknown."""
80 # Only consider the first two lines
81 str = str.split("\n")[:2]
84 match
= coding_re
.search(str)
88 # Check whether the encoding is known
93 # The standard encoding error does not indicate the encoding
94 raise LookupError, "Unknown encoding "+name
99 def __init__(self
, editwin
):
100 self
.editwin
= editwin
101 self
.text
= editwin
.text
102 self
.__id
_open
= self
.text
.bind("<<open-window-from-file>>", self
.open)
103 self
.__id
_save
= self
.text
.bind("<<save-window>>", self
.save
)
104 self
.__id
_saveas
= self
.text
.bind("<<save-window-as-file>>",
106 self
.__id
_savecopy
= self
.text
.bind("<<save-copy-of-window-as-file>>",
108 self
.__id
_print
= self
.text
.bind("<<print-window>>", self
.print_window
)
109 self
.fileencoding
= None
112 # Undo command bindings
113 self
.text
.unbind("<<open-window-from-file>>", self
.__id
_open
)
114 self
.text
.unbind("<<save-window>>", self
.__id
_save
)
115 self
.text
.unbind("<<save-window-as-file>>",self
.__id
_saveas
)
116 self
.text
.unbind("<<save-copy-of-window-as-file>>", self
.__id
_savecopy
)
117 self
.text
.unbind("<<print-window>>", self
.__id
_print
)
121 self
.filename_change_hook
= None
124 return self
.editwin
.get_saved()
126 def set_saved(self
, flag
):
127 self
.editwin
.set_saved(flag
)
129 def reset_undo(self
):
130 self
.editwin
.reset_undo()
132 filename_change_hook
= None
134 def set_filename_change_hook(self
, hook
):
135 self
.filename_change_hook
= hook
139 def set_filename(self
, filename
):
140 self
.filename
= filename
142 if self
.filename_change_hook
:
143 self
.filename_change_hook()
145 def open(self
, event
):
146 if self
.editwin
.flist
:
147 filename
= self
.askopenfile()
149 self
.editwin
.flist
.open(filename
)
151 self
.text
.focus_set()
153 # Code for use outside IDLE:
155 reply
= self
.maybesave()
156 if reply
== "cancel":
157 self
.text
.focus_set()
159 filename
= self
.askopenfile()
161 self
.loadfile(filename
)
163 self
.text
.focus_set()
166 def loadfile(self
, filename
):
172 tkMessageBox
.showerror("I/O Error", str(msg
), master
=self
.text
)
175 chars
= self
.decode(chars
)
177 self
.text
.delete("1.0", "end")
178 self
.set_filename(None)
179 self
.text
.insert("1.0", chars
)
181 self
.set_filename(filename
)
182 self
.text
.mark_set("insert", "1.0")
183 self
.text
.see("insert")
186 def decode(self
, chars
):
187 # Try to create a Unicode string. If that fails, let Tcl try
190 # Check presence of a UTF-8 signature first
191 if chars
.startswith(BOM_UTF8
):
193 chars
= chars
[3:].decode("utf-8")
195 # has UTF-8 signature, but fails to decode...
198 # Indicates that this file originally had a BOM
199 self
.fileencoding
= BOM_UTF8
202 # Next look for coding specification
204 enc
= coding_spec(chars
)
205 except LookupError, name
:
206 tkMessageBox
.showerror(
207 title
="Error loading the file",
208 message
="The encoding '%s' is not known to this Python "\
209 "installation. The file may not display correctly" % name
,
215 return unicode(chars
, enc
)
219 # If it is ASCII, we need not to record anything
221 return unicode(chars
, 'ascii')
225 # Finally, try the locale's encoding. This is deprecated;
226 # the user should declare a non-ASCII encoding
228 chars
= unicode(chars
, encoding
)
229 self
.fileencoding
= encoding
237 message
= "Do you want to save %s before closing?" % (
238 self
.filename
or "this untitled document")
239 m
= tkMessageBox
.Message(
240 title
="Save On Close",
242 icon
=tkMessageBox
.QUESTION
,
243 type=tkMessageBox
.YESNOCANCEL
,
248 if not self
.get_saved():
250 self
.text
.focus_set()
253 def save(self
, event
):
254 if not self
.filename
:
257 if self
.writefile(self
.filename
):
259 self
.text
.focus_set()
262 def save_as(self
, event
):
263 filename
= self
.asksavefile()
265 if self
.writefile(filename
):
266 self
.set_filename(filename
)
268 self
.text
.focus_set()
271 def save_a_copy(self
, event
):
272 filename
= self
.asksavefile()
274 self
.writefile(filename
)
275 self
.text
.focus_set()
278 def print_window(self
, event
):
280 filename
= self
.filename
282 (tfd
, tfn
) = tempfile
.mkstemp()
285 if not self
.writefile(filename
):
288 edconf
= idleconf
.getsection('EditorWindow')
289 command
= edconf
.get('print-command')
290 command
= command
% filename
291 if os
.name
== 'posix':
292 command
= command
+ " 2>&1"
293 pipe
= os
.popen(command
, "r")
294 output
= pipe
.read().strip()
295 status
= pipe
.close()
297 output
= "Printing failed (exit status 0x%x)\n" % status
+ output
299 output
= "Printing command: %s\n" % repr(command
) + output
300 tkMessageBox
.showerror("Print status", output
, master
=self
.text
)
303 def writefile(self
, filename
):
305 chars
= self
.encode(self
.text
.get("1.0", "end-1c"))
307 f
= open(filename
, "w")
310 ## print "saved to", `filename`
313 tkMessageBox
.showerror("I/O Error", str(msg
),
317 def encode(self
, chars
):
318 if isinstance(chars
, types
.StringType
):
319 # This is either plain ASCII, or Tk was returning mixed-encoding
320 # text to us. Don't try to guess further.
323 # See whether there is anything non-ASCII in it.
324 # If not, no need to figure out the encoding.
326 return chars
.encode('ascii')
330 # If there is an encoding declared, try this first.
332 enc
= coding_spec(chars
)
334 except LookupError, msg
:
339 return chars
.encode(enc
)
341 failed
= "Invalid encoding '%s'" % enc
344 tkMessageBox
.showerror(
346 "%s. Saving as UTF-8" % failed
,
349 # If there was a UTF-8 signature, use that. This should not fail
350 if self
.fileencoding
== BOM_UTF8
or failed
:
351 return BOM_UTF8
+ chars
.encode("utf-8")
353 # Try the original file encoding next, if any
354 if self
.fileencoding
:
356 return chars
.encode(self
.fileencoding
)
358 tkMessageBox
.showerror(
360 "Cannot save this as '%s' anymore. Saving as UTF-8" % self
.fileencoding
,
362 return BOM_UTF8
+ chars
.encode("utf-8")
364 # Nothing was declared, and we had not determined an encoding
365 # on loading. Recommend an encoding line.
367 chars
= chars
.encode(encoding
)
370 chars
= BOM_UTF8
+ chars
.encode("utf-8")
372 tkMessageBox
.showerror(
374 "Non-ASCII found, yet no encoding declared. Add a line like\n"
375 "# -*- coding: %s -*- \nto your file" % enc
,
379 def fixlastline(self
):
380 c
= self
.text
.get("end-2c")
382 self
.text
.insert("end-1c", "\n")
388 ("Python and text files", "*.py *.pyw *.txt", "TEXT"),
389 ("All text files", "*", "TEXT"),
393 def askopenfile(self
):
394 dir, base
= self
.defaultfilename("open")
395 if not self
.opendialog
:
396 self
.opendialog
= tkFileDialog
.Open(master
=self
.text
,
397 filetypes
=self
.filetypes
)
398 return self
.opendialog
.show(initialdir
=dir, initialfile
=base
)
400 def defaultfilename(self
, mode
="open"):
402 return os
.path
.split(self
.filename
)
410 def asksavefile(self
):
411 dir, base
= self
.defaultfilename("save")
412 if not self
.savedialog
:
413 self
.savedialog
= tkFileDialog
.SaveAs(master
=self
.text
,
414 filetypes
=self
.filetypes
)
415 return self
.savedialog
.show(initialdir
=dir, initialfile
=base
)
421 def __init__(self
, text
):
424 self
.text
.bind("<Control-o>", self
.open)
425 self
.text
.bind("<Control-s>", self
.save
)
426 self
.text
.bind("<Alt-s>", self
.save_as
)
427 self
.text
.bind("<Alt-z>", self
.save_a_copy
)
428 def get_saved(self
): return 0
429 def set_saved(self
, flag
): pass
430 def reset_undo(self
): pass
431 def open(self
, event
):
432 self
.text
.event_generate("<<open-window-from-file>>")
433 def save(self
, event
):
434 self
.text
.event_generate("<<save-window>>")
435 def save_as(self
, event
):
436 self
.text
.event_generate("<<save-window-as-file>>")
437 def save_a_copy(self
, event
):
438 self
.text
.event_generate("<<save-copy-of-window-as-file>>")
442 editwin
= MyEditWin(text
)
443 io
= IOBinding(editwin
)
446 if __name__
== "__main__":
447 from Tkinter
import *