EditorWindow.py revision 00b0bd55b4d615740e06ac4d445221a176da30f3
17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys 27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os 3592436552816f23b585e0a8e25284eeb1d25a184Terry Jan Reedyfrom platform import python_version 47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re 57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport imp 66634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandlfrom Tkinter import * 76634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandlimport tkSimpleDialog 86634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandlimport tkMessageBox 9fd182cd9d36adefba00d86542eb3134119cdc804Kurt B. Kaiserimport webbrowser 10d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna 11d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.MultiCall import MultiCallCreator 12d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import idlever 13d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import WindowList 14d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import SearchDialog 15d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import GrepDialog 16d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import ReplaceDialog 17d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import PyParse 18d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.configHandler import idleConf 19d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import aboutDialog, textView, configDialog 20d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import macosxSupport 217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# The default tab setting for a Text widget, in average-width characters. 237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David SchererTK_TABWIDTH_DEFAULT = 8 247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 25f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiserdef _sphinx_version(): 26f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser "Format sys.version_info to produce the Sphinx version string used to install the chm docs" 27f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser major, minor, micro, level, serial = sys.version_info 28f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser release = '%s%s' % (major, minor) 29f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser if micro: 30fb23463139a173062031df9c258ac772b56ae08dBenjamin Peterson release += '%s' % (micro,) 31fb23463139a173062031df9c258ac772b56ae08dBenjamin Peterson if level == 'candidate': 32fb23463139a173062031df9c258ac772b56ae08dBenjamin Peterson release += 'rc%s' % (serial,) 33fb23463139a173062031df9c258ac772b56ae08dBenjamin Peterson elif level != 'final': 34f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser release += '%s%s' % (level[0], serial) 35f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser return release 36f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser 37220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiserdef _find_module(fullname, path=None): 38220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser """Version of imp.find_module() that handles hierarchical module names""" 39220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser 40220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser file = None 41220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser for tgt in fullname.split('.'): 42220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser if file is not None: 43220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser file.close() # close intermediate files 44220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser (file, filename, descr) = imp.find_module(tgt, path) 45220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser if descr[2] == imp.PY_SOURCE: 46220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser break # find but not load the source file 47220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser module = imp.load_module(tgt, file, filename, descr) 4869e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser try: 4969e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser path = module.__path__ 5069e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser except AttributeError: 5169e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser raise ImportError, 'No source for module ' + module.__name__ 52179816df59744313693d21525046d1d38af9119cRaymond Hettinger if descr[2] != imp.PY_SOURCE: 53179816df59744313693d21525046d1d38af9119cRaymond Hettinger # If all of the above fails and didn't raise an exception,fallback 54179816df59744313693d21525046d1d38af9119cRaymond Hettinger # to a straight import which can find __init__.py in a package. 55179816df59744313693d21525046d1d38af9119cRaymond Hettinger m = __import__(fullname) 56179816df59744313693d21525046d1d38af9119cRaymond Hettinger try: 57179816df59744313693d21525046d1d38af9119cRaymond Hettinger filename = m.__file__ 58179816df59744313693d21525046d1d38af9119cRaymond Hettinger except AttributeError: 59179816df59744313693d21525046d1d38af9119cRaymond Hettinger pass 60179816df59744313693d21525046d1d38af9119cRaymond Hettinger else: 61179816df59744313693d21525046d1d38af9119cRaymond Hettinger file = None 62179816df59744313693d21525046d1d38af9119cRaymond Hettinger base, ext = os.path.splitext(filename) 63179816df59744313693d21525046d1d38af9119cRaymond Hettinger if ext == '.pyc': 64179816df59744313693d21525046d1d38af9119cRaymond Hettinger ext = '.py' 65179816df59744313693d21525046d1d38af9119cRaymond Hettinger filename = base + ext 66179816df59744313693d21525046d1d38af9119cRaymond Hettinger descr = filename, None, imp.PY_SOURCE 67220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return file, filename, descr 68220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser 69adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 70adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedyclass HelpDialog(object): 71adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 72adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy def __init__(self): 73adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.parent = None # parent of help window 74adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.dlg = None # the help window iteself 75adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 76adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy def display(self, parent, near=None): 77adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy """ Display the help dialog. 78adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 79adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy parent - parent widget for the help window 80adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 81adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy near - a Toplevel widget (e.g. EditorWindow or PyShell) 82adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy to use as a reference for placing the help window 83adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy """ 84adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy if self.dlg is None: 85adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.show_dialog(parent) 86adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy if near: 87adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.nearwindow(near) 88adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 89adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy def show_dialog(self, parent): 90adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.parent = parent 91adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') 92adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.dlg = dlg = textView.view_file(parent,'Help',fn, modal=False) 93adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg.bind('<Destroy>', self.destroy, '+') 94adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 95adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy def nearwindow(self, near): 96adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy # Place the help dialog near the window specified by parent. 97adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy # Note - this may not reposition the window in Metacity 98adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy # if "/apps/metacity/general/disable_workarounds" is enabled 99adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg = self.dlg 100adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy geom = (near.winfo_rootx() + 10, near.winfo_rooty() + 10) 101adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg.withdraw() 102adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg.geometry("=+%d+%d" % geom) 103adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg.deiconify() 104adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy dlg.lift() 105adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 106adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy def destroy(self, ev=None): 107adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.dlg = None 108adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy self.parent = None 109adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 110adb87e2677caad4cd167e4915763dda105bc982cTerry Jan ReedyhelpDialog = HelpDialog() # singleton instance 11100b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedydef _Help_dialog(parent): # wrapper for htest 11200b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy helpDialog.show_dialog(parent) 113adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 114adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy 115dcba6622f52efafa28104a07db9d5ba2b1a8d628Kurt B. Kaiserclass EditorWindow(object): 116d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib.Percolator import Percolator 117d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib.ColorDelegator import ColorDelegator 118d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib.UndoDelegator import UndoDelegator 119d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib.IOBinding import IOBinding, filesystemencoding, encoding 120d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib import Bindings 1216634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandl from Tkinter import Toplevel 122d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib.MultiStatusBar import MultiStatusBar 1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 124114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser help_url = None 1257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def __init__(self, flist=None, filename=None, key=None, root=None): 127114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if EditorWindow.help_url is None: 12884ef153c74decf0b036042b5ca3f5cb3cd785eddThomas Heller dochome = os.path.join(sys.prefix, 'Doc', 'index.html') 129114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if sys.platform.count('linux'): 130114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser # look for html docs in a couple of standard places 131114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] 132114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if os.path.isdir('/var/www/html/python/'): # "python2" rpm 133114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = '/var/www/html/python/index.html' 134114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 135114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser basepath = '/usr/share/doc/' # standard location 136114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = os.path.join(basepath, pyver, 137114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser 'Doc', 'index.html') 1388aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser elif sys.platform[:3] == 'win': 139090e636add33907d196b9899eb0f019654a055e8Kurt B. Kaiser chmfile = os.path.join(sys.prefix, 'Doc', 140f13447f3f75c7b56eec6a602b0b72a48fbbc5486Kurt B. Kaiser 'Python%s.chm' % _sphinx_version()) 14184ef153c74decf0b036042b5ca3f5cb3cd785eddThomas Heller if os.path.isfile(chmfile): 14284ef153c74decf0b036042b5ca3f5cb3cd785eddThomas Heller dochome = chmfile 14357847df4e59015c141e645b47112829cf41b582aNed Deily elif sys.platform == 'darwin': 14457847df4e59015c141e645b47112829cf41b582aNed Deily # documentation may be stored inside a python framework 14519302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren dochome = os.path.join(sys.prefix, 14619302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren 'Resources/English.lproj/Documentation/index.html') 147114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = os.path.normpath(dochome) 148114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if os.path.isfile(dochome): 149114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser EditorWindow.help_url = dochome 15019302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren if sys.platform == 'darwin': 15119302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren # Safari requires real file:-URLs 15219302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren EditorWindow.help_url = 'file://' + EditorWindow.help_url 153114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 1547b4c2beda6b54c28070a04467e22e03f90b43450Raymond Hettinger EditorWindow.help_url = "http://docs.python.org/%d.%d" % sys.version_info[:2] 155dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava currentTheme=idleConf.CurrentTheme() 1567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist = flist 1577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root = root or flist.root 1587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.root = root 159b3c4d16e688d073dae92f272d66b6efa4b70a734Kurt B. Kaiser try: 160b3c4d16e688d073dae92f272d66b6efa4b70a734Kurt B. Kaiser sys.ps1 161b3c4d16e688d073dae92f272d66b6efa4b70a734Kurt B. Kaiser except AttributeError: 162b3c4d16e688d073dae92f272d66b6efa4b70a734Kurt B. Kaiser sys.ps1 = '>>> ' 1637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.menubar = Menu(root) 164183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser self.top = top = WindowList.ListedToplevel(root, menu=self.menubar) 1650c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava if flist: 166610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser self.tkinter_vars = flist.vars 16724b07bcba350bb86c4d6ca446e1564647a199868Ezio Melotti #self.top.instance_dict makes flist.inversedict available to 16824b07bcba350bb86c4d6ca446e1564647a199868Ezio Melotti #configDialog.py so it can access all EditorWindow instances 169a2946a437ee7886e6192b9e02725b8a04cdc80aeKurt B. Kaiser self.top.instance_dict = flist.inversedict 170610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser else: 171610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser self.tkinter_vars = {} # keys: Tkinter event names 172610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser # values: Tkinter variable instances 173a2946a437ee7886e6192b9e02725b8a04cdc80aeKurt B. Kaiser self.top.instance_dict = {} 174a2946a437ee7886e6192b9e02725b8a04cdc80aeKurt B. Kaiser self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(), 1751d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava 'recent-files.lst') 1767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text_frame = text_frame = Frame(top) 1774ebbefe677f47a8e4f624737338f22e714a7e5bcMartin v. Löwis self.vbar = vbar = Scrollbar(text_frame, name='vbar') 178d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov self.width = idleConf.GetOption('main','EditorWindow','width', type='int') 179ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser text_options = { 180ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser 'name': 'text', 181ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser 'padx': 5, 182ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser 'wrap': 'none', 183ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser 'width': self.width, 184d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')} 185ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser if TkVersion >= 8.5: 186ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser # Starting with tk 8.5 we have to set the new tabstyle option 187ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser # to 'wordprocessor' to achieve the same display of tabs as in 188ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser # older tk versions. 189ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser text_options['tabstyle'] = 'wordprocessor' 190ce46511957740aa9963b95db80c764b6c346fb1dKurt B. Kaiser self.text = text = MultiCallCreator(Text)(text_frame, **text_options) 191183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser self.top.focused_widget = self.text 1927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.createmenubar() 1947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.apply_bindings() 1957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.protocol("WM_DELETE_WINDOW", self.close) 1977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.bind("<<close-window>>", self.close_event) 19857847df4e59015c141e645b47112829cf41b582aNed Deily if macosxSupport.isAquaTk(): 19917db495445ba1f6c9d360ade62471d49ceb05cfeRonald Oussoren # Command-W on editorwindows doesn't work without this. 2003075e16c516e3975b61e4356a6d64def9cc5110eRonald Oussoren text.bind('<<close-window>>', self.close_event) 2013f752ab22e369bd664bbce395099f263e3cff784R. David Murray # Some OS X systems have only one mouse button, 2023f752ab22e369bd664bbce395099f263e3cff784R. David Murray # so use control-click for pulldown menus there. 2033f752ab22e369bd664bbce395099f263e3cff784R. David Murray # (Note, AquaTk defines <2> as the right button if 2043f752ab22e369bd664bbce395099f263e3cff784R. David Murray # present and the Tk Text widget already binds <2>.) 2053f752ab22e369bd664bbce395099f263e3cff784R. David Murray text.bind("<Control-Button-1>",self.right_menu_event) 2063f752ab22e369bd664bbce395099f263e3cff784R. David Murray else: 2073f752ab22e369bd664bbce395099f263e3cff784R. David Murray # Elsewhere, use right-click for pulldown menus. 2083f752ab22e369bd664bbce395099f263e3cff784R. David Murray text.bind("<3>",self.right_menu_event) 20984f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<cut>>", self.cut) 21084f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<copy>>", self.copy) 21184f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<paste>>", self.paste) 2127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<center-insert>>", self.center_insert_event) 2137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<help>>", self.help_dialog) 2147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<python-docs>>", self.python_docs) 2157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<about-idle>>", self.about_dialog) 2163b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava text.bind("<<open-config-dialog>>", self.config_dialog) 2177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-module>>", self.open_module) 2187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<do-nothing>>", lambda event: "break") 2197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<select-all>>", self.select_all) 2207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<remove-selection>>", self.remove_selection) 221c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find>>", self.find_event) 222c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-again>>", self.find_again_event) 223c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-in-files>>", self.find_in_files_event) 224c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-selection>>", self.find_selection_event) 225c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<replace>>", self.replace_event) 226c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<goto-line>>", self.goto_line_event) 227cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<smart-backspace>>",self.smart_backspace_event) 228cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<newline-and-indent>>",self.newline_and_indent_event) 229cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<smart-indent>>",self.smart_indent_event) 230cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<indent-region>>",self.indent_region_event) 231cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<dedent-region>>",self.dedent_region_event) 232cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<comment-region>>",self.comment_region_event) 233cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<uncomment-region>>",self.uncomment_region_event) 234cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<tabify-region>>",self.tabify_region_event) 235cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<untabify-region>>",self.untabify_region_event) 236cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<toggle-tabs>>",self.toggle_tabs_event) 237cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<change-indentwidth>>",self.change_indentwidth_event) 2385ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser text.bind("<Left>", self.move_at_edge_if_selection(0)) 2395ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser text.bind("<Right>", self.move_at_edge_if_selection(1)) 2403069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser text.bind("<<del-word-left>>", self.del_word_left) 2413069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser text.bind("<<del-word-right>>", self.del_word_right) 24293cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser text.bind("<<beginning-of-line>>", self.home_callback) 2436655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 2447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if flist: 2457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer flist.inversedict[self] = key 2467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if key: 2477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer flist.dict[key] = self 248d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser text.bind("<<open-new-window>>", self.new_callback) 2497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<close-all-windows>>", self.flist.close_all_callback) 2507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-class-browser>>", self.open_class_browser) 2517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-path-browser>>", self.open_path_browser) 2527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 253898a365c276951ab2471afe2e24bbc910666d361Steven M. Gava self.set_status_bar() 2547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer vbar['command'] = text.yview 2557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer vbar.pack(side=RIGHT, fill=Y) 2567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text['yscrollcommand'] = vbar.set 257acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser fontWeight = 'normal' 258acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): 259b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='bold' 260acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), 261d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov idleConf.GetOption('main', 'EditorWindow', 262d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov 'font-size', type='int'), 263acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser fontWeight)) 2647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text_frame.pack(side=LEFT, fill=BOTH, expand=1) 2657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.pack(side=TOP, fill=BOTH, expand=1) 2667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.focus_set() 2677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2686af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # usetabs true -> literal tab characters are used by indent and 2696af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # dedent cmds, possibly mixed with spaces if 2706af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # indentwidth is not a multiple of tabwidth, 2716af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # which will cause Tabnanny to nag! 2726af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # false -> tab characters are converted to spaces by indent 2736af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # and dedent cmds, and ditto TAB keystrokes 274acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # Although use-spaces=0 can be configured manually in config-main.def, 275acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # configuration of tabs v. spaces is not supported in the configuration 276acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # dialog. IDLE promotes the preferred Python indentation: use spaces! 277acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool') 278acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser self.usetabs = not usespaces 2796af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser 2806af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # tabwidth is the display width of a literal tab character. 2816af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # CAUTION: telling Tk to use anything other than its default 2826af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # tab setting causes it to use an entirely different tabbing algorithm, 2836af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # treating tab stops as fixed distances from the left margin. 2846af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # Nobody expects this, so for now tabwidth should never be changed. 285acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser self.tabwidth = 8 # must remain 8 until Tk is fixed. 286acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser 287acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # indentwidth is the number of screen characters per indent level. 288acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # The recommended Python indentation is four spaces. 289acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser self.indentwidth = self.tabwidth 290acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser self.set_notabs_indentwidth() 2916af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser 2926af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # If context_use_ps1 is true, parsing searches back for a ps1 line; 2936af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # else searches for a popular (if, def, ...) Python stmt. 2946af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser self.context_use_ps1 = False 2956af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser 2966af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # When searching backwards for a reliable place to begin parsing, 2976af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # first start num_context_lines[0] lines back, then 2986af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # num_context_lines[1] lines back if that didn't work, and so on. 2996af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # The last value should be huge (larger than the # of lines in a 3006af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # conceivable file). 3016af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # Making the initial values larger slows things down more often. 3026af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser self.num_context_lines = 50, 500, 5000000 3036af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser 3047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per = per = self.Percolator(text) 305dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 306dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser self.undo = undo = self.UndoDelegator() 307dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser per.insertfilter(undo) 308dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser text.undo_block_start = undo.undo_block_start 309dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser text.undo_block_stop = undo.undo_block_stop 310dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser undo.set_saved_change_hook(self.saved_change_hook) 311dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 312dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser # IOBinding implements file I/O and printing functionality 3137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.io = io = self.IOBinding(self) 314dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser io.set_filename_change_hook(self.filename_change_hook) 315dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 316cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser # Create the recent files submenu 317cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser self.recent_files_menu = Menu(self.menubar) 318cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser self.menudict['file'].insert_cascade(3, label='Recent Files', 319cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser underline=0, 320cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser menu=self.recent_files_menu) 321cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser self.update_recent_files_list() 3227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 323f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.color = None # initialized below in self.ResetColorizer 3247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if filename: 325d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser if os.path.exists(filename) and not os.path.isdir(filename): 3267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer io.loadfile(filename) 3277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 3287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer io.set_filename(filename) 329f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.ResetColorizer() 3307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.saved_change_hook() 3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3326af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser self.set_indentation_params(self.ispythonsource(filename)) 3336af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser 3347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_extensions() 3357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = self.menudict.get('windows') 3377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if menu: 3387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = menu.index("end") 3397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end is None: 3407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = -1 3417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end >= 0: 3427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_separator() 3437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = end + 1 3447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.wmenu_end = end 3457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.register_callback(self.postwindowsmenu) 3467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Some abstractions so IDLE extensions are cross-IDE 3487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.askyesno = tkMessageBox.askyesno 3497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.askinteger = tkSimpleDialog.askinteger 3507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.showerror = tkMessageBox.showerror 3517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 35202c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy self._highlight_workaround() # Fix selection tags on Windows 35302c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy 35402c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy def _highlight_workaround(self): 35502c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy # On Windows, Tk removes painting of the selection 35602c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy # tags which is different behavior than on Linux and Mac. 35702c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy # See issue14146 for more information. 35802c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy if not sys.platform.startswith('win'): 35902c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy return 36002c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy 36102c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text = self.text 36202c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.event_add("<<Highlight-FocusOut>>", "<FocusOut>") 36302c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.event_add("<<Highlight-FocusIn>>", "<FocusIn>") 36402c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy def highlight_fix(focus): 36502c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy sel_range = text.tag_ranges("sel") 36602c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy if sel_range: 36702c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy if focus == 'out': 36802c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy HILITE_CONFIG = idleConf.GetHighlight( 36902c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy idleConf.CurrentTheme(), 'hilite') 37002c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.tag_config("sel_fix", HILITE_CONFIG) 37102c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.tag_raise("sel_fix") 37202c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.tag_add("sel_fix", *sel_range) 37302c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy elif focus == 'in': 37402c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.tag_remove("sel_fix", "1.0", "end") 37502c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy 37602c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.bind("<<Highlight-FocusOut>>", 37702c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy lambda ev: highlight_fix("out")) 37802c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy text.bind("<<Highlight-FocusIn>>", 37902c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy lambda ev: highlight_fix("in")) 38002c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy 38102c0ed06123d62dcf4c686e0f5bc48bac55676ccRoger Serwy 382307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis def _filename_to_unicode(self, filename): 383307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis """convert filename to unicode in order to display it in Tk""" 384307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis if isinstance(filename, unicode) or not filename: 385307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis return filename 386307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis else: 387307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis try: 388307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis return filename.decode(self.filesystemencoding) 389307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis except UnicodeDecodeError: 390307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis # XXX 391307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis try: 392307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis return filename.decode(self.encoding) 393307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis except UnicodeDecodeError: 394307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis # byte-to-byte conversion 395307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis return filename.decode('iso8859-1') 396307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis 397d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser def new_callback(self, event): 398d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser dirname, basename = self.io.defaultfilename() 399d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser self.flist.new(dirname) 400d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser return "break" 401d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser 40293cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser def home_callback(self, event): 403020d3d985698aac55383eb1a309fd6d281f58a97Kurt B. Kaiser if (event.state & 4) != 0 and event.keysym == "Home": 404020d3d985698aac55383eb1a309fd6d281f58a97Kurt B. Kaiser # state&4==Control. If <Control-Home>, use the Tk binding. 405020d3d985698aac55383eb1a309fd6d281f58a97Kurt B. Kaiser return 40693cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if self.text.index("iomark") and \ 40793cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.compare("iomark", "<=", "insert lineend") and \ 40893cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.compare("insert linestart", "<=", "iomark"): 4097548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser # In Shell on input line, go to just after prompt 41093cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser insertpt = int(self.text.index("iomark").split(".")[1]) 41193cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser else: 41293cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser line = self.text.get("insert linestart", "insert lineend") 41393cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser for insertpt in xrange(len(line)): 41493cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if line[insertpt] not in (' ','\t'): 41593cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser break 41693cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser else: 41793cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser insertpt=len(line) 41893cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser lineat = int(self.text.index("insert").split('.')[1]) 41993cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if insertpt == lineat: 42093cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser insertpt = 0 42193cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser dest = "insert linestart+"+str(insertpt)+"c" 42293cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if (event.state&1) == 0: 4237548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser # shift was not pressed 42493cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.tag_remove("sel", "1.0", "end") 42593cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser else: 42693cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if not self.text.index("sel.first"): 4277548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser self.text.mark_set("my_anchor", "insert") # there was no previous selection 4287548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser else: 4297548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")): 4307548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser self.text.mark_set("my_anchor", "sel.first") # extend back 4317548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser else: 4327548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser self.text.mark_set("my_anchor", "sel.last") # extend forward 43393cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser first = self.text.index(dest) 4347548bce0ee08a7eb1c2e88ee88799e5982ca21e9Kurt B. Kaiser last = self.text.index("my_anchor") 43593cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser if self.text.compare(first,">",last): 43693cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser first,last = last,first 43793cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.tag_remove("sel", "1.0", "end") 43893cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.tag_add("sel", first, last) 43993cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.mark_set("insert", dest) 44093cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser self.text.see("insert") 44193cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser return "break" 44293cdae5f814292da17c38374d0cfa314b96fd3beKurt B. Kaiser 4437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_status_bar(self): 444898a365c276951ab2471afe2e24bbc910666d361Steven M. Gava self.status_bar = self.MultiStatusBar(self.top) 44557847df4e59015c141e645b47112829cf41b582aNed Deily if sys.platform == "darwin": 44619302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren # Insert some padding to avoid obscuring some of the statusbar 44719302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren # by the resize widget. 44819302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren self.status_bar.set_label('_padding1', ' ', side=RIGHT) 4497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('column', 'Col: ?', side=RIGHT) 4507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('line', 'Ln: ?', side=RIGHT) 4517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.pack(side=BOTTOM, fill=X) 452b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self.text.bind("<<set-line-and-column>>", self.set_line_and_column) 453b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self.text.event_add("<<set-line-and-column>>", 454b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser "<KeyRelease>", "<ButtonRelease>") 4557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.after_idle(self.set_line_and_column) 4567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_line_and_column(self, event=None): 458220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser line, column = self.text.index(INSERT).split('.') 4597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('column', 'Col: %s' % column) 4607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('line', 'Ln: %s' % line) 4617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu_specs = [ 4637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("file", "_File"), 4647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("edit", "_Edit"), 4657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("format", "F_ormat"), 4667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("run", "_Run"), 4671061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser ("options", "_Options"), 4687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("windows", "_Windows"), 4697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("help", "_Help"), 4707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ] 4717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 47257847df4e59015c141e645b47112829cf41b582aNed Deily if sys.platform == "darwin": 47319302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren menu_specs[-2] = ("windows", "_Window") 47419302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren 47519302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren 4767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def createmenubar(self): 4777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer mbar = self.menubar 4787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.menudict = menudict = {} 4797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name, label in self.menu_specs: 4807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer underline, label = prepstr(label) 4817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menudict[name] = menu = Menu(mbar, name=name) 4827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer mbar.add_cascade(label=label, menu=menu, underline=underline) 48319302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren 48457847df4e59015c141e645b47112829cf41b582aNed Deily if macosxSupport.isCarbonTk(): 48519302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren # Insert the application menu 48619302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren menudict['application'] = menu = Menu(mbar, name='apple') 48719302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren mbar.add_cascade(label='IDLE', menu=menu) 48819302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren 4897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.fill_menus() 4908e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.base_helpmenu_length = self.menudict['help'].index(END) 4918e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.reset_help_menu_entries() 4927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def postwindowsmenu(self): 4947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Only called when Windows menu exists 4957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = self.menudict['windows'] 4967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = menu.index("end") 4977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end is None: 4987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = -1 4997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end > self.wmenu_end: 5007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.delete(self.wmenu_end+1, end) 5017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.add_windows_to_menu(menu) 5027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = None 5047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def right_menu_event(self, event): 5067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) 5077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.rmenu: 5087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.make_rmenu() 5097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = self.rmenu 5107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.event = event 5117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer iswin = sys.platform[:3] == 'win' 5127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if iswin: 5137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.config(cursor="arrow") 5145018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov 515231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy for item in self.rmenu_specs: 516231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy try: 517231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy label, eventname, verify_state = item 518231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy except ValueError: # see issue1207589 519231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy continue 520231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy 5215018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov if verify_state is None: 5225018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov continue 5235018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov state = getattr(self, verify_state)() 5245018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov rmenu.entryconfigure(label, state=state) 5255018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov 5267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu.tk_popup(event.x_root, event.y_root) 5277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if iswin: 5287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.config(cursor="ibeam") 5297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu_specs = [ 5315018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov # ("Label", "<<virtual-event>>", "statefuncname"), ... 5325018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov ("Close", "<<close-window>>", None), # Example 5337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ] 5347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def make_rmenu(self): 5367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = Menu(self.text, tearoff=0) 537231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy for item in self.rmenu_specs: 538231a8fd22dcb60b2090e05029a536df73ef44373Roger Serwy label, eventname = item[0], item[1] 5395018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov if label is not None: 5405018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov def command(text=self.text, eventname=eventname): 5415018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov text.event_generate(eventname) 5425018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov rmenu.add_command(label=label, command=command) 5435018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov else: 5445018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov rmenu.add_separator() 5457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.rmenu = rmenu 5467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5475018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov def rmenu_check_cut(self): 5485018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov return self.rmenu_check_copy() 5495018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov 5505018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov def rmenu_check_copy(self): 5515018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov try: 5525018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov indx = self.text.index('sel.first') 5535018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov except TclError: 5545018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov return 'disabled' 5555018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov else: 5565018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov return 'normal' if indx else 'disabled' 5575018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov 5585018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov def rmenu_check_paste(self): 5595018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov try: 5605018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') 5615018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov except TclError: 5625018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov return 'disabled' 5635018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov else: 5645018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov return 'normal' 5655018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov 5667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def about_dialog(self, event=None): 567d78b23025c9c9f6288e14112411d83f44bcf85a8Kurt B. Kaiser aboutDialog.AboutDialog(self.top,'About IDLE') 5686655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 5693b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava def config_dialog(self, event=None): 5703b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava configDialog.ConfigDialog(self.top,'Settings') 5716655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 5727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def help_dialog(self, event=None): 573adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy if self.root: 574adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy parent = self.root 575adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy else: 576adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy parent = self.top 577adb87e2677caad4cd167e4915763dda105bc982cTerry Jan Reedy helpDialog.display(parent, near=self.top) 5786655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 579114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser def python_docs(self, event=None): 5808aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser if sys.platform[:3] == 'win': 581247327a27e622a344787464fea404dd73bc71c50Terry Reedy try: 582247327a27e622a344787464fea404dd73bc71c50Terry Reedy os.startfile(self.help_url) 583247327a27e622a344787464fea404dd73bc71c50Terry Reedy except WindowsError as why: 584247327a27e622a344787464fea404dd73bc71c50Terry Reedy tkMessageBox.showerror(title='Document Start Failure', 585247327a27e622a344787464fea404dd73bc71c50Terry Reedy message=str(why), parent=self.text) 586114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 587114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser webbrowser.open(self.help_url) 5888aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser return "break" 5897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 59084f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def cut(self,event): 59184f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Cut>>") 59284f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 59384f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 59484f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def copy(self,event): 595b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser if not self.text.tag_ranges("sel"): 596b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser # There is no selection, so do nothing and maybe interrupt. 597b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser return 59884f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Copy>>") 59984f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 60084f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 60184f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def paste(self,event): 60284f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Paste>>") 603631fee62351397e940e4616ef48f03788962c3ebKurt B. Kaiser self.text.see("insert") 60484f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 60584f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 6067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def select_all(self, event=None): 6077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_add("sel", "1.0", "end-1c") 6087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "1.0") 6097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.see("insert") 6107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "break" 6117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def remove_selection(self, event=None): 6137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_remove("sel", "1.0", "end") 6147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.see("insert") 6157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6165ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser def move_at_edge_if_selection(self, edge_index): 6175ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser """Cursor move begins at start or end of selection 6185ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 6195ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser When a left/right cursor key is pressed create and return to Tkinter a 6205ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser function which causes a cursor move from the associated edge of the 6215ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser selection. 6225ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 6235ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser """ 6245ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_index = self.text.index 6255ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_mark_set = self.text.mark_set 6265ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser edges_table = ("sel.first+1c", "sel.last-1c") 6275ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser def move_at_edge(event): 6285ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed 6295ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser try: 6305ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_index("sel.first") 6315ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_mark_set("insert", edges_table[edge_index]) 6325ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser except TclError: 6335ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser pass 6345ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser return move_at_edge 6355ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 6363069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser def del_word_left(self, event): 6373069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser self.text.event_generate('<Meta-Delete>') 6383069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser return "break" 6393069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser 6403069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser def del_word_right(self, event): 6413069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser self.text.event_generate('<Meta-d>') 6423069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser return "break" 6433069dbb8ec9c287c2ff6b3a1c8bfde83af81c11bKurt B. Kaiser 644c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_event(self, event): 645c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find(self.text) 646c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 647c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 648c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_again_event(self, event): 649c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find_again(self.text) 650c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 651c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 652c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_selection_event(self, event): 653c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find_selection(self.text) 654c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 655c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 656c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_in_files_event(self, event): 657c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava GrepDialog.grep(self.text, self.io, self.flist) 658c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 659c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 660c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def replace_event(self, event): 661c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava ReplaceDialog.replace(self.text) 662c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 663c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 664c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def goto_line_event(self, event): 665c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text = self.text 666c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava lineno = tkSimpleDialog.askinteger("Goto", 667c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava "Go to line number:",parent=text) 668c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava if lineno is None: 669c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 670c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava if lineno <= 0: 671c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bell() 672c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 673c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.mark_set("insert", "%d.0" % lineno) 674c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.see("insert") 675c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 6767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_module(self, event=None): 6777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX Shouldn't this be in IOBinding or in FileList? 6787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 6797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name = self.text.get("sel.first", "sel.last") 6807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except TclError: 6817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name = "" 6827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 683220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser name = name.strip() 684852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum name = tkSimpleDialog.askstring("Module", 685852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum "Enter the name of a Python module\n" 686852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum "to search on sys.path and open:", 687852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum parent=self.text, initialvalue=name) 688852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum if name: 689852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum name = name.strip() 6907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not name: 691852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum return 6927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX Ought to insert current file's directory in front of path 6937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 694220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser (f, file, (suffix, mode, type)) = _find_module(name) 6952b149860a052606500cc4293db29cde5c85bf288Terry Jan Reedy except (NameError, ImportError) as msg: 6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror("Import error", str(msg), parent=self.text) 6977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 6987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if type != imp.PY_SOURCE: 6997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror("Unsupported type", 7007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "%s is not a source module" % name, parent=self.text) 7017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 7027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if f: 7037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f.close() 7047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 7057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist.open(file) 7067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 7077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.io.loadfile(file) 7087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_class_browser(self, event=None): 7107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = self.io.filename 7117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not filename: 7127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror( 7137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "No filename", 7147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "This buffer has no associated filename", 7157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer master=self.text) 7167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.focus_set() 7177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return None 7187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer head, tail = os.path.split(filename) 7197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer base, ext = os.path.splitext(tail) 720d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib import ClassBrowser 7217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ClassBrowser.ClassBrowser(self.flist, base, [head]) 7227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_path_browser(self, event=None): 724d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna from idlelib import PathBrowser 7257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer PathBrowser.PathBrowser(self.flist) 7267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def gotoline(self, lineno): 7287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if lineno is not None and lineno > 0: 7297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "%d.0" % lineno) 7307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_remove("sel", "1.0", "end") 7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_add("sel", "insert", "insert +1l") 7327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.center() 7337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def ispythonsource(self, filename): 735df506ea98b1c9424634c6063e90a664ac9127164Kurt B. Kaiser if not filename or os.path.isdir(filename): 736220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return True 7377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer base, ext = os.path.splitext(os.path.basename(filename)) 7387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if os.path.normcase(ext) in (".py", ".pyw"): 739220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return True 7407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 7417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f = open(filename) 7427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer line = f.readline() 7437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f.close() 7447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except IOError: 745220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return False 74683a3560527f9e62bce6adbc12b8ff6b57be8b1acKurt B. Kaiser return line.startswith('#!') and line.find('python') >= 0 7477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close_hook(self): 7497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 7500b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.flist.unregister_maybe_terminate(self) 7510b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.flist = None 7527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_close_hook(self, close_hook): 7547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.close_hook = close_hook 7557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def filename_change_hook(self): 7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 7587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist.filename_changed_edit(self) 7597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.saved_change_hook() 760260cb9034c861fa159f26fba8679ac265af47109Kurt B. Kaiser self.top.update_windowlist_registry(self) 761f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.ResetColorizer() 7627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 763f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser def _addcolorizer(self): 7647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 7657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 766f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser if self.ispythonsource(self.io.filename): 767f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.color = self.ColorDelegator() 768f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser # can add more colorizers here... 769f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser if self.color: 770f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.per.removefilter(self.undo) 771f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.per.insertfilter(self.color) 772f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.per.insertfilter(self.undo) 7737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 774f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser def _rmcolorizer(self): 7757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.color: 7767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 777df506ea98b1c9424634c6063e90a664ac9127164Kurt B. Kaiser self.color.removecolors() 7787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.removefilter(self.color) 7797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.color = None 7806655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 781b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava def ResetColorizer(self): 782f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser "Update the colour theme" 783f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser # Called from self.filename_change_hook and from configDialog.py 784f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self._rmcolorizer() 785f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self._addcolorizer() 78673360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser theme = idleConf.GetOption('main','Theme','name') 787f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser normal_colors = idleConf.GetHighlight(theme, 'normal') 788f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') 789f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser select_colors = idleConf.GetHighlight(theme, 'hilite') 790f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser self.text.config( 791f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser foreground=normal_colors['foreground'], 792f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser background=normal_colors['background'], 793f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser insertbackground=cursor_color, 794f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser selectforeground=select_colors['foreground'], 795f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser selectbackground=select_colors['background'], 796f05fa33a6c42bc21ffdfe7a20226a2b9a83ac3c2Kurt B. Kaiser ) 7977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 798b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava def ResetFont(self): 7996655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser "Update the text widgets' font if it is changed" 80083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser # Called from configDialog.py 801b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='normal' 802b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): 803b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='bold' 804b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 805d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov idleConf.GetOption('main','EditorWindow','font-size', 806d8590ff209369f45a5ed417c79ce255a33f70a1dAndrew Svetlov type='int'), 807b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight)) 808b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava 809b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser def RemoveKeybindings(self): 810b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser "Remove the keybindings before they are changed." 81183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser # Called from configDialog.py 8125a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() 813dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for event, keylist in keydefs.items(): 814b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self.text.event_delete(event, *keylist) 815b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser for extensionName in self.get_standard_extension_names(): 8165a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser xkeydefs = idleConf.GetExtensionBindings(extensionName) 8175a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser if xkeydefs: 8185a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser for event, keylist in xkeydefs.items(): 819b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self.text.event_delete(event, *keylist) 820b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser 821b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser def ApplyKeybindings(self): 822b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser "Update the keybindings after they are changed" 823b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser # Called from configDialog.py 8245a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() 825dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava self.apply_bindings() 826b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser for extensionName in self.get_standard_extension_names(): 8275a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser xkeydefs = idleConf.GetExtensionBindings(extensionName) 8285a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser if xkeydefs: 8295a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser self.apply_bindings(xkeydefs) 830dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava #update menu accelerators 8315a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser menuEventDict = {} 832dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for menu in self.Bindings.menudefs: 8335a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser menuEventDict[menu[0]] = {} 834dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for item in menu[1]: 835dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if item: 8365a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1] 837dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for menubarItem in self.menudict.keys(): 8385a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser menu = self.menudict[menubarItem] 83914ef0c8d6bb1794910e815fb3c61d22cc966a49eNed Deily end = menu.index(END) 84014ef0c8d6bb1794910e815fb3c61d22cc966a49eNed Deily if end is None: 84114ef0c8d6bb1794910e815fb3c61d22cc966a49eNed Deily # Skip empty menus 84214ef0c8d6bb1794910e815fb3c61d22cc966a49eNed Deily continue 84314ef0c8d6bb1794910e815fb3c61d22cc966a49eNed Deily end += 1 8445a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser for index in range(0, end): 8455a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser if menu.type(index) == 'command': 8465a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser accel = menu.entrycget(index, 'accelerator') 847dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if accel: 8485a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser itemName = menu.entrycget(index, 'label') 8495a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser event = '' 8506e3dbbdf39f3b4eb6f18c0165e446df17218b7dcBenjamin Peterson if menubarItem in menuEventDict: 8516e3dbbdf39f3b4eb6f18c0165e446df17218b7dcBenjamin Peterson if itemName in menuEventDict[menubarItem]: 8525a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser event = menuEventDict[menubarItem][itemName] 853dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if event: 8545a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser accel = get_accelerator(keydefs, event) 8555a67f9b815fdd34617395c6ec5d9a679361b76eaKurt B. Kaiser menu.entryconfig(index, accelerator=accel) 856dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava 857acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser def set_notabs_indentwidth(self): 858acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser "Update the indentwidth if changed and not using tabs in this window" 859acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser # Called from configDialog.py 860acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser if not self.usetabs: 861acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces', 862acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser type='int') 863acdef858a51f32d2b2c82f3d47025cb26c2a63eeKurt B. Kaiser 8648e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def reset_help_menu_entries(self): 8658e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser "Update the additional help entries on the Help menu" 8668e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser help_list = idleConf.GetAllExtraHelpSourcesList() 8678e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu = self.menudict['help'] 8688e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # first delete the extra help entries, if any 8698e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu_length = helpmenu.index(END) 8708e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser if helpmenu_length > self.base_helpmenu_length: 8718e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) 8728e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # then rebuild them 8738e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser if help_list: 8748e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.add_separator() 8758e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser for entry in help_list: 8768e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser cmd = self.__extra_help_callback(entry[1]) 8778e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.add_command(label=entry[0], command=cmd) 8788e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # and update the menu dictionary 8798e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.menudict['help'] = helpmenu 8808e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser 8818e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def __extra_help_callback(self, helpfile): 8828e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser "Create a callback with the helpfile value frozen at definition time" 8838e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def display_extra_help(helpfile=helpfile): 884b2afe855e5d75a570707d6bf0e32206e4b7b1c4dGeorg Brandl if not helpfile.startswith(('www', 'http')): 885247327a27e622a344787464fea404dd73bc71c50Terry Reedy helpfile = os.path.normpath(helpfile) 8868aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser if sys.platform[:3] == 'win': 887247327a27e622a344787464fea404dd73bc71c50Terry Reedy try: 888247327a27e622a344787464fea404dd73bc71c50Terry Reedy os.startfile(helpfile) 889247327a27e622a344787464fea404dd73bc71c50Terry Reedy except WindowsError as why: 890247327a27e622a344787464fea404dd73bc71c50Terry Reedy tkMessageBox.showerror(title='Document Start Failure', 891247327a27e622a344787464fea404dd73bc71c50Terry Reedy message=str(why), parent=self.text) 8928aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser else: 8938aa23927e339ca13459dd408751546352d81fefaKurt B. Kaiser webbrowser.open(helpfile) 8948e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser return display_extra_help 8956655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 896cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser def update_recent_files_list(self, new_file=None): 897cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser "Load and update the recent files list and menus" 898cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list = [] 899cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser if os.path.exists(self.recent_files_path): 900f9489436041b319ffab52eb1769d11849d68129dTerry Jan Reedy with open(self.recent_files_path, 'r') as rf_list_file: 901cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list = rf_list_file.readlines() 902cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser if new_file: 903cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser new_file = os.path.abspath(new_file) + '\n' 904cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser if new_file in rf_list: 905cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list.remove(new_file) # move to top 906cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list.insert(0, new_file) 907cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser # clean and save the recent files list 908cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser bad_paths = [] 909cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser for path in rf_list: 910cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser if '\0' in path or not os.path.exists(path[0:-1]): 911cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser bad_paths.append(path) 912cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list = [path for path in rf_list if path not in bad_paths] 913cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser ulchars = "1234567890ABCDEFGHIJK" 914cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser rf_list = rf_list[0:len(ulchars)] 9151d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava try: 91640ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily with open(self.recent_files_path, 'w') as rf_file: 91740ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily rf_file.writelines(rf_list) 91840ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily except IOError as err: 91940ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily if not getattr(self.root, "recentfilelist_error_displayed", False): 92040ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily self.root.recentfilelist_error_displayed = True 92140ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily tkMessageBox.showerror(title='IDLE Error', 92240ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily message='Unable to update Recent Files list:\n%s' 92340ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily % str(err), 92440ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily parent=self.text) 925cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser # for each edit window instance, construct the recent files menu 926cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser for instance in self.top.instance_dict.keys(): 927cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser menu = instance.recent_files_menu 9287148984d61b5677af1ee090e52c1cba08299c9f9Ned Deily menu.delete(0, END) # clear, and rebuild: 92986b882f3a6978cf359dfedcf1193bd930f024780Guilherme Polo for i, file_name in enumerate(rf_list): 93086b882f3a6978cf359dfedcf1193bd930f024780Guilherme Polo file_name = file_name.rstrip() # zap \n 931307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis # make unicode string to display non-ASCII chars correctly 932307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis ufile_name = self._filename_to_unicode(file_name) 933cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser callback = instance.__recent_file_callback(file_name) 934307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis menu.add_command(label=ulchars[i] + " " + ufile_name, 935cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser command=callback, 936cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser underline=0) 937cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser 938cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser def __recent_file_callback(self, file_name): 939cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser def open_recent_file(fn_closure=file_name): 940cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser self.io.open(editFile=fn_closure) 941cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser return open_recent_file 9426655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 9437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def saved_change_hook(self): 9447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer short = self.short_title() 9457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer long = self.long_title() 9467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if short and long: 9477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = short + " - " + long 9487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer elif short: 9497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = short 9507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer elif long: 9517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = long 9527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 9537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = "Untitled" 9547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer icon = short or long or title 9557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.get_saved(): 9567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = "*%s*" % title 9577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer icon = "*%s" % icon 9587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_title(title) 9597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_iconname(icon) 9607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_saved(self): 9627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.undo.get_saved() 9637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_saved(self, flag): 9657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.undo.set_saved(flag) 9667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def reset_undo(self): 9687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.undo.reset_undo() 9697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def short_title(self): 971592436552816f23b585e0a8e25284eeb1d25a184Terry Jan Reedy pyversion = "Python " + python_version() + ": " 9727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = self.io.filename 9737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if filename: 9747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = os.path.basename(filename) 975592436552816f23b585e0a8e25284eeb1d25a184Terry Jan Reedy else: 976592436552816f23b585e0a8e25284eeb1d25a184Terry Jan Reedy filename = "Untitled" 977307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis # return unicode string to display non-ASCII chars correctly 978592436552816f23b585e0a8e25284eeb1d25a184Terry Jan Reedy return pyversion + self._filename_to_unicode(filename) 9797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def long_title(self): 981307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis # return unicode string to display non-ASCII chars correctly 982307021f40b227d2bf114b536c37cc41e03fc2affMartin v. Löwis return self._filename_to_unicode(self.io.filename or "") 9837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def center_insert_event(self, event): 9857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.center() 9867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def center(self, mark="insert"): 9887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 9897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top, bot = self.getwindowlines() 9907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer lineno = self.getlineno(mark) 9917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer height = bot - top 992220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser newtop = max(1, lineno - height//2) 9937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.yview(float(newtop)) 9947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 9957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getwindowlines(self): 9967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 9977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top = self.getlineno("@0,0") 9987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer bot = self.getlineno("@0,65535") 9997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if top == bot and text.winfo_height() == 1: 10007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Geometry manager hasn't run yet 10017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer height = int(text['height']) 10027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer bot = top + height - 1 10037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return top, bot 10047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getlineno(self, mark="insert"): 10067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 10077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return int(float(text.index(mark))) 10087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10091061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser def get_geometry(self): 10101061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser "Return (width, height, x, y)" 10111061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser geom = self.top.wm_geometry() 10121061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) 10131061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser tuple = (map(int, m.groups())) 10141061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser return tuple 10151061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser 10167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close_event(self, event): 10177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.close() 10187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def maybesave(self): 10207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.io: 102167716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava if not self.get_saved(): 10226655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser if self.top.state()!='normal': 102367716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.deiconify() 102467716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.lower() 102567716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.lift() 10267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.io.maybesave() 10277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close(self): 10297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer reply = self.maybesave() 1030a398e2d0592464b6594bac0e4ee3ef091cce5159Matthias Klose if str(reply) != "cancel": 10317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self._close() 10327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return reply 10337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def _close(self): 10351d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if self.io.filename: 1036cf6f1b69eb5f491dd3cba6c5c90bcb344d4b3a96Kurt B. Kaiser self.update_recent_files_list(new_file=self.io.filename) 10377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.unregister_callback(self.postwindowsmenu) 10387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.unload_extensions() 10390b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.io.close() 10400b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.io = None 10410b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.undo = None 10427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 10430b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.color.close(False) 10440b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.color = None 10457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text = None 1046610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser self.tkinter_vars = None 10470b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.per.close() 10480b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.per = None 10490b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.top.destroy() 10500b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser if self.close_hook: 10510b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser # unless override: unregister from flist, terminate if last window 10520b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser self.close_hook() 10537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_extensions(self): 10557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions = {} 10567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_standard_extensions() 10577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def unload_extensions(self): 10597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for ins in self.extensions.values(): 10607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(ins, "close"): 10617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ins.close() 10627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions = {} 10637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_standard_extensions(self): 10657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name in self.get_standard_extension_names(): 10667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 10677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_extension(name) 10687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except: 106970a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald print "Failed to load extension", repr(name) 10707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer import traceback 10717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer traceback.print_exc() 10727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_standard_extension_names(self): 10744d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser return idleConf.GetExtensions(editor_only=True) 10757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 10767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_extension(self, name): 1077b00e89faab0d69feb040118bbc5ea6149e91867fKurt B. Kaiser try: 1078b00e89faab0d69feb040118bbc5ea6149e91867fKurt B. Kaiser mod = __import__(name, globals(), locals(), []) 1079b00e89faab0d69feb040118bbc5ea6149e91867fKurt B. Kaiser except ImportError: 1080b00e89faab0d69feb040118bbc5ea6149e91867fKurt B. Kaiser print "\nFailed to import extension: ", name 1081b00e89faab0d69feb040118bbc5ea6149e91867fKurt B. Kaiser return 10827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer cls = getattr(mod, name) 10834d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser keydefs = idleConf.GetExtensionBindings(name) 10844d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser if hasattr(cls, "menudefs"): 10854d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser self.fill_menus(cls.menudefs, keydefs) 10867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ins = cls(self) 10877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions[name] = ins 10887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs: 10897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.apply_bindings(keydefs) 10907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for vevent in keydefs.keys(): 1091220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser methodname = vevent.replace("-", "_") 10927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer while methodname[:1] == '<': 10937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname[1:] 10947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer while methodname[-1:] == '>': 10957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname[:-1] 10967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname + "_event" 10977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(ins, methodname): 10987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.bind(vevent, getattr(ins, methodname)) 10997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def apply_bindings(self, keydefs=None): 11017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs is None: 11027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer keydefs = self.Bindings.default_keydefs 11037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 11047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.keydefs = keydefs 11057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for event, keylist in keydefs.items(): 11067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keylist: 1107931237e2e66975c54e2ac6c5e503ee2992a22bcfRaymond Hettinger text.event_add(event, *keylist) 11087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1109610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser def fill_menus(self, menudefs=None, keydefs=None): 111083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser """Add appropriate entries to the menus and submenus 111183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser 111283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser Menus that are absent or None in self.menudict are ignored. 111383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser """ 1114610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser if menudefs is None: 1115610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser menudefs = self.Bindings.menudefs 11167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs is None: 11177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer keydefs = self.Bindings.default_keydefs 11187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menudict = self.menudict 11197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 1120610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser for mname, entrylist in menudefs: 11217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = menudict.get(mname) 11227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not menu: 11237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer continue 1124610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser for entry in entrylist: 1125610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser if not entry: 11267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_separator() 11277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1128610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser label, eventname = entry 11297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer checkbutton = (label[:1] == '!') 11307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if checkbutton: 11317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer label = label[1:] 11327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer underline, label = prepstr(label) 1133610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser accelerator = get_accelerator(keydefs, eventname) 1134610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser def command(text=text, eventname=eventname): 1135610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser text.event_generate(eventname) 11367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if checkbutton: 1137610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser var = self.get_var_obj(eventname, BooleanVar) 11387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_checkbutton(label=label, underline=underline, 11397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer command=command, accelerator=accelerator, 11407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer variable=var) 11417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 11427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_command(label=label, underline=underline, 114384f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser command=command, 114484f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser accelerator=accelerator) 11457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getvar(self, name): 1147610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser var = self.get_var_obj(name) 11487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if var: 1149610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser value = var.get() 1150610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser return value 1151610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser else: 1152610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser raise NameError, name 11537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def setvar(self, name, value, vartype=None): 1155610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser var = self.get_var_obj(name, vartype) 11567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if var: 11577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var.set(value) 1158610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser else: 1159610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser raise NameError, name 11607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1161610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser def get_var_obj(self, name, vartype=None): 1162610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser var = self.tkinter_vars.get(name) 11637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not var and vartype: 1164610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser # create a Tkinter variable object with self.text as master: 1165610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser self.tkinter_vars[name] = var = vartype(self.text) 11667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return var 11677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Tk implementations of "virtual text methods" -- each platform 11697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # reusing IDLE's support code needs to define these for its GUI's 11707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # flavor of widget. 11717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Is character at text_index in a Python string? Return 0 for 11737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # "guaranteed no", true for anything else. This info is expensive 11747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # to compute ab initio, but is probably already known by the 11757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # platform's colorizer. 11767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def is_char_in_string(self, text_index): 11787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 11797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Return true iff colorizer hasn't (re)gotten this far 11807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # yet, or the character is tagged as being in a string 11817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.text.tag_prevrange("TODO", text_index) or \ 11827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "STRING" in self.text.tag_names(text_index) 11837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 11847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # The colorizer is missing: assume the worst 11857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 1 11867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # If a selection is defined in the text widget, return (start, 11887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # end) as Tkinter text indices, otherwise return (None, None) 11897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_selection_indices(self): 11907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 11917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer first = self.text.index("sel.first") 11927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer last = self.text.index("sel.last") 11937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return first, last 11947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except TclError: 11957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return None, None 11967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 11977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Return the text widget's current view of what a tab stop means 11987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # (equivalent width in spaces). 11997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 12007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_tabwidth(self): 12017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer current = self.text['tabs'] or TK_TABWIDTH_DEFAULT 12027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return int(current) 12037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 12047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Set the text widget's current view of what a tab stop means. 12057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 12067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_tabwidth(self, newtabwidth): 12077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 12087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.get_tabwidth() != newtabwidth: 12097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer pixels = text.tk.call("font", "measure", text["font"], 12107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "-displayof", text.master, 1211afdf71b9eefdfb5904e40602984836b28318bad0Kurt B. Kaiser "n" * newtabwidth) 12127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.configure(tabs=pixels) 12137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1214cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # If ispythonsource and guess are true, guess a good value for 1215cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth based on file content (if possible), and if 1216cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth != tabwidth set usetabs false. 1217cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # In any case, adjust the Text widget's view of what a tab 1218cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # character means. 1219cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 12206af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser def set_indentation_params(self, ispythonsource, guess=True): 1221cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if guess and ispythonsource: 1222cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = self.guess_indent() 1223cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if 2 <= i <= 8: 1224cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentwidth = i 1225cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.indentwidth != self.tabwidth: 12266af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser self.usetabs = False 1227cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_tabwidth(self.tabwidth) 1228cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1229cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def smart_backspace_event(self, event): 1230cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1231cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1232cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1233cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 1234cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 1235cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1236cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Delete whitespace left, until hitting a real char or closest 1237cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # preceding virtual tab stop. 1238cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = text.get("insert linestart", "insert") 1239cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if chars == '': 1240cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if text.compare("insert", ">", "1.0"): 1241cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # easy: delete preceding newline 1242cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-1c") 1243cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1244cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bell() # at start of buffer 1245cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1246cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if chars[-1] not in " \t": 1247cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # easy: delete preceding real char 1248cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-1c") 1249cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1250cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Ick. It may require *inserting* spaces if we back up over a 1251cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # tab character! This is written to be clear, not fast. 12521b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser tabwidth = self.tabwidth 12531b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser have = len(chars.expandtabs(tabwidth)) 1254cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser assert have > 0 1255cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser want = ((have - 1) // self.indentwidth) * self.indentwidth 12564ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # Debug prompt is multilined.... 12578ef4a70a48daa451fca6d59a6129f49389e5b0feTerry Jan Reedy if self.context_use_ps1: 12588ef4a70a48daa451fca6d59a6129f49389e5b0feTerry Jan Reedy last_line_of_prompt = sys.ps1.split('\n')[-1] 12598ef4a70a48daa451fca6d59a6129f49389e5b0feTerry Jan Reedy else: 12608ef4a70a48daa451fca6d59a6129f49389e5b0feTerry Jan Reedy last_line_of_prompt = '' 1261cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ncharsdeleted = 0 1262cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while 1: 12634ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser if chars == last_line_of_prompt: 12641bdca5e051a5424aaaaf7968c710d31132a6c335Kurt B. Kaiser break 1265cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = chars[:-1] 1266cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ncharsdeleted = ncharsdeleted + 1 12671b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser have = len(chars.expandtabs(tabwidth)) 1268cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if have <= want or chars[-1] not in " \t": 1269cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser break 1270cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1271cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-%dc" % ncharsdeleted, "insert") 1272cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if have < want: 1273cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", ' ' * (want - have)) 1274cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1275cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1276cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1277cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def smart_indent_event(self, event): 1278cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # if intraline selection: 1279cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # delete it 1280cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # elif multiline selection: 12816af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # do indent-region 12826af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # else: 12836af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # indent one level 1284cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1285cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1286cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1287cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1288cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1289cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if index2line(first) != index2line(last): 1290cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.indent_region_event(event) 1291cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 1292cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 1293cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser prefix = text.get("insert linestart", "insert") 1294cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(prefix, self.tabwidth) 1295cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if raw == len(prefix): 1296cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # only whitespace to the left 1297cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(effective + self.indentwidth) 1298cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 12996af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # tab to the next 'stop' within or to right of line's text: 1300cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.usetabs: 1301cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pad = '\t' 1302cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 13031b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser effective = len(prefix.expandtabs(self.tabwidth)) 1304cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser n = self.indentwidth 1305cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pad = ' ' * (n - effective % n) 1306cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", pad) 1307cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.see("insert") 1308cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1309cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1310cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1311cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1312cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def newline_and_indent_event(self, event): 1313cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1314cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1315cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1316cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1317cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1318cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 1319cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 1320cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = text.get("insert linestart", "insert") 1321cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i, n = 0, len(line) 1322cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while i < n and line[i] in " \t": 1323cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = i+1 1324cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if i == n: 13254ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # the cursor is in or at leading indentation in a continuation 13264ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # line; just inject an empty line at the start 1327cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert linestart", '\n') 1328cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1329cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indent = line[:i] 13304ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # strip whitespace before insert point unless it's in the prompt 1331cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = 0 13324ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser last_line_of_prompt = sys.ps1.split('\n')[-1] 13334ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser while line and line[-1] in " \t" and line != last_line_of_prompt: 1334cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[:-1] 1335cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = i+1 1336cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if i: 1337cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert - %d chars" % i, "insert") 1338cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # strip whitespace after insert point 1339cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while text.get("insert") in " \t": 1340cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert") 1341cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # start new line 1342cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", '\n') 1343cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1344cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # adjust indentation for continuations and block 1345cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # open/close first need to find the last stmt 1346cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lno = index2line(text.index('insert')) 1347cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser y = PyParse.Parser(self.indentwidth, self.tabwidth) 1348b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser if not self.context_use_ps1: 1349b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser for context in self.num_context_lines: 1350b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser startat = max(lno - context, 1) 1351dfd3618422bc19ae48047e74c6320746ee6b610eFlorent Xicluna startatindex = repr(startat) + ".0" 1352b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser rawtext = text.get(startatindex, "insert") 1353b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser y.set_str(rawtext) 1354b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser bod = y.find_good_parse_start( 1355b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self.context_use_ps1, 1356b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser self._build_char_in_string_func(startatindex)) 1357b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser if bod is not None or startat == 1: 1358b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser break 1359b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser y.set_lo(bod or 0) 1360b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser else: 1361b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser r = text.tag_prevrange("console", "insert") 1362b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser if r: 1363b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser startatindex = r[1] 1364b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser else: 1365b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser startatindex = "1.0" 1366cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser rawtext = text.get(startatindex, "insert") 1367cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser y.set_str(rawtext) 1368b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser y.set_lo(0) 1369b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser 1370cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser c = y.get_continuation_type() 1371cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if c != PyParse.C_NONE: 1372cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # The current stmt hasn't ended yet. 1373b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser if c == PyParse.C_STRING_FIRST_LINE: 1374b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser # after the first line of a string; do not indent at all 1375b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser pass 1376b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser elif c == PyParse.C_STRING_NEXT_LINES: 1377b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser # inside a string which started before this line; 1378b61602c96821997884e7de08d56404904baa034bKurt B. Kaiser # just mimic the current indent 1379cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1380cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif c == PyParse.C_BRACKET: 1381cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # line up with the first (if any) element of the 1382cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # last open bracket structure; else indent one 1383cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # level beyond the indent of the line with the 1384cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # last open bracket 1385cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(y.compute_bracket_indent()) 1386cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif c == PyParse.C_BACKSLASH: 1387cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # if more than one line in this stmt already, just 1388cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # mimic the current indent; else if initial line 1389cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # has a start on an assignment stmt, indent to 1390cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # beyond leftmost =; else to beyond first chunk of 1391cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # non-whitespace on initial line 1392cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if y.get_num_lines_in_stmt() > 1: 1393cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1394cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1395cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(y.compute_backslash_indent()) 1396cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 139770a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald assert 0, "bogus continuation type %r" % (c,) 1398cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1399cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1400cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # This line starts a brand new stmt; indent relative to 1401cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentation of initial line of closest preceding 1402cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # interesting stmt. 1403cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indent = y.get_base_indent_string() 1404cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1405cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if y.is_block_opener(): 1406cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.smart_indent_event(event) 1407cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif indent and y.is_block_closer(): 1408cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.smart_backspace_event(event) 1409cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1410cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1411cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.see("insert") 1412cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1413cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1414cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Our editwin provides a is_char_in_string function that works 1415cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # with a Tk text index, but PyParse only knows about offsets into 1416cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # a string. This builds a function for PyParse that accepts an 1417cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # offset. 1418cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1419cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _build_char_in_string_func(self, startindex): 1420cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def inner(offset, _startindex=startindex, 1421cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _icis=self.is_char_in_string): 1422cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return _icis(_startindex + "+%dc" % offset) 1423cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return inner 1424cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1425cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def indent_region_event(self, event): 1426cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1427cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1428cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1429cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1430cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, self.tabwidth) 1431cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = effective + self.indentwidth 1432cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = self._make_blanks(effective) + line[raw:] 1433cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1434cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1435cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1436cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def dedent_region_event(self, event): 1437cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1438cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1439cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1440cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1441cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, self.tabwidth) 1442cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = max(effective - self.indentwidth, 0) 1443cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = self._make_blanks(effective) + line[raw:] 1444cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1445cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1446cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1447cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def comment_region_event(self, event): 1448cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1449cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines) - 1): 1450cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1451cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = '##' + line 1452cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1453cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1454cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def uncomment_region_event(self, event): 1455cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1456cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1457cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1458cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if not line: 1459cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser continue 1460cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line[:2] == '##': 1461cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[2:] 1462cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif line[:1] == '#': 1463cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[1:] 1464cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = line 1465cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1466cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1467cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def tabify_region_event(self, event): 1468cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1469cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tabwidth = self._asktabwidth() 147075b249c914561166602bb42fe748b6e00211cc91Roger Serwy if tabwidth is None: return 1471cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1472cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1473cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1474cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, tabwidth) 1475cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ntabs, nspaces = divmod(effective, tabwidth) 1476cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] 1477cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1478cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1479cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def untabify_region_event(self, event): 1480cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1481cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tabwidth = self._asktabwidth() 148275b249c914561166602bb42fe748b6e00211cc91Roger Serwy if tabwidth is None: return 1483cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 14841b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser lines[pos] = lines[pos].expandtabs(tabwidth) 1485cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1486cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1487cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def toggle_tabs_event(self, event): 1488cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.askyesno( 1489cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Toggle tabs", 14906af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser "Turn tabs " + ("on", "off")[self.usetabs] + 14916af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser "?\nIndent width " + 149253f2b5fab2f525342dbb69f6f2d5eed978c7883fKurt B. Kaiser ("will be", "remains at")[self.usetabs] + " 8." + 149353f2b5fab2f525342dbb69f6f2d5eed978c7883fKurt B. Kaiser "\n Note: a tab is always 8 columns", 1494cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text): 1495cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.usetabs = not self.usetabs 149653f2b5fab2f525342dbb69f6f2d5eed978c7883fKurt B. Kaiser # Try to prevent inconsistent indentation. 149753f2b5fab2f525342dbb69f6f2d5eed978c7883fKurt B. Kaiser # User must change indent width manually after using tabs. 149853f2b5fab2f525342dbb69f6f2d5eed978c7883fKurt B. Kaiser self.indentwidth = 8 1499cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1500cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 15016af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser # XXX this isn't bound to anything -- see tabwidth comments 15026af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## def change_tabwidth_event(self, event): 15036af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## new = self._asktabwidth() 15046af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## if new != self.tabwidth: 15056af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## self.tabwidth = new 15066af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## self.set_indentation_params(0, guess=0) 15076af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser## return "break" 1508cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1509cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def change_indentwidth_event(self, event): 1510cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser new = self.askinteger( 1511cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Indent width", 15126af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser "New indent width (2-16)\n(Always use 8 when using tabs)", 1513cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text, 1514cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser initialvalue=self.indentwidth, 1515cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser minvalue=2, 1516cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser maxvalue=16) 15176af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser if new and new != self.indentwidth and not self.usetabs: 1518cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentwidth = new 1519cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1520cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1521cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def get_region(self): 1522cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1523cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1524cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1525cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head = text.index(first + " linestart") 1526cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tail = text.index(last + "-1c lineend +1c") 1527cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1528cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head = text.index("insert linestart") 1529cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tail = text.index("insert lineend +1c") 1530cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = text.get(head, tail) 15311b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser lines = chars.split("\n") 1532cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return head, tail, chars, lines 1533cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1534cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def set_region(self, head, tail, chars, lines): 1535cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 15361b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser newchars = "\n".join(lines) 1537cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if newchars == chars: 1538cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bell() 1539cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return 1540cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.tag_remove("sel", "1.0", "end") 1541cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", head) 1542cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1543cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(head, tail) 1544cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert(head, newchars) 1545cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1546cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.tag_add("sel", head, "insert") 1547cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1548cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Make string that displays as n leading blanks. 1549cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1550cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _make_blanks(self, n): 1551cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.usetabs: 1552cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ntabs, nspaces = divmod(n, self.tabwidth) 1553cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return '\t' * ntabs + ' ' * nspaces 1554cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1555cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return ' ' * n 1556cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1557cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Delete from beginning of line to insert point, then reinsert 1558cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # column logical (meaning use tabs if appropriate) spaces. 1559cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1560cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def reindent_to(self, column): 1561cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1562cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1563cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if text.compare("insert linestart", "!=", "insert"): 1564cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert linestart", "insert") 1565cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if column: 1566cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", self._make_blanks(column)) 1567cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1568cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1569cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _asktabwidth(self): 1570cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.askinteger( 1571cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Tab width", 1572ca7329c9c124080b817ceb67b4e3ee7963b81d41Kurt B. Kaiser "Columns per tab? (2-16)", 1573cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text, 1574cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser initialvalue=self.indentwidth, 1575cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser minvalue=2, 157675b249c914561166602bb42fe748b6e00211cc91Roger Serwy maxvalue=16) 1577cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1578cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Guess indentwidth from text content. 1579cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Return guessed indentwidth. This should not be believed unless 1580cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # it's in a reasonable range (e.g., it will be 0 if no indented 1581cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # blocks are found). 1582cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1583cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def guess_indent(self): 1584cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser opener, indented = IndentSearcher(self.text, self.tabwidth).run() 1585cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if opener and indented: 1586cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, indentsmall = classifyws(opener, self.tabwidth) 1587cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, indentlarge = classifyws(indented, self.tabwidth) 1588cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1589cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indentsmall = indentlarge = 0 1590cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return indentlarge - indentsmall 1591cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1592cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# "line.col" -> line, as an int 1593cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdef index2line(index): 1594cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return int(float(index)) 1595cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1596cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# Look at the leading whitespace in s. 1597cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# Return pair (# of leading ws characters, 1598cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# effective # of leading blanks after expanding 1599cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# tabs to width tabwidth) 1600cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1601cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdef classifyws(s, tabwidth): 1602cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = effective = 0 1603cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for ch in s: 1604cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if ch == ' ': 1605cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = raw + 1 1606cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = effective + 1 1607cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif ch == '\t': 1608cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = raw + 1 1609cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = (effective // tabwidth + 1) * tabwidth 1610cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1611cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser break 1612cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return raw, effective 1613cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1614cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserimport tokenize 1615cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser_tokenize = tokenize 1616cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdel tokenize 1617cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1618dcba6622f52efafa28104a07db9d5ba2b1a8d628Kurt B. Kaiserclass IndentSearcher(object): 1619cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1620cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # .run() chews over the Text widget, looking for a block opener 1621cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # and the stmt following it. Returns a pair, 1622cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # (line containing block opener, line containing stmt) 1623cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Either or both may be None. 1624cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1625cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def __init__(self, text, tabwidth): 1626cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.text = text 1627cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.tabwidth = tabwidth 1628cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.i = self.finished = 0 1629cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.blkopenline = self.indentedline = None 1630cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1631cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def readline(self): 1632cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.finished: 1633cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "" 1634cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = self.i = self.i + 1 163570a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald mark = repr(i) + ".0" 1636cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.text.compare(mark, ">=", "end"): 1637cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "" 1638cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.text.get(mark, mark + " lineend+1c") 1639cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1640cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def tokeneater(self, type, token, start, end, line, 1641cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser INDENT=_tokenize.INDENT, 1642cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser NAME=_tokenize.NAME, 1643cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser OPENERS=('class', 'def', 'for', 'if', 'try', 'while')): 1644cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.finished: 1645cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pass 1646cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif type == NAME and token in OPENERS: 1647cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.blkopenline = line 1648cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif type == INDENT and self.blkopenline: 1649cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentedline = line 1650cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.finished = 1 1651cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1652cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def run(self): 1653cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser save_tabsize = _tokenize.tabsize 1654cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tabsize = self.tabwidth 1655cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1656cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1657cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tokenize(self.readline, self.tokeneater) 165861006a211339f592dcb60f20ee7e478ad012556dSerhiy Storchaka except (_tokenize.TokenError, SyntaxError): 1659cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # since we cut off the tokenizer early, we can trigger 1660cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # spurious errors 1661cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pass 1662cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1663cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tabsize = save_tabsize 1664cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.blkopenline, self.indentedline 1665cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1666cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser### end autoindent code ### 1667cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 16687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef prepstr(s): 16697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Helper to extract the underscore from a string, e.g. 16707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # prepstr("Co_py") returns (2, "Copy"). 1671220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser i = s.find('_') 16727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if i >= 0: 16737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = s[:i] + s[i+1:] 16747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return i, s 16757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 16767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 16777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererkeynames = { 16787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'bracketleft': '[', 16797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'bracketright': ']', 16807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'slash': '/', 16817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer} 16827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1683610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiserdef get_accelerator(keydefs, eventname): 1684610c7e07f3e41e1f4baf7303edc8124269c01250Kurt B. Kaiser keylist = keydefs.get(eventname) 168560651535c997bd3b55afb3b5718680ec2a404f69Ned Deily # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 168660651535c997bd3b55afb3b5718680ec2a404f69Ned Deily # if not keylist: 168757847df4e59015c141e645b47112829cf41b582aNed Deily if (not keylist) or (macosxSupport.isCocoaTk() and eventname in { 168860651535c997bd3b55afb3b5718680ec2a404f69Ned Deily "<<open-module>>", 168960651535c997bd3b55afb3b5718680ec2a404f69Ned Deily "<<goto-line>>", 169060651535c997bd3b55afb3b5718680ec2a404f69Ned Deily "<<change-indentwidth>>"}): 16917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "" 16927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = keylist[0] 1693220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) 16947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s) 16957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Key-", "", s) 16967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu 16977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Control-", "Ctrl-", s) 16987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("-", "+", s) 16997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("><", " ", s) 17007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("<", "", s) 17017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub(">", "", s) 17027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return s 17037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 17047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 17057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef fixwordbreaks(root): 17067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Make sure that Tk's double-click and next/previous word 17077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # operations use our definition of a word (i.e. an identifier) 17087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk = root.tk 17097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded 17107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]') 17117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') 17127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 17137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 171400b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedydef _Editor_window(parent): 171500b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy root = parent 17167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer fixwordbreaks(root) 17177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root.withdraw() 17187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if sys.argv[1:]: 17197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = sys.argv[1] 17207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 17217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = None 172200b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy macosxSupport.setupApp(root, None) 17237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit = EditorWindow(root=root, filename=filename) 17247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit.set_close_hook(root.quit) 17250b634efcbcd10d9364796e9b048f18cd4a08b88bKurt B. Kaiser edit.text.bind("<<close-all-windows>>", edit.close_event) 17267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 17277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == '__main__': 172800b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy from idlelib.idle_test.htest import run 172900b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy if len(sys.argv) <= 1: 173000b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy run(_Help_dialog) 173100b0bd55b4d615740e06ac4d445221a176da30f3Terry Jan Reedy run(_Editor_window) 1732