1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport re 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport imp 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Tkinter import * 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tkSimpleDialog 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tkMessageBox 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport webbrowser 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib.MultiCall import MultiCallCreator 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import idlever 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import WindowList 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import SearchDialog 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import GrepDialog 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import ReplaceDialog 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import PyParse 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib.configHandler import idleConf 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import aboutDialog, textView, configDialog 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib import macosxSupport 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# The default tab setting for a Text widget, in average-width characters. 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehTK_TABWIDTH_DEFAULT = 8 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _sphinx_version(): 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Format sys.version_info to produce the Sphinx version string used to install the chm docs" 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh major, minor, micro, level, serial = sys.version_info 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh release = '%s%s' % (major, minor) 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if micro: 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh release += '%s' % (micro,) 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if level == 'candidate': 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh release += 'rc%s' % (serial,) 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif level != 'final': 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh release += '%s%s' % (level[0], serial) 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return release 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _find_module(fullname, path=None): 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Version of imp.find_module() that handles hierarchical module names""" 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh file = None 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for tgt in fullname.split('.'): 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if file is not None: 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh file.close() # close intermediate files 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (file, filename, descr) = imp.find_module(tgt, path) 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if descr[2] == imp.PY_SOURCE: 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break # find but not load the source file 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh module = imp.load_module(tgt, file, filename, descr) 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh path = module.__path__ 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ImportError, 'No source for module ' + module.__name__ 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if descr[2] != imp.PY_SOURCE: 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If all of the above fails and didn't raise an exception,fallback 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to a straight import which can find __init__.py in a package. 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh m = __import__(fullname) 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = m.__file__ 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh file = None 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base, ext = os.path.splitext(filename) 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if ext == '.pyc': 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ext = '.py' 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = base + ext 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh descr = filename, None, imp.PY_SOURCE 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return file, filename, descr 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass HelpDialog(object): 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.parent = None # parent of help window 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dlg = None # the help window iteself 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def display(self, parent, near=None): 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ Display the help dialog. 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent - parent widget for the help window 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh near - a Toplevel widget (e.g. EditorWindow or PyShell) 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh to use as a reference for placing the help window 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.dlg is None: 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.show_dialog(parent) 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if near: 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.nearwindow(near) 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def show_dialog(self, parent): 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.parent = parent 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dlg = dlg = textView.view_file(parent,'Help',fn, modal=False) 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg.bind('<Destroy>', self.destroy, '+') 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def nearwindow(self, near): 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Place the help dialog near the window specified by parent. 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Note - this may not reposition the window in Metacity 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if "/apps/metacity/general/disable_workarounds" is enabled 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg = self.dlg 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh geom = (near.winfo_rootx() + 10, near.winfo_rooty() + 10) 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg.withdraw() 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg.geometry("=+%d+%d" % geom) 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg.deiconify() 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dlg.lift() 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def destroy(self, ev=None): 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dlg = None 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.parent = None 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehhelpDialog = HelpDialog() # singleton instance 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass EditorWindow(object): 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib.Percolator import Percolator 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib.ColorDelegator import ColorDelegator 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib.UndoDelegator import UndoDelegator 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib.IOBinding import IOBinding, filesystemencoding, encoding 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib import Bindings 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from Tkinter import Toplevel 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib.MultiStatusBar import MultiStatusBar 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help_url = None 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, flist=None, filename=None, key=None, root=None): 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if EditorWindow.help_url is None: 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = os.path.join(sys.prefix, 'Doc', 'index.html') 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform.count('linux'): 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # look for html docs in a couple of standard places 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.isdir('/var/www/html/python/'): # "python2" rpm 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = '/var/www/html/python/index.html' 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh basepath = '/usr/share/doc/' # standard location 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = os.path.join(basepath, pyver, 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'Doc', 'index.html') 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif sys.platform[:3] == 'win': 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chmfile = os.path.join(sys.prefix, 'Doc', 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'Python%s.chm' % _sphinx_version()) 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.isfile(chmfile): 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = chmfile 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif macosxSupport.runningAsOSXApp(): 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # documentation is stored inside the python framework 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = os.path.join(sys.prefix, 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'Resources/English.lproj/Documentation/index.html') 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dochome = os.path.normpath(dochome) 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.isfile(dochome): 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh EditorWindow.help_url = dochome 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform == 'darwin': 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Safari requires real file:-URLs 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh EditorWindow.help_url = 'file://' + EditorWindow.help_url 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh EditorWindow.help_url = "http://docs.python.org/%d.%d" % sys.version_info[:2] 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh currentTheme=idleConf.CurrentTheme() 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist = flist 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root = root or flist.root 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.root = root 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.ps1 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.ps1 = '>>> ' 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.menubar = Menu(root) 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top = top = WindowList.ListedToplevel(root, menu=self.menubar) 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if flist: 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tkinter_vars = flist.vars 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #self.top.instance_dict makes flist.inversedict available to 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #configDialog.py so it can access all EditorWindow instances 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.instance_dict = flist.inversedict 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tkinter_vars = {} # keys: Tkinter event names 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # values: Tkinter variable instances 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.instance_dict = {} 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(), 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'recent-files.lst') 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text_frame = text_frame = Frame(top) 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.vbar = vbar = Scrollbar(text_frame, name='vbar') 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.width = idleConf.GetOption('main','EditorWindow','width', type='int') 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text_options = { 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'name': 'text', 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'padx': 5, 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'wrap': 'none', 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'width': self.width, 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')} 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if TkVersion >= 8.5: 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Starting with tk 8.5 we have to set the new tabstyle option 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to 'wordprocessor' to achieve the same display of tabs as in 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # older tk versions. 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text_options['tabstyle'] = 'wordprocessor' 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = text = MultiCallCreator(Text)(text_frame, **text_options) 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.focused_widget = self.text 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.createmenubar() 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.apply_bindings() 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.protocol("WM_DELETE_WINDOW", self.close) 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.bind("<<close-window>>", self.close_event) 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if macosxSupport.runningAsOSXApp(): 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Command-W on editorwindows doesn't work without this. 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind('<<close-window>>', self.close_event) 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Some OS X systems have only one mouse button, 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # so use control-click for pulldown menus there. 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (Note, AquaTk defines <2> as the right button if 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # present and the Tk Text widget already binds <2>.) 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<Control-Button-1>",self.right_menu_event) 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Elsewhere, use right-click for pulldown menus. 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<3>",self.right_menu_event) 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<cut>>", self.cut) 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<copy>>", self.copy) 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<paste>>", self.paste) 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<center-insert>>", self.center_insert_event) 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<help>>", self.help_dialog) 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<python-docs>>", self.python_docs) 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<about-idle>>", self.about_dialog) 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<open-config-dialog>>", self.config_dialog) 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<open-module>>", self.open_module) 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<do-nothing>>", lambda event: "break") 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<select-all>>", self.select_all) 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<remove-selection>>", self.remove_selection) 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<find>>", self.find_event) 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<find-again>>", self.find_again_event) 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<find-in-files>>", self.find_in_files_event) 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<find-selection>>", self.find_selection_event) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<replace>>", self.replace_event) 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<goto-line>>", self.goto_line_event) 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<smart-backspace>>",self.smart_backspace_event) 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<newline-and-indent>>",self.newline_and_indent_event) 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<smart-indent>>",self.smart_indent_event) 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<indent-region>>",self.indent_region_event) 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<dedent-region>>",self.dedent_region_event) 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<comment-region>>",self.comment_region_event) 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<uncomment-region>>",self.uncomment_region_event) 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<tabify-region>>",self.tabify_region_event) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<untabify-region>>",self.untabify_region_event) 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<toggle-tabs>>",self.toggle_tabs_event) 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<change-indentwidth>>",self.change_indentwidth_event) 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<Left>", self.move_at_edge_if_selection(0)) 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<Right>", self.move_at_edge_if_selection(1)) 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<del-word-left>>", self.del_word_left) 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<del-word-right>>", self.del_word_right) 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<beginning-of-line>>", self.home_callback) 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if flist: 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flist.inversedict[self] = key 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if key: 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flist.dict[key] = self 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<open-new-window>>", self.new_callback) 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<close-all-windows>>", self.flist.close_all_callback) 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<open-class-browser>>", self.open_class_browser) 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bind("<<open-path-browser>>", self.open_path_browser) 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_status_bar() 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh vbar['command'] = text.yview 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh vbar.pack(side=RIGHT, fill=Y) 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text['yscrollcommand'] = vbar.set 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight = 'normal' 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight='bold' 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh idleConf.GetOption('main', 'EditorWindow', 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'font-size', type='int'), 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight)) 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text_frame.pack(side=LEFT, fill=BOTH, expand=1) 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.pack(side=TOP, fill=BOTH, expand=1) 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.focus_set() 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # usetabs true -> literal tab characters are used by indent and 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dedent cmds, possibly mixed with spaces if 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indentwidth is not a multiple of tabwidth, 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # which will cause Tabnanny to nag! 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # false -> tab characters are converted to spaces by indent 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and dedent cmds, and ditto TAB keystrokes 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Although use-spaces=0 can be configured manually in config-main.def, 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # configuration of tabs v. spaces is not supported in the configuration 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dialog. IDLE promotes the preferred Python indentation: use spaces! 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool') 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.usetabs = not usespaces 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tabwidth is the display width of a literal tab character. 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # CAUTION: telling Tk to use anything other than its default 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tab setting causes it to use an entirely different tabbing algorithm, 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # treating tab stops as fixed distances from the left margin. 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Nobody expects this, so for now tabwidth should never be changed. 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tabwidth = 8 # must remain 8 until Tk is fixed. 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indentwidth is the number of screen characters per indent level. 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The recommended Python indentation is four spaces. 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentwidth = self.tabwidth 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_notabs_indentwidth() 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If context_use_ps1 is true, parsing searches back for a ps1 line; 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # else searches for a popular (if, def, ...) Python stmt. 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.context_use_ps1 = False 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # When searching backwards for a reliable place to begin parsing, 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # first start num_context_lines[0] lines back, then 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # num_context_lines[1] lines back if that didn't work, and so on. 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The last value should be huge (larger than the # of lines in a 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # conceivable file). 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Making the initial values larger slows things down more often. 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.num_context_lines = 50, 500, 5000000 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per = per = self.Percolator(text) 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.undo = undo = self.UndoDelegator() 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh per.insertfilter(undo) 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start = undo.undo_block_start 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop = undo.undo_block_stop 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh undo.set_saved_change_hook(self.saved_change_hook) 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # IOBinding implements file I/O and printing functionality 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.io = io = self.IOBinding(self) 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh io.set_filename_change_hook(self.filename_change_hook) 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Create the recent files submenu 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.recent_files_menu = Menu(self.menubar) 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.menudict['file'].insert_cascade(3, label='Recent Files', 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh underline=0, 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu=self.recent_files_menu) 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.update_recent_files_list() 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color = None # initialized below in self.ResetColorizer 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.exists(filename) and not os.path.isdir(filename): 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh io.loadfile(filename) 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh io.set_filename(filename) 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.ResetColorizer() 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.saved_change_hook() 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_indentation_params(self.ispythonsource(filename)) 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.load_extensions() 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu = self.menudict.get('windows') 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if menu: 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = menu.index("end") 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if end is None: 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = -1 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if end >= 0: 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.add_separator() 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = end + 1 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.wmenu_end = end 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh WindowList.register_callback(self.postwindowsmenu) 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Some abstractions so IDLE extensions are cross-IDE 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.askyesno = tkMessageBox.askyesno 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.askinteger = tkSimpleDialog.askinteger 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.showerror = tkMessageBox.showerror 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _filename_to_unicode(self, filename): 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """convert filename to unicode in order to display it in Tk""" 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(filename, unicode) or not filename: 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename.decode(self.filesystemencoding) 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeDecodeError: 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXX 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename.decode(self.encoding) 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeDecodeError: 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # byte-to-byte conversion 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename.decode('iso8859-1') 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def new_callback(self, event): 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dirname, basename = self.io.defaultfilename() 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist.new(dirname) 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def home_callback(self, event): 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (event.state & 4) != 0 and event.keysym == "Home": 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # state&4==Control. If <Control-Home>, use the Tk binding. 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.text.index("iomark") and \ 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.compare("iomark", "<=", "insert lineend") and \ 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.compare("insert linestart", "<=", "iomark"): 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In Shell on input line, go to just after prompt 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insertpt = int(self.text.index("iomark").split(".")[1]) 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = self.text.get("insert linestart", "insert lineend") 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for insertpt in xrange(len(line)): 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line[insertpt] not in (' ','\t'): 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insertpt=len(line) 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lineat = int(self.text.index("insert").split('.')[1]) 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if insertpt == lineat: 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insertpt = 0 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dest = "insert linestart+"+str(insertpt)+"c" 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (event.state&1) == 0: 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # shift was not pressed 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_remove("sel", "1.0", "end") 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.text.index("sel.first"): 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("my_anchor", "insert") # there was no previous selection 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")): 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("my_anchor", "sel.first") # extend back 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("my_anchor", "sel.last") # extend forward 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first = self.text.index(dest) 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh last = self.text.index("my_anchor") 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.text.compare(first,">",last): 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first,last = last,first 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_remove("sel", "1.0", "end") 405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_add("sel", first, last) 406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("insert", dest) 407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.see("insert") 408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_status_bar(self): 411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar = self.MultiStatusBar(self.top) 412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if macosxSupport.runningAsOSXApp(): 413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Insert some padding to avoid obscuring some of the statusbar 414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # by the resize widget. 415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.set_label('_padding1', ' ', side=RIGHT) 416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.set_label('column', 'Col: ?', side=RIGHT) 417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.set_label('line', 'Ln: ?', side=RIGHT) 418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.pack(side=BOTTOM, fill=X) 419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind("<<set-line-and-column>>", self.set_line_and_column) 420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_add("<<set-line-and-column>>", 421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "<KeyRelease>", "<ButtonRelease>") 422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.after_idle(self.set_line_and_column) 423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_line_and_column(self, event=None): 425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line, column = self.text.index(INSERT).split('.') 426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.set_label('column', 'Col: %s' % column) 427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.status_bar.set_label('line', 'Ln: %s' % line) 428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu_specs = [ 430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("file", "_File"), 431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("edit", "_Edit"), 432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("format", "F_ormat"), 433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("run", "_Run"), 434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("options", "_Options"), 435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("windows", "_Windows"), 436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("help", "_Help"), 437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ] 438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if macosxSupport.runningAsOSXApp(): 440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh del menu_specs[-3] 441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu_specs[-2] = ("windows", "_Window") 442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def createmenubar(self): 445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mbar = self.menubar 446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.menudict = menudict = {} 447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, label in self.menu_specs: 448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh underline, label = prepstr(label) 449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menudict[name] = menu = Menu(mbar, name=name) 450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mbar.add_cascade(label=label, menu=menu, underline=underline) 451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if macosxSupport.isCarbonAquaTk(self.root): 453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Insert the application menu 454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menudict['application'] = menu = Menu(mbar, name='apple') 455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mbar.add_cascade(label='IDLE', menu=menu) 456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fill_menus() 458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.base_helpmenu_length = self.menudict['help'].index(END) 459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reset_help_menu_entries() 460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def postwindowsmenu(self): 462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Only called when Windows menu exists 463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu = self.menudict['windows'] 464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = menu.index("end") 465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if end is None: 466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = -1 467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if end > self.wmenu_end: 468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.delete(self.wmenu_end+1, end) 469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh WindowList.add_windows_to_menu(menu) 470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu = None 472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def right_menu_event(self, event): 474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) 475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.rmenu: 476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.make_rmenu() 477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu = self.rmenu 478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.event = event 479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh iswin = sys.platform[:3] == 'win' 480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if iswin: 481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.config(cursor="arrow") 482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for item in self.rmenu_specs: 484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh label, eventname, verify_state = item 486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ValueError: # see issue1207589 487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verify_state is None: 490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh state = getattr(self, verify_state)() 492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu.entryconfigure(label, state=state) 493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu.tk_popup(event.x_root, event.y_root) 495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if iswin: 496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.config(cursor="ibeam") 497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu_specs = [ 499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ("Label", "<<virtual-event>>", "statefuncname"), ... 500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("Close", "<<close-window>>", None), # Example 501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ] 502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def make_rmenu(self): 504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu = Menu(self.text, tearoff=0) 505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for item in self.rmenu_specs: 506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh label, eventname = item[0], item[1] 507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if label is not None: 508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def command(text=self.text, eventname=eventname): 509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.event_generate(eventname) 510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu.add_command(label=label, command=command) 511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rmenu.add_separator() 513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.rmenu = rmenu 514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def rmenu_check_cut(self): 516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.rmenu_check_copy() 517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def rmenu_check_copy(self): 519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh indx = self.text.index('sel.first') 521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except TclError: 522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'disabled' 523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'normal' if indx else 'disabled' 525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def rmenu_check_paste(self): 527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') 529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except TclError: 530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'disabled' 531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'normal' 533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def about_dialog(self, event=None): 535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh aboutDialog.AboutDialog(self.top,'About IDLE') 536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def config_dialog(self, event=None): 538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh configDialog.ConfigDialog(self.top,'Settings') 539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def help_dialog(self, event=None): 541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.root: 542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent = self.root 543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent = self.top 545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpDialog.display(parent, near=self.top) 546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def python_docs(self, event=None): 548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform[:3] == 'win': 549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.startfile(self.help_url) 551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except WindowsError as why: 552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror(title='Document Start Failure', 553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message=str(why), parent=self.text) 554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh webbrowser.open(self.help_url) 556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def cut(self,event): 559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<Cut>>") 560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def copy(self,event): 563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.text.tag_ranges("sel"): 564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # There is no selection, so do nothing and maybe interrupt. 565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<Copy>>") 567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def paste(self,event): 570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<Paste>>") 571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.see("insert") 572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def select_all(self, event=None): 575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_add("sel", "1.0", "end-1c") 576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("insert", "1.0") 577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.see("insert") 578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def remove_selection(self, event=None): 581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_remove("sel", "1.0", "end") 582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.see("insert") 583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def move_at_edge_if_selection(self, edge_index): 585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Cursor move begins at start or end of selection 586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh When a left/right cursor key is pressed create and return to Tkinter a 588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh function which causes a cursor move from the associated edge of the 589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh selection. 590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self_text_index = self.text.index 593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self_text_mark_set = self.text.mark_set 594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh edges_table = ("sel.first+1c", "sel.last-1c") 595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def move_at_edge(event): 596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed 597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self_text_index("sel.first") 599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self_text_mark_set("insert", edges_table[edge_index]) 600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except TclError: 601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return move_at_edge 603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def del_word_left(self, event): 605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate('<Meta-Delete>') 606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def del_word_right(self, event): 609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate('<Meta-d>') 610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def find_event(self, event): 613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SearchDialog.find(self.text) 614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def find_again_event(self, event): 617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SearchDialog.find_again(self.text) 618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def find_selection_event(self, event): 621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SearchDialog.find_selection(self.text) 622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def find_in_files_event(self, event): 625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh GrepDialog.grep(self.text, self.io, self.flist) 626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def replace_event(self, event): 629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ReplaceDialog.replace(self.text) 630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def goto_line_event(self, event): 633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lineno = tkSimpleDialog.askinteger("Goto", 635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Go to line number:",parent=text) 636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if lineno is None: 637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if lineno <= 0: 639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bell() 640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.mark_set("insert", "%d.0" % lineno) 642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.see("insert") 643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open_module(self, event=None): 645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXX Shouldn't this be in IOBinding or in FileList? 646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = self.text.get("sel.first", "sel.last") 648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except TclError: 649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = "" 650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = name.strip() 652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = tkSimpleDialog.askstring("Module", 653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Enter the name of a Python module\n" 654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "to search on sys.path and open:", 655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent=self.text, initialvalue=name) 656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name: 657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = name.strip() 658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not name: 659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXX Ought to insert current file's directory in front of path 661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (f, file, (suffix, mode, type)) = _find_module(name) 663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (NameError, ImportError), msg: 664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror("Import error", str(msg), parent=self.text) 665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if type != imp.PY_SOURCE: 667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror("Unsupported type", 668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s is not a source module" % name, parent=self.text) 669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if f: 671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.close() 672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.flist: 673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist.open(file) 674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.io.loadfile(file) 676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open_class_browser(self, event=None): 678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.io.filename 679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not filename: 680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror( 681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "No filename", 682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "This buffer has no associated filename", 683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master=self.text) 684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail = os.path.split(filename) 687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base, ext = os.path.splitext(tail) 688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib import ClassBrowser 689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ClassBrowser.ClassBrowser(self.flist, base, [head]) 690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open_path_browser(self, event=None): 692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from idlelib import PathBrowser 693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh PathBrowser.PathBrowser(self.flist) 694ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 695ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def gotoline(self, lineno): 696ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if lineno is not None and lineno > 0: 697ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("insert", "%d.0" % lineno) 698ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_remove("sel", "1.0", "end") 699ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.tag_add("sel", "insert", "insert +1l") 700ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.center() 701ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 702ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ispythonsource(self, filename): 703ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not filename or os.path.isdir(filename): 704ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 705ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base, ext = os.path.splitext(os.path.basename(filename)) 706ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.normcase(ext) in (".py", ".pyw"): 707ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 708ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 709ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = open(filename) 710ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = f.readline() 711ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.close() 712ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError: 713ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return False 714ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return line.startswith('#!') and line.find('python') >= 0 715ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 716ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def close_hook(self): 717ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.flist: 718ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist.unregister_maybe_terminate(self) 719ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist = None 720ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 721ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_close_hook(self, close_hook): 722ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.close_hook = close_hook 723ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 724ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def filename_change_hook(self): 725ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.flist: 726ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist.filename_changed_edit(self) 727ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.saved_change_hook() 728ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.update_windowlist_registry(self) 729ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.ResetColorizer() 730ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 731ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _addcolorizer(self): 732ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.color: 733ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 734ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.ispythonsource(self.io.filename): 735ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color = self.ColorDelegator() 736ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # can add more colorizers here... 737ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.color: 738ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per.removefilter(self.undo) 739ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per.insertfilter(self.color) 740ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per.insertfilter(self.undo) 741ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 742ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _rmcolorizer(self): 743ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.color: 744ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 745ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color.removecolors() 746ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per.removefilter(self.color) 747ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color = None 748ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 749ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ResetColorizer(self): 750ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update the colour theme" 751ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Called from self.filename_change_hook and from configDialog.py 752ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._rmcolorizer() 753ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._addcolorizer() 754ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theme = idleConf.GetOption('main','Theme','name') 755ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh normal_colors = idleConf.GetHighlight(theme, 'normal') 756ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') 757ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh select_colors = idleConf.GetHighlight(theme, 'hilite') 758ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.config( 759ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh foreground=normal_colors['foreground'], 760ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh background=normal_colors['background'], 761ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insertbackground=cursor_color, 762ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh selectforeground=select_colors['foreground'], 763ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh selectbackground=select_colors['background'], 764ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ) 765ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 766ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ResetFont(self): 767ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update the text widgets' font if it is changed" 768ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Called from configDialog.py 769ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight='normal' 770ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): 771ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight='bold' 772ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 773ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh idleConf.GetOption('main','EditorWindow','font-size', 774ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh type='int'), 775ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fontWeight)) 776ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 777ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def RemoveKeybindings(self): 778ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Remove the keybindings before they are changed." 779ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Called from configDialog.py 780ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() 781ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for event, keylist in keydefs.items(): 782ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_delete(event, *keylist) 783ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for extensionName in self.get_standard_extension_names(): 784ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xkeydefs = idleConf.GetExtensionBindings(extensionName) 785ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if xkeydefs: 786ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for event, keylist in xkeydefs.items(): 787ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_delete(event, *keylist) 788ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 789ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ApplyKeybindings(self): 790ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update the keybindings after they are changed" 791ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Called from configDialog.py 792ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() 793ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.apply_bindings() 794ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for extensionName in self.get_standard_extension_names(): 795ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xkeydefs = idleConf.GetExtensionBindings(extensionName) 796ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if xkeydefs: 797ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.apply_bindings(xkeydefs) 798ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #update menu accelerators 799ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menuEventDict = {} 800ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for menu in self.Bindings.menudefs: 801ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menuEventDict[menu[0]] = {} 802ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for item in menu[1]: 803ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if item: 804ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1] 805ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for menubarItem in self.menudict.keys(): 806ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu = self.menudict[menubarItem] 807ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = menu.index(END) + 1 808ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for index in range(0, end): 809ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if menu.type(index) == 'command': 810ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh accel = menu.entrycget(index, 'accelerator') 811ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if accel: 812ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh itemName = menu.entrycget(index, 'label') 813ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh event = '' 814ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if menubarItem in menuEventDict: 815ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if itemName in menuEventDict[menubarItem]: 816ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh event = menuEventDict[menubarItem][itemName] 817ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if event: 818ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh accel = get_accelerator(keydefs, event) 819ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.entryconfig(index, accelerator=accel) 820ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 821ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_notabs_indentwidth(self): 822ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update the indentwidth if changed and not using tabs in this window" 823ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Called from configDialog.py 824ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.usetabs: 825ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces', 826ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh type='int') 827ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 828ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def reset_help_menu_entries(self): 829ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update the additional help entries on the Help menu" 830ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help_list = idleConf.GetAllExtraHelpSourcesList() 831ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpmenu = self.menudict['help'] 832ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # first delete the extra help entries, if any 833ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpmenu_length = helpmenu.index(END) 834ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if helpmenu_length > self.base_helpmenu_length: 835ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) 836ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # then rebuild them 837ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if help_list: 838ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpmenu.add_separator() 839ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for entry in help_list: 840ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd = self.__extra_help_callback(entry[1]) 841ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpmenu.add_command(label=entry[0], command=cmd) 842ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and update the menu dictionary 843ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.menudict['help'] = helpmenu 844ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 845ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __extra_help_callback(self, helpfile): 846ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Create a callback with the helpfile value frozen at definition time" 847ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def display_extra_help(helpfile=helpfile): 848ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not helpfile.startswith(('www', 'http')): 849ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh helpfile = os.path.normpath(helpfile) 850ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform[:3] == 'win': 851ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 852ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.startfile(helpfile) 853ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except WindowsError as why: 854ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror(title='Document Start Failure', 855ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message=str(why), parent=self.text) 856ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 857ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh webbrowser.open(helpfile) 858ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return display_extra_help 859ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 860ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def update_recent_files_list(self, new_file=None): 861ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Load and update the recent files list and menus" 862ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list = [] 863ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.exists(self.recent_files_path): 864ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list_file = open(self.recent_files_path,'r') 865ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 866ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list = rf_list_file.readlines() 867ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 868ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list_file.close() 869ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if new_file: 870ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh new_file = os.path.abspath(new_file) + '\n' 871ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if new_file in rf_list: 872ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list.remove(new_file) # move to top 873ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list.insert(0, new_file) 874ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # clean and save the recent files list 875ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bad_paths = [] 876ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for path in rf_list: 877ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if '\0' in path or not os.path.exists(path[0:-1]): 878ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bad_paths.append(path) 879ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list = [path for path in rf_list if path not in bad_paths] 880ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ulchars = "1234567890ABCDEFGHIJK" 881ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_list = rf_list[0:len(ulchars)] 882ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 883ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with open(self.recent_files_path, 'w') as rf_file: 884ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rf_file.writelines(rf_list) 885ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError as err: 886ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not getattr(self.root, "recentfilelist_error_displayed", False): 887ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.root.recentfilelist_error_displayed = True 888ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror(title='IDLE Error', 889ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message='Unable to update Recent Files list:\n%s' 890ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh % str(err), 891ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent=self.text) 892ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # for each edit window instance, construct the recent files menu 893ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for instance in self.top.instance_dict.keys(): 894ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu = instance.recent_files_menu 895ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.delete(0, END) # clear, and rebuild: 896ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i, file_name in enumerate(rf_list): 897ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh file_name = file_name.rstrip() # zap \n 898ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make unicode string to display non-ASCII chars correctly 899ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ufile_name = self._filename_to_unicode(file_name) 900ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh callback = instance.__recent_file_callback(file_name) 901ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.add_command(label=ulchars[i] + " " + ufile_name, 902ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command=callback, 903ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh underline=0) 904ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 905ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __recent_file_callback(self, file_name): 906ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open_recent_file(fn_closure=file_name): 907ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.io.open(editFile=fn_closure) 908ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return open_recent_file 909ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 910ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def saved_change_hook(self): 911ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh short = self.short_title() 912ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh long = self.long_title() 913ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if short and long: 914ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title = short + " - " + long 915ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif short: 916ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title = short 917ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif long: 918ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title = long 919ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 920ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title = "Untitled" 921ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh icon = short or long or title 922ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.get_saved(): 923ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title = "*%s*" % title 924ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh icon = "*%s" % icon 925ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.wm_title(title) 926ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.wm_iconname(icon) 927ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 928ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_saved(self): 929ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.undo.get_saved() 930ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 931ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_saved(self, flag): 932ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.undo.set_saved(flag) 933ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 934ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def reset_undo(self): 935ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.undo.reset_undo() 936ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 937ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def short_title(self): 938ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.io.filename 939ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 940ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = os.path.basename(filename) 941ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # return unicode string to display non-ASCII chars correctly 942ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._filename_to_unicode(filename) 943ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 944ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def long_title(self): 945ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # return unicode string to display non-ASCII chars correctly 946ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._filename_to_unicode(self.io.filename or "") 947ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 948ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def center_insert_event(self, event): 949ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.center() 950ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 951ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def center(self, mark="insert"): 952ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 953ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top, bot = self.getwindowlines() 954ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lineno = self.getlineno(mark) 955ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh height = bot - top 956ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newtop = max(1, lineno - height//2) 957ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.yview(float(newtop)) 958ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 959ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getwindowlines(self): 960ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 961ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top = self.getlineno("@0,0") 962ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bot = self.getlineno("@0,65535") 963ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if top == bot and text.winfo_height() == 1: 964ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Geometry manager hasn't run yet 965ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh height = int(text['height']) 966ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bot = top + height - 1 967ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return top, bot 968ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 969ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getlineno(self, mark="insert"): 970ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 971ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(float(text.index(mark))) 972ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 973ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_geometry(self): 974ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Return (width, height, x, y)" 975ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh geom = self.top.wm_geometry() 976ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) 977ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tuple = (map(int, m.groups())) 978ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return tuple 979ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 980ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def close_event(self, event): 981ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.close() 982ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 983ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def maybesave(self): 984ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.io: 985ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.get_saved(): 986ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.top.state()!='normal': 987ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.deiconify() 988ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.lower() 989ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.lift() 990ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.io.maybesave() 991ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 992ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def close(self): 993ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = self.maybesave() 994ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if str(reply) != "cancel": 995ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._close() 996ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return reply 997ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 998ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _close(self): 999ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.io.filename: 1000ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.update_recent_files_list(new_file=self.io.filename) 1001ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh WindowList.unregister_callback(self.postwindowsmenu) 1002ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.unload_extensions() 1003ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.io.close() 1004ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.io = None 1005ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.undo = None 1006ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.color: 1007ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color.close(False) 1008ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.color = None 1009ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = None 1010ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tkinter_vars = None 1011ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per.close() 1012ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.per = None 1013ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top.destroy() 1014ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.close_hook: 1015ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # unless override: unregister from flist, terminate if last window 1016ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.close_hook() 1017ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1018ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def load_extensions(self): 1019ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.extensions = {} 1020ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.load_standard_extensions() 1021ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1022ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def unload_extensions(self): 1023ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for ins in self.extensions.values(): 1024ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(ins, "close"): 1025ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ins.close() 1026ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.extensions = {} 1027ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1028ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def load_standard_extensions(self): 1029ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name in self.get_standard_extension_names(): 1030ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1031ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.load_extension(name) 1032ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 1033ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print "Failed to load extension", repr(name) 1034ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import traceback 1035ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh traceback.print_exc() 1036ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1037ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_standard_extension_names(self): 1038ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return idleConf.GetExtensions(editor_only=True) 1039ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1040ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def load_extension(self, name): 1041ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1042ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mod = __import__(name, globals(), locals(), []) 1043ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 1044ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print "\nFailed to import extension: ", name 1045ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 1046ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = getattr(mod, name) 1047ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh keydefs = idleConf.GetExtensionBindings(name) 1048ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(cls, "menudefs"): 1049ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fill_menus(cls.menudefs, keydefs) 1050ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ins = cls(self) 1051ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.extensions[name] = ins 1052ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if keydefs: 1053ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.apply_bindings(keydefs) 1054ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for vevent in keydefs.keys(): 1055ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh methodname = vevent.replace("-", "_") 1056ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while methodname[:1] == '<': 1057ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh methodname = methodname[1:] 1058ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while methodname[-1:] == '>': 1059ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh methodname = methodname[:-1] 1060ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh methodname = methodname + "_event" 1061ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(ins, methodname): 1062ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind(vevent, getattr(ins, methodname)) 1063ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1064ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def apply_bindings(self, keydefs=None): 1065ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if keydefs is None: 1066ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh keydefs = self.Bindings.default_keydefs 1067ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1068ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.keydefs = keydefs 1069ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for event, keylist in keydefs.items(): 1070ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if keylist: 1071ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.event_add(event, *keylist) 1072ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1073ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def fill_menus(self, menudefs=None, keydefs=None): 1074ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Add appropriate entries to the menus and submenus 1075ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1076ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Menus that are absent or None in self.menudict are ignored. 1077ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 1078ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if menudefs is None: 1079ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menudefs = self.Bindings.menudefs 1080ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if keydefs is None: 1081ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh keydefs = self.Bindings.default_keydefs 1082ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menudict = self.menudict 1083ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1084ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for mname, entrylist in menudefs: 1085ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu = menudict.get(mname) 1086ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not menu: 1087ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 1088ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for entry in entrylist: 1089ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not entry: 1090ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.add_separator() 1091ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1092ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh label, eventname = entry 1093ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh checkbutton = (label[:1] == '!') 1094ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if checkbutton: 1095ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh label = label[1:] 1096ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh underline, label = prepstr(label) 1097ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh accelerator = get_accelerator(keydefs, eventname) 1098ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def command(text=text, eventname=eventname): 1099ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.event_generate(eventname) 1100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if checkbutton: 1101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh var = self.get_var_obj(eventname, BooleanVar) 1102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.add_checkbutton(label=label, underline=underline, 1103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command=command, accelerator=accelerator, 1104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh variable=var) 1105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh menu.add_command(label=label, underline=underline, 1107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command=command, 1108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh accelerator=accelerator) 1109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getvar(self, name): 1111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh var = self.get_var_obj(name) 1112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if var: 1113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value = var.get() 1114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return value 1115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise NameError, name 1117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setvar(self, name, value, vartype=None): 1119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh var = self.get_var_obj(name, vartype) 1120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if var: 1121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh var.set(value) 1122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise NameError, name 1124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_var_obj(self, name, vartype=None): 1126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh var = self.tkinter_vars.get(name) 1127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not var and vartype: 1128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # create a Tkinter variable object with self.text as master: 1129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tkinter_vars[name] = var = vartype(self.text) 1130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return var 1131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Tk implementations of "virtual text methods" -- each platform 1133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # reusing IDLE's support code needs to define these for its GUI's 1134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # flavor of widget. 1135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Is character at text_index in a Python string? Return 0 for 1137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # "guaranteed no", true for anything else. This info is expensive 1138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to compute ab initio, but is probably already known by the 1139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # platform's colorizer. 1140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def is_char_in_string(self, text_index): 1142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.color: 1143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return true iff colorizer hasn't (re)gotten this far 1144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # yet, or the character is tagged as being in a string 1145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.text.tag_prevrange("TODO", text_index) or \ 1146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "STRING" in self.text.tag_names(text_index) 1147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The colorizer is missing: assume the worst 1149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 1 1150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If a selection is defined in the text widget, return (start, 1152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # end) as Tkinter text indices, otherwise return (None, None) 1153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_selection_indices(self): 1154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first = self.text.index("sel.first") 1156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh last = self.text.index("sel.last") 1157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return first, last 1158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except TclError: 1159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None, None 1160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return the text widget's current view of what a tab stop means 1162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (equivalent width in spaces). 1163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_tabwidth(self): 1165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh current = self.text['tabs'] or TK_TABWIDTH_DEFAULT 1166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(current) 1167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Set the text widget's current view of what a tab stop means. 1169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_tabwidth(self, newtabwidth): 1171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.get_tabwidth() != newtabwidth: 1173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pixels = text.tk.call("font", "measure", text["font"], 1174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "-displayof", text.master, 1175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "n" * newtabwidth) 1176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.configure(tabs=pixels) 1177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If ispythonsource and guess are true, guess a good value for 1179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indentwidth based on file content (if possible), and if 1180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indentwidth != tabwidth set usetabs false. 1181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In any case, adjust the Text widget's view of what a tab 1182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # character means. 1183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_indentation_params(self, ispythonsource, guess=True): 1185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if guess and ispythonsource: 1186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = self.guess_indent() 1187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if 2 <= i <= 8: 1188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentwidth = i 1189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.indentwidth != self.tabwidth: 1190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.usetabs = False 1191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_tabwidth(self.tabwidth) 1192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def smart_backspace_event(self, event): 1194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first, last = self.get_selection_indices() 1196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if first and last: 1197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete(first, last) 1198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.mark_set("insert", first) 1199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Delete whitespace left, until hitting a real char or closest 1201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # preceding virtual tab stop. 1202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = text.get("insert linestart", "insert") 1203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if chars == '': 1204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if text.compare("insert", ">", "1.0"): 1205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # easy: delete preceding newline 1206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert-1c") 1207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bell() # at start of buffer 1209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if chars[-1] not in " \t": 1211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # easy: delete preceding real char 1212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert-1c") 1213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ick. It may require *inserting* spaces if we back up over a 1215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tab character! This is written to be clear, not fast. 1216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tabwidth = self.tabwidth 1217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh have = len(chars.expandtabs(tabwidth)) 1218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert have > 0 1219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh want = ((have - 1) // self.indentwidth) * self.indentwidth 1220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Debug prompt is multilined.... 1221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.context_use_ps1: 1222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh last_line_of_prompt = sys.ps1.split('\n')[-1] 1223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh last_line_of_prompt = '' 1225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncharsdeleted = 0 1226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while 1: 1227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if chars == last_line_of_prompt: 1228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 1229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = chars[:-1] 1230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncharsdeleted = ncharsdeleted + 1 1231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh have = len(chars.expandtabs(tabwidth)) 1232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if have <= want or chars[-1] not in " \t": 1233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 1234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start() 1235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert-%dc" % ncharsdeleted, "insert") 1236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if have < want: 1237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", ' ' * (want - have)) 1238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop() 1239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def smart_indent_event(self, event): 1242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if intraline selection: 1243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # delete it 1244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # elif multiline selection: 1245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # do indent-region 1246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # else: 1247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indent one level 1248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first, last = self.get_selection_indices() 1250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start() 1251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if first and last: 1253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if index2line(first) != index2line(last): 1254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.indent_region_event(event) 1255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete(first, last) 1256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.mark_set("insert", first) 1257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh prefix = text.get("insert linestart", "insert") 1258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, effective = classifyws(prefix, self.tabwidth) 1259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if raw == len(prefix): 1260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # only whitespace to the left 1261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reindent_to(effective + self.indentwidth) 1262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tab to the next 'stop' within or to right of line's text: 1264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.usetabs: 1265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pad = '\t' 1266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effective = len(prefix.expandtabs(self.tabwidth)) 1268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n = self.indentwidth 1269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pad = ' ' * (n - effective % n) 1270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", pad) 1271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.see("insert") 1272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 1274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop() 1275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newline_and_indent_event(self, event): 1277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first, last = self.get_selection_indices() 1279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start() 1280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if first and last: 1282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete(first, last) 1283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.mark_set("insert", first) 1284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = text.get("insert linestart", "insert") 1285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i, n = 0, len(line) 1286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while i < n and line[i] in " \t": 1287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = i+1 1288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if i == n: 1289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the cursor is in or at leading indentation in a continuation 1290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # line; just inject an empty line at the start 1291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert linestart", '\n') 1292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh indent = line[:i] 1294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # strip whitespace before insert point unless it's in the prompt 1295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 1296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh last_line_of_prompt = sys.ps1.split('\n')[-1] 1297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while line and line[-1] in " \t" and line != last_line_of_prompt: 1298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = line[:-1] 1299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = i+1 1300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if i: 1301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert - %d chars" % i, "insert") 1302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # strip whitespace after insert point 1303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while text.get("insert") in " \t": 1304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert") 1305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # start new line 1306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", '\n') 1307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # adjust indentation for continuations and block 1309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # open/close first need to find the last stmt 1310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lno = index2line(text.index('insert')) 1311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh y = PyParse.Parser(self.indentwidth, self.tabwidth) 1312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.context_use_ps1: 1313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for context in self.num_context_lines: 1314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh startat = max(lno - context, 1) 1315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh startatindex = repr(startat) + ".0" 1316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rawtext = text.get(startatindex, "insert") 1317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh y.set_str(rawtext) 1318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bod = y.find_good_parse_start( 1319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.context_use_ps1, 1320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._build_char_in_string_func(startatindex)) 1321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if bod is not None or startat == 1: 1322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 1323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh y.set_lo(bod or 0) 1324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh r = text.tag_prevrange("console", "insert") 1326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if r: 1327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh startatindex = r[1] 1328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh startatindex = "1.0" 1330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rawtext = text.get(startatindex, "insert") 1331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh y.set_str(rawtext) 1332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh y.set_lo(0) 1333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh c = y.get_continuation_type() 1335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if c != PyParse.C_NONE: 1336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The current stmt hasn't ended yet. 1337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if c == PyParse.C_STRING_FIRST_LINE: 1338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # after the first line of a string; do not indent at all 1339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 1340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif c == PyParse.C_STRING_NEXT_LINES: 1341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # inside a string which started before this line; 1342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # just mimic the current indent 1343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", indent) 1344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif c == PyParse.C_BRACKET: 1345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # line up with the first (if any) element of the 1346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # last open bracket structure; else indent one 1347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # level beyond the indent of the line with the 1348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # last open bracket 1349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reindent_to(y.compute_bracket_indent()) 1350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif c == PyParse.C_BACKSLASH: 1351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if more than one line in this stmt already, just 1352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # mimic the current indent; else if initial line 1353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # has a start on an assignment stmt, indent to 1354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # beyond leftmost =; else to beyond first chunk of 1355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # non-whitespace on initial line 1356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if y.get_num_lines_in_stmt() > 1: 1357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", indent) 1358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reindent_to(y.compute_backslash_indent()) 1360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert 0, "bogus continuation type %r" % (c,) 1362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This line starts a brand new stmt; indent relative to 1365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # indentation of initial line of closest preceding 1366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # interesting stmt. 1367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh indent = y.get_base_indent_string() 1368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", indent) 1369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if y.is_block_opener(): 1370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.smart_indent_event(event) 1371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif indent and y.is_block_closer(): 1372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.smart_backspace_event(event) 1373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 1375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.see("insert") 1376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop() 1377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Our editwin provides a is_char_in_string function that works 1379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # with a Tk text index, but PyParse only knows about offsets into 1380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # a string. This builds a function for PyParse that accepts an 1381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # offset. 1382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _build_char_in_string_func(self, startindex): 1384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def inner(offset, _startindex=startindex, 1385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _icis=self.is_char_in_string): 1386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return _icis(_startindex + "+%dc" % offset) 1387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return inner 1388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def indent_region_event(self, event): 1390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines)): 1392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = lines[pos] 1393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line: 1394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, effective = classifyws(line, self.tabwidth) 1395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effective = effective + self.indentwidth 1396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = self._make_blanks(effective) + line[raw:] 1397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dedent_region_event(self, event): 1401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines)): 1403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = lines[pos] 1404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line: 1405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, effective = classifyws(line, self.tabwidth) 1406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effective = max(effective - self.indentwidth, 0) 1407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = self._make_blanks(effective) + line[raw:] 1408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def comment_region_event(self, event): 1412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines) - 1): 1414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = lines[pos] 1415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = '##' + line 1416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def uncomment_region_event(self, event): 1419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines)): 1421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = lines[pos] 1422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not line: 1423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 1424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line[:2] == '##': 1425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = line[2:] 1426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif line[:1] == '#': 1427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = line[1:] 1428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = line 1429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tabify_region_event(self, event): 1432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tabwidth = self._asktabwidth() 1434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tabwidth is None: return 1435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines)): 1436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = lines[pos] 1437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line: 1438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, effective = classifyws(line, tabwidth) 1439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ntabs, nspaces = divmod(effective, tabwidth) 1440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] 1441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def untabify_region_event(self, event): 1444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head, tail, chars, lines = self.get_region() 1445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tabwidth = self._asktabwidth() 1446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tabwidth is None: return 1447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pos in range(len(lines)): 1448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines[pos] = lines[pos].expandtabs(tabwidth) 1449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_region(head, tail, chars, lines) 1450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def toggle_tabs_event(self, event): 1452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.askyesno( 1453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Toggle tabs", 1454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Turn tabs " + ("on", "off")[self.usetabs] + 1455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "?\nIndent width " + 1456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("will be", "remains at")[self.usetabs] + " 8." + 1457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "\n Note: a tab is always 8 columns", 1458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent=self.text): 1459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.usetabs = not self.usetabs 1460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try to prevent inconsistent indentation. 1461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # User must change indent width manually after using tabs. 1462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentwidth = 8 1463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXX this isn't bound to anything -- see tabwidth comments 1466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## def change_tabwidth_event(self, event): 1467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## new = self._asktabwidth() 1468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## if new != self.tabwidth: 1469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## self.tabwidth = new 1470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## self.set_indentation_params(0, guess=0) 1471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## return "break" 1472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def change_indentwidth_event(self, event): 1474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh new = self.askinteger( 1475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Indent width", 1476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "New indent width (2-16)\n(Always use 8 when using tabs)", 1477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent=self.text, 1478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh initialvalue=self.indentwidth, 1479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh minvalue=2, 1480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh maxvalue=16) 1481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if new and new != self.indentwidth and not self.usetabs: 1482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentwidth = new 1483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 1484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_region(self): 1486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first, last = self.get_selection_indices() 1488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if first and last: 1489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head = text.index(first + " linestart") 1490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tail = text.index(last + "-1c lineend +1c") 1491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh head = text.index("insert linestart") 1493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tail = text.index("insert lineend +1c") 1494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = text.get(head, tail) 1495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lines = chars.split("\n") 1496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return head, tail, chars, lines 1497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_region(self, head, tail, chars, lines): 1499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newchars = "\n".join(lines) 1501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if newchars == chars: 1502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.bell() 1503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 1504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.tag_remove("sel", "1.0", "end") 1505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.mark_set("insert", head) 1506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start() 1507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete(head, tail) 1508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert(head, newchars) 1509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop() 1510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.tag_add("sel", head, "insert") 1511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make string that displays as n leading blanks. 1513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _make_blanks(self, n): 1515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.usetabs: 1516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ntabs, nspaces = divmod(n, self.tabwidth) 1517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return '\t' * ntabs + ' ' * nspaces 1518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return ' ' * n 1520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Delete from beginning of line to insert point, then reinsert 1522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # column logical (meaning use tabs if appropriate) spaces. 1523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def reindent_to(self, column): 1525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = self.text 1526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_start() 1527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if text.compare("insert linestart", "!=", "insert"): 1528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.delete("insert linestart", "insert") 1529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if column: 1530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.insert("insert", self._make_blanks(column)) 1531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.undo_block_stop() 1532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _asktabwidth(self): 1534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.askinteger( 1535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Tab width", 1536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Columns per tab? (2-16)", 1537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parent=self.text, 1538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh initialvalue=self.indentwidth, 1539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh minvalue=2, 1540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh maxvalue=16) 1541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Guess indentwidth from text content. 1543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return guessed indentwidth. This should not be believed unless 1544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # it's in a reasonable range (e.g., it will be 0 if no indented 1545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # blocks are found). 1546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def guess_indent(self): 1548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh opener, indented = IndentSearcher(self.text, self.tabwidth).run() 1549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if opener and indented: 1550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, indentsmall = classifyws(opener, self.tabwidth) 1551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw, indentlarge = classifyws(indented, self.tabwidth) 1552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh indentsmall = indentlarge = 0 1554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return indentlarge - indentsmall 1555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# "line.col" -> line, as an int 1557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef index2line(index): 1558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(float(index)) 1559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Look at the leading whitespace in s. 1561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Return pair (# of leading ws characters, 1562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# effective # of leading blanks after expanding 1563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# tabs to width tabwidth) 1564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef classifyws(s, tabwidth): 1566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw = effective = 0 1567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for ch in s: 1568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if ch == ' ': 1569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw = raw + 1 1570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effective = effective + 1 1571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif ch == '\t': 1572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raw = raw + 1 1573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effective = (effective // tabwidth + 1) * tabwidth 1574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 1576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return raw, effective 1577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tokenize 1579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh_tokenize = tokenize 1580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdel tokenize 1581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass IndentSearcher(object): 1583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # .run() chews over the Text widget, looking for a block opener 1585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and the stmt following it. Returns a pair, 1586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (line containing block opener, line containing stmt) 1587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Either or both may be None. 1588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, text, tabwidth): 1590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = text 1591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.tabwidth = tabwidth 1592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.i = self.finished = 0 1593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.blkopenline = self.indentedline = None 1594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def readline(self): 1596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.finished: 1597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "" 1598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = self.i = self.i + 1 1599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mark = repr(i) + ".0" 1600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.text.compare(mark, ">=", "end"): 1601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "" 1602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.text.get(mark, mark + " lineend+1c") 1603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tokeneater(self, type, token, start, end, line, 1605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh INDENT=_tokenize.INDENT, 1606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh NAME=_tokenize.NAME, 1607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh OPENERS=('class', 'def', 'for', 'if', 'try', 'while')): 1608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.finished: 1609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 1610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif type == NAME and token in OPENERS: 1611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.blkopenline = line 1612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif type == INDENT and self.blkopenline: 1613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.indentedline = line 1614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.finished = 1 1615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def run(self): 1617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh save_tabsize = _tokenize.tabsize 1618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _tokenize.tabsize = self.tabwidth 1619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _tokenize.tokenize(self.readline, self.tokeneater) 1622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (_tokenize.TokenError, SyntaxError): 1623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # since we cut off the tokenizer early, we can trigger 1624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # spurious errors 1625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 1626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 1627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _tokenize.tabsize = save_tabsize 1628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.blkopenline, self.indentedline 1629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh### end autoindent code ### 1631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef prepstr(s): 1633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Helper to extract the underscore from a string, e.g. 1634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # prepstr("Co_py") returns (2, "Copy"). 1635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = s.find('_') 1636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if i >= 0: 1637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = s[:i] + s[i+1:] 1638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return i, s 1639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehkeynames = { 1642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'bracketleft': '[', 1643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'bracketright': ']', 1644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'slash': '/', 1645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh} 1646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef get_accelerator(keydefs, eventname): 1648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh keylist = keydefs.get(eventname) 1649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 1650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if not keylist: 1651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in { 1652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "<<open-module>>", 1653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "<<goto-line>>", 1654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "<<change-indentwidth>>"}): 1655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "" 1656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = keylist[0] 1657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) 1658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s) 1659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("Key-", "", s) 1660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu 1661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("Control-", "Ctrl-", s) 1662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("-", "+", s) 1663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("><", " ", s) 1664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub("<", "", s) 1665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = re.sub(">", "", s) 1666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return s 1667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef fixwordbreaks(root): 1670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure that Tk's double-click and next/previous word 1671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # operations use our definition of a word (i.e. an identifier) 1672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tk = root.tk 1673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded 1674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]') 1675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') 1676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test(): 1679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root = Tk() 1680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fixwordbreaks(root) 1681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root.withdraw() 1682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.argv[1:]: 1683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = sys.argv[1] 1684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 1685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = None 1686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh edit = EditorWindow(root=root, filename=filename) 1687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh edit.set_close_hook(root.quit) 1688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh edit.text.bind("<<close-all-windows>>", edit.close_event) 1689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root.mainloop() 1690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root.destroy() 1691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == '__main__': 1693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test() 1694