Commit 8c95c27c authored by Guido van Rossum's avatar Guido van Rossum

Added a new command: Check module (Alt-F5) It does a full syntax check

of the current module.  It also runs the tabnanny to catch any
inconsistent tabs.

Also did a little bit of refactoring: added an errorbox() method to
simplify the display of error dialogs.
parent 772dd417
"""Extension to execute code outside the Python shell window.
This adds two commands (to the Edit menu, until there's a separate
Python menu):
This adds the following commands (to the Edit menu, until there's a
separate Python menu):
- Check module (Alt-F5) does a full syntax check of the current module.
It also runs the tabnanny to catch any inconsistent tabs.
- Import module (F5) is equivalent to either import or reload of the
current module. The window must have been saved previously. The
......@@ -18,16 +21,29 @@ import os
import imp
import tkMessageBox
indent_message = """Error: Inconsistent indentation detected!
This means that either:
(1) your indentation is outright incorrect (easy to fix), or
(2) your indentation mixes tabs and spaces in a way that depends on \
how many spaces a tab is worth.
To fix case 2, change all tabs to spaces by using Select All followed \
by Untabify Region (both in the Edit menu)."""
class ScriptBinding:
keydefs = {
'<<check-module>>': ['<Alt-F5>', '<Meta-F5>'],
'<<import-module>>': ['<F5>'],
'<<run-script>>': ['<Control-F5>'],
}
menudefs = [
('edit', [None,
('Check module', '<<check-module>>'),
('Import module', '<<import-module>>'),
('Run script', '<<run-script>>'),
]
......@@ -41,6 +57,59 @@ class ScriptBinding:
self.flist = self.editwin.flist
self.root = self.flist.root
def check_module_event(self, event):
filename = self.getfilename()
if not filename:
return
if not self.tabnanny(filename):
return
if not self.checksyntax(filename):
return
def tabnanny(self, filename):
import tabnanny
import tokenize
tabnanny.reset_globals()
f = open(filename, 'r')
try:
tokenize.tokenize(f.readline, tabnanny.tokeneater)
except tokenize.TokenError, msg:
self.errorbox("Token error",
"Token error:\n%s" % str(msg))
return 0
except tabnanny.NannyNag, nag:
# The error messages from tabnanny are too confusing...
self.editwin.gotoline(nag.get_lineno())
self.errorbox("Tab/space error", indent_message)
return 0
return 1
def checksyntax(self, filename):
f = open(filename, 'r')
source = f.read()
f.close()
if '\r' in source:
import re
source = re.sub(r"\r\n", "\n", source)
if source and source[-1] != '\n':
source = source + '\n'
try:
compile(source, filename, "exec")
except (SyntaxError, OverflowError), err:
try:
msg, (errorfilename, lineno, offset, line) = err
if not errorfilename:
err.args = msg, (filename, lineno, offset, line)
err.filename = filename
except:
lineno = None
msg = "*** " + str(err)
if lineno:
self.editwin.gotoline(lineno)
self.errorbox("Syntax error",
"There's an error in your program:\n" + msg)
return 1
def import_module_event(self, event):
filename = self.getfilename()
if not filename:
......@@ -75,22 +144,26 @@ class ScriptBinding:
interp = shell.interp
if (not sys.argv or
os.path.basename(sys.argv[0]) != os.path.basename(filename)):
# XXX Too often this discards arguments the user just set...
sys.argv = [filename]
interp.execfile(filename)
def getfilename(self):
# Logic to make sure we have a saved filename
# XXX Better logic would offer to save!
if not self.editwin.get_saved():
tkMessageBox.showerror("Not saved",
"Please save first!",
master=self.editwin.text)
self.errorbox("Not saved",
"Please save first!")
self.editwin.text.focus_set()
return
filename = self.editwin.io.filename
if not filename:
tkMessageBox.showerror("No file name",
"This window has no file name",
master=self.editwin.text)
self.editwin.text.focus_set()
self.errorbox("No file name",
"This window has no file name")
return
return filename
def errorbox(self, title, message):
# XXX This should really be a function of EditorWindow...
tkMessageBox.showerror(title, message, master=self.editwin.text)
self.editwin.text.focus_set()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment