EditorWindow.py revision 260cb9034c861fa159f26fba8679ac265af47109
17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys 27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os 37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re 47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport imp 57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom Tkinter import * 67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport tkSimpleDialog 77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport tkMessageBox 8fd182cd9d36adefba00d86542eb3134119cdc804Kurt B. Kaiser 9fd182cd9d36adefba00d86542eb3134119cdc804Kurt B. Kaiserimport webbrowser 107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport idlever 117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport WindowList 12c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gavaimport SearchDialog 13c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gavaimport GrepDialog 14c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gavaimport ReplaceDialog 15cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserimport PyParse 16dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gavafrom configHandler import idleConf 173b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gavaimport aboutDialog, textView, configDialog 187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# The default tab setting for a Text widget, in average-width characters. 207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David SchererTK_TABWIDTH_DEFAULT = 8 217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 22220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiserdef _find_module(fullname, path=None): 23220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser """Version of imp.find_module() that handles hierarchical module names""" 24220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser 25220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser file = None 26220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser for tgt in fullname.split('.'): 27220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser if file is not None: 28220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser file.close() # close intermediate files 29220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser (file, filename, descr) = imp.find_module(tgt, path) 30220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser if descr[2] == imp.PY_SOURCE: 31220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser break # find but not load the source file 32220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser module = imp.load_module(tgt, file, filename, descr) 3369e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser try: 3469e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser path = module.__path__ 3569e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser except AttributeError: 3669e8afcc9fcd8a41a1035893d60893d51fae62f1Kurt B. Kaiser raise ImportError, 'No source for module ' + module.__name__ 37220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return file, filename, descr 38220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser 397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass EditorWindow: 407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from Percolator import Percolator 417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from ColorDelegator import ColorDelegator 427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from UndoDelegator import UndoDelegator 437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from IOBinding import IOBinding 447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer import Bindings 457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from Tkinter import Toplevel 467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer from MultiStatusBar import MultiStatusBar 477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer vars = {} 49114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser help_url = None 507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def __init__(self, flist=None, filename=None, key=None, root=None): 52114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if EditorWindow.help_url is None: 53114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if sys.platform.count('linux'): 54114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser # look for html docs in a couple of standard places 55114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] 56114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if os.path.isdir('/var/www/html/python/'): # "python2" rpm 57114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = '/var/www/html/python/index.html' 58114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 59114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser basepath = '/usr/share/doc/' # standard location 60114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = os.path.join(basepath, pyver, 61114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser 'Doc', 'index.html') 62114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 63114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = os.path.join(sys.prefix, 'Doc', 'index.html') 64114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser dochome = os.path.normpath(dochome) 65114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if os.path.isfile(dochome): 66114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser EditorWindow.help_url = dochome 67114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 68114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser EditorWindow.help_url = "http://www.python.org/doc/current" 69dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava currentTheme=idleConf.CurrentTheme() 707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist = flist 717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root = root or flist.root 727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.root = root 737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.menubar = Menu(root) 747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top = top = self.Toplevel(root, menu=self.menubar) 750c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava if flist: 760c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava self.vars = flist.vars 770c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava #self.top.instanceDict makes flist.inversedict avalable to 780c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava #configDialog.py so it can access all EditorWindow instaces 790c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava self.top.instanceDict=flist.inversedict 801d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.recentFilesPath=os.path.join(idleConf.GetUserCfgDir(), 811d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava 'recent-files.lst') 827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.vbar = vbar = Scrollbar(top, name='vbar') 837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text_frame = text_frame = Frame(top) 841061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser self.width = idleConf.GetOption('main','EditorWindow','width') 85a1dee069831c5551dc28d90d495ab5de967c17d5Kurt B. Kaiser self.text = text = Text(text_frame, name='text', padx=5, wrap='none', 86dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava foreground=idleConf.GetHighlight(currentTheme, 87dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava 'normal',fgBg='fg'), 88dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava background=idleConf.GetHighlight(currentTheme, 89dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava 'normal',fgBg='bg'), 90dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava highlightcolor=idleConf.GetHighlight(currentTheme, 91dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava 'hilite',fgBg='fg'), 92dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava highlightbackground=idleConf.GetHighlight(currentTheme, 93dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava 'hilite',fgBg='bg'), 94dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava insertbackground=idleConf.GetHighlight(currentTheme, 95dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava 'cursor',fgBg='fg'), 961061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser width=self.width, 97dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava height=idleConf.GetOption('main','EditorWindow','height') ) 987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.createmenubar() 1007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.apply_bindings() 1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.protocol("WM_DELETE_WINDOW", self.close) 1037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.bind("<<close-window>>", self.close_event) 10484f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<cut>>", self.cut) 10584f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<copy>>", self.copy) 10684f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser text.bind("<<paste>>", self.paste) 1077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<center-insert>>", self.center_insert_event) 1087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<help>>", self.help_dialog) 109abdfc4147d1f1334bb4dbaf5d9dd66af1db175adSteven M. Gava text.bind("<<view-readme>>", self.view_readme) 1107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<python-docs>>", self.python_docs) 1117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<about-idle>>", self.about_dialog) 1123b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava text.bind("<<open-config-dialog>>", self.config_dialog) 1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-module>>", self.open_module) 1147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<do-nothing>>", lambda event: "break") 1157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<select-all>>", self.select_all) 1167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<remove-selection>>", self.remove_selection) 117c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find>>", self.find_event) 118c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-again>>", self.find_again_event) 119c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-in-files>>", self.find_in_files_event) 120c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<find-selection>>", self.find_selection_event) 121c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<replace>>", self.replace_event) 122c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bind("<<goto-line>>", self.goto_line_event) 1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<3>", self.right_menu_event) 124cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<smart-backspace>>",self.smart_backspace_event) 125cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<newline-and-indent>>",self.newline_and_indent_event) 126cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<smart-indent>>",self.smart_indent_event) 127cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<indent-region>>",self.indent_region_event) 128cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<dedent-region>>",self.dedent_region_event) 129cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<comment-region>>",self.comment_region_event) 130cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<uncomment-region>>",self.uncomment_region_event) 131cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<tabify-region>>",self.tabify_region_event) 132cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<untabify-region>>",self.untabify_region_event) 133cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<toggle-tabs>>",self.toggle_tabs_event) 134cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bind("<<change-indentwidth>>",self.change_indentwidth_event) 1355ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser text.bind("<Left>", self.move_at_edge_if_selection(0)) 1365ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser text.bind("<Right>", self.move_at_edge_if_selection(1)) 1376655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 1387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if flist: 1397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer flist.inversedict[self] = key 1407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if key: 1417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer flist.dict[key] = self 142d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser text.bind("<<open-new-window>>", self.new_callback) 1437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<close-all-windows>>", self.flist.close_all_callback) 1447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-class-browser>>", self.open_class_browser) 1457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.bind("<<open-path-browser>>", self.open_path_browser) 1467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 147898a365c276951ab2471afe2e24bbc910666d361Steven M. Gava self.set_status_bar() 1487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer vbar['command'] = text.yview 1497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer vbar.pack(side=RIGHT, fill=Y) 1507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text['yscrollcommand'] = vbar.set 151b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='normal' 152b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): 153b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='bold' 154dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 155b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava idleConf.GetOption('main','EditorWindow','font-size'), 156b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight)) 1577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text_frame.pack(side=LEFT, fill=BOTH, expand=1) 1587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.pack(side=TOP, fill=BOTH, expand=1) 1597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.focus_set() 1607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per = per = self.Percolator(text) 1627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.ispythonsource(filename): 163dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser self.color = color = self.ColorDelegator() 164dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser per.insertfilter(color) 1657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.color = None 167dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 168dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser self.undo = undo = self.UndoDelegator() 169dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser per.insertfilter(undo) 170dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser text.undo_block_start = undo.undo_block_start 171dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser text.undo_block_stop = undo.undo_block_stop 172dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser undo.set_saved_change_hook(self.saved_change_hook) 173dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 174dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser # IOBinding implements file I/O and printing functionality 1757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.io = io = self.IOBinding(self) 176dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser io.set_filename_change_hook(self.filename_change_hook) 177dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser 1781d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava #create the Recent Files submenu 1791d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.menuRecentFiles=Menu(self.menubar) 1801d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.menudict['file'].insert_cascade(3,label='Recent Files', 1811d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava underline=0,menu=self.menuRecentFiles) 1821d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.UpdateRecentFilesList() 1837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if filename: 185d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser if os.path.exists(filename) and not os.path.isdir(filename): 1867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer io.loadfile(filename) 1877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 1887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer io.set_filename(filename) 1897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.saved_change_hook() 1907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_extensions() 1927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 1937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = self.menudict.get('windows') 1947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if menu: 1957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = menu.index("end") 1967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end is None: 1977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = -1 1987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end >= 0: 1997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_separator() 2007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = end + 1 2017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.wmenu_end = end 2027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.register_callback(self.postwindowsmenu) 2037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Some abstractions so IDLE extensions are cross-IDE 2057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.askyesno = tkMessageBox.askyesno 2067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.askinteger = tkSimpleDialog.askinteger 2077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.showerror = tkMessageBox.showerror 2087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.extensions.has_key('AutoIndent'): 2107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions['AutoIndent'].set_indentation_params( 2117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.ispythonsource(filename)) 2126655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 213d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser def new_callback(self, event): 214d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser dirname, basename = self.io.defaultfilename() 215d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser self.flist.new(dirname) 216d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser return "break" 217d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser 2187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_status_bar(self): 219898a365c276951ab2471afe2e24bbc910666d361Steven M. Gava self.status_bar = self.MultiStatusBar(self.top) 2207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('column', 'Col: ?', side=RIGHT) 2217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('line', 'Ln: ?', side=RIGHT) 2227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.pack(side=BOTTOM, fill=X) 2237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.bind('<KeyRelease>', self.set_line_and_column) 2247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.bind('<ButtonRelease>', self.set_line_and_column) 2257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.after_idle(self.set_line_and_column) 2267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_line_and_column(self, event=None): 228220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser line, column = self.text.index(INSERT).split('.') 2297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('column', 'Col: %s' % column) 2307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.status_bar.set_label('line', 'Ln: %s' % line) 2317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def wakeup(self): 2337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.top.wm_state() == "iconic": 2347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_deiconify() 2357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 2367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.tkraise() 2377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.focus_set() 2387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu_specs = [ 2407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("file", "_File"), 2417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("edit", "_Edit"), 2427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("format", "F_ormat"), 2437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("run", "_Run"), 2441061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser ("options", "_Options"), 2457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("windows", "_Windows"), 2467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("help", "_Help"), 2477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ] 2487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def createmenubar(self): 2507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer mbar = self.menubar 2517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.menudict = menudict = {} 2527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name, label in self.menu_specs: 2537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer underline, label = prepstr(label) 2547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menudict[name] = menu = Menu(mbar, name=name) 2557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer mbar.add_cascade(label=label, menu=menu, underline=underline) 2567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.fill_menus() 2578e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.base_helpmenu_length = self.menudict['help'].index(END) 2588e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.reset_help_menu_entries() 2597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def postwindowsmenu(self): 2617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Only called when Windows menu exists 2627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX Actually, this Just-In-Time updating interferes badly 2637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX with the tear-off feature. It would be better to update 2647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX all Windows menus whenever the list of windows changes. 2657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = self.menudict['windows'] 2667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = menu.index("end") 2677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end is None: 2687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer end = -1 2697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if end > self.wmenu_end: 2707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.delete(self.wmenu_end+1, end) 2717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.add_windows_to_menu(menu) 2727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = None 2747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def right_menu_event(self, event): 2767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_remove("sel", "1.0", "end") 2777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) 2787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.rmenu: 2797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.make_rmenu() 2807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = self.rmenu 2817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.event = event 2827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer iswin = sys.platform[:3] == 'win' 2837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if iswin: 2847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.config(cursor="arrow") 2857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu.tk_popup(event.x_root, event.y_root) 2867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if iswin: 2877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.config(cursor="ibeam") 2887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu_specs = [ 2907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # ("Label", "<<virtual-event>>"), ... 2917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ("Close", "<<close-window>>"), # Example 2927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ] 2937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 2947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def make_rmenu(self): 2957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu = Menu(self.text, tearoff=0) 2967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for label, eventname in self.rmenu_specs: 2977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def command(text=self.text, eventname=eventname): 2987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.event_generate(eventname) 2997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer rmenu.add_command(label=label, command=command) 3007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.rmenu = rmenu 3017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def about_dialog(self, event=None): 3037d9ed726fb6ec15dbfb8e922d35aa8816cbd0b0cSteven M. Gava aboutDialog.AboutDialog(self.top,'About IDLEfork') 3046655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 3053b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava def config_dialog(self, event=None): 3063b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava configDialog.ConfigDialog(self.top,'Settings') 3076655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 308abdfc4147d1f1334bb4dbaf5d9dd66af1db175adSteven M. Gava def view_readme(self, event=None): 309abdfc4147d1f1334bb4dbaf5d9dd66af1db175adSteven M. Gava fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'README.txt') 3106655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser textView.TextViewer(self.top,'IDLEfork - README',fn) 311abdfc4147d1f1334bb4dbaf5d9dd66af1db175adSteven M. Gava 3127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def help_dialog(self, event=None): 313b9d07b5a8b8b70268ffa520895e7843ab594a486Steven M. Gava fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') 3146655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser textView.TextViewer(self.top,'Help',fn) 3156655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 316114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser def python_docs(self, event=None): 317114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if sys.platform.count('win') or sys.platform.count('nt'): 318931625dc77cfd527b059e579615d517d8d994110Steven M. Gava os.startfile(self.help_url) 319114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser return "break" 320114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 321114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser webbrowser.open(self.help_url) 322114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser return "break" 3230c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava 3240c5bc8c9518fd18d41aedede536c4a9aa8dfa619Steven M. Gava def display_docs(self, url): 3258e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser if not (url.startswith('www') or url.startswith('http')): 3268e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser url = os.path.normpath(url) 327114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser if sys.platform.count('win') or sys.platform.count('nt'): 328114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser os.startfile(url) 329114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser else: 330114713d19451e893dc7dabea9b96d396baf7ecafKurt B. Kaiser webbrowser.open(url) 3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 33284f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def cut(self,event): 33384f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Cut>>") 33484f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 33584f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 33684f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def copy(self,event): 33784f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Copy>>") 33884f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 33984f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 34084f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser def paste(self,event): 34184f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser self.text.event_generate("<<Paste>>") 34284f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser return "break" 34384f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser 3447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def select_all(self, event=None): 3457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_add("sel", "1.0", "end-1c") 3467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "1.0") 3477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.see("insert") 3487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "break" 3497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def remove_selection(self, event=None): 3517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_remove("sel", "1.0", "end") 3527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.see("insert") 3537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 3545ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser def move_at_edge_if_selection(self, edge_index): 3555ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser """Cursor move begins at start or end of selection 3565ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 3575ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser When a left/right cursor key is pressed create and return to Tkinter a 3585ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser function which causes a cursor move from the associated edge of the 3595ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser selection. 3605ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 3615ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser """ 3625ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_index = self.text.index 3635ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_mark_set = self.text.mark_set 3645ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser edges_table = ("sel.first+1c", "sel.last-1c") 3655ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser def move_at_edge(event): 3665ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed 3675ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser try: 3685ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_index("sel.first") 3695ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser self_text_mark_set("insert", edges_table[edge_index]) 3705ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser except TclError: 3715ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser pass 3725ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser return move_at_edge 3735ec186b1cbf06cf66262882fb5b6f54a893e48a5Kurt B. Kaiser 374c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_event(self, event): 375c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find(self.text) 376c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 377c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 378c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_again_event(self, event): 379c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find_again(self.text) 380c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 381c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 382c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_selection_event(self, event): 383c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava SearchDialog.find_selection(self.text) 384c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 385c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 386c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def find_in_files_event(self, event): 387c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava GrepDialog.grep(self.text, self.io, self.flist) 388c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 389c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 390c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def replace_event(self, event): 391c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava ReplaceDialog.replace(self.text) 392c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 393c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 394c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava def goto_line_event(self, event): 395c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text = self.text 396c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava lineno = tkSimpleDialog.askinteger("Goto", 397c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava "Go to line number:",parent=text) 398c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava if lineno is None: 399c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 400c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava if lineno <= 0: 401c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.bell() 402c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava return "break" 403c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.mark_set("insert", "%d.0" % lineno) 404c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava text.see("insert") 405c597640515a9ca3aa1807cc633b8d7bf2aa4a4e6Steven M. Gava 4067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_module(self, event=None): 4077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX Shouldn't this be in IOBinding or in FileList? 4087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 4097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name = self.text.get("sel.first", "sel.last") 4107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except TclError: 4117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer name = "" 4127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 413220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser name = name.strip() 414852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum name = tkSimpleDialog.askstring("Module", 415852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum "Enter the name of a Python module\n" 416852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum "to search on sys.path and open:", 417852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum parent=self.text, initialvalue=name) 418852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum if name: 419852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum name = name.strip() 4207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not name: 421852f35bbeb23d898fb0d16489effb1197ee3fe02Guido van Rossum return 4227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # XXX Ought to insert current file's directory in front of path 4237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 424220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser (f, file, (suffix, mode, type)) = _find_module(name) 4257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except (NameError, ImportError), msg: 4267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror("Import error", str(msg), parent=self.text) 4277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 4287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if type != imp.PY_SOURCE: 4297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror("Unsupported type", 4307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "%s is not a source module" % name, parent=self.text) 4317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 4327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if f: 4337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f.close() 4347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 4357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist.open(file) 4367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 4377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.io.loadfile(file) 4387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_class_browser(self, event=None): 4407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = self.io.filename 4417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not filename: 4427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tkMessageBox.showerror( 4437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "No filename", 4447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "This buffer has no associated filename", 4457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer master=self.text) 4467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.focus_set() 4477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return None 4487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer head, tail = os.path.split(filename) 4497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer base, ext = os.path.splitext(tail) 4507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer import ClassBrowser 4517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ClassBrowser.ClassBrowser(self.flist, base, [head]) 4527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def open_path_browser(self, event=None): 4547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer import PathBrowser 4557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer PathBrowser.PathBrowser(self.flist) 4567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def gotoline(self, lineno): 4587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if lineno is not None and lineno > 0: 4597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.mark_set("insert", "%d.0" % lineno) 4607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_remove("sel", "1.0", "end") 4617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.tag_add("sel", "insert", "insert +1l") 4627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.center() 4637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def ispythonsource(self, filename): 4657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not filename: 466220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return True 4677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer base, ext = os.path.splitext(os.path.basename(filename)) 4687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if os.path.normcase(ext) in (".py", ".pyw"): 469220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return True 4707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 4717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f = open(filename) 4727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer line = f.readline() 4737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer f.close() 4747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except IOError: 475220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser return False 47683a3560527f9e62bce6adbc12b8ff6b57be8b1acKurt B. Kaiser return line.startswith('#!') and line.find('python') >= 0 4777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close_hook(self): 4797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 4807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist.close_edit(self) 4817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_close_hook(self, close_hook): 4837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.close_hook = close_hook 4847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def filename_change_hook(self): 4867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.flist: 4877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist.filename_changed_edit(self) 4887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.saved_change_hook() 489260cb9034c861fa159f26fba8679ac265af47109Kurt B. Kaiser self.top.update_windowlist_registry(self) 4907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.ispythonsource(self.io.filename): 4917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.addcolorizer() 4927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 4937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.rmcolorizer() 4947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 4957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def addcolorizer(self): 4967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 4977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 4987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.removefilter(self.undo) 4997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.color = self.ColorDelegator() 5007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.insertfilter(self.color) 5017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.insertfilter(self.undo) 5027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 5037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def rmcolorizer(self): 5047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.color: 5057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 5067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.removefilter(self.undo) 5077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.removefilter(self.color) 5087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.color = None 5097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.insertfilter(self.undo) 5106655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 511b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava def ResetColorizer(self): 51283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser "Update the colour theme if it is changed" 51383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser # Called from configDialog.py 514b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava if self.color: 515b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava self.color = self.ColorDelegator() 516b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava self.per.insertfilter(self.color) 5177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 518b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava def ResetFont(self): 5196655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser "Update the text widgets' font if it is changed" 52083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser # Called from configDialog.py 521b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='normal' 522b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): 523b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight='bold' 524b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), 525b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava idleConf.GetOption('main','EditorWindow','font-size'), 526b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava fontWeight)) 527b1585417d1f7ae8984ca72b16fd5a21746949ae5Steven M. Gava 528dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava def ResetKeybindings(self): 52983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser "Update the keybindings if they are changed" 53083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser # Called from configDialog.py 531dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava self.Bindings.default_keydefs=idleConf.GetCurrentKeySet() 532dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava keydefs = self.Bindings.default_keydefs 533dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for event, keylist in keydefs.items(): 534dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava self.text.event_delete(event) 535dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava self.apply_bindings() 536dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava #update menu accelerators 537dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava menuEventDict={} 538dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for menu in self.Bindings.menudefs: 539dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava menuEventDict[menu[0]]={} 540dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for item in menu[1]: 541dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if item: 542dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava menuEventDict[menu[0]][prepstr(item[0])[1]]=item[1] 543dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for menubarItem in self.menudict.keys(): 544dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava menu=self.menudict[menubarItem] 545dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava end=menu.index(END)+1 546dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava for index in range(0,end): 547dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if menu.type(index)=='command': 548dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava accel=menu.entrycget(index,'accelerator') 549dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if accel: 550dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava itemName=menu.entrycget(index,'label') 551dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava event='' 552dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if menuEventDict.has_key(menubarItem): 553dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if menuEventDict[menubarItem].has_key(itemName): 554dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava event=menuEventDict[menubarItem][itemName] 555dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava if event: 556dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava #print 'accel was:',accel 557dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava accel=get_accelerator(keydefs, event) 558dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava menu.entryconfig(index,accelerator=accel) 559dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava #print 'accel now:',accel,'\n' 560dbfe92cd27f08d38cc8a2882c147c4289b6b5db1Steven M. Gava 5618e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def reset_help_menu_entries(self): 5628e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser "Update the additional help entries on the Help menu" 5638e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser help_list = idleConf.GetAllExtraHelpSourcesList() 5648e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu = self.menudict['help'] 5658e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # first delete the extra help entries, if any 5668e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu_length = helpmenu.index(END) 5678e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser if helpmenu_length > self.base_helpmenu_length: 5688e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) 5698e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # then rebuild them 5708e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser if help_list: 5718e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.add_separator() 5728e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser for entry in help_list: 5738e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser cmd = self.__extra_help_callback(entry[1]) 5748e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser helpmenu.add_command(label=entry[0], command=cmd) 5758e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser # and update the menu dictionary 5768e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.menudict['help'] = helpmenu 5778e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser 5788e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def __extra_help_callback(self, helpfile): 5798e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser "Create a callback with the helpfile value frozen at definition time" 5808e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser def display_extra_help(helpfile=helpfile): 5818e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser self.display_docs(helpfile) 5828e92bf7699ac3617d3a0a9a55a38f642f5a6ecc6Kurt B. Kaiser return display_extra_help 5836655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 5841d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava def UpdateRecentFilesList(self,newFile=None): 58583118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser "Load or update the recent files list, and menu if required" 5861d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList=[] 5871d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if os.path.exists(self.recentFilesPath): 5881d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava RFfile=open(self.recentFilesPath,'r') 5891d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava try: 5901d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList=RFfile.readlines() 5911d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava finally: 5921d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava RFfile.close() 5936655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser if newFile: 5941d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava newFile=os.path.abspath(newFile)+'\n' 5951d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if newFile in rfList: 5961d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList.remove(newFile) 5971d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList.insert(0,newFile) 5981d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList=self.__CleanRecentFiles(rfList) 59983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser #print self.flist.inversedict 60083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser #print self.top.instanceDict 60183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser #print self 602c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser ullist = "1234567890ABCDEFGHIJ" 6031d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if rfList: 6041d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava for instance in self.top.instanceDict.keys(): 605c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser menu = instance.menuRecentFiles 606c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser menu.delete(1,END) 6076655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser i = 0 ; ul = 0; ullen = len(ullist) 6081d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava for file in rfList: 6091d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava fileName=file[0:-1] 610c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser callback = instance.__RecentFileCallback(fileName) 611c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser if i > ullen: # don't underline menuitems 612c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser ul=None 613c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser menu.add_command(label=ullist[i] + " " + fileName, 614c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser command=callback, 615c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser underline=ul) 616c9a5b5c72e6017c154b26d2796141091e7614d44Kurt B. Kaiser i += 1 6176655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 6181d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava def __CleanRecentFiles(self,rfList): 6191d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava origRfList=rfList[:] 6201d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava count=0 6211d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava nonFiles=[] 6221d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava for path in rfList: 6236655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser if not os.path.exists(path[0:-1]): 6241d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava nonFiles.append(count) 6251d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava count=count+1 6261d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if nonFiles: 6271d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava nonFiles.reverse() 6281d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava for index in nonFiles: 6291d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava del(rfList[index]) 6301d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if len(rfList)>19: 6311d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava rfList=rfList[0:19] 6321d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava #if rfList != origRfList: 6331d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava RFfile=open(self.recentFilesPath,'w') 6341d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava try: 6351d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava RFfile.writelines(rfList) 6361d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava finally: 6371d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava RFfile.close() 6381d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava return rfList 6396655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 6401d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava def __RecentFileCallback(self,fileName): 6411d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava def OpenRecentFile(fileName=fileName): 6421d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.io.open(editFile=fileName) 6431d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava return OpenRecentFile 6446655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser 6457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def saved_change_hook(self): 6467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer short = self.short_title() 6477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer long = self.long_title() 6487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if short and long: 6497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = short + " - " + long 6507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer elif short: 6517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = short 6527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer elif long: 6537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = long 6547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 6557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = "Untitled" 6567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer icon = short or long or title 6577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not self.get_saved(): 6587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer title = "*%s*" % title 6597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer icon = "*%s" % icon 6607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_title(title) 6617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.wm_iconname(icon) 6627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_saved(self): 6647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.undo.get_saved() 6657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_saved(self, flag): 6677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.undo.set_saved(flag) 6687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def reset_undo(self): 6707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.undo.reset_undo() 6717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def short_title(self): 6737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = self.io.filename 6747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if filename: 6757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = os.path.basename(filename) 6767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return filename 6777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def long_title(self): 6797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.io.filename or "" 6807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def center_insert_event(self, event): 6827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.center() 6837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def center(self, mark="insert"): 6857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 6867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top, bot = self.getwindowlines() 6877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer lineno = self.getlineno(mark) 6887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer height = bot - top 689220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser newtop = max(1, lineno - height//2) 6907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.yview(float(newtop)) 6917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 6927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getwindowlines(self): 6937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 6947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer top = self.getlineno("@0,0") 6957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer bot = self.getlineno("@0,65535") 6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if top == bot and text.winfo_height() == 1: 6977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Geometry manager hasn't run yet 6987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer height = int(text['height']) 6997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer bot = top + height - 1 7007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return top, bot 7017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getlineno(self, mark="insert"): 7037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 7047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return int(float(text.index(mark))) 7057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7061061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser def get_geometry(self): 7071061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser "Return (width, height, x, y)" 7081061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser geom = self.top.wm_geometry() 7091061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) 7101061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser tuple = (map(int, m.groups())) 7111061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser return tuple 7121061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser 7137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close_event(self, event): 7147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.close() 7157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def maybesave(self): 7177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.io: 71867716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava if not self.get_saved(): 7196655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser if self.top.state()!='normal': 72067716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.deiconify() 72167716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.lower() 72267716b5f53715e57d147cde9539b8d76a5a56e11Steven M. Gava self.top.lift() 7237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.io.maybesave() 7247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def close(self): 7267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer reply = self.maybesave() 7277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if reply != "cancel": 7287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self._close() 7297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return reply 7307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def _close(self): 73283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser #print self.io.filename 7331d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava if self.io.filename: 7341d46e40f58b21dd6c30e21a841d65e9bcbc899b1Steven M. Gava self.UpdateRecentFilesList(newFile=self.io.filename) 7357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer WindowList.unregister_callback(self.postwindowsmenu) 7367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.close_hook: 7377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.close_hook() 7387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.flist = None 7397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer colorizing = 0 7407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.unload_extensions() 7417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.io.close(); self.io = None 7427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.undo = None # XXX 7437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 7447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer colorizing = self.color.colorizing 7457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer doh = colorizing and self.top 7467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.color.close(doh) # Cancel colorization 7477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text = None 7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.vars = None 7497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.per.close(); self.per = None 7507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not colorizing: 7517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.top.destroy() 7527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_extensions(self): 7547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions = {} 7557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_standard_extensions() 7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def unload_extensions(self): 7587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for ins in self.extensions.values(): 7597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(ins, "close"): 7607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ins.close() 7617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions = {} 7627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_standard_extensions(self): 7647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for name in self.get_standard_extension_names(): 7657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 7667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.load_extension(name) 7677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except: 7687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer print "Failed to load extension", `name` 7697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer import traceback 7707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer traceback.print_exc() 7717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_standard_extension_names(self): 773dc72f48e262a7aaf177a37676c79ced4ddce0fffSteven M. Gava return idleConf.GetExtensions() 7747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def load_extension(self, name): 7767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer mod = __import__(name, globals(), locals(), []) 7777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer cls = getattr(mod, name) 7787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer ins = cls(self) 7797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.extensions[name] = ins 78072c3bf076f785aaf54d63a7e8cae29bc8282920eSteven M. Gava keydefs=idleConf.GetExtensionBindings(name) 7817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs: 7827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.apply_bindings(keydefs) 7837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for vevent in keydefs.keys(): 784220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser methodname = vevent.replace("-", "_") 7857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer while methodname[:1] == '<': 7867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname[1:] 7877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer while methodname[-1:] == '>': 7887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname[:-1] 7897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer methodname = methodname + "_event" 7907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(ins, methodname): 7917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.text.bind(vevent, getattr(ins, methodname)) 7927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if hasattr(ins, "menudefs"): 7937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.fill_menus(ins.menudefs, keydefs) 7947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return ins 7957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 7967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def apply_bindings(self, keydefs=None): 7977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs is None: 7987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer keydefs = self.Bindings.default_keydefs 7997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 8007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.keydefs = keydefs 8017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for event, keylist in keydefs.items(): 8027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keylist: 8037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer apply(text.event_add, (event,) + tuple(keylist)) 8047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def fill_menus(self, defs=None, keydefs=None): 80683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser """Add appropriate entries to the menus and submenus 80783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser 80883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser Menus that are absent or None in self.menudict are ignored. 80983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser """ 8107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if defs is None: 8117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer defs = self.Bindings.menudefs 8127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if keydefs is None: 8137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer keydefs = self.Bindings.default_keydefs 8147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menudict = self.menudict 8157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 8167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for mname, itemlist in defs: 8177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu = menudict.get(mname) 8187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not menu: 8197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer continue 8207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer for item in itemlist: 8217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not item: 8227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_separator() 8237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 8247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer label, event = item 8257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer checkbutton = (label[:1] == '!') 8267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if checkbutton: 8277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer label = label[1:] 8287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer underline, label = prepstr(label) 8297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer accelerator = get_accelerator(keydefs, event) 8307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def command(text=text, event=event): 8317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.event_generate(event) 8327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if checkbutton: 8337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var = self.getrawvar(event, BooleanVar) 8347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_checkbutton(label=label, underline=underline, 8357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer command=command, accelerator=accelerator, 8367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer variable=var) 8377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 8387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer menu.add_command(label=label, underline=underline, 83984f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser command=command, 84084f4803f4f7ccf40cd777d1e9627528c30bc9053Kurt B. Kaiser accelerator=accelerator) 8417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getvar(self, name): 8437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var = self.getrawvar(name) 8447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if var: 8457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return var.get() 8467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def setvar(self, name, value, vartype=None): 8487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var = self.getrawvar(name, vartype) 8497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if var: 8507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var.set(value) 8517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def getrawvar(self, name, vartype=None): 8537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer var = self.vars.get(name) 8547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not var and vartype: 8557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer self.vars[name] = var = vartype(self.text) 8567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return var 8577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Tk implementations of "virtual text methods" -- each platform 8597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # reusing IDLE's support code needs to define these for its GUI's 8607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # flavor of widget. 8617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Is character at text_index in a Python string? Return 0 for 8637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # "guaranteed no", true for anything else. This info is expensive 8647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # to compute ab initio, but is probably already known by the 8657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # platform's colorizer. 8667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def is_char_in_string(self, text_index): 8687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.color: 8697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Return true iff colorizer hasn't (re)gotten this far 8707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # yet, or the character is tagged as being in a string 8717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return self.text.tag_prevrange("TODO", text_index) or \ 8727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "STRING" in self.text.tag_names(text_index) 8737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 8747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # The colorizer is missing: assume the worst 8757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return 1 8767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # If a selection is defined in the text widget, return (start, 8787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # end) as Tkinter text indices, otherwise return (None, None) 8797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_selection_indices(self): 8807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer try: 8817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer first = self.text.index("sel.first") 8827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer last = self.text.index("sel.last") 8837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return first, last 8847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer except TclError: 8857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return None, None 8867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Return the text widget's current view of what a tab stop means 8887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # (equivalent width in spaces). 8897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def get_tabwidth(self): 8917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer current = self.text['tabs'] or TK_TABWIDTH_DEFAULT 8927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return int(current) 8937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Set the text widget's current view of what a tab stop means. 8957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 8967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer def set_tabwidth(self, newtabwidth): 8977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text = self.text 8987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if self.get_tabwidth() != newtabwidth: 8997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer pixels = text.tk.call("font", "measure", text["font"], 9007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer "-displayof", text.master, 901afdf71b9eefdfb5904e40602984836b28318bad0Kurt B. Kaiser "n" * newtabwidth) 9027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer text.configure(tabs=pixels) 9037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 904cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser### begin autoindent code ### 905cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 906cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # usetabs true -> literal tab characters are used by indent and 907cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # dedent cmds, possibly mixed with spaces if 908cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth is not a multiple of tabwidth 909cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # false -> tab characters are converted to spaces by indent 910cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # and dedent cmds, and ditto TAB keystrokes 911cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth is the number of characters per logical indent level. 912cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # tabwidth is the display width of a literal tab character. 913cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # CAUTION: telling Tk to use anything other than its default 914cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # tab setting causes it to use an entirely different tabbing algorithm, 915cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # treating tab stops as fixed distances from the left margin. 916cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Nobody expects this, so for now tabwidth should never be changed. 917cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser usetabs = 0 918cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indentwidth = 4 919cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tabwidth = 8 # for IDLE use, must remain 8 until Tk is fixed 920cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 921cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # If context_use_ps1 is true, parsing searches back for a ps1 line; 922cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # else searches for a popular (if, def, ...) Python stmt. 923cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser context_use_ps1 = 0 924cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 925cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # When searching backwards for a reliable place to begin parsing, 926cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # first start num_context_lines[0] lines back, then 927cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # num_context_lines[1] lines back if that didn't work, and so on. 928cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # The last value should be huge (larger than the # of lines in a 929cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # conceivable file). 930cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Making the initial values larger slows things down more often. 931cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser num_context_lines = 50, 500, 5000000 932cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 933cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def config(self, **options): 934cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for key, value in options.items(): 935cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if key == 'usetabs': 936cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.usetabs = value 937cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif key == 'indentwidth': 938cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentwidth = value 939cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif key == 'tabwidth': 940cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.tabwidth = value 941cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif key == 'context_use_ps1': 942cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.context_use_ps1 = value 943cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 944cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raise KeyError, "bad option name: %s" % `key` 945cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 946cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # If ispythonsource and guess are true, guess a good value for 947cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth based on file content (if possible), and if 948cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentwidth != tabwidth set usetabs false. 949cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # In any case, adjust the Text widget's view of what a tab 950cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # character means. 951cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 952cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def set_indentation_params(self, ispythonsource, guess=1): 953cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if guess and ispythonsource: 954cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = self.guess_indent() 955cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if 2 <= i <= 8: 956cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentwidth = i 957cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.indentwidth != self.tabwidth: 958cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.usetabs = 0 959cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 960cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_tabwidth(self.tabwidth) 961cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 962cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def smart_backspace_event(self, event): 963cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 964cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 965cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 966cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 967cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 968cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 969cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Delete whitespace left, until hitting a real char or closest 970cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # preceding virtual tab stop. 971cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = text.get("insert linestart", "insert") 972cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if chars == '': 973cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if text.compare("insert", ">", "1.0"): 974cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # easy: delete preceding newline 975cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-1c") 976cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 977cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bell() # at start of buffer 978cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 979cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if chars[-1] not in " \t": 980cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # easy: delete preceding real char 981cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-1c") 982cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 983cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Ick. It may require *inserting* spaces if we back up over a 984cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # tab character! This is written to be clear, not fast. 9851b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser tabwidth = self.tabwidth 9861b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser have = len(chars.expandtabs(tabwidth)) 987cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser assert have > 0 988cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser want = ((have - 1) // self.indentwidth) * self.indentwidth 9894ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # Debug prompt is multilined.... 9904ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser last_line_of_prompt = sys.ps1.split('\n')[-1] 991cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ncharsdeleted = 0 992cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while 1: 9934ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser if chars == last_line_of_prompt: 9941bdca5e051a5424aaaaf7968c710d31132a6c335Kurt B. Kaiser break 995cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = chars[:-1] 996cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ncharsdeleted = ncharsdeleted + 1 9971b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser have = len(chars.expandtabs(tabwidth)) 998cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if have <= want or chars[-1] not in " \t": 999cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser break 1000cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1001cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert-%dc" % ncharsdeleted, "insert") 1002cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if have < want: 1003cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", ' ' * (want - have)) 1004cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1005cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1006cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1007cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def smart_indent_event(self, event): 1008cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # if intraline selection: 1009cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # delete it 1010cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # elif multiline selection: 1011cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # do indent-region & return 1012cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indent one level 1013cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1014cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1015cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1016cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1017cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1018cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if index2line(first) != index2line(last): 1019cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.indent_region_event(event) 1020cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 1021cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 1022cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser prefix = text.get("insert linestart", "insert") 1023cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(prefix, self.tabwidth) 1024cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if raw == len(prefix): 1025cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # only whitespace to the left 1026cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(effective + self.indentwidth) 1027cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1028cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.usetabs: 1029cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pad = '\t' 1030cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 10311b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser effective = len(prefix.expandtabs(self.tabwidth)) 1032cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser n = self.indentwidth 1033cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pad = ' ' * (n - effective % n) 1034cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", pad) 1035cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.see("insert") 1036cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1037cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1038cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1039cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1040cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def newline_and_indent_event(self, event): 1041cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1042cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1043cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1044cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1045cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1046cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(first, last) 1047cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", first) 1048cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = text.get("insert linestart", "insert") 1049cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i, n = 0, len(line) 1050cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while i < n and line[i] in " \t": 1051cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = i+1 1052cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if i == n: 10534ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # the cursor is in or at leading indentation in a continuation 10544ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # line; just inject an empty line at the start 1055cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert linestart", '\n') 1056cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1057cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indent = line[:i] 10584ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser # strip whitespace before insert point unless it's in the prompt 1059cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = 0 10604ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser last_line_of_prompt = sys.ps1.split('\n')[-1] 10614ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser while line and line[-1] in " \t" and line != last_line_of_prompt: 1062cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[:-1] 1063cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = i+1 1064cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if i: 1065cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert - %d chars" % i, "insert") 1066cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # strip whitespace after insert point 1067cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser while text.get("insert") in " \t": 1068cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert") 1069cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # start new line 1070cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", '\n') 1071cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1072cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # adjust indentation for continuations and block 1073cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # open/close first need to find the last stmt 1074cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lno = index2line(text.index('insert')) 1075cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser y = PyParse.Parser(self.indentwidth, self.tabwidth) 1076cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for context in self.num_context_lines: 1077cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser startat = max(lno - context, 1) 1078cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser startatindex = `startat` + ".0" 1079cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser rawtext = text.get(startatindex, "insert") 1080cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser y.set_str(rawtext) 1081cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser bod = y.find_good_parse_start( 1082cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.context_use_ps1, 1083cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self._build_char_in_string_func(startatindex)) 1084cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if bod is not None or startat == 1: 1085cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser break 1086cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser y.set_lo(bod or 0) 1087cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser c = y.get_continuation_type() 1088cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if c != PyParse.C_NONE: 1089cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # The current stmt hasn't ended yet. 1090cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if c == PyParse.C_STRING: 1091cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # inside a string; just mimic the current indent 1092cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1093cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif c == PyParse.C_BRACKET: 1094cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # line up with the first (if any) element of the 1095cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # last open bracket structure; else indent one 1096cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # level beyond the indent of the line with the 1097cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # last open bracket 1098cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(y.compute_bracket_indent()) 1099cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif c == PyParse.C_BACKSLASH: 1100cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # if more than one line in this stmt already, just 1101cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # mimic the current indent; else if initial line 1102cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # has a start on an assignment stmt, indent to 1103cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # beyond leftmost =; else to beyond first chunk of 1104cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # non-whitespace on initial line 1105cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if y.get_num_lines_in_stmt() > 1: 1106cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1107cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1108cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.reindent_to(y.compute_backslash_indent()) 1109cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1110cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser assert 0, "bogus continuation type " + `c` 1111cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1112cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1113cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # This line starts a brand new stmt; indent relative to 1114cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # indentation of initial line of closest preceding 1115cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # interesting stmt. 1116cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indent = y.get_base_indent_string() 1117cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", indent) 1118cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if y.is_block_opener(): 1119cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.smart_indent_event(event) 1120cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif indent and y.is_block_closer(): 1121cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.smart_backspace_event(event) 1122cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1123cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1124cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.see("insert") 1125cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1126cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1127cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Our editwin provides a is_char_in_string function that works 1128cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # with a Tk text index, but PyParse only knows about offsets into 1129cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # a string. This builds a function for PyParse that accepts an 1130cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # offset. 1131cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1132cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _build_char_in_string_func(self, startindex): 1133cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def inner(offset, _startindex=startindex, 1134cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _icis=self.is_char_in_string): 1135cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return _icis(_startindex + "+%dc" % offset) 1136cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return inner 1137cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1138cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def indent_region_event(self, event): 1139cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1140cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1141cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1142cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1143cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, self.tabwidth) 1144cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = effective + self.indentwidth 1145cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = self._make_blanks(effective) + line[raw:] 1146cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1147cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1148cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1149cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def dedent_region_event(self, event): 1150cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1151cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1152cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1153cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1154cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, self.tabwidth) 1155cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = max(effective - self.indentwidth, 0) 1156cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = self._make_blanks(effective) + line[raw:] 1157cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1158cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1159cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1160cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def comment_region_event(self, event): 1161cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1162cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines) - 1): 1163cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1164cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = '##' + line 1165cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1166cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1167cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def uncomment_region_event(self, event): 1168cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1169cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1170cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1171cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if not line: 1172cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser continue 1173cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line[:2] == '##': 1174cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[2:] 1175cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif line[:1] == '#': 1176cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = line[1:] 1177cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = line 1178cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1179cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1180cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def tabify_region_event(self, event): 1181cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1182cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tabwidth = self._asktabwidth() 1183cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 1184cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser line = lines[pos] 1185cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if line: 1186cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, effective = classifyws(line, tabwidth) 1187cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ntabs, nspaces = divmod(effective, tabwidth) 1188cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] 1189cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1190cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1191cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def untabify_region_event(self, event): 1192cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head, tail, chars, lines = self.get_region() 1193cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tabwidth = self._asktabwidth() 1194cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for pos in range(len(lines)): 11951b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser lines[pos] = lines[pos].expandtabs(tabwidth) 1196cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_region(head, tail, chars, lines) 1197cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1198cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def toggle_tabs_event(self, event): 1199cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.askyesno( 1200cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Toggle tabs", 1201cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Turn tabs " + ("on", "off")[self.usetabs] + "?", 1202cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text): 1203cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.usetabs = not self.usetabs 1204cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1205cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1206cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # XXX this isn't bound to anything -- see class tabwidth comments 1207cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def change_tabwidth_event(self, event): 1208cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser new = self._asktabwidth() 1209cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if new != self.tabwidth: 1210cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.tabwidth = new 1211cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.set_indentation_params(0, guess=0) 1212cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1213cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1214cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def change_indentwidth_event(self, event): 1215cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser new = self.askinteger( 1216cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Indent width", 1217cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "New indent width (2-16)", 1218cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text, 1219cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser initialvalue=self.indentwidth, 1220cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser minvalue=2, 1221cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser maxvalue=16) 1222cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if new and new != self.indentwidth: 1223cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentwidth = new 1224cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "break" 1225cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1226cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def get_region(self): 1227cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1228cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser first, last = self.get_selection_indices() 1229cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if first and last: 1230cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head = text.index(first + " linestart") 1231cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tail = text.index(last + "-1c lineend +1c") 1232cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1233cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser head = text.index("insert linestart") 1234cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser tail = text.index("insert lineend +1c") 1235cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser chars = text.get(head, tail) 12361b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser lines = chars.split("\n") 1237cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return head, tail, chars, lines 1238cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1239cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def set_region(self, head, tail, chars, lines): 1240cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 12411b3c26998e0f8b6975f7bbccf043c0afe398f151Kurt B. Kaiser newchars = "\n".join(lines) 1242cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if newchars == chars: 1243cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.bell() 1244cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return 1245cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.tag_remove("sel", "1.0", "end") 1246cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.mark_set("insert", head) 1247cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1248cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete(head, tail) 1249cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert(head, newchars) 1250cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1251cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.tag_add("sel", head, "insert") 1252cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1253cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Make string that displays as n leading blanks. 1254cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1255cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _make_blanks(self, n): 1256cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.usetabs: 1257cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser ntabs, nspaces = divmod(n, self.tabwidth) 1258cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return '\t' * ntabs + ' ' * nspaces 1259cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1260cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return ' ' * n 1261cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1262cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Delete from beginning of line to insert point, then reinsert 1263cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # column logical (meaning use tabs if appropriate) spaces. 1264cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1265cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def reindent_to(self, column): 1266cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text = self.text 1267cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_start() 1268cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if text.compare("insert linestart", "!=", "insert"): 1269cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.delete("insert linestart", "insert") 1270cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if column: 1271cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.insert("insert", self._make_blanks(column)) 1272cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser text.undo_block_stop() 1273cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1274cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def _asktabwidth(self): 1275cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.askinteger( 1276cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Tab width", 1277cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser "Spaces per tab? (2-16)", 1278cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser parent=self.text, 1279cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser initialvalue=self.indentwidth, 1280cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser minvalue=2, 1281cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser maxvalue=16) or self.tabwidth 1282cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1283cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Guess indentwidth from text content. 1284cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Return guessed indentwidth. This should not be believed unless 1285cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # it's in a reasonable range (e.g., it will be 0 if no indented 1286cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # blocks are found). 1287cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1288cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def guess_indent(self): 1289cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser opener, indented = IndentSearcher(self.text, self.tabwidth).run() 1290cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if opener and indented: 1291cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, indentsmall = classifyws(opener, self.tabwidth) 1292cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw, indentlarge = classifyws(indented, self.tabwidth) 1293cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1294cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser indentsmall = indentlarge = 0 1295cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return indentlarge - indentsmall 1296cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1297cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# "line.col" -> line, as an int 1298cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdef index2line(index): 1299cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return int(float(index)) 1300cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1301cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# Look at the leading whitespace in s. 1302cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# Return pair (# of leading ws characters, 1303cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# effective # of leading blanks after expanding 1304cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser# tabs to width tabwidth) 1305cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1306cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdef classifyws(s, tabwidth): 1307cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = effective = 0 1308cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser for ch in s: 1309cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if ch == ' ': 1310cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = raw + 1 1311cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = effective + 1 1312cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif ch == '\t': 1313cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser raw = raw + 1 1314cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser effective = (effective // tabwidth + 1) * tabwidth 1315cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser else: 1316cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser break 1317cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return raw, effective 1318cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1319cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserimport tokenize 1320cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser_tokenize = tokenize 1321cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserdel tokenize 1322cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1323cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiserclass IndentSearcher: 1324cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1325cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # .run() chews over the Text widget, looking for a block opener 1326cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # and the stmt following it. Returns a pair, 1327cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # (line containing block opener, line containing stmt) 1328cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # Either or both may be None. 1329cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1330cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def __init__(self, text, tabwidth): 1331cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.text = text 1332cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.tabwidth = tabwidth 1333cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.i = self.finished = 0 1334cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.blkopenline = self.indentedline = None 1335cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1336cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def readline(self): 1337cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.finished: 1338cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "" 1339cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser i = self.i = self.i + 1 1340cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser mark = `i` + ".0" 1341cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.text.compare(mark, ">=", "end"): 1342cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return "" 1343cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.text.get(mark, mark + " lineend+1c") 1344cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1345cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def tokeneater(self, type, token, start, end, line, 1346cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser INDENT=_tokenize.INDENT, 1347cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser NAME=_tokenize.NAME, 1348cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser OPENERS=('class', 'def', 'for', 'if', 'try', 'while')): 1349cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser if self.finished: 1350cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pass 1351cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif type == NAME and token in OPENERS: 1352cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.blkopenline = line 1353cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser elif type == INDENT and self.blkopenline: 1354cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.indentedline = line 1355cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser self.finished = 1 1356cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1357cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser def run(self): 1358cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser save_tabsize = _tokenize.tabsize 1359cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tabsize = self.tabwidth 1360cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1361cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser try: 1362cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tokenize(self.readline, self.tokeneater) 1363cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser except _tokenize.TokenError: 1364cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # since we cut off the tokenizer early, we can trigger 1365cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser # spurious errors 1366cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser pass 1367cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser finally: 1368cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser _tokenize.tabsize = save_tabsize 1369cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser return self.blkopenline, self.indentedline 1370cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 1371cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser### end autoindent code ### 1372cb7a383bad7e7085f1bd6067865516aa9244cf23Kurt B. Kaiser 13737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef prepstr(s): 13747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Helper to extract the underscore from a string, e.g. 13757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # prepstr("Co_py") returns (2, "Copy"). 1376220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser i = s.find('_') 13777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if i >= 0: 13787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = s[:i] + s[i+1:] 13797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return i, s 13807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 13817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 13827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererkeynames = { 13837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'bracketleft': '[', 13847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'bracketright': ']', 13857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 'slash': '/', 13867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer} 13877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 13887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef get_accelerator(keydefs, event): 13897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer keylist = keydefs.get(event) 13907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if not keylist: 13917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return "" 13927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = keylist[0] 1393220ecbc731bf600fe977e1721f2f5c1aec7b033cKurt B. Kaiser s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) 13947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s) 13957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Key-", "", s) 13967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu 13977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("Control-", "Ctrl-", s) 13987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("-", "+", s) 13997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("><", " ", s) 14007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub("<", "", s) 14017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer s = re.sub(">", "", s) 14027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer return s 14037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 14047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 14057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef fixwordbreaks(root): 14067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # Make sure that Tk's double-click and next/previous word 14077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer # operations use our definition of a word (i.e. an identifier) 14087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk = root.tk 14097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded 14107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]') 14117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') 14127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 14137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 14147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef test(): 14157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root = Tk() 14167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer fixwordbreaks(root) 14177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root.withdraw() 14187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer if sys.argv[1:]: 14197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = sys.argv[1] 14207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer else: 14217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer filename = None 14227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit = EditorWindow(root=root, filename=filename) 14237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer edit.set_close_hook(root.quit) 14247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root.mainloop() 14257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer root.destroy() 14267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer 14277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == '__main__': 14287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer test() 1429