aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/idlelib/EditorWindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib/EditorWindow.py')
-rw-r--r--Lib/idlelib/EditorWindow.py147
1 files changed, 77 insertions, 70 deletions
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 0a01c9ec305..16f63c52a40 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -1,10 +1,12 @@
import sys
import os
import re
+import string
import imp
-from Tkinter import *
-import tkSimpleDialog
-import tkMessageBox
+from tkinter import *
+import tkinter.simpledialog as tkSimpleDialog
+import tkinter.messagebox as tkMessageBox
+import traceback
import webbrowser
from idlelib.MultiCall import MultiCallCreator
@@ -47,7 +49,7 @@ def _find_module(fullname, path=None):
try:
path = module.__path__
except AttributeError:
- raise ImportError, 'No source for module ' + module.__name__
+ raise ImportError('No source for module ' + module.__name__)
if descr[2] != imp.PY_SOURCE:
# If all of the above fails and didn't raise an exception,fallback
# to a straight import which can find __init__.py in a package.
@@ -58,11 +60,7 @@ def _find_module(fullname, path=None):
pass
else:
file = None
- base, ext = os.path.splitext(filename)
- if ext == '.pyc':
- ext = '.py'
- filename = base + ext
- descr = filename, None, imp.PY_SOURCE
+ descr = os.path.splitext(filename)[1], None, imp.PY_SOURCE
return file, filename, descr
@@ -115,7 +113,7 @@ class EditorWindow(object):
from idlelib.UndoDelegator import UndoDelegator
from idlelib.IOBinding import IOBinding, filesystemencoding, encoding
from idlelib import Bindings
- from Tkinter import Toplevel
+ from tkinter import Toplevel
from idlelib.MultiStatusBar import MultiStatusBar
help_url = None
@@ -172,13 +170,15 @@ class EditorWindow(object):
'recent-files.lst')
self.text_frame = text_frame = Frame(top)
self.vbar = vbar = Scrollbar(text_frame, name='vbar')
- self.width = idleConf.GetOption('main','EditorWindow','width', type='int')
+ self.width = idleConf.GetOption('main', 'EditorWindow',
+ 'width', type='int')
text_options = {
'name': 'text',
'padx': 5,
'wrap': 'none',
'width': self.width,
- 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')}
+ 'height': idleConf.GetOption('main', 'EditorWindow',
+ 'height', type='int')}
if TkVersion >= 8.5:
# Starting with tk 8.5 we have to set the new tabstyle option
# to 'wordprocessor' to achieve the same display of tabs as in
@@ -271,7 +271,8 @@ class EditorWindow(object):
# Although use-spaces=0 can be configured manually in config-main.def,
# configuration of tabs v. spaces is not supported in the configuration
# dialog. IDLE promotes the preferred Python indentation: use spaces!
- usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool')
+ usespaces = idleConf.GetOption('main', 'Indent',
+ 'use-spaces', type='bool')
self.usetabs = not usespaces
# tabwidth is the display width of a literal tab character.
@@ -297,39 +298,33 @@ class EditorWindow(object):
# conceivable file).
# Making the initial values larger slows things down more often.
self.num_context_lines = 50, 500, 5000000
-
self.per = per = self.Percolator(text)
-
self.undo = undo = self.UndoDelegator()
per.insertfilter(undo)
text.undo_block_start = undo.undo_block_start
text.undo_block_stop = undo.undo_block_stop
undo.set_saved_change_hook(self.saved_change_hook)
-
# IOBinding implements file I/O and printing functionality
self.io = io = self.IOBinding(self)
io.set_filename_change_hook(self.filename_change_hook)
-
- # Create the recent files submenu
- self.recent_files_menu = Menu(self.menubar)
- self.menudict['file'].insert_cascade(3, label='Recent Files',
- underline=0,
- menu=self.recent_files_menu)
- self.update_recent_files_list()
-
+ self.good_load = False
+ self.set_indentation_params(False)
self.color = None # initialized below in self.ResetColorizer
if filename:
if os.path.exists(filename) and not os.path.isdir(filename):
- io.loadfile(filename)
+ if io.loadfile(filename):
+ self.good_load = True
+ is_py_src = self.ispythonsource(filename)
+ self.set_indentation_params(is_py_src)
+ if is_py_src:
+ self.color = color = self.ColorDelegator()
+ per.insertfilter(color)
else:
io.set_filename(filename)
self.ResetColorizer()
self.saved_change_hook()
-
- self.set_indentation_params(self.ispythonsource(filename))
-
+ self.update_recent_files_list()
self.load_extensions()
-
menu = self.menudict.get('windows')
if menu:
end = menu.index("end")
@@ -348,7 +343,7 @@ class EditorWindow(object):
def _filename_to_unicode(self, filename):
"""convert filename to unicode in order to display it in Tk"""
- if isinstance(filename, unicode) or not filename:
+ if isinstance(filename, str) or not filename:
return filename
else:
try:
@@ -377,7 +372,7 @@ class EditorWindow(object):
insertpt = int(self.text.index("iomark").split(".")[1])
else:
line = self.text.get("insert linestart", "insert lineend")
- for insertpt in xrange(len(line)):
+ for insertpt in range(len(line)):
if line[insertpt] not in (' ','\t'):
break
else:
@@ -391,9 +386,11 @@ class EditorWindow(object):
self.text.tag_remove("sel", "1.0", "end")
else:
if not self.text.index("sel.first"):
- self.text.mark_set("my_anchor", "insert") # there was no previous selection
+ # there was no previous selection
+ self.text.mark_set("my_anchor", "insert")
else:
- if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")):
+ if self.text.compare(self.text.index("sel.first"), "<",
+ self.text.index("insert")):
self.text.mark_set("my_anchor", "sel.first") # extend back
else:
self.text.mark_set("my_anchor", "sel.last") # extend forward
@@ -448,13 +445,15 @@ class EditorWindow(object):
underline, label = prepstr(label)
menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline)
-
if macosxSupport.isCarbonAquaTk(self.root):
# Insert the application menu
menudict['application'] = menu = Menu(mbar, name='apple')
mbar.add_cascade(label='IDLE', menu=menu)
-
self.fill_menus()
+ self.recent_files_menu = Menu(self.menubar)
+ self.menudict['file'].insert_cascade(3, label='Recent Files',
+ underline=0,
+ menu=self.recent_files_menu)
self.base_helpmenu_length = self.menudict['help'].index(END)
self.reset_help_menu_entries()
@@ -486,6 +485,7 @@ class EditorWindow(object):
state = getattr(self, verify_state)()
rmenu.entryconfigure(label, state=state)
+
rmenu.tk_popup(event.x_root, event.y_root)
if iswin:
self.text.config(cursor="ibeam")
@@ -636,7 +636,7 @@ class EditorWindow(object):
text.see("insert")
def open_module(self, event=None):
- # XXX Shouldn't this be in IOBinding or in FileList?
+ # XXX Shouldn't this be in IOBinding?
try:
name = self.text.get("sel.first", "sel.last")
except TclError:
@@ -654,7 +654,7 @@ class EditorWindow(object):
# XXX Ought to insert current file's directory in front of path
try:
(f, file, (suffix, mode, type)) = _find_module(name)
- except (NameError, ImportError), msg:
+ except (NameError, ImportError) as msg:
tkMessageBox.showerror("Import error", str(msg), parent=self.text)
return
if type != imp.PY_SOURCE:
@@ -699,13 +699,8 @@ class EditorWindow(object):
base, ext = os.path.splitext(os.path.basename(filename))
if os.path.normcase(ext) in (".py", ".pyw"):
return True
- try:
- f = open(filename)
- line = f.readline()
- f.close()
- except IOError:
- return False
- return line.startswith('#!') and line.find('python') >= 0
+ line = self.text.get('1.0', '1.0 lineend')
+ return line.startswith('#!') and 'python' in line
def close_hook(self):
if self.flist:
@@ -757,6 +752,19 @@ class EditorWindow(object):
selectbackground=select_colors['background'],
)
+ IDENTCHARS = string.ascii_letters + string.digits + "_"
+
+ def colorize_syntax_error(self, text, pos):
+ text.tag_add("ERROR", pos)
+ char = text.get(pos)
+ if char and char in self.IDENTCHARS:
+ text.tag_add("ERROR", pos + " wordstart", pos)
+ if '\n' == text.get(pos): # error at line end
+ text.mark_set("insert", pos)
+ else:
+ text.mark_set("insert", pos + "+1c")
+ text.see(pos)
+
def ResetFont(self):
"Update the text widgets' font if it is changed"
# Called from configDialog.py
@@ -796,7 +804,7 @@ class EditorWindow(object):
for item in menu[1]:
if item:
menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1]
- for menubarItem in self.menudict.keys():
+ for menubarItem in self.menudict:
menu = self.menudict[menubarItem]
end = menu.index(END) + 1
for index in range(0, end):
@@ -855,7 +863,8 @@ class EditorWindow(object):
"Load and update the recent files list and menus"
rf_list = []
if os.path.exists(self.recent_files_path):
- rf_list_file = open(self.recent_files_path,'r')
+ rf_list_file = open(self.recent_files_path,'r',
+ encoding='utf_8', errors='replace')
try:
rf_list = rf_list_file.readlines()
finally:
@@ -874,7 +883,8 @@ class EditorWindow(object):
ulchars = "1234567890ABCDEFGHIJK"
rf_list = rf_list[0:len(ulchars)]
try:
- with open(self.recent_files_path, 'w') as rf_file:
+ with open(self.recent_files_path, 'w',
+ encoding='utf_8', errors='replace') as rf_file:
rf_file.writelines(rf_list)
except IOError as err:
if not getattr(self.root, "recentfilelist_error_displayed", False):
@@ -884,7 +894,7 @@ class EditorWindow(object):
% str(err),
parent=self.text)
# for each edit window instance, construct the recent files menu
- for instance in self.top.instance_dict.keys():
+ for instance in self.top.instance_dict:
menu = instance.recent_files_menu
menu.delete(0, END) # clear, and rebuild:
for i, file_name in enumerate(rf_list):
@@ -968,8 +978,7 @@ class EditorWindow(object):
"Return (width, height, x, y)"
geom = self.top.wm_geometry()
m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom)
- tuple = (map(int, m.groups()))
- return tuple
+ return list(map(int, m.groups()))
def close_event(self, event):
self.close()
@@ -1014,7 +1023,7 @@ class EditorWindow(object):
self.load_standard_extensions()
def unload_extensions(self):
- for ins in self.extensions.values():
+ for ins in list(self.extensions.values()):
if hasattr(ins, "close"):
ins.close()
self.extensions = {}
@@ -1024,8 +1033,7 @@ class EditorWindow(object):
try:
self.load_extension(name)
except:
- print "Failed to load extension", repr(name)
- import traceback
+ print("Failed to load extension", repr(name))
traceback.print_exc()
def get_standard_extension_names(self):
@@ -1035,8 +1043,8 @@ class EditorWindow(object):
try:
mod = __import__(name, globals(), locals(), [])
except ImportError:
- print "\nFailed to import extension: ", name
- return
+ print("\nFailed to import extension: ", name)
+ raise
cls = getattr(mod, name)
keydefs = idleConf.GetExtensionBindings(name)
if hasattr(cls, "menudefs"):
@@ -1045,7 +1053,7 @@ class EditorWindow(object):
self.extensions[name] = ins
if keydefs:
self.apply_bindings(keydefs)
- for vevent in keydefs.keys():
+ for vevent in keydefs:
methodname = vevent.replace("-", "_")
while methodname[:1] == '<':
methodname = methodname[1:]
@@ -1107,14 +1115,14 @@ class EditorWindow(object):
value = var.get()
return value
else:
- raise NameError, name
+ raise NameError(name)
def setvar(self, name, value, vartype=None):
var = self.get_var_obj(name, vartype)
if var:
var.set(value)
else:
- raise NameError, name
+ raise NameError(name)
def get_var_obj(self, name, vartype=None):
var = self.tkinter_vars.get(name)
@@ -1155,34 +1163,31 @@ class EditorWindow(object):
# Return the text widget's current view of what a tab stop means
# (equivalent width in spaces).
- def get_tabwidth(self):
+ def get_tk_tabwidth(self):
current = self.text['tabs'] or TK_TABWIDTH_DEFAULT
return int(current)
# Set the text widget's current view of what a tab stop means.
- def set_tabwidth(self, newtabwidth):
+ def set_tk_tabwidth(self, newtabwidth):
text = self.text
- if self.get_tabwidth() != newtabwidth:
+ if self.get_tk_tabwidth() != newtabwidth:
+ # Set text widget tab width
pixels = text.tk.call("font", "measure", text["font"],
"-displayof", text.master,
"n" * newtabwidth)
text.configure(tabs=pixels)
- # If ispythonsource and guess are true, guess a good value for
- # indentwidth based on file content (if possible), and if
- # indentwidth != tabwidth set usetabs false.
- # In any case, adjust the Text widget's view of what a tab
- # character means.
+### begin autoindent code ### (configuration was moved to beginning of class)
- def set_indentation_params(self, ispythonsource, guess=True):
- if guess and ispythonsource:
+ def set_indentation_params(self, is_py_src, guess=True):
+ if is_py_src and guess:
i = self.guess_indent()
if 2 <= i <= 8:
self.indentwidth = i
if self.indentwidth != self.tabwidth:
self.usetabs = False
- self.set_tabwidth(self.tabwidth)
+ self.set_tk_tabwidth(self.tabwidth)
def smart_backspace_event(self, event):
text = self.text
@@ -1610,7 +1615,9 @@ class IndentSearcher(object):
_tokenize.tabsize = self.tabwidth
try:
try:
- _tokenize.tokenize(self.readline, self.tokeneater)
+ tokens = _tokenize.generate_tokens(self.readline)
+ for token in tokens:
+ self.tokeneater(*token)
except (_tokenize.TokenError, SyntaxError):
# since we cut off the tokenizer early, we can trigger
# spurious errors