summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/EditorWindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib/EditorWindow.py')
-rw-r--r--Lib/idlelib/EditorWindow.py210
1 files changed, 133 insertions, 77 deletions
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 259c7f3..7cc69cb 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -6,22 +6,32 @@ from itertools import count
from Tkinter import *
import tkSimpleDialog
import tkMessageBox
-from MultiCall import MultiCallCreator
-
import webbrowser
-import idlever
-import WindowList
-import SearchDialog
-import GrepDialog
-import ReplaceDialog
-import PyParse
-from configHandler import idleConf
-import aboutDialog, textView, configDialog
-import macosxSupport
+
+from idlelib.MultiCall import MultiCallCreator
+from idlelib import idlever
+from idlelib import WindowList
+from idlelib import SearchDialog
+from idlelib import GrepDialog
+from idlelib import ReplaceDialog
+from idlelib import PyParse
+from idlelib.configHandler import idleConf
+from idlelib import aboutDialog, textView, configDialog
+from idlelib import macosxSupport
# The default tab setting for a Text widget, in average-width characters.
TK_TABWIDTH_DEFAULT = 8
+def _sphinx_version():
+ "Format sys.version_info to produce the Sphinx version string used to install the chm docs"
+ major, minor, micro, level, serial = sys.version_info
+ release = '%s%s' % (major, minor)
+ if micro:
+ release += '%s' % micro
+ if level != 'final':
+ release += '%s%s' % (level[0], serial)
+ return release
+
def _find_module(fullname, path=None):
"""Version of imp.find_module() that handles hierarchical module names"""
@@ -40,13 +50,13 @@ def _find_module(fullname, path=None):
return file, filename, descr
class EditorWindow(object):
- from Percolator import Percolator
- from ColorDelegator import ColorDelegator
- from UndoDelegator import UndoDelegator
- from IOBinding import IOBinding, filesystemencoding, encoding
- import Bindings
+ from idlelib.Percolator import Percolator
+ from idlelib.ColorDelegator import ColorDelegator
+ from idlelib.UndoDelegator import UndoDelegator
+ from idlelib.IOBinding import IOBinding, filesystemencoding, encoding
+ from idlelib import Bindings
from Tkinter import Toplevel
- from MultiStatusBar import MultiStatusBar
+ from idlelib.MultiStatusBar import MultiStatusBar
help_url = None
@@ -64,15 +74,13 @@ class EditorWindow(object):
'Doc', 'index.html')
elif sys.platform[:3] == 'win':
chmfile = os.path.join(sys.prefix, 'Doc',
- 'Python%d%d.chm' % sys.version_info[:2])
+ 'Python%s.chm' % _sphinx_version())
if os.path.isfile(chmfile):
dochome = chmfile
-
elif macosxSupport.runningAsOSXApp():
# documentation is stored inside the python framework
dochome = os.path.join(sys.prefix,
'Resources/English.lproj/Documentation/index.html')
-
dochome = os.path.normpath(dochome)
if os.path.isfile(dochome):
EditorWindow.help_url = dochome
@@ -80,7 +88,7 @@ class EditorWindow(object):
# Safari requires real file:-URLs
EditorWindow.help_url = 'file://' + EditorWindow.help_url
else:
- EditorWindow.help_url = "http://www.python.org/doc/current"
+ EditorWindow.help_url = "http://docs.python.org/%d.%d" % sys.version_info[:2]
currentTheme=idleConf.CurrentTheme()
self.flist = flist
root = root or flist.root
@@ -102,23 +110,21 @@ class EditorWindow(object):
self.top.instance_dict = {}
self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(),
'recent-files.lst')
- self.vbar = vbar = Scrollbar(top, name='vbar')
self.text_frame = text_frame = Frame(top)
+ self.vbar = vbar = Scrollbar(text_frame, name='vbar')
self.width = idleConf.GetOption('main','EditorWindow','width')
- self.text = text = MultiCallCreator(Text)(
- text_frame, name='text', padx=5, wrap='none',
- foreground=idleConf.GetHighlight(currentTheme,
- 'normal',fgBg='fg'),
- background=idleConf.GetHighlight(currentTheme,
- 'normal',fgBg='bg'),
- highlightcolor=idleConf.GetHighlight(currentTheme,
- 'hilite',fgBg='fg'),
- highlightbackground=idleConf.GetHighlight(currentTheme,
- 'hilite',fgBg='bg'),
- insertbackground=idleConf.GetHighlight(currentTheme,
- 'cursor',fgBg='fg'),
- width=self.width,
- height=idleConf.GetOption('main','EditorWindow','height') )
+ text_options = {
+ 'name': 'text',
+ 'padx': 5,
+ 'wrap': 'none',
+ 'width': self.width,
+ 'height': idleConf.GetOption('main', 'EditorWindow', 'height')}
+ 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
+ # older tk versions.
+ text_options['tabstyle'] = 'wordprocessor'
+ self.text = text = MultiCallCreator(Text)(text_frame, **text_options)
self.top.focused_widget = self.text
self.createmenubar()
@@ -163,6 +169,7 @@ class EditorWindow(object):
text.bind("<Right>", self.move_at_edge_if_selection(1))
text.bind("<<del-word-left>>", self.del_word_left)
text.bind("<<del-word-right>>", self.del_word_right)
+ text.bind("<<beginning-of-line>>", self.home_callback)
if flist:
flist.inversedict[self] = key
@@ -224,11 +231,6 @@ class EditorWindow(object):
self.num_context_lines = 50, 500, 5000000
self.per = per = self.Percolator(text)
- if self.ispythonsource(filename):
- self.color = color = self.ColorDelegator()
- per.insertfilter(color)
- else:
- self.color = None
self.undo = undo = self.UndoDelegator()
per.insertfilter(undo)
@@ -247,11 +249,13 @@ class EditorWindow(object):
menu=self.recent_files_menu)
self.update_recent_files_list()
+ self.color = None # initialized below in self.ResetColorizer
if filename:
if os.path.exists(filename) and not os.path.isdir(filename):
io.loadfile(filename)
else:
io.set_filename(filename)
+ self.ResetColorizer()
self.saved_change_hook()
self.set_indentation_params(self.ispythonsource(filename))
@@ -294,6 +298,50 @@ class EditorWindow(object):
self.flist.new(dirname)
return "break"
+ def home_callback(self, event):
+ if (event.state & 12) != 0 and event.keysym == "Home":
+ # state&1==shift, state&4==control, state&8==alt
+ return # <Modifier-Home>; fall back to class binding
+
+ if self.text.index("iomark") and \
+ self.text.compare("iomark", "<=", "insert lineend") and \
+ self.text.compare("insert linestart", "<=", "iomark"):
+ insertpt = int(self.text.index("iomark").split(".")[1])
+ else:
+ line = self.text.get("insert linestart", "insert lineend")
+ for insertpt in xrange(len(line)):
+ if line[insertpt] not in (' ','\t'):
+ break
+ else:
+ insertpt=len(line)
+
+ lineat = int(self.text.index("insert").split('.')[1])
+
+ if insertpt == lineat:
+ insertpt = 0
+
+ dest = "insert linestart+"+str(insertpt)+"c"
+
+ if (event.state&1) == 0:
+ # shift not pressed
+ self.text.tag_remove("sel", "1.0", "end")
+ else:
+ if not self.text.index("sel.first"):
+ self.text.mark_set("anchor","insert")
+
+ first = self.text.index(dest)
+ last = self.text.index("anchor")
+
+ if self.text.compare(first,">",last):
+ first,last = last,first
+
+ self.text.tag_remove("sel", "1.0", "end")
+ self.text.tag_add("sel", first, last)
+
+ self.text.mark_set("insert", dest)
+ self.text.see("insert")
+ return "break"
+
def set_status_bar(self):
self.status_bar = self.MultiStatusBar(self.top)
if macosxSupport.runningAsOSXApp():
@@ -336,7 +384,7 @@ class EditorWindow(object):
menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline)
- if sys.platform == 'darwin' and '.framework' in sys.executable:
+ if macosxSupport.runningAsOSXApp():
# Insert the application menu
menudict['application'] = menu = Menu(mbar, name='apple')
mbar.add_cascade(label='IDLE', menu=menu)
@@ -392,7 +440,7 @@ class EditorWindow(object):
def help_dialog(self, event=None):
fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt')
- textView.TextViewer(self.top,'Help',fn)
+ textView.view_file(self.top,'Help',fn)
def python_docs(self, event=None):
if sys.platform[:3] == 'win':
@@ -414,6 +462,7 @@ class EditorWindow(object):
def paste(self,event):
self.text.event_generate("<<Paste>>")
+ self.text.see("insert")
return "break"
def select_all(self, event=None):
@@ -530,11 +579,11 @@ class EditorWindow(object):
return None
head, tail = os.path.split(filename)
base, ext = os.path.splitext(tail)
- import ClassBrowser
+ from idlelib import ClassBrowser
ClassBrowser.ClassBrowser(self.flist, base, [head])
def open_path_browser(self, event=None):
- import PathBrowser
+ from idlelib import PathBrowser
PathBrowser.PathBrowser(self.flist)
def gotoline(self, lineno):
@@ -560,7 +609,8 @@ class EditorWindow(object):
def close_hook(self):
if self.flist:
- self.flist.close_edit(self)
+ self.flist.unregister_maybe_terminate(self)
+ self.flist = None
def set_close_hook(self, close_hook):
self.close_hook = close_hook
@@ -570,36 +620,42 @@ class EditorWindow(object):
self.flist.filename_changed_edit(self)
self.saved_change_hook()
self.top.update_windowlist_registry(self)
- if self.ispythonsource(self.io.filename):
- self.addcolorizer()
- else:
- self.rmcolorizer()
+ self.ResetColorizer()
- def addcolorizer(self):
+ def _addcolorizer(self):
if self.color:
return
- self.per.removefilter(self.undo)
- self.color = self.ColorDelegator()
- self.per.insertfilter(self.color)
- self.per.insertfilter(self.undo)
+ if self.ispythonsource(self.io.filename):
+ self.color = self.ColorDelegator()
+ # can add more colorizers here...
+ if self.color:
+ self.per.removefilter(self.undo)
+ self.per.insertfilter(self.color)
+ self.per.insertfilter(self.undo)
- def rmcolorizer(self):
+ def _rmcolorizer(self):
if not self.color:
return
self.color.removecolors()
- self.per.removefilter(self.undo)
self.per.removefilter(self.color)
self.color = None
- self.per.insertfilter(self.undo)
def ResetColorizer(self):
- "Update the colour theme if it is changed"
- # Called from configDialog.py
- if self.color:
- self.color = self.ColorDelegator()
- self.per.insertfilter(self.color)
+ "Update the colour theme"
+ # Called from self.filename_change_hook and from configDialog.py
+ self._rmcolorizer()
+ self._addcolorizer()
theme = idleConf.GetOption('main','Theme','name')
- self.text.config(idleConf.GetHighlight(theme, "normal"))
+ normal_colors = idleConf.GetHighlight(theme, 'normal')
+ cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
+ select_colors = idleConf.GetHighlight(theme, 'hilite')
+ self.text.config(
+ foreground=normal_colors['foreground'],
+ background=normal_colors['background'],
+ insertbackground=cursor_color,
+ selectforeground=select_colors['foreground'],
+ selectbackground=select_colors['background'],
+ )
def ResetFont(self):
"Update the text widgets' font if it is changed"
@@ -827,22 +883,21 @@ class EditorWindow(object):
if self.io.filename:
self.update_recent_files_list(new_file=self.io.filename)
WindowList.unregister_callback(self.postwindowsmenu)
- if self.close_hook:
- self.close_hook()
- self.flist = None
- colorizing = 0
self.unload_extensions()
- self.io.close(); self.io = None
- self.undo = None # XXX
+ self.io.close()
+ self.io = None
+ self.undo = None
if self.color:
- colorizing = self.color.colorizing
- doh = colorizing and self.top
- self.color.close(doh) # Cancel colorization
+ self.color.close(False)
+ self.color = None
self.text = None
self.tkinter_vars = None
- self.per.close(); self.per = None
- if not colorizing:
- self.top.destroy()
+ self.per.close()
+ self.per = None
+ self.top.destroy()
+ if self.close_hook:
+ # unless override: unregister from flist, terminate if last window
+ self.close_hook()
def load_extensions(self):
self.extensions = {}
@@ -1138,7 +1193,7 @@ class EditorWindow(object):
if not self.context_use_ps1:
for context in self.num_context_lines:
startat = max(lno - context, 1)
- startatindex = `startat` + ".0"
+ startatindex = repr(startat) + ".0"
rawtext = text.get(startatindex, "insert")
y.set_str(rawtext)
bod = y.find_good_parse_start(
@@ -1504,6 +1559,7 @@ def test():
filename = None
edit = EditorWindow(root=root, filename=filename)
edit.set_close_hook(root.quit)
+ edit.text.bind("<<close-all-windows>>", edit.close_event)
root.mainloop()
root.destroy()