diff options
author | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
commit | a73a964e51247ed169d322c725a3a18859f109a3 (patch) | |
tree | 3f752d117274d444bda44e85609aeac1acf313f3 /sys/lib/python/idlelib | |
parent | e64efe273fcb921a61bf27d33b230c4e64fcd425 (diff) |
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/lib/python/idlelib')
79 files changed, 0 insertions, 18407 deletions
diff --git a/sys/lib/python/idlelib/AutoComplete.py b/sys/lib/python/idlelib/AutoComplete.py deleted file mode 100644 index 708538662..000000000 --- a/sys/lib/python/idlelib/AutoComplete.py +++ /dev/null @@ -1,226 +0,0 @@ -"""AutoComplete.py - An IDLE extension for automatically completing names. - -This extension can complete either attribute names of file names. It can pop -a window with all available names, for the user to select from. -""" -import os -import sys -import string - -from configHandler import idleConf - -import AutoCompleteWindow -from HyperParser import HyperParser - -import __main__ - -# This string includes all chars that may be in a file name (without a path -# separator) -FILENAME_CHARS = string.ascii_letters + string.digits + os.curdir + "._~#$:-" -# This string includes all chars that may be in an identifier -ID_CHARS = string.ascii_letters + string.digits + "_" - -# These constants represent the two different types of completions -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - -class AutoComplete: - - menudefs = [ - ('edit', [ - ("Show completions", "<<force-open-completions>>"), - ]) - ] - - popupwait = idleConf.GetOption("extensions", "AutoComplete", - "popupwait", type="int", default=0) - - def __init__(self, editwin=None): - if editwin == None: # subprocess and test - self.editwin = None - return - self.editwin = editwin - self.text = editwin.text - self.autocompletewindow = None - - # id of delayed call, and the index of the text insert when the delayed - # call was issued. If _delayed_completion_id is None, there is no - # delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None - - def _make_autocomplete_window(self): - return AutoCompleteWindow.AutoCompleteWindow(self.text) - - def _remove_autocomplete_window(self, event=None): - if self.autocompletewindow: - self.autocompletewindow.hide_window() - self.autocompletewindow = None - - def force_open_completions_event(self, event): - """Happens when the user really wants to open a completion list, even - if a function call is needed. - """ - self.open_completions(True, False, True) - - def try_open_completions_event(self, event): - """Happens when it would be nice to open a completion list, but not - really neccesary, for example after an dot, so function - calls won't be made. - """ - lastchar = self.text.get("insert-1c") - if lastchar == ".": - self._open_completions_later(False, False, False, - COMPLETE_ATTRIBUTES) - elif lastchar == os.sep: - self._open_completions_later(False, False, False, - COMPLETE_FILES) - - def autocomplete_event(self, event): - """Happens when the user wants to complete his word, and if neccesary, - open a completion list after that (if there is more than one - completion) - """ - if hasattr(event, "mc_state") and event.mc_state: - # A modifier was pressed along with the tab, continue as usual. - return - if self.autocompletewindow and self.autocompletewindow.is_active(): - self.autocompletewindow.complete() - return "break" - else: - opened = self.open_completions(False, True, True) - if opened: - return "break" - - def _open_completions_later(self, *args): - self._delayed_completion_index = self.text.index("insert") - if self._delayed_completion_id is not None: - self.text.after_cancel(self._delayed_completion_id) - self._delayed_completion_id = \ - self.text.after(self.popupwait, self._delayed_open_completions, - *args) - - def _delayed_open_completions(self, *args): - self._delayed_completion_id = None - if self.text.index("insert") != self._delayed_completion_index: - return - self.open_completions(*args) - - def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): - """Find the completions and create the AutoCompleteWindow. - Return True if successful (no syntax error or so found). - if complete is True, then if there's nothing to complete and no - start of completion, won't open completions and return False. - If mode is given, will open a completion list only in this mode. - """ - # Cancel another delayed call, if it exists. - if self._delayed_completion_id is not None: - self.text.after_cancel(self._delayed_completion_id) - self._delayed_completion_id = None - - hp = HyperParser(self.editwin, "insert") - curline = self.text.get("insert linestart", "insert") - i = j = len(curline) - if hp.is_in_string() and (not mode or mode==COMPLETE_FILES): - self._remove_autocomplete_window() - mode = COMPLETE_FILES - while i and curline[i-1] in FILENAME_CHARS: - i -= 1 - comp_start = curline[i:j] - j = i - while i and curline[i-1] in FILENAME_CHARS+os.sep: - i -= 1 - comp_what = curline[i:j] - elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES): - self._remove_autocomplete_window() - mode = COMPLETE_ATTRIBUTES - while i and curline[i-1] in ID_CHARS: - i -= 1 - comp_start = curline[i:j] - if i and curline[i-1] == '.': - hp.set_index("insert-%dc" % (len(curline)-(i-1))) - comp_what = hp.get_expression() - if not comp_what or \ - (not evalfuncs and comp_what.find('(') != -1): - return - else: - comp_what = "" - else: - return - - if complete and not comp_what and not comp_start: - return - comp_lists = self.fetch_completions(comp_what, mode) - if not comp_lists[0]: - return - self.autocompletewindow = self._make_autocomplete_window() - self.autocompletewindow.show_window(comp_lists, - "insert-%dc" % len(comp_start), - complete, - mode, - userWantsWin) - return True - - def fetch_completions(self, what, mode): - """Return a pair of lists of completions for something. The first list - is a sublist of the second. Both are sorted. - - If there is a Python subprocess, get the comp. list there. Otherwise, - either fetch_completions() is running in the subprocess itself or it - was called in an IDLE EditorWindow before any script had been run. - - The subprocess environment is that of the most recently run script. If - two unrelated modules are being edited some calltips in the current - module may be inoperative if the module was not the last to run. - """ - try: - rpcclt = self.editwin.flist.pyshell.interp.rpcclt - except: - rpcclt = None - if rpcclt: - return rpcclt.remotecall("exec", "get_the_completion_list", - (what, mode), {}) - else: - if mode == COMPLETE_ATTRIBUTES: - if what == "": - namespace = __main__.__dict__.copy() - namespace.update(__main__.__builtins__.__dict__) - bigl = eval("dir()", namespace) - bigl.sort() - if "__all__" in bigl: - smalll = eval("__all__", namespace) - smalll.sort() - else: - smalll = filter(lambda s: s[:1] != '_', bigl) - else: - try: - entity = self.get_entity(what) - bigl = dir(entity) - bigl.sort() - if "__all__" in bigl: - smalll = entity.__all__ - smalll.sort() - else: - smalll = filter(lambda s: s[:1] != '_', bigl) - except: - return [], [] - - elif mode == COMPLETE_FILES: - if what == "": - what = "." - try: - expandedpath = os.path.expanduser(what) - bigl = os.listdir(expandedpath) - bigl.sort() - smalll = filter(lambda s: s[:1] != '.', bigl) - except OSError: - return [], [] - - if not smalll: - smalll = bigl - return smalll, bigl - - def get_entity(self, name): - """Lookup name in a namespace spanning sys.modules and __main.dict__""" - namespace = sys.modules.copy() - namespace.update(__main__.__dict__) - return eval(name, namespace) diff --git a/sys/lib/python/idlelib/AutoCompleteWindow.py b/sys/lib/python/idlelib/AutoCompleteWindow.py deleted file mode 100644 index d8bbff4a1..000000000 --- a/sys/lib/python/idlelib/AutoCompleteWindow.py +++ /dev/null @@ -1,393 +0,0 @@ -""" -An auto-completion window for IDLE, used by the AutoComplete extension -""" -from Tkinter import * -from MultiCall import MC_SHIFT -import AutoComplete - -HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>" -HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>") -KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>" -# We need to bind event beyond <Key> so that the function will be called -# before the default specific IDLE function -KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", - "<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>") -KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>" -KEYRELEASE_SEQUENCE = "<KeyRelease>" -LISTUPDATE_SEQUENCE = "<ButtonRelease>" -WINCONFIG_SEQUENCE = "<Configure>" -DOUBLECLICK_SEQUENCE = "<Double-ButtonRelease>" - -class AutoCompleteWindow: - - def __init__(self, widget): - # The widget (Text) on which we place the AutoCompleteWindow - self.widget = widget - # The widgets we create - self.autocompletewindow = self.listbox = self.scrollbar = None - # The default foreground and background of a selection. Saved because - # they are changed to the regular colors of list items when the - # completion start is not a prefix of the selected completion - self.origselforeground = self.origselbackground = None - # The list of completions - self.completions = None - # A list with more completions, or None - self.morecompletions = None - # The completion mode. Either AutoComplete.COMPLETE_ATTRIBUTES or - # AutoComplete.COMPLETE_FILES - self.mode = None - # The current completion start, on the text box (a string) - self.start = None - # The index of the start of the completion - self.startindex = None - # The last typed start, used so that when the selection changes, - # the new start will be as close as possible to the last typed one. - self.lasttypedstart = None - # Do we have an indication that the user wants the completion window - # (for example, he clicked the list) - self.userwantswindow = None - # event ids - self.hideid = self.keypressid = self.listupdateid = self.winconfigid \ - = self.keyreleaseid = self.doubleclickid = None - - def _change_start(self, newstart): - i = 0 - while i < len(self.start) and i < len(newstart) and \ - self.start[i] == newstart[i]: - i += 1 - if i < len(self.start): - self.widget.delete("%s+%dc" % (self.startindex, i), - "%s+%dc" % (self.startindex, len(self.start))) - if i < len(newstart): - self.widget.insert("%s+%dc" % (self.startindex, i), - newstart[i:]) - self.start = newstart - - def _binary_search(self, s): - """Find the first index in self.completions where completions[i] is - greater or equal to s, or the last index if there is no such - one.""" - i = 0; j = len(self.completions) - while j > i: - m = (i + j) // 2 - if self.completions[m] >= s: - j = m - else: - i = m + 1 - return min(i, len(self.completions)-1) - - def _complete_string(self, s): - """Assuming that s is the prefix of a string in self.completions, - return the longest string which is a prefix of all the strings which - s is a prefix of them. If s is not a prefix of a string, return s.""" - first = self._binary_search(s) - if self.completions[first][:len(s)] != s: - # There is not even one completion which s is a prefix of. - return s - # Find the end of the range of completions where s is a prefix of. - i = first + 1 - j = len(self.completions) - while j > i: - m = (i + j) // 2 - if self.completions[m][:len(s)] != s: - j = m - else: - i = m + 1 - last = i-1 - - # We should return the maximum prefix of first and last - i = len(s) - while len(self.completions[first]) > i and \ - len(self.completions[last]) > i and \ - self.completions[first][i] == self.completions[last][i]: - i += 1 - return self.completions[first][:i] - - def _selection_changed(self): - """Should be called when the selection of the Listbox has changed. - Updates the Listbox display and calls _change_start.""" - cursel = int(self.listbox.curselection()[0]) - - self.listbox.see(cursel) - - lts = self.lasttypedstart - selstart = self.completions[cursel] - if self._binary_search(lts) == cursel: - newstart = lts - else: - i = 0 - while i < len(lts) and i < len(selstart) and lts[i] == selstart[i]: - i += 1 - while cursel > 0 and selstart[:i] <= self.completions[cursel-1]: - i += 1 - newstart = selstart[:i] - self._change_start(newstart) - - if self.completions[cursel][:len(self.start)] == self.start: - # start is a prefix of the selected completion - self.listbox.configure(selectbackground=self.origselbackground, - selectforeground=self.origselforeground) - else: - self.listbox.configure(selectbackground=self.listbox.cget("bg"), - selectforeground=self.listbox.cget("fg")) - # If there are more completions, show them, and call me again. - if self.morecompletions: - self.completions = self.morecompletions - self.morecompletions = None - self.listbox.delete(0, END) - for item in self.completions: - self.listbox.insert(END, item) - self.listbox.select_set(self._binary_search(self.start)) - self._selection_changed() - - def show_window(self, comp_lists, index, complete, mode, userWantsWin): - """Show the autocomplete list, bind events. - If complete is True, complete the text, and if there is exactly one - matching completion, don't open a list.""" - # Handle the start we already have - self.completions, self.morecompletions = comp_lists - self.mode = mode - self.startindex = self.widget.index(index) - self.start = self.widget.get(self.startindex, "insert") - if complete: - completed = self._complete_string(self.start) - self._change_start(completed) - i = self._binary_search(completed) - if self.completions[i] == completed and \ - (i == len(self.completions)-1 or - self.completions[i+1][:len(completed)] != completed): - # There is exactly one matching completion - return - self.userwantswindow = userWantsWin - self.lasttypedstart = self.start - - # Put widgets in place - self.autocompletewindow = acw = Toplevel(self.widget) - # Put it in a position so that it is not seen. - acw.wm_geometry("+10000+10000") - # Make it float - acw.wm_overrideredirect(1) - try: - # This command is only needed and available on Tk >= 8.4.0 for OSX - # Without it, call tips intrude on the typing process by grabbing - # the focus. - acw.tk.call("::tk::unsupported::MacWindowStyle", "style", acw._w, - "help", "noActivates") - except TclError: - pass - self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL) - self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set, - exportselection=False, bg="white") - for item in self.completions: - listbox.insert(END, item) - self.origselforeground = listbox.cget("selectforeground") - self.origselbackground = listbox.cget("selectbackground") - scrollbar.config(command=listbox.yview) - scrollbar.pack(side=RIGHT, fill=Y) - listbox.pack(side=LEFT, fill=BOTH, expand=True) - - # Initialize the listbox selection - self.listbox.select_set(self._binary_search(self.start)) - self._selection_changed() - - # bind events - self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, - self.hide_event) - for seq in HIDE_SEQUENCES: - self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq) - self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME, - self.keypress_event) - for seq in KEYPRESS_SEQUENCES: - self.widget.event_add(KEYPRESS_VIRTUAL_EVENT_NAME, seq) - self.keyreleaseid = self.widget.bind(KEYRELEASE_VIRTUAL_EVENT_NAME, - self.keyrelease_event) - self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE) - self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE, - self.listupdate_event) - self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event) - self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE, - self.doubleclick_event) - - def winconfig_event(self, event): - if not self.is_active(): - return - # Position the completion list window - acw = self.autocompletewindow - self.widget.see(self.startindex) - x, y, cx, cy = self.widget.bbox(self.startindex) - acw.wm_geometry("+%d+%d" % (x + self.widget.winfo_rootx(), - y + self.widget.winfo_rooty() \ - -acw.winfo_height())) - - - def hide_event(self, event): - if not self.is_active(): - return - self.hide_window() - - def listupdate_event(self, event): - if not self.is_active(): - return - self.userwantswindow = True - self._selection_changed() - - def doubleclick_event(self, event): - # Put the selected completion in the text, and close the list - cursel = int(self.listbox.curselection()[0]) - self._change_start(self.completions[cursel]) - self.hide_window() - - def keypress_event(self, event): - if not self.is_active(): - return - keysym = event.keysym - if hasattr(event, "mc_state"): - state = event.mc_state - else: - state = 0 - - if (len(keysym) == 1 or keysym in ("underscore", "BackSpace") - or (self.mode==AutoComplete.COMPLETE_FILES and keysym in - ("period", "minus"))) \ - and not (state & ~MC_SHIFT): - # Normal editing of text - if len(keysym) == 1: - self._change_start(self.start + keysym) - elif keysym == "underscore": - self._change_start(self.start + '_') - elif keysym == "period": - self._change_start(self.start + '.') - elif keysym == "minus": - self._change_start(self.start + '-') - else: - # keysym == "BackSpace" - if len(self.start) == 0: - self.hide_window() - return - self._change_start(self.start[:-1]) - self.lasttypedstart = self.start - self.listbox.select_clear(0, int(self.listbox.curselection()[0])) - self.listbox.select_set(self._binary_search(self.start)) - self._selection_changed() - return "break" - - elif keysym == "Return" and not state: - # If start is a prefix of the selection, or there was an indication - # that the user used the completion window, put the selected - # completion in the text, and close the list. - # Otherwise, close the window and let the event through. - cursel = int(self.listbox.curselection()[0]) - if self.completions[cursel][:len(self.start)] == self.start or \ - self.userwantswindow: - self._change_start(self.completions[cursel]) - self.hide_window() - return "break" - else: - self.hide_window() - return - - elif (self.mode == AutoComplete.COMPLETE_ATTRIBUTES and keysym in - ("period", "space", "parenleft", "parenright", "bracketleft", - "bracketright")) or \ - (self.mode == AutoComplete.COMPLETE_FILES and keysym in - ("slash", "backslash", "quotedbl", "apostrophe")) \ - and not (state & ~MC_SHIFT): - # If start is a prefix of the selection, but is not '' when - # completing file names, put the whole - # selected completion. Anyway, close the list. - cursel = int(self.listbox.curselection()[0]) - if self.completions[cursel][:len(self.start)] == self.start \ - and (self.mode==AutoComplete.COMPLETE_ATTRIBUTES or self.start): - self._change_start(self.completions[cursel]) - self.hide_window() - return - - elif keysym in ("Home", "End", "Prior", "Next", "Up", "Down") and \ - not state: - # Move the selection in the listbox - self.userwantswindow = True - cursel = int(self.listbox.curselection()[0]) - if keysym == "Home": - newsel = 0 - elif keysym == "End": - newsel = len(self.completions)-1 - elif keysym in ("Prior", "Next"): - jump = self.listbox.nearest(self.listbox.winfo_height()) - \ - self.listbox.nearest(0) - if keysym == "Prior": - newsel = max(0, cursel-jump) - else: - assert keysym == "Next" - newsel = min(len(self.completions)-1, cursel+jump) - elif keysym == "Up": - newsel = max(0, cursel-1) - else: - assert keysym == "Down" - newsel = min(len(self.completions)-1, cursel+1) - self.listbox.select_clear(cursel) - self.listbox.select_set(newsel) - self._selection_changed() - return "break" - - elif (keysym == "Tab" and not state): - # The user wants a completion, but it is handled by AutoComplete - # (not AutoCompleteWindow), so ignore. - self.userwantswindow = True - return - - elif reduce(lambda x, y: x or y, - [keysym.find(s) != -1 for s in ("Shift", "Control", "Alt", - "Meta", "Command", "Option") - ]): - # A modifier key, so ignore - return - - else: - # Unknown event, close the window and let it through. - self.hide_window() - return - - def keyrelease_event(self, event): - if not self.is_active(): - return - if self.widget.index("insert") != \ - self.widget.index("%s+%dc" % (self.startindex, len(self.start))): - # If we didn't catch an event which moved the insert, close window - self.hide_window() - - def is_active(self): - return self.autocompletewindow is not None - - def complete(self): - self._change_start(self._complete_string(self.start)) - # The selection doesn't change. - - def hide_window(self): - if not self.is_active(): - return - - # unbind events - for seq in HIDE_SEQUENCES: - self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq) - self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid) - self.hideid = None - for seq in KEYPRESS_SEQUENCES: - self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq) - self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid) - self.keypressid = None - self.widget.event_delete(KEYRELEASE_VIRTUAL_EVENT_NAME, - KEYRELEASE_SEQUENCE) - self.widget.unbind(KEYRELEASE_VIRTUAL_EVENT_NAME, self.keyreleaseid) - self.keyreleaseid = None - self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid) - self.listupdateid = None - self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid) - self.winconfigid = None - - # destroy widgets - self.scrollbar.destroy() - self.scrollbar = None - self.listbox.destroy() - self.listbox = None - self.autocompletewindow.destroy() - self.autocompletewindow = None diff --git a/sys/lib/python/idlelib/AutoExpand.py b/sys/lib/python/idlelib/AutoExpand.py deleted file mode 100644 index 9e93d57d6..000000000 --- a/sys/lib/python/idlelib/AutoExpand.py +++ /dev/null @@ -1,83 +0,0 @@ -import string -import re - -###$ event <<expand-word>> -###$ win <Alt-slash> -###$ unix <Alt-slash> - -class AutoExpand: - - menudefs = [ - ('edit', [ - ('E_xpand Word', '<<expand-word>>'), - ]), - ] - - wordchars = string.ascii_letters + string.digits + "_" - - def __init__(self, editwin): - self.text = editwin.text - self.state = None - - def expand_word_event(self, event): - curinsert = self.text.index("insert") - curline = self.text.get("insert linestart", "insert lineend") - if not self.state: - words = self.getwords() - index = 0 - else: - words, index, insert, line = self.state - if insert != curinsert or line != curline: - words = self.getwords() - index = 0 - if not words: - self.text.bell() - return "break" - word = self.getprevword() - self.text.delete("insert - %d chars" % len(word), "insert") - newword = words[index] - index = (index + 1) % len(words) - if index == 0: - self.text.bell() # Warn we cycled around - self.text.insert("insert", newword) - curinsert = self.text.index("insert") - curline = self.text.get("insert linestart", "insert lineend") - self.state = words, index, curinsert, curline - return "break" - - def getwords(self): - word = self.getprevword() - if not word: - return [] - before = self.text.get("1.0", "insert wordstart") - wbefore = re.findall(r"\b" + word + r"\w+\b", before) - del before - after = self.text.get("insert wordend", "end") - wafter = re.findall(r"\b" + word + r"\w+\b", after) - del after - if not wbefore and not wafter: - return [] - words = [] - dict = {} - # search backwards through words before - wbefore.reverse() - for w in wbefore: - if dict.get(w): - continue - words.append(w) - dict[w] = w - # search onwards through words after - for w in wafter: - if dict.get(w): - continue - words.append(w) - dict[w] = w - words.append(word) - return words - - def getprevword(self): - line = self.text.get("insert linestart", "insert") - i = len(line) - while i > 0 and line[i-1] in self.wordchars: - i = i-1 - return line[i:] diff --git a/sys/lib/python/idlelib/Bindings.py b/sys/lib/python/idlelib/Bindings.py deleted file mode 100644 index a3c9fc45f..000000000 --- a/sys/lib/python/idlelib/Bindings.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Define the menu contents, hotkeys, and event bindings. - -There is additional configuration information in the EditorWindow class (and -subclasses): the menus are created there based on the menu_specs (class) -variable, and menus not created are silently skipped in the code here. This -makes it possible, for example, to define a Debug menu which is only present in -the PythonShell window, and a Format menu which is only present in the Editor -windows. - -""" -import sys -from configHandler import idleConf - -menudefs = [ - # underscore prefixes character to underscore - ('file', [ - ('_New Window', '<<open-new-window>>'), - ('_Open...', '<<open-window-from-file>>'), - ('Open _Module...', '<<open-module>>'), - ('Class _Browser', '<<open-class-browser>>'), - ('_Path Browser', '<<open-path-browser>>'), - None, - ('_Save', '<<save-window>>'), - ('Save _As...', '<<save-window-as-file>>'), - ('Save Cop_y As...', '<<save-copy-of-window-as-file>>'), - None, - ('Prin_t Window', '<<print-window>>'), - None, - ('_Close', '<<close-window>>'), - ('E_xit', '<<close-all-windows>>'), - ]), - ('edit', [ - ('_Undo', '<<undo>>'), - ('_Redo', '<<redo>>'), - None, - ('Cu_t', '<<cut>>'), - ('_Copy', '<<copy>>'), - ('_Paste', '<<paste>>'), - ('Select _All', '<<select-all>>'), - None, - ('_Find...', '<<find>>'), - ('Find A_gain', '<<find-again>>'), - ('Find _Selection', '<<find-selection>>'), - ('Find in Files...', '<<find-in-files>>'), - ('R_eplace...', '<<replace>>'), - ('Go to _Line', '<<goto-line>>'), - ]), -('format', [ - ('_Indent Region', '<<indent-region>>'), - ('_Dedent Region', '<<dedent-region>>'), - ('Comment _Out Region', '<<comment-region>>'), - ('U_ncomment Region', '<<uncomment-region>>'), - ('Tabify Region', '<<tabify-region>>'), - ('Untabify Region', '<<untabify-region>>'), - ('Toggle Tabs', '<<toggle-tabs>>'), - ('New Indent Width', '<<change-indentwidth>>'), - ]), - ('run', [ - ('Python Shell', '<<open-python-shell>>'), - ]), - ('shell', [ - ('_View Last Restart', '<<view-restart>>'), - ('_Restart Shell', '<<restart-shell>>'), - ]), - ('debug', [ - ('_Go to File/Line', '<<goto-file-line>>'), - ('!_Debugger', '<<toggle-debugger>>'), - ('_Stack Viewer', '<<open-stack-viewer>>'), - ('!_Auto-open Stack Viewer', '<<toggle-jit-stack-viewer>>'), - ]), - ('options', [ - ('_Configure IDLE...', '<<open-config-dialog>>'), - None, - ]), - ('help', [ - ('_About IDLE', '<<about-idle>>'), - None, - ('_IDLE Help', '<<help>>'), - ('Python _Docs', '<<python-docs>>'), - ]), -] - -import sys -if sys.platform == 'darwin' and '.app' in sys.executable: - # Running as a proper MacOS application bundle. This block restructures - # the menus a little to make them conform better to the HIG. - - quitItem = menudefs[0][1][-1] - closeItem = menudefs[0][1][-2] - - # Remove the last 3 items of the file menu: a separator, close window and - # quit. Close window will be reinserted just above the save item, where - # it should be according to the HIG. Quit is in the application menu. - del menudefs[0][1][-3:] - menudefs[0][1].insert(6, closeItem) - - # Remove the 'About' entry from the help menu, it is in the application - # menu - del menudefs[-1][1][0:2] - - menudefs.insert(0, - ('application', [ - ('About IDLE', '<<about-idle>>'), - None, - ('_Preferences....', '<<open-config-dialog>>'), - ])) - - -default_keydefs = idleConf.GetCurrentKeySet() - -del sys diff --git a/sys/lib/python/idlelib/CREDITS.txt b/sys/lib/python/idlelib/CREDITS.txt deleted file mode 100644 index 30561a9ea..000000000 --- a/sys/lib/python/idlelib/CREDITS.txt +++ /dev/null @@ -1,36 +0,0 @@ -Guido van Rossum, as well as being the creator of the Python language, is the -original creator of IDLE. Other contributors prior to Version 0.8 include -Mark Hammond, Jeremy Hylton, Tim Peters, and Moshe Zadka. - -IDLE's recent development has been carried out in the IDLEfork project. -The objective was to develop a version of IDLE which had an execution -environment which could be initialized prior to each run of user code. - -The IDLEfork project was initiated by David Scherer, with some help from Peter -Schneider-Kamp and Nicholas Riley. David wrote the first version of the RPC -code and designed a fast turn-around environment for VPython. Guido developed -the RPC code and Remote Debugger currently integrated in IDLE. Bruce Sherwood -contributed considerable time testing and suggesting improvements. - -Besides David and Guido, the main developers who have been active on IDLEfork -are Stephen M. Gava, who implemented the configuration GUI, the new -configuration system, and the About dialog, and Kurt B. Kaiser, who completed -the integration of the RPC and remote debugger, implemented the threaded -subprocess, and made a number of usability enhancements. - -Other contributors include Raymond Hettinger, Tony Lownds (Mac integration), -Neal Norwitz (code check and clean-up), Ronald Oussoren (Mac integration), -Noam Raphael (Code Context, Call Tips, many other patches), and Chui Tey (RPC -integration, debugger integration and persistent breakpoints). - -Scott David Daniels, Tal Einat, Hernan Foffani, Christos Georgiou, -Jim Jewett, Martin v. Löwis, Jason Orendorff, Josh Robb, Nigel Rowe, -Bruce Sherwood, and Jeff Shute have submitted useful patches. Thanks, guys! - -For additional details refer to NEWS.txt and Changelog. - -Please contact the IDLE maintainer (kbk@shore.net) to have yourself included -here if you are one of those we missed! - - - diff --git a/sys/lib/python/idlelib/CallTipWindow.py b/sys/lib/python/idlelib/CallTipWindow.py deleted file mode 100644 index 22238855c..000000000 --- a/sys/lib/python/idlelib/CallTipWindow.py +++ /dev/null @@ -1,171 +0,0 @@ -"""A CallTip window class for Tkinter/IDLE. - -After ToolTip.py, which uses ideas gleaned from PySol -Used by the CallTips IDLE extension. - -""" -from Tkinter import * - -HIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-hide>>" -HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>") -CHECKHIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-checkhide>>" -CHECKHIDE_SEQUENCES = ("<KeyRelease>", "<ButtonRelease>") -CHECKHIDE_TIME = 100 # miliseconds - -MARK_RIGHT = "calltipwindowregion_right" - -class CallTip: - - def __init__(self, widget): - self.widget = widget - self.tipwindow = self.label = None - self.parenline = self.parencol = None - self.lastline = None - self.hideid = self.checkhideid = None - - def position_window(self): - """Check if needs to reposition the window, and if so - do it.""" - curline = int(self.widget.index("insert").split('.')[0]) - if curline == self.lastline: - return - self.lastline = curline - self.widget.see("insert") - if curline == self.parenline: - box = self.widget.bbox("%d.%d" % (self.parenline, - self.parencol)) - else: - box = self.widget.bbox("%d.0" % curline) - if not box: - box = list(self.widget.bbox("insert")) - # align to left of window - box[0] = 0 - box[2] = 0 - x = box[0] + self.widget.winfo_rootx() + 2 - y = box[1] + box[3] + self.widget.winfo_rooty() - self.tipwindow.wm_geometry("+%d+%d" % (x, y)) - - def showtip(self, text, parenleft, parenright): - """Show the calltip, bind events which will close it and reposition it. - """ - # truncate overly long calltip - if len(text) >= 79: - textlines = text.splitlines() - for i, line in enumerate(textlines): - if len(line) > 79: - textlines[i] = line[:75] + ' ...' - text = '\n'.join(textlines) - self.text = text - if self.tipwindow or not self.text: - return - - self.widget.mark_set(MARK_RIGHT, parenright) - self.parenline, self.parencol = map( - int, self.widget.index(parenleft).split(".")) - - self.tipwindow = tw = Toplevel(self.widget) - self.position_window() - # remove border on calltip window - tw.wm_overrideredirect(1) - try: - # This command is only needed and available on Tk >= 8.4.0 for OSX - # Without it, call tips intrude on the typing process by grabbing - # the focus. - tw.tk.call("::tk::unsupported::MacWindowStyle", "style", tw._w, - "help", "noActivates") - except TclError: - pass - self.label = Label(tw, text=self.text, justify=LEFT, - background="#ffffe0", relief=SOLID, borderwidth=1, - font = self.widget['font']) - self.label.pack() - - self.checkhideid = self.widget.bind(CHECKHIDE_VIRTUAL_EVENT_NAME, - self.checkhide_event) - for seq in CHECKHIDE_SEQUENCES: - self.widget.event_add(CHECKHIDE_VIRTUAL_EVENT_NAME, seq) - self.widget.after(CHECKHIDE_TIME, self.checkhide_event) - self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, - self.hide_event) - for seq in HIDE_SEQUENCES: - self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq) - - def checkhide_event(self, event=None): - if not self.tipwindow: - # If the event was triggered by the same event that unbinded - # this function, the function will be called nevertheless, - # so do nothing in this case. - return - curline, curcol = map(int, self.widget.index("insert").split('.')) - if curline < self.parenline or \ - (curline == self.parenline and curcol <= self.parencol) or \ - self.widget.compare("insert", ">", MARK_RIGHT): - self.hidetip() - else: - self.position_window() - self.widget.after(CHECKHIDE_TIME, self.checkhide_event) - - def hide_event(self, event): - if not self.tipwindow: - # See the explanation in checkhide_event. - return - self.hidetip() - - def hidetip(self): - if not self.tipwindow: - return - - for seq in CHECKHIDE_SEQUENCES: - self.widget.event_delete(CHECKHIDE_VIRTUAL_EVENT_NAME, seq) - self.widget.unbind(CHECKHIDE_VIRTUAL_EVENT_NAME, self.checkhideid) - self.checkhideid = None - for seq in HIDE_SEQUENCES: - self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq) - self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid) - self.hideid = None - - self.label.destroy() - self.label = None - self.tipwindow.destroy() - self.tipwindow = None - - self.widget.mark_unset(MARK_RIGHT) - self.parenline = self.parencol = self.lastline = None - - def is_active(self): - return bool(self.tipwindow) - - - -############################### -# -# Test Code -# -class container: # Conceptually an editor_window - def __init__(self): - root = Tk() - text = self.text = Text(root) - text.pack(side=LEFT, fill=BOTH, expand=1) - text.insert("insert", "string.split") - root.update() - self.calltip = CallTip(text) - - text.event_add("<<calltip-show>>", "(") - text.event_add("<<calltip-hide>>", ")") - text.bind("<<calltip-show>>", self.calltip_show) - text.bind("<<calltip-hide>>", self.calltip_hide) - - text.focus_set() - root.mainloop() - - def calltip_show(self, event): - self.calltip.showtip("Hello world") - - def calltip_hide(self, event): - self.calltip.hidetip() - -def main(): - # Test code - c=container() - -if __name__=='__main__': - main() diff --git a/sys/lib/python/idlelib/CallTips.py b/sys/lib/python/idlelib/CallTips.py deleted file mode 100644 index 997eb13a0..000000000 --- a/sys/lib/python/idlelib/CallTips.py +++ /dev/null @@ -1,212 +0,0 @@ -"""CallTips.py - An IDLE Extension to Jog Your Memory - -Call Tips are floating windows which display function, class, and method -parameter and docstring information when you type an opening parenthesis, and -which disappear when you type a closing parenthesis. -""" -import sys -import types - -import CallTipWindow -from HyperParser import HyperParser - -import __main__ - -class CallTips: - - menudefs = [ - ('edit', [ - ("Show call tip", "<<force-open-calltip>>"), - ]) - ] - - def __init__(self, editwin=None): - if editwin is None: # subprocess and test - self.editwin = None - return - self.editwin = editwin - self.text = editwin.text - self.calltip = None - self._make_calltip_window = self._make_tk_calltip_window - - def close(self): - self._make_calltip_window = None - - def _make_tk_calltip_window(self): - # See __init__ for usage - return CallTipWindow.CallTip(self.text) - - def _remove_calltip_window(self, event=None): - if self.calltip: - self.calltip.hidetip() - self.calltip = None - - def force_open_calltip_event(self, event): - """Happens when the user really wants to open a CallTip, even if a - function call is needed. - """ - self.open_calltip(True) - - def try_open_calltip_event(self, event): - """Happens when it would be nice to open a CallTip, but not really - neccesary, for example after an opening bracket, so function calls - won't be made. - """ - self.open_calltip(False) - - def refresh_calltip_event(self, event): - """If there is already a calltip window, check if it is still needed, - and if so, reload it. - """ - if self.calltip and self.calltip.is_active(): - self.open_calltip(False) - - def open_calltip(self, evalfuncs): - self._remove_calltip_window() - - hp = HyperParser(self.editwin, "insert") - sur_paren = hp.get_surrounding_brackets('(') - if not sur_paren: - return - hp.set_index(sur_paren[0]) - name = hp.get_expression() - if not name or (not evalfuncs and name.find('(') != -1): - return - arg_text = self.fetch_tip(name) - if not arg_text: - return - self.calltip = self._make_calltip_window() - self.calltip.showtip(arg_text, sur_paren[0], sur_paren[1]) - - def fetch_tip(self, name): - """Return the argument list and docstring of a function or class - - If there is a Python subprocess, get the calltip there. Otherwise, - either fetch_tip() is running in the subprocess itself or it was called - in an IDLE EditorWindow before any script had been run. - - The subprocess environment is that of the most recently run script. If - two unrelated modules are being edited some calltips in the current - module may be inoperative if the module was not the last to run. - - """ - try: - rpcclt = self.editwin.flist.pyshell.interp.rpcclt - except: - rpcclt = None - if rpcclt: - return rpcclt.remotecall("exec", "get_the_calltip", - (name,), {}) - else: - entity = self.get_entity(name) - return get_arg_text(entity) - - def get_entity(self, name): - "Lookup name in a namespace spanning sys.modules and __main.dict__" - if name: - namespace = sys.modules.copy() - namespace.update(__main__.__dict__) - try: - return eval(name, namespace) - except: - return None - -def _find_constructor(class_ob): - # Given a class object, return a function object used for the - # constructor (ie, __init__() ) or None if we can't find one. - try: - return class_ob.__init__.im_func - except AttributeError: - for base in class_ob.__bases__: - rc = _find_constructor(base) - if rc is not None: return rc - return None - -def get_arg_text(ob): - """Get a string describing the arguments for the given object""" - argText = "" - if ob is not None: - argOffset = 0 - if type(ob) in (types.ClassType, types.TypeType): - # Look for the highest __init__ in the class chain. - fob = _find_constructor(ob) - if fob is None: - fob = lambda: None - else: - argOffset = 1 - elif type(ob)==types.MethodType: - # bit of a hack for methods - turn it into a function - # but we drop the "self" param. - fob = ob.im_func - argOffset = 1 - else: - fob = ob - # Try and build one for Python defined functions - if type(fob) in [types.FunctionType, types.LambdaType]: - try: - realArgs = fob.func_code.co_varnames[argOffset:fob.func_code.co_argcount] - defaults = fob.func_defaults or [] - defaults = list(map(lambda name: "=%s" % repr(name), defaults)) - defaults = [""] * (len(realArgs)-len(defaults)) + defaults - items = map(lambda arg, dflt: arg+dflt, realArgs, defaults) - if fob.func_code.co_flags & 0x4: - items.append("...") - if fob.func_code.co_flags & 0x8: - items.append("***") - argText = ", ".join(items) - argText = "(%s)" % argText - except: - pass - # See if we can use the docstring - doc = getattr(ob, "__doc__", "") - if doc: - doc = doc.lstrip() - pos = doc.find("\n") - if pos < 0 or pos > 70: - pos = 70 - if argText: - argText += "\n" - argText += doc[:pos] - return argText - -################################################# -# -# Test code -# -if __name__=='__main__': - - def t1(): "()" - def t2(a, b=None): "(a, b=None)" - def t3(a, *args): "(a, ...)" - def t4(*args): "(...)" - def t5(a, *args): "(a, ...)" - def t6(a, b=None, *args, **kw): "(a, b=None, ..., ***)" - - class TC: - "(a=None, ...)" - def __init__(self, a=None, *b): "(a=None, ...)" - def t1(self): "()" - def t2(self, a, b=None): "(a, b=None)" - def t3(self, a, *args): "(a, ...)" - def t4(self, *args): "(...)" - def t5(self, a, *args): "(a, ...)" - def t6(self, a, b=None, *args, **kw): "(a, b=None, ..., ***)" - - def test(tests): - ct = CallTips() - failed=[] - for t in tests: - expected = t.__doc__ + "\n" + t.__doc__ - name = t.__name__ - arg_text = ct.fetch_tip(name) - if arg_text != expected: - failed.append(t) - print "%s - expected %s, but got %s" % (t, expected, - get_arg_text(entity)) - print "%d of %d tests failed" % (len(failed), len(tests)) - - tc = TC() - tests = (t1, t2, t3, t4, t5, t6, - TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6) - - test(tests) diff --git a/sys/lib/python/idlelib/ChangeLog b/sys/lib/python/idlelib/ChangeLog deleted file mode 100644 index 985871bee..000000000 --- a/sys/lib/python/idlelib/ChangeLog +++ /dev/null @@ -1,1591 +0,0 @@ -Please refer to the IDLEfork and IDLE CVS repositories for -change details subsequent to the 0.8.1 release. - - -IDLEfork ChangeLog -================== - -2001-07-20 11:35 elguavas - - * README.txt, NEWS.txt: bring up to date for 0.8.1 release - -2001-07-19 16:40 elguavas - - * IDLEFORK.html: replaced by IDLEFORK-index.html - -2001-07-19 16:39 elguavas - - * IDLEFORK-index.html: updated placeholder idlefork homepage - -2001-07-19 14:49 elguavas - - * ChangeLog, EditorWindow.py, INSTALLATION, NEWS.txt, README.txt, - TODO.txt, idlever.py: - minor tidy-ups ready for 0.8.1 alpha tarball release - -2001-07-17 15:12 kbk - - * INSTALLATION, setup.py: INSTALLATION: Remove the coexist.patch - instructions - - **************** setup.py: - - Remove the idles script, add some words on IDLE Fork to the - long_description, and clean up some line spacing. - -2001-07-17 15:01 kbk - - * coexist.patch: Put this in the attic, at least for now... - -2001-07-17 14:59 kbk - - * PyShell.py, idle, idles: Implement idle command interface as - suggested by GvR [idle-dev] 16 July **************** PyShell: Added - functionality: - - usage: idle.py [-c command] [-d] [-i] [-r script] [-s] [-t title] - [arg] ... - - idle file(s) (without options) edit the file(s) - - -c cmd run the command in a shell -d enable the - debugger -i open an interactive shell -i file(s) open a - shell and also an editor window for each file -r script run a file - as a script in a shell -s run $IDLESTARTUP or - $PYTHONSTARTUP before anything else -t title set title of shell - window - - Remaining arguments are applied to the command (-c) or script (-r). - - ****************** idles: Removed the idles script, not needed - - ****************** idle: Removed the IdleConf references, not - required anymore - -2001-07-16 17:08 kbk - - * INSTALLATION, coexist.patch: Added installation instructions. - - Added a patch which modifies idlefork so that it can co-exist with - "official" IDLE in the site-packages directory. This patch is not - necessary if only idlefork IDLE is installed. See INSTALLATION for - further details. - -2001-07-16 15:50 kbk - - * idles: Add a script "idles" which opens a Python Shell window. - - The default behaviour of idlefork idle is to open an editor window - instead of a shell. Complex expressions may be run in a fresh - environment by selecting "run". There are times, however, when a - shell is desired. Though one can be started by "idle -t 'foo'", - this script is more convenient. In addition, a shell and an editor - window can be started in parallel by "idles -e foo.py". - -2001-07-16 15:25 kbk - - * PyShell.py: Call out IDLE Fork in startup message. - -2001-07-16 14:00 kbk - - * PyShell.py, setup.py: Add a script "idles" which opens a Python - Shell window. - - The default behaviour of idlefork idle is to open an editor window - instead of a shell. Complex expressions may be run in a fresh - environment by selecting "run". There are times, however, when a - shell is desired. Though one can be started by "idle -t 'foo'", - this script is more convenient. In addition, a shell and an editor - window can be started in parallel by "idles -e foo.py". - -2001-07-15 03:06 kbk - - * pyclbr.py, tabnanny.py: tabnanny and pyclbr are now found in /Lib - -2001-07-15 02:29 kbk - - * BrowserControl.py: Remove, was retained for 1.5.2 support - -2001-07-14 15:48 kbk - - * setup.py: Installing Idle to site-packages via Distutils does not - copy the Idle help.txt file. - - Ref SF Python Patch 422471 - -2001-07-14 15:26 kbk - - * keydefs.py: py-cvs-2001_07_13 (Rev 1.3) merge - - "Make copy, cut and paste events case insensitive. Reported by - Patrick K. O'Brien on idle-dev. (Should other bindings follow - suit?)" --GvR - -2001-07-14 15:21 kbk - - * idle.py: py-cvs-2001_07_13 (Rev 1.4) merge - - "Move the action of loading the configuration to the IdleConf - module rather than the idle.py script. This has advantages and - disadvantages; the biggest advantage being that we can more easily - have an alternative main program." --GvR - -2001-07-14 15:18 kbk - - * extend.txt: py-cvs-2001_07_13 (Rev 1.4) merge - - "Quick update to the extension mechanism (extend.py is gone, long - live config.txt)" --GvR - -2001-07-14 15:15 kbk - - * StackViewer.py: py-cvs-2001_07_13 (Rev 1.16) merge - - "Refactored, with some future plans in mind. This now uses the new - gotofileline() method defined in FileList.py" --GvR - -2001-07-14 15:10 kbk - - * PyShell.py: py-cvs-2001_07_13 (Rev 1.34) merge - - "Amazing. A very subtle change in policy in descr-branch actually - found a bug here. Here's the deal: Class PyShell derives from - class OutputWindow. Method PyShell.close() wants to invoke its - parent method, but because PyShell long ago was inherited from - class PyShellEditorWindow, it invokes - PyShelEditorWindow.close(self). Now, class PyShellEditorWindow - itself derives from class OutputWindow, and inherits the close() - method from there without overriding it. Under the old rules, - PyShellEditorWindow.close would return an unbound method restricted - to the class that defined the implementation of close(), which was - OutputWindow.close. Under the new rules, the unbound method is - restricted to the class whose method was requested, that is - PyShellEditorWindow, and this was correctly trapped as an error." - --GvR - -2001-07-14 14:59 kbk - - * PyParse.py: py-cvs-2001_07_13 (Rel 1.9) merge - - "Taught IDLE's autoident parser that "yield" is a keyword that - begins a stmt. Along w/ the preceding change to keyword.py, making - all this work w/ a future-stmt just looks harder and harder." - --tim_one - - (From Rel 1.8: "Hack to make this still work with Python 1.5.2. - ;-( " --fdrake) - -2001-07-14 14:51 kbk - - * IdleConf.py: py-cvs-2001_07_13 (Rel 1.7) merge - - "Move the action of loading the configuration to the IdleConf - module rather than the idle.py script. This has advantages and - disadvantages; the biggest advantage being that we can more easily - have an alternative main program." --GvR - -2001-07-14 14:45 kbk - - * FileList.py: py-cvs-2000_07_13 (Rev 1.9) merge - - "Delete goodname() method, which is unused. Add gotofileline(), a - convenience method which I intend to use in a variant. Rename - test() to _test()." --GvR - - This was an interesting merge. The join completely missed removing - goodname(), which was adjacent, but outside of, a small conflict. - I only caught it by comparing the 1.1.3.2/1.1.3.3 diff. CVS ain't - infallible. - -2001-07-14 13:58 kbk - - * EditorWindow.py: py-cvs-2000_07_13 (Rev 1.38) merge "Remove - legacy support for the BrowserControl module; the webbrowser module - has been included since Python 2.0, and that is the preferred - interface." --fdrake - -2001-07-14 13:32 kbk - - * EditorWindow.py, FileList.py, IdleConf.py, PyParse.py, - PyShell.py, StackViewer.py, extend.txt, idle.py, keydefs.py: Import - the 2001 July 13 23:59 GMT version of Python CVS IDLE on the - existing 1.1.3 vendor branch named py-cvs-vendor-branch. Release - tag is py-cvs-2001_07_13. - -2001-07-14 12:02 kbk - - * Icons/python.gif: py-cvs-rel2_1 (Rev 1.2) merge Copied py-cvs rev - 1.2 changed file to idlefork MAIN - -2001-07-14 11:58 kbk - - * Icons/minusnode.gif: py-cvs-rel2_1 (Rev 1.2) merge Copied py-cvs - 1.2 changed file to idlefork MAIN - -2001-07-14 11:23 kbk - - * ScrolledList.py: py-cvs-rel2_1 (rev 1.5) merge - whitespace - normalization - -2001-07-14 11:20 kbk - - * Separator.py: py-cvs-rel2_1 (Rev 1.3) merge - whitespace - normalization - -2001-07-14 11:16 kbk - - * StackViewer.py: py-cvs-rel2_1 (Rev 1.15) merge - whitespace - normalization - -2001-07-14 11:14 kbk - - * ToolTip.py: py-cvs-rel2_1 (Rev 1.2) merge - whitespace - normalization - -2001-07-14 10:13 kbk - - * PyShell.py: cvs-py-rel2_1 (Rev 1.29 - 1.33) merge - - Merged the following py-cvs revs without conflict: 1.29 Reduce - copyright text output at startup 1.30 Delay setting sys.args until - Tkinter is fully initialized 1.31 Whitespace normalization 1.32 - Turn syntax warning into error when interactive 1.33 Fix warning - initialization bug - - Note that module is extensively modified wrt py-cvs - -2001-07-14 06:33 kbk - - * PyParse.py: py-cvs-rel2_1 (Rev 1.6 - 1.8) merge Fix autoindent - bug and deflect Unicode from text.get() - -2001-07-14 06:00 kbk - - * Percolator.py: py-cvs-rel2_1 (Rev 1.3) "move "from Tkinter import - *" to module level" --jhylton - -2001-07-14 05:57 kbk - - * PathBrowser.py: py-cvs-rel2_1 (Rev 1.6) merge - whitespace - normalization - -2001-07-14 05:49 kbk - - * ParenMatch.py: cvs-py-rel2_1 (Rev 1.5) merge - whitespace - normalization - -2001-07-14 03:57 kbk - - * ObjectBrowser.py: py-cvs-rel2_1 (Rev 1.3) merge "Make the test - program work outside IDLE." -- GvR - -2001-07-14 03:52 kbk - - * MultiStatusBar.py: py-cvs-rel2_1 (Rev 1.2) merge - whitespace - normalization - -2001-07-14 03:44 kbk - - * MultiScrolledLists.py: py-cvs-rel2_1 (Rev 1.2) merge - whitespace - normalization - -2001-07-14 03:40 kbk - - * IdleHistory.py: py-cvs-rel2_1 (Rev 1.4) merge - whitespace - normalization - -2001-07-14 03:38 kbk - - * IdleConf.py: py-cvs-rel2_1 (Rev 1.6) merge - whitespace - normalization - -2001-07-13 14:18 kbk - - * IOBinding.py: py-cvs-rel2_1 (Rev 1.4) merge - move "import *" to - module level - -2001-07-13 14:12 kbk - - * FormatParagraph.py: py-cvs-rel2_1 (Rev 1.9) merge - whitespace - normalization - -2001-07-13 14:07 kbk - - * FileList.py: py-cvs-rel2_1 (Rev 1.8) merge - whitespace - normalization - -2001-07-13 13:35 kbk - - * EditorWindow.py: py-cvs-rel2_1 (Rev 1.33 - 1.37) merge - - VP IDLE version depended on VP's ExecBinding.py and spawn.py to get - the path to the Windows Doc directory (relative to python.exe). - Removed this conflicting code in favor of py-cvs updates which on - Windows use a hard coded path relative to the location of this - module. py-cvs updates include support for webbrowser.py. Module - still has BrowserControl.py for 1.5.2 support. - - At this point, the differences wrt py-cvs relate to menu - functionality. - -2001-07-13 11:30 kbk - - * ConfigParser.py: py-cvs-rel2_1 merge - Remove, lives in /Lib - -2001-07-13 10:10 kbk - - * Delegator.py: py-cvs-rel2_1 (Rev 1.3) merge - whitespace - normalization - -2001-07-13 10:07 kbk - - * Debugger.py: py-cvs-rel2_1 (Rev 1.15) merge - whitespace - normalization - -2001-07-13 10:04 kbk - - * ColorDelegator.py: py-cvs-rel2_1 (Rev 1.11 and 1.12) merge - Colorize "as" after "import" / use DEBUG instead of __debug__ - -2001-07-13 09:54 kbk - - * ClassBrowser.py: py-cvs-rel2_1 (Rev 1.12) merge - whitespace - normalization - -2001-07-13 09:41 kbk - - * BrowserControl.py: py-cvs-rel2_1 (Rev 1.1) merge - New File - - Force HEAD to trunk with -f Note: browser.py was renamed - BrowserControl.py 10 May 2000. It provides a collection of classes - and convenience functions to control external browsers "for 1.5.2 - support". It was removed from py-cvs 18 April 2001. - -2001-07-13 09:10 kbk - - * CallTips.py: py-cvs-rel2_1 (Rev 1.8) merge - whitespace - normalization - -2001-07-13 08:26 kbk - - * CallTipWindow.py: py-cvs-rel2_1 (Rev 1.3) merge - whitespace - normalization - -2001-07-13 08:13 kbk - - * AutoExpand.py: py-cvs-rel1_2 (Rev 1.4) merge, "Add Alt-slash to - Unix keydefs (I somehow need it on RH 6.2). Get rid of assignment - to unused self.text.wordlist." --GvR - -2001-07-12 16:54 elguavas - - * ReplaceDialog.py: py-cvs merge, python 1.5.2 compatibility - -2001-07-12 16:46 elguavas - - * ScriptBinding.py: py-cvs merge, better error dialog - -2001-07-12 16:38 elguavas - - * TODO.txt: py-cvs merge, additions - -2001-07-12 15:35 elguavas - - * WindowList.py: py-cvs merge, correct indentation - -2001-07-12 15:24 elguavas - - * config.txt: py-cvs merge, correct typo - -2001-07-12 15:21 elguavas - - * help.txt: py-cvs merge, update colour changing info - -2001-07-12 14:51 elguavas - - * idle.py: py-cvs merge, idle_dir loading changed - -2001-07-12 14:44 elguavas - - * idlever.py: py-cvs merge, version update - -2001-07-11 12:53 kbk - - * BrowserControl.py: Initial revision - -2001-07-11 12:53 kbk - - * AutoExpand.py, BrowserControl.py, CallTipWindow.py, CallTips.py, - ClassBrowser.py, ColorDelegator.py, Debugger.py, Delegator.py, - EditorWindow.py, FileList.py, FormatParagraph.py, IOBinding.py, - IdleConf.py, IdleHistory.py, MultiScrolledLists.py, - MultiStatusBar.py, ObjectBrowser.py, OutputWindow.py, - ParenMatch.py, PathBrowser.py, Percolator.py, PyParse.py, - PyShell.py, RemoteInterp.py, ReplaceDialog.py, ScriptBinding.py, - ScrolledList.py, Separator.py, StackViewer.py, TODO.txt, - ToolTip.py, WindowList.py, config.txt, help.txt, idle, idle.bat, - idle.py, idlever.py, setup.py, Icons/minusnode.gif, - Icons/python.gif: Import the release 2.1 version of Python CVS IDLE - on the existing 1.1.3 vendor branch named py-cvs-vendor-branch, - with release tag py-cvs-rel2_1. - -2001-07-11 12:34 kbk - - * AutoExpand.py, AutoIndent.py, Bindings.py, CallTipWindow.py, - CallTips.py, ChangeLog, ClassBrowser.py, ColorDelegator.py, - Debugger.py, Delegator.py, EditorWindow.py, FileList.py, - FormatParagraph.py, FrameViewer.py, GrepDialog.py, IOBinding.py, - IdleConf.py, IdleHistory.py, MultiScrolledLists.py, - MultiStatusBar.py, NEWS.txt, ObjectBrowser.py, OldStackViewer.py, - OutputWindow.py, ParenMatch.py, PathBrowser.py, Percolator.py, - PyParse.py, PyShell.py, README.txt, RemoteInterp.py, - ReplaceDialog.py, ScriptBinding.py, ScrolledList.py, - SearchBinding.py, SearchDialog.py, SearchDialogBase.py, - SearchEngine.py, Separator.py, StackViewer.py, TODO.txt, - ToolTip.py, TreeWidget.py, UndoDelegator.py, WidgetRedirector.py, - WindowList.py, ZoomHeight.py, __init__.py, config-unix.txt, - config-win.txt, config.txt, eventparse.py, extend.txt, help.txt, - idle.bat, idle.py, idle.pyw, idlever.py, keydefs.py, pyclbr.py, - tabnanny.py, testcode.py, Icons/folder.gif, Icons/minusnode.gif, - Icons/openfolder.gif, Icons/plusnode.gif, Icons/python.gif, - Icons/tk.gif: Import the 9 March 2000 version of Python CVS IDLE as - 1.1.3 vendor branch named py-cvs-vendor-branch. - -2001-07-04 13:43 kbk - - * Icons/: folder.gif, minusnode.gif, openfolder.gif, plusnode.gif, - python.gif, tk.gif: Null commit with -f option to force an uprev - and put HEADs firmly on the trunk. - -2001-07-04 13:15 kbk - - * AutoExpand.py, AutoIndent.py, Bindings.py, CallTipWindow.py, - CallTips.py, ChangeLog, ClassBrowser.py, ColorDelegator.py, - ConfigParser.py, Debugger.py, Delegator.py, EditorWindow.py, - ExecBinding.py, FileList.py, FormatParagraph.py, FrameViewer.py, - GrepDialog.py, IDLEFORK.html, IOBinding.py, IdleConf.py, - IdleHistory.py, MultiScrolledLists.py, MultiStatusBar.py, NEWS.txt, - ObjectBrowser.py, OldStackViewer.py, OutputWindow.py, - ParenMatch.py, PathBrowser.py, Percolator.py, PyParse.py, - PyShell.py, README.txt, Remote.py, RemoteInterp.py, - ReplaceDialog.py, ScriptBinding.py, ScrolledList.py, - SearchBinding.py, SearchDialog.py, SearchDialogBase.py, - SearchEngine.py, Separator.py, StackViewer.py, TODO.txt, - ToolTip.py, TreeWidget.py, UndoDelegator.py, WidgetRedirector.py, - WindowList.py, ZoomHeight.py, __init__.py, config-unix.txt, - config-win.txt, config.txt, eventparse.py, extend.txt, help.txt, - idle, idle.bat, idle.py, idle.pyw, idlever.py, keydefs.py, - loader.py, protocol.py, pyclbr.py, setup.py, spawn.py, tabnanny.py, - testcode.py: Null commit with -f option to force an uprev and put - HEADs firmly on the trunk. - -2001-06-27 10:24 elguavas - - * IDLEFORK.html: updated contact details - -2001-06-25 17:23 elguavas - - * idle, RemoteInterp.py, setup.py: Initial revision - -2001-06-25 17:23 elguavas - - * idle, RemoteInterp.py, setup.py: import current python cvs idle - as a vendor branch - -2001-06-24 15:10 elguavas - - * IDLEFORK.html: tiny change to test new syncmail setup - -2001-06-24 14:41 elguavas - - * IDLEFORK.html: change to new developer contact, also a test - commit for new syncmail setup - -2001-06-23 18:15 elguavas - - * IDLEFORK.html: tiny test update for revitalised idle-fork - -2000-09-24 17:29 nriley - - * protocol.py: Fixes for Python 1.6 compatibility - socket bind and - connect get a tuple instead two arguments. - -2000-09-24 17:28 nriley - - * spawn.py: Change for Python 1.6 compatibility - UNIX's 'os' - module defines 'spawnv' now, so we check for 'fork' first. - -2000-08-15 22:51 nowonder - - * IDLEFORK.html: - corrected email address - -2000-08-15 22:47 nowonder - - * IDLEFORK.html: - added .html file for http://idlefork.sourceforge.net - -2000-08-15 11:13 dscherer - - * AutoExpand.py, AutoIndent.py, Bindings.py, CallTipWindow.py, - CallTips.py, __init__.py, ChangeLog, ClassBrowser.py, - ColorDelegator.py, ConfigParser.py, Debugger.py, Delegator.py, - FileList.py, FormatParagraph.py, FrameViewer.py, GrepDialog.py, - IOBinding.py, IdleConf.py, IdleHistory.py, MultiScrolledLists.py, - MultiStatusBar.py, NEWS.txt, ObjectBrowser.py, OldStackViewer.py, - OutputWindow.py, ParenMatch.py, PathBrowser.py, Percolator.py, - PyParse.py, PyShell.py, README.txt, ReplaceDialog.py, - ScriptBinding.py, ScrolledList.py, SearchBinding.py, - SearchDialog.py, SearchDialogBase.py, SearchEngine.py, - Separator.py, StackViewer.py, TODO.txt, ToolTip.py, TreeWidget.py, - UndoDelegator.py, WidgetRedirector.py, WindowList.py, help.txt, - ZoomHeight.py, config-unix.txt, config-win.txt, config.txt, - eventparse.py, extend.txt, idle.bat, idle.py, idle.pyw, idlever.py, - keydefs.py, loader.py, pyclbr.py, tabnanny.py, testcode.py, - EditorWindow.py, ExecBinding.py, Remote.py, protocol.py, spawn.py, - Icons/folder.gif, Icons/minusnode.gif, Icons/openfolder.gif, - Icons/plusnode.gif, Icons/python.gif, Icons/tk.gif: Initial - revision - -2000-08-15 11:13 dscherer - - * AutoExpand.py, AutoIndent.py, Bindings.py, CallTipWindow.py, - CallTips.py, __init__.py, ChangeLog, ClassBrowser.py, - ColorDelegator.py, ConfigParser.py, Debugger.py, Delegator.py, - FileList.py, FormatParagraph.py, FrameViewer.py, GrepDialog.py, - IOBinding.py, IdleConf.py, IdleHistory.py, MultiScrolledLists.py, - MultiStatusBar.py, NEWS.txt, ObjectBrowser.py, OldStackViewer.py, - OutputWindow.py, ParenMatch.py, PathBrowser.py, Percolator.py, - PyParse.py, PyShell.py, README.txt, ReplaceDialog.py, - ScriptBinding.py, ScrolledList.py, SearchBinding.py, - SearchDialog.py, SearchDialogBase.py, SearchEngine.py, - Separator.py, StackViewer.py, TODO.txt, ToolTip.py, TreeWidget.py, - UndoDelegator.py, WidgetRedirector.py, WindowList.py, help.txt, - ZoomHeight.py, config-unix.txt, config-win.txt, config.txt, - eventparse.py, extend.txt, idle.bat, idle.py, idle.pyw, idlever.py, - keydefs.py, loader.py, pyclbr.py, tabnanny.py, testcode.py, - EditorWindow.py, ExecBinding.py, Remote.py, protocol.py, spawn.py, - Icons/folder.gif, Icons/minusnode.gif, Icons/openfolder.gif, - Icons/plusnode.gif, Icons/python.gif, Icons/tk.gif: Modified IDLE - from VPython 0.2 - - -original IDLE ChangeLog: -======================== - -Tue Feb 15 18:08:19 2000 Guido van Rossum <guido@cnri.reston.va.us> - - * NEWS.txt: Notice status bar and stack viewer. - - * EditorWindow.py: Support for Moshe's status bar. - - * MultiStatusBar.py: Status bar code -- by Moshe Zadka. - - * OldStackViewer.py: - Adding the old stack viewer implementation back, for the debugger. - - * StackViewer.py: New stack viewer, uses a tree widget. - (XXX: the debugger doesn't yet use this.) - - * WindowList.py: - Correct a typo and remove an unqualified except that was hiding the error. - - * ClassBrowser.py: Add an XXX comment about the ClassBrowser AIP. - - * ChangeLog: Updated change log. - - * NEWS.txt: News update. Probably incomplete; what else is new? - - * README.txt: - Updated for pending IDLE 0.5 release (still very rough -- just getting - it out in a more convenient format than CVS). - - * TODO.txt: Tiny addition. - -Thu Sep 9 14:16:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TODO.txt: A few new TODO entries. - -Thu Aug 26 23:06:22 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * Bindings.py: Add Python Documentation entry to Help menu. - - * EditorWindow.py: - Find the help.txt file relative to __file__ or ".", not in sys.path. - (Suggested by Moshe Zadka, but implemented differently.) - - Add <<python-docs>> event which, on Unix, brings up Netscape pointing - to http://www.python.doc/current/ (a local copy would be nice but its - location can't be predicted). Windows solution TBD. - -Wed Aug 11 14:55:43 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TreeWidget.py: - Moshe noticed an inconsistency in his comment, so I'm rephrasing it to - be clearer. - - * TreeWidget.py: - Patch inspired by Moshe Zadka to search for the Icons directory in the - same directory as __file__, rather than searching for it along sys.path. - This works better when idle is a package. - -Thu Jul 15 13:11:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TODO.txt: New wishes. - -Sat Jul 10 13:17:35 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * IdlePrefs.py: - Make the color for stderr red (i.e. the standard warning/danger/stop - color) rather than green. Suggested by Sam Schulenburg. - -Fri Jun 25 17:26:34 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * PyShell.py: Close debugger when closing. This may break a cycle. - - * Debugger.py: Break cycle on close. - - * ClassBrowser.py: Destroy the tree when closing. - - * TreeWidget.py: Add destroy() method to recursively destroy a tree. - - * PyShell.py: Extend _close() to break cycles. - Break some other cycles too (and destroy the root when done). - - * EditorWindow.py: - Add _close() method that does the actual cleanup (close() asks the - user what they want first if there's unsaved stuff, and may cancel). - It closes more than before. - - Add unload_extensions() method to unload all extensions; called from - _close(). It calls an extension's close() method if it has one. - - * Percolator.py: Add close() method that breaks cycles. - - * WidgetRedirector.py: Add unregister() method. - Unregister everything at closing. - Don't call close() in __del__, rely on explicit call to close(). - - * IOBinding.py, FormatParagraph.py, CallTips.py: - Add close() method that breaks a cycle. - -Fri Jun 11 15:03:00 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * AutoIndent.py, EditorWindow.py, FormatParagraph.py: - Tim Peters smart.patch: - - EditorWindow.py: - - + Added get_tabwidth & set_tabwidth "virtual text" methods, that get/set the - widget's view of what a tab means. - - + Moved TK_TABWIDTH_DEFAULT here from AutoIndent. - - + Renamed Mark's get_selection_index to get_selection_indices (sorry, Mark, - but the name was plain wrong <wink>). - - FormatParagraph.py: renamed use of get_selection_index. - - AutoIndent.py: - - + Moved TK_TABWIDTH_DEFAULT to EditorWindow. - - + Rewrote set_indentation_params to use new VTW get/set_tabwidth methods. - - + Changed smart_backspace_event to delete whitespace back to closest - preceding virtual tab stop or real character (note that this may require - inserting characters if backspacing over a tab!). - - + Nuked almost references to the selection tag, in favor of using - get_selection_indices. The sole exception is in set_region, for which no - "set_selection" abstraction has yet been agreed upon. - - + Had too much fun using the spiffy new features of the format-paragraph - cmd. - -Thu Jun 10 17:48:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * FormatParagraph.py: - Code by Mark Hammond to format paragraphs embedded in comments. - Read the comments (which I reformatted using the new feature :-) - for some limitations. - - * EditorWindow.py: - Added abstraction get_selection_index() (Mark Hammond). Also - reformatted some comment blocks to show off a cool feature I'm about - to check in next. - - * ClassBrowser.py: - Adapt to the new pyclbr's support of listing top-level functions. If - this functionality is not present (e.g. when used with a vintage - Python 1.5.2 installation) top-level functions are not listed. - - (Hmm... Any distribution of IDLE 0.5 should probably include a copy - of the new pyclbr.py!) - - * AutoIndent.py: - Fix off-by-one error in Tim's recent change to comment_region(): the - list of lines returned by get_region() contains an empty line at the - end representing the start of the next line, and this shouldn't be - commented out! - - * CallTips.py: - Mark Hammond writes: Here is another change that allows it to work for - class creation - tries to locate an __init__ function. Also updated - the test code to reflect your new "***" change. - - * CallTipWindow.py: - Mark Hammond writes: Tim's suggestion of copying the font for the - CallTipWindow from the text control makes sense, and actually makes - the control look better IMO. - -Wed Jun 9 20:34:57 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * CallTips.py: - Append "..." if the appropriate flag (for varargs) in co_flags is set. - Ditto "***" for kwargs. - -Tue Jun 8 13:06:07 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ReplaceDialog.py: - Hmm... Tim didn't turn "replace all" into a single undo block. - I think I like it better if it os, so here. - - * ReplaceDialog.py: Tim Peters: made replacement atomic for undo/redo. - - * AutoIndent.py: Tim Peters: - - + Set usetabs=1. Editing pyclbr.py was driving me nuts <0.6 wink>. - usetabs=1 is the Emacs pymode default too, and thanks to indentwidth != - tabwidth magical usetabs disabling, new files are still created with tabs - turned off. The only implication is that if you open a file whose first - indent is a single tab, IDLE will now magically use tabs for that file (and - set indentwidth to 8). Note that the whole scheme doesn't work right for - PythonWin, though, since Windows users typically set tabwidth to 4; Mark - probably has to hide the IDLE algorithm from them (which he already knows). - - + Changed comment_region_event to stick "##" in front of every line. The - "holes" previously left on blank lines were visually confusing (made it - needlessly hard to figure out what to uncomment later). - -Mon Jun 7 15:38:40 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TreeWidget.py, ObjectBrowser.py: - Remove unnecessary reference to pyclbr from test() code. - - * PyParse.py: Tim Peters: - - Smarter logic for finding a parse synch point. - - Does a half to a fifth the work in normal cases; don't notice the speedup, - but makes more breathing room for other extensions. - - Speeds terrible cases by at least a factor of 10. "Terrible" == e.g. you put - """ at the start of Tkinter.py, undo it, zoom to the bottom, and start - typing in code. Used to take about 8 seconds for ENTER to respond, now some - large fraction of a second. The new code gets indented correctly, despite - that it all remains "string colored" until the colorizer catches up (after - which, ENTER appears instantaneous again). - -Fri Jun 4 19:21:19 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * extend.py: Might as well enable CallTips by default. - If there are too many complaints I'll remove it again or fix it. - -Thu Jun 3 14:32:16 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * AutoIndent.py, EditorWindow.py, PyParse.py: - New offerings by Tim Peters; he writes: - - IDLE is now the first Python editor in the Universe not confused by my - doctest.py <wink>. - - As threatened, this defines IDLE's is_char_in_string function as a - method of EditorWindow. You just need to define one similarly in - whatever it is you pass as editwin to AutoIndent; looking at the - EditorWindow.py part of the patch should make this clear. - - * GrepDialog.py: Enclose pattern in quotes in status message. - - * CallTips.py: - Mark Hammond fixed some comments and improved the way the tip text is - constructed. - -Wed Jun 2 18:18:57 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * CallTips.py: - My fix to Mark's code: restore the universal check on <KeyRelease>. - Always cancel on <Key-Escape> or <ButtonPress>. - - * CallTips.py: - A version that Mark Hammond posted to the newsgroup. Has some newer - stuff for getting the tip. Had to fix the Key-( and Key-) events - for Unix. Will have to re-apply my patch for catching KeyRelease and - ButtonRelease events. - - * CallTipWindow.py, CallTips.py: - Call tips by Mark Hammond (plus tiny fix by me.) - - * IdleHistory.py: - Changes by Mark Hammond: (1) support optional output_sep argument to - the constructor so he can eliminate the sys.ps2 that PythonWin leaves - in the source; (2) remove duplicate history items. - - * AutoIndent.py: - Changes by Mark Hammond to allow using IDLE extensions in PythonWin as - well: make three dialog routines instance variables. - - * EditorWindow.py: - Change by Mark Hammond to allow using IDLE extensions in PythonWin as - well: make three dialog routines instance variables. - -Tue Jun 1 20:06:44 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * AutoIndent.py: Hah! A fix of my own to Tim's code! - Unix bindings for <<toggle-tabs>> and <<change-indentwidth>> were - missing, and somehow that meant the events were never generated, - even though they were in the menu. The new Unix bindings are now - the same as the Windows bindings (M-t and M-u). - - * AutoIndent.py, PyParse.py, PyShell.py: Tim Peters again: - - The new version (attached) is fast enough all the time in every real module - I have <whew!>. You can make it slow by, e.g., creating an open list with - 5,000 90-character identifiers (+ trailing comma) each on its own line, then - adding an item to the end -- but that still consumes less than a second on - my P5-166. Response time in real code appears instantaneous. - - Fixed some bugs. - - New feature: when hitting ENTER and the cursor is beyond the line's leading - indentation, whitespace is removed on both sides of the cursor; before - whitespace was removed only on the left; e.g., assuming the cursor is - between the comma and the space: - - def something(arg1, arg2): - ^ cursor to the left of here, and hit ENTER - arg2): # new line used to end up here - arg2): # but now lines up the way you expect - - New hack: AutoIndent has grown a context_use_ps1 Boolean config option, - defaulting to 0 (false) and set to 1 (only) by PyShell. Reason: handling - the fancy stuff requires looking backward for a parsing synch point; ps1 - lines are the only sensible thing to look for in a shell window, but are a - bad thing to look for in a file window (ps1 lines show up in my module - docstrings often). PythonWin's shell should set this true too. - - Persistent problem: strings containing def/class can still screw things up - completely. No improvement. Simplest workaround is on the user's head, and - consists of inserting e.g. - - def _(): pass - - (or any other def/class) after the end of the multiline string that's - screwing them up. This is especially irksome because IDLE's syntax coloring - is *not* confused, so when this happens the colors don't match the - indentation behavior they see. - - * AutoIndent.py: Tim Peters again: - - [Tim, after adding some bracket smarts to AutoIndent.py] - > ... - > What it can't possibly do without reparsing large gobs of text is - > suggest a reasonable indent level after you've *closed* a bracket - > left open on some previous line. - > ... - - The attached can, and actually fast enough to use -- most of the time. The - code is tricky beyond belief to achieve that, but it works so far; e.g., - - return len(string.expandtabs(str[self.stmt_start : - ^ indents to caret - i], - ^ indents to caret - self.tabwidth)) + 1 - ^ indents to caret - - It's about as smart as pymode now, wrt both bracket and backslash - continuation rules. It does require reparsing large gobs of text, and if it - happens to find something that looks like a "def" or "class" or sys.ps1 - buried in a multiline string, but didn't suck up enough preceding text to - see the start of the string, it's completely hosed. I can't repair that -- - it's just too slow to reparse from the start of the file all the time. - - AutoIndent has grown a new num_context_lines tuple attribute that controls - how far to look back, and-- like other params --this could/should be made - user-overridable at startup and per-file on the fly. - - * PyParse.py: New file by Tim Peters: - - One new file in the attached, PyParse.py. The LineStudier (whatever it was - called <wink>) class was removed from AutoIndent; PyParse subsumes its - functionality. - - * AutoIndent.py: Tim Peters keeps revising this module (more to come): - - Removed "New tabwidth" menu binding. - - Added "a tab means how many spaces?" dialog to block tabify and untabify. I - think prompting for this is good now: they're usually at-most-once-per-file - commands, and IDLE can't let them change tabwidth from the Tk default - anymore, so IDLE can no longer presume to have any idea what a tab means. - - Irony: for the purpose of keeping comments aligned via tabs, Tk's - non-default approach is much nicer than the Emacs/Notepad/Codewright/vi/etc - approach. - - * EditorWindow.py: - 1. Catch NameError on import (could be raised by case mismatch on Windows). - 2. No longer need to reset pyclbr cache and show watch cursor when calling - ClassBrowser -- the ClassBrowser takes care of pyclbr and the TreeWidget - takes care of the watch cursor. - 3. Reset the focus to the current window after error message about class - browser on buffer without filename. - - * Icons/minusnode.gif, Icons/plusnode.gif: Missed a few. - - * ClassBrowser.py, PathBrowser.py: Rewritten based on TreeWidget.py - - * ObjectBrowser.py: Object browser, based on TreeWidget.py. - - * TreeWidget.py: Tree widget done right. - - * ToolTip.py: As yet unused code for tool tips. - - * ScriptBinding.py: - Ensure sys.argv[0] is the script name on Run Script. - - * ZoomHeight.py: Move zoom height functionality to separate function. - - * Icons/folder.gif, Icons/openfolder.gif, Icons/python.gif, Icons/tk.gif: - A few icons used by ../TreeWidget.py and its callers. - - * AutoIndent.py: New version by Tim Peters improves block opening test. - -Fri May 21 04:46:17 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * Attic/History.py, PyShell.py: Rename History to IdleHistory. - Add isatty() to pseudo files. - - * StackViewer.py: Make initial stack viewer wider - - * TODO.txt: New wishes - - * AutoIndent.py, EditorWindow.py, PyShell.py: - Much improved autoindent and handling of tabs, - by Tim Peters. - -Mon May 3 15:49:52 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * AutoIndent.py, EditorWindow.py, FormatParagraph.py, UndoDelegator.py: - Tim Peters writes: - - I'm still unsure, but couldn't stand the virtual event trickery so tried a - different sin (adding undo_block_start/stop methods to the Text instance in - EditorWindow.py). Like it or not, it's efficient and works <wink>. Better - idea? - - Give the attached a whirl. Even if you hate the implementation, I think - you'll like the results. Think I caught all the "block edit" cmds, - including Format Paragraph, plus subtler ones involving smart indents and - backspacing. - - * WidgetRedirector.py: Tim Peters writes: - - [W]hile trying to dope out how redirection works, stumbled into two - possible glitches. In the first, it doesn't appear to make sense to try to - rename a command that's already been destroyed; in the second, the name - "previous" doesn't really bring to mind "ignore the previous value" <wink>. - -Fri Apr 30 19:39:25 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * __init__.py: Support for using idle as a package. - - * PathBrowser.py: - Avoid listing files more than once (e.g. foomodule.so has two hits: - once for foo + module.so, once for foomodule + .so). - -Mon Apr 26 22:20:38 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ChangeLog, ColorDelegator.py, PyShell.py: Tim Peters strikes again: - - Ho ho ho -- that's trickier than it sounded! The colorizer is working with - "line.col" strings instead of Text marks, and the absolute coordinates of - the point of interest can change across the self.update call (voice of - baffled experience, when two quick backspaces no longer fooled it, but a - backspace followed by a quick ENTER did <wink>). - - Anyway, the attached appears to do the trick. CPU usage goes way up when - typing quickly into a long triple-quoted string, but the latency is fine for - me (a relatively fast typist on a relatively slow machine). Most of the - changes here are left over from reducing the # of vrbl names to help me - reason about the logic better; I hope the code is a *little* easier to - -Fri Apr 23 14:01:25 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * EditorWindow.py: - Provide full arguments to __import__ so it works in packagized IDLE. - -Thu Apr 22 23:20:17 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * help.txt: - Bunch of updates necessary due to recent changes; added docs for File - menu, command line and color preferences. - - * Bindings.py: Remove obsolete 'script' menu. - - * TODO.txt: Several wishes fulfilled. - - * OutputWindow.py: - Moved classes OnDemandOutputWindow and PseudoFile here, - from ScriptBinding.py where they are no longer needed. - - * ScriptBinding.py: - Mostly rewritten. Instead of the old Run module and Debug module, - there are two new commands: - - Import module (F5) imports or reloads the module and also adds its - name to the __main__ namespace. This gets executed in the PyShell - window under control of its debug settings. - - Run script (Control-F5) is similar but executes the contents of the - file directly in the __main__ namespace. - - * PyShell.py: Nits: document use of $IDLESTARTUP; display idle version - - * idlever.py: New version to celebrate new command line - - * OutputWindow.py: Added flush(), for completeness. - - * PyShell.py: - A lot of changes to make the command line more useful. You can now do: - idle.py -e file ... -- to edit files - idle.py script arg ... -- to run a script - idle.py -c cmd arg ... -- to run a command - Other options, see also the usage message (also new!) for more details: - -d -- enable debugger - -s -- run $IDLESTARTUP or $PYTHONSTARTUP - -t title -- set Python Shell window's title - sys.argv is set accordingly, unless -e is used. - sys.path is absolutized, and all relevant paths are inserted into it. - - Other changes: - - the environment in which commands are executed is now the - __main__ module - - explicitly save sys.stdout etc., don't restore from sys.__stdout__ - - new interpreter methods execsource(), execfile(), stuffsource() - - a few small nits - - * TODO.txt: - Some more TODO items. Made up my mind about command line args, - Run/Import, __main__. - - * ColorDelegator.py: - Super-elegant patch by Tim Peters that speeds up colorization - dramatically (up to 15 times he claims). Works by reading more than - one line at a time, up to 100-line chunks (starting with one line and - then doubling up to the limit). On a typical machine (e.g. Tim's - P5-166) this doesn't reduce interactive responsiveness in a noticeable - way. - -Wed Apr 21 15:49:34 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ColorDelegator.py: - Patch by Tim Peters to speed up colorizing of big multiline strings. - -Tue Apr 20 17:32:52 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * extend.txt: - For an event 'foo-bar', the corresponding method must be called - foo_bar_event(). Therefore, fix the references to zoom_height() in - the example. - - * IdlePrefs.py: Restored the original IDLE color scheme. - - * PyShell.py, IdlePrefs.py, ColorDelegator.py, EditorWindow.py: - Color preferences code by Loren Luke (massaged by me somewhat) - - * SearchEngine.py: - Patch by Mark Favas: it fixes the search engine behaviour where an - unsuccessful search wraps around and re-searches that part of the file - between the start of the search and the end of the file - only really - an issue for very large files, but... (also removes a redundant - m.span() call). - -Mon Apr 19 16:26:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TODO.txt: A few wishes are now fulfilled. - - * AutoIndent.py: Tim Peters implements some of my wishes: - - o Makes the tab key intelligently insert spaces when appropriate - (see Help list banter twixt David Ascher and me; idea stolen from - every other editor on earth <wink>). - - o newline_and_indent_event trims trailing whitespace on the old - line (pymode and Codewright). - - o newline_and_indent_event no longer fooled by trailing whitespace or - comment after ":" (pymode, PTUI). - - o newline_and_indent_event now reduces the new line's indentation after - return, break, continue, raise and pass stmts (pymode). - - The last two are easy to fool in the presence of strings & - continuations, but pymode requires Emacs's high-powered C parsing - functions to avoid that in finite time. - -====================================================================== - Python release 1.5.2c1, IDLE version 0.4 -====================================================================== - -Wed Apr 7 18:41:59 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * README.txt, NEWS.txt: New version. - - * idlever.py: Version bump awaiting impending new release. - (Not much has changed :-( ) - -Mon Mar 29 14:52:28 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ScriptBinding.py, PyShell.py: - At Tim Peters' recommendation, add a dummy flush() method to - PseudoFile. - -Thu Mar 11 23:21:23 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * PathBrowser.py: Don't crash when sys.path contains an empty string. - - * Attic/Outline.py: This file was never supposed to be part of IDLE. - - * PathBrowser.py: - - Don't crash in the case where a superclass is a string instead of a - pyclbr.Class object; this can happen when the superclass is - unrecognizable (to pyclbr), e.g. when module renaming is used. - - - Show a watch cursor when calling pyclbr (since it may take a while - recursively parsing imported modules!). - -Wed Mar 10 05:18:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * EditorWindow.py, Bindings.py: Add PathBrowser to File module - - * PathBrowser.py: "Path browser" - 4 scrolled lists displaying: - directories on sys.path - modules in selected directory - classes in selected module - methods of selected class - - Sinlge clicking in a directory, module or class item updates the next - column with info about the selected item. Double clicking in a - module, class or method item opens the file (and selects the clicked - item if it is a class or method). - - I guess eventually I should be using a tree widget for this, but the - ones I've seen don't work well enough, so for now I use the old - Smalltalk or NeXT style multi-column hierarchical browser. - - * MultiScrolledLists.py: - New utility: multiple scrolled lists in parallel - - * ScrolledList.py: - White background. - - Display "(None)" (or text of your choosing) when empty. - - Don't set the focus. - -====================================================================== - Python release 1.5.2b2, IDLE version 0.3 -====================================================================== - -Wed Feb 17 22:47:41 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * NEWS.txt: News in 0.3. - - * README.txt, idlever.py: Bump version to 0.3. - - * EditorWindow.py: - After all, we don't need to call the callbacks ourselves! - - * WindowList.py: - When deleting, call the callbacks *after* deleting the window from our list! - - * EditorWindow.py: - Fix up the Windows menu via the new callback mechanism instead of - depending on menu post commands (which don't work when the menu is - torn off). - - * WindowList.py: - Support callbacks to patch up Windows menus everywhere. - - * ChangeLog: Oh, why not. Checking in the Emacs-generated change log. - -Tue Feb 16 22:34:17 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ScriptBinding.py: - Only pop up the stack viewer when requested in the Debug menu. - -Mon Feb 8 22:27:49 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * WindowList.py: Don't crash if a window no longer exists. - - * TODO.txt: Restructured a bit. - -Mon Feb 1 23:06:17 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * PyShell.py: Add current dir or paths of file args to sys.path. - - * Debugger.py: Add canonic() function -- for brand new bdb.py feature. - - * StackViewer.py: Protect against accessing an empty stack. - -Fri Jan 29 20:44:45 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * ZoomHeight.py: - Use only the height to decide whether to zoom in or out. - -Thu Jan 28 22:24:30 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * EditorWindow.py, FileList.py: - Make sure the Tcl variables are shared between windows. - - * PyShell.py, EditorWindow.py, Bindings.py: - Move menu/key binding code from Bindings.py to EditorWindow.py, - with changed APIs -- it makes much more sense there. - Also add a new feature: if the first character of a menu label is - a '!', it gets a checkbox. Checkboxes are bound to Boolean Tcl variables - that can be accessed through the new getvar/setvar/getrawvar API; - the variable is named after the event to which the menu is bound. - - * Debugger.py: Add Quit button to the debugger window. - - * SearchDialog.py: - When find_again() finds exactly the current selection, it's a failure. - - * idle.py, Attic/idle: Rename idle -> idle.py - -Mon Jan 18 15:18:57 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * EditorWindow.py, WindowList.py: Only deiconify when iconic. - - * TODO.txt: Misc - -Tue Jan 12 22:14:34 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * testcode.py, Attic/test.py: - Renamed test.py to testcode.py so one can import Python's - test package from inside IDLE. (Suggested by Jack Jansen.) - - * EditorWindow.py, ColorDelegator.py: - Hack to close a window that is colorizing. - - * Separator.py: Vladimir Marangozov's patch: - The separator dances too much and seems to jump by arbitrary amounts - in arbitrary directions when I try to move it for resizing the frames. - This patch makes it more quiet. - -Mon Jan 11 14:52:40 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * TODO.txt: Some requests have been fulfilled. - - * EditorWindow.py: - Set the cursor to a watch when opening the class browser (which may - take quite a while, browsing multiple files). - - Newer, better center() -- but assumes no wrapping. - - * SearchBinding.py: - Got rid of debug print statement in goto_line_event(). - - * ScriptBinding.py: - I think I like it better if it prints the traceback even when it displays - the stack viewer. - - * Debugger.py: Bind ESC to close-window. - - * ClassBrowser.py: Use a HSeparator between the classes and the items. - Make the list of classes wider by default (40 chars). - Bind ESC to close-window. - - * Separator.py: - Separator classes (draggable divider between two panes). - -Sat Jan 9 22:01:33 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * WindowList.py: - Don't traceback when wakeup() is called when the window has been destroyed. - This can happen when a torn-of Windows menu references closed windows. - And Tim Peters claims that the Windows menu is his favorite to tear off... - - * EditorWindow.py: Allow tearing off of the Windows menu. - - * StackViewer.py: Close on ESC. - - * help.txt: Updated a bunch of things (it was mostly still 0.1!) - - * extend.py: Added ScriptBinding to standard bindings. - - * ScriptBinding.py: - This now actually works. See doc string. It can run a module (i.e. - import or reload) or debug it (same with debugger control). Output - goes to a fresh output window, only created when needed. - -====================================================================== - Python release 1.5.2b1, IDLE version 0.2 -====================================================================== - -Fri Jan 8 17:26:02 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * README.txt, NEWS.txt: What's new in this release. - - * Bindings.py, PyShell.py: - Paul Prescod's patches to allow the stack viewer to pop up when a - traceback is printed. - -Thu Jan 7 00:12:15 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * FormatParagraph.py: - Change paragraph width limit to 70 (like Emacs M-Q). - - * README.txt: - Separating TODO from README. Slight reformulation of features. No - exact release date. - - * TODO.txt: Separating TODO from README. - -Mon Jan 4 21:19:09 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * FormatParagraph.py: - Hm. There was a boundary condition error at the end of the file too. - - * SearchBinding.py: Hm. Add Unix binding for replace, too. - - * keydefs.py: Ran eventparse.py again. - - * FormatParagraph.py: Added Unix Meta-q key binding; - fix find_paragraph when at start of file. - - * AutoExpand.py: Added Meta-/ binding for Unix as alt for Alt-/. - - * SearchBinding.py: - Add unix binding for grep (otherwise the menu entry doesn't work!) - - * ZoomHeight.py: Adjusted Unix height to work with fvwm96. :=( - - * GrepDialog.py: Need to import sys! - - * help.txt, extend.txt, README.txt: Formatted some paragraphs - - * extend.py, FormatParagraph.py: - Add new extension to reformat a (text) paragraph. - - * ZoomHeight.py: Typo in Win specific height setting. - -Sun Jan 3 00:47:35 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * AutoIndent.py: Added something like Tim Peters' backspace patch. - - * ZoomHeight.py: Adapted to Unix (i.e., more hardcoded constants). - -Sat Jan 2 21:28:54 1999 Guido van Rossum <guido@cnri.reston.va.us> - - * keydefs.py, idlever.py, idle.pyw, idle.bat, help.txt, extend.txt, extend.py, eventparse.py, ZoomHeight.py, WindowList.py, UndoDelegator.py, StackViewer.py, SearchEngine.py, SearchDialogBase.py, SearchDialog.py, ScrolledList.py, SearchBinding.py, ScriptBinding.py, ReplaceDialog.py, Attic/README, README.txt, PyShell.py, Attic/PopupMenu.py, OutputWindow.py, IOBinding.py, Attic/HelpWindow.py, History.py, GrepDialog.py, FileList.py, FrameViewer.py, EditorWindow.py, Debugger.py, Delegator.py, ColorDelegator.py, Bindings.py, ClassBrowser.py, AutoExpand.py, AutoIndent.py: - Checking in IDLE 0.2. - - Much has changed -- too much, in fact, to write down. - The big news is that there's a standard way to write IDLE extensions; - see extend.txt. Some sample extensions have been provided, and - some existing code has been converted to extensions. Probably the - biggest new user feature is a new search dialog with more options, - search and replace, and even search in files (grep). - - This is exactly as downloaded from my laptop after returning - from the holidays -- it hasn't even been tested on Unix yet. - -Fri Dec 18 15:52:54 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * FileList.py, ClassBrowser.py: - Fix the class browser to work even when the file is not on sys.path. - -Tue Dec 8 20:39:36 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Attic/turtle.py: Moved to Python 1.5.2/Lib - -Fri Nov 27 03:19:20 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * help.txt: Typo - - * EditorWindow.py, FileList.py: Support underlining of menu labels - - * Bindings.py: - New approach, separate tables for menus (platform-independent) and key - definitions (platform-specific), and generating accelerator strings - automatically from the key definitions. - -Mon Nov 16 18:37:42 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Attic/README: Clarify portability and main program. - - * Attic/README: Added intro for 0.1 release and append Grail notes. - -Mon Oct 26 18:49:00 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Attic/turtle.py: root is now a global called _root - -Sat Oct 24 16:38:38 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Attic/turtle.py: Raise the root window on reset(). - Different action on WM_DELETE_WINDOW is more likely to do the right thing, - allowing us to destroy old windows. - - * Attic/turtle.py: - Split the goto() function in two: _goto() is the internal one, - using Canvas coordinates, and goto() uses turtle coordinates - and accepts variable argument lists. - - * Attic/turtle.py: Cope with destruction of the window - - * Attic/turtle.py: Turtle graphics - - * Debugger.py: Use of Breakpoint class should be bdb.Breakpoint. - -Mon Oct 19 03:33:40 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * SearchBinding.py: - Speed up the search a bit -- don't drag a mark around... - - * PyShell.py: - Change our special entries from <console#N> to <pyshell#N>. - Patch linecache.checkcache() to keep our special entries alive. - Add popup menu to all editor windows to set a breakpoint. - - * Debugger.py: - Use and pass through the 'force' flag to set_dict() where appropriate. - Default source and globals checkboxes to false. - Don't interact in user_return(). - Add primitive set_breakpoint() method. - - * ColorDelegator.py: - Raise priority of 'sel' tag so its foreground (on Windows) will take - priority over text colorization (which on Windows is almost the - same color as the selection background). - - Define a tag and color for breakpoints ("BREAK"). - - * Attic/PopupMenu.py: Disable "Open stack viewer" and "help" commands. - - * StackViewer.py: - Add optional 'force' argument (default 0) to load_dict(). - If set, redo the display even if it's the same dict. - -Fri Oct 16 21:10:12 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * StackViewer.py: Do nothing when loading the same dict as before. - - * PyShell.py: Details for debugger interface. - - * Debugger.py: - Restructured and more consistent. Save checkboxes across instantiations. - - * EditorWindow.py, Attic/README, Bindings.py: - Get rid of conflicting ^X binding. Use ^W. - - * Debugger.py, StackViewer.py: - Debugger can now show local and global variables. - - * Debugger.py: Oops - - * Debugger.py, PyShell.py: Better debugger support (show stack etc). - - * Attic/PopupMenu.py: Follow renames in StackViewer module - - * StackViewer.py: - Rename classes to StackViewer (the widget) and StackBrowser (the toplevel). - - * ScrolledList.py: Add close() method - - * EditorWindow.py: Clarify 'Open Module' dialog text - - * StackViewer.py: Restructured into a browser and a widget. - -Thu Oct 15 23:27:08 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * ClassBrowser.py, ScrolledList.py: - Generalized the scrolled list which is the base for the class and - method browser into a separate class in its own module. - - * Attic/test.py: Cosmetic change - - * Debugger.py: Don't show function name if there is none - -Wed Oct 14 03:43:05 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Debugger.py, PyShell.py: Polish the Debugger GUI a bit. - Closing it now also does the right thing. - -Tue Oct 13 23:51:13 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * Debugger.py, PyShell.py, Bindings.py: - Ad primitive debugger interface (so far it will step and show you the - source, but it doesn't yet show the stack). - - * Attic/README: Misc - - * StackViewer.py: Whoops -- referenced self.top before it was set. - - * help.txt: Added history and completion commands. - - * help.txt: Updated - - * FileList.py: Add class browser functionality. - - * StackViewer.py: - Add a close() method and bind to WM_DELETE_WINDOW protocol - - * PyShell.py: Clear the linecache before printing a traceback - - * Bindings.py: Added class browser binding. - - * ClassBrowser.py: Much improved, much left to do. - - * PyShell.py: Make the return key do what I mean more often. - - * ClassBrowser.py: - Adding the beginnings of a Class browser. Incomplete, yet. - - * EditorWindow.py, Bindings.py: - Add new command, "Open module". You select or type a module name, - and it opens the source. - -Mon Oct 12 23:59:27 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * PyShell.py: Subsume functionality from Popup menu in Debug menu. - Other stuff so the PyShell window can be resurrected from the Windows menu. - - * FileList.py: Get rid of PopUp menu. - Create a simple Windows menu. (Imperfect when Untitled windows exist.) - Add wakeup() method: deiconify, raise, focus. - - * EditorWindow.py: Generalize menu creation. - - * Bindings.py: Add Debug and Help menu items. - - * EditorWindow.py: Added a menu bar to every window. - - * Bindings.py: Add menu configuration to the event configuration. - - * Attic/PopupMenu.py: Pass a root to the help window. - - * SearchBinding.py: - Add parent argument to 'to to line number' dialog box. - -Sat Oct 10 19:15:32 1998 Guido van Rossum <guido@cnri.reston.va.us> - - * StackViewer.py: - Add a label at the top showing (very basic) help for the stack viewer. - Add a label at the bottom showing the exception info. - - * Attic/test.py, Attic/idle: Add Unix main script and test program. - - * idle.pyw, help.txt, WidgetRedirector.py, UndoDelegator.py, StackViewer.py, SearchBinding.py, Attic/README, PyShell.py, Attic/PopupMenu.py, Percolator.py, Outline.py, IOBinding.py, History.py, Attic/HelpWindow.py, FrameViewer.py, FileList.py, EditorWindow.py, Delegator.py, ColorDelegator.py, Bindings.py, AutoIndent.py, AutoExpand.py: - Initial checking of Tk-based Python IDE. - Features: text editor with syntax coloring and undo; - subclassed into interactive Python shell which adds history. - diff --git a/sys/lib/python/idlelib/ClassBrowser.py b/sys/lib/python/idlelib/ClassBrowser.py deleted file mode 100644 index e5a60a513..000000000 --- a/sys/lib/python/idlelib/ClassBrowser.py +++ /dev/null @@ -1,221 +0,0 @@ -"""Class browser. - -XXX TO DO: - -- reparse when source changed (maybe just a button would be OK?) - (or recheck on window popup) -- add popup menu with more options (e.g. doc strings, base classes, imports) -- show function argument list? (have to do pattern matching on source) -- should the classes and methods lists also be in the module's menu bar? -- add base classes to class browser tree -""" - -import os -import sys -import pyclbr - -import PyShell -from WindowList import ListedToplevel -from TreeWidget import TreeNode, TreeItem, ScrolledCanvas -from configHandler import idleConf - -class ClassBrowser: - - def __init__(self, flist, name, path): - # XXX This API should change, if the file doesn't end in ".py" - # XXX the code here is bogus! - self.name = name - self.file = os.path.join(path[0], self.name + ".py") - self.init(flist) - - def close(self, event=None): - self.top.destroy() - self.node.destroy() - - def init(self, flist): - self.flist = flist - # reset pyclbr - pyclbr._modules.clear() - # create top - self.top = top = ListedToplevel(flist.root) - top.protocol("WM_DELETE_WINDOW", self.close) - top.bind("<Escape>", self.close) - self.settitle() - top.focus_set() - # create scrolled canvas - theme = idleConf.GetOption('main','Theme','name') - background = idleConf.GetHighlight(theme, 'normal')['background'] - sc = ScrolledCanvas(top, bg=background, highlightthickness=0, takefocus=1) - sc.frame.pack(expand=1, fill="both") - item = self.rootnode() - self.node = node = TreeNode(sc.canvas, None, item) - node.update() - node.expand() - - def settitle(self): - self.top.wm_title("Class Browser - " + self.name) - self.top.wm_iconname("Class Browser") - - def rootnode(self): - return ModuleBrowserTreeItem(self.file) - -class ModuleBrowserTreeItem(TreeItem): - - def __init__(self, file): - self.file = file - - def GetText(self): - return os.path.basename(self.file) - - def GetIconName(self): - return "python" - - def GetSubList(self): - sublist = [] - for name in self.listclasses(): - item = ClassBrowserTreeItem(name, self.classes, self.file) - sublist.append(item) - return sublist - - def OnDoubleClick(self): - if os.path.normcase(self.file[-3:]) != ".py": - return - if not os.path.exists(self.file): - return - PyShell.flist.open(self.file) - - def IsExpandable(self): - return os.path.normcase(self.file[-3:]) == ".py" - - def listclasses(self): - dir, file = os.path.split(self.file) - name, ext = os.path.splitext(file) - if os.path.normcase(ext) != ".py": - return [] - try: - dict = pyclbr.readmodule_ex(name, [dir] + sys.path) - except ImportError, msg: - return [] - items = [] - self.classes = {} - for key, cl in dict.items(): - if cl.module == name: - s = key - if hasattr(cl, 'super') and cl.super: - supers = [] - for sup in cl.super: - if type(sup) is type(''): - sname = sup - else: - sname = sup.name - if sup.module != cl.module: - sname = "%s.%s" % (sup.module, sname) - supers.append(sname) - s = s + "(%s)" % ", ".join(supers) - items.append((cl.lineno, s)) - self.classes[s] = cl - items.sort() - list = [] - for item, s in items: - list.append(s) - return list - -class ClassBrowserTreeItem(TreeItem): - - def __init__(self, name, classes, file): - self.name = name - self.classes = classes - self.file = file - try: - self.cl = self.classes[self.name] - except (IndexError, KeyError): - self.cl = None - self.isfunction = isinstance(self.cl, pyclbr.Function) - - def GetText(self): - if self.isfunction: - return "def " + self.name + "(...)" - else: - return "class " + self.name - - def GetIconName(self): - if self.isfunction: - return "python" - else: - return "folder" - - def IsExpandable(self): - if self.cl: - try: - return not not self.cl.methods - except AttributeError: - return False - - def GetSubList(self): - if not self.cl: - return [] - sublist = [] - for name in self.listmethods(): - item = MethodBrowserTreeItem(name, self.cl, self.file) - sublist.append(item) - return sublist - - def OnDoubleClick(self): - if not os.path.exists(self.file): - return - edit = PyShell.flist.open(self.file) - if hasattr(self.cl, 'lineno'): - lineno = self.cl.lineno - edit.gotoline(lineno) - - def listmethods(self): - if not self.cl: - return [] - items = [] - for name, lineno in self.cl.methods.items(): - items.append((lineno, name)) - items.sort() - list = [] - for item, name in items: - list.append(name) - return list - -class MethodBrowserTreeItem(TreeItem): - - def __init__(self, name, cl, file): - self.name = name - self.cl = cl - self.file = file - - def GetText(self): - return "def " + self.name + "(...)" - - def GetIconName(self): - return "python" # XXX - - def IsExpandable(self): - return 0 - - def OnDoubleClick(self): - if not os.path.exists(self.file): - return - edit = PyShell.flist.open(self.file) - edit.gotoline(self.cl.methods[self.name]) - -def main(): - try: - file = __file__ - except NameError: - file = sys.argv[0] - if sys.argv[1:]: - file = sys.argv[1] - else: - file = sys.argv[0] - dir, file = os.path.split(file) - name = os.path.splitext(file)[0] - ClassBrowser(PyShell.flist, name, [dir]) - if sys.stdin is sys.__stdin__: - mainloop() - -if __name__ == "__main__": - main() diff --git a/sys/lib/python/idlelib/CodeContext.py b/sys/lib/python/idlelib/CodeContext.py deleted file mode 100644 index 74d5b7024..000000000 --- a/sys/lib/python/idlelib/CodeContext.py +++ /dev/null @@ -1,167 +0,0 @@ -"""CodeContext - Extension to display the block context above the edit window - -Once code has scrolled off the top of a window, it can be difficult to -determine which block you are in. This extension implements a pane at the top -of each IDLE edit window which provides block structure hints. These hints are -the lines which contain the block opening keywords, e.g. 'if', for the -enclosing block. The number of hint lines is determined by the numlines -variable in the CodeContext section of config-extensions.def. Lines which do -not open blocks are not shown in the context hints pane. - -""" -import Tkinter -from configHandler import idleConf -import re -from sys import maxint as INFINITY - -BLOCKOPENERS = set(["class", "def", "elif", "else", "except", "finally", "for", - "if", "try", "while", "with"]) -UPDATEINTERVAL = 100 # millisec -FONTUPDATEINTERVAL = 1000 # millisec - -getspacesfirstword =\ - lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() - -class CodeContext: - menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])] - - context_depth = idleConf.GetOption("extensions", "CodeContext", - "numlines", type="int", default=3) - bgcolor = idleConf.GetOption("extensions", "CodeContext", - "bgcolor", type="str", default="LightGray") - fgcolor = idleConf.GetOption("extensions", "CodeContext", - "fgcolor", type="str", default="Black") - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - self.textfont = self.text["font"] - self.label = None - # self.info is a list of (line number, indent level, line text, block - # keyword) tuples providing the block structure associated with - # self.topvisible (the linenumber of the line displayed at the top of - # the edit window). self.info[0] is initialized as a 'dummy' line which - # starts the toplevel 'block' of the module. - self.info = [(0, -1, "", False)] - self.topvisible = 1 - visible = idleConf.GetOption("extensions", "CodeContext", - "visible", type="bool", default=False) - if visible: - self.toggle_code_context_event() - self.editwin.setvar('<<toggle-code-context>>', True) - # Start two update cycles, one for context lines, one for font changes. - self.text.after(UPDATEINTERVAL, self.timer_event) - self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) - - def toggle_code_context_event(self, event=None): - if not self.label: - self.pad_frame = Tkinter.Frame(self.editwin.top, - bg=self.bgcolor, border=2, - relief="sunken") - self.label = Tkinter.Label(self.pad_frame, - text="\n" * (self.context_depth - 1), - anchor="w", justify="left", - font=self.textfont, - bg=self.bgcolor, fg=self.fgcolor, - border=0, - width=1, # Don't request more than we get - ) - self.label.pack(side="top", fill="x", expand=True, - padx=4, pady=0) - self.pad_frame.pack(side="top", fill="x", expand=False, - padx=0, pady=0, - after=self.editwin.status_bar) - else: - self.label.destroy() - self.pad_frame.destroy() - self.label = None - idleConf.SetOption("extensions", "CodeContext", "visible", - str(self.label is not None)) - idleConf.SaveUserCfgFiles() - - def get_line_info(self, linenum): - """Get the line indent value, text, and any block start keyword - - If the line does not start a block, the keyword value is False. - The indentation of empty lines (or comment lines) is INFINITY. - - """ - text = self.text.get("%d.0" % linenum, "%d.end" % linenum) - spaces, firstword = getspacesfirstword(text) - opener = firstword in BLOCKOPENERS and firstword - if len(text) == len(spaces) or text[len(spaces)] == '#': - indent = INFINITY - else: - indent = len(spaces) - return indent, text, opener - - def get_context(self, new_topvisible, stopline=1, stopindent=0): - """Get context lines, starting at new_topvisible and working backwards. - - Stop when stopline or stopindent is reached. Return a tuple of context - data and the indent level at the top of the region inspected. - - """ - assert stopline > 0 - lines = [] - # The indentation level we are currently in: - lastindent = INFINITY - # For a line to be interesting, it must begin with a block opening - # keyword, and have less indentation than lastindent. - for linenum in xrange(new_topvisible, stopline-1, -1): - indent, text, opener = self.get_line_info(linenum) - if indent < lastindent: - lastindent = indent - if opener in ("else", "elif"): - # We also show the if statement - lastindent += 1 - if opener and linenum < new_topvisible and indent >= stopindent: - lines.append((linenum, indent, text, opener)) - if lastindent <= stopindent: - break - lines.reverse() - return lines, lastindent - - def update_code_context(self): - """Update context information and lines visible in the context pane. - - """ - new_topvisible = int(self.text.index("@0,0").split('.')[0]) - if self.topvisible == new_topvisible: # haven't scrolled - return - if self.topvisible < new_topvisible: # scroll down - lines, lastindent = self.get_context(new_topvisible, - self.topvisible) - # retain only context info applicable to the region - # between topvisible and new_topvisible: - while self.info[-1][1] >= lastindent: - del self.info[-1] - elif self.topvisible > new_topvisible: # scroll up - stopindent = self.info[-1][1] + 1 - # retain only context info associated - # with lines above new_topvisible: - while self.info[-1][0] >= new_topvisible: - stopindent = self.info[-1][1] - del self.info[-1] - lines, lastindent = self.get_context(new_topvisible, - self.info[-1][0]+1, - stopindent) - self.info.extend(lines) - self.topvisible = new_topvisible - - # empty lines in context pane: - context_strings = [""] * max(0, self.context_depth - len(self.info)) - # followed by the context hint lines: - context_strings += [x[2] for x in self.info[-self.context_depth:]] - self.label["text"] = '\n'.join(context_strings) - - def timer_event(self): - if self.label: - self.update_code_context() - self.text.after(UPDATEINTERVAL, self.timer_event) - - def font_timer_event(self): - newtextfont = self.text["font"] - if self.label and newtextfont != self.textfont: - self.textfont = newtextfont - self.label["font"] = self.textfont - self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) diff --git a/sys/lib/python/idlelib/ColorDelegator.py b/sys/lib/python/idlelib/ColorDelegator.py deleted file mode 100644 index e55f9e6b7..000000000 --- a/sys/lib/python/idlelib/ColorDelegator.py +++ /dev/null @@ -1,263 +0,0 @@ -import time -import re -import keyword -import __builtin__ -from Tkinter import * -from Delegator import Delegator -from configHandler import idleConf - -DEBUG = False - -def any(name, alternates): - "Return a named group pattern matching list of alternates." - return "(?P<%s>" % name + "|".join(alternates) + ")" - -def make_pat(): - kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" - builtinlist = [str(name) for name in dir(__builtin__) - if not name.startswith('_')] - # self.file = file("file") : - # 1st 'file' colorized normal, 2nd as builtin, 3rd as string - builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" - comment = any("COMMENT", [r"#[^\n]*"]) - sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" - dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' - sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" - dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' - string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) - return kw + "|" + builtin + "|" + comment + "|" + string +\ - "|" + any("SYNC", [r"\n"]) - -prog = re.compile(make_pat(), re.S) -idprog = re.compile(r"\s+(\w+)", re.S) -asprog = re.compile(r".*?\b(as)\b") - -class ColorDelegator(Delegator): - - def __init__(self): - Delegator.__init__(self) - self.prog = prog - self.idprog = idprog - self.asprog = asprog - self.LoadTagDefs() - - def setdelegate(self, delegate): - if self.delegate is not None: - self.unbind("<<toggle-auto-coloring>>") - Delegator.setdelegate(self, delegate) - if delegate is not None: - self.config_colors() - self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event) - self.notify_range("1.0", "end") - - def config_colors(self): - for tag, cnf in self.tagdefs.items(): - if cnf: - self.tag_configure(tag, **cnf) - self.tag_raise('sel') - - def LoadTagDefs(self): - theme = idleConf.GetOption('main','Theme','name') - self.tagdefs = { - "COMMENT": idleConf.GetHighlight(theme, "comment"), - "KEYWORD": idleConf.GetHighlight(theme, "keyword"), - "BUILTIN": idleConf.GetHighlight(theme, "builtin"), - "STRING": idleConf.GetHighlight(theme, "string"), - "DEFINITION": idleConf.GetHighlight(theme, "definition"), - "SYNC": {'background':None,'foreground':None}, - "TODO": {'background':None,'foreground':None}, - "BREAK": idleConf.GetHighlight(theme, "break"), - "ERROR": idleConf.GetHighlight(theme, "error"), - # The following is used by ReplaceDialog: - "hit": idleConf.GetHighlight(theme, "hit"), - } - - if DEBUG: print 'tagdefs',self.tagdefs - - def insert(self, index, chars, tags=None): - index = self.index(index) - self.delegate.insert(index, chars, tags) - self.notify_range(index, index + "+%dc" % len(chars)) - - def delete(self, index1, index2=None): - index1 = self.index(index1) - self.delegate.delete(index1, index2) - self.notify_range(index1) - - after_id = None - allow_colorizing = True - colorizing = False - - def notify_range(self, index1, index2=None): - self.tag_add("TODO", index1, index2) - if self.after_id: - if DEBUG: print "colorizing already scheduled" - return - if self.colorizing: - self.stop_colorizing = True - if DEBUG: print "stop colorizing" - if self.allow_colorizing: - if DEBUG: print "schedule colorizing" - self.after_id = self.after(1, self.recolorize) - - close_when_done = None # Window to be closed when done colorizing - - def close(self, close_when_done=None): - if self.after_id: - after_id = self.after_id - self.after_id = None - if DEBUG: print "cancel scheduled recolorizer" - self.after_cancel(after_id) - self.allow_colorizing = False - self.stop_colorizing = True - if close_when_done: - if not self.colorizing: - close_when_done.destroy() - else: - self.close_when_done = close_when_done - - def toggle_colorize_event(self, event): - if self.after_id: - after_id = self.after_id - self.after_id = None - if DEBUG: print "cancel scheduled recolorizer" - self.after_cancel(after_id) - if self.allow_colorizing and self.colorizing: - if DEBUG: print "stop colorizing" - self.stop_colorizing = True - self.allow_colorizing = not self.allow_colorizing - if self.allow_colorizing and not self.colorizing: - self.after_id = self.after(1, self.recolorize) - if DEBUG: - print "auto colorizing turned",\ - self.allow_colorizing and "on" or "off" - return "break" - - def recolorize(self): - self.after_id = None - if not self.delegate: - if DEBUG: print "no delegate" - return - if not self.allow_colorizing: - if DEBUG: print "auto colorizing is off" - return - if self.colorizing: - if DEBUG: print "already colorizing" - return - try: - self.stop_colorizing = False - self.colorizing = True - if DEBUG: print "colorizing..." - t0 = time.clock() - self.recolorize_main() - t1 = time.clock() - if DEBUG: print "%.3f seconds" % (t1-t0) - finally: - self.colorizing = False - if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"): - if DEBUG: print "reschedule colorizing" - self.after_id = self.after(1, self.recolorize) - if self.close_when_done: - top = self.close_when_done - self.close_when_done = None - top.destroy() - - def recolorize_main(self): - next = "1.0" - while True: - item = self.tag_nextrange("TODO", next) - if not item: - break - head, tail = item - self.tag_remove("SYNC", head, tail) - item = self.tag_prevrange("SYNC", head) - if item: - head = item[1] - else: - head = "1.0" - - chars = "" - next = head - lines_to_get = 1 - ok = False - while not ok: - mark = next - next = self.index(mark + "+%d lines linestart" % - lines_to_get) - lines_to_get = min(lines_to_get * 2, 100) - ok = "SYNC" in self.tag_names(next + "-1c") - line = self.get(mark, next) - ##print head, "get", mark, next, "->", repr(line) - if not line: - return - for tag in self.tagdefs.keys(): - self.tag_remove(tag, mark, next) - chars = chars + line - m = self.prog.search(chars) - while m: - for key, value in m.groupdict().items(): - if value: - a, b = m.span(key) - self.tag_add(key, - head + "+%dc" % a, - head + "+%dc" % b) - if value in ("def", "class"): - m1 = self.idprog.match(chars, b) - if m1: - a, b = m1.span(1) - self.tag_add("DEFINITION", - head + "+%dc" % a, - head + "+%dc" % b) - elif value == "import": - # color all the "as" words on same line, except - # if in a comment; cheap approximation to the - # truth - if '#' in chars: - endpos = chars.index('#') - else: - endpos = len(chars) - while True: - m1 = self.asprog.match(chars, b, endpos) - if not m1: - break - a, b = m1.span(1) - self.tag_add("KEYWORD", - head + "+%dc" % a, - head + "+%dc" % b) - m = self.prog.search(chars, m.end()) - if "SYNC" in self.tag_names(next + "-1c"): - head = next - chars = "" - else: - ok = False - if not ok: - # We're in an inconsistent state, and the call to - # update may tell us to stop. It may also change - # the correct value for "next" (since this is a - # line.col string, not a true mark). So leave a - # crumb telling the next invocation to resume here - # in case update tells us to leave. - self.tag_add("TODO", next) - self.update() - if self.stop_colorizing: - if DEBUG: print "colorizing stopped" - return - - def removecolors(self): - for tag in self.tagdefs.keys(): - self.tag_remove(tag, "1.0", "end") - -def main(): - from Percolator import Percolator - root = Tk() - root.wm_protocol("WM_DELETE_WINDOW", root.quit) - text = Text(background="white") - text.pack(expand=1, fill="both") - text.focus_set() - p = Percolator(text) - d = ColorDelegator() - p.insertfilter(d) - root.mainloop() - -if __name__ == "__main__": - main() diff --git a/sys/lib/python/idlelib/Debugger.py b/sys/lib/python/idlelib/Debugger.py deleted file mode 100644 index f56460aad..000000000 --- a/sys/lib/python/idlelib/Debugger.py +++ /dev/null @@ -1,481 +0,0 @@ -import os -import bdb -import types -from Tkinter import * -from WindowList import ListedToplevel -from ScrolledList import ScrolledList -import macosxSupport - - -class Idb(bdb.Bdb): - - def __init__(self, gui): - self.gui = gui - bdb.Bdb.__init__(self) - - def user_line(self, frame): - if self.in_rpc_code(frame): - self.set_step() - return - message = self.__frame2message(frame) - self.gui.interaction(message, frame) - - def user_exception(self, frame, info): - if self.in_rpc_code(frame): - self.set_step() - return - message = self.__frame2message(frame) - self.gui.interaction(message, frame, info) - - def in_rpc_code(self, frame): - if frame.f_code.co_filename.count('rpc.py'): - return True - else: - prev_frame = frame.f_back - if prev_frame.f_code.co_filename.count('Debugger.py'): - # (that test will catch both Debugger.py and RemoteDebugger.py) - return False - return self.in_rpc_code(prev_frame) - - def __frame2message(self, frame): - code = frame.f_code - filename = code.co_filename - lineno = frame.f_lineno - basename = os.path.basename(filename) - message = "%s:%s" % (basename, lineno) - if code.co_name != "?": - message = "%s: %s()" % (message, code.co_name) - return message - - -class Debugger: - - vstack = vsource = vlocals = vglobals = None - - def __init__(self, pyshell, idb=None): - if idb is None: - idb = Idb(self) - self.pyshell = pyshell - self.idb = idb - self.frame = None - self.make_gui() - self.interacting = 0 - - def run(self, *args): - try: - self.interacting = 1 - return self.idb.run(*args) - finally: - self.interacting = 0 - - def close(self, event=None): - if self.interacting: - self.top.bell() - return - if self.stackviewer: - self.stackviewer.close(); self.stackviewer = None - # Clean up pyshell if user clicked debugger control close widget. - # (Causes a harmless extra cycle through close_debugger() if user - # toggled debugger from pyshell Debug menu) - self.pyshell.close_debugger() - # Now close the debugger control window.... - self.top.destroy() - - def make_gui(self): - pyshell = self.pyshell - self.flist = pyshell.flist - self.root = root = pyshell.root - self.top = top = ListedToplevel(root) - self.top.wm_title("Debug Control") - self.top.wm_iconname("Debug") - top.wm_protocol("WM_DELETE_WINDOW", self.close) - self.top.bind("<Escape>", self.close) - # - self.bframe = bframe = Frame(top) - self.bframe.pack(anchor="w") - self.buttons = bl = [] - # - self.bcont = b = Button(bframe, text="Go", command=self.cont) - bl.append(b) - self.bstep = b = Button(bframe, text="Step", command=self.step) - bl.append(b) - self.bnext = b = Button(bframe, text="Over", command=self.next) - bl.append(b) - self.bret = b = Button(bframe, text="Out", command=self.ret) - bl.append(b) - self.bret = b = Button(bframe, text="Quit", command=self.quit) - bl.append(b) - # - for b in bl: - b.configure(state="disabled") - b.pack(side="left") - # - self.cframe = cframe = Frame(bframe) - self.cframe.pack(side="left") - # - if not self.vstack: - self.__class__.vstack = BooleanVar(top) - self.vstack.set(1) - self.bstack = Checkbutton(cframe, - text="Stack", command=self.show_stack, variable=self.vstack) - self.bstack.grid(row=0, column=0) - if not self.vsource: - self.__class__.vsource = BooleanVar(top) - self.bsource = Checkbutton(cframe, - text="Source", command=self.show_source, variable=self.vsource) - self.bsource.grid(row=0, column=1) - if not self.vlocals: - self.__class__.vlocals = BooleanVar(top) - self.vlocals.set(1) - self.blocals = Checkbutton(cframe, - text="Locals", command=self.show_locals, variable=self.vlocals) - self.blocals.grid(row=1, column=0) - if not self.vglobals: - self.__class__.vglobals = BooleanVar(top) - self.bglobals = Checkbutton(cframe, - text="Globals", command=self.show_globals, variable=self.vglobals) - self.bglobals.grid(row=1, column=1) - # - self.status = Label(top, anchor="w") - self.status.pack(anchor="w") - self.error = Label(top, anchor="w") - self.error.pack(anchor="w", fill="x") - self.errorbg = self.error.cget("background") - # - self.fstack = Frame(top, height=1) - self.fstack.pack(expand=1, fill="both") - self.flocals = Frame(top) - self.flocals.pack(expand=1, fill="both") - self.fglobals = Frame(top, height=1) - self.fglobals.pack(expand=1, fill="both") - # - if self.vstack.get(): - self.show_stack() - if self.vlocals.get(): - self.show_locals() - if self.vglobals.get(): - self.show_globals() - - def interaction(self, message, frame, info=None): - self.frame = frame - self.status.configure(text=message) - # - if info: - type, value, tb = info - try: - m1 = type.__name__ - except AttributeError: - m1 = "%s" % str(type) - if value is not None: - try: - m1 = "%s: %s" % (m1, str(value)) - except: - pass - bg = "yellow" - else: - m1 = "" - tb = None - bg = self.errorbg - self.error.configure(text=m1, background=bg) - # - sv = self.stackviewer - if sv: - stack, i = self.idb.get_stack(self.frame, tb) - sv.load_stack(stack, i) - # - self.show_variables(1) - # - if self.vsource.get(): - self.sync_source_line() - # - for b in self.buttons: - b.configure(state="normal") - # - self.top.wakeup() - self.root.mainloop() - # - for b in self.buttons: - b.configure(state="disabled") - self.status.configure(text="") - self.error.configure(text="", background=self.errorbg) - self.frame = None - - def sync_source_line(self): - frame = self.frame - if not frame: - return - filename, lineno = self.__frame2fileline(frame) - if filename[:1] + filename[-1:] != "<>" and os.path.exists(filename): - self.flist.gotofileline(filename, lineno) - - def __frame2fileline(self, frame): - code = frame.f_code - filename = code.co_filename - lineno = frame.f_lineno - return filename, lineno - - def cont(self): - self.idb.set_continue() - self.root.quit() - - def step(self): - self.idb.set_step() - self.root.quit() - - def next(self): - self.idb.set_next(self.frame) - self.root.quit() - - def ret(self): - self.idb.set_return(self.frame) - self.root.quit() - - def quit(self): - self.idb.set_quit() - self.root.quit() - - stackviewer = None - - def show_stack(self): - if not self.stackviewer and self.vstack.get(): - self.stackviewer = sv = StackViewer(self.fstack, self.flist, self) - if self.frame: - stack, i = self.idb.get_stack(self.frame, None) - sv.load_stack(stack, i) - else: - sv = self.stackviewer - if sv and not self.vstack.get(): - self.stackviewer = None - sv.close() - self.fstack['height'] = 1 - - def show_source(self): - if self.vsource.get(): - self.sync_source_line() - - def show_frame(self, (frame, lineno)): - self.frame = frame - self.show_variables() - - localsviewer = None - globalsviewer = None - - def show_locals(self): - lv = self.localsviewer - if self.vlocals.get(): - if not lv: - self.localsviewer = NamespaceViewer(self.flocals, "Locals") - else: - if lv: - self.localsviewer = None - lv.close() - self.flocals['height'] = 1 - self.show_variables() - - def show_globals(self): - gv = self.globalsviewer - if self.vglobals.get(): - if not gv: - self.globalsviewer = NamespaceViewer(self.fglobals, "Globals") - else: - if gv: - self.globalsviewer = None - gv.close() - self.fglobals['height'] = 1 - self.show_variables() - - def show_variables(self, force=0): - lv = self.localsviewer - gv = self.globalsviewer - frame = self.frame - if not frame: - ldict = gdict = None - else: - ldict = frame.f_locals - gdict = frame.f_globals - if lv and gv and ldict is gdict: - ldict = None - if lv: - lv.load_dict(ldict, force, self.pyshell.interp.rpcclt) - if gv: - gv.load_dict(gdict, force, self.pyshell.interp.rpcclt) - - def set_breakpoint_here(self, filename, lineno): - self.idb.set_break(filename, lineno) - - def clear_breakpoint_here(self, filename, lineno): - self.idb.clear_break(filename, lineno) - - def clear_file_breaks(self, filename): - self.idb.clear_all_file_breaks(filename) - - def load_breakpoints(self): - "Load PyShellEditorWindow breakpoints into subprocess debugger" - pyshell_edit_windows = self.pyshell.flist.inversedict.keys() - for editwin in pyshell_edit_windows: - filename = editwin.io.filename - try: - for lineno in editwin.breakpoints: - self.set_breakpoint_here(filename, lineno) - except AttributeError: - continue - -class StackViewer(ScrolledList): - - def __init__(self, master, flist, gui): - if macosxSupport.runningAsOSXApp(): - # At least on with the stock AquaTk version on OSX 10.4 you'll - # get an shaking GUI that eventually kills IDLE if the width - # argument is specified. - ScrolledList.__init__(self, master) - else: - ScrolledList.__init__(self, master, width=80) - self.flist = flist - self.gui = gui - self.stack = [] - - def load_stack(self, stack, index=None): - self.stack = stack - self.clear() - for i in range(len(stack)): - frame, lineno = stack[i] - try: - modname = frame.f_globals["__name__"] - except: - modname = "?" - code = frame.f_code - filename = code.co_filename - funcname = code.co_name - import linecache - sourceline = linecache.getline(filename, lineno) - import string - sourceline = string.strip(sourceline) - if funcname in ("?", "", None): - item = "%s, line %d: %s" % (modname, lineno, sourceline) - else: - item = "%s.%s(), line %d: %s" % (modname, funcname, - lineno, sourceline) - if i == index: - item = "> " + item - self.append(item) - if index is not None: - self.select(index) - - def popup_event(self, event): - "override base method" - if self.stack: - return ScrolledList.popup_event(self, event) - - def fill_menu(self): - "override base method" - menu = self.menu - menu.add_command(label="Go to source line", - command=self.goto_source_line) - menu.add_command(label="Show stack frame", - command=self.show_stack_frame) - - def on_select(self, index): - "override base method" - if 0 <= index < len(self.stack): - self.gui.show_frame(self.stack[index]) - - def on_double(self, index): - "override base method" - self.show_source(index) - - def goto_source_line(self): - index = self.listbox.index("active") - self.show_source(index) - - def show_stack_frame(self): - index = self.listbox.index("active") - if 0 <= index < len(self.stack): - self.gui.show_frame(self.stack[index]) - - def show_source(self, index): - if not (0 <= index < len(self.stack)): - return - frame, lineno = self.stack[index] - code = frame.f_code - filename = code.co_filename - if os.path.isfile(filename): - edit = self.flist.open(filename) - if edit: - edit.gotoline(lineno) - - -class NamespaceViewer: - - def __init__(self, master, title, dict=None): - width = 0 - height = 40 - if dict: - height = 20*len(dict) # XXX 20 == observed height of Entry widget - self.master = master - self.title = title - import repr - self.repr = repr.Repr() - self.repr.maxstring = 60 - self.repr.maxother = 60 - self.frame = frame = Frame(master) - self.frame.pack(expand=1, fill="both") - self.label = Label(frame, text=title, borderwidth=2, relief="groove") - self.label.pack(fill="x") - self.vbar = vbar = Scrollbar(frame, name="vbar") - vbar.pack(side="right", fill="y") - self.canvas = canvas = Canvas(frame, - height=min(300, max(40, height)), - scrollregion=(0, 0, width, height)) - canvas.pack(side="left", fill="both", expand=1) - vbar["command"] = canvas.yview - canvas["yscrollcommand"] = vbar.set - self.subframe = subframe = Frame(canvas) - self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw") - self.load_dict(dict) - - dict = -1 - - def load_dict(self, dict, force=0, rpc_client=None): - if dict is self.dict and not force: - return - subframe = self.subframe - frame = self.frame - for c in subframe.children.values(): - c.destroy() - self.dict = None - if not dict: - l = Label(subframe, text="None") - l.grid(row=0, column=0) - else: - names = dict.keys() - names.sort() - row = 0 - for name in names: - value = dict[name] - svalue = self.repr.repr(value) # repr(value) - # Strip extra quotes caused by calling repr on the (already) - # repr'd value sent across the RPC interface: - if rpc_client: - svalue = svalue[1:-1] - l = Label(subframe, text=name) - l.grid(row=row, column=0, sticky="nw") - l = Entry(subframe, width=0, borderwidth=0) - l.insert(0, svalue) - l.grid(row=row, column=1, sticky="nw") - row = row+1 - self.dict = dict - # XXX Could we use a <Configure> callback for the following? - subframe.update_idletasks() # Alas! - width = subframe.winfo_reqwidth() - height = subframe.winfo_reqheight() - canvas = self.canvas - self.canvas["scrollregion"] = (0, 0, width, height) - if height > 300: - canvas["height"] = 300 - frame.pack(expand=1) - else: - canvas["height"] = height - frame.pack(expand=0) - - def close(self): - self.frame.destroy() diff --git a/sys/lib/python/idlelib/Delegator.py b/sys/lib/python/idlelib/Delegator.py deleted file mode 100644 index 6125591fe..000000000 --- a/sys/lib/python/idlelib/Delegator.py +++ /dev/null @@ -1,33 +0,0 @@ -class Delegator: - - # The cache is only used to be able to change delegates! - - def __init__(self, delegate=None): - self.delegate = delegate - self.__cache = {} - - def __getattr__(self, name): - attr = getattr(self.delegate, name) # May raise AttributeError - setattr(self, name, attr) - self.__cache[name] = attr - return attr - - def resetcache(self): - for key in self.__cache.keys(): - try: - delattr(self, key) - except AttributeError: - pass - self.__cache.clear() - - def cachereport(self): - keys = self.__cache.keys() - keys.sort() - print keys - - def setdelegate(self, delegate): - self.resetcache() - self.delegate = delegate - - def getdelegate(self): - return self.delegate diff --git a/sys/lib/python/idlelib/EditorWindow.py b/sys/lib/python/idlelib/EditorWindow.py deleted file mode 100644 index 259c7f340..000000000 --- a/sys/lib/python/idlelib/EditorWindow.py +++ /dev/null @@ -1,1511 +0,0 @@ -import sys -import os -import re -import imp -from itertools import count -from Tkinter import * -import tkSimpleDialog -import tkMessageBox -from MultiCall import MultiCallCreator - -import webbrowser -import idlever -import WindowList -import SearchDialog -import GrepDialog -import ReplaceDialog -import PyParse -from configHandler import idleConf -import aboutDialog, textView, configDialog -import macosxSupport - -# The default tab setting for a Text widget, in average-width characters. -TK_TABWIDTH_DEFAULT = 8 - -def _find_module(fullname, path=None): - """Version of imp.find_module() that handles hierarchical module names""" - - file = None - for tgt in fullname.split('.'): - if file is not None: - file.close() # close intermediate files - (file, filename, descr) = imp.find_module(tgt, path) - if descr[2] == imp.PY_SOURCE: - break # find but not load the source file - module = imp.load_module(tgt, file, filename, descr) - try: - path = module.__path__ - except AttributeError: - raise ImportError, 'No source for module ' + module.__name__ - return file, filename, descr - -class EditorWindow(object): - from Percolator import Percolator - from ColorDelegator import ColorDelegator - from UndoDelegator import UndoDelegator - from IOBinding import IOBinding, filesystemencoding, encoding - import Bindings - from Tkinter import Toplevel - from MultiStatusBar import MultiStatusBar - - help_url = None - - def __init__(self, flist=None, filename=None, key=None, root=None): - if EditorWindow.help_url is None: - dochome = os.path.join(sys.prefix, 'Doc', 'index.html') - if sys.platform.count('linux'): - # look for html docs in a couple of standard places - pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] - if os.path.isdir('/var/www/html/python/'): # "python2" rpm - dochome = '/var/www/html/python/index.html' - else: - basepath = '/usr/share/doc/' # standard location - dochome = os.path.join(basepath, pyver, - 'Doc', 'index.html') - elif sys.platform[:3] == 'win': - chmfile = os.path.join(sys.prefix, 'Doc', - 'Python%d%d.chm' % sys.version_info[:2]) - if os.path.isfile(chmfile): - dochome = chmfile - - elif macosxSupport.runningAsOSXApp(): - # documentation is stored inside the python framework - dochome = os.path.join(sys.prefix, - 'Resources/English.lproj/Documentation/index.html') - - dochome = os.path.normpath(dochome) - if os.path.isfile(dochome): - EditorWindow.help_url = dochome - if sys.platform == 'darwin': - # Safari requires real file:-URLs - EditorWindow.help_url = 'file://' + EditorWindow.help_url - else: - EditorWindow.help_url = "http://www.python.org/doc/current" - currentTheme=idleConf.CurrentTheme() - self.flist = flist - root = root or flist.root - self.root = root - try: - sys.ps1 - except AttributeError: - sys.ps1 = '>>> ' - self.menubar = Menu(root) - self.top = top = WindowList.ListedToplevel(root, menu=self.menubar) - if flist: - self.tkinter_vars = flist.vars - #self.top.instance_dict makes flist.inversedict avalable to - #configDialog.py so it can access all EditorWindow instaces - self.top.instance_dict = flist.inversedict - else: - self.tkinter_vars = {} # keys: Tkinter event names - # values: Tkinter variable instances - self.top.instance_dict = {} - self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(), - 'recent-files.lst') - self.vbar = vbar = Scrollbar(top, name='vbar') - self.text_frame = text_frame = Frame(top) - self.width = idleConf.GetOption('main','EditorWindow','width') - self.text = text = MultiCallCreator(Text)( - text_frame, name='text', padx=5, wrap='none', - foreground=idleConf.GetHighlight(currentTheme, - 'normal',fgBg='fg'), - background=idleConf.GetHighlight(currentTheme, - 'normal',fgBg='bg'), - highlightcolor=idleConf.GetHighlight(currentTheme, - 'hilite',fgBg='fg'), - highlightbackground=idleConf.GetHighlight(currentTheme, - 'hilite',fgBg='bg'), - insertbackground=idleConf.GetHighlight(currentTheme, - 'cursor',fgBg='fg'), - width=self.width, - height=idleConf.GetOption('main','EditorWindow','height') ) - self.top.focused_widget = self.text - - self.createmenubar() - self.apply_bindings() - - self.top.protocol("WM_DELETE_WINDOW", self.close) - self.top.bind("<<close-window>>", self.close_event) - if macosxSupport.runningAsOSXApp(): - # Command-W on editorwindows doesn't work without this. - text.bind('<<close-window>>', self.close_event) - text.bind("<<cut>>", self.cut) - text.bind("<<copy>>", self.copy) - text.bind("<<paste>>", self.paste) - text.bind("<<center-insert>>", self.center_insert_event) - text.bind("<<help>>", self.help_dialog) - text.bind("<<python-docs>>", self.python_docs) - text.bind("<<about-idle>>", self.about_dialog) - text.bind("<<open-config-dialog>>", self.config_dialog) - text.bind("<<open-module>>", self.open_module) - text.bind("<<do-nothing>>", lambda event: "break") - text.bind("<<select-all>>", self.select_all) - text.bind("<<remove-selection>>", self.remove_selection) - text.bind("<<find>>", self.find_event) - text.bind("<<find-again>>", self.find_again_event) - text.bind("<<find-in-files>>", self.find_in_files_event) - text.bind("<<find-selection>>", self.find_selection_event) - text.bind("<<replace>>", self.replace_event) - text.bind("<<goto-line>>", self.goto_line_event) - text.bind("<3>", self.right_menu_event) - text.bind("<<smart-backspace>>",self.smart_backspace_event) - text.bind("<<newline-and-indent>>",self.newline_and_indent_event) - text.bind("<<smart-indent>>",self.smart_indent_event) - text.bind("<<indent-region>>",self.indent_region_event) - text.bind("<<dedent-region>>",self.dedent_region_event) - text.bind("<<comment-region>>",self.comment_region_event) - text.bind("<<uncomment-region>>",self.uncomment_region_event) - text.bind("<<tabify-region>>",self.tabify_region_event) - text.bind("<<untabify-region>>",self.untabify_region_event) - text.bind("<<toggle-tabs>>",self.toggle_tabs_event) - text.bind("<<change-indentwidth>>",self.change_indentwidth_event) - text.bind("<Left>", self.move_at_edge_if_selection(0)) - text.bind("<Right>", self.move_at_edge_if_selection(1)) - text.bind("<<del-word-left>>", self.del_word_left) - text.bind("<<del-word-right>>", self.del_word_right) - - if flist: - flist.inversedict[self] = key - if key: - flist.dict[key] = self - text.bind("<<open-new-window>>", self.new_callback) - text.bind("<<close-all-windows>>", self.flist.close_all_callback) - text.bind("<<open-class-browser>>", self.open_class_browser) - text.bind("<<open-path-browser>>", self.open_path_browser) - - self.set_status_bar() - vbar['command'] = text.yview - vbar.pack(side=RIGHT, fill=Y) - text['yscrollcommand'] = vbar.set - fontWeight = 'normal' - if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): - fontWeight='bold' - text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', 'font-size'), - fontWeight)) - text_frame.pack(side=LEFT, fill=BOTH, expand=1) - text.pack(side=TOP, fill=BOTH, expand=1) - text.focus_set() - - # usetabs true -> literal tab characters are used by indent and - # dedent cmds, possibly mixed with spaces if - # indentwidth is not a multiple of tabwidth, - # which will cause Tabnanny to nag! - # false -> tab characters are converted to spaces by indent - # and dedent cmds, and ditto TAB keystrokes - # Although use-spaces=0 can be configured manually in config-main.def, - # configuration of tabs v. spaces is not supported in the configuration - # dialog. IDLE promotes the preferred Python indentation: use spaces! - usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool') - self.usetabs = not usespaces - - # tabwidth is the display width of a literal tab character. - # CAUTION: telling Tk to use anything other than its default - # tab setting causes it to use an entirely different tabbing algorithm, - # treating tab stops as fixed distances from the left margin. - # Nobody expects this, so for now tabwidth should never be changed. - self.tabwidth = 8 # must remain 8 until Tk is fixed. - - # indentwidth is the number of screen characters per indent level. - # The recommended Python indentation is four spaces. - self.indentwidth = self.tabwidth - self.set_notabs_indentwidth() - - # If context_use_ps1 is true, parsing searches back for a ps1 line; - # else searches for a popular (if, def, ...) Python stmt. - self.context_use_ps1 = False - - # When searching backwards for a reliable place to begin parsing, - # first start num_context_lines[0] lines back, then - # num_context_lines[1] lines back if that didn't work, and so on. - # The last value should be huge (larger than the # of lines in a - # conceivable file). - # Making the initial values larger slows things down more often. - self.num_context_lines = 50, 500, 5000000 - - self.per = per = self.Percolator(text) - if self.ispythonsource(filename): - self.color = color = self.ColorDelegator() - per.insertfilter(color) - else: - self.color = None - - self.undo = undo = self.UndoDelegator() - per.insertfilter(undo) - text.undo_block_start = undo.undo_block_start - text.undo_block_stop = undo.undo_block_stop - undo.set_saved_change_hook(self.saved_change_hook) - - # IOBinding implements file I/O and printing functionality - self.io = io = self.IOBinding(self) - io.set_filename_change_hook(self.filename_change_hook) - - # Create the recent files submenu - self.recent_files_menu = Menu(self.menubar) - self.menudict['file'].insert_cascade(3, label='Recent Files', - underline=0, - menu=self.recent_files_menu) - self.update_recent_files_list() - - if filename: - if os.path.exists(filename) and not os.path.isdir(filename): - io.loadfile(filename) - else: - io.set_filename(filename) - self.saved_change_hook() - - self.set_indentation_params(self.ispythonsource(filename)) - - self.load_extensions() - - menu = self.menudict.get('windows') - if menu: - end = menu.index("end") - if end is None: - end = -1 - if end >= 0: - menu.add_separator() - end = end + 1 - self.wmenu_end = end - WindowList.register_callback(self.postwindowsmenu) - - # Some abstractions so IDLE extensions are cross-IDE - self.askyesno = tkMessageBox.askyesno - self.askinteger = tkSimpleDialog.askinteger - self.showerror = tkMessageBox.showerror - - def _filename_to_unicode(self, filename): - """convert filename to unicode in order to display it in Tk""" - if isinstance(filename, unicode) or not filename: - return filename - else: - try: - return filename.decode(self.filesystemencoding) - except UnicodeDecodeError: - # XXX - try: - return filename.decode(self.encoding) - except UnicodeDecodeError: - # byte-to-byte conversion - return filename.decode('iso8859-1') - - def new_callback(self, event): - dirname, basename = self.io.defaultfilename() - self.flist.new(dirname) - return "break" - - def set_status_bar(self): - self.status_bar = self.MultiStatusBar(self.top) - if macosxSupport.runningAsOSXApp(): - # Insert some padding to avoid obscuring some of the statusbar - # by the resize widget. - self.status_bar.set_label('_padding1', ' ', side=RIGHT) - self.status_bar.set_label('column', 'Col: ?', side=RIGHT) - self.status_bar.set_label('line', 'Ln: ?', side=RIGHT) - self.status_bar.pack(side=BOTTOM, fill=X) - self.text.bind("<<set-line-and-column>>", self.set_line_and_column) - self.text.event_add("<<set-line-and-column>>", - "<KeyRelease>", "<ButtonRelease>") - self.text.after_idle(self.set_line_and_column) - - def set_line_and_column(self, event=None): - line, column = self.text.index(INSERT).split('.') - self.status_bar.set_label('column', 'Col: %s' % column) - self.status_bar.set_label('line', 'Ln: %s' % line) - - menu_specs = [ - ("file", "_File"), - ("edit", "_Edit"), - ("format", "F_ormat"), - ("run", "_Run"), - ("options", "_Options"), - ("windows", "_Windows"), - ("help", "_Help"), - ] - - if macosxSupport.runningAsOSXApp(): - del menu_specs[-3] - menu_specs[-2] = ("windows", "_Window") - - - def createmenubar(self): - mbar = self.menubar - self.menudict = menudict = {} - for name, label in self.menu_specs: - underline, label = prepstr(label) - menudict[name] = menu = Menu(mbar, name=name) - mbar.add_cascade(label=label, menu=menu, underline=underline) - - if sys.platform == 'darwin' and '.framework' in sys.executable: - # Insert the application menu - menudict['application'] = menu = Menu(mbar, name='apple') - mbar.add_cascade(label='IDLE', menu=menu) - - self.fill_menus() - self.base_helpmenu_length = self.menudict['help'].index(END) - self.reset_help_menu_entries() - - def postwindowsmenu(self): - # Only called when Windows menu exists - menu = self.menudict['windows'] - end = menu.index("end") - if end is None: - end = -1 - if end > self.wmenu_end: - menu.delete(self.wmenu_end+1, end) - WindowList.add_windows_to_menu(menu) - - rmenu = None - - def right_menu_event(self, event): - self.text.tag_remove("sel", "1.0", "end") - self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) - if not self.rmenu: - self.make_rmenu() - rmenu = self.rmenu - self.event = event - iswin = sys.platform[:3] == 'win' - if iswin: - self.text.config(cursor="arrow") - rmenu.tk_popup(event.x_root, event.y_root) - if iswin: - self.text.config(cursor="ibeam") - - rmenu_specs = [ - # ("Label", "<<virtual-event>>"), ... - ("Close", "<<close-window>>"), # Example - ] - - def make_rmenu(self): - rmenu = Menu(self.text, tearoff=0) - for label, eventname in self.rmenu_specs: - def command(text=self.text, eventname=eventname): - text.event_generate(eventname) - rmenu.add_command(label=label, command=command) - self.rmenu = rmenu - - def about_dialog(self, event=None): - aboutDialog.AboutDialog(self.top,'About IDLE') - - def config_dialog(self, event=None): - configDialog.ConfigDialog(self.top,'Settings') - - def help_dialog(self, event=None): - fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),'help.txt') - textView.TextViewer(self.top,'Help',fn) - - def python_docs(self, event=None): - if sys.platform[:3] == 'win': - os.startfile(self.help_url) - else: - webbrowser.open(self.help_url) - return "break" - - def cut(self,event): - self.text.event_generate("<<Cut>>") - return "break" - - def copy(self,event): - if not self.text.tag_ranges("sel"): - # There is no selection, so do nothing and maybe interrupt. - return - self.text.event_generate("<<Copy>>") - return "break" - - def paste(self,event): - self.text.event_generate("<<Paste>>") - return "break" - - def select_all(self, event=None): - self.text.tag_add("sel", "1.0", "end-1c") - self.text.mark_set("insert", "1.0") - self.text.see("insert") - return "break" - - def remove_selection(self, event=None): - self.text.tag_remove("sel", "1.0", "end") - self.text.see("insert") - - def move_at_edge_if_selection(self, edge_index): - """Cursor move begins at start or end of selection - - When a left/right cursor key is pressed create and return to Tkinter a - function which causes a cursor move from the associated edge of the - selection. - - """ - self_text_index = self.text.index - self_text_mark_set = self.text.mark_set - edges_table = ("sel.first+1c", "sel.last-1c") - def move_at_edge(event): - if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed - try: - self_text_index("sel.first") - self_text_mark_set("insert", edges_table[edge_index]) - except TclError: - pass - return move_at_edge - - def del_word_left(self, event): - self.text.event_generate('<Meta-Delete>') - return "break" - - def del_word_right(self, event): - self.text.event_generate('<Meta-d>') - return "break" - - def find_event(self, event): - SearchDialog.find(self.text) - return "break" - - def find_again_event(self, event): - SearchDialog.find_again(self.text) - return "break" - - def find_selection_event(self, event): - SearchDialog.find_selection(self.text) - return "break" - - def find_in_files_event(self, event): - GrepDialog.grep(self.text, self.io, self.flist) - return "break" - - def replace_event(self, event): - ReplaceDialog.replace(self.text) - return "break" - - def goto_line_event(self, event): - text = self.text - lineno = tkSimpleDialog.askinteger("Goto", - "Go to line number:",parent=text) - if lineno is None: - return "break" - if lineno <= 0: - text.bell() - return "break" - text.mark_set("insert", "%d.0" % lineno) - text.see("insert") - - def open_module(self, event=None): - # XXX Shouldn't this be in IOBinding or in FileList? - try: - name = self.text.get("sel.first", "sel.last") - except TclError: - name = "" - else: - name = name.strip() - name = tkSimpleDialog.askstring("Module", - "Enter the name of a Python module\n" - "to search on sys.path and open:", - parent=self.text, initialvalue=name) - if name: - name = name.strip() - if not name: - return - # XXX Ought to insert current file's directory in front of path - try: - (f, file, (suffix, mode, type)) = _find_module(name) - except (NameError, ImportError), msg: - tkMessageBox.showerror("Import error", str(msg), parent=self.text) - return - if type != imp.PY_SOURCE: - tkMessageBox.showerror("Unsupported type", - "%s is not a source module" % name, parent=self.text) - return - if f: - f.close() - if self.flist: - self.flist.open(file) - else: - self.io.loadfile(file) - - def open_class_browser(self, event=None): - filename = self.io.filename - if not filename: - tkMessageBox.showerror( - "No filename", - "This buffer has no associated filename", - master=self.text) - self.text.focus_set() - return None - head, tail = os.path.split(filename) - base, ext = os.path.splitext(tail) - import ClassBrowser - ClassBrowser.ClassBrowser(self.flist, base, [head]) - - def open_path_browser(self, event=None): - import PathBrowser - PathBrowser.PathBrowser(self.flist) - - def gotoline(self, lineno): - if lineno is not None and lineno > 0: - self.text.mark_set("insert", "%d.0" % lineno) - self.text.tag_remove("sel", "1.0", "end") - self.text.tag_add("sel", "insert", "insert +1l") - self.center() - - def ispythonsource(self, filename): - if not filename or os.path.isdir(filename): - return True - base, ext = os.path.splitext(os.path.basename(filename)) - if os.path.normcase(ext) in (".py", ".pyw"): - return True - try: - f = open(filename) - line = f.readline() - f.close() - except IOError: - return False - return line.startswith('#!') and line.find('python') >= 0 - - def close_hook(self): - if self.flist: - self.flist.close_edit(self) - - def set_close_hook(self, close_hook): - self.close_hook = close_hook - - def filename_change_hook(self): - if self.flist: - self.flist.filename_changed_edit(self) - self.saved_change_hook() - self.top.update_windowlist_registry(self) - if self.ispythonsource(self.io.filename): - self.addcolorizer() - else: - self.rmcolorizer() - - def addcolorizer(self): - if self.color: - return - self.per.removefilter(self.undo) - self.color = self.ColorDelegator() - self.per.insertfilter(self.color) - self.per.insertfilter(self.undo) - - def rmcolorizer(self): - if not self.color: - return - self.color.removecolors() - self.per.removefilter(self.undo) - self.per.removefilter(self.color) - self.color = None - self.per.insertfilter(self.undo) - - def ResetColorizer(self): - "Update the colour theme if it is changed" - # Called from configDialog.py - if self.color: - self.color = self.ColorDelegator() - self.per.insertfilter(self.color) - theme = idleConf.GetOption('main','Theme','name') - self.text.config(idleConf.GetHighlight(theme, "normal")) - - def ResetFont(self): - "Update the text widgets' font if it is changed" - # Called from configDialog.py - fontWeight='normal' - if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): - fontWeight='bold' - self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size'), - fontWeight)) - - def RemoveKeybindings(self): - "Remove the keybindings before they are changed." - # Called from configDialog.py - self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() - for event, keylist in keydefs.items(): - self.text.event_delete(event, *keylist) - for extensionName in self.get_standard_extension_names(): - xkeydefs = idleConf.GetExtensionBindings(extensionName) - if xkeydefs: - for event, keylist in xkeydefs.items(): - self.text.event_delete(event, *keylist) - - def ApplyKeybindings(self): - "Update the keybindings after they are changed" - # Called from configDialog.py - self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() - self.apply_bindings() - for extensionName in self.get_standard_extension_names(): - xkeydefs = idleConf.GetExtensionBindings(extensionName) - if xkeydefs: - self.apply_bindings(xkeydefs) - #update menu accelerators - menuEventDict = {} - for menu in self.Bindings.menudefs: - menuEventDict[menu[0]] = {} - for item in menu[1]: - if item: - menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1] - for menubarItem in self.menudict.keys(): - menu = self.menudict[menubarItem] - end = menu.index(END) + 1 - for index in range(0, end): - if menu.type(index) == 'command': - accel = menu.entrycget(index, 'accelerator') - if accel: - itemName = menu.entrycget(index, 'label') - event = '' - if menuEventDict.has_key(menubarItem): - if menuEventDict[menubarItem].has_key(itemName): - event = menuEventDict[menubarItem][itemName] - if event: - accel = get_accelerator(keydefs, event) - menu.entryconfig(index, accelerator=accel) - - def set_notabs_indentwidth(self): - "Update the indentwidth if changed and not using tabs in this window" - # Called from configDialog.py - if not self.usetabs: - self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces', - type='int') - - def reset_help_menu_entries(self): - "Update the additional help entries on the Help menu" - help_list = idleConf.GetAllExtraHelpSourcesList() - helpmenu = self.menudict['help'] - # first delete the extra help entries, if any - helpmenu_length = helpmenu.index(END) - if helpmenu_length > self.base_helpmenu_length: - helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) - # then rebuild them - if help_list: - helpmenu.add_separator() - for entry in help_list: - cmd = self.__extra_help_callback(entry[1]) - helpmenu.add_command(label=entry[0], command=cmd) - # and update the menu dictionary - self.menudict['help'] = helpmenu - - def __extra_help_callback(self, helpfile): - "Create a callback with the helpfile value frozen at definition time" - def display_extra_help(helpfile=helpfile): - if not helpfile.startswith(('www', 'http')): - url = os.path.normpath(helpfile) - if sys.platform[:3] == 'win': - os.startfile(helpfile) - else: - webbrowser.open(helpfile) - return display_extra_help - - def update_recent_files_list(self, new_file=None): - "Load and update the recent files list and menus" - rf_list = [] - if os.path.exists(self.recent_files_path): - rf_list_file = open(self.recent_files_path,'r') - try: - rf_list = rf_list_file.readlines() - finally: - rf_list_file.close() - if new_file: - new_file = os.path.abspath(new_file) + '\n' - if new_file in rf_list: - rf_list.remove(new_file) # move to top - rf_list.insert(0, new_file) - # clean and save the recent files list - bad_paths = [] - for path in rf_list: - if '\0' in path or not os.path.exists(path[0:-1]): - bad_paths.append(path) - rf_list = [path for path in rf_list if path not in bad_paths] - ulchars = "1234567890ABCDEFGHIJK" - rf_list = rf_list[0:len(ulchars)] - rf_file = open(self.recent_files_path, 'w') - try: - rf_file.writelines(rf_list) - finally: - rf_file.close() - # for each edit window instance, construct the recent files menu - for instance in self.top.instance_dict.keys(): - menu = instance.recent_files_menu - menu.delete(1, END) # clear, and rebuild: - for i, file in zip(count(), rf_list): - file_name = file[0:-1] # zap \n - # make unicode string to display non-ASCII chars correctly - ufile_name = self._filename_to_unicode(file_name) - callback = instance.__recent_file_callback(file_name) - menu.add_command(label=ulchars[i] + " " + ufile_name, - command=callback, - underline=0) - - def __recent_file_callback(self, file_name): - def open_recent_file(fn_closure=file_name): - self.io.open(editFile=fn_closure) - return open_recent_file - - def saved_change_hook(self): - short = self.short_title() - long = self.long_title() - if short and long: - title = short + " - " + long - elif short: - title = short - elif long: - title = long - else: - title = "Untitled" - icon = short or long or title - if not self.get_saved(): - title = "*%s*" % title - icon = "*%s" % icon - self.top.wm_title(title) - self.top.wm_iconname(icon) - - def get_saved(self): - return self.undo.get_saved() - - def set_saved(self, flag): - self.undo.set_saved(flag) - - def reset_undo(self): - self.undo.reset_undo() - - def short_title(self): - filename = self.io.filename - if filename: - filename = os.path.basename(filename) - # return unicode string to display non-ASCII chars correctly - return self._filename_to_unicode(filename) - - def long_title(self): - # return unicode string to display non-ASCII chars correctly - return self._filename_to_unicode(self.io.filename or "") - - def center_insert_event(self, event): - self.center() - - def center(self, mark="insert"): - text = self.text - top, bot = self.getwindowlines() - lineno = self.getlineno(mark) - height = bot - top - newtop = max(1, lineno - height//2) - text.yview(float(newtop)) - - def getwindowlines(self): - text = self.text - top = self.getlineno("@0,0") - bot = self.getlineno("@0,65535") - if top == bot and text.winfo_height() == 1: - # Geometry manager hasn't run yet - height = int(text['height']) - bot = top + height - 1 - return top, bot - - def getlineno(self, mark="insert"): - text = self.text - return int(float(text.index(mark))) - - def get_geometry(self): - "Return (width, height, x, y)" - geom = self.top.wm_geometry() - m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) - tuple = (map(int, m.groups())) - return tuple - - def close_event(self, event): - self.close() - - def maybesave(self): - if self.io: - if not self.get_saved(): - if self.top.state()!='normal': - self.top.deiconify() - self.top.lower() - self.top.lift() - return self.io.maybesave() - - def close(self): - reply = self.maybesave() - if str(reply) != "cancel": - self._close() - return reply - - def _close(self): - if self.io.filename: - self.update_recent_files_list(new_file=self.io.filename) - WindowList.unregister_callback(self.postwindowsmenu) - if self.close_hook: - self.close_hook() - self.flist = None - colorizing = 0 - self.unload_extensions() - self.io.close(); self.io = None - self.undo = None # XXX - if self.color: - colorizing = self.color.colorizing - doh = colorizing and self.top - self.color.close(doh) # Cancel colorization - self.text = None - self.tkinter_vars = None - self.per.close(); self.per = None - if not colorizing: - self.top.destroy() - - def load_extensions(self): - self.extensions = {} - self.load_standard_extensions() - - def unload_extensions(self): - for ins in self.extensions.values(): - if hasattr(ins, "close"): - ins.close() - self.extensions = {} - - def load_standard_extensions(self): - for name in self.get_standard_extension_names(): - try: - self.load_extension(name) - except: - print "Failed to load extension", repr(name) - import traceback - traceback.print_exc() - - def get_standard_extension_names(self): - return idleConf.GetExtensions(editor_only=True) - - def load_extension(self, name): - try: - mod = __import__(name, globals(), locals(), []) - except ImportError: - print "\nFailed to import extension: ", name - return - cls = getattr(mod, name) - keydefs = idleConf.GetExtensionBindings(name) - if hasattr(cls, "menudefs"): - self.fill_menus(cls.menudefs, keydefs) - ins = cls(self) - self.extensions[name] = ins - if keydefs: - self.apply_bindings(keydefs) - for vevent in keydefs.keys(): - methodname = vevent.replace("-", "_") - while methodname[:1] == '<': - methodname = methodname[1:] - while methodname[-1:] == '>': - methodname = methodname[:-1] - methodname = methodname + "_event" - if hasattr(ins, methodname): - self.text.bind(vevent, getattr(ins, methodname)) - - def apply_bindings(self, keydefs=None): - if keydefs is None: - keydefs = self.Bindings.default_keydefs - text = self.text - text.keydefs = keydefs - for event, keylist in keydefs.items(): - if keylist: - text.event_add(event, *keylist) - - def fill_menus(self, menudefs=None, keydefs=None): - """Add appropriate entries to the menus and submenus - - Menus that are absent or None in self.menudict are ignored. - """ - if menudefs is None: - menudefs = self.Bindings.menudefs - if keydefs is None: - keydefs = self.Bindings.default_keydefs - menudict = self.menudict - text = self.text - for mname, entrylist in menudefs: - menu = menudict.get(mname) - if not menu: - continue - for entry in entrylist: - if not entry: - menu.add_separator() - else: - label, eventname = entry - checkbutton = (label[:1] == '!') - if checkbutton: - label = label[1:] - underline, label = prepstr(label) - accelerator = get_accelerator(keydefs, eventname) - def command(text=text, eventname=eventname): - text.event_generate(eventname) - if checkbutton: - var = self.get_var_obj(eventname, BooleanVar) - menu.add_checkbutton(label=label, underline=underline, - command=command, accelerator=accelerator, - variable=var) - else: - menu.add_command(label=label, underline=underline, - command=command, - accelerator=accelerator) - - def getvar(self, name): - var = self.get_var_obj(name) - if var: - value = var.get() - return value - else: - raise NameError, name - - def setvar(self, name, value, vartype=None): - var = self.get_var_obj(name, vartype) - if var: - var.set(value) - else: - raise NameError, name - - def get_var_obj(self, name, vartype=None): - var = self.tkinter_vars.get(name) - if not var and vartype: - # create a Tkinter variable object with self.text as master: - self.tkinter_vars[name] = var = vartype(self.text) - return var - - # Tk implementations of "virtual text methods" -- each platform - # reusing IDLE's support code needs to define these for its GUI's - # flavor of widget. - - # Is character at text_index in a Python string? Return 0 for - # "guaranteed no", true for anything else. This info is expensive - # to compute ab initio, but is probably already known by the - # platform's colorizer. - - def is_char_in_string(self, text_index): - if self.color: - # Return true iff colorizer hasn't (re)gotten this far - # yet, or the character is tagged as being in a string - return self.text.tag_prevrange("TODO", text_index) or \ - "STRING" in self.text.tag_names(text_index) - else: - # The colorizer is missing: assume the worst - return 1 - - # If a selection is defined in the text widget, return (start, - # end) as Tkinter text indices, otherwise return (None, None) - def get_selection_indices(self): - try: - first = self.text.index("sel.first") - last = self.text.index("sel.last") - return first, last - except TclError: - return None, None - - # Return the text widget's current view of what a tab stop means - # (equivalent width in spaces). - - def get_tabwidth(self): - current = self.text['tabs'] or TK_TABWIDTH_DEFAULT - return int(current) - - # Set the text widget's current view of what a tab stop means. - - def set_tabwidth(self, newtabwidth): - text = self.text - if self.get_tabwidth() != newtabwidth: - pixels = text.tk.call("font", "measure", text["font"], - "-displayof", text.master, - "n" * newtabwidth) - text.configure(tabs=pixels) - - # If ispythonsource and guess are true, guess a good value for - # indentwidth based on file content (if possible), and if - # indentwidth != tabwidth set usetabs false. - # In any case, adjust the Text widget's view of what a tab - # character means. - - def set_indentation_params(self, ispythonsource, guess=True): - if guess and ispythonsource: - i = self.guess_indent() - if 2 <= i <= 8: - self.indentwidth = i - if self.indentwidth != self.tabwidth: - self.usetabs = False - self.set_tabwidth(self.tabwidth) - - def smart_backspace_event(self, event): - text = self.text - first, last = self.get_selection_indices() - if first and last: - text.delete(first, last) - text.mark_set("insert", first) - return "break" - # Delete whitespace left, until hitting a real char or closest - # preceding virtual tab stop. - chars = text.get("insert linestart", "insert") - if chars == '': - if text.compare("insert", ">", "1.0"): - # easy: delete preceding newline - text.delete("insert-1c") - else: - text.bell() # at start of buffer - return "break" - if chars[-1] not in " \t": - # easy: delete preceding real char - text.delete("insert-1c") - return "break" - # Ick. It may require *inserting* spaces if we back up over a - # tab character! This is written to be clear, not fast. - tabwidth = self.tabwidth - have = len(chars.expandtabs(tabwidth)) - assert have > 0 - want = ((have - 1) // self.indentwidth) * self.indentwidth - # Debug prompt is multilined.... - last_line_of_prompt = sys.ps1.split('\n')[-1] - ncharsdeleted = 0 - while 1: - if chars == last_line_of_prompt: - break - chars = chars[:-1] - ncharsdeleted = ncharsdeleted + 1 - have = len(chars.expandtabs(tabwidth)) - if have <= want or chars[-1] not in " \t": - break - text.undo_block_start() - text.delete("insert-%dc" % ncharsdeleted, "insert") - if have < want: - text.insert("insert", ' ' * (want - have)) - text.undo_block_stop() - return "break" - - def smart_indent_event(self, event): - # if intraline selection: - # delete it - # elif multiline selection: - # do indent-region - # else: - # indent one level - text = self.text - first, last = self.get_selection_indices() - text.undo_block_start() - try: - if first and last: - if index2line(first) != index2line(last): - return self.indent_region_event(event) - text.delete(first, last) - text.mark_set("insert", first) - prefix = text.get("insert linestart", "insert") - raw, effective = classifyws(prefix, self.tabwidth) - if raw == len(prefix): - # only whitespace to the left - self.reindent_to(effective + self.indentwidth) - else: - # tab to the next 'stop' within or to right of line's text: - if self.usetabs: - pad = '\t' - else: - effective = len(prefix.expandtabs(self.tabwidth)) - n = self.indentwidth - pad = ' ' * (n - effective % n) - text.insert("insert", pad) - text.see("insert") - return "break" - finally: - text.undo_block_stop() - - def newline_and_indent_event(self, event): - text = self.text - first, last = self.get_selection_indices() - text.undo_block_start() - try: - if first and last: - text.delete(first, last) - text.mark_set("insert", first) - line = text.get("insert linestart", "insert") - i, n = 0, len(line) - while i < n and line[i] in " \t": - i = i+1 - if i == n: - # the cursor is in or at leading indentation in a continuation - # line; just inject an empty line at the start - text.insert("insert linestart", '\n') - return "break" - indent = line[:i] - # strip whitespace before insert point unless it's in the prompt - i = 0 - last_line_of_prompt = sys.ps1.split('\n')[-1] - while line and line[-1] in " \t" and line != last_line_of_prompt: - line = line[:-1] - i = i+1 - if i: - text.delete("insert - %d chars" % i, "insert") - # strip whitespace after insert point - while text.get("insert") in " \t": - text.delete("insert") - # start new line - text.insert("insert", '\n') - - # adjust indentation for continuations and block - # open/close first need to find the last stmt - lno = index2line(text.index('insert')) - y = PyParse.Parser(self.indentwidth, self.tabwidth) - if not self.context_use_ps1: - for context in self.num_context_lines: - startat = max(lno - context, 1) - startatindex = `startat` + ".0" - rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) - bod = y.find_good_parse_start( - self.context_use_ps1, - self._build_char_in_string_func(startatindex)) - if bod is not None or startat == 1: - break - y.set_lo(bod or 0) - else: - r = text.tag_prevrange("console", "insert") - if r: - startatindex = r[1] - else: - startatindex = "1.0" - rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) - y.set_lo(0) - - c = y.get_continuation_type() - if c != PyParse.C_NONE: - # The current stmt hasn't ended yet. - if c == PyParse.C_STRING_FIRST_LINE: - # after the first line of a string; do not indent at all - pass - elif c == PyParse.C_STRING_NEXT_LINES: - # inside a string which started before this line; - # just mimic the current indent - text.insert("insert", indent) - elif c == PyParse.C_BRACKET: - # line up with the first (if any) element of the - # last open bracket structure; else indent one - # level beyond the indent of the line with the - # last open bracket - self.reindent_to(y.compute_bracket_indent()) - elif c == PyParse.C_BACKSLASH: - # if more than one line in this stmt already, just - # mimic the current indent; else if initial line - # has a start on an assignment stmt, indent to - # beyond leftmost =; else to beyond first chunk of - # non-whitespace on initial line - if y.get_num_lines_in_stmt() > 1: - text.insert("insert", indent) - else: - self.reindent_to(y.compute_backslash_indent()) - else: - assert 0, "bogus continuation type %r" % (c,) - return "break" - - # This line starts a brand new stmt; indent relative to - # indentation of initial line of closest preceding - # interesting stmt. - indent = y.get_base_indent_string() - text.insert("insert", indent) - if y.is_block_opener(): - self.smart_indent_event(event) - elif indent and y.is_block_closer(): - self.smart_backspace_event(event) - return "break" - finally: - text.see("insert") - text.undo_block_stop() - - # Our editwin provides a is_char_in_string function that works - # with a Tk text index, but PyParse only knows about offsets into - # a string. This builds a function for PyParse that accepts an - # offset. - - def _build_char_in_string_func(self, startindex): - def inner(offset, _startindex=startindex, - _icis=self.is_char_in_string): - return _icis(_startindex + "+%dc" % offset) - return inner - - def indent_region_event(self, event): - head, tail, chars, lines = self.get_region() - for pos in range(len(lines)): - line = lines[pos] - if line: - raw, effective = classifyws(line, self.tabwidth) - effective = effective + self.indentwidth - lines[pos] = self._make_blanks(effective) + line[raw:] - self.set_region(head, tail, chars, lines) - return "break" - - def dedent_region_event(self, event): - head, tail, chars, lines = self.get_region() - for pos in range(len(lines)): - line = lines[pos] - if line: - raw, effective = classifyws(line, self.tabwidth) - effective = max(effective - self.indentwidth, 0) - lines[pos] = self._make_blanks(effective) + line[raw:] - self.set_region(head, tail, chars, lines) - return "break" - - def comment_region_event(self, event): - head, tail, chars, lines = self.get_region() - for pos in range(len(lines) - 1): - line = lines[pos] - lines[pos] = '##' + line - self.set_region(head, tail, chars, lines) - - def uncomment_region_event(self, event): - head, tail, chars, lines = self.get_region() - for pos in range(len(lines)): - line = lines[pos] - if not line: - continue - if line[:2] == '##': - line = line[2:] - elif line[:1] == '#': - line = line[1:] - lines[pos] = line - self.set_region(head, tail, chars, lines) - - def tabify_region_event(self, event): - head, tail, chars, lines = self.get_region() - tabwidth = self._asktabwidth() - for pos in range(len(lines)): - line = lines[pos] - if line: - raw, effective = classifyws(line, tabwidth) - ntabs, nspaces = divmod(effective, tabwidth) - lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] - self.set_region(head, tail, chars, lines) - - def untabify_region_event(self, event): - head, tail, chars, lines = self.get_region() - tabwidth = self._asktabwidth() - for pos in range(len(lines)): - lines[pos] = lines[pos].expandtabs(tabwidth) - self.set_region(head, tail, chars, lines) - - def toggle_tabs_event(self, event): - if self.askyesno( - "Toggle tabs", - "Turn tabs " + ("on", "off")[self.usetabs] + - "?\nIndent width " + - ("will be", "remains at")[self.usetabs] + " 8." + - "\n Note: a tab is always 8 columns", - parent=self.text): - self.usetabs = not self.usetabs - # Try to prevent inconsistent indentation. - # User must change indent width manually after using tabs. - self.indentwidth = 8 - return "break" - - # XXX this isn't bound to anything -- see tabwidth comments -## def change_tabwidth_event(self, event): -## new = self._asktabwidth() -## if new != self.tabwidth: -## self.tabwidth = new -## self.set_indentation_params(0, guess=0) -## return "break" - - def change_indentwidth_event(self, event): - new = self.askinteger( - "Indent width", - "New indent width (2-16)\n(Always use 8 when using tabs)", - parent=self.text, - initialvalue=self.indentwidth, - minvalue=2, - maxvalue=16) - if new and new != self.indentwidth and not self.usetabs: - self.indentwidth = new - return "break" - - def get_region(self): - text = self.text - first, last = self.get_selection_indices() - if first and last: - head = text.index(first + " linestart") - tail = text.index(last + "-1c lineend +1c") - else: - head = text.index("insert linestart") - tail = text.index("insert lineend +1c") - chars = text.get(head, tail) - lines = chars.split("\n") - return head, tail, chars, lines - - def set_region(self, head, tail, chars, lines): - text = self.text - newchars = "\n".join(lines) - if newchars == chars: - text.bell() - return - text.tag_remove("sel", "1.0", "end") - text.mark_set("insert", head) - text.undo_block_start() - text.delete(head, tail) - text.insert(head, newchars) - text.undo_block_stop() - text.tag_add("sel", head, "insert") - - # Make string that displays as n leading blanks. - - def _make_blanks(self, n): - if self.usetabs: - ntabs, nspaces = divmod(n, self.tabwidth) - return '\t' * ntabs + ' ' * nspaces - else: - return ' ' * n - - # Delete from beginning of line to insert point, then reinsert - # column logical (meaning use tabs if appropriate) spaces. - - def reindent_to(self, column): - text = self.text - text.undo_block_start() - if text.compare("insert linestart", "!=", "insert"): - text.delete("insert linestart", "insert") - if column: - text.insert("insert", self._make_blanks(column)) - text.undo_block_stop() - - def _asktabwidth(self): - return self.askinteger( - "Tab width", - "Columns per tab? (2-16)", - parent=self.text, - initialvalue=self.indentwidth, - minvalue=2, - maxvalue=16) or self.tabwidth - - # Guess indentwidth from text content. - # Return guessed indentwidth. This should not be believed unless - # it's in a reasonable range (e.g., it will be 0 if no indented - # blocks are found). - - def guess_indent(self): - opener, indented = IndentSearcher(self.text, self.tabwidth).run() - if opener and indented: - raw, indentsmall = classifyws(opener, self.tabwidth) - raw, indentlarge = classifyws(indented, self.tabwidth) - else: - indentsmall = indentlarge = 0 - return indentlarge - indentsmall - -# "line.col" -> line, as an int -def index2line(index): - return int(float(index)) - -# Look at the leading whitespace in s. -# Return pair (# of leading ws characters, -# effective # of leading blanks after expanding -# tabs to width tabwidth) - -def classifyws(s, tabwidth): - raw = effective = 0 - for ch in s: - if ch == ' ': - raw = raw + 1 - effective = effective + 1 - elif ch == '\t': - raw = raw + 1 - effective = (effective // tabwidth + 1) * tabwidth - else: - break - return raw, effective - -import tokenize -_tokenize = tokenize -del tokenize - -class IndentSearcher(object): - - # .run() chews over the Text widget, looking for a block opener - # and the stmt following it. Returns a pair, - # (line containing block opener, line containing stmt) - # Either or both may be None. - - def __init__(self, text, tabwidth): - self.text = text - self.tabwidth = tabwidth - self.i = self.finished = 0 - self.blkopenline = self.indentedline = None - - def readline(self): - if self.finished: - return "" - i = self.i = self.i + 1 - mark = repr(i) + ".0" - if self.text.compare(mark, ">=", "end"): - return "" - return self.text.get(mark, mark + " lineend+1c") - - def tokeneater(self, type, token, start, end, line, - INDENT=_tokenize.INDENT, - NAME=_tokenize.NAME, - OPENERS=('class', 'def', 'for', 'if', 'try', 'while')): - if self.finished: - pass - elif type == NAME and token in OPENERS: - self.blkopenline = line - elif type == INDENT and self.blkopenline: - self.indentedline = line - self.finished = 1 - - def run(self): - save_tabsize = _tokenize.tabsize - _tokenize.tabsize = self.tabwidth - try: - try: - _tokenize.tokenize(self.readline, self.tokeneater) - except _tokenize.TokenError: - # since we cut off the tokenizer early, we can trigger - # spurious errors - pass - finally: - _tokenize.tabsize = save_tabsize - return self.blkopenline, self.indentedline - -### end autoindent code ### - -def prepstr(s): - # Helper to extract the underscore from a string, e.g. - # prepstr("Co_py") returns (2, "Copy"). - i = s.find('_') - if i >= 0: - s = s[:i] + s[i+1:] - return i, s - - -keynames = { - 'bracketleft': '[', - 'bracketright': ']', - 'slash': '/', -} - -def get_accelerator(keydefs, eventname): - keylist = keydefs.get(eventname) - if not keylist: - return "" - s = keylist[0] - s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) - s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s) - s = re.sub("Key-", "", s) - s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu - s = re.sub("Control-", "Ctrl-", s) - s = re.sub("-", "+", s) - s = re.sub("><", " ", s) - s = re.sub("<", "", s) - s = re.sub(">", "", s) - return s - - -def fixwordbreaks(root): - # Make sure that Tk's double-click and next/previous word - # operations use our definition of a word (i.e. an identifier) - tk = root.tk - tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded - tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]') - tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') - - -def test(): - root = Tk() - fixwordbreaks(root) - root.withdraw() - if sys.argv[1:]: - filename = sys.argv[1] - else: - filename = None - edit = EditorWindow(root=root, filename=filename) - edit.set_close_hook(root.quit) - root.mainloop() - root.destroy() - -if __name__ == '__main__': - test() diff --git a/sys/lib/python/idlelib/FileList.py b/sys/lib/python/idlelib/FileList.py deleted file mode 100644 index 4b5790102..000000000 --- a/sys/lib/python/idlelib/FileList.py +++ /dev/null @@ -1,124 +0,0 @@ -import os -from Tkinter import * -import tkMessageBox - - -class FileList: - - from EditorWindow import EditorWindow # class variable, may be overridden - # e.g. by PyShellFileList - - def __init__(self, root): - self.root = root - self.dict = {} - self.inversedict = {} - self.vars = {} # For EditorWindow.getrawvar (shared Tcl variables) - - def open(self, filename, action=None): - assert filename - filename = self.canonize(filename) - if os.path.isdir(filename): - # This can happen when bad filename is passed on command line: - tkMessageBox.showerror( - "File Error", - "%r is a directory." % (filename,), - master=self.root) - return None - key = os.path.normcase(filename) - if self.dict.has_key(key): - edit = self.dict[key] - edit.top.wakeup() - return edit - if action: - # Don't create window, perform 'action', e.g. open in same window - return action(filename) - else: - return self.EditorWindow(self, filename, key) - - def gotofileline(self, filename, lineno=None): - edit = self.open(filename) - if edit is not None and lineno is not None: - edit.gotoline(lineno) - - def new(self, filename=None): - return self.EditorWindow(self, filename) - - def close_all_callback(self, event): - for edit in self.inversedict.keys(): - reply = edit.close() - if reply == "cancel": - break - return "break" - - def close_edit(self, edit): - try: - key = self.inversedict[edit] - except KeyError: - print "Don't know this EditorWindow object. (close)" - return - if key: - del self.dict[key] - del self.inversedict[edit] - if not self.inversedict: - self.root.quit() - - def filename_changed_edit(self, edit): - edit.saved_change_hook() - try: - key = self.inversedict[edit] - except KeyError: - print "Don't know this EditorWindow object. (rename)" - return - filename = edit.io.filename - if not filename: - if key: - del self.dict[key] - self.inversedict[edit] = None - return - filename = self.canonize(filename) - newkey = os.path.normcase(filename) - if newkey == key: - return - if self.dict.has_key(newkey): - conflict = self.dict[newkey] - self.inversedict[conflict] = None - tkMessageBox.showerror( - "Name Conflict", - "You now have multiple edit windows open for %r" % (filename,), - master=self.root) - self.dict[newkey] = edit - self.inversedict[edit] = newkey - if key: - try: - del self.dict[key] - except KeyError: - pass - - def canonize(self, filename): - if not os.path.isabs(filename): - try: - pwd = os.getcwd() - except os.error: - pass - else: - filename = os.path.join(pwd, filename) - return os.path.normpath(filename) - - -def _test(): - from EditorWindow import fixwordbreaks - import sys - root = Tk() - fixwordbreaks(root) - root.withdraw() - flist = FileList(root) - if sys.argv[1:]: - for filename in sys.argv[1:]: - flist.open(filename) - else: - flist.new() - if flist.inversedict: - root.mainloop() - -if __name__ == '__main__': - _test() diff --git a/sys/lib/python/idlelib/FormatParagraph.py b/sys/lib/python/idlelib/FormatParagraph.py deleted file mode 100644 index ed9f28d12..000000000 --- a/sys/lib/python/idlelib/FormatParagraph.py +++ /dev/null @@ -1,148 +0,0 @@ -# Extension to format a paragraph - -# Does basic, standard text formatting, and also understands Python -# comment blocks. Thus, for editing Python source code, this -# extension is really only suitable for reformatting these comment -# blocks or triple-quoted strings. - -# Known problems with comment reformatting: -# * If there is a selection marked, and the first line of the -# selection is not complete, the block will probably not be detected -# as comments, and will have the normal "text formatting" rules -# applied. -# * If a comment block has leading whitespace that mixes tabs and -# spaces, they will not be considered part of the same block. -# * Fancy comments, like this bulleted list, arent handled :-) - -import re -from configHandler import idleConf - -class FormatParagraph: - - menudefs = [ - ('format', [ # /s/edit/format dscherer@cmu.edu - ('Format Paragraph', '<<format-paragraph>>'), - ]) - ] - - def __init__(self, editwin): - self.editwin = editwin - - def close(self): - self.editwin = None - - def format_paragraph_event(self, event): - maxformatwidth = int(idleConf.GetOption('main','FormatParagraph','paragraph')) - text = self.editwin.text - first, last = self.editwin.get_selection_indices() - if first and last: - data = text.get(first, last) - comment_header = '' - else: - first, last, comment_header, data = \ - find_paragraph(text, text.index("insert")) - if comment_header: - # Reformat the comment lines - convert to text sans header. - lines = data.split("\n") - lines = map(lambda st, l=len(comment_header): st[l:], lines) - data = "\n".join(lines) - # Reformat to maxformatwidth chars or a 20 char width, whichever is greater. - format_width = max(maxformatwidth - len(comment_header), 20) - newdata = reformat_paragraph(data, format_width) - # re-split and re-insert the comment header. - newdata = newdata.split("\n") - # If the block ends in a \n, we dont want the comment - # prefix inserted after it. (Im not sure it makes sense to - # reformat a comment block that isnt made of complete - # lines, but whatever!) Can't think of a clean soltution, - # so we hack away - block_suffix = "" - if not newdata[-1]: - block_suffix = "\n" - newdata = newdata[:-1] - builder = lambda item, prefix=comment_header: prefix+item - newdata = '\n'.join(map(builder, newdata)) + block_suffix - else: - # Just a normal text format - newdata = reformat_paragraph(data, maxformatwidth) - text.tag_remove("sel", "1.0", "end") - if newdata != data: - text.mark_set("insert", first) - text.undo_block_start() - text.delete(first, last) - text.insert(first, newdata) - text.undo_block_stop() - else: - text.mark_set("insert", last) - text.see("insert") - -def find_paragraph(text, mark): - lineno, col = map(int, mark.split(".")) - line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) - while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line): - lineno = lineno + 1 - line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) - first_lineno = lineno - comment_header = get_comment_header(line) - comment_header_len = len(comment_header) - while get_comment_header(line)==comment_header and \ - not is_all_white(line[comment_header_len:]): - lineno = lineno + 1 - line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) - last = "%d.0" % lineno - # Search back to beginning of paragraph - lineno = first_lineno - 1 - line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) - while lineno > 0 and \ - get_comment_header(line)==comment_header and \ - not is_all_white(line[comment_header_len:]): - lineno = lineno - 1 - line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) - first = "%d.0" % (lineno+1) - return first, last, comment_header, text.get(first, last) - -def reformat_paragraph(data, limit): - lines = data.split("\n") - i = 0 - n = len(lines) - while i < n and is_all_white(lines[i]): - i = i+1 - if i >= n: - return data - indent1 = get_indent(lines[i]) - if i+1 < n and not is_all_white(lines[i+1]): - indent2 = get_indent(lines[i+1]) - else: - indent2 = indent1 - new = lines[:i] - partial = indent1 - while i < n and not is_all_white(lines[i]): - # XXX Should take double space after period (etc.) into account - words = re.split("(\s+)", lines[i]) - for j in range(0, len(words), 2): - word = words[j] - if not word: - continue # Can happen when line ends in whitespace - if len((partial + word).expandtabs()) > limit and \ - partial != indent1: - new.append(partial.rstrip()) - partial = indent2 - partial = partial + word + " " - if j+1 < len(words) and words[j+1] != " ": - partial = partial + " " - i = i+1 - new.append(partial.rstrip()) - # XXX Should reformat remaining paragraphs as well - new.extend(lines[i:]) - return "\n".join(new) - -def is_all_white(line): - return re.match(r"^\s*$", line) is not None - -def get_indent(line): - return re.match(r"^(\s*)", line).group() - -def get_comment_header(line): - m = re.match(r"^(\s*#*)", line) - if m is None: return "" - return m.group(1) diff --git a/sys/lib/python/idlelib/GrepDialog.py b/sys/lib/python/idlelib/GrepDialog.py deleted file mode 100644 index ab136bc11..000000000 --- a/sys/lib/python/idlelib/GrepDialog.py +++ /dev/null @@ -1,133 +0,0 @@ -import os -import fnmatch -import sys -from Tkinter import * -import SearchEngine -from SearchDialogBase import SearchDialogBase - -def grep(text, io=None, flist=None): - root = text._root() - engine = SearchEngine.get(root) - if not hasattr(engine, "_grepdialog"): - engine._grepdialog = GrepDialog(root, engine, flist) - dialog = engine._grepdialog - searchphrase = text.get("sel.first", "sel.last") - dialog.open(text, searchphrase, io) - -class GrepDialog(SearchDialogBase): - - title = "Find in Files Dialog" - icon = "Grep" - needwrapbutton = 0 - - def __init__(self, root, engine, flist): - SearchDialogBase.__init__(self, root, engine) - self.flist = flist - self.globvar = StringVar(root) - self.recvar = BooleanVar(root) - - def open(self, text, searchphrase, io=None): - SearchDialogBase.open(self, text, searchphrase) - if io: - path = io.filename or "" - else: - path = "" - dir, base = os.path.split(path) - head, tail = os.path.splitext(base) - if not tail: - tail = ".py" - self.globvar.set(os.path.join(dir, "*" + tail)) - - def create_entries(self): - SearchDialogBase.create_entries(self) - self.globent = self.make_entry("In files:", self.globvar) - - def create_other_buttons(self): - f = self.make_frame() - - btn = Checkbutton(f, anchor="w", - variable=self.recvar, - text="Recurse down subdirectories") - btn.pack(side="top", fill="both") - btn.select() - - def create_command_buttons(self): - SearchDialogBase.create_command_buttons(self) - self.make_button("Search Files", self.default_command, 1) - - def default_command(self, event=None): - prog = self.engine.getprog() - if not prog: - return - path = self.globvar.get() - if not path: - self.top.bell() - return - from OutputWindow import OutputWindow - save = sys.stdout - try: - sys.stdout = OutputWindow(self.flist) - self.grep_it(prog, path) - finally: - sys.stdout = save - - def grep_it(self, prog, path): - dir, base = os.path.split(path) - list = self.findfiles(dir, base, self.recvar.get()) - list.sort() - self.close() - pat = self.engine.getpat() - print "Searching %r in %s ..." % (pat, path) - hits = 0 - for fn in list: - try: - f = open(fn) - except IOError, msg: - print msg - continue - lineno = 0 - while 1: - block = f.readlines(100000) - if not block: - break - for line in block: - lineno = lineno + 1 - if line[-1:] == '\n': - line = line[:-1] - if prog.search(line): - sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line)) - hits = hits + 1 - if hits: - if hits == 1: - s = "" - else: - s = "s" - print "Found", hits, "hit%s." % s - print "(Hint: right-click to open locations.)" - else: - print "No hits." - - def findfiles(self, dir, base, rec): - try: - names = os.listdir(dir or os.curdir) - except os.error, msg: - print msg - return [] - list = [] - subdirs = [] - for name in names: - fn = os.path.join(dir, name) - if os.path.isdir(fn): - subdirs.append(fn) - else: - if fnmatch.fnmatch(name, base): - list.append(fn) - if rec: - for subdir in subdirs: - list.extend(self.findfiles(subdir, base, rec)) - return list - - def close(self, event=None): - if self.top: - self.top.grab_release() - self.top.withdraw() diff --git a/sys/lib/python/idlelib/HISTORY.txt b/sys/lib/python/idlelib/HISTORY.txt deleted file mode 100644 index c0faaad87..000000000 --- a/sys/lib/python/idlelib/HISTORY.txt +++ /dev/null @@ -1,296 +0,0 @@ -IDLE History -============ - -This file contains the release messages for previous IDLE releases. -As you read on you go back to the dark ages of IDLE's history. - - -What's New in IDLEfork 0.8.1? -============================= - -*Release date: 22-Jul-2001* - -- New tarball released as a result of the 'revitalisation' of the IDLEfork - project. - -- This release requires python 2.1 or better. Compatability with earlier - versions of python (especially ancient ones like 1.5x) is no longer a - priority in IDLEfork development. - -- This release is based on a merging of the earlier IDLE fork work with current - cvs IDLE (post IDLE version 0.8), with some minor additional coding by Kurt - B. Kaiser and Stephen M. Gava. - -- This release is basically functional but also contains some known breakages, - particularly with running things from the shell window. Also the debugger is - not working, but I believe this was the case with the previous IDLE fork - release (0.7.1) as well. - -- This release is being made now to mark the point at which IDLEfork is - launching into a new stage of development. - -- IDLEfork CVS will now be branched to enable further development and - exploration of the two "execution in a remote process" patches submitted by - David Scherer (David's is currently in IDLEfork) and GvR, while stabilisation - and development of less heavyweight improvements (like user customisation) - can continue on the trunk. - - -What's New in IDLEfork 0.7.1? -============================== - -*Release date: 15-Aug-2000* - -- First project tarball released. - -- This was the first release of IDLE fork, which at this stage was a - combination of IDLE 0.5 and the VPython idle fork, with additional changes - coded by David Scherer, Peter Schneider-Kamp and Nicholas Riley. - - - -IDLEfork 0.7.1 - 29 May 2000 ------------------------------ - - David Scherer <dscherer@cmu.edu> - -- This is a modification of the CVS version of IDLE 0.5, updated as of - 2000-03-09. It is alpha software and might be unstable. If it breaks, you - get to keep both pieces. - -- If you have problems or suggestions, you should either contact me or post to - the list at http://www.python.org/mailman/listinfo/idle-dev (making it clear - that you are using this modified version of IDLE). - -- Changes: - - - The ExecBinding module, a replacement for ScriptBinding, executes programs - in a separate process, piping standard I/O through an RPC mechanism to an - OnDemandOutputWindow in IDLE. It supports executing unnamed programs - (through a temporary file). It does not yet support debugging. - - - When running programs with ExecBinding, tracebacks will be clipped to - exclude system modules. If, however, a system module calls back into the - user program, that part of the traceback will be shown. - - - The OnDemandOutputWindow class has been improved. In particular, it now - supports a readline() function used to implement user input, and a - scroll_clear() operation which is used to hide the output of a previous run - by scrolling it out of the window. - - - Startup behavior has been changed. By default IDLE starts up with just a - blank editor window, rather than an interactive window. Opening a file in - such a blank window replaces the (nonexistent) contents of that window - instead of creating another window. Because of the need to have a - well-known port for the ExecBinding protocol, only one copy of IDLE can be - running. Additional invocations use the RPC mechanism to report their - command line arguments to the copy already running. - - - The menus have been reorganized. In particular, the excessively large - 'edit' menu has been split up into 'edit', 'format', and 'run'. - - - 'Python Documentation' now works on Windows, if the win32api module is - present. - - - A few key bindings have been changed: F1 now loads Python Documentation - instead of the IDLE help; shift-TAB is now a synonym for unindent. - -- New modules: - - ExecBinding.py Executes program through loader - loader.py Bootstraps user program - protocol.py RPC protocol - Remote.py User-process interpreter - spawn.py OS-specific code to start programs - -- Files modified: - - autoindent.py ( bindings tweaked ) - bindings.py ( menus reorganized ) - config.txt ( execbinding enabled ) - editorwindow.py ( new menus, fixed 'Python Documentation' ) - filelist.py ( hook for "open in same window" ) - formatparagraph.py ( bindings tweaked ) - idle.bat ( removed absolute pathname ) - idle.pyw ( weird bug due to import with same name? ) - iobinding.py ( open in same window, EOL convention ) - keydefs.py ( bindings tweaked ) - outputwindow.py ( readline, scroll_clear, etc ) - pyshell.py ( changed startup behavior ) - readme.txt ( <Recursion on file with id=1234567> ) - - - -IDLE 0.5 - February 2000 - Release Notes ----------------------------------------- - -This is an early release of IDLE, my own attempt at a Tkinter-based -IDE for Python. - -(For a more detailed change log, see the file ChangeLog.) - -FEATURES - -IDLE has the following features: - -- coded in 100% pure Python, using the Tkinter GUI toolkit (i.e. Tcl/Tk) - -- cross-platform: works on Windows and Unix (on the Mac, there are -currently problems with Tcl/Tk) - -- multi-window text editor with multiple undo, Python colorizing -and many other features, e.g. smart indent and call tips - -- Python shell window (a.k.a. interactive interpreter) - -- debugger (not complete, but you can set breakpoints, view and step) - -USAGE - -The main program is in the file "idle.py"; on Unix, you should be able -to run it by typing "./idle.py" to your shell. On Windows, you can -run it by double-clicking it; you can use idle.pyw to avoid popping up -a DOS console. If you want to pass command line arguments on Windows, -use the batch file idle.bat. - -Command line arguments: files passed on the command line are executed, -not opened for editing, unless you give the -e command line option. -Try "./idle.py -h" to see other command line options. - -IDLE requires Python 1.5.2, so it is currently only usable with a -Python 1.5.2 distribution. (An older version of IDLE is distributed -with Python 1.5.2; you can drop this version on top of it.) - -COPYRIGHT - -IDLE is covered by the standard Python copyright notice -(http://www.python.org/doc/Copyright.html). - - -New in IDLE 0.5 (2/15/2000) ---------------------------- - -Tons of stuff, much of it contributed by Tim Peters and Mark Hammond: - -- Status bar, displaying current line/column (Moshe Zadka). - -- Better stack viewer, using tree widget. (XXX Only used by Stack -Viewer menu, not by the debugger.) - -- Format paragraph now recognizes Python block comments and reformats -them correctly (MH) - -- New version of pyclbr.py parses top-level functions and understands -much more of Python's syntax; this is reflected in the class and path -browsers (TP) - -- Much better auto-indent; knows how to indent the insides of -multi-line statements (TP) - -- Call tip window pops up when you type the name of a known function -followed by an open parenthesis. Hit ESC or click elsewhere in the -window to close the tip window (MH) - -- Comment out region now inserts ## to make it stand out more (TP) - -- New path and class browsers based on a tree widget that looks -familiar to Windows users - -- Reworked script running commands to be more intuitive: I/O now -always goes to the *Python Shell* window, and raw_input() works -correctly. You use F5 to import/reload a module: this adds the module -name to the __main__ namespace. You use Control-F5 to run a script: -this runs the script *in* the __main__ namespace. The latter also -sets sys.argv[] to the script name - - -New in IDLE 0.4 (4/7/99) ------------------------- - -Most important change: a new menu entry "File -> Path browser", shows -a 4-column hierarchical browser which lets you browse sys.path, -directories, modules, and classes. Yes, it's a superset of the Class -browser menu entry. There's also a new internal module, -MultiScrolledLists.py, which provides the framework for this dialog. - - -New in IDLE 0.3 (2/17/99) -------------------------- - -Most important changes: - -- Enabled support for running a module, with or without the debugger. -Output goes to a new window. Pressing F5 in a module is effectively a -reload of that module; Control-F5 loads it under the debugger. - -- Re-enable tearing off the Windows menu, and make a torn-off Windows -menu update itself whenever a window is opened or closed. - -- Menu items can now be have a checkbox (when the menu label starts -with "!"); use this for the Debugger and "Auto-open stack viewer" -(was: JIT stack viewer) menu items. - -- Added a Quit button to the Debugger API. - -- The current directory is explicitly inserted into sys.path. - -- Fix the debugger (when using Python 1.5.2b2) to use canonical -filenames for breakpoints, so these actually work. (There's still a -lot of work to be done to the management of breakpoints in the -debugger though.) - -- Closing a window that is still colorizing now actually works. - -- Allow dragging of the separator between the two list boxes in the -class browser. - -- Bind ESC to "close window" of the debugger, stack viewer and class -browser. It removes the selection highlighting in regular text -windows. (These are standard Windows conventions.) - - -New in IDLE 0.2 (1/8/99) ------------------------- - -Lots of changes; here are the highlights: - -General: - -- You can now write and configure your own IDLE extension modules; see -extend.txt. - - -File menu: - -The command to open the Python shell window is now in the File menu. - - -Edit menu: - -New Find dialog with more options; replace dialog; find in files dialog. - -Commands to tabify or untabify a region. - -Command to format a paragraph. - - -Debug menu: - -JIT (Just-In-Time) stack viewer toggle -- if set, the stack viewer -automaticall pops up when you get a traceback. - -Windows menu: - -Zoom height -- make the window full height. - - -Help menu: - -The help text now show up in a regular window so you can search and -even edit it if you like. - - - -IDLE 0.1 was distributed with the Python 1.5.2b1 release on 12/22/98. - -====================================================================== diff --git a/sys/lib/python/idlelib/HyperParser.py b/sys/lib/python/idlelib/HyperParser.py deleted file mode 100644 index 519de74d1..000000000 --- a/sys/lib/python/idlelib/HyperParser.py +++ /dev/null @@ -1,241 +0,0 @@ -""" -HyperParser -=========== -This module defines the HyperParser class, which provides advanced parsing -abilities for the ParenMatch and other extensions. -The HyperParser uses PyParser. PyParser is intended mostly to give information -on the proper indentation of code. HyperParser gives some information on the -structure of code, used by extensions to help the user. -""" - -import string -import keyword -import PyParse - -class HyperParser: - - def __init__(self, editwin, index): - """Initialize the HyperParser to analyze the surroundings of the given - index. - """ - - self.editwin = editwin - self.text = text = editwin.text - - parser = PyParse.Parser(editwin.indentwidth, editwin.tabwidth) - - def index2line(index): - return int(float(index)) - lno = index2line(text.index(index)) - - if not editwin.context_use_ps1: - for context in editwin.num_context_lines: - startat = max(lno - context, 1) - startatindex = `startat` + ".0" - stopatindex = "%d.end" % lno - # We add the newline because PyParse requires a newline at end. - # We add a space so that index won't be at end of line, so that - # its status will be the same as the char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') - bod = parser.find_good_parse_start( - editwin._build_char_in_string_func(startatindex)) - if bod is not None or startat == 1: - break - parser.set_lo(bod or 0) - else: - r = text.tag_prevrange("console", index) - if r: - startatindex = r[1] - else: - startatindex = "1.0" - stopatindex = "%d.end" % lno - # We add the newline because PyParse requires a newline at end. - # We add a space so that index won't be at end of line, so that - # its status will be the same as the char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') - parser.set_lo(0) - - # We want what the parser has, except for the last newline and space. - self.rawtext = parser.str[:-2] - # As far as I can see, parser.str preserves the statement we are in, - # so that stopatindex can be used to synchronize the string with the - # text box indices. - self.stopatindex = stopatindex - self.bracketing = parser.get_last_stmt_bracketing() - # find which pairs of bracketing are openers. These always correspond - # to a character of rawtext. - self.isopener = [i>0 and self.bracketing[i][1] > self.bracketing[i-1][1] - for i in range(len(self.bracketing))] - - self.set_index(index) - - def set_index(self, index): - """Set the index to which the functions relate. Note that it must be - in the same statement. - """ - indexinrawtext = \ - len(self.rawtext) - len(self.text.get(index, self.stopatindex)) - if indexinrawtext < 0: - raise ValueError("The index given is before the analyzed statement") - self.indexinrawtext = indexinrawtext - # find the rightmost bracket to which index belongs - self.indexbracket = 0 - while self.indexbracket < len(self.bracketing)-1 and \ - self.bracketing[self.indexbracket+1][0] < self.indexinrawtext: - self.indexbracket += 1 - if self.indexbracket < len(self.bracketing)-1 and \ - self.bracketing[self.indexbracket+1][0] == self.indexinrawtext and \ - not self.isopener[self.indexbracket+1]: - self.indexbracket += 1 - - def is_in_string(self): - """Is the index given to the HyperParser is in a string?""" - # The bracket to which we belong should be an opener. - # If it's an opener, it has to have a character. - return self.isopener[self.indexbracket] and \ - self.rawtext[self.bracketing[self.indexbracket][0]] in ('"', "'") - - def is_in_code(self): - """Is the index given to the HyperParser is in a normal code?""" - return not self.isopener[self.indexbracket] or \ - self.rawtext[self.bracketing[self.indexbracket][0]] not in \ - ('#', '"', "'") - - def get_surrounding_brackets(self, openers='([{', mustclose=False): - """If the index given to the HyperParser is surrounded by a bracket - defined in openers (or at least has one before it), return the - indices of the opening bracket and the closing bracket (or the - end of line, whichever comes first). - If it is not surrounded by brackets, or the end of line comes before - the closing bracket and mustclose is True, returns None. - """ - bracketinglevel = self.bracketing[self.indexbracket][1] - before = self.indexbracket - while not self.isopener[before] or \ - self.rawtext[self.bracketing[before][0]] not in openers or \ - self.bracketing[before][1] > bracketinglevel: - before -= 1 - if before < 0: - return None - bracketinglevel = min(bracketinglevel, self.bracketing[before][1]) - after = self.indexbracket + 1 - while after < len(self.bracketing) and \ - self.bracketing[after][1] >= bracketinglevel: - after += 1 - - beforeindex = self.text.index("%s-%dc" % - (self.stopatindex, len(self.rawtext)-self.bracketing[before][0])) - if after >= len(self.bracketing) or \ - self.bracketing[after][0] > len(self.rawtext): - if mustclose: - return None - afterindex = self.stopatindex - else: - # We are after a real char, so it is a ')' and we give the index - # before it. - afterindex = self.text.index("%s-%dc" % - (self.stopatindex, - len(self.rawtext)-(self.bracketing[after][0]-1))) - - return beforeindex, afterindex - - # This string includes all chars that may be in a white space - _whitespace_chars = " \t\n\\" - # This string includes all chars that may be in an identifier - _id_chars = string.ascii_letters + string.digits + "_" - # This string includes all chars that may be the first char of an identifier - _id_first_chars = string.ascii_letters + "_" - - # Given a string and pos, return the number of chars in the identifier - # which ends at pos, or 0 if there is no such one. Saved words are not - # identifiers. - def _eat_identifier(self, str, limit, pos): - i = pos - while i > limit and str[i-1] in self._id_chars: - i -= 1 - if i < pos and (str[i] not in self._id_first_chars or \ - keyword.iskeyword(str[i:pos])): - i = pos - return pos - i - - def get_expression(self): - """Return a string with the Python expression which ends at the given - index, which is empty if there is no real one. - """ - if not self.is_in_code(): - raise ValueError("get_expression should only be called if index "\ - "is inside a code.") - - rawtext = self.rawtext - bracketing = self.bracketing - - brck_index = self.indexbracket - brck_limit = bracketing[brck_index][0] - pos = self.indexinrawtext - - last_identifier_pos = pos - postdot_phase = True - - while 1: - # Eat whitespaces, comments, and if postdot_phase is False - one dot - while 1: - if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars: - # Eat a whitespace - pos -= 1 - elif not postdot_phase and \ - pos > brck_limit and rawtext[pos-1] == '.': - # Eat a dot - pos -= 1 - postdot_phase = True - # The next line will fail if we are *inside* a comment, but we - # shouldn't be. - elif pos == brck_limit and brck_index > 0 and \ - rawtext[bracketing[brck_index-1][0]] == '#': - # Eat a comment - brck_index -= 2 - brck_limit = bracketing[brck_index][0] - pos = bracketing[brck_index+1][0] - else: - # If we didn't eat anything, quit. - break - - if not postdot_phase: - # We didn't find a dot, so the expression end at the last - # identifier pos. - break - - ret = self._eat_identifier(rawtext, brck_limit, pos) - if ret: - # There is an identifier to eat - pos = pos - ret - last_identifier_pos = pos - # Now, in order to continue the search, we must find a dot. - postdot_phase = False - # (the loop continues now) - - elif pos == brck_limit: - # We are at a bracketing limit. If it is a closing bracket, - # eat the bracket, otherwise, stop the search. - level = bracketing[brck_index][1] - while brck_index > 0 and bracketing[brck_index-1][1] > level: - brck_index -= 1 - if bracketing[brck_index][0] == brck_limit: - # We were not at the end of a closing bracket - break - pos = bracketing[brck_index][0] - brck_index -= 1 - brck_limit = bracketing[brck_index][0] - last_identifier_pos = pos - if rawtext[pos] in "([": - # [] and () may be used after an identifier, so we - # continue. postdot_phase is True, so we don't allow a dot. - pass - else: - # We can't continue after other types of brackets - break - - else: - # We've found an operator or something. - break - - return rawtext[last_identifier_pos:self.indexinrawtext] diff --git a/sys/lib/python/idlelib/IOBinding.py b/sys/lib/python/idlelib/IOBinding.py deleted file mode 100644 index deeb5c527..000000000 --- a/sys/lib/python/idlelib/IOBinding.py +++ /dev/null @@ -1,584 +0,0 @@ -# changes by dscherer@cmu.edu -# - IOBinding.open() replaces the current window with the opened file, -# if the current window is both unmodified and unnamed -# - IOBinding.loadfile() interprets Windows, UNIX, and Macintosh -# end-of-line conventions, instead of relying on the standard library, -# which will only understand the local convention. - -import os -import types -import sys -import codecs -import tempfile -import tkFileDialog -import tkMessageBox -import re -from Tkinter import * -from SimpleDialog import SimpleDialog - -from configHandler import idleConf - -try: - from codecs import BOM_UTF8 -except ImportError: - # only available since Python 2.3 - BOM_UTF8 = '\xef\xbb\xbf' - -# Try setting the locale, so that we can find out -# what encoding to use -try: - import locale - locale.setlocale(locale.LC_CTYPE, "") -except (ImportError, locale.Error): - pass - -# Encoding for file names -filesystemencoding = sys.getfilesystemencoding() - -encoding = "ascii" -if sys.platform == 'win32': - # On Windows, we could use "mbcs". However, to give the user - # a portable encoding name, we need to find the code page - try: - encoding = locale.getdefaultlocale()[1] - codecs.lookup(encoding) - except LookupError: - pass -else: - try: - # Different things can fail here: the locale module may not be - # loaded, it may not offer nl_langinfo, or CODESET, or the - # resulting codeset may be unknown to Python. We ignore all - # these problems, falling back to ASCII - encoding = locale.nl_langinfo(locale.CODESET) - if encoding is None or encoding is '': - # situation occurs on Mac OS X - encoding = 'ascii' - codecs.lookup(encoding) - except (NameError, AttributeError, LookupError): - # Try getdefaultlocale well: it parses environment variables, - # which may give a clue. Unfortunately, getdefaultlocale has - # bugs that can cause ValueError. - try: - encoding = locale.getdefaultlocale()[1] - if encoding is None or encoding is '': - # situation occurs on Mac OS X - encoding = 'ascii' - codecs.lookup(encoding) - except (ValueError, LookupError): - pass - -encoding = encoding.lower() - -coding_re = re.compile("coding[:=]\s*([-\w_.]+)") - -class EncodingMessage(SimpleDialog): - "Inform user that an encoding declaration is needed." - def __init__(self, master, enc): - self.should_edit = False - - self.root = top = Toplevel(master) - top.bind("<Return>", self.return_event) - top.bind("<Escape>", self.do_ok) - top.protocol("WM_DELETE_WINDOW", self.wm_delete_window) - top.wm_title("I/O Warning") - top.wm_iconname("I/O Warning") - self.top = top - - l1 = Label(top, - text="Non-ASCII found, yet no encoding declared. Add a line like") - l1.pack(side=TOP, anchor=W) - l2 = Entry(top, font="courier") - l2.insert(0, "# -*- coding: %s -*-" % enc) - # For some reason, the text is not selectable anymore if the - # widget is disabled. - # l2['state'] = DISABLED - l2.pack(side=TOP, anchor = W, fill=X) - l3 = Label(top, text="to your file\n" - "Choose OK to save this file as %s\n" - "Edit your general options to silence this warning" % enc) - l3.pack(side=TOP, anchor = W) - - buttons = Frame(top) - buttons.pack(side=TOP, fill=X) - # Both return and cancel mean the same thing: do nothing - self.default = self.cancel = 0 - b1 = Button(buttons, text="Ok", default="active", - command=self.do_ok) - b1.pack(side=LEFT, fill=BOTH, expand=1) - b2 = Button(buttons, text="Edit my file", - command=self.do_edit) - b2.pack(side=LEFT, fill=BOTH, expand=1) - - self._set_transient(master) - - def do_ok(self): - self.done(0) - - def do_edit(self): - self.done(1) - -def coding_spec(str): - """Return the encoding declaration according to PEP 263. - - Raise LookupError if the encoding is declared but unknown. - """ - # Only consider the first two lines - str = str.split("\n")[:2] - str = "\n".join(str) - - match = coding_re.search(str) - if not match: - return None - name = match.group(1) - # Check whether the encoding is known - import codecs - try: - codecs.lookup(name) - except LookupError: - # The standard encoding error does not indicate the encoding - raise LookupError, "Unknown encoding "+name - return name - - -class IOBinding: - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - self.__id_open = self.text.bind("<<open-window-from-file>>", self.open) - self.__id_save = self.text.bind("<<save-window>>", self.save) - self.__id_saveas = self.text.bind("<<save-window-as-file>>", - self.save_as) - self.__id_savecopy = self.text.bind("<<save-copy-of-window-as-file>>", - self.save_a_copy) - self.fileencoding = None - self.__id_print = self.text.bind("<<print-window>>", self.print_window) - - def close(self): - # Undo command bindings - self.text.unbind("<<open-window-from-file>>", self.__id_open) - self.text.unbind("<<save-window>>", self.__id_save) - self.text.unbind("<<save-window-as-file>>",self.__id_saveas) - self.text.unbind("<<save-copy-of-window-as-file>>", self.__id_savecopy) - self.text.unbind("<<print-window>>", self.__id_print) - # Break cycles - self.editwin = None - self.text = None - self.filename_change_hook = None - - def get_saved(self): - return self.editwin.get_saved() - - def set_saved(self, flag): - self.editwin.set_saved(flag) - - def reset_undo(self): - self.editwin.reset_undo() - - filename_change_hook = None - - def set_filename_change_hook(self, hook): - self.filename_change_hook = hook - - filename = None - dirname = None - - def set_filename(self, filename): - if filename and os.path.isdir(filename): - self.filename = None - self.dirname = filename - else: - self.filename = filename - self.dirname = None - self.set_saved(1) - if self.filename_change_hook: - self.filename_change_hook() - - def open(self, event=None, editFile=None): - if self.editwin.flist: - if not editFile: - filename = self.askopenfile() - else: - filename=editFile - if filename: - # If the current window has no filename and hasn't been - # modified, we replace its contents (no loss). Otherwise - # we open a new window. But we won't replace the - # shell window (which has an interp(reter) attribute), which - # gets set to "not modified" at every new prompt. - try: - interp = self.editwin.interp - except: - interp = None - if not self.filename and self.get_saved() and not interp: - self.editwin.flist.open(filename, self.loadfile) - else: - self.editwin.flist.open(filename) - else: - self.text.focus_set() - return "break" - # - # Code for use outside IDLE: - if self.get_saved(): - reply = self.maybesave() - if reply == "cancel": - self.text.focus_set() - return "break" - if not editFile: - filename = self.askopenfile() - else: - filename=editFile - if filename: - self.loadfile(filename) - else: - self.text.focus_set() - return "break" - - eol = r"(\r\n)|\n|\r" # \r\n (Windows), \n (UNIX), or \r (Mac) - eol_re = re.compile(eol) - eol_convention = os.linesep # Default - - def loadfile(self, filename): - try: - # open the file in binary mode so that we can handle - # end-of-line convention ourselves. - f = open(filename,'rb') - chars = f.read() - f.close() - except IOError, msg: - tkMessageBox.showerror("I/O Error", str(msg), master=self.text) - return False - - chars = self.decode(chars) - # We now convert all end-of-lines to '\n's - firsteol = self.eol_re.search(chars) - if firsteol: - self.eol_convention = firsteol.group(0) - if isinstance(self.eol_convention, unicode): - # Make sure it is an ASCII string - self.eol_convention = self.eol_convention.encode("ascii") - chars = self.eol_re.sub(r"\n", chars) - - self.text.delete("1.0", "end") - self.set_filename(None) - self.text.insert("1.0", chars) - self.reset_undo() - self.set_filename(filename) - self.text.mark_set("insert", "1.0") - self.text.see("insert") - self.updaterecentfileslist(filename) - return True - - def decode(self, chars): - """Create a Unicode string - - If that fails, let Tcl try its best - """ - # Check presence of a UTF-8 signature first - if chars.startswith(BOM_UTF8): - try: - chars = chars[3:].decode("utf-8") - except UnicodeError: - # has UTF-8 signature, but fails to decode... - return chars - else: - # Indicates that this file originally had a BOM - self.fileencoding = BOM_UTF8 - return chars - # Next look for coding specification - try: - enc = coding_spec(chars) - except LookupError, name: - tkMessageBox.showerror( - title="Error loading the file", - message="The encoding '%s' is not known to this Python "\ - "installation. The file may not display correctly" % name, - master = self.text) - enc = None - if enc: - try: - return unicode(chars, enc) - except UnicodeError: - pass - # If it is ASCII, we need not to record anything - try: - return unicode(chars, 'ascii') - except UnicodeError: - pass - # Finally, try the locale's encoding. This is deprecated; - # the user should declare a non-ASCII encoding - try: - chars = unicode(chars, encoding) - self.fileencoding = encoding - except UnicodeError: - pass - return chars - - def maybesave(self): - if self.get_saved(): - return "yes" - message = "Do you want to save %s before closing?" % ( - self.filename or "this untitled document") - m = tkMessageBox.Message( - title="Save On Close", - message=message, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.YESNOCANCEL, - master=self.text) - reply = m.show() - if reply == "yes": - self.save(None) - if not self.get_saved(): - reply = "cancel" - self.text.focus_set() - return reply - - def save(self, event): - if not self.filename: - self.save_as(event) - else: - if self.writefile(self.filename): - self.set_saved(1) - try: - self.editwin.store_file_breaks() - except AttributeError: # may be a PyShell - pass - self.text.focus_set() - return "break" - - def save_as(self, event): - filename = self.asksavefile() - if filename: - if self.writefile(filename): - self.set_filename(filename) - self.set_saved(1) - try: - self.editwin.store_file_breaks() - except AttributeError: - pass - self.text.focus_set() - self.updaterecentfileslist(filename) - return "break" - - def save_a_copy(self, event): - filename = self.asksavefile() - if filename: - self.writefile(filename) - self.text.focus_set() - self.updaterecentfileslist(filename) - return "break" - - def writefile(self, filename): - self.fixlastline() - chars = self.encode(self.text.get("1.0", "end-1c")) - if self.eol_convention != "\n": - chars = chars.replace("\n", self.eol_convention) - try: - f = open(filename, "wb") - f.write(chars) - f.flush() - f.close() - return True - except IOError, msg: - tkMessageBox.showerror("I/O Error", str(msg), - master=self.text) - return False - - def encode(self, chars): - if isinstance(chars, types.StringType): - # This is either plain ASCII, or Tk was returning mixed-encoding - # text to us. Don't try to guess further. - return chars - # See whether there is anything non-ASCII in it. - # If not, no need to figure out the encoding. - try: - return chars.encode('ascii') - except UnicodeError: - pass - # If there is an encoding declared, try this first. - try: - enc = coding_spec(chars) - failed = None - except LookupError, msg: - failed = msg - enc = None - if enc: - try: - return chars.encode(enc) - except UnicodeError: - failed = "Invalid encoding '%s'" % enc - if failed: - tkMessageBox.showerror( - "I/O Error", - "%s. Saving as UTF-8" % failed, - master = self.text) - # If there was a UTF-8 signature, use that. This should not fail - if self.fileencoding == BOM_UTF8 or failed: - return BOM_UTF8 + chars.encode("utf-8") - # Try the original file encoding next, if any - if self.fileencoding: - try: - return chars.encode(self.fileencoding) - except UnicodeError: - tkMessageBox.showerror( - "I/O Error", - "Cannot save this as '%s' anymore. Saving as UTF-8" \ - % self.fileencoding, - master = self.text) - return BOM_UTF8 + chars.encode("utf-8") - # Nothing was declared, and we had not determined an encoding - # on loading. Recommend an encoding line. - config_encoding = idleConf.GetOption("main","EditorWindow", - "encoding") - if config_encoding == 'utf-8': - # User has requested that we save files as UTF-8 - return BOM_UTF8 + chars.encode("utf-8") - ask_user = True - try: - chars = chars.encode(encoding) - enc = encoding - if config_encoding == 'locale': - ask_user = False - except UnicodeError: - chars = BOM_UTF8 + chars.encode("utf-8") - enc = "utf-8" - if not ask_user: - return chars - dialog = EncodingMessage(self.editwin.top, enc) - dialog.go() - if dialog.num == 1: - # User asked us to edit the file - encline = "# -*- coding: %s -*-\n" % enc - firstline = self.text.get("1.0", "2.0") - if firstline.startswith("#!"): - # Insert encoding after #! line - self.text.insert("2.0", encline) - else: - self.text.insert("1.0", encline) - return self.encode(self.text.get("1.0", "end-1c")) - return chars - - def fixlastline(self): - c = self.text.get("end-2c") - if c != '\n': - self.text.insert("end-1c", "\n") - - def print_window(self, event): - tempfilename = None - saved = self.get_saved() - if saved: - filename = self.filename - # shell undo is reset after every prompt, looks saved, probably isn't - if not saved or filename is None: - # XXX KBK 08Jun03 Wouldn't it be better to ask the user to save? - (tfd, tempfilename) = tempfile.mkstemp(prefix='IDLE_tmp_') - filename = tempfilename - os.close(tfd) - if not self.writefile(tempfilename): - os.unlink(tempfilename) - return "break" - platform=os.name - printPlatform=1 - if platform == 'posix': #posix platform - command = idleConf.GetOption('main','General', - 'print-command-posix') - command = command + " 2>&1" - elif platform == 'nt': #win32 platform - command = idleConf.GetOption('main','General','print-command-win') - else: #no printing for this platform - printPlatform=0 - if printPlatform: #we can try to print for this platform - command = command % filename - pipe = os.popen(command, "r") - # things can get ugly on NT if there is no printer available. - output = pipe.read().strip() - status = pipe.close() - if status: - output = "Printing failed (exit status 0x%x)\n" % \ - status + output - if output: - output = "Printing command: %s\n" % repr(command) + output - tkMessageBox.showerror("Print status", output, master=self.text) - else: #no printing for this platform - message="Printing is not enabled for this platform: %s" % platform - tkMessageBox.showinfo("Print status", message, master=self.text) - if tempfilename: - os.unlink(tempfilename) - return "break" - - opendialog = None - savedialog = None - - filetypes = [ - ("Python and text files", "*.py *.pyw *.txt", "TEXT"), - ("All text files", "*", "TEXT"), - ("All files", "*"), - ] - - def askopenfile(self): - dir, base = self.defaultfilename("open") - if not self.opendialog: - self.opendialog = tkFileDialog.Open(master=self.text, - filetypes=self.filetypes) - filename = self.opendialog.show(initialdir=dir, initialfile=base) - if isinstance(filename, unicode): - filename = filename.encode(filesystemencoding) - return filename - - def defaultfilename(self, mode="open"): - if self.filename: - return os.path.split(self.filename) - elif self.dirname: - return self.dirname, "" - else: - try: - pwd = os.getcwd() - except os.error: - pwd = "" - return pwd, "" - - def asksavefile(self): - dir, base = self.defaultfilename("save") - if not self.savedialog: - self.savedialog = tkFileDialog.SaveAs(master=self.text, - filetypes=self.filetypes) - filename = self.savedialog.show(initialdir=dir, initialfile=base) - if isinstance(filename, unicode): - filename = filename.encode(filesystemencoding) - return filename - - def updaterecentfileslist(self,filename): - "Update recent file list on all editor windows" - self.editwin.update_recent_files_list(filename) - -def test(): - root = Tk() - class MyEditWin: - def __init__(self, text): - self.text = text - self.flist = None - self.text.bind("<Control-o>", self.open) - self.text.bind("<Control-s>", self.save) - self.text.bind("<Alt-s>", self.save_as) - self.text.bind("<Alt-z>", self.save_a_copy) - def get_saved(self): return 0 - def set_saved(self, flag): pass - def reset_undo(self): pass - def open(self, event): - self.text.event_generate("<<open-window-from-file>>") - def save(self, event): - self.text.event_generate("<<save-window>>") - def save_as(self, event): - self.text.event_generate("<<save-window-as-file>>") - def save_a_copy(self, event): - self.text.event_generate("<<save-copy-of-window-as-file>>") - text = Text(root) - text.pack() - text.focus_set() - editwin = MyEditWin(text) - io = IOBinding(editwin) - root.mainloop() - -if __name__ == "__main__": - test() diff --git a/sys/lib/python/idlelib/Icons/folder.gif b/sys/lib/python/idlelib/Icons/folder.gif Binary files differdeleted file mode 100644 index effe8dc8a..000000000 --- a/sys/lib/python/idlelib/Icons/folder.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/idle.icns b/sys/lib/python/idlelib/Icons/idle.icns Binary files differdeleted file mode 100644 index f65e3130f..000000000 --- a/sys/lib/python/idlelib/Icons/idle.icns +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/minusnode.gif b/sys/lib/python/idlelib/Icons/minusnode.gif Binary files differdeleted file mode 100644 index c72e46ff8..000000000 --- a/sys/lib/python/idlelib/Icons/minusnode.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/openfolder.gif b/sys/lib/python/idlelib/Icons/openfolder.gif Binary files differdeleted file mode 100644 index 24aea1beb..000000000 --- a/sys/lib/python/idlelib/Icons/openfolder.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/plusnode.gif b/sys/lib/python/idlelib/Icons/plusnode.gif Binary files differdeleted file mode 100644 index 13ace90eb..000000000 --- a/sys/lib/python/idlelib/Icons/plusnode.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/python.gif b/sys/lib/python/idlelib/Icons/python.gif Binary files differdeleted file mode 100644 index 58271edec..000000000 --- a/sys/lib/python/idlelib/Icons/python.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/Icons/tk.gif b/sys/lib/python/idlelib/Icons/tk.gif Binary files differdeleted file mode 100644 index a603f5ecb..000000000 --- a/sys/lib/python/idlelib/Icons/tk.gif +++ /dev/null diff --git a/sys/lib/python/idlelib/IdleHistory.py b/sys/lib/python/idlelib/IdleHistory.py deleted file mode 100644 index 960242f78..000000000 --- a/sys/lib/python/idlelib/IdleHistory.py +++ /dev/null @@ -1,88 +0,0 @@ -from configHandler import idleConf - -class History: - - def __init__(self, text, output_sep = "\n"): - self.text = text - self.history = [] - self.history_prefix = None - self.history_pointer = None - self.output_sep = output_sep - self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool") - text.bind("<<history-previous>>", self.history_prev) - text.bind("<<history-next>>", self.history_next) - - def history_next(self, event): - self.history_do(0) - return "break" - - def history_prev(self, event): - self.history_do(1) - return "break" - - def _get_source(self, start, end): - # Get source code from start index to end index. Lines in the - # text control may be separated by sys.ps2 . - lines = self.text.get(start, end).split(self.output_sep) - return "\n".join(lines) - - def _put_source(self, where, source): - output = self.output_sep.join(source.split("\n")) - self.text.insert(where, output) - - def history_do(self, reverse): - nhist = len(self.history) - pointer = self.history_pointer - prefix = self.history_prefix - if pointer is not None and prefix is not None: - if self.text.compare("insert", "!=", "end-1c") or \ - self._get_source("iomark", "end-1c") != self.history[pointer]: - pointer = prefix = None - if pointer is None or prefix is None: - prefix = self._get_source("iomark", "end-1c") - if reverse: - pointer = nhist - else: - if self.cyclic: - pointer = -1 - else: - self.text.bell() - return - nprefix = len(prefix) - while 1: - if reverse: - pointer = pointer - 1 - else: - pointer = pointer + 1 - if pointer < 0 or pointer >= nhist: - self.text.bell() - if not self.cyclic and pointer < 0: - return - else: - if self._get_source("iomark", "end-1c") != prefix: - self.text.delete("iomark", "end-1c") - self._put_source("iomark", prefix) - pointer = prefix = None - break - item = self.history[pointer] - if item[:nprefix] == prefix and len(item) > nprefix: - self.text.delete("iomark", "end-1c") - self._put_source("iomark", item) - break - self.text.mark_set("insert", "end-1c") - self.text.see("insert") - self.text.tag_remove("sel", "1.0", "end") - self.history_pointer = pointer - self.history_prefix = prefix - - def history_store(self, source): - source = source.strip() - if len(source) > 2: - # avoid duplicates - try: - self.history.remove(source) - except ValueError: - pass - self.history.append(source) - self.history_pointer = None - self.history_prefix = None diff --git a/sys/lib/python/idlelib/MultiCall.py b/sys/lib/python/idlelib/MultiCall.py deleted file mode 100644 index 547df13ee..000000000 --- a/sys/lib/python/idlelib/MultiCall.py +++ /dev/null @@ -1,406 +0,0 @@ -""" -MultiCall - a class which inherits its methods from a Tkinter widget (Text, for -example), but enables multiple calls of functions per virtual event - all -matching events will be called, not only the most specific one. This is done -by wrapping the event functions - event_add, event_delete and event_info. -MultiCall recognizes only a subset of legal event sequences. Sequences which -are not recognized are treated by the original Tk handling mechanism. A -more-specific event will be called before a less-specific event. - -The recognized sequences are complete one-event sequences (no emacs-style -Ctrl-X Ctrl-C, no shortcuts like <3>), for all types of events. -Key/Button Press/Release events can have modifiers. -The recognized modifiers are Shift, Control, Option and Command for Mac, and -Control, Alt, Shift, Meta/M for other platforms. - -For all events which were handled by MultiCall, a new member is added to the -event instance passed to the binded functions - mc_type. This is one of the -event type constants defined in this module (such as MC_KEYPRESS). -For Key/Button events (which are handled by MultiCall and may receive -modifiers), another member is added - mc_state. This member gives the state -of the recognized modifiers, as a combination of the modifier constants -also defined in this module (for example, MC_SHIFT). -Using these members is absolutely portable. - -The order by which events are called is defined by these rules: -1. A more-specific event will be called before a less-specific event. -2. A recently-binded event will be called before a previously-binded event, - unless this conflicts with the first rule. -Each function will be called at most once for each event. -""" - -import sys -import os -import string -import re -import Tkinter - -# the event type constants, which define the meaning of mc_type -MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3; -MC_ACTIVATE=4; MC_CIRCULATE=5; MC_COLORMAP=6; MC_CONFIGURE=7; -MC_DEACTIVATE=8; MC_DESTROY=9; MC_ENTER=10; MC_EXPOSE=11; MC_FOCUSIN=12; -MC_FOCUSOUT=13; MC_GRAVITY=14; MC_LEAVE=15; MC_MAP=16; MC_MOTION=17; -MC_MOUSEWHEEL=18; MC_PROPERTY=19; MC_REPARENT=20; MC_UNMAP=21; MC_VISIBILITY=22; -# the modifier state constants, which define the meaning of mc_state -MC_SHIFT = 1<<0; MC_CONTROL = 1<<2; MC_ALT = 1<<3; MC_META = 1<<5 -MC_OPTION = 1<<6; MC_COMMAND = 1<<7 - -# define the list of modifiers, to be used in complex event types. -if sys.platform == "darwin" and sys.executable.count(".app"): - _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",)) - _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND) -else: - _modifiers = (("Control",), ("Alt",), ("Shift",), ("Meta", "M")) - _modifier_masks = (MC_CONTROL, MC_ALT, MC_SHIFT, MC_META) - -# a dictionary to map a modifier name into its number -_modifier_names = dict([(name, number) - for number in range(len(_modifiers)) - for name in _modifiers[number]]) - -# A binder is a class which binds functions to one type of event. It has two -# methods: bind and unbind, which get a function and a parsed sequence, as -# returned by _parse_sequence(). There are two types of binders: -# _SimpleBinder handles event types with no modifiers and no detail. -# No Python functions are called when no events are binded. -# _ComplexBinder handles event types with modifiers and a detail. -# A Python function is called each time an event is generated. - -class _SimpleBinder: - def __init__(self, type, widget, widgetinst): - self.type = type - self.sequence = '<'+_types[type][0]+'>' - self.widget = widget - self.widgetinst = widgetinst - self.bindedfuncs = [] - self.handlerid = None - - def bind(self, triplet, func): - if not self.handlerid: - def handler(event, l = self.bindedfuncs, mc_type = self.type): - event.mc_type = mc_type - wascalled = {} - for i in range(len(l)-1, -1, -1): - func = l[i] - if func not in wascalled: - wascalled[func] = True - r = func(event) - if r: - return r - self.handlerid = self.widget.bind(self.widgetinst, - self.sequence, handler) - self.bindedfuncs.append(func) - - def unbind(self, triplet, func): - self.bindedfuncs.remove(func) - if not self.bindedfuncs: - self.widget.unbind(self.widgetinst, self.sequence, self.handlerid) - self.handlerid = None - - def __del__(self): - if self.handlerid: - self.widget.unbind(self.widgetinst, self.sequence, self.handlerid) - -# An int in range(1 << len(_modifiers)) represents a combination of modifiers -# (if the least significent bit is on, _modifiers[0] is on, and so on). -# _state_subsets gives for each combination of modifiers, or *state*, -# a list of the states which are a subset of it. This list is ordered by the -# number of modifiers is the state - the most specific state comes first. -_states = range(1 << len(_modifiers)) -_state_names = [reduce(lambda x, y: x + y, - [_modifiers[i][0]+'-' for i in range(len(_modifiers)) - if (1 << i) & s], - "") - for s in _states] -_state_subsets = map(lambda i: filter(lambda j: not (j & (~i)), _states), - _states) -for l in _state_subsets: - l.sort(lambda a, b, nummod = lambda x: len(filter(lambda i: (1<<i) & x, - range(len(_modifiers)))): - nummod(b) - nummod(a)) -# _state_codes gives for each state, the portable code to be passed as mc_state -_state_codes = [reduce(lambda x, y: x | y, - [_modifier_masks[i] for i in range(len(_modifiers)) - if (1 << i) & s], - 0) - for s in _states] - -class _ComplexBinder: - # This class binds many functions, and only unbinds them when it is deleted. - # self.handlerids is the list of seqs and ids of binded handler functions. - # The binded functions sit in a dictionary of lists of lists, which maps - # a detail (or None) and a state into a list of functions. - # When a new detail is discovered, handlers for all the possible states - # are binded. - - def __create_handler(self, lists, mc_type, mc_state): - def handler(event, lists = lists, - mc_type = mc_type, mc_state = mc_state, - ishandlerrunning = self.ishandlerrunning, - doafterhandler = self.doafterhandler): - ishandlerrunning[:] = [True] - event.mc_type = mc_type - event.mc_state = mc_state - wascalled = {} - r = None - for l in lists: - for i in range(len(l)-1, -1, -1): - func = l[i] - if func not in wascalled: - wascalled[func] = True - r = l[i](event) - if r: - break - if r: - break - ishandlerrunning[:] = [] - # Call all functions in doafterhandler and remove them from list - while doafterhandler: - doafterhandler.pop()() - if r: - return r - return handler - - def __init__(self, type, widget, widgetinst): - self.type = type - self.typename = _types[type][0] - self.widget = widget - self.widgetinst = widgetinst - self.bindedfuncs = {None: [[] for s in _states]} - self.handlerids = [] - # we don't want to change the lists of functions while a handler is - # running - it will mess up the loop and anyway, we usually want the - # change to happen from the next event. So we have a list of functions - # for the handler to run after it finishes calling the binded functions. - # It calls them only once. - # ishandlerrunning is a list. An empty one means no, otherwise - yes. - # this is done so that it would be mutable. - self.ishandlerrunning = [] - self.doafterhandler = [] - for s in _states: - lists = [self.bindedfuncs[None][i] for i in _state_subsets[s]] - handler = self.__create_handler(lists, type, _state_codes[s]) - seq = '<'+_state_names[s]+self.typename+'>' - self.handlerids.append((seq, self.widget.bind(self.widgetinst, - seq, handler))) - - def bind(self, triplet, func): - if not self.bindedfuncs.has_key(triplet[2]): - self.bindedfuncs[triplet[2]] = [[] for s in _states] - for s in _states: - lists = [ self.bindedfuncs[detail][i] - for detail in (triplet[2], None) - for i in _state_subsets[s] ] - handler = self.__create_handler(lists, self.type, - _state_codes[s]) - seq = "<%s%s-%s>"% (_state_names[s], self.typename, triplet[2]) - self.handlerids.append((seq, self.widget.bind(self.widgetinst, - seq, handler))) - doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].append(func) - if not self.ishandlerrunning: - doit() - else: - self.doafterhandler.append(doit) - - def unbind(self, triplet, func): - doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].remove(func) - if not self.ishandlerrunning: - doit() - else: - self.doafterhandler.append(doit) - - def __del__(self): - for seq, id in self.handlerids: - self.widget.unbind(self.widgetinst, seq, id) - -# define the list of event types to be handled by MultiEvent. the order is -# compatible with the definition of event type constants. -_types = ( - ("KeyPress", "Key"), ("KeyRelease",), ("ButtonPress", "Button"), - ("ButtonRelease",), ("Activate",), ("Circulate",), ("Colormap",), - ("Configure",), ("Deactivate",), ("Destroy",), ("Enter",), ("Expose",), - ("FocusIn",), ("FocusOut",), ("Gravity",), ("Leave",), ("Map",), - ("Motion",), ("MouseWheel",), ("Property",), ("Reparent",), ("Unmap",), - ("Visibility",), -) - -# which binder should be used for every event type? -_binder_classes = (_ComplexBinder,) * 4 + (_SimpleBinder,) * (len(_types)-4) - -# A dictionary to map a type name into its number -_type_names = dict([(name, number) - for number in range(len(_types)) - for name in _types[number]]) - -_keysym_re = re.compile(r"^\w+$") -_button_re = re.compile(r"^[1-5]$") -def _parse_sequence(sequence): - """Get a string which should describe an event sequence. If it is - successfully parsed as one, return a tuple containing the state (as an int), - the event type (as an index of _types), and the detail - None if none, or a - string if there is one. If the parsing is unsuccessful, return None. - """ - if not sequence or sequence[0] != '<' or sequence[-1] != '>': - return None - words = string.split(sequence[1:-1], '-') - - modifiers = 0 - while words and words[0] in _modifier_names: - modifiers |= 1 << _modifier_names[words[0]] - del words[0] - - if words and words[0] in _type_names: - type = _type_names[words[0]] - del words[0] - else: - return None - - if _binder_classes[type] is _SimpleBinder: - if modifiers or words: - return None - else: - detail = None - else: - # _ComplexBinder - if type in [_type_names[s] for s in ("KeyPress", "KeyRelease")]: - type_re = _keysym_re - else: - type_re = _button_re - - if not words: - detail = None - elif len(words) == 1 and type_re.match(words[0]): - detail = words[0] - else: - return None - - return modifiers, type, detail - -def _triplet_to_sequence(triplet): - if triplet[2]: - return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'-'+ \ - triplet[2]+'>' - else: - return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'>' - -_multicall_dict = {} -def MultiCallCreator(widget): - """Return a MultiCall class which inherits its methods from the - given widget class (for example, Tkinter.Text). This is used - instead of a templating mechanism. - """ - if widget in _multicall_dict: - return _multicall_dict[widget] - - class MultiCall (widget): - assert issubclass(widget, Tkinter.Misc) - - def __init__(self, *args, **kwargs): - apply(widget.__init__, (self,)+args, kwargs) - # a dictionary which maps a virtual event to a tuple with: - # 0. the function binded - # 1. a list of triplets - the sequences it is binded to - self.__eventinfo = {} - self.__binders = [_binder_classes[i](i, widget, self) - for i in range(len(_types))] - - def bind(self, sequence=None, func=None, add=None): - #print "bind(%s, %s, %s) called." % (sequence, func, add) - if type(sequence) is str and len(sequence) > 2 and \ - sequence[:2] == "<<" and sequence[-2:] == ">>": - if sequence in self.__eventinfo: - ei = self.__eventinfo[sequence] - if ei[0] is not None: - for triplet in ei[1]: - self.__binders[triplet[1]].unbind(triplet, ei[0]) - ei[0] = func - if ei[0] is not None: - for triplet in ei[1]: - self.__binders[triplet[1]].bind(triplet, func) - else: - self.__eventinfo[sequence] = [func, []] - return widget.bind(self, sequence, func, add) - - def unbind(self, sequence, funcid=None): - if type(sequence) is str and len(sequence) > 2 and \ - sequence[:2] == "<<" and sequence[-2:] == ">>" and \ - sequence in self.__eventinfo: - func, triplets = self.__eventinfo[sequence] - if func is not None: - for triplet in triplets: - self.__binders[triplet[1]].unbind(triplet, func) - self.__eventinfo[sequence][0] = None - return widget.unbind(self, sequence, funcid) - - def event_add(self, virtual, *sequences): - #print "event_add(%s,%s) was called"%(repr(virtual),repr(sequences)) - if virtual not in self.__eventinfo: - self.__eventinfo[virtual] = [None, []] - - func, triplets = self.__eventinfo[virtual] - for seq in sequences: - triplet = _parse_sequence(seq) - if triplet is None: - #print >> sys.stderr, "Seq. %s was added by Tkinter."%seq - widget.event_add(self, virtual, seq) - else: - if func is not None: - self.__binders[triplet[1]].bind(triplet, func) - triplets.append(triplet) - - def event_delete(self, virtual, *sequences): - if virtual not in self.__eventinfo: - return - func, triplets = self.__eventinfo[virtual] - for seq in sequences: - triplet = _parse_sequence(seq) - if triplet is None: - #print >> sys.stderr, "Seq. %s was deleted by Tkinter."%seq - widget.event_delete(self, virtual, seq) - else: - if func is not None: - self.__binders[triplet[1]].unbind(triplet, func) - triplets.remove(triplet) - - def event_info(self, virtual=None): - if virtual is None or virtual not in self.__eventinfo: - return widget.event_info(self, virtual) - else: - return tuple(map(_triplet_to_sequence, - self.__eventinfo[virtual][1])) + \ - widget.event_info(self, virtual) - - def __del__(self): - for virtual in self.__eventinfo: - func, triplets = self.__eventinfo[virtual] - if func: - for triplet in triplets: - self.__binders[triplet[1]].unbind(triplet, func) - - - _multicall_dict[widget] = MultiCall - return MultiCall - -if __name__ == "__main__": - # Test - root = Tkinter.Tk() - text = MultiCallCreator(Tkinter.Text)(root) - text.pack() - def bindseq(seq, n=[0]): - def handler(event): - print seq - text.bind("<<handler%d>>"%n[0], handler) - text.event_add("<<handler%d>>"%n[0], seq) - n[0] += 1 - bindseq("<Key>") - bindseq("<Control-Key>") - bindseq("<Alt-Key-a>") - bindseq("<Control-Key-a>") - bindseq("<Alt-Control-Key-a>") - bindseq("<Key-b>") - bindseq("<Control-Button-1>") - bindseq("<Alt-Button-1>") - bindseq("<FocusOut>") - bindseq("<Enter>") - bindseq("<Leave>") - root.mainloop() diff --git a/sys/lib/python/idlelib/MultiStatusBar.py b/sys/lib/python/idlelib/MultiStatusBar.py deleted file mode 100644 index 2d4c5473d..000000000 --- a/sys/lib/python/idlelib/MultiStatusBar.py +++ /dev/null @@ -1,32 +0,0 @@ -from Tkinter import * - -class MultiStatusBar(Frame): - - def __init__(self, master=None, **kw): - if master is None: - master = Tk() - Frame.__init__(self, master, **kw) - self.labels = {} - - def set_label(self, name, text='', side=LEFT): - if not self.labels.has_key(name): - label = Label(self, bd=1, relief=SUNKEN, anchor=W) - label.pack(side=side) - self.labels[name] = label - else: - label = self.labels[name] - label.config(text=text) - -def _test(): - b = Frame() - c = Text(b) - c.pack(side=TOP) - a = MultiStatusBar(b) - a.set_label("one", "hello") - a.set_label("two", "world") - a.pack(side=BOTTOM, fill=X) - b.pack() - b.mainloop() - -if __name__ == '__main__': - _test() diff --git a/sys/lib/python/idlelib/NEWS.txt b/sys/lib/python/idlelib/NEWS.txt deleted file mode 100644 index 54ce807d6..000000000 --- a/sys/lib/python/idlelib/NEWS.txt +++ /dev/null @@ -1,613 +0,0 @@ -What's New in IDLE 1.2.1? -========================= - -*Release date: 18-APR-2007* - -What's New in IDLE 1.2.1c1? -=========================== - -*Release date: 05-APR-2007* - -What's New in IDLE 1.2? -======================= - -*Release date: 19-SEP-2006* - -What's New in IDLE 1.2c2? -========================= - -*Release date: 12-SEP-2006* - -What's New in IDLE 1.2c1? -========================= - -*Release date: 17-AUG-2006* - -- File menu hotkeys: there were three 'p' assignments. Reassign the - 'Save Copy As' and 'Print' hotkeys to 'y' and 't'. Change the - Shell hotkey from 's' to 'l'. - -- IDLE honors new quit() and exit() commands from site.py Quitter() object. - Patch 1540892, Jim Jewett - -- The 'with' statement is now a Code Context block opener. - Patch 1540851, Jim Jewett - -- Retrieval of previous shell command was not always preserving indentation - (since 1.2a1) Patch 1528468 Tal Einat. - -- Changing tokenize (39046) to detect dedent broke tabnanny check (since 1.2a1) - -- ToggleTab dialog was setting indent to 8 even if cancelled (since 1.2a1). - -- When used w/o subprocess, all exceptions were preceded by an error - message claiming they were IDLE internal errors (since 1.2a1). - -What's New in IDLE 1.2b3? -========================= - -*Release date: 03-AUG-2006* - -- EditorWindow.test() was failing. Bug 1417598 - -- EditorWindow failed when used stand-alone if sys.ps1 not set. - Bug 1010370 Dave Florek - -- Tooltips failed on new-syle class __init__ args. Bug 1027566 Loren Guthrie - -- Avoid occasional failure to detect closing paren properly. - Patch 1407280 Tal Einat - -- Rebinding Tab key was inserting 'tab' instead of 'Tab'. Bug 1179168. - -- Colorizer now handles #<builtin> correctly, also unicode strings and - 'as' keyword in comment directly following import command. Closes 1325071. - Patch 1479219 Tal Einat - -What's New in IDLE 1.2b2? -========================= - -*Release date: 11-JUL-2006* - -What's New in IDLE 1.2b1? -========================= - -*Release date: 20-JUN-2006* - -What's New in IDLE 1.2a2? -========================= - -*Release date: 27-APR-2006* - -What's New in IDLE 1.2a1? -========================= - -*Release date: 05-APR-2006* - -- Source file f.flush() after writing; trying to avoid lossage if user - kills GUI. - -- Options / Keys / Advanced dialog made functional. Also, allow binding - of 'movement' keys. - -- 'syntax' patch adds improved calltips and a new class attribute listbox. - MultiCall module allows binding multiple actions to an event. - Patch 906702 Noam Raphael - -- Better indentation after first line of string continuation. - IDLEfork Patch 681992, Noam Raphael - -- Fixed CodeContext alignment problem, following suggestion from Tal Einat. - -- Increased performance in CodeContext extension Patch 936169 Noam Raphael - -- Mac line endings were incorrect when pasting code from some browsers - when using X11 and the Fink distribution. Python Bug 1263656. - -- <Enter> when cursor is on a previous command retrieves that command. Instead - of replacing the input line, the previous command is now appended to the - input line. Indentation is preserved, and undo is enabled. - Patch 1196917 Jeff Shute - -- Clarify "tab/space" Error Dialog and "Tab Width" Dialog associated with - the Untabify command. - -- Corrected "tab/space" Error Dialog to show correct menu for Untabify. - Patch 1196980 Jeff Shute - -- New files are colorized by default, and colorizing is removed when - saving as non-Python files. Patch 1196895 Jeff Shute - Closes Python Bugs 775012 and 800432, partial fix IDLEfork 763524 - -- Improve subprocess link error notification. - -- run.py: use Queue's blocking feature instead of sleeping in the main - loop. Patch # 1190163 Michiel de Hoon - -- Add config-main option to make the 'history' feature non-cyclic. - Default remains cyclic. Python Patch 914546 Noam Raphael. - -- Removed ability to configure tabs indent from Options dialog. This 'feature' - has never worked and no one has complained. It is still possible to set a - default tabs (v. spaces) indent 'manually' via config-main.def (or to turn on - tabs for the current EditorWindow via the Format menu) but IDLE will - encourage indentation via spaces. - -- Enable setting the indentation width using the Options dialog. - Bug # 783877 - -- Add keybindings for del-word-left and del-word-right. - -- Discourage using an indent width other than 8 when using tabs to indent - Python code. - -- Restore use of EditorWindow.set_indentation_params(), was dead code since - Autoindent was merged into EditorWindow. This allows IDLE to conform to the - indentation width of a loaded file. (But it still will not switch to tabs - even if the file uses tabs.) Any change in indent width is local to that - window. - -- Add Tabnanny check before Run/F5, not just when Checking module. - -- If an extension can't be loaded, print warning and skip it instead of - erroring out. - -- Improve error handling when .idlerc can't be created (warn and exit). - -- The GUI was hanging if the shell window was closed while a raw_input() - was pending. Restored the quit() of the readline() mainloop(). - http://mail.python.org/pipermail/idle-dev/2004-December/002307.html - -- The remote procedure call module rpc.py can now access data attributes of - remote registered objects. Changes to these attributes are local, however. - -What's New in IDLE 1.1? -======================= - -*Release date: 30-NOV-2004* - -- On OpenBSD, terminating IDLE with ctrl-c from the command line caused a - stuck subprocess MainThread because only the SocketThread was exiting. - -What's New in IDLE 1.1b3/rc1? -============================= - -*Release date: 18-NOV-2004* - -- Saving a Keyset w/o making changes (by using the "Save as New Custom Key Set" - button) caused IDLE to fail on restart (no new keyset was created in - config-keys.cfg). Also true for Theme/highlights. Python Bug 1064535. - -- A change to the linecache.py API caused IDLE to exit when an exception was - raised while running without the subprocess (-n switch). Python Bug 1063840. - -What's New in IDLE 1.1b2? -========================= - -*Release date: 03-NOV-2004* - -- When paragraph reformat width was made configurable, a bug was - introduced that caused reformatting of comment blocks to ignore how - far the block was indented, effectively adding the indentation width - to the reformat width. This has been repaired, and the reformat - width is again a bound on the total width of reformatted lines. - -What's New in IDLE 1.1b1? -========================= - -*Release date: 15-OCT-2004* - - -What's New in IDLE 1.1a3? -========================= - -*Release date: 02-SEP-2004* - -- Improve keyboard focus binding, especially in Windows menu. Improve - window raising, especially in the Windows menu and in the debugger. - IDLEfork 763524. - -- If user passes a non-existant filename on the commandline, just - open a new file, don't raise a dialog. IDLEfork 854928. - - -What's New in IDLE 1.1a2? -========================= - -*Release date: 05-AUG-2004* - -- EditorWindow.py was not finding the .chm help file on Windows. Typo - at Rev 1.54. Python Bug 990954 - -- checking sys.platform for substring 'win' was breaking IDLE docs on Mac - (darwin). Also, Mac Safari browser requires full file:// URIs. SF 900580. - - -What's New in IDLE 1.1a1? -========================= - -*Release date: 08-JUL-2004* - -- Redirect the warning stream to the shell during the ScriptBinding check of - user code and format the warning similarly to an exception for both that - check and for runtime warnings raised in the subprocess. - -- CodeContext hint pane visibility state is now persistent across sessions. - The pane no longer appears in the shell window. Added capability to limit - extensions to shell window or editor windows. Noam Raphael addition - to Patch 936169. - -- Paragraph reformat width is now a configurable parameter in the - Options GUI. - -- New Extension: CodeContext. Provides block structuring hints for code - which has scrolled above an edit window. Patch 936169 Noam Raphael. - -- If nulls somehow got into the strings in recent-files.lst - EditorWindow.update_recent_files_list() was failing. Python Bug 931336. - -- If the normal background is changed via Configure/Highlighting, it will - update immediately, thanks to the previously mentioned patch by Nigel Rowe. - -- Add a highlight theme for builtin keywords. Python Patch 805830 Nigel Rowe - This also fixed IDLEfork bug [ 693418 ] Normal text background color not - refreshed and Python bug [897872 ] Unknown color name on HP-UX - -- rpc.py:SocketIO - Large modules were generating large pickles when downloaded - to the execution server. The return of the OK response from the subprocess - initialization was interfering and causing the sending socket to be not - ready. Add an IO ready test to fix this. Moved the polling IO ready test - into pollpacket(). - -- Fix typo in rpc.py, s/b "pickle.PicklingError" not "pickle.UnpicklingError". - -- Added a Tk error dialog to run.py inform the user if the subprocess can't - connect to the user GUI process. Added a timeout to the GUI's listening - socket. Added Tk error dialogs to PyShell.py to announce a failure to bind - the port or connect to the subprocess. Clean up error handling during - connection initiation phase. This is an update of Python Patch 778323. - -- Print correct exception even if source file changed since shell was - restarted. IDLEfork Patch 869012 Noam Raphael - -- Keybindings with the Shift modifier now work correctly. So do bindings which - use the Space key. Limit unmodified user keybindings to the function keys. - Python Bug 775353, IDLEfork Bugs 755647, 761557 - -- After an exception, run.py was not setting the exception vector. Noam - Raphael suggested correcting this so pdb's postmortem pm() would work. - IDLEfork Patch 844675 - -- IDLE now does not fail to save the file anymore if the Tk buffer is not a - Unicode string, yet eol_convention is. Python Bugs 774680, 788378 - -- IDLE didn't start correctly when Python was installed in "Program Files" on - W2K and XP. Python Bugs 780451, 784183 - -- config-main.def documentation incorrectly referred to idle- instead of - config- filenames. SF 782759 Also added note about .idlerc location. - - -What's New in IDLE 1.0? -======================= - -*Release date: 29-Jul-2003* - -- Added a banner to the shell discussing warnings possibly raised by personal - firewall software. Added same comment to README.txt. - - -What's New in IDLE 1.0 release candidate 2? -=========================================== - -*Release date: 24-Jul-2003* - -- Calltip error when docstring was None Python Bug 775541 - - -What's New in IDLE 1.0 release candidate 1? -=========================================== - -*Release date: 18-Jul-2003* - -- Updated extend.txt, help.txt, and config-extensions.def to correctly - reflect the current status of the configuration system. Python Bug 768469 - -- Fixed: Call Tip Trimming May Loop Forever. Python Patch 769142 (Daniels) - -- Replaced apply(f, args, kwds) with f(*args, **kwargs) to improve performance - Python Patch 768187 - -- Break or continue statements outside a loop were causing IDLE crash - Python Bug 767794 - -- Convert Unicode strings from readline to IOBinding.encoding. Also set - sys.std{in|out|err}.encoding, for both the local and the subprocess case. - SF IDLEfork patch 682347. - - -What's New in IDLE 1.0b2? -========================= - -*Release date: 29-Jun-2003* - -- Extend AboutDialog.ViewFile() to support file encodings. Make the CREDITS - file Latin-1. - -- Updated the About dialog to reflect re-integration into Python. Provide - buttons to display Python's NEWS, License, and Credits, plus additional - buttons for IDLE's README and NEWS. - -- TextViewer() now has a third parameter which allows inserting text into the - viewer instead of reading from a file. - -- (Created the .../Lib/idlelib directory in the Python CVS, which is a clone of - IDLEfork modified to install in the Python environment. The code in the - interrupt module has been moved to thread.interrupt_main(). ) - -- Printing the Shell window was failing if it was not saved first SF 748975 - -- When using the Search in Files dialog, if the user had a selection - highlighted in his Editor window, insert it into the dialog search field. - -- The Python Shell entry was disappearing from the Windows menu. - -- Update the Windows file list when a file name change occurs - -- Change to File / Open Module: always pop up the dialog, using the current - selection as the default value. This is easier to use habitually. - -- Avoided a problem with starting the subprocess when 'localhost' doesn't - resolve to the user's loopback interface. SF 747772 - -- Fixed an issue with highlighted errors never de-colorizing. SF 747677. Also - improved notification of Tabnanny Token Error. - -- File / New will by default save in the directory of the Edit window from - which it was initiated. SF 748973 Guido van Rossum patch. - - -What's New in IDLEfork 0.9b1? -============================= - -*Release date: 02-Jun-2003* - -- The current working directory of the execution environment (and shell - following completion of execution) is now that of the module being run. - -- Added the delete-exitfunc option to config-main.def. (This option is not - included in the Options dialog.) Setting this to True (the default) will - cause IDLE to not run sys.exitfunc/atexit when the subprocess exits. - -- IDLE now preserves the line ending codes when editing a file produced on - a different platform. SF 661759, SF 538584 - -- Reduced default editor font size to 10 point and increased window height - to provide a better initial impression on Windows. - -- Options / Fonts/Tabs / Set Base Editor Font: List box was not highlighting - the default font when first installed on Windows. SF 661676 - -- Added Autosave feature: when user runs code from edit window, if the file - has been modified IDLE will silently save it if Autosave is enabled. The - option is set in the Options dialog, and the default is to prompt the - user to save the file. SF 661318 Bruce Sherwood patch. - -- Improved the RESTART annotation in the shell window when the user restarts - the shell while it is generating output. Also improved annotation when user - repeatedly hammers the Ctrl-F6 restart. - -- Allow IDLE to run when not installed and cwd is not the IDLE directory - SF Patch 686254 "Run IDLEfork from any directory without set-up" - Raphael - -- When a module is run from an EditorWindow: if its directory is not in - sys.path, prepend it. This allows the module to import other modules in - the same directory. Do the same for a script run from the command line. - -- Correctly restart the subprocess if it is running user code and the user - attempts to run some other module or restarts the shell. Do the same if - the link is broken and it is possible to restart the subprocess and re- - connect to the GUI. SF RFE 661321. - -- Improved exception reporting when running commands or scripts from the - command line. - -- Added a -n command line switch to start IDLE without the subprocess. - Removed the Shell menu when running in that mode. Updated help messages. - -- Added a comment to the shell startup header to indicate when IDLE is not - using the subprocess. - -- Restore the ability to run without the subprocess. This can be important for - some platforms or configurations. (Running without the subprocess allows the - debugger to trace through parts of IDLE itself, which may or may not be - desirable, depending on your point of view. In addition, the traditional - reload/import tricks must be use if user source code is changed.) This is - helpful for developing IDLE using IDLE, because one instance can be used to - edit the code and a separate instance run to test changes. (Multiple - concurrent IDLE instances with subprocesses is a future feature) - -- Improve the error message a user gets when saving a file with non-ASCII - characters and no source encoding is specified. Done by adding a dialog - 'EncodingMessage', which contains the line to add in a fixed-font entry - widget, and which has a button to add that line to the file automatically. - Also, add a configuration option 'EditorWindow/encoding', which has three - possible values: none, utf-8, and locale. None is the default: IDLE will show - this dialog when non-ASCII characters are encountered. utf-8 means that files - with non-ASCII characters are saved as utf-8-with-bom. locale means that - files are saved in the locale's encoding; the dialog is only displayed if the - source contains characters outside the locale's charset. SF 710733 - Loewis - -- Improved I/O response by tweaking the wait parameter in various - calls to signal.signal(). - -- Implemented a threaded subprocess which allows interrupting a pass - loop in user code using the 'interrupt' extension. User code runs - in MainThread, while the RPCServer is handled by SockThread. This is - necessary because Windows doesn't support signals. - -- Implemented the 'interrupt' extension module, which allows a subthread - to raise a KeyboardInterrupt in the main thread. - -- Attempting to save the shell raised an error related to saving - breakpoints, which are not implemented in the shell - -- Provide a correct message when 'exit' or 'quit' are entered at the - IDLE command prompt SF 695861 - -- Eliminate extra blank line in shell output caused by not flushing - stdout when user code ends with an unterminated print. SF 695861 - -- Moved responsibility for exception formatting (i.e. pruning IDLE internal - calls) out of rpc.py into the client and server. - -- Exit IDLE cleanly even when doing subprocess I/O - -- Handle subprocess interrupt with an RPC message. - -- Restart the subprocess if it terminates itself. (VPython programs do that) - -- Support subclassing of exceptions, including in the shell, by moving the - exception formatting to the subprocess. - - - -What's New in IDLEfork 0.9 Alpha 2? -=================================== - -*Release date: 27-Jan-2003* - -- Updated INSTALL.txt to claify use of the python2 rpm. - -- Improved formatting in IDLE Help. - -- Run menu: Replace "Run Script" with "Run Module". - -- Code encountering an unhandled exception under the debugger now shows - the correct traceback, with IDLE internal levels pruned out. - -- If an exception occurs entirely in IDLE, don't prune the IDLE internal - modules from the traceback displayed. - -- Class Browser and Path Browser now use Alt-Key-2 for vertical zoom. - -- IDLE icons will now install correctly even when setup.py is run from the - build directory - -- Class Browser now compatible with Python2.3 version of pyclbr.py - -- Left cursor move in presence of selected text now moves from left end - of the selection. - -- Add Meta keybindings to "IDLE Classic Windows" to handle reversed - Alt/Meta on some Linux distros. - -- Change default: IDLE now starts with Python Shell. - -- Removed the File Path from the Additional Help Sources scrolled list. - -- Add capability to access Additional Help Sources on the web if the - Help File Path begins with //http or www. (Otherwise local path is - validated, as before.) - -- Additional Help Sources were not being posted on the Help menu in the - order entered. Implement sorting the list by [HelpFiles] 'option' - number. - -- Add Browse button to New Help Source dialog. Arrange to start in - Python/Doc if platform is Windows, otherwise start in current directory. - -- Put the Additional Help Sources directly on the Help menu instead of in - an Extra Help cascade menu. Rearrange the Help menu so the Additional - Help Sources come last. Update help.txt appropriately. - -- Fix Tk root pop-ups in configSectionNameDialog.py and configDialog.py - -- Uniform capitalization in General tab of ConfigDialog, update the doc string. - -- Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly - deleting Additional Help Sources from the user's config file. - -- Make configHelpSourceEdit OK button the default and bind <Return> - -- Fix Tk root pop-ups in configHelpSourceEdit: error dialogs not attached - to parents. - -- Use os.startfile() to open both Additional Help and Python Help on the - Windows platform. The application associated with the file type will act as - the viewer. Windows help files (.chm) are now supported via the - Settings/General/Additional Help facility. - -- If Python Help files are installed locally on Linux, use them instead of - accessing python.org. - -- Make the methods for finding the Python help docs more robust, and make - them work in the installed configuration, also. - -- On the Save Before Run dialog, make the OK button the default. One - less mouse action! - -- Add a method: EditorWindow.get_geometry() for future use in implementing - window location persistence. - -- Removed the "Help/Advice" menu entry. Thanks, David! We'll remember! - -- Change the "Classic Windows" theme's paste key to be <ctrl-v>. - -- Rearrange the Shell menu to put Stack Viewer entries adjacent. - -- Add the ability to restart the subprocess interpreter from the shell window; - add an associated menu entry "Shell/Restart" with binding Control-F6. Update - IDLE help. - -- Upon a restart, annotate the shell window with a "restart boundary". Add a - shell window menu "Shell/View Restart" with binding F6 to jump to the most - recent restart boundary. - -- Add Shell menu to Python Shell; change "Settings" to "Options". - -- Remove incorrect comment in setup.py: IDLEfork is now installed as a package. - -- Add INSTALL.txt, HISTORY.txt, NEWS.txt to installed configuration. - -- In installer text, fix reference to Visual Python, should be VPython. - Properly credit David Scherer. - -- Modified idle, idle.py, idle.pyw to improve exception handling. - - -What's New in IDLEfork 0.9 Alpha 1? -=================================== - -*Release date: 31-Dec-2002* - -- First release of major new functionality. For further details refer to - Idle-dev and/or the Sourceforge CVS. - -- Adapted to the Mac platform. - -- Overhauled the IDLE startup options and revised the idle -h help message, - which provides details of command line usage. - -- Multiple bug fixes and usability enhancements. - -- Introduced the new RPC implementation, which includes a debugger. The output - of user code is to the shell, and the shell may be used to inspect the - environment after the run has finished. (In version 0.8.1 the shell - environment was separate from the environment of the user code.) - -- Introduced the configuration GUI and a new About dialog. - -- Removed David Scherer's Remote Procedure Call code and replaced with Guido - van Rossum's. GvR code has support for the IDLE debugger and uses the shell - to inspect the environment of code Run from an Edit window. Files removed: - ExecBinding.py, loader.py, protocol.py, Remote.py, spawn.py - --------------------------------------------------------------------- -Refer to HISTORY.txt for additional information on earlier releases. --------------------------------------------------------------------- - - - - - diff --git a/sys/lib/python/idlelib/ObjectBrowser.py b/sys/lib/python/idlelib/ObjectBrowser.py deleted file mode 100644 index a2a6cee49..000000000 --- a/sys/lib/python/idlelib/ObjectBrowser.py +++ /dev/null @@ -1,151 +0,0 @@ -# XXX TO DO: -# - popup menu -# - support partial or total redisplay -# - more doc strings -# - tooltips - -# object browser - -# XXX TO DO: -# - for classes/modules, add "open source" to object browser - -from TreeWidget import TreeItem, TreeNode, ScrolledCanvas - -from repr import Repr - -myrepr = Repr() -myrepr.maxstring = 100 -myrepr.maxother = 100 - -class ObjectTreeItem(TreeItem): - def __init__(self, labeltext, object, setfunction=None): - self.labeltext = labeltext - self.object = object - self.setfunction = setfunction - def GetLabelText(self): - return self.labeltext - def GetText(self): - return myrepr.repr(self.object) - def GetIconName(self): - if not self.IsExpandable(): - return "python" - def IsEditable(self): - return self.setfunction is not None - def SetText(self, text): - try: - value = eval(text) - self.setfunction(value) - except: - pass - else: - self.object = value - def IsExpandable(self): - return not not dir(self.object) - def GetSubList(self): - keys = dir(self.object) - sublist = [] - for key in keys: - try: - value = getattr(self.object, key) - except AttributeError: - continue - item = make_objecttreeitem( - str(key) + " =", - value, - lambda value, key=key, object=self.object: - setattr(object, key, value)) - sublist.append(item) - return sublist - -class InstanceTreeItem(ObjectTreeItem): - def IsExpandable(self): - return True - def GetSubList(self): - sublist = ObjectTreeItem.GetSubList(self) - sublist.insert(0, - make_objecttreeitem("__class__ =", self.object.__class__)) - return sublist - -class ClassTreeItem(ObjectTreeItem): - def IsExpandable(self): - return True - def GetSubList(self): - sublist = ObjectTreeItem.GetSubList(self) - if len(self.object.__bases__) == 1: - item = make_objecttreeitem("__bases__[0] =", - self.object.__bases__[0]) - else: - item = make_objecttreeitem("__bases__ =", self.object.__bases__) - sublist.insert(0, item) - return sublist - -class AtomicObjectTreeItem(ObjectTreeItem): - def IsExpandable(self): - return 0 - -class SequenceTreeItem(ObjectTreeItem): - def IsExpandable(self): - return len(self.object) > 0 - def keys(self): - return range(len(self.object)) - def GetSubList(self): - sublist = [] - for key in self.keys(): - try: - value = self.object[key] - except KeyError: - continue - def setfunction(value, key=key, object=self.object): - object[key] = value - item = make_objecttreeitem("%r:" % (key,), value, setfunction) - sublist.append(item) - return sublist - -class DictTreeItem(SequenceTreeItem): - def keys(self): - keys = self.object.keys() - try: - keys.sort() - except: - pass - return keys - -from types import * - -dispatch = { - IntType: AtomicObjectTreeItem, - LongType: AtomicObjectTreeItem, - FloatType: AtomicObjectTreeItem, - StringType: AtomicObjectTreeItem, - TupleType: SequenceTreeItem, - ListType: SequenceTreeItem, - DictType: DictTreeItem, - InstanceType: InstanceTreeItem, - ClassType: ClassTreeItem, -} - -def make_objecttreeitem(labeltext, object, setfunction=None): - t = type(object) - if dispatch.has_key(t): - c = dispatch[t] - else: - c = ObjectTreeItem - return c(labeltext, object, setfunction) - -# Test script - -def _test(): - import sys - from Tkinter import Tk - root = Tk() - root.configure(bd=0, bg="yellow") - root.focus_set() - sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1) - sc.frame.pack(expand=1, fill="both") - item = make_objecttreeitem("sys", sys) - node = TreeNode(sc.canvas, None, item) - node.update() - root.mainloop() - -if __name__ == '__main__': - _test() diff --git a/sys/lib/python/idlelib/OutputWindow.py b/sys/lib/python/idlelib/OutputWindow.py deleted file mode 100644 index 787e9b0bb..000000000 --- a/sys/lib/python/idlelib/OutputWindow.py +++ /dev/null @@ -1,157 +0,0 @@ -from Tkinter import * -from EditorWindow import EditorWindow -import re -import tkMessageBox -import IOBinding - -class OutputWindow(EditorWindow): - - """An editor window that can serve as an output file. - - Also the future base class for the Python shell window. - This class has no input facilities. - """ - - def __init__(self, *args): - EditorWindow.__init__(self, *args) - self.text.bind("<<goto-file-line>>", self.goto_file_line) - - # Customize EditorWindow - - def ispythonsource(self, filename): - # No colorization needed - return 0 - - def short_title(self): - return "Output" - - def maybesave(self): - # Override base class method -- don't ask any questions - if self.get_saved(): - return "yes" - else: - return "no" - - # Act as output file - - def write(self, s, tags=(), mark="insert"): - # Tk assumes that byte strings are Latin-1; - # we assume that they are in the locale's encoding - if isinstance(s, str): - try: - s = unicode(s, IOBinding.encoding) - except UnicodeError: - # some other encoding; let Tcl deal with it - pass - self.text.insert(mark, s, tags) - self.text.see(mark) - self.text.update() - - def writelines(self, l): - map(self.write, l) - - def flush(self): - pass - - # Our own right-button menu - - rmenu_specs = [ - ("Go to file/line", "<<goto-file-line>>"), - ] - - file_line_pats = [ - r'file "([^"]*)", line (\d+)', - r'([^\s]+)\((\d+)\)', - r'([^\s]+):\s*(\d+):', - ] - - file_line_progs = None - - def goto_file_line(self, event=None): - if self.file_line_progs is None: - l = [] - for pat in self.file_line_pats: - l.append(re.compile(pat, re.IGNORECASE)) - self.file_line_progs = l - # x, y = self.event.x, self.event.y - # self.text.mark_set("insert", "@%d,%d" % (x, y)) - line = self.text.get("insert linestart", "insert lineend") - result = self._file_line_helper(line) - if not result: - # Try the previous line. This is handy e.g. in tracebacks, - # where you tend to right-click on the displayed source line - line = self.text.get("insert -1line linestart", - "insert -1line lineend") - result = self._file_line_helper(line) - if not result: - tkMessageBox.showerror( - "No special line", - "The line you point at doesn't look like " - "a valid file name followed by a line number.", - master=self.text) - return - filename, lineno = result - edit = self.flist.open(filename) - edit.gotoline(lineno) - - def _file_line_helper(self, line): - for prog in self.file_line_progs: - m = prog.search(line) - if m: - break - else: - return None - filename, lineno = m.group(1, 2) - try: - f = open(filename, "r") - f.close() - except IOError: - return None - try: - return filename, int(lineno) - except TypeError: - return None - -# These classes are currently not used but might come in handy - -class OnDemandOutputWindow: - - tagdefs = { - # XXX Should use IdlePrefs.ColorPrefs - "stdout": {"foreground": "blue"}, - "stderr": {"foreground": "#007700"}, - } - - def __init__(self, flist): - self.flist = flist - self.owin = None - - def write(self, s, tags, mark): - if not self.owin: - self.setup() - self.owin.write(s, tags, mark) - - def setup(self): - self.owin = owin = OutputWindow(self.flist) - text = owin.text - for tag, cnf in self.tagdefs.items(): - if cnf: - text.tag_configure(tag, **cnf) - text.tag_raise('sel') - self.write = self.owin.write - -#class PseudoFile: -# -# def __init__(self, owin, tags, mark="end"): -# self.owin = owin -# self.tags = tags -# self.mark = mark - -# def write(self, s): -# self.owin.write(s, self.tags, self.mark) - -# def writelines(self, l): -# map(self.write, l) - -# def flush(self): -# pass diff --git a/sys/lib/python/idlelib/ParenMatch.py b/sys/lib/python/idlelib/ParenMatch.py deleted file mode 100644 index 250ae8b70..000000000 --- a/sys/lib/python/idlelib/ParenMatch.py +++ /dev/null @@ -1,172 +0,0 @@ -"""ParenMatch -- An IDLE extension for parenthesis matching. - -When you hit a right paren, the cursor should move briefly to the left -paren. Paren here is used generically; the matching applies to -parentheses, square brackets, and curly braces. -""" - -from HyperParser import HyperParser -from configHandler import idleConf - -_openers = {')':'(',']':'[','}':'{'} -CHECK_DELAY = 100 # miliseconds - -class ParenMatch: - """Highlight matching parentheses - - There are three supported style of paren matching, based loosely - on the Emacs options. The style is select based on the - HILITE_STYLE attribute; it can be changed used the set_style - method. - - The supported styles are: - - default -- When a right paren is typed, highlight the matching - left paren for 1/2 sec. - - expression -- When a right paren is typed, highlight the entire - expression from the left paren to the right paren. - - TODO: - - extend IDLE with configuration dialog to change options - - implement rest of Emacs highlight styles (see below) - - print mismatch warning in IDLE status window - - Note: In Emacs, there are several styles of highlight where the - matching paren is highlighted whenever the cursor is immediately - to the right of a right paren. I don't know how to do that in Tk, - so I haven't bothered. - """ - menudefs = [ - ('edit', [ - ("Show surrounding parens", "<<flash-paren>>"), - ]) - ] - STYLE = idleConf.GetOption('extensions','ParenMatch','style', - default='expression') - FLASH_DELAY = idleConf.GetOption('extensions','ParenMatch','flash-delay', - type='int',default=500) - HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(),'hilite') - BELL = idleConf.GetOption('extensions','ParenMatch','bell', - type='bool',default=1) - - RESTORE_VIRTUAL_EVENT_NAME = "<<parenmatch-check-restore>>" - # We want the restore event be called before the usual return and - # backspace events. - RESTORE_SEQUENCES = ("<KeyPress>", "<ButtonPress>", - "<Key-Return>", "<Key-BackSpace>") - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - # Bind the check-restore event to the function restore_event, - # so that we can then use activate_restore (which calls event_add) - # and deactivate_restore (which calls event_delete). - editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME, - self.restore_event) - self.counter = 0 - self.is_restore_active = 0 - self.set_style(self.STYLE) - - def activate_restore(self): - if not self.is_restore_active: - for seq in self.RESTORE_SEQUENCES: - self.text.event_add(self.RESTORE_VIRTUAL_EVENT_NAME, seq) - self.is_restore_active = True - - def deactivate_restore(self): - if self.is_restore_active: - for seq in self.RESTORE_SEQUENCES: - self.text.event_delete(self.RESTORE_VIRTUAL_EVENT_NAME, seq) - self.is_restore_active = False - - def set_style(self, style): - self.STYLE = style - if style == "default": - self.create_tag = self.create_tag_default - self.set_timeout = self.set_timeout_last - elif style == "expression": - self.create_tag = self.create_tag_expression - self.set_timeout = self.set_timeout_none - - def flash_paren_event(self, event): - indices = HyperParser(self.editwin, "insert").get_surrounding_brackets() - if indices is None: - self.warn_mismatched() - return - self.activate_restore() - self.create_tag(indices) - self.set_timeout_last() - - def paren_closed_event(self, event): - # If it was a shortcut and not really a closing paren, quit. - closer = self.text.get("insert-1c") - if closer not in _openers: - return - hp = HyperParser(self.editwin, "insert-1c") - if not hp.is_in_code(): - return - indices = hp.get_surrounding_brackets(_openers[closer], True) - if indices is None: - self.warn_mismatched() - return - self.activate_restore() - self.create_tag(indices) - self.set_timeout() - - def restore_event(self, event=None): - self.text.tag_delete("paren") - self.deactivate_restore() - self.counter += 1 # disable the last timer, if there is one. - - def handle_restore_timer(self, timer_count): - if timer_count == self.counter: - self.restore_event() - - def warn_mismatched(self): - if self.BELL: - self.text.bell() - - # any one of the create_tag_XXX methods can be used depending on - # the style - - def create_tag_default(self, indices): - """Highlight the single paren that matches""" - self.text.tag_add("paren", indices[0]) - self.text.tag_config("paren", self.HILITE_CONFIG) - - def create_tag_expression(self, indices): - """Highlight the entire expression""" - if self.text.get(indices[1]) in (')', ']', '}'): - rightindex = indices[1]+"+1c" - else: - rightindex = indices[1] - self.text.tag_add("paren", indices[0], rightindex) - self.text.tag_config("paren", self.HILITE_CONFIG) - - # any one of the set_timeout_XXX methods can be used depending on - # the style - - def set_timeout_none(self): - """Highlight will remain until user input turns it off - or the insert has moved""" - # After CHECK_DELAY, call a function which disables the "paren" tag - # if the event is for the most recent timer and the insert has changed, - # or schedules another call for itself. - self.counter += 1 - def callme(callme, self=self, c=self.counter, - index=self.text.index("insert")): - if index != self.text.index("insert"): - self.handle_restore_timer(c) - else: - self.editwin.text_frame.after(CHECK_DELAY, callme, callme) - self.editwin.text_frame.after(CHECK_DELAY, callme, callme) - - def set_timeout_last(self): - """The last highlight created will be removed after .5 sec""" - # associate a counter with an event; only disable the "paren" - # tag if the event is for the most recent timer. - self.counter += 1 - self.editwin.text_frame.after(self.FLASH_DELAY, - lambda self=self, c=self.counter: \ - self.handle_restore_timer(c)) diff --git a/sys/lib/python/idlelib/PathBrowser.py b/sys/lib/python/idlelib/PathBrowser.py deleted file mode 100644 index 86cd2707d..000000000 --- a/sys/lib/python/idlelib/PathBrowser.py +++ /dev/null @@ -1,95 +0,0 @@ -import os -import sys -import imp - -from TreeWidget import TreeItem -from ClassBrowser import ClassBrowser, ModuleBrowserTreeItem - -class PathBrowser(ClassBrowser): - - def __init__(self, flist): - self.init(flist) - - def settitle(self): - self.top.wm_title("Path Browser") - self.top.wm_iconname("Path Browser") - - def rootnode(self): - return PathBrowserTreeItem() - -class PathBrowserTreeItem(TreeItem): - - def GetText(self): - return "sys.path" - - def GetSubList(self): - sublist = [] - for dir in sys.path: - item = DirBrowserTreeItem(dir) - sublist.append(item) - return sublist - -class DirBrowserTreeItem(TreeItem): - - def __init__(self, dir, packages=[]): - self.dir = dir - self.packages = packages - - def GetText(self): - if not self.packages: - return self.dir - else: - return self.packages[-1] + ": package" - - def GetSubList(self): - try: - names = os.listdir(self.dir or os.curdir) - except os.error: - return [] - packages = [] - for name in names: - file = os.path.join(self.dir, name) - if self.ispackagedir(file): - nn = os.path.normcase(name) - packages.append((nn, name, file)) - packages.sort() - sublist = [] - for nn, name, file in packages: - item = DirBrowserTreeItem(file, self.packages + [name]) - sublist.append(item) - for nn, name in self.listmodules(names): - item = ModuleBrowserTreeItem(os.path.join(self.dir, name)) - sublist.append(item) - return sublist - - def ispackagedir(self, file): - if not os.path.isdir(file): - return 0 - init = os.path.join(file, "__init__.py") - return os.path.exists(init) - - def listmodules(self, allnames): - modules = {} - suffixes = imp.get_suffixes() - sorted = [] - for suff, mode, flag in suffixes: - i = -len(suff) - for name in allnames[:]: - normed_name = os.path.normcase(name) - if normed_name[i:] == suff: - mod_name = name[:i] - if not modules.has_key(mod_name): - modules[mod_name] = None - sorted.append((normed_name, name)) - allnames.remove(name) - sorted.sort() - return sorted - -def main(): - import PyShell - PathBrowser(PyShell.flist) - if sys.stdin is sys.__stdin__: - mainloop() - -if __name__ == "__main__": - main() diff --git a/sys/lib/python/idlelib/Percolator.py b/sys/lib/python/idlelib/Percolator.py deleted file mode 100644 index ebbcba9e6..000000000 --- a/sys/lib/python/idlelib/Percolator.py +++ /dev/null @@ -1,85 +0,0 @@ -from WidgetRedirector import WidgetRedirector -from Delegator import Delegator - -class Percolator: - - def __init__(self, text): - # XXX would be nice to inherit from Delegator - self.text = text - self.redir = WidgetRedirector(text) - self.top = self.bottom = Delegator(text) - self.bottom.insert = self.redir.register("insert", self.insert) - self.bottom.delete = self.redir.register("delete", self.delete) - self.filters = [] - - def close(self): - while self.top is not self.bottom: - self.removefilter(self.top) - self.top = None - self.bottom.setdelegate(None); self.bottom = None - self.redir.close(); self.redir = None - self.text = None - - def insert(self, index, chars, tags=None): - # Could go away if inheriting from Delegator - self.top.insert(index, chars, tags) - - def delete(self, index1, index2=None): - # Could go away if inheriting from Delegator - self.top.delete(index1, index2) - - def insertfilter(self, filter): - # Perhaps rename to pushfilter()? - assert isinstance(filter, Delegator) - assert filter.delegate is None - filter.setdelegate(self.top) - self.top = filter - - def removefilter(self, filter): - # XXX Perhaps should only support popfilter()? - assert isinstance(filter, Delegator) - assert filter.delegate is not None - f = self.top - if f is filter: - self.top = filter.delegate - filter.setdelegate(None) - else: - while f.delegate is not filter: - assert f is not self.bottom - f.resetcache() - f = f.delegate - f.setdelegate(filter.delegate) - filter.setdelegate(None) - - -def main(): - class Tracer(Delegator): - def __init__(self, name): - self.name = name - Delegator.__init__(self, None) - def insert(self, *args): - print self.name, ": insert", args - self.delegate.insert(*args) - def delete(self, *args): - print self.name, ": delete", args - self.delegate.delete(*args) - root = Tk() - root.wm_protocol("WM_DELETE_WINDOW", root.quit) - text = Text() - text.pack() - text.focus_set() - p = Percolator(text) - t1 = Tracer("t1") - t2 = Tracer("t2") - p.insertfilter(t1) - p.insertfilter(t2) - root.mainloop() - p.removefilter(t2) - root.mainloop() - p.insertfilter(t2) - p.removefilter(t1) - root.mainloop() - -if __name__ == "__main__": - from Tkinter import * - main() diff --git a/sys/lib/python/idlelib/PyParse.py b/sys/lib/python/idlelib/PyParse.py deleted file mode 100644 index 1a9db6743..000000000 --- a/sys/lib/python/idlelib/PyParse.py +++ /dev/null @@ -1,594 +0,0 @@ -import re -import sys - -# Reason last stmt is continued (or C_NONE if it's not). -(C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, - C_STRING_NEXT_LINES, C_BRACKET) = range(5) - -if 0: # for throwaway debugging output - def dump(*stuff): - sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") - -# Find what looks like the start of a popular stmt. - -_synchre = re.compile(r""" - ^ - [ \t]* - (?: while - | else - | def - | return - | assert - | break - | class - | continue - | elif - | try - | except - | raise - | import - | yield - ) - \b -""", re.VERBOSE | re.MULTILINE).search - -# Match blank line or non-indenting comment line. - -_junkre = re.compile(r""" - [ \t]* - (?: \# \S .* )? - \n -""", re.VERBOSE).match - -# Match any flavor of string; the terminating quote is optional -# so that we're robust in the face of incomplete program text. - -_match_stringre = re.compile(r""" - \""" [^"\\]* (?: - (?: \\. | "(?!"") ) - [^"\\]* - )* - (?: \""" )? - -| " [^"\\\n]* (?: \\. [^"\\\n]* )* "? - -| ''' [^'\\]* (?: - (?: \\. | '(?!'') ) - [^'\\]* - )* - (?: ''' )? - -| ' [^'\\\n]* (?: \\. [^'\\\n]* )* '? -""", re.VERBOSE | re.DOTALL).match - -# Match a line that starts with something interesting; -# used to find the first item of a bracket structure. - -_itemre = re.compile(r""" - [ \t]* - [^\s#\\] # if we match, m.end()-1 is the interesting char -""", re.VERBOSE).match - -# Match start of stmts that should be followed by a dedent. - -_closere = re.compile(r""" - \s* - (?: return - | break - | continue - | raise - | pass - ) - \b -""", re.VERBOSE).match - -# Chew up non-special chars as quickly as possible. If match is -# successful, m.end() less 1 is the index of the last boring char -# matched. If match is unsuccessful, the string starts with an -# interesting char. - -_chew_ordinaryre = re.compile(r""" - [^[\](){}#'"\\]+ -""", re.VERBOSE).match - -# Build translation table to map uninteresting chars to "x", open -# brackets to "(", and close brackets to ")". - -_tran = ['x'] * 256 -for ch in "({[": - _tran[ord(ch)] = '(' -for ch in ")}]": - _tran[ord(ch)] = ')' -for ch in "\"'\\\n#": - _tran[ord(ch)] = ch -_tran = ''.join(_tran) -del ch - -try: - UnicodeType = type(unicode("")) -except NameError: - UnicodeType = None - -class Parser: - - def __init__(self, indentwidth, tabwidth): - self.indentwidth = indentwidth - self.tabwidth = tabwidth - - def set_str(self, str): - assert len(str) == 0 or str[-1] == '\n' - if type(str) is UnicodeType: - # The parse functions have no idea what to do with Unicode, so - # replace all Unicode characters with "x". This is "safe" - # so long as the only characters germane to parsing the structure - # of Python are 7-bit ASCII. It's *necessary* because Unicode - # strings don't have a .translate() method that supports - # deletechars. - uniphooey = str - str = [] - push = str.append - for raw in map(ord, uniphooey): - push(raw < 127 and chr(raw) or "x") - str = "".join(str) - self.str = str - self.study_level = 0 - - # Return index of a good place to begin parsing, as close to the - # end of the string as possible. This will be the start of some - # popular stmt like "if" or "def". Return None if none found: - # the caller should pass more prior context then, if possible, or - # if not (the entire program text up until the point of interest - # has already been tried) pass 0 to set_lo. - # - # This will be reliable iff given a reliable is_char_in_string - # function, meaning that when it says "no", it's absolutely - # guaranteed that the char is not in a string. - - def find_good_parse_start(self, is_char_in_string=None, - _synchre=_synchre): - str, pos = self.str, None - - if not is_char_in_string: - # no clue -- make the caller pass everything - return None - - # Peek back from the end for a good place to start, - # but don't try too often; pos will be left None, or - # bumped to a legitimate synch point. - limit = len(str) - for tries in range(5): - i = str.rfind(":\n", 0, limit) - if i < 0: - break - i = str.rfind('\n', 0, i) + 1 # start of colon line - m = _synchre(str, i, limit) - if m and not is_char_in_string(m.start()): - pos = m.start() - break - limit = i - if pos is None: - # Nothing looks like a block-opener, or stuff does - # but is_char_in_string keeps returning true; most likely - # we're in or near a giant string, the colorizer hasn't - # caught up enough to be helpful, or there simply *aren't* - # any interesting stmts. In any of these cases we're - # going to have to parse the whole thing to be sure, so - # give it one last try from the start, but stop wasting - # time here regardless of the outcome. - m = _synchre(str) - if m and not is_char_in_string(m.start()): - pos = m.start() - return pos - - # Peeking back worked; look forward until _synchre no longer - # matches. - i = pos + 1 - while 1: - m = _synchre(str, i) - if m: - s, i = m.span() - if not is_char_in_string(s): - pos = s - else: - break - return pos - - # Throw away the start of the string. Intended to be called with - # find_good_parse_start's result. - - def set_lo(self, lo): - assert lo == 0 or self.str[lo-1] == '\n' - if lo > 0: - self.str = self.str[lo:] - - # As quickly as humanly possible <wink>, find the line numbers (0- - # based) of the non-continuation lines. - # Creates self.{goodlines, continuation}. - - def _study1(self): - if self.study_level >= 1: - return - self.study_level = 1 - - # Map all uninteresting characters to "x", all open brackets - # to "(", all close brackets to ")", then collapse runs of - # uninteresting characters. This can cut the number of chars - # by a factor of 10-40, and so greatly speed the following loop. - str = self.str - str = str.translate(_tran) - str = str.replace('xxxxxxxx', 'x') - str = str.replace('xxxx', 'x') - str = str.replace('xx', 'x') - str = str.replace('xx', 'x') - str = str.replace('\nx', '\n') - # note that replacing x\n with \n would be incorrect, because - # x may be preceded by a backslash - - # March over the squashed version of the program, accumulating - # the line numbers of non-continued stmts, and determining - # whether & why the last stmt is a continuation. - continuation = C_NONE - level = lno = 0 # level is nesting level; lno is line number - self.goodlines = goodlines = [0] - push_good = goodlines.append - i, n = 0, len(str) - while i < n: - ch = str[i] - i = i+1 - - # cases are checked in decreasing order of frequency - if ch == 'x': - continue - - if ch == '\n': - lno = lno + 1 - if level == 0: - push_good(lno) - # else we're in an unclosed bracket structure - continue - - if ch == '(': - level = level + 1 - continue - - if ch == ')': - if level: - level = level - 1 - # else the program is invalid, but we can't complain - continue - - if ch == '"' or ch == "'": - # consume the string - quote = ch - if str[i-1:i+2] == quote * 3: - quote = quote * 3 - firstlno = lno - w = len(quote) - 1 - i = i+w - while i < n: - ch = str[i] - i = i+1 - - if ch == 'x': - continue - - if str[i-1:i+w] == quote: - i = i+w - break - - if ch == '\n': - lno = lno + 1 - if w == 0: - # unterminated single-quoted string - if level == 0: - push_good(lno) - break - continue - - if ch == '\\': - assert i < n - if str[i] == '\n': - lno = lno + 1 - i = i+1 - continue - - # else comment char or paren inside string - - else: - # didn't break out of the loop, so we're still - # inside a string - if (lno - 1) == firstlno: - # before the previous \n in str, we were in the first - # line of the string - continuation = C_STRING_FIRST_LINE - else: - continuation = C_STRING_NEXT_LINES - continue # with outer loop - - if ch == '#': - # consume the comment - i = str.find('\n', i) - assert i >= 0 - continue - - assert ch == '\\' - assert i < n - if str[i] == '\n': - lno = lno + 1 - if i+1 == n: - continuation = C_BACKSLASH - i = i+1 - - # The last stmt may be continued for all 3 reasons. - # String continuation takes precedence over bracket - # continuation, which beats backslash continuation. - if (continuation != C_STRING_FIRST_LINE - and continuation != C_STRING_NEXT_LINES and level > 0): - continuation = C_BRACKET - self.continuation = continuation - - # Push the final line number as a sentinel value, regardless of - # whether it's continued. - assert (continuation == C_NONE) == (goodlines[-1] == lno) - if goodlines[-1] != lno: - push_good(lno) - - def get_continuation_type(self): - self._study1() - return self.continuation - - # study1 was sufficient to determine the continuation status, - # but doing more requires looking at every character. study2 - # does this for the last interesting statement in the block. - # Creates: - # self.stmt_start, stmt_end - # slice indices of last interesting stmt - # self.stmt_bracketing - # the bracketing structure of the last interesting stmt; - # for example, for the statement "say(boo) or die", stmt_bracketing - # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are - # treated as brackets, for the matter. - # self.lastch - # last non-whitespace character before optional trailing - # comment - # self.lastopenbracketpos - # if continuation is C_BRACKET, index of last open bracket - - def _study2(self): - if self.study_level >= 2: - return - self._study1() - self.study_level = 2 - - # Set p and q to slice indices of last interesting stmt. - str, goodlines = self.str, self.goodlines - i = len(goodlines) - 1 - p = len(str) # index of newest line - while i: - assert p - # p is the index of the stmt at line number goodlines[i]. - # Move p back to the stmt at line number goodlines[i-1]. - q = p - for nothing in range(goodlines[i-1], goodlines[i]): - # tricky: sets p to 0 if no preceding newline - p = str.rfind('\n', 0, p-1) + 1 - # The stmt str[p:q] isn't a continuation, but may be blank - # or a non-indenting comment line. - if _junkre(str, p): - i = i-1 - else: - break - if i == 0: - # nothing but junk! - assert p == 0 - q = p - self.stmt_start, self.stmt_end = p, q - - # Analyze this stmt, to find the last open bracket (if any) - # and last interesting character (if any). - lastch = "" - stack = [] # stack of open bracket indices - push_stack = stack.append - bracketing = [(p, 0)] - while p < q: - # suck up all except ()[]{}'"#\\ - m = _chew_ordinaryre(str, p, q) - if m: - # we skipped at least one boring char - newp = m.end() - # back up over totally boring whitespace - i = newp - 1 # index of last boring char - while i >= p and str[i] in " \t\n": - i = i-1 - if i >= p: - lastch = str[i] - p = newp - if p >= q: - break - - ch = str[p] - - if ch in "([{": - push_stack(p) - bracketing.append((p, len(stack))) - lastch = ch - p = p+1 - continue - - if ch in ")]}": - if stack: - del stack[-1] - lastch = ch - p = p+1 - bracketing.append((p, len(stack))) - continue - - if ch == '"' or ch == "'": - # consume string - # Note that study1 did this with a Python loop, but - # we use a regexp here; the reason is speed in both - # cases; the string may be huge, but study1 pre-squashed - # strings to a couple of characters per line. study1 - # also needed to keep track of newlines, and we don't - # have to. - bracketing.append((p, len(stack)+1)) - lastch = ch - p = _match_stringre(str, p, q).end() - bracketing.append((p, len(stack))) - continue - - if ch == '#': - # consume comment and trailing newline - bracketing.append((p, len(stack)+1)) - p = str.find('\n', p, q) + 1 - assert p > 0 - bracketing.append((p, len(stack))) - continue - - assert ch == '\\' - p = p+1 # beyond backslash - assert p < q - if str[p] != '\n': - # the program is invalid, but can't complain - lastch = ch + str[p] - p = p+1 # beyond escaped char - - # end while p < q: - - self.lastch = lastch - if stack: - self.lastopenbracketpos = stack[-1] - self.stmt_bracketing = tuple(bracketing) - - # Assuming continuation is C_BRACKET, return the number - # of spaces the next line should be indented. - - def compute_bracket_indent(self): - self._study2() - assert self.continuation == C_BRACKET - j = self.lastopenbracketpos - str = self.str - n = len(str) - origi = i = str.rfind('\n', 0, j) + 1 - j = j+1 # one beyond open bracket - # find first list item; set i to start of its line - while j < n: - m = _itemre(str, j) - if m: - j = m.end() - 1 # index of first interesting char - extra = 0 - break - else: - # this line is junk; advance to next line - i = j = str.find('\n', j) + 1 - else: - # nothing interesting follows the bracket; - # reproduce the bracket line's indentation + a level - j = i = origi - while str[j] in " \t": - j = j+1 - extra = self.indentwidth - return len(str[i:j].expandtabs(self.tabwidth)) + extra - - # Return number of physical lines in last stmt (whether or not - # it's an interesting stmt! this is intended to be called when - # continuation is C_BACKSLASH). - - def get_num_lines_in_stmt(self): - self._study1() - goodlines = self.goodlines - return goodlines[-1] - goodlines[-2] - - # Assuming continuation is C_BACKSLASH, return the number of spaces - # the next line should be indented. Also assuming the new line is - # the first one following the initial line of the stmt. - - def compute_backslash_indent(self): - self._study2() - assert self.continuation == C_BACKSLASH - str = self.str - i = self.stmt_start - while str[i] in " \t": - i = i+1 - startpos = i - - # See whether the initial line starts an assignment stmt; i.e., - # look for an = operator - endpos = str.find('\n', startpos) + 1 - found = level = 0 - while i < endpos: - ch = str[i] - if ch in "([{": - level = level + 1 - i = i+1 - elif ch in ")]}": - if level: - level = level - 1 - i = i+1 - elif ch == '"' or ch == "'": - i = _match_stringre(str, i, endpos).end() - elif ch == '#': - break - elif level == 0 and ch == '=' and \ - (i == 0 or str[i-1] not in "=<>!") and \ - str[i+1] != '=': - found = 1 - break - else: - i = i+1 - - if found: - # found a legit =, but it may be the last interesting - # thing on the line - i = i+1 # move beyond the = - found = re.match(r"\s*\\", str[i:endpos]) is None - - if not found: - # oh well ... settle for moving beyond the first chunk - # of non-whitespace chars - i = startpos - while str[i] not in " \t\n": - i = i+1 - - return len(str[self.stmt_start:i].expandtabs(\ - self.tabwidth)) + 1 - - # Return the leading whitespace on the initial line of the last - # interesting stmt. - - def get_base_indent_string(self): - self._study2() - i, n = self.stmt_start, self.stmt_end - j = i - str = self.str - while j < n and str[j] in " \t": - j = j + 1 - return str[i:j] - - # Did the last interesting stmt open a block? - - def is_block_opener(self): - self._study2() - return self.lastch == ':' - - # Did the last interesting stmt close a block? - - def is_block_closer(self): - self._study2() - return _closere(self.str, self.stmt_start) is not None - - # index of last open bracket ({[, or None if none - lastopenbracketpos = None - - def get_last_open_bracket_pos(self): - self._study2() - return self.lastopenbracketpos - - # the structure of the bracketing of the last interesting statement, - # in the format defined in _study2, or None if the text didn't contain - # anything - stmt_bracketing = None - - def get_last_stmt_bracketing(self): - self._study2() - return self.stmt_bracketing diff --git a/sys/lib/python/idlelib/PyShell.py b/sys/lib/python/idlelib/PyShell.py deleted file mode 100644 index 1bdd0a64c..000000000 --- a/sys/lib/python/idlelib/PyShell.py +++ /dev/null @@ -1,1441 +0,0 @@ -#! /usr/bin/env python - -import os -import os.path -import sys -import string -import getopt -import re -import socket -import time -import threading -import traceback -import types -import macosxSupport - -import linecache -from code import InteractiveInterpreter - -try: - from Tkinter import * -except ImportError: - print>>sys.__stderr__, "** IDLE can't import Tkinter. " \ - "Your Python may not be configured for Tk. **" - sys.exit(1) -import tkMessageBox - -from EditorWindow import EditorWindow, fixwordbreaks -from FileList import FileList -from ColorDelegator import ColorDelegator -from UndoDelegator import UndoDelegator -from OutputWindow import OutputWindow -from configHandler import idleConf -import idlever - -import rpc -import Debugger -import RemoteDebugger - -IDENTCHARS = string.ascii_letters + string.digits + "_" -LOCALHOST = '127.0.0.1' - -try: - from signal import SIGTERM -except ImportError: - SIGTERM = 15 - -# Override warnings module to write to warning_stream. Initialize to send IDLE -# internal warnings to the console. ScriptBinding.check_syntax() will -# temporarily redirect the stream to the shell window to display warnings when -# checking user's code. -global warning_stream -warning_stream = sys.__stderr__ -try: - import warnings -except ImportError: - pass -else: - def idle_showwarning(message, category, filename, lineno): - file = warning_stream - try: - file.write(warnings.formatwarning(message, category, filename, lineno)) - except IOError: - pass ## file (probably __stderr__) is invalid, warning dropped. - warnings.showwarning = idle_showwarning - def idle_formatwarning(message, category, filename, lineno): - """Format warnings the IDLE way""" - s = "\nWarning (from warnings module):\n" - s += ' File \"%s\", line %s\n' % (filename, lineno) - line = linecache.getline(filename, lineno).strip() - if line: - s += " %s\n" % line - s += "%s: %s\n>>> " % (category.__name__, message) - return s - warnings.formatwarning = idle_formatwarning - -def extended_linecache_checkcache(filename=None, - orig_checkcache=linecache.checkcache): - """Extend linecache.checkcache to preserve the <pyshell#...> entries - - Rather than repeating the linecache code, patch it to save the - <pyshell#...> entries, call the original linecache.checkcache() - (which destroys them), and then restore the saved entries. - - orig_checkcache is bound at definition time to the original - method, allowing it to be patched. - - """ - cache = linecache.cache - save = {} - for filename in cache.keys(): - if filename[:1] + filename[-1:] == '<>': - save[filename] = cache[filename] - orig_checkcache() - cache.update(save) - -# Patch linecache.checkcache(): -linecache.checkcache = extended_linecache_checkcache - - -class PyShellEditorWindow(EditorWindow): - "Regular text edit window in IDLE, supports breakpoints" - - def __init__(self, *args): - self.breakpoints = [] - EditorWindow.__init__(self, *args) - self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here) - self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here) - self.text.bind("<<open-python-shell>>", self.flist.open_shell) - - self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(), - 'breakpoints.lst') - # whenever a file is changed, restore breakpoints - if self.io.filename: self.restore_file_breaks() - def filename_changed_hook(old_hook=self.io.filename_change_hook, - self=self): - self.restore_file_breaks() - old_hook() - self.io.set_filename_change_hook(filename_changed_hook) - - rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"), - ("Clear Breakpoint", "<<clear-breakpoint-here>>")] - - def set_breakpoint(self, lineno): - text = self.text - filename = self.io.filename - text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) - try: - i = self.breakpoints.index(lineno) - except ValueError: # only add if missing, i.e. do once - self.breakpoints.append(lineno) - try: # update the subprocess debugger - debug = self.flist.pyshell.interp.debugger - debug.set_breakpoint_here(filename, lineno) - except: # but debugger may not be active right now.... - pass - - def set_breakpoint_here(self, event=None): - text = self.text - filename = self.io.filename - if not filename: - text.bell() - return - lineno = int(float(text.index("insert"))) - self.set_breakpoint(lineno) - - def clear_breakpoint_here(self, event=None): - text = self.text - filename = self.io.filename - if not filename: - text.bell() - return - lineno = int(float(text.index("insert"))) - try: - self.breakpoints.remove(lineno) - except: - pass - text.tag_remove("BREAK", "insert linestart",\ - "insert lineend +1char") - try: - debug = self.flist.pyshell.interp.debugger - debug.clear_breakpoint_here(filename, lineno) - except: - pass - - def clear_file_breaks(self): - if self.breakpoints: - text = self.text - filename = self.io.filename - if not filename: - text.bell() - return - self.breakpoints = [] - text.tag_remove("BREAK", "1.0", END) - try: - debug = self.flist.pyshell.interp.debugger - debug.clear_file_breaks(filename) - except: - pass - - def store_file_breaks(self): - "Save breakpoints when file is saved" - # XXX 13 Dec 2002 KBK Currently the file must be saved before it can - # be run. The breaks are saved at that time. If we introduce - # a temporary file save feature the save breaks functionality - # needs to be re-verified, since the breaks at the time the - # temp file is created may differ from the breaks at the last - # permanent save of the file. Currently, a break introduced - # after a save will be effective, but not persistent. - # This is necessary to keep the saved breaks synched with the - # saved file. - # - # Breakpoints are set as tagged ranges in the text. Certain - # kinds of edits cause these ranges to be deleted: Inserting - # or deleting a line just before a breakpoint, and certain - # deletions prior to a breakpoint. These issues need to be - # investigated and understood. It's not clear if they are - # Tk issues or IDLE issues, or whether they can actually - # be fixed. Since a modified file has to be saved before it is - # run, and since self.breakpoints (from which the subprocess - # debugger is loaded) is updated during the save, the visible - # breaks stay synched with the subprocess even if one of these - # unexpected breakpoint deletions occurs. - breaks = self.breakpoints - filename = self.io.filename - try: - lines = open(self.breakpointPath,"r").readlines() - except IOError: - lines = [] - new_file = open(self.breakpointPath,"w") - for line in lines: - if not line.startswith(filename + '='): - new_file.write(line) - self.update_breakpoints() - breaks = self.breakpoints - if breaks: - new_file.write(filename + '=' + str(breaks) + '\n') - new_file.close() - - def restore_file_breaks(self): - self.text.update() # this enables setting "BREAK" tags to be visible - filename = self.io.filename - if filename is None: - return - if os.path.isfile(self.breakpointPath): - lines = open(self.breakpointPath,"r").readlines() - for line in lines: - if line.startswith(filename + '='): - breakpoint_linenumbers = eval(line[len(filename)+1:]) - for breakpoint_linenumber in breakpoint_linenumbers: - self.set_breakpoint(breakpoint_linenumber) - - def update_breakpoints(self): - "Retrieves all the breakpoints in the current window" - text = self.text - ranges = text.tag_ranges("BREAK") - linenumber_list = self.ranges_to_linenumbers(ranges) - self.breakpoints = linenumber_list - - def ranges_to_linenumbers(self, ranges): - lines = [] - for index in range(0, len(ranges), 2): - lineno = int(float(ranges[index])) - end = int(float(ranges[index+1])) - while lineno < end: - lines.append(lineno) - lineno += 1 - return lines - -# XXX 13 Dec 2002 KBK Not used currently -# def saved_change_hook(self): -# "Extend base method - clear breaks if module is modified" -# if not self.get_saved(): -# self.clear_file_breaks() -# EditorWindow.saved_change_hook(self) - - def _close(self): - "Extend base method - clear breaks when module is closed" - self.clear_file_breaks() - EditorWindow._close(self) - - -class PyShellFileList(FileList): - "Extend base class: IDLE supports a shell and breakpoints" - - # override FileList's class variable, instances return PyShellEditorWindow - # instead of EditorWindow when new edit windows are created. - EditorWindow = PyShellEditorWindow - - pyshell = None - - def open_shell(self, event=None): - if self.pyshell: - self.pyshell.top.wakeup() - else: - self.pyshell = PyShell(self) - if self.pyshell: - if not self.pyshell.begin(): - return None - return self.pyshell - - -class ModifiedColorDelegator(ColorDelegator): - "Extend base class: colorizer for the shell window itself" - - def __init__(self): - ColorDelegator.__init__(self) - self.LoadTagDefs() - - def recolorize_main(self): - self.tag_remove("TODO", "1.0", "iomark") - self.tag_add("SYNC", "1.0", "iomark") - ColorDelegator.recolorize_main(self) - - def LoadTagDefs(self): - ColorDelegator.LoadTagDefs(self) - theme = idleConf.GetOption('main','Theme','name') - self.tagdefs.update({ - "stdin": {'background':None,'foreground':None}, - "stdout": idleConf.GetHighlight(theme, "stdout"), - "stderr": idleConf.GetHighlight(theme, "stderr"), - "console": idleConf.GetHighlight(theme, "console"), - None: idleConf.GetHighlight(theme, "normal"), - }) - -class ModifiedUndoDelegator(UndoDelegator): - "Extend base class: forbid insert/delete before the I/O mark" - - def insert(self, index, chars, tags=None): - try: - if self.delegate.compare(index, "<", "iomark"): - self.delegate.bell() - return - except TclError: - pass - UndoDelegator.insert(self, index, chars, tags) - - def delete(self, index1, index2=None): - try: - if self.delegate.compare(index1, "<", "iomark"): - self.delegate.bell() - return - except TclError: - pass - UndoDelegator.delete(self, index1, index2) - - -class MyRPCClient(rpc.RPCClient): - - def handle_EOF(self): - "Override the base class - just re-raise EOFError" - raise EOFError - - -class ModifiedInterpreter(InteractiveInterpreter): - - def __init__(self, tkconsole): - self.tkconsole = tkconsole - locals = sys.modules['__main__'].__dict__ - InteractiveInterpreter.__init__(self, locals=locals) - self.save_warnings_filters = None - self.restarting = False - self.subprocess_arglist = self.build_subprocess_arglist() - - port = 8833 - rpcclt = None - rpcpid = None - - def spawn_subprocess(self): - args = self.subprocess_arglist - self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) - - def build_subprocess_arglist(self): - w = ['-W' + s for s in sys.warnoptions] - if 1/2 > 0: # account for new division - w.append('-Qnew') - # Maybe IDLE is installed and is being accessed via sys.path, - # or maybe it's not installed and the idle.py script is being - # run from the IDLE source directory. - del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', - default=False, type='bool') - if __name__ == 'idlelib.PyShell': - command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,) - else: - command = "__import__('run').main(%r)" % (del_exitf,) - if sys.platform[:3] == 'win' and ' ' in sys.executable: - # handle embedded space in path by quoting the argument - decorated_exec = '"%s"' % sys.executable - else: - decorated_exec = sys.executable - return [decorated_exec] + w + ["-c", command, str(self.port)] - - def start_subprocess(self): - # spawning first avoids passing a listening socket to the subprocess - self.spawn_subprocess() - #time.sleep(20) # test to simulate GUI not accepting connection - addr = (LOCALHOST, self.port) - # Idle starts listening for connection on localhost - for i in range(3): - time.sleep(i) - try: - self.rpcclt = MyRPCClient(addr) - break - except socket.error, err: - pass - else: - self.display_port_binding_error() - return None - # Accept the connection from the Python execution server - self.rpcclt.listening_sock.settimeout(10) - try: - self.rpcclt.accept() - except socket.timeout, err: - self.display_no_subprocess_error() - return None - self.rpcclt.register("stdin", self.tkconsole) - self.rpcclt.register("stdout", self.tkconsole.stdout) - self.rpcclt.register("stderr", self.tkconsole.stderr) - self.rpcclt.register("flist", self.tkconsole.flist) - self.rpcclt.register("linecache", linecache) - self.rpcclt.register("interp", self) - self.transfer_path() - self.poll_subprocess() - return self.rpcclt - - def restart_subprocess(self): - if self.restarting: - return self.rpcclt - self.restarting = True - # close only the subprocess debugger - debug = self.getdebugger() - if debug: - try: - # Only close subprocess debugger, don't unregister gui_adap! - RemoteDebugger.close_subprocess_debugger(self.rpcclt) - except: - pass - # Kill subprocess, spawn a new one, accept connection. - self.rpcclt.close() - self.unix_terminate() - console = self.tkconsole - was_executing = console.executing - console.executing = False - self.spawn_subprocess() - try: - self.rpcclt.accept() - except socket.timeout, err: - self.display_no_subprocess_error() - return None - self.transfer_path() - # annotate restart in shell window and mark it - console.text.delete("iomark", "end-1c") - if was_executing: - console.write('\n') - console.showprompt() - halfbar = ((int(console.width) - 16) // 2) * '=' - console.write(halfbar + ' RESTART ' + halfbar) - console.text.mark_set("restart", "end-1c") - console.text.mark_gravity("restart", "left") - console.showprompt() - # restart subprocess debugger - if debug: - # Restarted debugger connects to current instance of debug GUI - gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) - # reload remote debugger breakpoints for all PyShellEditWindows - debug.load_breakpoints() - self.restarting = False - return self.rpcclt - - def __request_interrupt(self): - self.rpcclt.remotecall("exec", "interrupt_the_server", (), {}) - - def interrupt_subprocess(self): - threading.Thread(target=self.__request_interrupt).start() - - def kill_subprocess(self): - try: - self.rpcclt.close() - except AttributeError: # no socket - pass - self.unix_terminate() - self.tkconsole.executing = False - self.rpcclt = None - - def unix_terminate(self): - "UNIX: make sure subprocess is terminated and collect status" - if hasattr(os, 'kill'): - try: - os.kill(self.rpcpid, SIGTERM) - except OSError: - # process already terminated: - return - else: - try: - os.waitpid(self.rpcpid, 0) - except OSError: - return - - def transfer_path(self): - self.runcommand("""if 1: - import sys as _sys - _sys.path = %r - del _sys - \n""" % (sys.path,)) - - active_seq = None - - def poll_subprocess(self): - clt = self.rpcclt - if clt is None: - return - try: - response = clt.pollresponse(self.active_seq, wait=0.05) - except (EOFError, IOError, KeyboardInterrupt): - # lost connection or subprocess terminated itself, restart - # [the KBI is from rpc.SocketIO.handle_EOF()] - if self.tkconsole.closing: - return - response = None - self.restart_subprocess() - if response: - self.tkconsole.resetoutput() - self.active_seq = None - how, what = response - console = self.tkconsole.console - if how == "OK": - if what is not None: - print >>console, repr(what) - elif how == "EXCEPTION": - if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): - self.remote_stack_viewer() - elif how == "ERROR": - errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n" - print >>sys.__stderr__, errmsg, what - print >>console, errmsg, what - # we received a response to the currently active seq number: - try: - self.tkconsole.endexecuting() - except AttributeError: # shell may have closed - pass - # Reschedule myself - if not self.tkconsole.closing: - self.tkconsole.text.after(self.tkconsole.pollinterval, - self.poll_subprocess) - - debugger = None - - def setdebugger(self, debugger): - self.debugger = debugger - - def getdebugger(self): - return self.debugger - - def open_remote_stack_viewer(self): - """Initiate the remote stack viewer from a separate thread. - - This method is called from the subprocess, and by returning from this - method we allow the subprocess to unblock. After a bit the shell - requests the subprocess to open the remote stack viewer which returns a - static object looking at the last exceptiopn. It is queried through - the RPC mechanism. - - """ - self.tkconsole.text.after(300, self.remote_stack_viewer) - return - - def remote_stack_viewer(self): - import RemoteObjectBrowser - oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {}) - if oid is None: - self.tkconsole.root.bell() - return - item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid) - from TreeWidget import ScrolledCanvas, TreeNode - top = Toplevel(self.tkconsole.root) - theme = idleConf.GetOption('main','Theme','name') - background = idleConf.GetHighlight(theme, 'normal')['background'] - sc = ScrolledCanvas(top, bg=background, highlightthickness=0) - sc.frame.pack(expand=1, fill="both") - node = TreeNode(sc.canvas, None, item) - node.expand() - # XXX Should GC the remote tree when closing the window - - gid = 0 - - def execsource(self, source): - "Like runsource() but assumes complete exec source" - filename = self.stuffsource(source) - self.execfile(filename, source) - - def execfile(self, filename, source=None): - "Execute an existing file" - if source is None: - source = open(filename, "r").read() - try: - code = compile(source, filename, "exec") - except (OverflowError, SyntaxError): - self.tkconsole.resetoutput() - tkerr = self.tkconsole.stderr - print>>tkerr, '*** Error in script or command!\n' - print>>tkerr, 'Traceback (most recent call last):' - InteractiveInterpreter.showsyntaxerror(self, filename) - self.tkconsole.showprompt() - else: - self.runcode(code) - - def runsource(self, source): - "Extend base class method: Stuff the source in the line cache first" - filename = self.stuffsource(source) - self.more = 0 - self.save_warnings_filters = warnings.filters[:] - warnings.filterwarnings(action="error", category=SyntaxWarning) - if isinstance(source, types.UnicodeType): - import IOBinding - try: - source = source.encode(IOBinding.encoding) - except UnicodeError: - self.tkconsole.resetoutput() - self.write("Unsupported characters in input\n") - return - try: - # InteractiveInterpreter.runsource() calls its runcode() method, - # which is overridden (see below) - return InteractiveInterpreter.runsource(self, source, filename) - finally: - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None - - def stuffsource(self, source): - "Stuff source in the filename cache" - filename = "<pyshell#%d>" % self.gid - self.gid = self.gid + 1 - lines = source.split("\n") - linecache.cache[filename] = len(source)+1, 0, lines, filename - return filename - - def prepend_syspath(self, filename): - "Prepend sys.path with file's directory if not already included" - self.runcommand("""if 1: - _filename = %r - import sys as _sys - from os.path import dirname as _dirname - _dir = _dirname(_filename) - if not _dir in _sys.path: - _sys.path.insert(0, _dir) - del _filename, _sys, _dirname, _dir - \n""" % (filename,)) - - def showsyntaxerror(self, filename=None): - """Extend base class method: Add Colorizing - - Color the offending position instead of printing it and pointing at it - with a caret. - - """ - text = self.tkconsole.text - stuff = self.unpackerror() - if stuff: - msg, lineno, offset, line = stuff - if lineno == 1: - pos = "iomark + %d chars" % (offset-1) - else: - pos = "iomark linestart + %d lines + %d chars" % \ - (lineno-1, offset-1) - text.tag_add("ERROR", pos) - text.see(pos) - char = text.get(pos) - if char and char in IDENTCHARS: - text.tag_add("ERROR", pos + " wordstart", pos) - self.tkconsole.resetoutput() - self.write("SyntaxError: %s\n" % str(msg)) - else: - self.tkconsole.resetoutput() - InteractiveInterpreter.showsyntaxerror(self, filename) - self.tkconsole.showprompt() - - def unpackerror(self): - type, value, tb = sys.exc_info() - ok = type is SyntaxError - if ok: - try: - msg, (dummy_filename, lineno, offset, line) = value - if not offset: - offset = 0 - except: - ok = 0 - if ok: - return msg, lineno, offset, line - else: - return None - - def showtraceback(self): - "Extend base class method to reset output properly" - self.tkconsole.resetoutput() - self.checklinecache() - InteractiveInterpreter.showtraceback(self) - if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): - self.tkconsole.open_stack_viewer() - - def checklinecache(self): - c = linecache.cache - for key in c.keys(): - if key[:1] + key[-1:] != "<>": - del c[key] - - def runcommand(self, code): - "Run the code without invoking the debugger" - # The code better not raise an exception! - if self.tkconsole.executing: - self.display_executing_dialog() - return 0 - if self.rpcclt: - self.rpcclt.remotequeue("exec", "runcode", (code,), {}) - else: - exec code in self.locals - return 1 - - def runcode(self, code): - "Override base class method" - if self.tkconsole.executing: - self.interp.restart_subprocess() - self.checklinecache() - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None - debugger = self.debugger - try: - self.tkconsole.beginexecuting() - try: - if not debugger and self.rpcclt is not None: - self.active_seq = self.rpcclt.asyncqueue("exec", "runcode", - (code,), {}) - elif debugger: - debugger.run(code, self.locals) - else: - exec code in self.locals - except SystemExit: - if not self.tkconsole.closing: - if tkMessageBox.askyesno( - "Exit?", - "Do you want to exit altogether?", - default="yes", - master=self.tkconsole.text): - raise - else: - self.showtraceback() - else: - raise - except: - if use_subprocess: - print >> self.tkconsole.stderr, \ - "IDLE internal error in runcode()" - self.showtraceback() - if use_subprocess: - self.tkconsole.endexecuting() - finally: - if not use_subprocess: - try: - self.tkconsole.endexecuting() - except AttributeError: # shell may have closed - pass - - def write(self, s): - "Override base class method" - self.tkconsole.stderr.write(s) - - def display_port_binding_error(self): - tkMessageBox.showerror( - "Port Binding Error", - "IDLE can't bind TCP/IP port 8833, which is necessary to " - "communicate with its Python execution server. Either " - "no networking is installed on this computer or another " - "process (another IDLE?) is using the port. Run IDLE with the -n " - "command line switch to start without a subprocess and refer to " - "Help/IDLE Help 'Running without a subprocess' for further " - "details.", - master=self.tkconsole.text) - - def display_no_subprocess_error(self): - tkMessageBox.showerror( - "Subprocess Startup Error", - "IDLE's subprocess didn't make connection. Either IDLE can't " - "start a subprocess or personal firewall software is blocking " - "the connection.", - master=self.tkconsole.text) - - def display_executing_dialog(self): - tkMessageBox.showerror( - "Already executing", - "The Python Shell window is already executing a command; " - "please wait until it is finished.", - master=self.tkconsole.text) - - -class PyShell(OutputWindow): - - shell_title = "Python Shell" - - # Override classes - ColorDelegator = ModifiedColorDelegator - UndoDelegator = ModifiedUndoDelegator - - # Override menus - menu_specs = [ - ("file", "_File"), - ("edit", "_Edit"), - ("debug", "_Debug"), - ("options", "_Options"), - ("windows", "_Windows"), - ("help", "_Help"), - ] - - if macosxSupport.runningAsOSXApp(): - del menu_specs[-3] - menu_specs[-2] = ("windows", "_Window") - - - # New classes - from IdleHistory import History - - def __init__(self, flist=None): - if use_subprocess: - ms = self.menu_specs - if ms[2][0] != "shell": - ms.insert(2, ("shell", "She_ll")) - self.interp = ModifiedInterpreter(self) - if flist is None: - root = Tk() - fixwordbreaks(root) - root.withdraw() - flist = PyShellFileList(root) - # - OutputWindow.__init__(self, flist, None, None) - # -## self.config(usetabs=1, indentwidth=8, context_use_ps1=1) - self.usetabs = True - # indentwidth must be 8 when using tabs. See note in EditorWindow: - self.indentwidth = 8 - self.context_use_ps1 = True - # - text = self.text - text.configure(wrap="char") - text.bind("<<newline-and-indent>>", self.enter_callback) - text.bind("<<plain-newline-and-indent>>", self.linefeed_callback) - text.bind("<<interrupt-execution>>", self.cancel_callback) - text.bind("<<beginning-of-line>>", self.home_callback) - text.bind("<<end-of-file>>", self.eof_callback) - text.bind("<<open-stack-viewer>>", self.open_stack_viewer) - text.bind("<<toggle-debugger>>", self.toggle_debugger) - text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer) - if use_subprocess: - text.bind("<<view-restart>>", self.view_restart_mark) - text.bind("<<restart-shell>>", self.restart_shell) - # - self.save_stdout = sys.stdout - self.save_stderr = sys.stderr - self.save_stdin = sys.stdin - import IOBinding - self.stdout = PseudoFile(self, "stdout", IOBinding.encoding) - self.stderr = PseudoFile(self, "stderr", IOBinding.encoding) - self.console = PseudoFile(self, "console", IOBinding.encoding) - if not use_subprocess: - sys.stdout = self.stdout - sys.stderr = self.stderr - sys.stdin = self - # - self.history = self.History(self.text) - # - self.pollinterval = 50 # millisec - - def get_standard_extension_names(self): - return idleConf.GetExtensions(shell_only=True) - - reading = False - executing = False - canceled = False - endoffile = False - closing = False - - def set_warning_stream(self, stream): - global warning_stream - warning_stream = stream - - def get_warning_stream(self): - return warning_stream - - def toggle_debugger(self, event=None): - if self.executing: - tkMessageBox.showerror("Don't debug now", - "You can only toggle the debugger when idle", - master=self.text) - self.set_debugger_indicator() - return "break" - else: - db = self.interp.getdebugger() - if db: - self.close_debugger() - else: - self.open_debugger() - - def set_debugger_indicator(self): - db = self.interp.getdebugger() - self.setvar("<<toggle-debugger>>", not not db) - - def toggle_jit_stack_viewer(self, event=None): - pass # All we need is the variable - - def close_debugger(self): - db = self.interp.getdebugger() - if db: - self.interp.setdebugger(None) - db.close() - if self.interp.rpcclt: - RemoteDebugger.close_remote_debugger(self.interp.rpcclt) - self.resetoutput() - self.console.write("[DEBUG OFF]\n") - sys.ps1 = ">>> " - self.showprompt() - self.set_debugger_indicator() - - def open_debugger(self): - if self.interp.rpcclt: - dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, - self) - else: - dbg_gui = Debugger.Debugger(self) - self.interp.setdebugger(dbg_gui) - dbg_gui.load_breakpoints() - sys.ps1 = "[DEBUG ON]\n>>> " - self.showprompt() - self.set_debugger_indicator() - - def beginexecuting(self): - "Helper for ModifiedInterpreter" - self.resetoutput() - self.executing = 1 - - def endexecuting(self): - "Helper for ModifiedInterpreter" - self.executing = 0 - self.canceled = 0 - self.showprompt() - - def close(self): - "Extend EditorWindow.close()" - if self.executing: - response = tkMessageBox.askokcancel( - "Kill?", - "The program is still running!\n Do you want to kill it?", - default="ok", - parent=self.text) - if response == False: - return "cancel" - if self.reading: - self.top.quit() - self.canceled = True - self.closing = True - # Wait for poll_subprocess() rescheduling to stop - self.text.after(2 * self.pollinterval, self.close2) - - def close2(self): - return EditorWindow.close(self) - - def _close(self): - "Extend EditorWindow._close(), shut down debugger and execution server" - self.close_debugger() - if use_subprocess: - self.interp.kill_subprocess() - # Restore std streams - sys.stdout = self.save_stdout - sys.stderr = self.save_stderr - sys.stdin = self.save_stdin - # Break cycles - self.interp = None - self.console = None - self.flist.pyshell = None - self.history = None - EditorWindow._close(self) - - def ispythonsource(self, filename): - "Override EditorWindow method: never remove the colorizer" - return True - - def short_title(self): - return self.shell_title - - COPYRIGHT = \ - 'Type "copyright", "credits" or "license()" for more information.' - - firewallmessage = """ - **************************************************************** - Personal firewall software may warn about the connection IDLE - makes to its subprocess using this computer's internal loopback - interface. This connection is not visible on any external - interface and no data is sent to or received from the Internet. - **************************************************************** - """ - - def begin(self): - self.resetoutput() - if use_subprocess: - nosub = '' - client = self.interp.start_subprocess() - if not client: - self.close() - return False - else: - nosub = "==== No Subprocess ====" - self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" % - (sys.version, sys.platform, self.COPYRIGHT, - self.firewallmessage, idlever.IDLE_VERSION, nosub)) - self.showprompt() - import Tkinter - Tkinter._default_root = None # 03Jan04 KBK What's this? - return True - - def readline(self): - save = self.reading - try: - self.reading = 1 - self.top.mainloop() # nested mainloop() - finally: - self.reading = save - line = self.text.get("iomark", "end-1c") - if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C - line = "\n" - if isinstance(line, unicode): - import IOBinding - try: - line = line.encode(IOBinding.encoding) - except UnicodeError: - pass - self.resetoutput() - if self.canceled: - self.canceled = 0 - if not use_subprocess: - raise KeyboardInterrupt - if self.endoffile: - self.endoffile = 0 - line = "" - return line - - def isatty(self): - return True - - def cancel_callback(self, event=None): - try: - if self.text.compare("sel.first", "!=", "sel.last"): - return # Active selection -- always use default binding - except: - pass - if not (self.executing or self.reading): - self.resetoutput() - self.interp.write("KeyboardInterrupt\n") - self.showprompt() - return "break" - self.endoffile = 0 - self.canceled = 1 - if (self.executing and self.interp.rpcclt): - if self.interp.getdebugger(): - self.interp.restart_subprocess() - else: - self.interp.interrupt_subprocess() - if self.reading: - self.top.quit() # exit the nested mainloop() in readline() - return "break" - - def eof_callback(self, event): - if self.executing and not self.reading: - return # Let the default binding (delete next char) take over - if not (self.text.compare("iomark", "==", "insert") and - self.text.compare("insert", "==", "end-1c")): - return # Let the default binding (delete next char) take over - if not self.executing: - self.resetoutput() - self.close() - else: - self.canceled = 0 - self.endoffile = 1 - self.top.quit() - return "break" - - def home_callback(self, event): - if event.state != 0 and event.keysym == "Home": - return # <Modifier-Home>; fall back to class binding - if self.text.compare("iomark", "<=", "insert") and \ - self.text.compare("insert linestart", "<=", "iomark"): - self.text.mark_set("insert", "iomark") - self.text.tag_remove("sel", "1.0", "end") - self.text.see("insert") - return "break" - - def linefeed_callback(self, event): - # Insert a linefeed without entering anything (still autoindented) - if self.reading: - self.text.insert("insert", "\n") - self.text.see("insert") - else: - self.newline_and_indent_event(event) - return "break" - - def enter_callback(self, event): - if self.executing and not self.reading: - return # Let the default binding (insert '\n') take over - # If some text is selected, recall the selection - # (but only if this before the I/O mark) - try: - sel = self.text.get("sel.first", "sel.last") - if sel: - if self.text.compare("sel.last", "<=", "iomark"): - self.recall(sel, event) - return "break" - except: - pass - # If we're strictly before the line containing iomark, recall - # the current line, less a leading prompt, less leading or - # trailing whitespace - if self.text.compare("insert", "<", "iomark linestart"): - # Check if there's a relevant stdin range -- if so, use it - prev = self.text.tag_prevrange("stdin", "insert") - if prev and self.text.compare("insert", "<", prev[1]): - self.recall(self.text.get(prev[0], prev[1]), event) - return "break" - next = self.text.tag_nextrange("stdin", "insert") - if next and self.text.compare("insert lineend", ">=", next[0]): - self.recall(self.text.get(next[0], next[1]), event) - return "break" - # No stdin mark -- just get the current line, less any prompt - indices = self.text.tag_nextrange("console", "insert linestart") - if indices and \ - self.text.compare(indices[0], "<=", "insert linestart"): - self.recall(self.text.get(indices[1], "insert lineend"), event) - else: - self.recall(self.text.get("insert linestart", "insert lineend"), event) - return "break" - # If we're between the beginning of the line and the iomark, i.e. - # in the prompt area, move to the end of the prompt - if self.text.compare("insert", "<", "iomark"): - self.text.mark_set("insert", "iomark") - # If we're in the current input and there's only whitespace - # beyond the cursor, erase that whitespace first - s = self.text.get("insert", "end-1c") - if s and not s.strip(): - self.text.delete("insert", "end-1c") - # If we're in the current input before its last line, - # insert a newline right at the insert point - if self.text.compare("insert", "<", "end-1c linestart"): - self.newline_and_indent_event(event) - return "break" - # We're in the last line; append a newline and submit it - self.text.mark_set("insert", "end-1c") - if self.reading: - self.text.insert("insert", "\n") - self.text.see("insert") - else: - self.newline_and_indent_event(event) - self.text.tag_add("stdin", "iomark", "end-1c") - self.text.update_idletasks() - if self.reading: - self.top.quit() # Break out of recursive mainloop() in raw_input() - else: - self.runit() - return "break" - - def recall(self, s, event): - # remove leading and trailing empty or whitespace lines - s = re.sub(r'^\s*\n', '' , s) - s = re.sub(r'\n\s*$', '', s) - lines = s.split('\n') - self.text.undo_block_start() - try: - self.text.tag_remove("sel", "1.0", "end") - self.text.mark_set("insert", "end-1c") - prefix = self.text.get("insert linestart", "insert") - if prefix.rstrip().endswith(':'): - self.newline_and_indent_event(event) - prefix = self.text.get("insert linestart", "insert") - self.text.insert("insert", lines[0].strip()) - if len(lines) > 1: - orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0) - new_base_indent = re.search(r'^([ \t]*)', prefix).group(0) - for line in lines[1:]: - if line.startswith(orig_base_indent): - # replace orig base indentation with new indentation - line = new_base_indent + line[len(orig_base_indent):] - self.text.insert('insert', '\n'+line.rstrip()) - finally: - self.text.see("insert") - self.text.undo_block_stop() - - def runit(self): - line = self.text.get("iomark", "end-1c") - # Strip off last newline and surrounding whitespace. - # (To allow you to hit return twice to end a statement.) - i = len(line) - while i > 0 and line[i-1] in " \t": - i = i-1 - if i > 0 and line[i-1] == "\n": - i = i-1 - while i > 0 and line[i-1] in " \t": - i = i-1 - line = line[:i] - more = self.interp.runsource(line) - - def open_stack_viewer(self, event=None): - if self.interp.rpcclt: - return self.interp.remote_stack_viewer() - try: - sys.last_traceback - except: - tkMessageBox.showerror("No stack trace", - "There is no stack trace yet.\n" - "(sys.last_traceback is not defined)", - master=self.text) - return - from StackViewer import StackBrowser - sv = StackBrowser(self.root, self.flist) - - def view_restart_mark(self, event=None): - self.text.see("iomark") - self.text.see("restart") - - def restart_shell(self, event=None): - self.interp.restart_subprocess() - - def showprompt(self): - self.resetoutput() - try: - s = str(sys.ps1) - except: - s = "" - self.console.write(s) - self.text.mark_set("insert", "end-1c") - self.set_line_and_column() - self.io.reset_undo() - - def resetoutput(self): - source = self.text.get("iomark", "end-1c") - if self.history: - self.history.history_store(source) - if self.text.get("end-2c") != "\n": - self.text.insert("end-1c", "\n") - self.text.mark_set("iomark", "end-1c") - self.set_line_and_column() - sys.stdout.softspace = 0 - - def write(self, s, tags=()): - try: - self.text.mark_gravity("iomark", "right") - OutputWindow.write(self, s, tags, "iomark") - self.text.mark_gravity("iomark", "left") - except: - pass - if self.canceled: - self.canceled = 0 - if not use_subprocess: - raise KeyboardInterrupt - -class PseudoFile(object): - - def __init__(self, shell, tags, encoding=None): - self.shell = shell - self.tags = tags - self.softspace = 0 - self.encoding = encoding - - def write(self, s): - self.shell.write(s, self.tags) - - def writelines(self, l): - map(self.write, l) - - def flush(self): - pass - - def isatty(self): - return True - - -usage_msg = """\ - -USAGE: idle [-deins] [-t title] [file]* - idle [-dns] [-t title] (-c cmd | -r file) [arg]* - idle [-dns] [-t title] - [arg]* - - -h print this help message and exit - -n run IDLE without a subprocess (see Help/IDLE Help for details) - -The following options will override the IDLE 'settings' configuration: - - -e open an edit window - -i open a shell window - -The following options imply -i and will open a shell: - - -c cmd run the command in a shell, or - -r file run script from file - - -d enable the debugger - -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else - -t title set title of shell window - -A default edit window will be bypassed when -c, -r, or - are used. - -[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:]. - -Examples: - -idle - Open an edit window or shell depending on IDLE's configuration. - -idle foo.py foobar.py - Edit the files, also open a shell if configured to start with shell. - -idle -est "Baz" foo.py - Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell - window with the title "Baz". - -idle -c "import sys; print sys.argv" "foo" - Open a shell window and run the command, passing "-c" in sys.argv[0] - and "foo" in sys.argv[1]. - -idle -d -s -r foo.py "Hello World" - Open a shell window, run a startup script, enable the debugger, and - run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in - sys.argv[1]. - -echo "import sys; print sys.argv" | idle - "foobar" - Open a shell window, run the script piped in, passing '' in sys.argv[0] - and "foobar" in sys.argv[1]. -""" - -def main(): - global flist, root, use_subprocess - - use_subprocess = True - enable_shell = False - enable_edit = False - debug = False - cmd = None - script = None - startup = False - try: - opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:") - except getopt.error, msg: - sys.stderr.write("Error: %s\n" % str(msg)) - sys.stderr.write(usage_msg) - sys.exit(2) - for o, a in opts: - if o == '-c': - cmd = a - enable_shell = True - if o == '-d': - debug = True - enable_shell = True - if o == '-e': - enable_edit = True - if o == '-h': - sys.stdout.write(usage_msg) - sys.exit() - if o == '-i': - enable_shell = True - if o == '-n': - use_subprocess = False - if o == '-r': - script = a - if os.path.isfile(script): - pass - else: - print "No script file: ", script - sys.exit() - enable_shell = True - if o == '-s': - startup = True - enable_shell = True - if o == '-t': - PyShell.shell_title = a - enable_shell = True - if args and args[0] == '-': - cmd = sys.stdin.read() - enable_shell = True - # process sys.argv and sys.path: - for i in range(len(sys.path)): - sys.path[i] = os.path.abspath(sys.path[i]) - if args and args[0] == '-': - sys.argv = [''] + args[1:] - elif cmd: - sys.argv = ['-c'] + args - elif script: - sys.argv = [script] + args - elif args: - enable_edit = True - pathx = [] - for filename in args: - pathx.append(os.path.dirname(filename)) - for dir in pathx: - dir = os.path.abspath(dir) - if not dir in sys.path: - sys.path.insert(0, dir) - else: - dir = os.getcwd() - if not dir in sys.path: - sys.path.insert(0, dir) - # check the IDLE settings configuration (but command line overrides) - edit_start = idleConf.GetOption('main', 'General', - 'editor-on-startup', type='bool') - enable_edit = enable_edit or edit_start - enable_shell = enable_shell or not edit_start - # start editor and/or shell windows: - root = Tk(className="Idle") - - fixwordbreaks(root) - root.withdraw() - flist = PyShellFileList(root) - macosxSupport.setupApp(root, flist) - - if enable_edit: - if not (cmd or script): - for filename in args: - flist.open(filename) - if not args: - flist.new() - if enable_shell: - shell = flist.open_shell() - if not shell: - return # couldn't open shell - - if macosxSupport.runningAsOSXApp() and flist.dict: - # On OSX: when the user has double-clicked on a file that causes - # IDLE to be launched the shell window will open just in front of - # the file she wants to see. Lower the interpreter window when - # there are open files. - shell.top.lower() - - shell = flist.pyshell - # handle remaining options: - if debug: - shell.open_debugger() - if startup: - filename = os.environ.get("IDLESTARTUP") or \ - os.environ.get("PYTHONSTARTUP") - if filename and os.path.isfile(filename): - shell.interp.execfile(filename) - if shell and cmd or script: - shell.interp.runcommand("""if 1: - import sys as _sys - _sys.argv = %r - del _sys - \n""" % (sys.argv,)) - if cmd: - shell.interp.execsource(cmd) - elif script: - shell.interp.prepend_syspath(script) - shell.interp.execfile(script) - - root.mainloop() - root.destroy() - -if __name__ == "__main__": - sys.modules['PyShell'] = sys.modules['__main__'] - main() diff --git a/sys/lib/python/idlelib/README.txt b/sys/lib/python/idlelib/README.txt deleted file mode 100644 index 101f7eba1..000000000 --- a/sys/lib/python/idlelib/README.txt +++ /dev/null @@ -1,63 +0,0 @@ -IDLE is Python's Tkinter-based Integrated DeveLopment Environment. - -IDLE emphasizes a lightweight, clean design with a simple user interface. -Although it is suitable for beginners, even advanced users will find that -IDLE has everything they really need to develop pure Python code. - -IDLE features a multi-window text editor with multiple undo, Python colorizing, -and many other capabilities, e.g. smart indent, call tips, and autocompletion. - -The editor has comprehensive search functions, including searching through -multiple files. Class browsers and path browsers provide fast access to -code objects from a top level viewpoint without dealing with code folding. - -There is a Python Shell window which features colorizing and command recall. - -IDLE executes Python code in a separate process, which is restarted for each -Run (F5) initiated from an editor window. The environment can also be -restarted from the Shell window without restarting IDLE. - -This enhancement has often been requested, and is now finally available. The -magic "reload/import *" incantations are no longer required when editing and -testing a module two or three steps down the import chain. - -(Personal firewall software may warn about the connection IDLE makes to its -subprocess using this computer's internal loopback interface. This connection -is not visible on any external interface and no data is sent to or received -from the Internet.) - -It is possible to interrupt tightly looping user code, even on Windows. - -Applications which cannot support subprocesses and/or sockets can still run -IDLE in a single process. - -IDLE has an integrated debugger with stepping, persistent breakpoints, and call -stack visibility. - -There is a GUI configuration manager which makes it easy to select fonts, -colors, keybindings, and startup options. This facility includes a feature -which allows the user to specify additional help sources, either locally or on -the web. - -IDLE is coded in 100% pure Python, using the Tkinter GUI toolkit (Tk/Tcl) -and is cross-platform, working on Unix, Mac, and Windows. - -IDLE accepts command line arguments. Try idle -h to see the options. - - -If you find bugs or have suggestions, let us know about them by using the -Python Bug Tracker: - -http://sourceforge.net/projects/python - -Patches are always appreciated at the Python Patch Tracker, and change -requests should be posted to the RFE Tracker. - -For further details and links, read the Help files and check the IDLE home -page at - -http://www.python.org/idle/ - -There is a mail list for IDLE: idle-dev@python.org. You can join at - -http://mail.python.org/mailman/listinfo/idle-dev diff --git a/sys/lib/python/idlelib/RemoteDebugger.py b/sys/lib/python/idlelib/RemoteDebugger.py deleted file mode 100644 index 74085c36f..000000000 --- a/sys/lib/python/idlelib/RemoteDebugger.py +++ /dev/null @@ -1,381 +0,0 @@ -"""Support for remote Python debugging. - -Some ASCII art to describe the structure: - - IN PYTHON SUBPROCESS # IN IDLE PROCESS - # - # oid='gui_adapter' - +----------+ # +------------+ +-----+ - | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | -+-----+--calls-->+----------+ # +------------+ +-----+ -| Idb | # / -+-----+<-calls--+------------+ # +----------+<--calls-/ - | IdbAdapter |<--remote#call--| IdbProxy | - +------------+ # +----------+ - oid='idb_adapter' # - -The purpose of the Proxy and Adapter classes is to translate certain -arguments and return values that cannot be transported through the RPC -barrier, in particular frame and traceback objects. - -""" - -import sys -import types -import rpc -import Debugger - -debugging = 0 - -idb_adap_oid = "idb_adapter" -gui_adap_oid = "gui_adapter" - -#======================================= -# -# In the PYTHON subprocess: - -frametable = {} -dicttable = {} -codetable = {} -tracebacktable = {} - -def wrap_frame(frame): - fid = id(frame) - frametable[fid] = frame - return fid - -def wrap_info(info): - "replace info[2], a traceback instance, by its ID" - if info is None: - return None - else: - traceback = info[2] - assert isinstance(traceback, types.TracebackType) - traceback_id = id(traceback) - tracebacktable[traceback_id] = traceback - modified_info = (info[0], info[1], traceback_id) - return modified_info - -class GUIProxy: - - def __init__(self, conn, gui_adap_oid): - self.conn = conn - self.oid = gui_adap_oid - - def interaction(self, message, frame, info=None): - # calls rpc.SocketIO.remotecall() via run.MyHandler instance - # pass frame and traceback object IDs instead of the objects themselves - self.conn.remotecall(self.oid, "interaction", - (message, wrap_frame(frame), wrap_info(info)), - {}) - -class IdbAdapter: - - def __init__(self, idb): - self.idb = idb - - #----------called by an IdbProxy---------- - - def set_step(self): - self.idb.set_step() - - def set_quit(self): - self.idb.set_quit() - - def set_continue(self): - self.idb.set_continue() - - def set_next(self, fid): - frame = frametable[fid] - self.idb.set_next(frame) - - def set_return(self, fid): - frame = frametable[fid] - self.idb.set_return(frame) - - def get_stack(self, fid, tbid): - ##print >>sys.__stderr__, "get_stack(%r, %r)" % (fid, tbid) - frame = frametable[fid] - if tbid is None: - tb = None - else: - tb = tracebacktable[tbid] - stack, i = self.idb.get_stack(frame, tb) - ##print >>sys.__stderr__, "get_stack() ->", stack - stack = [(wrap_frame(frame), k) for frame, k in stack] - ##print >>sys.__stderr__, "get_stack() ->", stack - return stack, i - - def run(self, cmd): - import __main__ - self.idb.run(cmd, __main__.__dict__) - - def set_break(self, filename, lineno): - msg = self.idb.set_break(filename, lineno) - return msg - - def clear_break(self, filename, lineno): - msg = self.idb.clear_break(filename, lineno) - return msg - - def clear_all_file_breaks(self, filename): - msg = self.idb.clear_all_file_breaks(filename) - return msg - - #----------called by a FrameProxy---------- - - def frame_attr(self, fid, name): - frame = frametable[fid] - return getattr(frame, name) - - def frame_globals(self, fid): - frame = frametable[fid] - dict = frame.f_globals - did = id(dict) - dicttable[did] = dict - return did - - def frame_locals(self, fid): - frame = frametable[fid] - dict = frame.f_locals - did = id(dict) - dicttable[did] = dict - return did - - def frame_code(self, fid): - frame = frametable[fid] - code = frame.f_code - cid = id(code) - codetable[cid] = code - return cid - - #----------called by a CodeProxy---------- - - def code_name(self, cid): - code = codetable[cid] - return code.co_name - - def code_filename(self, cid): - code = codetable[cid] - return code.co_filename - - #----------called by a DictProxy---------- - - def dict_keys(self, did): - dict = dicttable[did] - return dict.keys() - - def dict_item(self, did, key): - dict = dicttable[did] - value = dict[key] - value = repr(value) - return value - -#----------end class IdbAdapter---------- - - -def start_debugger(rpchandler, gui_adap_oid): - """Start the debugger and its RPC link in the Python subprocess - - Start the subprocess side of the split debugger and set up that side of the - RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter - objects and linking them together. Register the IdbAdapter with the - RPCServer to handle RPC requests from the split debugger GUI via the - IdbProxy. - - """ - gui_proxy = GUIProxy(rpchandler, gui_adap_oid) - idb = Debugger.Idb(gui_proxy) - idb_adap = IdbAdapter(idb) - rpchandler.register(idb_adap_oid, idb_adap) - return idb_adap_oid - - -#======================================= -# -# In the IDLE process: - - -class FrameProxy: - - def __init__(self, conn, fid): - self._conn = conn - self._fid = fid - self._oid = "idb_adapter" - self._dictcache = {} - - def __getattr__(self, name): - if name[:1] == "_": - raise AttributeError, name - if name == "f_code": - return self._get_f_code() - if name == "f_globals": - return self._get_f_globals() - if name == "f_locals": - return self._get_f_locals() - return self._conn.remotecall(self._oid, "frame_attr", - (self._fid, name), {}) - - def _get_f_code(self): - cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {}) - return CodeProxy(self._conn, self._oid, cid) - - def _get_f_globals(self): - did = self._conn.remotecall(self._oid, "frame_globals", - (self._fid,), {}) - return self._get_dict_proxy(did) - - def _get_f_locals(self): - did = self._conn.remotecall(self._oid, "frame_locals", - (self._fid,), {}) - return self._get_dict_proxy(did) - - def _get_dict_proxy(self, did): - if self._dictcache.has_key(did): - return self._dictcache[did] - dp = DictProxy(self._conn, self._oid, did) - self._dictcache[did] = dp - return dp - - -class CodeProxy: - - def __init__(self, conn, oid, cid): - self._conn = conn - self._oid = oid - self._cid = cid - - def __getattr__(self, name): - if name == "co_name": - return self._conn.remotecall(self._oid, "code_name", - (self._cid,), {}) - if name == "co_filename": - return self._conn.remotecall(self._oid, "code_filename", - (self._cid,), {}) - - -class DictProxy: - - def __init__(self, conn, oid, did): - self._conn = conn - self._oid = oid - self._did = did - - def keys(self): - return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {}) - - def __getitem__(self, key): - return self._conn.remotecall(self._oid, "dict_item", - (self._did, key), {}) - - def __getattr__(self, name): - ##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name - raise AttributeError, name - - -class GUIAdapter: - - def __init__(self, conn, gui): - self.conn = conn - self.gui = gui - - def interaction(self, message, fid, modified_info): - ##print "interaction: (%s, %s, %s)" % (message, fid, modified_info) - frame = FrameProxy(self.conn, fid) - self.gui.interaction(message, frame, modified_info) - - -class IdbProxy: - - def __init__(self, conn, shell, oid): - self.oid = oid - self.conn = conn - self.shell = shell - - def call(self, methodname, *args, **kwargs): - ##print "**IdbProxy.call %s %s %s" % (methodname, args, kwargs) - value = self.conn.remotecall(self.oid, methodname, args, kwargs) - ##print "**IdbProxy.call %s returns %r" % (methodname, value) - return value - - def run(self, cmd, locals): - # Ignores locals on purpose! - seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {}) - self.shell.interp.active_seq = seq - - def get_stack(self, frame, tbid): - # passing frame and traceback IDs, not the objects themselves - stack, i = self.call("get_stack", frame._fid, tbid) - stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack] - return stack, i - - def set_continue(self): - self.call("set_continue") - - def set_step(self): - self.call("set_step") - - def set_next(self, frame): - self.call("set_next", frame._fid) - - def set_return(self, frame): - self.call("set_return", frame._fid) - - def set_quit(self): - self.call("set_quit") - - def set_break(self, filename, lineno): - msg = self.call("set_break", filename, lineno) - return msg - - def clear_break(self, filename, lineno): - msg = self.call("clear_break", filename, lineno) - return msg - - def clear_all_file_breaks(self, filename): - msg = self.call("clear_all_file_breaks", filename) - return msg - -def start_remote_debugger(rpcclt, pyshell): - """Start the subprocess debugger, initialize the debugger GUI and RPC link - - Request the RPCServer start the Python subprocess debugger and link. Set - up the Idle side of the split debugger by instantiating the IdbProxy, - debugger GUI, and debugger GUIAdapter objects and linking them together. - - Register the GUIAdapter with the RPCClient to handle debugger GUI - interaction requests coming from the subprocess debugger via the GUIProxy. - - The IdbAdapter will pass execution and environment requests coming from the - Idle debugger GUI to the subprocess debugger via the IdbProxy. - - """ - global idb_adap_oid - - idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\ - (gui_adap_oid,), {}) - idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid) - gui = Debugger.Debugger(pyshell, idb_proxy) - gui_adap = GUIAdapter(rpcclt, gui) - rpcclt.register(gui_adap_oid, gui_adap) - return gui - -def close_remote_debugger(rpcclt): - """Shut down subprocess debugger and Idle side of debugger RPC link - - Request that the RPCServer shut down the subprocess debugger and link. - Unregister the GUIAdapter, which will cause a GC on the Idle process - debugger and RPC link objects. (The second reference to the debugger GUI - is deleted in PyShell.close_remote_debugger().) - - """ - close_subprocess_debugger(rpcclt) - rpcclt.unregister(gui_adap_oid) - -def close_subprocess_debugger(rpcclt): - rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {}) - -def restart_subprocess_debugger(rpcclt): - idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\ - (gui_adap_oid,), {}) - assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid' diff --git a/sys/lib/python/idlelib/RemoteObjectBrowser.py b/sys/lib/python/idlelib/RemoteObjectBrowser.py deleted file mode 100644 index 6ba339137..000000000 --- a/sys/lib/python/idlelib/RemoteObjectBrowser.py +++ /dev/null @@ -1,36 +0,0 @@ -import rpc - -def remote_object_tree_item(item): - wrapper = WrappedObjectTreeItem(item) - oid = id(wrapper) - rpc.objecttable[oid] = wrapper - return oid - -class WrappedObjectTreeItem: - # Lives in PYTHON subprocess - - def __init__(self, item): - self.__item = item - - def __getattr__(self, name): - value = getattr(self.__item, name) - return value - - def _GetSubList(self): - list = self.__item._GetSubList() - return map(remote_object_tree_item, list) - -class StubObjectTreeItem: - # Lives in IDLE process - - def __init__(self, sockio, oid): - self.sockio = sockio - self.oid = oid - - def __getattr__(self, name): - value = rpc.MethodProxy(self.sockio, self.oid, name) - return value - - def _GetSubList(self): - list = self.sockio.remotecall(self.oid, "_GetSubList", (), {}) - return [StubObjectTreeItem(self.sockio, oid) for oid in list] diff --git a/sys/lib/python/idlelib/ReplaceDialog.py b/sys/lib/python/idlelib/ReplaceDialog.py deleted file mode 100644 index c8eb1c8c4..000000000 --- a/sys/lib/python/idlelib/ReplaceDialog.py +++ /dev/null @@ -1,167 +0,0 @@ -from Tkinter import * -import SearchEngine -from SearchDialogBase import SearchDialogBase - -def replace(text): - root = text._root() - engine = SearchEngine.get(root) - if not hasattr(engine, "_replacedialog"): - engine._replacedialog = ReplaceDialog(root, engine) - dialog = engine._replacedialog - dialog.open(text) - -class ReplaceDialog(SearchDialogBase): - - title = "Replace Dialog" - icon = "Replace" - - def __init__(self, root, engine): - SearchDialogBase.__init__(self, root, engine) - self.replvar = StringVar(root) - - def open(self, text): - SearchDialogBase.open(self, text) - try: - first = text.index("sel.first") - except TclError: - first = None - try: - last = text.index("sel.last") - except TclError: - last = None - first = first or text.index("insert") - last = last or first - self.show_hit(first, last) - self.ok = 1 - - def create_entries(self): - SearchDialogBase.create_entries(self) - self.replent = self.make_entry("Replace with:", self.replvar) - - def create_command_buttons(self): - SearchDialogBase.create_command_buttons(self) - self.make_button("Find", self.find_it) - self.make_button("Replace", self.replace_it) - self.make_button("Replace+Find", self.default_command, 1) - self.make_button("Replace All", self.replace_all) - - def find_it(self, event=None): - self.do_find(0) - - def replace_it(self, event=None): - if self.do_find(self.ok): - self.do_replace() - - def default_command(self, event=None): - if self.do_find(self.ok): - self.do_replace() - self.do_find(0) - - def replace_all(self, event=None): - prog = self.engine.getprog() - if not prog: - return - repl = self.replvar.get() - text = self.text - res = self.engine.search_text(text, prog) - if not res: - text.bell() - return - text.tag_remove("sel", "1.0", "end") - text.tag_remove("hit", "1.0", "end") - line = res[0] - col = res[1].start() - if self.engine.iswrap(): - line = 1 - col = 0 - ok = 1 - first = last = None - # XXX ought to replace circular instead of top-to-bottom when wrapping - text.undo_block_start() - while 1: - res = self.engine.search_forward(text, prog, line, col, 0, ok) - if not res: - break - line, m = res - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - orig = m.group() - new = m.expand(repl) - i, j = m.span() - first = "%d.%d" % (line, i) - last = "%d.%d" % (line, j) - if new == orig: - text.mark_set("insert", last) - else: - text.mark_set("insert", first) - if first != last: - text.delete(first, last) - if new: - text.insert(first, new) - col = i + len(new) - ok = 0 - text.undo_block_stop() - if first and last: - self.show_hit(first, last) - self.close() - - def do_find(self, ok=0): - if not self.engine.getprog(): - return False - text = self.text - res = self.engine.search_text(text, None, ok) - if not res: - text.bell() - return False - line, m = res - i, j = m.span() - first = "%d.%d" % (line, i) - last = "%d.%d" % (line, j) - self.show_hit(first, last) - self.ok = 1 - return True - - def do_replace(self): - prog = self.engine.getprog() - if not prog: - return False - text = self.text - try: - first = pos = text.index("sel.first") - last = text.index("sel.last") - except TclError: - pos = None - if not pos: - first = last = pos = text.index("insert") - line, col = SearchEngine.get_line_col(pos) - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - m = prog.match(chars, col) - if not prog: - return False - new = m.expand(self.replvar.get()) - text.mark_set("insert", first) - text.undo_block_start() - if m.group(): - text.delete(first, last) - if new: - text.insert(first, new) - text.undo_block_stop() - self.show_hit(first, text.index("insert")) - self.ok = 0 - return True - - def show_hit(self, first, last): - text = self.text - text.mark_set("insert", first) - text.tag_remove("sel", "1.0", "end") - text.tag_add("sel", first, last) - text.tag_remove("hit", "1.0", "end") - if first == last: - text.tag_add("hit", first) - else: - text.tag_add("hit", first, last) - text.see("insert") - text.update_idletasks() - - def close(self, event=None): - SearchDialogBase.close(self, event) - self.text.tag_remove("hit", "1.0", "end") diff --git a/sys/lib/python/idlelib/ScriptBinding.py b/sys/lib/python/idlelib/ScriptBinding.py deleted file mode 100644 index f325ad1d2..000000000 --- a/sys/lib/python/idlelib/ScriptBinding.py +++ /dev/null @@ -1,210 +0,0 @@ -"""Extension to execute code outside the Python shell window. - -This adds the following commands: - -- Check module does a full syntax check of the current module. - It also runs the tabnanny to catch any inconsistent tabs. - -- Run module executes the module's code in the __main__ namespace. The window - must have been saved previously. The module is added to sys.modules, and is - also added to the __main__ namespace. - -XXX GvR Redesign this interface (yet again) as follows: - -- Present a dialog box for ``Run Module'' - -- Allow specify command line arguments in the dialog box - -""" - -import os -import re -import string -import tabnanny -import tokenize -import tkMessageBox -import PyShell - -from configHandler import idleConf - -IDENTCHARS = string.ascii_letters + string.digits + "_" - -indent_message = """Error: Inconsistent indentation detected! - -1) Your indentation is outright incorrect (easy to fix), OR - -2) Your indentation mixes tabs and spaces. - -To fix case 2, change all tabs to spaces by using Edit->Select All followed \ -by Format->Untabify Region and specify the number of columns used by each tab. -""" - -class ScriptBinding: - - menudefs = [ - ('run', [None, - ('Check Module', '<<check-module>>'), - ('Run Module', '<<run-module>>'), ]), ] - - def __init__(self, editwin): - self.editwin = editwin - # Provide instance variables referenced by Debugger - # XXX This should be done differently - self.flist = self.editwin.flist - self.root = self.editwin.root - - def check_module_event(self, event): - filename = self.getfilename() - if not filename: - return - if not self.tabnanny(filename): - return - self.checksyntax(filename) - - def tabnanny(self, filename): - f = open(filename, 'r') - try: - tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) - except tokenize.TokenError, msg: - msgtxt, (lineno, start) = msg - self.editwin.gotoline(lineno) - self.errorbox("Tabnanny Tokenizing Error", - "Token Error: %s" % msgtxt) - return False - except tabnanny.NannyNag, nag: - # The error messages from tabnanny are too confusing... - self.editwin.gotoline(nag.get_lineno()) - self.errorbox("Tab/space error", indent_message) - return False - except IndentationError: - # From tokenize(), let compile() in checksyntax find it again. - pass - return True - - def checksyntax(self, filename): - self.shell = shell = self.flist.open_shell() - saved_stream = shell.get_warning_stream() - shell.set_warning_stream(shell.stderr) - f = open(filename, 'r') - source = f.read() - f.close() - if '\r' in source: - source = re.sub(r"\r\n", "\n", source) - source = re.sub(r"\r", "\n", source) - if source and source[-1] != '\n': - source = source + '\n' - text = self.editwin.text - text.tag_remove("ERROR", "1.0", "end") - try: - try: - # If successful, return the compiled code - return compile(source, filename, "exec") - except (SyntaxError, OverflowError), err: - try: - msg, (errorfilename, lineno, offset, line) = err - if not errorfilename: - err.args = msg, (filename, lineno, offset, line) - err.filename = filename - self.colorize_syntax_error(msg, lineno, offset) - except: - msg = "*** " + str(err) - self.errorbox("Syntax error", - "There's an error in your program:\n" + msg) - return False - finally: - shell.set_warning_stream(saved_stream) - - def colorize_syntax_error(self, msg, lineno, offset): - text = self.editwin.text - pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1) - text.tag_add("ERROR", pos) - char = text.get(pos) - if char and char in IDENTCHARS: - text.tag_add("ERROR", pos + " wordstart", pos) - if '\n' == text.get(pos): # error at line end - text.mark_set("insert", pos) - else: - text.mark_set("insert", pos + "+1c") - text.see(pos) - - def run_module_event(self, event): - """Run the module after setting up the environment. - - First check the syntax. If OK, make sure the shell is active and - then transfer the arguments, set the run environment's working - directory to the directory of the module being executed and also - add that directory to its sys.path if not already included. - - """ - filename = self.getfilename() - if not filename: - return - if not self.tabnanny(filename): - return - code = self.checksyntax(filename) - if not code: - return - shell = self.shell - interp = shell.interp - if PyShell.use_subprocess: - shell.restart_shell() - dirname = os.path.dirname(filename) - # XXX Too often this discards arguments the user just set... - interp.runcommand("""if 1: - _filename = %r - import sys as _sys - from os.path import basename as _basename - if (not _sys.argv or - _basename(_sys.argv[0]) != _basename(_filename)): - _sys.argv = [_filename] - import os as _os - _os.chdir(%r) - del _filename, _sys, _basename, _os - \n""" % (filename, dirname)) - interp.prepend_syspath(filename) - # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still - # go to __stderr__. With subprocess, they go to the shell. - # Need to change streams in PyShell.ModifiedInterpreter. - interp.runcode(code) - - def getfilename(self): - """Get source filename. If not saved, offer to save (or create) file - - The debugger requires a source file. Make sure there is one, and that - the current version of the source buffer has been saved. If the user - declines to save or cancels the Save As dialog, return None. - - If the user has configured IDLE for Autosave, the file will be - silently saved if it already exists and is dirty. - - """ - filename = self.editwin.io.filename - if not self.editwin.get_saved(): - autosave = idleConf.GetOption('main', 'General', - 'autosave', type='bool') - if autosave and filename: - self.editwin.io.save(None) - else: - reply = self.ask_save_dialog() - self.editwin.text.focus_set() - if reply == "ok": - self.editwin.io.save(None) - filename = self.editwin.io.filename - else: - filename = None - return filename - - def ask_save_dialog(self): - msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?" - mb = tkMessageBox.Message(title="Save Before Run or Check", - message=msg, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.OKCANCEL, - default=tkMessageBox.OK, - master=self.editwin.text) - return mb.show() - - def errorbox(self, title, message): - # XXX This should really be a function of EditorWindow... - tkMessageBox.showerror(title, message, master=self.editwin.text) - self.editwin.text.focus_set() diff --git a/sys/lib/python/idlelib/ScrolledList.py b/sys/lib/python/idlelib/ScrolledList.py deleted file mode 100644 index 921193657..000000000 --- a/sys/lib/python/idlelib/ScrolledList.py +++ /dev/null @@ -1,139 +0,0 @@ -from Tkinter import * - -class ScrolledList: - - default = "(None)" - - def __init__(self, master, **options): - # Create top frame, with scrollbar and listbox - self.master = master - self.frame = frame = Frame(master) - self.frame.pack(fill="both", expand=1) - self.vbar = vbar = Scrollbar(frame, name="vbar") - self.vbar.pack(side="right", fill="y") - self.listbox = listbox = Listbox(frame, exportselection=0, - background="white") - if options: - listbox.configure(options) - listbox.pack(expand=1, fill="both") - # Tie listbox and scrollbar together - vbar["command"] = listbox.yview - listbox["yscrollcommand"] = vbar.set - # Bind events to the list box - listbox.bind("<ButtonRelease-1>", self.click_event) - listbox.bind("<Double-ButtonRelease-1>", self.double_click_event) - listbox.bind("<ButtonPress-3>", self.popup_event) - listbox.bind("<Key-Up>", self.up_event) - listbox.bind("<Key-Down>", self.down_event) - # Mark as empty - self.clear() - - def close(self): - self.frame.destroy() - - def clear(self): - self.listbox.delete(0, "end") - self.empty = 1 - self.listbox.insert("end", self.default) - - def append(self, item): - if self.empty: - self.listbox.delete(0, "end") - self.empty = 0 - self.listbox.insert("end", str(item)) - - def get(self, index): - return self.listbox.get(index) - - def click_event(self, event): - self.listbox.activate("@%d,%d" % (event.x, event.y)) - index = self.listbox.index("active") - self.select(index) - self.on_select(index) - return "break" - - def double_click_event(self, event): - index = self.listbox.index("active") - self.select(index) - self.on_double(index) - return "break" - - menu = None - - def popup_event(self, event): - if not self.menu: - self.make_menu() - menu = self.menu - self.listbox.activate("@%d,%d" % (event.x, event.y)) - index = self.listbox.index("active") - self.select(index) - menu.tk_popup(event.x_root, event.y_root) - - def make_menu(self): - menu = Menu(self.listbox, tearoff=0) - self.menu = menu - self.fill_menu() - - def up_event(self, event): - index = self.listbox.index("active") - if self.listbox.selection_includes(index): - index = index - 1 - else: - index = self.listbox.size() - 1 - if index < 0: - self.listbox.bell() - else: - self.select(index) - self.on_select(index) - return "break" - - def down_event(self, event): - index = self.listbox.index("active") - if self.listbox.selection_includes(index): - index = index + 1 - else: - index = 0 - if index >= self.listbox.size(): - self.listbox.bell() - else: - self.select(index) - self.on_select(index) - return "break" - - def select(self, index): - self.listbox.focus_set() - self.listbox.activate(index) - self.listbox.selection_clear(0, "end") - self.listbox.selection_set(index) - self.listbox.see(index) - - # Methods to override for specific actions - - def fill_menu(self): - pass - - def on_select(self, index): - pass - - def on_double(self, index): - pass - - -def test(): - root = Tk() - root.protocol("WM_DELETE_WINDOW", root.destroy) - class MyScrolledList(ScrolledList): - def fill_menu(self): self.menu.add_command(label="pass") - def on_select(self, index): print "select", self.get(index) - def on_double(self, index): print "double", self.get(index) - s = MyScrolledList(root) - for i in range(30): - s.append("item %02d" % i) - return root - -def main(): - root = test() - root.mainloop() - -if __name__ == '__main__': - main() diff --git a/sys/lib/python/idlelib/SearchDialog.py b/sys/lib/python/idlelib/SearchDialog.py deleted file mode 100644 index d7124d67f..000000000 --- a/sys/lib/python/idlelib/SearchDialog.py +++ /dev/null @@ -1,68 +0,0 @@ -from Tkinter import * -import SearchEngine -from SearchDialogBase import SearchDialogBase - - -def _setup(text): - root = text._root() - engine = SearchEngine.get(root) - if not hasattr(engine, "_searchdialog"): - engine._searchdialog = SearchDialog(root, engine) - return engine._searchdialog - -def find(text): - pat = text.get("sel.first", "sel.last") - return _setup(text).open(text,pat) - -def find_again(text): - return _setup(text).find_again(text) - -def find_selection(text): - return _setup(text).find_selection(text) - -class SearchDialog(SearchDialogBase): - - def create_widgets(self): - f = SearchDialogBase.create_widgets(self) - self.make_button("Find", self.default_command, 1) - - def default_command(self, event=None): - if not self.engine.getprog(): - return - if self.find_again(self.text): - self.close() - - def find_again(self, text): - if not self.engine.getpat(): - self.open(text) - return False - if not self.engine.getprog(): - return False - res = self.engine.search_text(text) - if res: - line, m = res - i, j = m.span() - first = "%d.%d" % (line, i) - last = "%d.%d" % (line, j) - try: - selfirst = text.index("sel.first") - sellast = text.index("sel.last") - if selfirst == first and sellast == last: - text.bell() - return False - except TclError: - pass - text.tag_remove("sel", "1.0", "end") - text.tag_add("sel", first, last) - text.mark_set("insert", self.engine.isback() and first or last) - text.see("insert") - return True - else: - text.bell() - return False - - def find_selection(self, text): - pat = text.get("sel.first", "sel.last") - if pat: - self.engine.setcookedpat(pat) - return self.find_again(text) diff --git a/sys/lib/python/idlelib/SearchDialogBase.py b/sys/lib/python/idlelib/SearchDialogBase.py deleted file mode 100644 index f63e7ae37..000000000 --- a/sys/lib/python/idlelib/SearchDialogBase.py +++ /dev/null @@ -1,140 +0,0 @@ -from Tkinter import * - -class SearchDialogBase: - - title = "Search Dialog" - icon = "Search" - needwrapbutton = 1 - - def __init__(self, root, engine): - self.root = root - self.engine = engine - self.top = None - - def open(self, text, searchphrase=None): - self.text = text - if not self.top: - self.create_widgets() - else: - self.top.deiconify() - self.top.tkraise() - if searchphrase: - self.ent.delete(0,"end") - self.ent.insert("end",searchphrase) - self.ent.focus_set() - self.ent.selection_range(0, "end") - self.ent.icursor(0) - self.top.grab_set() - - def close(self, event=None): - if self.top: - self.top.grab_release() - self.top.withdraw() - - def create_widgets(self): - top = Toplevel(self.root) - top.bind("<Return>", self.default_command) - top.bind("<Escape>", self.close) - top.protocol("WM_DELETE_WINDOW", self.close) - top.wm_title(self.title) - top.wm_iconname(self.icon) - self.top = top - - self.row = 0 - self.top.grid_columnconfigure(0, pad=2, weight=0) - self.top.grid_columnconfigure(1, pad=2, minsize=100, weight=100) - - self.create_entries() - self.create_option_buttons() - self.create_other_buttons() - return self.create_command_buttons() - - def make_entry(self, label, var): - l = Label(self.top, text=label) - l.grid(row=self.row, column=0, sticky="nw") - e = Entry(self.top, textvariable=var, exportselection=0) - e.grid(row=self.row, column=1, sticky="nwe") - self.row = self.row + 1 - return e - - def make_frame(self,labeltext=None): - if labeltext: - l = Label(self.top, text=labeltext) - l.grid(row=self.row, column=0, sticky="nw") - f = Frame(self.top) - f.grid(row=self.row, column=1, columnspan=1, sticky="nwe") - self.row = self.row + 1 - return f - - def make_button(self, label, command, isdef=0): - b = Button(self.buttonframe, - text=label, command=command, - default=isdef and "active" or "normal") - cols,rows=self.buttonframe.grid_size() - b.grid(pady=1,row=rows,column=0,sticky="ew") - self.buttonframe.grid(rowspan=rows+1) - return b - - def create_entries(self): - self.ent = self.make_entry("Find:", self.engine.patvar) - - def create_option_buttons(self): - f = self.make_frame("Options") - - btn = Checkbutton(f, anchor="w", - variable=self.engine.revar, - text="Regular expression") - btn.pack(side="left", fill="both") - if self.engine.isre(): - btn.select() - - btn = Checkbutton(f, anchor="w", - variable=self.engine.casevar, - text="Match case") - btn.pack(side="left", fill="both") - if self.engine.iscase(): - btn.select() - - btn = Checkbutton(f, anchor="w", - variable=self.engine.wordvar, - text="Whole word") - btn.pack(side="left", fill="both") - if self.engine.isword(): - btn.select() - - if self.needwrapbutton: - btn = Checkbutton(f, anchor="w", - variable=self.engine.wrapvar, - text="Wrap around") - btn.pack(side="left", fill="both") - if self.engine.iswrap(): - btn.select() - - def create_other_buttons(self): - f = self.make_frame("Direction") - - #lbl = Label(f, text="Direction: ") - #lbl.pack(side="left") - - btn = Radiobutton(f, anchor="w", - variable=self.engine.backvar, value=1, - text="Up") - btn.pack(side="left", fill="both") - if self.engine.isback(): - btn.select() - - btn = Radiobutton(f, anchor="w", - variable=self.engine.backvar, value=0, - text="Down") - btn.pack(side="left", fill="both") - if not self.engine.isback(): - btn.select() - - def create_command_buttons(self): - # - # place button frame on the right - f = self.buttonframe = Frame(self.top) - f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2) - - b = self.make_button("close", self.close) - b.lower() diff --git a/sys/lib/python/idlelib/SearchEngine.py b/sys/lib/python/idlelib/SearchEngine.py deleted file mode 100644 index cc40a00c5..000000000 --- a/sys/lib/python/idlelib/SearchEngine.py +++ /dev/null @@ -1,220 +0,0 @@ -import re -from Tkinter import * -import tkMessageBox - -def get(root): - if not hasattr(root, "_searchengine"): - root._searchengine = SearchEngine(root) - # XXX This will never garbage-collect -- who cares - return root._searchengine - -class SearchEngine: - - def __init__(self, root): - self.root = root - # State shared by search, replace, and grep; - # the search dialogs bind these to UI elements. - self.patvar = StringVar(root) # search pattern - self.revar = BooleanVar(root) # regular expression? - self.casevar = BooleanVar(root) # match case? - self.wordvar = BooleanVar(root) # match whole word? - self.wrapvar = BooleanVar(root) # wrap around buffer? - self.wrapvar.set(1) # (on by default) - self.backvar = BooleanVar(root) # search backwards? - - # Access methods - - def getpat(self): - return self.patvar.get() - - def setpat(self, pat): - self.patvar.set(pat) - - def isre(self): - return self.revar.get() - - def iscase(self): - return self.casevar.get() - - def isword(self): - return self.wordvar.get() - - def iswrap(self): - return self.wrapvar.get() - - def isback(self): - return self.backvar.get() - - # Higher level access methods - - def getcookedpat(self): - pat = self.getpat() - if not self.isre(): - pat = re.escape(pat) - if self.isword(): - pat = r"\b%s\b" % pat - return pat - - def getprog(self): - pat = self.getpat() - if not pat: - self.report_error(pat, "Empty regular expression") - return None - pat = self.getcookedpat() - flags = 0 - if not self.iscase(): - flags = flags | re.IGNORECASE - try: - prog = re.compile(pat, flags) - except re.error, what: - try: - msg, col = what - except: - msg = str(what) - col = -1 - self.report_error(pat, msg, col) - return None - return prog - - def report_error(self, pat, msg, col=-1): - # Derived class could overrid this with something fancier - msg = "Error: " + str(msg) - if pat: - msg = msg + "\np\Pattern: " + str(pat) - if col >= 0: - msg = msg + "\nOffset: " + str(col) - tkMessageBox.showerror("Regular expression error", - msg, master=self.root) - - def setcookedpat(self, pat): - if self.isre(): - pat = re.escape(pat) - self.setpat(pat) - - def search_text(self, text, prog=None, ok=0): - """Search a text widget for the pattern. - - If prog is given, it should be the precompiled pattern. - Return a tuple (lineno, matchobj); None if not found. - - This obeys the wrap and direction (back) settings. - - The search starts at the selection (if there is one) or - at the insert mark (otherwise). If the search is forward, - it starts at the right of the selection; for a backward - search, it starts at the left end. An empty match exactly - at either end of the selection (or at the insert mark if - there is no selection) is ignored unless the ok flag is true - -- this is done to guarantee progress. - - If the search is allowed to wrap around, it will return the - original selection if (and only if) it is the only match. - - """ - if not prog: - prog = self.getprog() - if not prog: - return None # Compilation failed -- stop - wrap = self.wrapvar.get() - first, last = get_selection(text) - if self.isback(): - if ok: - start = last - else: - start = first - line, col = get_line_col(start) - res = self.search_backward(text, prog, line, col, wrap, ok) - else: - if ok: - start = first - else: - start = last - line, col = get_line_col(start) - res = self.search_forward(text, prog, line, col, wrap, ok) - return res - - def search_forward(self, text, prog, line, col, wrap, ok=0): - wrapped = 0 - startline = line - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - while chars: - m = prog.search(chars[:-1], col) - if m: - if ok or m.end() > col: - return line, m - line = line + 1 - if wrapped and line > startline: - break - col = 0 - ok = 1 - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - if not chars and wrap: - wrapped = 1 - wrap = 0 - line = 1 - chars = text.get("1.0", "2.0") - return None - - def search_backward(self, text, prog, line, col, wrap, ok=0): - wrapped = 0 - startline = line - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - while 1: - m = search_reverse(prog, chars[:-1], col) - if m: - if ok or m.start() < col: - return line, m - line = line - 1 - if wrapped and line < startline: - break - ok = 1 - if line <= 0: - if not wrap: - break - wrapped = 1 - wrap = 0 - pos = text.index("end-1c") - line, col = map(int, pos.split(".")) - chars = text.get("%d.0" % line, "%d.0" % (line+1)) - col = len(chars) - 1 - return None - -# Helper to search backwards in a string. -# (Optimized for the case where the pattern isn't found.) - -def search_reverse(prog, chars, col): - m = prog.search(chars) - if not m: - return None - found = None - i, j = m.span() - while i < col and j <= col: - found = m - if i == j: - j = j+1 - m = prog.search(chars, j) - if not m: - break - i, j = m.span() - return found - -# Helper to get selection end points, defaulting to insert mark. -# Return a tuple of indices ("line.col" strings). - -def get_selection(text): - try: - first = text.index("sel.first") - last = text.index("sel.last") - except TclError: - first = last = None - if not first: - first = text.index("insert") - if not last: - last = first - return first, last - -# Helper to parse a text index into a (line, col) tuple. - -def get_line_col(index): - line, col = map(int, index.split(".")) # Fails on invalid index - return line, col diff --git a/sys/lib/python/idlelib/StackViewer.py b/sys/lib/python/idlelib/StackViewer.py deleted file mode 100644 index 6b7730bcd..000000000 --- a/sys/lib/python/idlelib/StackViewer.py +++ /dev/null @@ -1,137 +0,0 @@ -import os -import sys -import linecache - -from TreeWidget import TreeNode, TreeItem, ScrolledCanvas -from ObjectBrowser import ObjectTreeItem, make_objecttreeitem - -def StackBrowser(root, flist=None, tb=None, top=None): - if top is None: - from Tkinter import Toplevel - top = Toplevel(root) - sc = ScrolledCanvas(top, bg="white", highlightthickness=0) - sc.frame.pack(expand=1, fill="both") - item = StackTreeItem(flist, tb) - node = TreeNode(sc.canvas, None, item) - node.expand() - -class StackTreeItem(TreeItem): - - def __init__(self, flist=None, tb=None): - self.flist = flist - self.stack = self.get_stack(tb) - self.text = self.get_exception() - - def get_stack(self, tb): - if tb is None: - tb = sys.last_traceback - stack = [] - if tb and tb.tb_frame is None: - tb = tb.tb_next - while tb is not None: - stack.append((tb.tb_frame, tb.tb_lineno)) - tb = tb.tb_next - return stack - - def get_exception(self): - type = sys.last_type - value = sys.last_value - if hasattr(type, "__name__"): - type = type.__name__ - s = str(type) - if value is not None: - s = s + ": " + str(value) - return s - - def GetText(self): - return self.text - - def GetSubList(self): - sublist = [] - for info in self.stack: - item = FrameTreeItem(info, self.flist) - sublist.append(item) - return sublist - -class FrameTreeItem(TreeItem): - - def __init__(self, info, flist): - self.info = info - self.flist = flist - - def GetText(self): - frame, lineno = self.info - try: - modname = frame.f_globals["__name__"] - except: - modname = "?" - code = frame.f_code - filename = code.co_filename - funcname = code.co_name - sourceline = linecache.getline(filename, lineno) - sourceline = sourceline.strip() - if funcname in ("?", "", None): - item = "%s, line %d: %s" % (modname, lineno, sourceline) - else: - item = "%s.%s(...), line %d: %s" % (modname, funcname, - lineno, sourceline) - return item - - def GetSubList(self): - frame, lineno = self.info - sublist = [] - if frame.f_globals is not frame.f_locals: - item = VariablesTreeItem("<locals>", frame.f_locals, self.flist) - sublist.append(item) - item = VariablesTreeItem("<globals>", frame.f_globals, self.flist) - sublist.append(item) - return sublist - - def OnDoubleClick(self): - if self.flist: - frame, lineno = self.info - filename = frame.f_code.co_filename - if os.path.isfile(filename): - self.flist.gotofileline(filename, lineno) - -class VariablesTreeItem(ObjectTreeItem): - - def GetText(self): - return self.labeltext - - def GetLabelText(self): - return None - - def IsExpandable(self): - return len(self.object) > 0 - - def keys(self): - return self.object.keys() - - def GetSubList(self): - sublist = [] - for key in self.keys(): - try: - value = self.object[key] - except KeyError: - continue - def setfunction(value, key=key, object=self.object): - object[key] = value - item = make_objecttreeitem(key + " =", value, setfunction) - sublist.append(item) - return sublist - - -def _test(): - try: - import testcode - reload(testcode) - except: - sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() - from Tkinter import Tk - root = Tk() - StackBrowser(None, top=root) - root.mainloop() - -if __name__ == "__main__": - _test() diff --git a/sys/lib/python/idlelib/TODO.txt b/sys/lib/python/idlelib/TODO.txt deleted file mode 100644 index e2f1ac0f2..000000000 --- a/sys/lib/python/idlelib/TODO.txt +++ /dev/null @@ -1,210 +0,0 @@ -Original IDLE todo, much of it now outdated: -============================================ -TO DO: - -- improve debugger: - - manage breakpoints globally, allow bp deletion, tbreak, cbreak etc. - - real object browser - - help on how to use it (a simple help button will do wonders) - - performance? (updates of large sets of locals are slow) - - better integration of "debug module" - - debugger should be global resource (attached to flist, not to shell) - - fix the stupid bug where you need to step twice - - display class name in stack viewer entries for methods - - suppress tracing through IDLE internals (e.g. print) DONE - - add a button to suppress through a specific module or class or method - - more object inspection to stack viewer, e.g. to view all array items -- insert the initial current directory into sys.path DONE -- default directory attribute for each window instead of only for windows - that have an associated filename -- command expansion from keywords, module contents, other buffers, etc. -- "Recent documents" menu item DONE -- Filter region command -- Optional horizontal scroll bar -- more Emacsisms: - - ^K should cut to buffer - - M-[, M-] to move by paragraphs - - incremental search? -- search should indicate wrap-around in some way -- restructure state sensitive code to avoid testing flags all the time -- persistent user state (e.g. window and cursor positions, bindings) -- make backups when saving -- check file mtimes at various points -- Pluggable interface with RCS/CVS/Perforce/Clearcase -- better help? -- don't open second class browser on same module (nor second path browser) -- unify class and path browsers -- Need to define a standard way whereby one can determine one is running - inside IDLE (needed for Tk mainloop, also handy for $PYTHONSTARTUP) -- Add more utility methods for use by extensions (a la get_selection) -- Way to run command in totally separate interpreter (fork+os.system?) DONE -- Way to find definition of fully-qualified name: - In other words, select "UserDict.UserDict", hit some magic key and - it loads up UserDict.py and finds the first def or class for UserDict. -- need a way to force colorization on/off -- need a way to force auto-indent on/off - -Details: - -- ^O (on Unix -- open-line) should honor autoindent -- after paste, show end of pasted text -- on Windows, should turn short filename to long filename (not only in argv!) - (shouldn't this be done -- or undone -- by ntpath.normpath?) -- new autoindent after colon even indents when the colon is in a comment! -- sometimes forward slashes in pathname remain -- sometimes star in window name remains in Windows menu -- With unix bindings, ESC by itself is ignored -- Sometimes for no apparent reason a selection from the cursor to the - end of the command buffer appears, which is hard to get rid of - because it stays when you are typing! -- The Line/Col in the status bar can be wrong initially in PyShell DONE - -Structural problems: - -- too much knowledge in FileList about EditorWindow (for example) -- should add some primitives for accessing the selection etc. - to repeat cumbersome code over and over - -====================================================================== - -Jeff Bauer suggests: - -- Open Module doesn't appear to handle hierarchical packages. -- Class browser should also allow hierarchical packages. -- Open and Open Module could benefit from a history, DONE - either command line style, or Microsoft recent-file - style. -- Add a Smalltalk-style inspector (i.e. Tkinspect) - -The last suggestion is already a reality, but not yet -integrated into IDLE. I use a module called inspector.py, -that used to be available from python.org(?) It no longer -appears to be in the contributed section, and the source -has no author attribution. - -In any case, the code is useful for visually navigating -an object's attributes, including its container hierarchy. - - >>> from inspector import Tkinspect - >>> Tkinspect(None, myObject) - -Tkinspect could probably be extended and refined to -integrate better into IDLE. - -====================================================================== - -Comparison to PTUI ------------------- - -+ PTUI's help is better (HTML!) - -+ PTUI can attach a shell to any module - -+ PTUI has some more I/O commands: - open multiple - append - examine (what's that?) - -====================================================================== - -Notes after trying to run Grail -------------------------------- - -- Grail does stuff to sys.path based on sys.argv[0]; you must set -sys.argv[0] to something decent first (it is normally set to the path of -the idle script). - -- Grail must be exec'ed in __main__ because that's imported by some -other parts of Grail. - -- Grail uses a module called History and so does idle :-( - -====================================================================== - -Robin Friedrich's items: - -Things I'd like to see: - - I'd like support for shift-click extending the selection. There's a - bug now that it doesn't work the first time you try it. - - Printing is needed. How hard can that be on Windows? FIRST CUT DONE - - The python-mode trick of autoindenting a line with <tab> is neat and - very handy. - - (someday) a spellchecker for docstrings and comments. - - a pagedown/up command key which moves to next class/def statement (top - level) - - split window capability - - DnD text relocation/copying - -Things I don't want to see. - - line numbers... will probably slow things down way too much. - - Please use another icon for the tree browser leaf. The small snake - isn't cutting it. - ----------------------------------------------------------------------- - -- Customizable views (multi-window or multi-pane). (Markus Gritsch) - -- Being able to double click (maybe double right click) on a callable -object in the editor which shows the source of the object, if -possible. (Gerrit Holl) - -- Hooks into the guts, like in Emacs. (Mike Romberg) - -- Sharing the editor with a remote tutor. (Martijn Faassen) - -- Multiple views on the same file. (Tony J Ibbs) - -- Store breakpoints in a global (per-project) database (GvR); Dirk -Heise adds: save some space-trimmed context and search around when -reopening a file that might have been edited by someone else. - -- Capture menu events in extensions without changing the IDLE source. -(Matthias Barmeier) - -- Use overlapping panels (a "notebook" in MFC terms I think) for info -that doesn't need to be accessible simultaneously (e.g. HTML source -and output). Use multi-pane windows for info that does need to be -shown together (e.g. class browser and source). (Albert Brandl) - -- A project should invisibly track all symbols, for instant search, -replace and cross-ref. Projects should be allowed to span multiple -directories, hosts, etc. Project management files are placed in a -directory you specify. A global mapping between project names and -project directories should exist [not so sure --GvR]. (Tim Peters) - -- Merge attr-tips and auto-expand. (Mark Hammond, Tim Peters) - -- Python Shell should behave more like a "shell window" as users know -it -- i.e. you can only edit the current command, and the cursor can't -escape from the command area. (Albert Brandl) - -- Set X11 class to "idle/Idle", set icon and title to something -beginning with "idle" -- for window manangers. (Randall Hopper) - -- Config files editable through a preferences dialog. (me) DONE - -- Config files still editable outside the preferences dialog. -(Randall Hopper) DONE - -- When you're editing a command in PyShell, and there are only blank -lines below the cursor, hitting Return should ignore or delete those -blank lines rather than deciding you're not on the last line. (me) - -- Run command (F5 c.s.) should be more like Pythonwin's Run -- a -dialog with options to give command line arguments, run the debugger, -etc. (me) - -- Shouldn't be able to delete part of the prompt (or any text before -it) in the PyShell. (Martijn Faassen) DONE - -- Emacs style auto-fill (also smart about comments and strings). -(Jeremy Hylton) - -- Output of Run Script should go to a separate output window, not to -the shell window. Output of separate runs should all go to the same -window but clearly delimited. (David Scherer) REJECT FIRST, LATTER DONE - -- GUI form designer to kick VB's butt. (Robert Geiger) THAT'S NOT IDLE - -- Printing! Possibly via generation of PDF files which the user must -then send to the printer separately. (Dinu Gherman) FIRST CUT diff --git a/sys/lib/python/idlelib/ToolTip.py b/sys/lib/python/idlelib/ToolTip.py deleted file mode 100644 index ce7a3d3ee..000000000 --- a/sys/lib/python/idlelib/ToolTip.py +++ /dev/null @@ -1,89 +0,0 @@ -# general purpose 'tooltip' routines - currently unused in idlefork -# (although the 'calltips' extension is partly based on this code) -# may be useful for some purposes in (or almost in ;) the current project scope -# Ideas gleaned from PySol - -from Tkinter import * - -class ToolTipBase: - - def __init__(self, button): - self.button = button - self.tipwindow = None - self.id = None - self.x = self.y = 0 - self._id1 = self.button.bind("<Enter>", self.enter) - self._id2 = self.button.bind("<Leave>", self.leave) - self._id3 = self.button.bind("<ButtonPress>", self.leave) - - def enter(self, event=None): - self.schedule() - - def leave(self, event=None): - self.unschedule() - self.hidetip() - - def schedule(self): - self.unschedule() - self.id = self.button.after(1500, self.showtip) - - def unschedule(self): - id = self.id - self.id = None - if id: - self.button.after_cancel(id) - - def showtip(self): - if self.tipwindow: - return - # The tip window must be completely outside the button; - # otherwise when the mouse enters the tip window we get - # a leave event and it disappears, and then we get an enter - # event and it reappears, and so on forever :-( - x = self.button.winfo_rootx() + 20 - y = self.button.winfo_rooty() + self.button.winfo_height() + 1 - self.tipwindow = tw = Toplevel(self.button) - tw.wm_overrideredirect(1) - tw.wm_geometry("+%d+%d" % (x, y)) - self.showcontents() - - def showcontents(self, text="Your text here"): - # Override this in derived class - label = Label(self.tipwindow, text=text, justify=LEFT, - background="#ffffe0", relief=SOLID, borderwidth=1) - label.pack() - - def hidetip(self): - tw = self.tipwindow - self.tipwindow = None - if tw: - tw.destroy() - -class ToolTip(ToolTipBase): - def __init__(self, button, text): - ToolTipBase.__init__(self, button) - self.text = text - def showcontents(self): - ToolTipBase.showcontents(self, self.text) - -class ListboxToolTip(ToolTipBase): - def __init__(self, button, items): - ToolTipBase.__init__(self, button) - self.items = items - def showcontents(self): - listbox = Listbox(self.tipwindow, background="#ffffe0") - listbox.pack() - for item in self.items: - listbox.insert(END, item) - -def main(): - # Test code - root = Tk() - b = Button(root, text="Hello", command=root.destroy) - b.pack() - root.update() - tip = ListboxToolTip(b, ["Hello", "world"]) - root.mainloop() - -if __name__ == '__main__': - main() diff --git a/sys/lib/python/idlelib/TreeWidget.py b/sys/lib/python/idlelib/TreeWidget.py deleted file mode 100644 index c5c171fb8..000000000 --- a/sys/lib/python/idlelib/TreeWidget.py +++ /dev/null @@ -1,478 +0,0 @@ -# XXX TO DO: -# - popup menu -# - support partial or total redisplay -# - key bindings (instead of quick-n-dirty bindings on Canvas): -# - up/down arrow keys to move focus around -# - ditto for page up/down, home/end -# - left/right arrows to expand/collapse & move out/in -# - more doc strings -# - add icons for "file", "module", "class", "method"; better "python" icon -# - callback for selection??? -# - multiple-item selection -# - tooltips -# - redo geometry without magic numbers -# - keep track of object ids to allow more careful cleaning -# - optimize tree redraw after expand of subnode - -import os -import sys -from Tkinter import * -import imp - -import ZoomHeight -from configHandler import idleConf - -ICONDIR = "Icons" - -# Look for Icons subdirectory in the same directory as this module -try: - _icondir = os.path.join(os.path.dirname(__file__), ICONDIR) -except NameError: - _icondir = ICONDIR -if os.path.isdir(_icondir): - ICONDIR = _icondir -elif not os.path.isdir(ICONDIR): - raise RuntimeError, "can't find icon directory (%r)" % (ICONDIR,) - -def listicons(icondir=ICONDIR): - """Utility to display the available icons.""" - root = Tk() - import glob - list = glob.glob(os.path.join(icondir, "*.gif")) - list.sort() - images = [] - row = column = 0 - for file in list: - name = os.path.splitext(os.path.basename(file))[0] - image = PhotoImage(file=file, master=root) - images.append(image) - label = Label(root, image=image, bd=1, relief="raised") - label.grid(row=row, column=column) - label = Label(root, text=name) - label.grid(row=row+1, column=column) - column = column + 1 - if column >= 10: - row = row+2 - column = 0 - root.images = images - - -class TreeNode: - - def __init__(self, canvas, parent, item): - self.canvas = canvas - self.parent = parent - self.item = item - self.state = 'collapsed' - self.selected = False - self.children = [] - self.x = self.y = None - self.iconimages = {} # cache of PhotoImage instances for icons - - def destroy(self): - for c in self.children[:]: - self.children.remove(c) - c.destroy() - self.parent = None - - def geticonimage(self, name): - try: - return self.iconimages[name] - except KeyError: - pass - file, ext = os.path.splitext(name) - ext = ext or ".gif" - fullname = os.path.join(ICONDIR, file + ext) - image = PhotoImage(master=self.canvas, file=fullname) - self.iconimages[name] = image - return image - - def select(self, event=None): - if self.selected: - return - self.deselectall() - self.selected = True - self.canvas.delete(self.image_id) - self.drawicon() - self.drawtext() - - def deselect(self, event=None): - if not self.selected: - return - self.selected = False - self.canvas.delete(self.image_id) - self.drawicon() - self.drawtext() - - def deselectall(self): - if self.parent: - self.parent.deselectall() - else: - self.deselecttree() - - def deselecttree(self): - if self.selected: - self.deselect() - for child in self.children: - child.deselecttree() - - def flip(self, event=None): - if self.state == 'expanded': - self.collapse() - else: - self.expand() - self.item.OnDoubleClick() - return "break" - - def expand(self, event=None): - if not self.item._IsExpandable(): - return - if self.state != 'expanded': - self.state = 'expanded' - self.update() - self.view() - - def collapse(self, event=None): - if self.state != 'collapsed': - self.state = 'collapsed' - self.update() - - def view(self): - top = self.y - 2 - bottom = self.lastvisiblechild().y + 17 - height = bottom - top - visible_top = self.canvas.canvasy(0) - visible_height = self.canvas.winfo_height() - visible_bottom = self.canvas.canvasy(visible_height) - if visible_top <= top and bottom <= visible_bottom: - return - x0, y0, x1, y1 = self.canvas._getints(self.canvas['scrollregion']) - if top >= visible_top and height <= visible_height: - fraction = top + height - visible_height - else: - fraction = top - fraction = float(fraction) / y1 - self.canvas.yview_moveto(fraction) - - def lastvisiblechild(self): - if self.children and self.state == 'expanded': - return self.children[-1].lastvisiblechild() - else: - return self - - def update(self): - if self.parent: - self.parent.update() - else: - oldcursor = self.canvas['cursor'] - self.canvas['cursor'] = "watch" - self.canvas.update() - self.canvas.delete(ALL) # XXX could be more subtle - self.draw(7, 2) - x0, y0, x1, y1 = self.canvas.bbox(ALL) - self.canvas.configure(scrollregion=(0, 0, x1, y1)) - self.canvas['cursor'] = oldcursor - - def draw(self, x, y): - # XXX This hard-codes too many geometry constants! - self.x, self.y = x, y - self.drawicon() - self.drawtext() - if self.state != 'expanded': - return y+17 - # draw children - if not self.children: - sublist = self.item._GetSubList() - if not sublist: - # _IsExpandable() was mistaken; that's allowed - return y+17 - for item in sublist: - child = self.__class__(self.canvas, self, item) - self.children.append(child) - cx = x+20 - cy = y+17 - cylast = 0 - for child in self.children: - cylast = cy - self.canvas.create_line(x+9, cy+7, cx, cy+7, fill="gray50") - cy = child.draw(cx, cy) - if child.item._IsExpandable(): - if child.state == 'expanded': - iconname = "minusnode" - callback = child.collapse - else: - iconname = "plusnode" - callback = child.expand - image = self.geticonimage(iconname) - id = self.canvas.create_image(x+9, cylast+7, image=image) - # XXX This leaks bindings until canvas is deleted: - self.canvas.tag_bind(id, "<1>", callback) - self.canvas.tag_bind(id, "<Double-1>", lambda x: None) - id = self.canvas.create_line(x+9, y+10, x+9, cylast+7, - ##stipple="gray50", # XXX Seems broken in Tk 8.0.x - fill="gray50") - self.canvas.tag_lower(id) # XXX .lower(id) before Python 1.5.2 - return cy - - def drawicon(self): - if self.selected: - imagename = (self.item.GetSelectedIconName() or - self.item.GetIconName() or - "openfolder") - else: - imagename = self.item.GetIconName() or "folder" - image = self.geticonimage(imagename) - id = self.canvas.create_image(self.x, self.y, anchor="nw", image=image) - self.image_id = id - self.canvas.tag_bind(id, "<1>", self.select) - self.canvas.tag_bind(id, "<Double-1>", self.flip) - - def drawtext(self): - textx = self.x+20-1 - texty = self.y-1 - labeltext = self.item.GetLabelText() - if labeltext: - id = self.canvas.create_text(textx, texty, anchor="nw", - text=labeltext) - self.canvas.tag_bind(id, "<1>", self.select) - self.canvas.tag_bind(id, "<Double-1>", self.flip) - x0, y0, x1, y1 = self.canvas.bbox(id) - textx = max(x1, 200) + 10 - text = self.item.GetText() or "<no text>" - try: - self.entry - except AttributeError: - pass - else: - self.edit_finish() - try: - label = self.label - except AttributeError: - # padding carefully selected (on Windows) to match Entry widget: - self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) - theme = idleConf.GetOption('main','Theme','name') - if self.selected: - self.label.configure(idleConf.GetHighlight(theme, 'hilite')) - else: - self.label.configure(idleConf.GetHighlight(theme, 'normal')) - id = self.canvas.create_window(textx, texty, - anchor="nw", window=self.label) - self.label.bind("<1>", self.select_or_edit) - self.label.bind("<Double-1>", self.flip) - self.text_id = id - - def select_or_edit(self, event=None): - if self.selected and self.item.IsEditable(): - self.edit(event) - else: - self.select(event) - - def edit(self, event=None): - self.entry = Entry(self.label, bd=0, highlightthickness=1, width=0) - self.entry.insert(0, self.label['text']) - self.entry.selection_range(0, END) - self.entry.pack(ipadx=5) - self.entry.focus_set() - self.entry.bind("<Return>", self.edit_finish) - self.entry.bind("<Escape>", self.edit_cancel) - - def edit_finish(self, event=None): - try: - entry = self.entry - del self.entry - except AttributeError: - return - text = entry.get() - entry.destroy() - if text and text != self.item.GetText(): - self.item.SetText(text) - text = self.item.GetText() - self.label['text'] = text - self.drawtext() - self.canvas.focus_set() - - def edit_cancel(self, event=None): - try: - entry = self.entry - del self.entry - except AttributeError: - return - entry.destroy() - self.drawtext() - self.canvas.focus_set() - - -class TreeItem: - - """Abstract class representing tree items. - - Methods should typically be overridden, otherwise a default action - is used. - - """ - - def __init__(self): - """Constructor. Do whatever you need to do.""" - - def GetText(self): - """Return text string to display.""" - - def GetLabelText(self): - """Return label text string to display in front of text (if any).""" - - expandable = None - - def _IsExpandable(self): - """Do not override! Called by TreeNode.""" - if self.expandable is None: - self.expandable = self.IsExpandable() - return self.expandable - - def IsExpandable(self): - """Return whether there are subitems.""" - return 1 - - def _GetSubList(self): - """Do not override! Called by TreeNode.""" - if not self.IsExpandable(): - return [] - sublist = self.GetSubList() - if not sublist: - self.expandable = 0 - return sublist - - def IsEditable(self): - """Return whether the item's text may be edited.""" - - def SetText(self, text): - """Change the item's text (if it is editable).""" - - def GetIconName(self): - """Return name of icon to be displayed normally.""" - - def GetSelectedIconName(self): - """Return name of icon to be displayed when selected.""" - - def GetSubList(self): - """Return list of items forming sublist.""" - - def OnDoubleClick(self): - """Called on a double-click on the item.""" - - -# Example application - -class FileTreeItem(TreeItem): - - """Example TreeItem subclass -- browse the file system.""" - - def __init__(self, path): - self.path = path - - def GetText(self): - return os.path.basename(self.path) or self.path - - def IsEditable(self): - return os.path.basename(self.path) != "" - - def SetText(self, text): - newpath = os.path.dirname(self.path) - newpath = os.path.join(newpath, text) - if os.path.dirname(newpath) != os.path.dirname(self.path): - return - try: - os.rename(self.path, newpath) - self.path = newpath - except os.error: - pass - - def GetIconName(self): - if not self.IsExpandable(): - return "python" # XXX wish there was a "file" icon - - def IsExpandable(self): - return os.path.isdir(self.path) - - def GetSubList(self): - try: - names = os.listdir(self.path) - except os.error: - return [] - names.sort(lambda a, b: cmp(os.path.normcase(a), os.path.normcase(b))) - sublist = [] - for name in names: - item = FileTreeItem(os.path.join(self.path, name)) - sublist.append(item) - return sublist - - -# A canvas widget with scroll bars and some useful bindings - -class ScrolledCanvas: - def __init__(self, master, **opts): - if not opts.has_key('yscrollincrement'): - opts['yscrollincrement'] = 17 - self.master = master - self.frame = Frame(master) - self.frame.rowconfigure(0, weight=1) - self.frame.columnconfigure(0, weight=1) - self.canvas = Canvas(self.frame, **opts) - self.canvas.grid(row=0, column=0, sticky="nsew") - self.vbar = Scrollbar(self.frame, name="vbar") - self.vbar.grid(row=0, column=1, sticky="nse") - self.hbar = Scrollbar(self.frame, name="hbar", orient="horizontal") - self.hbar.grid(row=1, column=0, sticky="ews") - self.canvas['yscrollcommand'] = self.vbar.set - self.vbar['command'] = self.canvas.yview - self.canvas['xscrollcommand'] = self.hbar.set - self.hbar['command'] = self.canvas.xview - self.canvas.bind("<Key-Prior>", self.page_up) - self.canvas.bind("<Key-Next>", self.page_down) - self.canvas.bind("<Key-Up>", self.unit_up) - self.canvas.bind("<Key-Down>", self.unit_down) - #if isinstance(master, Toplevel) or isinstance(master, Tk): - self.canvas.bind("<Alt-Key-2>", self.zoom_height) - self.canvas.focus_set() - def page_up(self, event): - self.canvas.yview_scroll(-1, "page") - return "break" - def page_down(self, event): - self.canvas.yview_scroll(1, "page") - return "break" - def unit_up(self, event): - self.canvas.yview_scroll(-1, "unit") - return "break" - def unit_down(self, event): - self.canvas.yview_scroll(1, "unit") - return "break" - def zoom_height(self, event): - ZoomHeight.zoom_height(self.master) - return "break" - - -# Testing functions - -def test(): - import PyShell - root = Toplevel(PyShell.root) - root.configure(bd=0, bg="yellow") - root.focus_set() - sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1) - sc.frame.pack(expand=1, fill="both") - item = FileTreeItem("C:/windows/desktop") - node = TreeNode(sc.canvas, None, item) - node.expand() - -def test2(): - # test w/o scrolling canvas - root = Tk() - root.configure(bd=0) - canvas = Canvas(root, bg="white", highlightthickness=0) - canvas.pack(expand=1, fill="both") - item = FileTreeItem(os.curdir) - node = TreeNode(canvas, None, item) - node.update() - canvas.focus_set() - -if __name__ == '__main__': - test() diff --git a/sys/lib/python/idlelib/UndoDelegator.py b/sys/lib/python/idlelib/UndoDelegator.py deleted file mode 100644 index 182a1170e..000000000 --- a/sys/lib/python/idlelib/UndoDelegator.py +++ /dev/null @@ -1,352 +0,0 @@ -import sys -import string -from Tkinter import * -from Delegator import Delegator - -#$ event <<redo>> -#$ win <Control-y> -#$ unix <Alt-z> - -#$ event <<undo>> -#$ win <Control-z> -#$ unix <Control-z> - -#$ event <<dump-undo-state>> -#$ win <Control-backslash> -#$ unix <Control-backslash> - - -class UndoDelegator(Delegator): - - max_undo = 1000 - - def __init__(self): - Delegator.__init__(self) - self.reset_undo() - - def setdelegate(self, delegate): - if self.delegate is not None: - self.unbind("<<undo>>") - self.unbind("<<redo>>") - self.unbind("<<dump-undo-state>>") - Delegator.setdelegate(self, delegate) - if delegate is not None: - self.bind("<<undo>>", self.undo_event) - self.bind("<<redo>>", self.redo_event) - self.bind("<<dump-undo-state>>", self.dump_event) - - def dump_event(self, event): - from pprint import pprint - pprint(self.undolist[:self.pointer]) - print "pointer:", self.pointer, - print "saved:", self.saved, - print "can_merge:", self.can_merge, - print "get_saved():", self.get_saved() - pprint(self.undolist[self.pointer:]) - return "break" - - def reset_undo(self): - self.was_saved = -1 - self.pointer = 0 - self.undolist = [] - self.undoblock = 0 # or a CommandSequence instance - self.set_saved(1) - - def set_saved(self, flag): - if flag: - self.saved = self.pointer - else: - self.saved = -1 - self.can_merge = False - self.check_saved() - - def get_saved(self): - return self.saved == self.pointer - - saved_change_hook = None - - def set_saved_change_hook(self, hook): - self.saved_change_hook = hook - - was_saved = -1 - - def check_saved(self): - is_saved = self.get_saved() - if is_saved != self.was_saved: - self.was_saved = is_saved - if self.saved_change_hook: - self.saved_change_hook() - - def insert(self, index, chars, tags=None): - self.addcmd(InsertCommand(index, chars, tags)) - - def delete(self, index1, index2=None): - self.addcmd(DeleteCommand(index1, index2)) - - # Clients should call undo_block_start() and undo_block_stop() - # around a sequence of editing cmds to be treated as a unit by - # undo & redo. Nested matching calls are OK, and the inner calls - # then act like nops. OK too if no editing cmds, or only one - # editing cmd, is issued in between: if no cmds, the whole - # sequence has no effect; and if only one cmd, that cmd is entered - # directly into the undo list, as if undo_block_xxx hadn't been - # called. The intent of all that is to make this scheme easy - # to use: all the client has to worry about is making sure each - # _start() call is matched by a _stop() call. - - def undo_block_start(self): - if self.undoblock == 0: - self.undoblock = CommandSequence() - self.undoblock.bump_depth() - - def undo_block_stop(self): - if self.undoblock.bump_depth(-1) == 0: - cmd = self.undoblock - self.undoblock = 0 - if len(cmd) > 0: - if len(cmd) == 1: - # no need to wrap a single cmd - cmd = cmd.getcmd(0) - # this blk of cmds, or single cmd, has already - # been done, so don't execute it again - self.addcmd(cmd, 0) - - def addcmd(self, cmd, execute=True): - if execute: - cmd.do(self.delegate) - if self.undoblock != 0: - self.undoblock.append(cmd) - return - if self.can_merge and self.pointer > 0: - lastcmd = self.undolist[self.pointer-1] - if lastcmd.merge(cmd): - return - self.undolist[self.pointer:] = [cmd] - if self.saved > self.pointer: - self.saved = -1 - self.pointer = self.pointer + 1 - if len(self.undolist) > self.max_undo: - ##print "truncating undo list" - del self.undolist[0] - self.pointer = self.pointer - 1 - if self.saved >= 0: - self.saved = self.saved - 1 - self.can_merge = True - self.check_saved() - - def undo_event(self, event): - if self.pointer == 0: - self.bell() - return "break" - cmd = self.undolist[self.pointer - 1] - cmd.undo(self.delegate) - self.pointer = self.pointer - 1 - self.can_merge = False - self.check_saved() - return "break" - - def redo_event(self, event): - if self.pointer >= len(self.undolist): - self.bell() - return "break" - cmd = self.undolist[self.pointer] - cmd.redo(self.delegate) - self.pointer = self.pointer + 1 - self.can_merge = False - self.check_saved() - return "break" - - -class Command: - - # Base class for Undoable commands - - tags = None - - def __init__(self, index1, index2, chars, tags=None): - self.marks_before = {} - self.marks_after = {} - self.index1 = index1 - self.index2 = index2 - self.chars = chars - if tags: - self.tags = tags - - def __repr__(self): - s = self.__class__.__name__ - t = (self.index1, self.index2, self.chars, self.tags) - if self.tags is None: - t = t[:-1] - return s + repr(t) - - def do(self, text): - pass - - def redo(self, text): - pass - - def undo(self, text): - pass - - def merge(self, cmd): - return 0 - - def save_marks(self, text): - marks = {} - for name in text.mark_names(): - if name != "insert" and name != "current": - marks[name] = text.index(name) - return marks - - def set_marks(self, text, marks): - for name, index in marks.items(): - text.mark_set(name, index) - - -class InsertCommand(Command): - - # Undoable insert command - - def __init__(self, index1, chars, tags=None): - Command.__init__(self, index1, None, chars, tags) - - def do(self, text): - self.marks_before = self.save_marks(text) - self.index1 = text.index(self.index1) - if text.compare(self.index1, ">", "end-1c"): - # Insert before the final newline - self.index1 = text.index("end-1c") - text.insert(self.index1, self.chars, self.tags) - self.index2 = text.index("%s+%dc" % (self.index1, len(self.chars))) - self.marks_after = self.save_marks(text) - ##sys.__stderr__.write("do: %s\n" % self) - - def redo(self, text): - text.mark_set('insert', self.index1) - text.insert(self.index1, self.chars, self.tags) - self.set_marks(text, self.marks_after) - text.see('insert') - ##sys.__stderr__.write("redo: %s\n" % self) - - def undo(self, text): - text.mark_set('insert', self.index1) - text.delete(self.index1, self.index2) - self.set_marks(text, self.marks_before) - text.see('insert') - ##sys.__stderr__.write("undo: %s\n" % self) - - def merge(self, cmd): - if self.__class__ is not cmd.__class__: - return False - if self.index2 != cmd.index1: - return False - if self.tags != cmd.tags: - return False - if len(cmd.chars) != 1: - return False - if self.chars and \ - self.classify(self.chars[-1]) != self.classify(cmd.chars): - return False - self.index2 = cmd.index2 - self.chars = self.chars + cmd.chars - return True - - alphanumeric = string.ascii_letters + string.digits + "_" - - def classify(self, c): - if c in self.alphanumeric: - return "alphanumeric" - if c == "\n": - return "newline" - return "punctuation" - - -class DeleteCommand(Command): - - # Undoable delete command - - def __init__(self, index1, index2=None): - Command.__init__(self, index1, index2, None, None) - - def do(self, text): - self.marks_before = self.save_marks(text) - self.index1 = text.index(self.index1) - if self.index2: - self.index2 = text.index(self.index2) - else: - self.index2 = text.index(self.index1 + " +1c") - if text.compare(self.index2, ">", "end-1c"): - # Don't delete the final newline - self.index2 = text.index("end-1c") - self.chars = text.get(self.index1, self.index2) - text.delete(self.index1, self.index2) - self.marks_after = self.save_marks(text) - ##sys.__stderr__.write("do: %s\n" % self) - - def redo(self, text): - text.mark_set('insert', self.index1) - text.delete(self.index1, self.index2) - self.set_marks(text, self.marks_after) - text.see('insert') - ##sys.__stderr__.write("redo: %s\n" % self) - - def undo(self, text): - text.mark_set('insert', self.index1) - text.insert(self.index1, self.chars) - self.set_marks(text, self.marks_before) - text.see('insert') - ##sys.__stderr__.write("undo: %s\n" % self) - -class CommandSequence(Command): - - # Wrapper for a sequence of undoable cmds to be undone/redone - # as a unit - - def __init__(self): - self.cmds = [] - self.depth = 0 - - def __repr__(self): - s = self.__class__.__name__ - strs = [] - for cmd in self.cmds: - strs.append(" %r" % (cmd,)) - return s + "(\n" + ",\n".join(strs) + "\n)" - - def __len__(self): - return len(self.cmds) - - def append(self, cmd): - self.cmds.append(cmd) - - def getcmd(self, i): - return self.cmds[i] - - def redo(self, text): - for cmd in self.cmds: - cmd.redo(text) - - def undo(self, text): - cmds = self.cmds[:] - cmds.reverse() - for cmd in cmds: - cmd.undo(text) - - def bump_depth(self, incr=1): - self.depth = self.depth + incr - return self.depth - -def main(): - from Percolator import Percolator - root = Tk() - root.wm_protocol("WM_DELETE_WINDOW", root.quit) - text = Text() - text.pack() - text.focus_set() - p = Percolator(text) - d = UndoDelegator() - p.insertfilter(d) - root.mainloop() - -if __name__ == "__main__": - main() diff --git a/sys/lib/python/idlelib/WidgetRedirector.py b/sys/lib/python/idlelib/WidgetRedirector.py deleted file mode 100644 index df60cea4f..000000000 --- a/sys/lib/python/idlelib/WidgetRedirector.py +++ /dev/null @@ -1,92 +0,0 @@ -from Tkinter import * - - -class WidgetRedirector: - - """Support for redirecting arbitrary widget subcommands.""" - - def __init__(self, widget): - self.dict = {} - self.widget = widget - self.tk = tk = widget.tk - w = widget._w - self.orig = w + "_orig" - tk.call("rename", w, self.orig) - tk.createcommand(w, self.dispatch) - - def __repr__(self): - return "WidgetRedirector(%s<%s>)" % (self.widget.__class__.__name__, - self.widget._w) - - def close(self): - for name in self.dict.keys(): - self.unregister(name) - widget = self.widget; del self.widget - orig = self.orig; del self.orig - tk = widget.tk - w = widget._w - tk.deletecommand(w) - tk.call("rename", orig, w) - - def register(self, name, function): - if self.dict.has_key(name): - previous = dict[name] - else: - previous = OriginalCommand(self, name) - self.dict[name] = function - setattr(self.widget, name, function) - return previous - - def unregister(self, name): - if self.dict.has_key(name): - function = self.dict[name] - del self.dict[name] - if hasattr(self.widget, name): - delattr(self.widget, name) - return function - else: - return None - - def dispatch(self, cmd, *args): - m = self.dict.get(cmd) - try: - if m: - return m(*args) - else: - return self.tk.call((self.orig, cmd) + args) - except TclError: - return "" - - -class OriginalCommand: - - def __init__(self, redir, name): - self.redir = redir - self.name = name - self.tk = redir.tk - self.orig = redir.orig - self.tk_call = self.tk.call - self.orig_and_name = (self.orig, self.name) - - def __repr__(self): - return "OriginalCommand(%r, %r)" % (self.redir, self.name) - - def __call__(self, *args): - return self.tk_call(self.orig_and_name + args) - - -def main(): - root = Tk() - text = Text() - text.pack() - text.focus_set() - redir = WidgetRedirector(text) - global orig_insert - def my_insert(*args): - print "insert", args - orig_insert(*args) - orig_insert = redir.register("insert", my_insert) - root.mainloop() - -if __name__ == "__main__": - main() diff --git a/sys/lib/python/idlelib/WindowList.py b/sys/lib/python/idlelib/WindowList.py deleted file mode 100644 index 658502b20..000000000 --- a/sys/lib/python/idlelib/WindowList.py +++ /dev/null @@ -1,90 +0,0 @@ -from Tkinter import * - -class WindowList: - - def __init__(self): - self.dict = {} - self.callbacks = [] - - def add(self, window): - window.after_idle(self.call_callbacks) - self.dict[str(window)] = window - - def delete(self, window): - try: - del self.dict[str(window)] - except KeyError: - # Sometimes, destroy() is called twice - pass - self.call_callbacks() - - def add_windows_to_menu(self, menu): - list = [] - for key in self.dict.keys(): - window = self.dict[key] - try: - title = window.get_title() - except TclError: - continue - list.append((title, window)) - list.sort() - for title, window in list: - menu.add_command(label=title, command=window.wakeup) - - def register_callback(self, callback): - self.callbacks.append(callback) - - def unregister_callback(self, callback): - try: - self.callbacks.remove(callback) - except ValueError: - pass - - def call_callbacks(self): - for callback in self.callbacks: - try: - callback() - except: - print "warning: callback failed in WindowList", \ - sys.exc_type, ":", sys.exc_value - -registry = WindowList() - -add_windows_to_menu = registry.add_windows_to_menu -register_callback = registry.register_callback -unregister_callback = registry.unregister_callback - - -class ListedToplevel(Toplevel): - - def __init__(self, master, **kw): - Toplevel.__init__(self, master, kw) - registry.add(self) - self.focused_widget = self - - def destroy(self): - registry.delete(self) - Toplevel.destroy(self) - # If this is Idle's last window then quit the mainloop - # (Needed for clean exit on Windows 98) - if not registry.dict: - self.quit() - - def update_windowlist_registry(self, window): - registry.call_callbacks() - - def get_title(self): - # Subclass can override - return self.wm_title() - - def wakeup(self): - try: - if self.wm_state() == "iconic": - self.wm_withdraw() - self.wm_deiconify() - self.tkraise() - self.focused_widget.focus_set() - except TclError: - # This can happen when the window menu was torn off. - # Simply ignore it. - pass diff --git a/sys/lib/python/idlelib/ZoomHeight.py b/sys/lib/python/idlelib/ZoomHeight.py deleted file mode 100644 index 83ca3a697..000000000 --- a/sys/lib/python/idlelib/ZoomHeight.py +++ /dev/null @@ -1,50 +0,0 @@ -# Sample extension: zoom a window to maximum height - -import re -import sys -import macosxSupport - -class ZoomHeight: - - menudefs = [ - ('windows', [ - ('_Zoom Height', '<<zoom-height>>'), - ]) - ] - - def __init__(self, editwin): - self.editwin = editwin - - def zoom_height_event(self, event): - top = self.editwin.top - zoom_height(top) - -def zoom_height(top): - geom = top.wm_geometry() - m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) - if not m: - top.bell() - return - width, height, x, y = map(int, m.groups()) - newheight = top.winfo_screenheight() - if sys.platform == 'win32': - newy = 0 - newheight = newheight - 72 - - elif macosxSupport.runningAsOSXApp(): - # The '88' below is a magic number that avoids placing the bottom - # of the window below the panel on my machine. I don't know how - # to calculate the correct value for this with tkinter. - newy = 22 - newheight = newheight - newy - 88 - - else: - #newy = 24 - newy = 0 - #newheight = newheight - 96 - newheight = newheight - 88 - if height >= newheight: - newgeom = "" - else: - newgeom = "%dx%d+%d+%d" % (width, newheight, x, newy) - top.wm_geometry(newgeom) diff --git a/sys/lib/python/idlelib/__init__.py b/sys/lib/python/idlelib/__init__.py deleted file mode 100644 index 7a83ddea7..000000000 --- a/sys/lib/python/idlelib/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Dummy file to make this a package. diff --git a/sys/lib/python/idlelib/aboutDialog.py b/sys/lib/python/idlelib/aboutDialog.py deleted file mode 100644 index c1210612e..000000000 --- a/sys/lib/python/idlelib/aboutDialog.py +++ /dev/null @@ -1,163 +0,0 @@ -"""About Dialog for IDLE - -""" - -from Tkinter import * -import string, os -import textView -import idlever - -class AboutDialog(Toplevel): - """Modal about dialog for idle - - """ - def __init__(self,parent,title): - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("+%d+%d" % (parent.winfo_rootx()+30, - parent.winfo_rooty()+30)) - self.bg = "#707070" - self.fg = "#ffffff" - self.CreateWidgets() - self.resizable(height=FALSE, width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Ok) - self.parent = parent - self.buttonOk.focus_set() - self.bind('<Return>',self.Ok) #dismiss dialog - self.bind('<Escape>',self.Ok) #dismiss dialog - self.wait_window() - - def CreateWidgets(self): - frameMain = Frame(self, borderwidth=2, relief=SUNKEN) - frameButtons = Frame(self) - frameButtons.pack(side=BOTTOM, fill=X) - frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) - self.buttonOk = Button(frameButtons, text='Close', - command=self.Ok) - self.buttonOk.pack(padx=5, pady=5) - #self.picture = Image('photo', data=self.pictureData) - frameBg = Frame(frameMain, bg=self.bg) - frameBg.pack(expand=TRUE, fill=BOTH) - labelTitle = Label(frameBg, text='IDLE', fg=self.fg, bg=self.bg, - font=('courier', 24, 'bold')) - labelTitle.grid(row=0, column=0, sticky=W, padx=10, pady=10) - #labelPicture = Label(frameBg, text='[picture]') - #image=self.picture, bg=self.bg) - #labelPicture.grid(row=1, column=1, sticky=W, rowspan=2, - # padx=0, pady=3) - byline = "Python's Integrated DeveLopment Environment" + 5*'\n' - labelDesc = Label(frameBg, text=byline, justify=LEFT, - fg=self.fg, bg=self.bg) - labelDesc.grid(row=2, column=0, sticky=W, columnspan=3, padx=10, pady=5) - labelEmail = Label(frameBg, text='email: idle-dev@python.org', - justify=LEFT, fg=self.fg, bg=self.bg) - labelEmail.grid(row=6, column=0, columnspan=2, - sticky=W, padx=10, pady=0) - labelWWW = Label(frameBg, text='www: http://www.python.org/idle/', - justify=LEFT, fg=self.fg, bg=self.bg) - labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) - Frame(frameBg, borderwidth=1, relief=SUNKEN, - height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, - columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg, text='Python version: ' + \ - sys.version.split()[0], fg=self.fg, bg=self.bg) - labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) - # handle weird tk version num in windoze python >= 1.6 (?!?) - tkVer = repr(TkVersion).split('.') - tkVer[len(tkVer)-1] = str('%.3g' % (float('.'+tkVer[len(tkVer)-1])))[2:] - if tkVer[len(tkVer)-1] == '': - tkVer[len(tkVer)-1] = '0' - tkVer = string.join(tkVer,'.') - labelTkVer = Label(frameBg, text='Tk version: '+ - tkVer, fg=self.fg, bg=self.bg) - labelTkVer.grid(row=9, column=1, sticky=W, padx=2, pady=0) - py_button_f = Frame(frameBg, bg=self.bg) - py_button_f.grid(row=10, column=0, columnspan=2, sticky=NSEW) - buttonLicense = Button(py_button_f, text='License', width=8, - highlightbackground=self.bg, - command=self.ShowLicense) - buttonLicense.pack(side=LEFT, padx=10, pady=10) - buttonCopyright = Button(py_button_f, text='Copyright', width=8, - highlightbackground=self.bg, - command=self.ShowCopyright) - buttonCopyright.pack(side=LEFT, padx=10, pady=10) - buttonCredits = Button(py_button_f, text='Credits', width=8, - highlightbackground=self.bg, - command=self.ShowPythonCredits) - buttonCredits.pack(side=LEFT, padx=10, pady=10) - Frame(frameBg, borderwidth=1, relief=SUNKEN, - height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, - columnspan=3, padx=5, pady=5) - idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, - fg=self.fg, bg=self.bg) - idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) - idle_button_f = Frame(frameBg, bg=self.bg) - idle_button_f.grid(row=13, column=0, columnspan=3, sticky=NSEW) - idle_about_b = Button(idle_button_f, text='README', width=8, - highlightbackground=self.bg, - command=self.ShowIDLEAbout) - idle_about_b.pack(side=LEFT, padx=10, pady=10) - idle_news_b = Button(idle_button_f, text='NEWS', width=8, - highlightbackground=self.bg, - command=self.ShowIDLENEWS) - idle_news_b.pack(side=LEFT, padx=10, pady=10) - idle_credits_b = Button(idle_button_f, text='Credits', width=8, - highlightbackground=self.bg, - command=self.ShowIDLECredits) - idle_credits_b.pack(side=LEFT, padx=10, pady=10) - - def ShowLicense(self): - self.display_printer_text(license, 'About - License') - - def ShowCopyright(self): - self.display_printer_text(copyright, 'About - Copyright') - - def ShowPythonCredits(self): - self.display_printer_text(credits, 'About - Python Credits') - - def ShowIDLECredits(self): - self.ViewFile('About - Credits','CREDITS.txt', 'iso-8859-1') - - def ShowIDLEAbout(self): - self.ViewFile('About - Readme', 'README.txt') - - def ShowIDLENEWS(self): - self.ViewFile('About - NEWS', 'NEWS.txt') - - def display_printer_text(self, printer, title): - printer._Printer__setup() - data = '\n'.join(printer._Printer__lines) - textView.TextViewer(self, title, None, data) - - def ViewFile(self, viewTitle, viewFile, encoding=None): - fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), viewFile) - if encoding: - import codecs - try: - textFile = codecs.open(fn, 'r') - except IOError: - import tkMessageBox - tkMessageBox.showerror(title='File Load Error', - message='Unable to load file %r .' % (fn,), - parent=self) - return - else: - data = textFile.read() - else: - data = None - textView.TextViewer(self, viewTitle, fn, data=data) - - def Ok(self, event=None): - self.destroy() - -if __name__ == '__main__': - # test the dialog - root = Tk() - def run(): - import aboutDialog - aboutDialog.AboutDialog(root, 'About') - Button(root, text='Dialog', command=run).pack() - root.mainloop() diff --git a/sys/lib/python/idlelib/config-extensions.def b/sys/lib/python/idlelib/config-extensions.def deleted file mode 100644 index 2d5cf6822..000000000 --- a/sys/lib/python/idlelib/config-extensions.def +++ /dev/null @@ -1,88 +0,0 @@ -# config-extensions.def -# -# IDLE reads several config files to determine user preferences. This -# file is the default configuration file for IDLE extensions settings. -# -# Each extension must have at least one section, named after the extension -# module. This section must contain an 'enable' item (=1 to enable the -# extension, =0 to disable it), it may contain 'enable_editor' or 'enable_shell' -# items, to apply it only to editor/shell windows, and may also contain any -# other general configuration items for the extension. -# -# Each extension must define at least one section named ExtensionName_bindings -# or ExtensionName_cfgBindings. If present, ExtensionName_bindings defines -# virtual event bindings for the extension that are not user re-configurable. -# If present, ExtensionName_cfgBindings defines virtual event bindings for the -# extension that may be sensibly re-configured. -# -# If there are no keybindings for a menus' virtual events, include lines like -# <<toggle-code-context>>= (See [CodeContext], below.) -# -# Currently it is necessary to manually modify this file to change extension -# key bindings and default values. To customize, create -# ~/.idlerc/config-extensions.cfg and append the appropriate customized -# section(s). Those sections will override the defaults in this file. -# -# Note: If a keybinding is already in use when the extension is -# loaded, the extension's virtual event's keybinding will be set to ''. -# -# See config-keys.def for notes on specifying keys and extend.txt for -# information on creating IDLE extensions. - -[FormatParagraph] -enable=1 -[FormatParagraph_cfgBindings] -format-paragraph=<Alt-Key-q> - -[AutoExpand] -enable=1 -[AutoExpand_cfgBindings] -expand-word=<Alt-Key-slash> - -[ZoomHeight] -enable=1 -[ZoomHeight_cfgBindings] -zoom-height=<Alt-Key-2> - -[ScriptBinding] -enable=1 -[ScriptBinding_cfgBindings] -run-module=<Key-F5> -check-module=<Alt-Key-x> - -[CallTips] -enable=1 -[CallTips_cfgBindings] -force-open-calltip=<Control-Key-backslash> -[CallTips_bindings] -try-open-calltip=<KeyRelease-parenleft> -refresh-calltip=<KeyRelease-parenright> <KeyRelease-0> - -[ParenMatch] -enable=1 -style= expression -flash-delay= 500 -bell= 1 -[ParenMatch_cfgBindings] -flash-paren=<Control-Key-0> -[ParenMatch_bindings] -paren-closed=<KeyRelease-parenright> <KeyRelease-bracketright> <KeyRelease-braceright> - -[AutoComplete] -enable=1 -popupwait=2000 -[AutoComplete_cfgBindings] -force-open-completions=<Control-Key-space> -[AutoComplete_bindings] -autocomplete=<Key-Tab> -try-open-completions=<KeyRelease-period> <KeyRelease-slash> <KeyRelease-backslash> - -[CodeContext] -enable=1 -enable_shell=0 -numlines=3 -visible=0 -bgcolor=LightGray -fgcolor=Black -[CodeContext_bindings] -toggle-code-context= diff --git a/sys/lib/python/idlelib/config-highlight.def b/sys/lib/python/idlelib/config-highlight.def deleted file mode 100644 index 7d20f7824..000000000 --- a/sys/lib/python/idlelib/config-highlight.def +++ /dev/null @@ -1,64 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for idle highlight theme settings. - -[IDLE Classic] -normal-foreground= #000000 -normal-background= #ffffff -keyword-foreground= #ff7700 -keyword-background= #ffffff -builtin-foreground= #900090 -builtin-background= #ffffff -comment-foreground= #dd0000 -comment-background= #ffffff -string-foreground= #00aa00 -string-background= #ffffff -definition-foreground= #0000ff -definition-background= #ffffff -hilite-foreground= #000000 -hilite-background= gray -break-foreground= black -break-background= #ffff55 -hit-foreground= #ffffff -hit-background= #000000 -error-foreground= #000000 -error-background= #ff7777 -#cursor (only foreground can be set, restart IDLE) -cursor-foreground= black -#shell window -stdout-foreground= blue -stdout-background= #ffffff -stderr-foreground= red -stderr-background= #ffffff -console-foreground= #770000 -console-background= #ffffff - -[IDLE New] -normal-foreground= #000000 -normal-background= #ffffff -keyword-foreground= #ff7700 -keyword-background= #ffffff -builtin-foreground= #900090 -builtin-background= #ffffff -comment-foreground= #dd0000 -comment-background= #ffffff -string-foreground= #00aa00 -string-background= #ffffff -definition-foreground= #0000ff -definition-background= #ffffff -hilite-foreground= #000000 -hilite-background= gray -break-foreground= black -break-background= #ffff55 -hit-foreground= #ffffff -hit-background= #000000 -error-foreground= #000000 -error-background= #ff7777 -#cursor (only foreground can be set, restart IDLE) -cursor-foreground= black -#shell window -stdout-foreground= blue -stdout-background= #ffffff -stderr-foreground= red -stderr-background= #ffffff -console-foreground= #770000 -console-background= #ffffff diff --git a/sys/lib/python/idlelib/config-keys.def b/sys/lib/python/idlelib/config-keys.def deleted file mode 100644 index fb0aaf4dc..000000000 --- a/sys/lib/python/idlelib/config-keys.def +++ /dev/null @@ -1,214 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for idle key binding settings. -# Where multiple keys are specified for an action: if they are separated -# by a space (eg. action=<key1> <key2>) then the keys are alternatives, if -# there is no space (eg. action=<key1><key2>) then the keys comprise a -# single 'emacs style' multi-keystoke binding. The tk event specifier 'Key' -# is used in all cases, for consistency in auto key conflict checking in the -# configuration gui. - -[IDLE Classic Windows] -copy=<Control-Key-c> <Control-Key-C> -cut=<Control-Key-x> <Control-Key-X> -paste=<Control-Key-v> <Control-Key-V> -beginning-of-line= <Key-Home> -center-insert=<Control-Key-l> <Control-Key-L> -close-all-windows=<Control-Key-q> -close-window=<Alt-Key-F4> <Meta-Key-F4> -do-nothing=<Control-Key-F12> -end-of-file=<Control-Key-d> <Control-Key-D> -python-docs=<Key-F1> -python-context-help=<Shift-Key-F1> -history-next=<Alt-Key-n> <Meta-Key-n> -history-previous=<Alt-Key-p> <Meta-Key-p> -interrupt-execution=<Control-Key-c> <Control-Key-C> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Alt-Key-c> <Meta-Key-c> <Alt-Key-C> -open-module=<Alt-Key-m> <Meta-Key-m> <Alt-Key-M> -open-new-window=<Control-Key-n> <Control-Key-N> -open-window-from-file=<Control-Key-o> <Control-Key-O> -plain-newline-and-indent=<Control-Key-j> <Control-Key-J> -print-window=<Control-Key-p> <Control-Key-P> -redo=<Control-Shift-Key-Z> -remove-selection=<Key-Escape> -save-copy-of-window-as-file=<Alt-Shift-Key-S> -save-window-as-file=<Control-Shift-Key-S> -save-window=<Control-Key-s> -select-all=<Control-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Control-Key-z> <Control-Key-Z> -find=<Control-Key-f> <Control-Key-F> -find-again=<Control-Key-g> <Key-F3> -find-in-files=<Alt-Key-F3> <Meta-Key-F3> -find-selection=<Control-Key-F3> -replace=<Control-Key-h> <Control-Key-H> -goto-line=<Alt-Key-g> <Meta-Key-g> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Control-Key-bracketright> -dedent-region=<Control-Key-bracketleft> -comment-region=<Alt-Key-3> <Meta-Key-3> -uncomment-region=<Alt-Key-4> <Meta-Key-4> -tabify-region=<Alt-Key-5> <Meta-Key-5> -untabify-region=<Alt-Key-6> <Meta-Key-6> -toggle-tabs=<Alt-Key-t> <Meta-Key-t> <Alt-Key-T> -change-indentwidth=<Alt-Key-u> <Meta-Key-u> <Alt-Key-U> -del-word-left=<Control-Key-BackSpace> -del-word-right=<Control-Key-Delete> - -[IDLE Classic Unix] -copy=<Alt-Key-w> <Meta-Key-w> -cut=<Control-Key-w> -paste=<Control-Key-y> -beginning-of-line=<Control-Key-a> <Key-Home> -center-insert=<Control-Key-l> -close-all-windows=<Control-Key-x><Control-Key-c> -close-window=<Control-Key-x><Control-Key-0> -do-nothing=<Control-Key-x> -end-of-file=<Control-Key-d> -history-next=<Alt-Key-n> <Meta-Key-n> -history-previous=<Alt-Key-p> <Meta-Key-p> -interrupt-execution=<Control-Key-c> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Control-Key-x><Control-Key-b> -open-module=<Control-Key-x><Control-Key-m> -open-new-window=<Control-Key-x><Control-Key-n> -open-window-from-file=<Control-Key-x><Control-Key-f> -plain-newline-and-indent=<Control-Key-j> -print-window=<Control-x><Control-Key-p> -python-docs=<Control-Key-h> -python-context-help=<Control-Shift-Key-H> -redo=<Alt-Key-z> <Meta-Key-z> -remove-selection=<Key-Escape> -save-copy-of-window-as-file=<Control-Key-x><Control-Key-y> -save-window-as-file=<Control-Key-x><Control-Key-w> -save-window=<Control-Key-x><Control-Key-s> -select-all=<Alt-Key-a> <Meta-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Control-Key-z> -find=<Control-Key-u><Control-Key-u><Control-Key-s> -find-again=<Control-Key-u><Control-Key-s> -find-in-files=<Alt-Key-s> <Meta-Key-s> -find-selection=<Control-Key-s> -replace=<Control-Key-r> -goto-line=<Alt-Key-g> <Meta-Key-g> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Control-Key-bracketright> -dedent-region=<Control-Key-bracketleft> -comment-region=<Alt-Key-3> -uncomment-region=<Alt-Key-4> -tabify-region=<Alt-Key-5> -untabify-region=<Alt-Key-6> -toggle-tabs=<Alt-Key-t> -change-indentwidth=<Alt-Key-u> -del-word-left=<Alt-Key-BackSpace> -del-word-right=<Alt-Key-d> - -[IDLE Classic Mac] -copy=<Command-Key-c> -cut=<Command-Key-x> -paste=<Command-Key-v> -beginning-of-line= <Key-Home> -center-insert=<Control-Key-l> -close-all-windows=<Command-Key-q> -close-window=<Command-Key-w> -do-nothing=<Control-Key-F12> -end-of-file=<Control-Key-d> -python-docs=<Key-F1> -python-context-help=<Shift-Key-F1> -history-next=<Control-Key-n> -history-previous=<Control-Key-p> -interrupt-execution=<Control-Key-c> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Command-Key-b> -open-module=<Command-Key-m> -open-new-window=<Command-Key-n> -open-window-from-file=<Command-Key-o> -plain-newline-and-indent=<Control-Key-j> -print-window=<Command-Key-p> -redo=<Shift-Command-Key-Z> -remove-selection=<Key-Escape> -save-window-as-file=<Shift-Command-Key-S> -save-window=<Command-Key-s> -save-copy-of-window-as-file=<Option-Command-Key-s> -select-all=<Command-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Command-Key-z> -find=<Command-Key-f> -find-again=<Command-Key-g> <Key-F3> -find-in-files=<Command-Key-F3> -find-selection=<Shift-Command-Key-F3> -replace=<Command-Key-r> -goto-line=<Command-Key-j> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Command-Key-bracketright> -dedent-region=<Command-Key-bracketleft> -comment-region=<Control-Key-3> -uncomment-region=<Control-Key-4> -tabify-region=<Control-Key-5> -untabify-region=<Control-Key-6> -toggle-tabs=<Control-Key-t> -change-indentwidth=<Control-Key-u> -del-word-left=<Control-Key-BackSpace> -del-word-right=<Control-Key-Delete> - -[IDLE Classic OSX] -toggle-tabs = <Control-Key-t> -interrupt-execution = <Control-Key-c> -untabify-region = <Control-Key-6> -remove-selection = <Key-Escape> -print-window = <Command-Key-p> -replace = <Command-Key-r> -goto-line = <Command-Key-j> -plain-newline-and-indent = <Control-Key-j> -history-previous = <Control-Key-p> -beginning-of-line = <Control-Key-Left> -end-of-line = <Control-Key-Right> -comment-region = <Control-Key-3> -redo = <Shift-Command-Key-Z> -close-window = <Command-Key-w> -restart-shell = <Control-Key-F6> -save-window-as-file = <Command-Key-S> -close-all-windows = <Command-Key-q> -view-restart = <Key-F6> -tabify-region = <Control-Key-5> -find-again = <Command-Key-g> <Key-F3> -find = <Command-Key-f> -toggle-auto-coloring = <Control-Key-slash> -select-all = <Command-Key-a> -smart-backspace = <Key-BackSpace> -change-indentwidth = <Control-Key-u> -do-nothing = <Control-Key-F12> -smart-indent = <Key-Tab> -center-insert = <Control-Key-l> -history-next = <Control-Key-n> -del-word-right = <Option-Key-Delete> -undo = <Command-Key-z> -save-window = <Command-Key-s> -uncomment-region = <Control-Key-4> -cut = <Command-Key-x> -find-in-files = <Command-Key-F3> -dedent-region = <Command-Key-bracketleft> -copy = <Command-Key-c> -paste = <Command-Key-v> -indent-region = <Command-Key-bracketright> -del-word-left = <Option-Key-BackSpace> <Option-Command-Key-BackSpace> -newline-and-indent = <Key-Return> <Key-KP_Enter> -end-of-file = <Control-Key-d> -open-class-browser = <Command-Key-b> -open-new-window = <Command-Key-n> -open-module = <Command-Key-m> -find-selection = <Shift-Command-Key-F3> -python-context-help = <Shift-Key-F1> -save-copy-of-window-as-file = <Shift-Command-Key-s> -open-window-from-file = <Command-Key-o> -python-docs = <Key-F1> - diff --git a/sys/lib/python/idlelib/config-main.def b/sys/lib/python/idlelib/config-main.def deleted file mode 100644 index 5ddd098de..000000000 --- a/sys/lib/python/idlelib/config-main.def +++ /dev/null @@ -1,79 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for general idle settings. -# -# When IDLE starts, it will look in -# the following two sets of files, in order: -# -# default configuration -# --------------------- -# config-main.def the default general config file -# config-extensions.def the default extension config file -# config-highlight.def the default highlighting config file -# config-keys.def the default keybinding config file -# -# user configuration -# ------------------- -# ~/.idlerc/config-main.cfg the user general config file -# ~/.idlerc/config-extensions.cfg the user extension config file -# ~/.idlerc/config-highlight.cfg the user highlighting config file -# ~/.idlerc/config-keys.cfg the user keybinding config file -# -# On Windows2000 and Windows XP the .idlerc directory is at -# Documents and Settings\<username>\.idlerc -# -# On Windows98 it is at c:\.idlerc -# -# Any options the user saves through the config dialog will be saved to -# the relevant user config file. Reverting any general setting to the -# default causes that entry to be wiped from the user file and re-read -# from the default file. User highlighting themes or keybinding sets are -# retained unless specifically deleted within the config dialog. Choosing -# one of the default themes or keysets just applies the relevant settings -# from the default file. -# -# Additional help sources are listed in the [HelpFiles] section and must be -# viewable by a web browser (or the Windows Help viewer in the case of .chm -# files). These sources will be listed on the Help menu. The pattern is -# <sequence_number = menu item;/path/to/help/source> -# You can't use a semi-colon in a menu item or path. The path will be platform -# specific because of path separators, drive specs etc. -# -# It is best to use the Configuration GUI to set up additional help sources! -# Example: -#1 = My Extra Help Source;/usr/share/doc/foo/index.html -#2 = Another Help Source;/path/to/another.pdf - -[General] -editor-on-startup= 0 -autosave= 0 -print-command-posix=lpr %s -print-command-win=start /min notepad /p %s -delete-exitfunc= 1 - -[EditorWindow] -width= 80 -height= 40 -font= courier -font-size= 10 -font-bold= 0 -encoding= none - -[FormatParagraph] -paragraph=70 - -[Indent] -use-spaces= 1 -num-spaces= 4 - -[Theme] -default= 1 -name= IDLE Classic - -[Keys] -default= 1 -name= IDLE Classic Windows - -[History] -cyclic=1 - -[HelpFiles] diff --git a/sys/lib/python/idlelib/configDialog.py b/sys/lib/python/idlelib/configDialog.py deleted file mode 100644 index 2d8835c2a..000000000 --- a/sys/lib/python/idlelib/configDialog.py +++ /dev/null @@ -1,1147 +0,0 @@ -"""IDLE Configuration Dialog: support user customization of IDLE by GUI - -Customize font faces, sizes, and colorization attributes. Set indentation -defaults. Customize keybindings. Colorization and keybindings can be -saved as user defined sets. Select startup options including shell/editor -and default window size. Define additional help sources. - -Note that tab width in IDLE is currently fixed at eight due to Tk issues. -Refer to comments in EditorWindow autoindent code for details. - -""" -from Tkinter import * -import tkMessageBox, tkColorChooser, tkFont -import string, copy - -from configHandler import idleConf -from dynOptionMenuWidget import DynOptionMenu -from tabpage import TabPageSet -from keybindingDialog import GetKeysDialog -from configSectionNameDialog import GetCfgSectionNameDialog -from configHelpSourceEdit import GetHelpSourceDialog - -class ConfigDialog(Toplevel): - - def __init__(self,parent,title): - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("+%d+%d" % (parent.winfo_rootx()+20, - parent.winfo_rooty()+30)) - #Theme Elements. Each theme element key is its display name. - #The first value of the tuple is the sample area tag name. - #The second value is the display name list sort index. - self.themeElements={'Normal Text':('normal','00'), - 'Python Keywords':('keyword','01'), - 'Python Definitions':('definition','02'), - 'Python Builtins':('builtin', '03'), - 'Python Comments':('comment','04'), - 'Python Strings':('string','05'), - 'Selected Text':('hilite','06'), - 'Found Text':('hit','07'), - 'Cursor':('cursor','08'), - 'Error Text':('error','09'), - 'Shell Normal Text':('console','10'), - 'Shell Stdout Text':('stdout','11'), - 'Shell Stderr Text':('stderr','12'), - } - self.ResetChangedItems() #load initial values in changed items dict - self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.tabPages.focus_set() - #key bindings for this dialog - #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save - #self.bind('<Alt-a>',self.Apply) #apply changes, save - #self.bind('<F1>',self.Help) #context help - self.LoadConfigs() - self.AttachVarCallbacks() #avoid callbacks during LoadConfigs - self.wait_window() - - def CreateWidgets(self): - self.tabPages = TabPageSet(self, - pageNames=['Fonts/Tabs','Highlighting','Keys','General']) - self.tabPages.ChangePage()#activates default (first) page - frameActionButtons = Frame(self) - #action buttons - self.buttonHelp = Button(frameActionButtons,text='Help', - command=self.Help,takefocus=FALSE) - self.buttonOk = Button(frameActionButtons,text='Ok', - command=self.Ok,takefocus=FALSE) - self.buttonApply = Button(frameActionButtons,text='Apply', - command=self.Apply,takefocus=FALSE) - self.buttonCancel = Button(frameActionButtons,text='Cancel', - command=self.Cancel,takefocus=FALSE) - self.CreatePageFontTab() - self.CreatePageHighlight() - self.CreatePageKeys() - self.CreatePageGeneral() - self.buttonHelp.pack(side=RIGHT,padx=5,pady=5) - self.buttonOk.pack(side=LEFT,padx=5,pady=5) - self.buttonApply.pack(side=LEFT,padx=5,pady=5) - self.buttonCancel.pack(side=LEFT,padx=5,pady=5) - frameActionButtons.pack(side=BOTTOM) - self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) - - def CreatePageFontTab(self): - #tkVars - self.fontSize=StringVar(self) - self.fontBold=BooleanVar(self) - self.fontName=StringVar(self) - self.spaceNum=IntVar(self) - self.editFont=tkFont.Font(self,('courier',10,'normal')) - ##widget creation - #body frame - frame=self.tabPages.pages['Fonts/Tabs']['page'] - #body section frames - frameFont=Frame(frame,borderwidth=2,relief=GROOVE) - frameIndent=Frame(frame,borderwidth=2,relief=GROOVE) - #frameFont - labelFontTitle=Label(frameFont,text='Set Base Editor Font') - frameFontName=Frame(frameFont) - frameFontParam=Frame(frameFont) - labelFontNameTitle=Label(frameFontName,justify=LEFT, - text='Font :') - self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, - exportselection=FALSE) - self.listFontName.bind('<ButtonRelease-1>',self.OnListFontButtonRelease) - scrollFont=Scrollbar(frameFontName) - scrollFont.config(command=self.listFontName.yview) - self.listFontName.config(yscrollcommand=scrollFont.set) - labelFontSizeTitle=Label(frameFontParam,text='Size :') - self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, - command=self.SetFontSample) - checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, - onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) - frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) - self.labelFontSample=Label(frameFontSample, - text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', - justify=LEFT,font=self.editFont) - #frameIndent - frameIndentSize=Frame(frameIndent) - labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT, - text='Python Standard: 4 Spaces!') - self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum, - label='Indentation Width', orient='horizontal', - tickinterval=2, from_=2, to=16) - #widget packing - #body - frameFont.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH) - frameIndent.pack(side=LEFT,padx=5,pady=10,fill=Y) - #frameFont - labelFontTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) - frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) - labelFontNameTitle.pack(side=TOP,anchor=W) - self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) - scrollFont.pack(side=LEFT,fill=Y) - labelFontSizeTitle.pack(side=LEFT,anchor=W) - self.optMenuFontSize.pack(side=LEFT,anchor=W) - checkFontBold.pack(side=LEFT,anchor=W,padx=20) - frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - self.labelFontSample.pack(expand=TRUE,fill=BOTH) - #frameIndent - frameIndentSize.pack(side=TOP,padx=5,pady=5,fill=BOTH) - labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) - self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) - return frame - - def CreatePageHighlight(self): - self.builtinTheme=StringVar(self) - self.customTheme=StringVar(self) - self.fgHilite=BooleanVar(self) - self.colour=StringVar(self) - self.fontName=StringVar(self) - self.themeIsBuiltin=BooleanVar(self) - self.highlightTarget=StringVar(self) - ##widget creation - #body frame - frame=self.tabPages.pages['Highlighting']['page'] - #body section frames - frameCustom=Frame(frame,borderwidth=2,relief=GROOVE) - frameTheme=Frame(frame,borderwidth=2,relief=GROOVE) - #frameCustom - self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, - font=('courier',12,''),cursor='hand2',width=21,height=10, - takefocus=FALSE,highlightthickness=0,wrap=NONE) - text=self.textHighlightSample - text.bind('<Double-Button-1>',lambda e: 'break') - text.bind('<B1-Motion>',lambda e: 'break') - textAndTags=(('#you can click here','comment'),('\n','normal'), - ('#to choose items','comment'),('\n','normal'),('def','keyword'), - (' ','normal'),('func','definition'),('(param):','normal'), - ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), - ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), - ('\n var2 = ','normal'),("'found'",'hit'), - ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'), - ('None', 'builtin'),(')\n\n','normal'), - (' error ','error'),(' ','normal'),('cursor |','cursor'), - ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), - (' ','normal'),('stderr','stderr'),('\n','normal')) - for txTa in textAndTags: - text.insert(END,txTa[0],txTa[1]) - for element in self.themeElements.keys(): - text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>', - lambda event,elem=element: event.widget.winfo_toplevel() - .highlightTarget.set(elem)) - text.config(state=DISABLED) - self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) - frameFgBg=Frame(frameCustom) - labelCustomTitle=Label(frameCustom,text='Set Custom Highlighting') - buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', - command=self.GetColour,highlightthickness=0) - self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, - self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding - self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=1,text='Foreground',command=self.SetColourSampleBinding) - self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=0,text='Background',command=self.SetColourSampleBinding) - self.fgHilite.set(1) - buttonSaveCustomTheme=Button(frameCustom, - text='Save as New Custom Theme',command=self.SaveAsNewTheme) - #frameTheme - labelThemeTitle=Label(frameTheme,text='Select a Highlighting Theme') - labelTypeTitle=Label(frameTheme,text='Select : ') - self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=1,command=self.SetThemeType,text='a Built-in Theme') - self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=0,command=self.SetThemeType,text='a Custom Theme') - self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, - self.builtinTheme,None,command=None) - self.optMenuThemeCustom=DynOptionMenu(frameTheme, - self.customTheme,None,command=None) - self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', - command=self.DeleteCustomTheme) - ##widget packing - #body - frameCustom.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH) - frameTheme.pack(side=LEFT,padx=5,pady=10,fill=Y) - #frameCustom - labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) - frameFgBg.pack(side=TOP,padx=5,pady=0) - self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, - fill=BOTH) - buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) - self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) - self.radioFg.pack(side=LEFT,anchor=E) - self.radioBg.pack(side=RIGHT,anchor=W) - buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) - #frameTheme - labelThemeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) - return frame - - def CreatePageKeys(self): - #tkVars - self.bindingTarget=StringVar(self) - self.builtinKeys=StringVar(self) - self.customKeys=StringVar(self) - self.keysAreBuiltin=BooleanVar(self) - self.keyBinding=StringVar(self) - ##widget creation - #body frame - frame=self.tabPages.pages['Keys']['page'] - #body section frames - frameCustom=Frame(frame,borderwidth=2,relief=GROOVE) - frameKeySets=Frame(frame,borderwidth=2,relief=GROOVE) - #frameCustom - frameTarget=Frame(frameCustom) - labelCustomTitle=Label(frameCustom,text='Set Custom Key Bindings') - labelTargetTitle=Label(frameTarget,text='Action - Key(s)') - scrollTargetY=Scrollbar(frameTarget) - scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) - self.listBindings=Listbox(frameTarget,takefocus=FALSE, - exportselection=FALSE) - self.listBindings.bind('<ButtonRelease-1>',self.KeyBindingSelected) - scrollTargetY.config(command=self.listBindings.yview) - scrollTargetX.config(command=self.listBindings.xview) - self.listBindings.config(yscrollcommand=scrollTargetY.set) - self.listBindings.config(xscrollcommand=scrollTargetX.set) - self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', - command=self.GetNewKeys,state=DISABLED) - buttonSaveCustomKeys=Button(frameCustom, - text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) - #frameKeySets - labelKeysTitle=Label(frameKeySets,text='Select a Key Set') - labelTypeTitle=Label(frameKeySets,text='Select : ') - self.radioKeysBuiltin=Radiobutton(frameKeySets,variable=self.keysAreBuiltin, - value=1,command=self.SetKeysType,text='a Built-in Key Set') - self.radioKeysCustom=Radiobutton(frameKeySets,variable=self.keysAreBuiltin, - value=0,command=self.SetKeysType,text='a Custom Key Set') - self.optMenuKeysBuiltin=DynOptionMenu(frameKeySets, - self.builtinKeys,None,command=None) - self.optMenuKeysCustom=DynOptionMenu(frameKeySets, - self.customKeys,None,command=None) - self.buttonDeleteCustomKeys=Button(frameKeySets,text='Delete Custom Key Set', - command=self.DeleteCustomKeys) - ##widget packing - #body - frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameKeySets.pack(side=LEFT,padx=5,pady=5,fill=Y) - #frameCustom - labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - buttonSaveCustomKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - #frame target - frameTarget.columnconfigure(0,weight=1) - frameTarget.rowconfigure(1,weight=1) - labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) - self.listBindings.grid(row=1,column=0,sticky=NSEW) - scrollTargetY.grid(row=1,column=1,sticky=NS) - scrollTargetX.grid(row=2,column=0,sticky=EW) - #frameKeySets - labelKeysTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioKeysBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioKeysCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuKeysBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuKeysCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomKeys.pack(side=TOP,fill=X,padx=5,pady=5) - return frame - - def CreatePageGeneral(self): - #tkVars - self.winWidth=StringVar(self) - self.winHeight=StringVar(self) - self.paraWidth=StringVar(self) - self.startupEdit=IntVar(self) - self.autoSave=IntVar(self) - self.encoding=StringVar(self) - self.userHelpBrowser=BooleanVar(self) - self.helpBrowser=StringVar(self) - #widget creation - #body - frame=self.tabPages.pages['General']['page'] - #body section frames - frameRun=Frame(frame,borderwidth=2,relief=GROOVE) - frameSave=Frame(frame,borderwidth=2,relief=GROOVE) - frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE) - frameHelp=Frame(frame,borderwidth=2,relief=GROOVE) - #frameRun - labelRunTitle=Label(frameRun,text='Startup Preferences') - labelRunChoiceTitle=Label(frameRun,text='At Startup') - radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, - value=1,command=self.SetKeysType,text="Open Edit Window") - radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, - value=0,command=self.SetKeysType,text='Open Shell Window') - #frameSave - labelSaveTitle=Label(frameSave,text='Autosave Preference') - labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ') - radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave, - value=0,command=self.SetKeysType,text="Prompt to Save") - radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave, - value=1,command=self.SetKeysType,text='No Prompt') - #frameWinSize - labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ - ' (in characters)') - labelWinWidthTitle=Label(frameWinSize,text='Width') - entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, - width=3) - labelWinHeightTitle=Label(frameWinSize,text='Height') - entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, - width=3) - #paragraphFormatWidth - labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+ - ' width (in characters)') - entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth, - width=3) - #frameEncoding - labelEncodingTitle=Label(frameEncoding,text="Default Source Encoding") - radioEncLocale=Radiobutton(frameEncoding,variable=self.encoding, - value="locale",text="Locale-defined") - radioEncUTF8=Radiobutton(frameEncoding,variable=self.encoding, - value="utf-8",text="UTF-8") - radioEncNone=Radiobutton(frameEncoding,variable=self.encoding, - value="none",text="None") - #frameHelp - frameHelpList=Frame(frameHelp) - frameHelpListButtons=Frame(frameHelpList) - labelHelpListTitle=Label(frameHelpList,text='Additional Help Sources:') - scrollHelpList=Scrollbar(frameHelpList) - self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, - exportselection=FALSE) - scrollHelpList.config(command=self.listHelp.yview) - self.listHelp.config(yscrollcommand=scrollHelpList.set) - self.listHelp.bind('<ButtonRelease-1>',self.HelpSourceSelected) - self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', - state=DISABLED,width=8,command=self.HelpListItemEdit) - self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', - width=8,command=self.HelpListItemAdd) - self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', - state=DISABLED,width=8,command=self.HelpListItemRemove) - #widget packing - #body - frameRun.pack(side=TOP,padx=5,pady=5,fill=X) - frameSave.pack(side=TOP,padx=5,pady=5,fill=X) - frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X) - frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - #frameRun - labelRunTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5) - #frameSave - labelSaveTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5) - #frameWinSize - labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) - entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) - #paragraphFormatWidth - labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - #frameEncoding - labelEncodingTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioEncNone.pack(side=RIGHT,anchor=E,pady=5) - radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5) - radioEncLocale.pack(side=RIGHT,anchor=E,pady=5) - #frameHelp - frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) - frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - labelHelpListTitle.pack(side=TOP,anchor=W) - scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) - self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) - self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) - self.buttonHelpListAdd.pack(side=TOP,anchor=W) - self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) - return frame - - def AttachVarCallbacks(self): - self.fontSize.trace_variable('w',self.VarChanged_fontSize) - self.fontName.trace_variable('w',self.VarChanged_fontName) - self.fontBold.trace_variable('w',self.VarChanged_fontBold) - self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) - self.colour.trace_variable('w',self.VarChanged_colour) - self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) - self.customTheme.trace_variable('w',self.VarChanged_customTheme) - self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) - self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) - self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) - self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) - self.customKeys.trace_variable('w',self.VarChanged_customKeys) - self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) - self.winWidth.trace_variable('w',self.VarChanged_winWidth) - self.winHeight.trace_variable('w',self.VarChanged_winHeight) - self.paraWidth.trace_variable('w',self.VarChanged_paraWidth) - self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) - self.autoSave.trace_variable('w',self.VarChanged_autoSave) - self.encoding.trace_variable('w',self.VarChanged_encoding) - - def VarChanged_fontSize(self,*params): - value=self.fontSize.get() - self.AddChangedItem('main','EditorWindow','font-size',value) - - def VarChanged_fontName(self,*params): - value=self.fontName.get() - self.AddChangedItem('main','EditorWindow','font',value) - - def VarChanged_fontBold(self,*params): - value=self.fontBold.get() - self.AddChangedItem('main','EditorWindow','font-bold',value) - - def VarChanged_spaceNum(self,*params): - value=self.spaceNum.get() - self.AddChangedItem('main','Indent','num-spaces',value) - - def VarChanged_colour(self,*params): - self.OnNewColourSet() - - def VarChanged_builtinTheme(self,*params): - value=self.builtinTheme.get() - self.AddChangedItem('main','Theme','name',value) - self.PaintThemeSample() - - def VarChanged_customTheme(self,*params): - value=self.customTheme.get() - if value != '- no custom themes -': - self.AddChangedItem('main','Theme','name',value) - self.PaintThemeSample() - - def VarChanged_themeIsBuiltin(self,*params): - value=self.themeIsBuiltin.get() - self.AddChangedItem('main','Theme','default',value) - if value: - self.VarChanged_builtinTheme() - else: - self.VarChanged_customTheme() - - def VarChanged_highlightTarget(self,*params): - self.SetHighlightTarget() - - def VarChanged_keyBinding(self,*params): - value=self.keyBinding.get() - keySet=self.customKeys.get() - event=self.listBindings.get(ANCHOR).split()[0] - if idleConf.IsCoreBinding(event): - #this is a core keybinding - self.AddChangedItem('keys',keySet,event,value) - else: #this is an extension key binding - extName=idleConf.GetExtnNameForEvent(event) - extKeybindSection=extName+'_cfgBindings' - self.AddChangedItem('extensions',extKeybindSection,event,value) - - def VarChanged_builtinKeys(self,*params): - value=self.builtinKeys.get() - self.AddChangedItem('main','Keys','name',value) - self.LoadKeysList(value) - - def VarChanged_customKeys(self,*params): - value=self.customKeys.get() - if value != '- no custom keys -': - self.AddChangedItem('main','Keys','name',value) - self.LoadKeysList(value) - - def VarChanged_keysAreBuiltin(self,*params): - value=self.keysAreBuiltin.get() - self.AddChangedItem('main','Keys','default',value) - if value: - self.VarChanged_builtinKeys() - else: - self.VarChanged_customKeys() - - def VarChanged_winWidth(self,*params): - value=self.winWidth.get() - self.AddChangedItem('main','EditorWindow','width',value) - - def VarChanged_winHeight(self,*params): - value=self.winHeight.get() - self.AddChangedItem('main','EditorWindow','height',value) - - def VarChanged_paraWidth(self,*params): - value=self.paraWidth.get() - self.AddChangedItem('main','FormatParagraph','paragraph',value) - - def VarChanged_startupEdit(self,*params): - value=self.startupEdit.get() - self.AddChangedItem('main','General','editor-on-startup',value) - - def VarChanged_autoSave(self,*params): - value=self.autoSave.get() - self.AddChangedItem('main','General','autosave',value) - - def VarChanged_encoding(self,*params): - value=self.encoding.get() - self.AddChangedItem('main','EditorWindow','encoding',value) - - def ResetChangedItems(self): - #When any config item is changed in this dialog, an entry - #should be made in the relevant section (config type) of this - #dictionary. The key should be the config file section name and the - #value a dictionary, whose key:value pairs are item=value pairs for - #that config file section. - self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} - - def AddChangedItem(self,type,section,item,value): - value=str(value) #make sure we use a string - if not self.changedItems[type].has_key(section): - self.changedItems[type][section]={} - self.changedItems[type][section][item]=value - - def GetDefaultItems(self): - dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} - for configType in dItems.keys(): - sections=idleConf.GetSectionList('default',configType) - for section in sections: - dItems[configType][section]={} - options=idleConf.defaultCfg[configType].GetOptionList(section) - for option in options: - dItems[configType][section][option]=( - idleConf.defaultCfg[configType].Get(section,option)) - return dItems - - def SetThemeType(self): - if self.themeIsBuiltin.get(): - self.optMenuThemeBuiltin.config(state=NORMAL) - self.optMenuThemeCustom.config(state=DISABLED) - self.buttonDeleteCustomTheme.config(state=DISABLED) - else: - self.optMenuThemeBuiltin.config(state=DISABLED) - self.radioThemeCustom.config(state=NORMAL) - self.optMenuThemeCustom.config(state=NORMAL) - self.buttonDeleteCustomTheme.config(state=NORMAL) - - def SetKeysType(self): - if self.keysAreBuiltin.get(): - self.optMenuKeysBuiltin.config(state=NORMAL) - self.optMenuKeysCustom.config(state=DISABLED) - self.buttonDeleteCustomKeys.config(state=DISABLED) - else: - self.optMenuKeysBuiltin.config(state=DISABLED) - self.radioKeysCustom.config(state=NORMAL) - self.optMenuKeysCustom.config(state=NORMAL) - self.buttonDeleteCustomKeys.config(state=NORMAL) - - def GetNewKeys(self): - listIndex=self.listBindings.index(ANCHOR) - binding=self.listBindings.get(listIndex) - bindName=binding.split()[0] #first part, up to first space - if self.keysAreBuiltin.get(): - currentKeySetName=self.builtinKeys.get() - else: - currentKeySetName=self.customKeys.get() - currentBindings=idleConf.GetCurrentKeySet() - if currentKeySetName in self.changedItems['keys'].keys(): #unsaved changes - keySetChanges=self.changedItems['keys'][currentKeySetName] - for event in keySetChanges.keys(): - currentBindings[event]=keySetChanges[event].split() - currentKeySequences=currentBindings.values() - newKeys=GetKeysDialog(self,'Get New Keys',bindName, - currentKeySequences).result - if newKeys: #new keys were specified - if self.keysAreBuiltin.get(): #current key set is a built-in - message=('Your changes will be saved as a new Custom Key Set. '+ - 'Enter a name for your new Custom Key Set below.') - newKeySet=self.GetNewKeysName(message) - if not newKeySet: #user cancelled custom key set creation - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - return - else: #create new custom key set based on previously active key set - self.CreateNewKeySet(newKeySet) - self.listBindings.delete(listIndex) - self.listBindings.insert(listIndex,bindName+' - '+newKeys) - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - self.keyBinding.set(newKeys) - else: - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - - def GetNewKeysName(self,message): - usedNames=(idleConf.GetSectionList('user','keys')+ - idleConf.GetSectionList('default','keys')) - newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', - message,usedNames).result - return newKeySet - - def SaveAsNewKeySet(self): - newKeysName=self.GetNewKeysName('New Key Set Name:') - if newKeysName: - self.CreateNewKeySet(newKeysName) - - def KeyBindingSelected(self,event): - self.buttonNewKeys.config(state=NORMAL) - - def CreateNewKeySet(self,newKeySetName): - #creates new custom key set based on the previously active key set, - #and makes the new key set active - if self.keysAreBuiltin.get(): - prevKeySetName=self.builtinKeys.get() - else: - prevKeySetName=self.customKeys.get() - prevKeys=idleConf.GetCoreKeys(prevKeySetName) - newKeys={} - for event in prevKeys.keys(): #add key set to changed items - eventName=event[2:-2] #trim off the angle brackets - binding=string.join(prevKeys[event]) - newKeys[eventName]=binding - #handle any unsaved changes to prev key set - if prevKeySetName in self.changedItems['keys'].keys(): - keySetChanges=self.changedItems['keys'][prevKeySetName] - for event in keySetChanges.keys(): - newKeys[event]=keySetChanges[event] - #save the new theme - self.SaveNewKeySet(newKeySetName,newKeys) - #change gui over to the new key set - customKeyList=idleConf.GetSectionList('user','keys') - customKeyList.sort() - self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) - self.keysAreBuiltin.set(0) - self.SetKeysType() - - def LoadKeysList(self,keySetName): - reselect=0 - newKeySet=0 - if self.listBindings.curselection(): - reselect=1 - listIndex=self.listBindings.index(ANCHOR) - keySet=idleConf.GetKeySet(keySetName) - bindNames=keySet.keys() - bindNames.sort() - self.listBindings.delete(0,END) - for bindName in bindNames: - key=string.join(keySet[bindName]) #make key(s) into a string - bindName=bindName[2:-2] #trim off the angle brackets - if keySetName in self.changedItems['keys'].keys(): - #handle any unsaved changes to this key set - if bindName in self.changedItems['keys'][keySetName].keys(): - key=self.changedItems['keys'][keySetName][bindName] - self.listBindings.insert(END, bindName+' - '+key) - if reselect: - self.listBindings.see(listIndex) - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - - def DeleteCustomKeys(self): - keySetName=self.customKeys.get() - if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set %r ?' % (keySetName), - parent=self): - return - #remove key set from config - idleConf.userCfg['keys'].remove_section(keySetName) - if self.changedItems['keys'].has_key(keySetName): - del(self.changedItems['keys'][keySetName]) - #write changes - idleConf.userCfg['keys'].Save() - #reload user key set list - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - if not itemList: - self.radioKeysCustom.config(state=DISABLED) - self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') - else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) - #revert to default key set - self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) - self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) - #user can't back out of these changes, they must be applied now - self.Apply() - self.SetKeysType() - - def DeleteCustomTheme(self): - themeName=self.customTheme.get() - if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme %r ?' % (themeName,), - parent=self): - return - #remove theme from config - idleConf.userCfg['highlight'].remove_section(themeName) - if self.changedItems['highlight'].has_key(themeName): - del(self.changedItems['highlight'][themeName]) - #write changes - idleConf.userCfg['highlight'].Save() - #reload user theme list - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - if not itemList: - self.radioThemeCustom.config(state=DISABLED) - self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') - else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) - #revert to default theme - self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) - self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) - #user can't back out of these changes, they must be applied now - self.Apply() - self.SetThemeType() - - def GetColour(self): - target=self.highlightTarget.get() - prevColour=self.frameColourSet.cget('bg') - rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, - title='Pick new colour for : '+target,initialcolor=prevColour) - if colourString and (colourString!=prevColour): - #user didn't cancel, and they chose a new colour - if self.themeIsBuiltin.get(): #current theme is a built-in - message=('Your changes will be saved as a new Custom Theme. '+ - 'Enter a name for your new Custom Theme below.') - newTheme=self.GetNewThemeName(message) - if not newTheme: #user cancelled custom theme creation - return - else: #create new custom theme based on previously active theme - self.CreateNewTheme(newTheme) - self.colour.set(colourString) - else: #current theme is user defined - self.colour.set(colourString) - - def OnNewColourSet(self): - newColour=self.colour.get() - self.frameColourSet.config(bg=newColour)#set sample - if self.fgHilite.get(): plane='foreground' - else: plane='background' - sampleElement=self.themeElements[self.highlightTarget.get()][0] - self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) - theme=self.customTheme.get() - themeElement=sampleElement+'-'+plane - self.AddChangedItem('highlight',theme,themeElement,newColour) - - def GetNewThemeName(self,message): - usedNames=(idleConf.GetSectionList('user','highlight')+ - idleConf.GetSectionList('default','highlight')) - newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', - message,usedNames).result - return newTheme - - def SaveAsNewTheme(self): - newThemeName=self.GetNewThemeName('New Theme Name:') - if newThemeName: - self.CreateNewTheme(newThemeName) - - def CreateNewTheme(self,newThemeName): - #creates new custom theme based on the previously active theme, - #and makes the new theme active - if self.themeIsBuiltin.get(): - themeType='default' - themeName=self.builtinTheme.get() - else: - themeType='user' - themeName=self.customTheme.get() - newTheme=idleConf.GetThemeDict(themeType,themeName) - #apply any of the old theme's unsaved changes to the new theme - if themeName in self.changedItems['highlight'].keys(): - themeChanges=self.changedItems['highlight'][themeName] - for element in themeChanges.keys(): - newTheme[element]=themeChanges[element] - #save the new theme - self.SaveNewTheme(newThemeName,newTheme) - #change gui over to the new theme - customThemeList=idleConf.GetSectionList('user','highlight') - customThemeList.sort() - self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) - self.themeIsBuiltin.set(0) - self.SetThemeType() - - def OnListFontButtonRelease(self,event): - font = self.listFontName.get(ANCHOR) - self.fontName.set(font.lower()) - self.SetFontSample() - - def SetFontSample(self,event=None): - fontName=self.fontName.get() - if self.fontBold.get(): - fontWeight=tkFont.BOLD - else: - fontWeight=tkFont.NORMAL - self.editFont.config(size=self.fontSize.get(), - weight=fontWeight,family=fontName) - - def SetHighlightTarget(self): - if self.highlightTarget.get()=='Cursor': #bg not possible - self.radioFg.config(state=DISABLED) - self.radioBg.config(state=DISABLED) - self.fgHilite.set(1) - else: #both fg and bg can be set - self.radioFg.config(state=NORMAL) - self.radioBg.config(state=NORMAL) - self.fgHilite.set(1) - self.SetColourSample() - - def SetColourSampleBinding(self,*args): - self.SetColourSample() - - def SetColourSample(self): - #set the colour smaple area - tag=self.themeElements[self.highlightTarget.get()][0] - if self.fgHilite.get(): plane='foreground' - else: plane='background' - colour=self.textHighlightSample.tag_cget(tag,plane) - self.frameColourSet.config(bg=colour) - - def PaintThemeSample(self): - if self.themeIsBuiltin.get(): #a default theme - theme=self.builtinTheme.get() - else: #a user theme - theme=self.customTheme.get() - for elementTitle in self.themeElements.keys(): - element=self.themeElements[elementTitle][0] - colours=idleConf.GetHighlight(theme,element) - if element=='cursor': #cursor sample needs special painting - colours['background']=idleConf.GetHighlight(theme, - 'normal', fgBg='bg') - #handle any unsaved changes to this theme - if theme in self.changedItems['highlight'].keys(): - themeDict=self.changedItems['highlight'][theme] - if themeDict.has_key(element+'-foreground'): - colours['foreground']=themeDict[element+'-foreground'] - if themeDict.has_key(element+'-background'): - colours['background']=themeDict[element+'-background'] - self.textHighlightSample.tag_config(element, **colours) - self.SetColourSample() - - def HelpSourceSelected(self,event): - self.SetHelpListButtonStates() - - def SetHelpListButtonStates(self): - if self.listHelp.size()<1: #no entries in list - self.buttonHelpListEdit.config(state=DISABLED) - self.buttonHelpListRemove.config(state=DISABLED) - else: #there are some entries - if self.listHelp.curselection(): #there currently is a selection - self.buttonHelpListEdit.config(state=NORMAL) - self.buttonHelpListRemove.config(state=NORMAL) - else: #there currently is not a selection - self.buttonHelpListEdit.config(state=DISABLED) - self.buttonHelpListRemove.config(state=DISABLED) - - def HelpListItemAdd(self): - helpSource=GetHelpSourceDialog(self,'New Help Source').result - if helpSource: - self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def HelpListItemEdit(self): - itemIndex=self.listHelp.index(ANCHOR) - helpSource=self.userHelpList[itemIndex] - newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', - menuItem=helpSource[0],filePath=helpSource[1]).result - if (not newHelpSource) or (newHelpSource==helpSource): - return #no changes - self.userHelpList[itemIndex]=newHelpSource - self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def HelpListItemRemove(self): - itemIndex=self.listHelp.index(ANCHOR) - del(self.userHelpList[itemIndex]) - self.listHelp.delete(itemIndex) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def UpdateUserHelpChangedItems(self): - "Clear and rebuild the HelpFiles section in self.changedItems" - self.changedItems['main']['HelpFiles'] = {} - for num in range(1,len(self.userHelpList)+1): - self.AddChangedItem('main','HelpFiles',str(num), - string.join(self.userHelpList[num-1][:2],';')) - - def LoadFontCfg(self): - ##base editor font selection list - fonts=list(tkFont.families(self)) - fonts.sort() - for font in fonts: - self.listFontName.insert(END,font) - configuredFont=idleConf.GetOption('main','EditorWindow','font', - default='courier') - lc_configuredFont = configuredFont.lower() - self.fontName.set(lc_configuredFont) - lc_fonts = [s.lower() for s in fonts] - if lc_configuredFont in lc_fonts: - currentFontIndex = lc_fonts.index(lc_configuredFont) - self.listFontName.see(currentFontIndex) - self.listFontName.select_set(currentFontIndex) - self.listFontName.select_anchor(currentFontIndex) - ##font size dropdown - fontSize=idleConf.GetOption('main','EditorWindow','font-size', - default='10') - self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', - '16','18','20','22'),fontSize ) - ##fontWeight - self.fontBold.set(idleConf.GetOption('main','EditorWindow', - 'font-bold',default=0,type='bool')) - ##font sample - self.SetFontSample() - - def LoadTabCfg(self): - ##indent sizes - spaceNum=idleConf.GetOption('main','Indent','num-spaces', - default=4,type='int') - self.spaceNum.set(spaceNum) - - def LoadThemeCfg(self): - ##current theme type radiobutton - self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', - type='bool',default=1)) - ##currently set theme - currentOption=idleConf.CurrentTheme() - ##load available theme option menus - if self.themeIsBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','highlight') - itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - if not itemList: - self.radioThemeCustom.config(state=DISABLED) - self.customTheme.set('- no custom themes -') - else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) - else: #user theme selected - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - self.optMenuThemeCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','highlight') - itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) - self.SetThemeType() - ##load theme element option menu - themeNames=self.themeElements.keys() - themeNames.sort(self.__ThemeNameIndexCompare) - self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) - self.PaintThemeSample() - self.SetHighlightTarget() - - def __ThemeNameIndexCompare(self,a,b): - if self.themeElements[a][1]<self.themeElements[b][1]: return -1 - elif self.themeElements[a][1]==self.themeElements[b][1]: return 0 - else: return 1 - - def LoadKeyCfg(self): - ##current keys type radiobutton - self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', - type='bool',default=1)) - ##currently set keys - currentOption=idleConf.CurrentKeys() - ##load available keyset option menus - if self.keysAreBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','keys') - itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - if not itemList: - self.radioKeysCustom.config(state=DISABLED) - self.customKeys.set('- no custom keys -') - else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) - else: #user key set selected - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - self.optMenuKeysCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','keys') - itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) - self.SetKeysType() - ##load keyset element list - keySetName=idleConf.CurrentKeys() - self.LoadKeysList(keySetName) - - def LoadGeneralCfg(self): - #startup state - self.startupEdit.set(idleConf.GetOption('main','General', - 'editor-on-startup',default=1,type='bool')) - #autosave state - self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', - default=0, type='bool')) - #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height')) - #initial paragraph reformat size - self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph')) - # default source encoding - self.encoding.set(idleConf.GetOption('main', 'EditorWindow', - 'encoding', default='none')) - # additional help sources - self.userHelpList = idleConf.GetAllExtraHelpSourcesList() - for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]) - self.SetHelpListButtonStates() - - def LoadConfigs(self): - """ - load configuration from default and user config files and populate - the widgets on the config dialog pages. - """ - ### fonts / tabs page - self.LoadFontCfg() - self.LoadTabCfg() - ### highlighting page - self.LoadThemeCfg() - ### keys page - self.LoadKeyCfg() - ### general page - self.LoadGeneralCfg() - - def SaveNewKeySet(self,keySetName,keySet): - """ - save a newly created core key set. - keySetName - string, the name of the new key set - keySet - dictionary containing the new key set - """ - if not idleConf.userCfg['keys'].has_section(keySetName): - idleConf.userCfg['keys'].add_section(keySetName) - for event in keySet.keys(): - value=keySet[event] - idleConf.userCfg['keys'].SetOption(keySetName,event,value) - - def SaveNewTheme(self,themeName,theme): - """ - save a newly created theme. - themeName - string, the name of the new theme - theme - dictionary containing the new theme - """ - if not idleConf.userCfg['highlight'].has_section(themeName): - idleConf.userCfg['highlight'].add_section(themeName) - for element in theme.keys(): - value=theme[element] - idleConf.userCfg['highlight'].SetOption(themeName,element,value) - - def SetUserValue(self,configType,section,item,value): - if idleConf.defaultCfg[configType].has_option(section,item): - if idleConf.defaultCfg[configType].Get(section,item)==value: - #the setting equals a default setting, remove it from user cfg - return idleConf.userCfg[configType].RemoveOption(section,item) - #if we got here set the option - return idleConf.userCfg[configType].SetOption(section,item,value) - - def SaveAllChangedConfigs(self): - "Save configuration changes to the user config file." - idleConf.userCfg['main'].Save() - for configType in self.changedItems.keys(): - cfgTypeHasChanges = False - for section in self.changedItems[configType].keys(): - if section == 'HelpFiles': - #this section gets completely replaced - idleConf.userCfg['main'].remove_section('HelpFiles') - cfgTypeHasChanges = True - for item in self.changedItems[configType][section].keys(): - value = self.changedItems[configType][section][item] - if self.SetUserValue(configType,section,item,value): - cfgTypeHasChanges = True - if cfgTypeHasChanges: - idleConf.userCfg[configType].Save() - for configType in ['keys', 'highlight']: - # save these even if unchanged! - idleConf.userCfg[configType].Save() - self.ResetChangedItems() #clear the changed items dict - - def DeactivateCurrentConfig(self): - #Before a config is saved, some cleanup of current - #config must be done - remove the previous keybindings - winInstances=self.parent.instance_dict.keys() - for instance in winInstances: - instance.RemoveKeybindings() - - def ActivateConfigChanges(self): - "Dynamically apply configuration changes" - winInstances=self.parent.instance_dict.keys() - for instance in winInstances: - instance.ResetColorizer() - instance.ResetFont() - instance.set_notabs_indentwidth() - instance.ApplyKeybindings() - instance.reset_help_menu_entries() - - def Cancel(self): - self.destroy() - - def Ok(self): - self.Apply() - self.destroy() - - def Apply(self): - self.DeactivateCurrentConfig() - self.SaveAllChangedConfigs() - self.ActivateConfigChanges() - - def Help(self): - pass - -if __name__ == '__main__': - #test the dialog - root=Tk() - Button(root,text='Dialog', - command=lambda:ConfigDialog(root,'Settings')).pack() - root.instance_dict={} - root.mainloop() diff --git a/sys/lib/python/idlelib/configHandler.py b/sys/lib/python/idlelib/configHandler.py deleted file mode 100644 index 826fb5dbb..000000000 --- a/sys/lib/python/idlelib/configHandler.py +++ /dev/null @@ -1,696 +0,0 @@ -"""Provides access to stored IDLE configuration information. - -Refer to the comments at the beginning of config-main.def for a description of -the available configuration files and the design implemented to update user -configuration information. In particular, user configuration choices which -duplicate the defaults will be removed from the user's configuration files, -and if a file becomes empty, it will be deleted. - -The contents of the user files may be altered using the Options/Configure IDLE -menu to access the configuration GUI (configDialog.py), or manually. - -Throughout this module there is an emphasis on returning useable defaults -when a problem occurs in returning a requested configuration value back to -idle. This is to allow IDLE to continue to function in spite of errors in -the retrieval of config information. When a default is returned instead of -a requested config value, a message is printed to stderr to aid in -configuration problem notification and resolution. - -""" -import os -import sys -import string -import macosxSupport -from ConfigParser import ConfigParser, NoOptionError, NoSectionError - -class InvalidConfigType(Exception): pass -class InvalidConfigSet(Exception): pass -class InvalidFgBg(Exception): pass -class InvalidTheme(Exception): pass - -class IdleConfParser(ConfigParser): - """ - A ConfigParser specialised for idle configuration file handling - """ - def __init__(self, cfgFile, cfgDefaults=None): - """ - cfgFile - string, fully specified configuration file name - """ - self.file=cfgFile - ConfigParser.__init__(self,defaults=cfgDefaults) - - def Get(self, section, option, type=None, default=None): - """ - Get an option value for given section/option or return default. - If type is specified, return as type. - """ - if type=='bool': - getVal=self.getboolean - elif type=='int': - getVal=self.getint - else: - getVal=self.get - if self.has_option(section,option): - #return getVal(section, option, raw, vars, default) - return getVal(section, option) - else: - return default - - def GetOptionList(self,section): - """ - Get an option list for given section - """ - if self.has_section(section): - return self.options(section) - else: #return a default value - return [] - - def Load(self): - """ - Load the configuration file from disk - """ - self.read(self.file) - -class IdleUserConfParser(IdleConfParser): - """ - IdleConfigParser specialised for user configuration handling. - """ - - def AddSection(self,section): - """ - if section doesn't exist, add it - """ - if not self.has_section(section): - self.add_section(section) - - def RemoveEmptySections(self): - """ - remove any sections that have no options - """ - for section in self.sections(): - if not self.GetOptionList(section): - self.remove_section(section) - - def IsEmpty(self): - """ - Remove empty sections and then return 1 if parser has no sections - left, else return 0. - """ - self.RemoveEmptySections() - if self.sections(): - return 0 - else: - return 1 - - def RemoveOption(self,section,option): - """ - If section/option exists, remove it. - Returns 1 if option was removed, 0 otherwise. - """ - if self.has_section(section): - return self.remove_option(section,option) - - def SetOption(self,section,option,value): - """ - Sets option to value, adding section if required. - Returns 1 if option was added or changed, otherwise 0. - """ - if self.has_option(section,option): - if self.get(section,option)==value: - return 0 - else: - self.set(section,option,value) - return 1 - else: - if not self.has_section(section): - self.add_section(section) - self.set(section,option,value) - return 1 - - def RemoveFile(self): - """ - Removes the user config file from disk if it exists. - """ - if os.path.exists(self.file): - os.remove(self.file) - - def Save(self): - """Update user configuration file. - - Remove empty sections. If resulting config isn't empty, write the file - to disk. If config is empty, remove the file from disk if it exists. - - """ - if not self.IsEmpty(): - cfgFile=open(self.file,'w') - self.write(cfgFile) - else: - self.RemoveFile() - -class IdleConf: - """ - holds config parsers for all idle config files: - default config files - (idle install dir)/config-main.def - (idle install dir)/config-extensions.def - (idle install dir)/config-highlight.def - (idle install dir)/config-keys.def - user config files - (user home dir)/.idlerc/config-main.cfg - (user home dir)/.idlerc/config-extensions.cfg - (user home dir)/.idlerc/config-highlight.cfg - (user home dir)/.idlerc/config-keys.cfg - """ - def __init__(self): - self.defaultCfg={} - self.userCfg={} - self.cfg={} - self.CreateConfigHandlers() - self.LoadCfgFiles() - #self.LoadCfg() - - def CreateConfigHandlers(self): - """ - set up a dictionary of config parsers for default and user - configurations respectively - """ - #build idle install path - if __name__ != '__main__': # we were imported - idleDir=os.path.dirname(__file__) - else: # we were exec'ed (for testing only) - idleDir=os.path.abspath(sys.path[0]) - userDir=self.GetUserCfgDir() - configTypes=('main','extensions','highlight','keys') - defCfgFiles={} - usrCfgFiles={} - for cfgType in configTypes: #build config file names - defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def') - usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg') - for cfgType in configTypes: #create config parsers - self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType]) - self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType]) - - def GetUserCfgDir(self): - """ - Creates (if required) and returns a filesystem directory for storing - user config files. - - """ - cfgDir = '.idlerc' - userDir = os.path.expanduser('~') - if userDir != '~': # expanduser() found user home dir - if not os.path.exists(userDir): - warn = ('\n Warning: os.path.expanduser("~") points to\n '+ - userDir+',\n but the path does not exist.\n') - sys.stderr.write(warn) - userDir = '~' - if userDir == "~": # still no path to home! - # traditionally IDLE has defaulted to os.getcwd(), is this adequate? - userDir = os.getcwd() - userDir = os.path.join(userDir, cfgDir) - if not os.path.exists(userDir): - try: - os.mkdir(userDir) - except (OSError, IOError): - warn = ('\n Warning: unable to create user config directory\n'+ - userDir+'\n Check path and permissions.\n Exiting!\n\n') - sys.stderr.write(warn) - raise SystemExit - return userDir - - def GetOption(self, configType, section, option, default=None, type=None, - warn_on_default=True): - """ - Get an option value for given config type and given general - configuration section/option or return a default. If type is specified, - return as type. Firstly the user configuration is checked, with a - fallback to the default configuration, and a final 'catch all' - fallback to a useable passed-in default if the option isn't present in - either the user or the default configuration. - configType must be one of ('main','extensions','highlight','keys') - If a default is returned, and warn_on_default is True, a warning is - printed to stderr. - - """ - if self.userCfg[configType].has_option(section,option): - return self.userCfg[configType].Get(section, option, type=type) - elif self.defaultCfg[configType].has_option(section,option): - return self.defaultCfg[configType].Get(section, option, type=type) - else: #returning default, print warning - if warn_on_default: - warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' - ' problem retrieving configration option %r\n' - ' from section %r.\n' - ' returning default value: %r\n' % - (option, section, default)) - sys.stderr.write(warning) - return default - - def SetOption(self, configType, section, option, value): - """In user's config file, set section's option to value. - - """ - self.userCfg[configType].SetOption(section, option, value) - - def GetSectionList(self, configSet, configType): - """ - Get a list of sections from either the user or default config for - the given config type. - configSet must be either 'user' or 'default' - configType must be one of ('main','extensions','highlight','keys') - """ - if not (configType in ('main','extensions','highlight','keys')): - raise InvalidConfigType, 'Invalid configType specified' - if configSet == 'user': - cfgParser=self.userCfg[configType] - elif configSet == 'default': - cfgParser=self.defaultCfg[configType] - else: - raise InvalidConfigSet, 'Invalid configSet specified' - return cfgParser.sections() - - def GetHighlight(self, theme, element, fgBg=None): - """ - return individual highlighting theme elements. - fgBg - string ('fg'or'bg') or None, if None return a dictionary - containing fg and bg colours (appropriate for passing to Tkinter in, - e.g., a tag_config call), otherwise fg or bg colour only as specified. - """ - if self.defaultCfg['highlight'].has_section(theme): - themeDict=self.GetThemeDict('default',theme) - else: - themeDict=self.GetThemeDict('user',theme) - fore=themeDict[element+'-foreground'] - if element=='cursor': #there is no config value for cursor bg - back=themeDict['normal-background'] - else: - back=themeDict[element+'-background'] - highlight={"foreground": fore,"background": back} - if not fgBg: #return dict of both colours - return highlight - else: #return specified colour only - if fgBg == 'fg': - return highlight["foreground"] - if fgBg == 'bg': - return highlight["background"] - else: - raise InvalidFgBg, 'Invalid fgBg specified' - - def GetThemeDict(self,type,themeName): - """ - type - string, 'default' or 'user' theme type - themeName - string, theme name - Returns a dictionary which holds {option:value} for each element - in the specified theme. Values are loaded over a set of ultimate last - fallback defaults to guarantee that all theme elements are present in - a newly created theme. - """ - if type == 'user': - cfgParser=self.userCfg['highlight'] - elif type == 'default': - cfgParser=self.defaultCfg['highlight'] - else: - raise InvalidTheme, 'Invalid theme type specified' - #foreground and background values are provded for each theme element - #(apart from cursor) even though all these values are not yet used - #by idle, to allow for their use in the future. Default values are - #generally black and white. - theme={ 'normal-foreground':'#000000', - 'normal-background':'#ffffff', - 'keyword-foreground':'#000000', - 'keyword-background':'#ffffff', - 'builtin-foreground':'#000000', - 'builtin-background':'#ffffff', - 'comment-foreground':'#000000', - 'comment-background':'#ffffff', - 'string-foreground':'#000000', - 'string-background':'#ffffff', - 'definition-foreground':'#000000', - 'definition-background':'#ffffff', - 'hilite-foreground':'#000000', - 'hilite-background':'gray', - 'break-foreground':'#ffffff', - 'break-background':'#000000', - 'hit-foreground':'#ffffff', - 'hit-background':'#000000', - 'error-foreground':'#ffffff', - 'error-background':'#000000', - #cursor (only foreground can be set) - 'cursor-foreground':'#000000', - #shell window - 'stdout-foreground':'#000000', - 'stdout-background':'#ffffff', - 'stderr-foreground':'#000000', - 'stderr-background':'#ffffff', - 'console-foreground':'#000000', - 'console-background':'#ffffff' } - for element in theme.keys(): - if not cfgParser.has_option(themeName,element): - #we are going to return a default, print warning - warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict' - ' -\n problem retrieving theme element %r' - '\n from theme %r.\n' - ' returning default value: %r\n' % - (element, themeName, theme[element])) - sys.stderr.write(warning) - colour=cfgParser.Get(themeName,element,default=theme[element]) - theme[element]=colour - return theme - - def CurrentTheme(self): - """ - Returns the name of the currently active theme - """ - return self.GetOption('main','Theme','name',default='') - - def CurrentKeys(self): - """ - Returns the name of the currently active key set - """ - return self.GetOption('main','Keys','name',default='') - - def GetExtensions(self, active_only=True, editor_only=False, shell_only=False): - """ - Gets a list of all idle extensions declared in the config files. - active_only - boolean, if true only return active (enabled) extensions - """ - extns=self.RemoveKeyBindNames( - self.GetSectionList('default','extensions')) - userExtns=self.RemoveKeyBindNames( - self.GetSectionList('user','extensions')) - for extn in userExtns: - if extn not in extns: #user has added own extension - extns.append(extn) - if active_only: - activeExtns=[] - for extn in extns: - if self.GetOption('extensions', extn, 'enable', default=True, - type='bool'): - #the extension is enabled - if editor_only or shell_only: - if editor_only: - option = "enable_editor" - else: - option = "enable_shell" - if self.GetOption('extensions', extn,option, - default=True, type='bool', - warn_on_default=False): - activeExtns.append(extn) - else: - activeExtns.append(extn) - return activeExtns - else: - return extns - - def RemoveKeyBindNames(self,extnNameList): - #get rid of keybinding section names - names=extnNameList - kbNameIndicies=[] - for name in names: - if name.endswith(('_bindings', '_cfgBindings')): - kbNameIndicies.append(names.index(name)) - kbNameIndicies.sort() - kbNameIndicies.reverse() - for index in kbNameIndicies: #delete each keybinding section name - del(names[index]) - return names - - def GetExtnNameForEvent(self,virtualEvent): - """ - Returns the name of the extension that virtualEvent is bound in, or - None if not bound in any extension. - virtualEvent - string, name of the virtual event to test for, without - the enclosing '<< >>' - """ - extName=None - vEvent='<<'+virtualEvent+'>>' - for extn in self.GetExtensions(active_only=0): - for event in self.GetExtensionKeys(extn).keys(): - if event == vEvent: - extName=extn - return extName - - def GetExtensionKeys(self,extensionName): - """ - returns a dictionary of the configurable keybindings for a particular - extension,as they exist in the dictionary returned by GetCurrentKeySet; - that is, where previously used bindings are disabled. - """ - keysName=extensionName+'_cfgBindings' - activeKeys=self.GetCurrentKeySet() - extKeys={} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - event='<<'+eventName+'>>' - binding=activeKeys[event] - extKeys[event]=binding - return extKeys - - def __GetRawExtensionKeys(self,extensionName): - """ - returns a dictionary of the configurable keybindings for a particular - extension, as defined in the configuration files, or an empty dictionary - if no bindings are found - """ - keysName=extensionName+'_cfgBindings' - extKeys={} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - binding=self.GetOption('extensions',keysName, - eventName,default='').split() - event='<<'+eventName+'>>' - extKeys[event]=binding - return extKeys - - def GetExtensionBindings(self,extensionName): - """ - Returns a dictionary of all the event bindings for a particular - extension. The configurable keybindings are returned as they exist in - the dictionary returned by GetCurrentKeySet; that is, where re-used - keybindings are disabled. - """ - bindsName=extensionName+'_bindings' - extBinds=self.GetExtensionKeys(extensionName) - #add the non-configurable bindings - if self.defaultCfg['extensions'].has_section(bindsName): - eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName) - for eventName in eventNames: - binding=self.GetOption('extensions',bindsName, - eventName,default='').split() - event='<<'+eventName+'>>' - extBinds[event]=binding - - return extBinds - - def GetKeyBinding(self, keySetName, eventStr): - """ - returns the keybinding for a specific event. - keySetName - string, name of key binding set - eventStr - string, the virtual event we want the binding for, - represented as a string, eg. '<<event>>' - """ - eventName=eventStr[2:-2] #trim off the angle brackets - binding=self.GetOption('keys',keySetName,eventName,default='').split() - return binding - - def GetCurrentKeySet(self): - result = self.GetKeySet(self.CurrentKeys()) - - if macosxSupport.runningAsOSXApp(): - # We're using AquaTk, replace all keybingings that use the - # Alt key by ones that use the Option key because the former - # don't work reliably. - for k, v in result.items(): - v2 = [ x.replace('<Alt-', '<Option-') for x in v ] - if v != v2: - result[k] = v2 - - return result - - def GetKeySet(self,keySetName): - """ - Returns a dictionary of: all requested core keybindings, plus the - keybindings for all currently active extensions. If a binding defined - in an extension is already in use, that binding is disabled. - """ - keySet=self.GetCoreKeys(keySetName) - activeExtns=self.GetExtensions(active_only=1) - for extn in activeExtns: - extKeys=self.__GetRawExtensionKeys(extn) - if extKeys: #the extension defines keybindings - for event in extKeys.keys(): - if extKeys[event] in keySet.values(): - #the binding is already in use - extKeys[event]='' #disable this binding - keySet[event]=extKeys[event] #add binding - return keySet - - def IsCoreBinding(self,virtualEvent): - """ - returns true if the virtual event is bound in the core idle keybindings. - virtualEvent - string, name of the virtual event to test for, without - the enclosing '<< >>' - """ - return ('<<'+virtualEvent+'>>') in self.GetCoreKeys().keys() - - def GetCoreKeys(self, keySetName=None): - """ - returns the requested set of core keybindings, with fallbacks if - required. - Keybindings loaded from the config file(s) are loaded _over_ these - defaults, so if there is a problem getting any core binding there will - be an 'ultimate last resort fallback' to the CUA-ish bindings - defined here. - """ - keyBindings={ - '<<copy>>': ['<Control-c>', '<Control-C>'], - '<<cut>>': ['<Control-x>', '<Control-X>'], - '<<paste>>': ['<Control-v>', '<Control-V>'], - '<<beginning-of-line>>': ['<Control-a>', '<Home>'], - '<<center-insert>>': ['<Control-l>'], - '<<close-all-windows>>': ['<Control-q>'], - '<<close-window>>': ['<Alt-F4>'], - '<<do-nothing>>': ['<Control-x>'], - '<<end-of-file>>': ['<Control-d>'], - '<<python-docs>>': ['<F1>'], - '<<python-context-help>>': ['<Shift-F1>'], - '<<history-next>>': ['<Alt-n>'], - '<<history-previous>>': ['<Alt-p>'], - '<<interrupt-execution>>': ['<Control-c>'], - '<<view-restart>>': ['<F6>'], - '<<restart-shell>>': ['<Control-F6>'], - '<<open-class-browser>>': ['<Alt-c>'], - '<<open-module>>': ['<Alt-m>'], - '<<open-new-window>>': ['<Control-n>'], - '<<open-window-from-file>>': ['<Control-o>'], - '<<plain-newline-and-indent>>': ['<Control-j>'], - '<<print-window>>': ['<Control-p>'], - '<<redo>>': ['<Control-y>'], - '<<remove-selection>>': ['<Escape>'], - '<<save-copy-of-window-as-file>>': ['<Alt-Shift-S>'], - '<<save-window-as-file>>': ['<Alt-s>'], - '<<save-window>>': ['<Control-s>'], - '<<select-all>>': ['<Alt-a>'], - '<<toggle-auto-coloring>>': ['<Control-slash>'], - '<<undo>>': ['<Control-z>'], - '<<find-again>>': ['<Control-g>', '<F3>'], - '<<find-in-files>>': ['<Alt-F3>'], - '<<find-selection>>': ['<Control-F3>'], - '<<find>>': ['<Control-f>'], - '<<replace>>': ['<Control-h>'], - '<<goto-line>>': ['<Alt-g>'], - '<<smart-backspace>>': ['<Key-BackSpace>'], - '<<newline-and-indent>>': ['<Key-Return> <Key-KP_Enter>'], - '<<smart-indent>>': ['<Key-Tab>'], - '<<indent-region>>': ['<Control-Key-bracketright>'], - '<<dedent-region>>': ['<Control-Key-bracketleft>'], - '<<comment-region>>': ['<Alt-Key-3>'], - '<<uncomment-region>>': ['<Alt-Key-4>'], - '<<tabify-region>>': ['<Alt-Key-5>'], - '<<untabify-region>>': ['<Alt-Key-6>'], - '<<toggle-tabs>>': ['<Alt-Key-t>'], - '<<change-indentwidth>>': ['<Alt-Key-u>'], - '<<del-word-left>>': ['<Control-Key-BackSpace>'], - '<<del-word-right>>': ['<Control-Key-Delete>'] - } - if keySetName: - for event in keyBindings.keys(): - binding=self.GetKeyBinding(keySetName,event) - if binding: - keyBindings[event]=binding - else: #we are going to return a default, print warning - warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys' - ' -\n problem retrieving key binding for event %r' - '\n from key set %r.\n' - ' returning default value: %r\n' % - (event, keySetName, keyBindings[event])) - sys.stderr.write(warning) - return keyBindings - - def GetExtraHelpSourceList(self,configSet): - """Fetch list of extra help sources from a given configSet. - - Valid configSets are 'user' or 'default'. Return a list of tuples of - the form (menu_item , path_to_help_file , option), or return the empty - list. 'option' is the sequence number of the help resource. 'option' - values determine the position of the menu items on the Help menu, - therefore the returned list must be sorted by 'option'. - - """ - helpSources=[] - if configSet=='user': - cfgParser=self.userCfg['main'] - elif configSet=='default': - cfgParser=self.defaultCfg['main'] - else: - raise InvalidConfigSet, 'Invalid configSet specified' - options=cfgParser.GetOptionList('HelpFiles') - for option in options: - value=cfgParser.Get('HelpFiles',option,default=';') - if value.find(';')==-1: #malformed config entry with no ';' - menuItem='' #make these empty - helpPath='' #so value won't be added to list - else: #config entry contains ';' as expected - value=string.split(value,';') - menuItem=value[0].strip() - helpPath=value[1].strip() - if menuItem and helpPath: #neither are empty strings - helpSources.append( (menuItem,helpPath,option) ) - helpSources.sort(self.__helpsort) - return helpSources - - def __helpsort(self, h1, h2): - if int(h1[2]) < int(h2[2]): - return -1 - elif int(h1[2]) > int(h2[2]): - return 1 - else: - return 0 - - def GetAllExtraHelpSourcesList(self): - """ - Returns a list of tuples containing the details of all additional help - sources configured, or an empty list if there are none. Tuples are of - the format returned by GetExtraHelpSourceList. - """ - allHelpSources=( self.GetExtraHelpSourceList('default')+ - self.GetExtraHelpSourceList('user') ) - return allHelpSources - - def LoadCfgFiles(self): - """ - load all configuration files. - """ - for key in self.defaultCfg.keys(): - self.defaultCfg[key].Load() - self.userCfg[key].Load() #same keys - - def SaveUserCfgFiles(self): - """ - write all loaded user configuration files back to disk - """ - for key in self.userCfg.keys(): - self.userCfg[key].Save() - -idleConf=IdleConf() - -### module test -if __name__ == '__main__': - def dumpCfg(cfg): - print '\n',cfg,'\n' - for key in cfg.keys(): - sections=cfg[key].sections() - print key - print sections - for section in sections: - options=cfg[key].options(section) - print section - print options - for option in options: - print option, '=', cfg[key].Get(section,option) - dumpCfg(idleConf.defaultCfg) - dumpCfg(idleConf.userCfg) - print idleConf.userCfg['main'].Get('Theme','name') - #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal') diff --git a/sys/lib/python/idlelib/configHelpSourceEdit.py b/sys/lib/python/idlelib/configHelpSourceEdit.py deleted file mode 100644 index 661162196..000000000 --- a/sys/lib/python/idlelib/configHelpSourceEdit.py +++ /dev/null @@ -1,169 +0,0 @@ -"Dialog to specify or edit the parameters for a user configured help source." - -import os -import sys - -from Tkinter import * -import tkMessageBox -import tkFileDialog - -class GetHelpSourceDialog(Toplevel): - def __init__(self, parent, title, menuItem='', filePath=''): - """Get menu entry and url/ local file location for Additional Help - - User selects a name for the Help resource and provides a web url - or a local file as its source. The user can enter a url or browse - for the file. - - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE, width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.result = None - self.CreateWidgets() - self.menu.set(menuItem) - self.path.set(filePath) - self.withdraw() #hide while setting geometry - #needs to be done here so that the winfo_reqwidth is valid - self.update_idletasks() - #centre dialog over parent: - self.geometry("+%d+%d" % - ((parent.winfo_rootx() + ((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty() + ((parent.winfo_height()/2) - -(self.winfo_reqheight()/2))))) - self.deiconify() #geometry set, unhide - self.bind('<Return>', self.Ok) - self.wait_window() - - def CreateWidgets(self): - self.menu = StringVar(self) - self.path = StringVar(self) - self.fontSize = StringVar(self) - self.frameMain = Frame(self, borderwidth=2, relief=GROOVE) - self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) - labelMenu = Label(self.frameMain, anchor=W, justify=LEFT, - text='Menu Item:') - self.entryMenu = Entry(self.frameMain, textvariable=self.menu, - width=30) - self.entryMenu.focus_set() - labelPath = Label(self.frameMain, anchor=W, justify=LEFT, - text='Help File Path: Enter URL or browse for file') - self.entryPath = Entry(self.frameMain, textvariable=self.path, - width=40) - self.entryMenu.focus_set() - labelMenu.pack(anchor=W, padx=5, pady=3) - self.entryMenu.pack(anchor=W, padx=5, pady=3) - labelPath.pack(anchor=W, padx=5, pady=3) - self.entryPath.pack(anchor=W, padx=5, pady=3) - browseButton = Button(self.frameMain, text='Browse', width=8, - command=self.browseFile) - browseButton.pack(pady=3) - frameButtons = Frame(self) - frameButtons.pack(side=BOTTOM, fill=X) - self.buttonOk = Button(frameButtons, text='OK', - width=8, default=ACTIVE, command=self.Ok) - self.buttonOk.grid(row=0, column=0, padx=5,pady=5) - self.buttonCancel = Button(frameButtons, text='Cancel', - width=8, command=self.Cancel) - self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) - - def browseFile(self): - filetypes = [ - ("HTML Files", "*.htm *.html", "TEXT"), - ("PDF Files", "*.pdf", "TEXT"), - ("Windows Help Files", "*.chm"), - ("Text Files", "*.txt", "TEXT"), - ("All Files", "*")] - path = self.path.get() - if path: - dir, base = os.path.split(path) - else: - base = None - if sys.platform[:3] == 'win': - dir = os.path.join(os.path.dirname(sys.executable), 'Doc') - if not os.path.isdir(dir): - dir = os.getcwd() - else: - dir = os.getcwd() - opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes) - file = opendialog.show(initialdir=dir, initialfile=base) - if file: - self.path.set(file) - - def MenuOk(self): - "Simple validity check for a sensible menu item name" - menuOk = True - menu = self.menu.get() - menu.strip() - if not menu: - tkMessageBox.showerror(title='Menu Item Error', - message='No menu item specified', - parent=self) - self.entryMenu.focus_set() - menuOk = False - elif len(menu) > 30: - tkMessageBox.showerror(title='Menu Item Error', - message='Menu item too long:' - '\nLimit 30 characters.', - parent=self) - self.entryMenu.focus_set() - menuOk = False - return menuOk - - def PathOk(self): - "Simple validity check for menu file path" - pathOk = True - path = self.path.get() - path.strip() - if not path: #no path specified - tkMessageBox.showerror(title='File Path Error', - message='No help file path specified.', - parent=self) - self.entryPath.focus_set() - pathOk = False - elif path.startswith(('www.', 'http')): - pass - else: - if path[:5] == 'file:': - path = path[5:] - if not os.path.exists(path): - tkMessageBox.showerror(title='File Path Error', - message='Help file path does not exist.', - parent=self) - self.entryPath.focus_set() - pathOk = False - return pathOk - - def Ok(self, event=None): - if self.MenuOk() and self.PathOk(): - self.result = (self.menu.get().strip(), - self.path.get().strip()) - if sys.platform == 'darwin': - path = self.result[1] - if path.startswith(('www', 'file:', 'http:')): - pass - else: - # Mac Safari insists on using the URI form for local files - self.result = list(self.result) - self.result[1] = "file://" + path - self.destroy() - - def Cancel(self, event=None): - self.result = None - self.destroy() - -if __name__ == '__main__': - #test the dialog - root = Tk() - def run(): - keySeq = '' - dlg = GetHelpSourceDialog(root, 'Get Help Source') - print dlg.result - Button(root,text='Dialog', command=run).pack() - root.mainloop() diff --git a/sys/lib/python/idlelib/configSectionNameDialog.py b/sys/lib/python/idlelib/configSectionNameDialog.py deleted file mode 100644 index 4f1b002af..000000000 --- a/sys/lib/python/idlelib/configSectionNameDialog.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Dialog that allows user to specify a new config file section name. -Used to get new highlight theme and keybinding set names. -""" -from Tkinter import * -import tkMessageBox - -class GetCfgSectionNameDialog(Toplevel): - def __init__(self,parent,title,message,usedNames): - """ - message - string, informational message to display - usedNames - list, list of names already in use for validity check - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE,width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.message=message - self.usedNames=usedNames - self.result='' - self.CreateWidgets() - self.withdraw() #hide while setting geometry - self.update_idletasks() - #needs to be done here so that the winfo_reqwidth is valid - self.messageInfo.config(width=self.frameMain.winfo_reqwidth()) - self.geometry("+%d+%d" % - ((parent.winfo_rootx()+((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty()+((parent.winfo_height()/2) - -(self.winfo_reqheight()/2)) )) ) #centre dialog over parent - self.deiconify() #geometry set, unhide - self.wait_window() - - def CreateWidgets(self): - self.name=StringVar(self) - self.fontSize=StringVar(self) - self.frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - self.frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - self.messageInfo=Message(self.frameMain,anchor=W,justify=LEFT,padx=5,pady=5, - text=self.message)#,aspect=200) - entryName=Entry(self.frameMain,textvariable=self.name,width=30) - entryName.focus_set() - self.messageInfo.pack(padx=5,pady=5)#,expand=TRUE,fill=BOTH) - entryName.pack(padx=5,pady=5) - frameButtons=Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - self.buttonOk = Button(frameButtons,text='Ok', - width=8,command=self.Ok) - self.buttonOk.grid(row=0,column=0,padx=5,pady=5) - self.buttonCancel = Button(frameButtons,text='Cancel', - width=8,command=self.Cancel) - self.buttonCancel.grid(row=0,column=1,padx=5,pady=5) - - def NameOk(self): - #simple validity check for a sensible - #ConfigParser file section name - nameOk=1 - name=self.name.get() - name.strip() - if not name: #no name specified - tkMessageBox.showerror(title='Name Error', - message='No name specified.', parent=self) - nameOk=0 - elif len(name)>30: #name too long - tkMessageBox.showerror(title='Name Error', - message='Name too long. It should be no more than '+ - '30 characters.', parent=self) - nameOk=0 - elif name in self.usedNames: - tkMessageBox.showerror(title='Name Error', - message='This name is already in use.', parent=self) - nameOk=0 - return nameOk - - def Ok(self, event=None): - if self.NameOk(): - self.result=self.name.get().strip() - self.destroy() - - def Cancel(self, event=None): - self.result='' - self.destroy() - -if __name__ == '__main__': - #test the dialog - root=Tk() - def run(): - keySeq='' - dlg=GetCfgSectionNameDialog(root,'Get Name', - 'The information here should need to be word wrapped. Test.') - print dlg.result - Button(root,text='Dialog',command=run).pack() - root.mainloop() diff --git a/sys/lib/python/idlelib/dynOptionMenuWidget.py b/sys/lib/python/idlelib/dynOptionMenuWidget.py deleted file mode 100644 index e81f7babe..000000000 --- a/sys/lib/python/idlelib/dynOptionMenuWidget.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -OptionMenu widget modified to allow dynamic menu reconfiguration -and setting of highlightthickness -""" -from Tkinter import OptionMenu -from Tkinter import _setit -import copy - -class DynOptionMenu(OptionMenu): - """ - unlike OptionMenu, our kwargs can include highlightthickness - """ - def __init__(self, master, variable, value, *values, **kwargs): - #get a copy of kwargs before OptionMenu.__init__ munges them - kwargsCopy=copy.copy(kwargs) - if 'highlightthickness' in kwargs.keys(): - del(kwargs['highlightthickness']) - OptionMenu.__init__(self, master, variable, value, *values, **kwargs) - self.config(highlightthickness=kwargsCopy.get('highlightthickness')) - #self.menu=self['menu'] - self.variable=variable - self.command=kwargs.get('command') - - def SetMenu(self,valueList,value=None): - """ - clear and reload the menu with a new set of options. - valueList - list of new options - value - initial value to set the optionmenu's menubutton to - """ - self['menu'].delete(0,'end') - for item in valueList: - self['menu'].add_command(label=item, - command=_setit(self.variable,item,self.command)) - if value: - self.variable.set(value) diff --git a/sys/lib/python/idlelib/extend.txt b/sys/lib/python/idlelib/extend.txt deleted file mode 100644 index f5fb3e040..000000000 --- a/sys/lib/python/idlelib/extend.txt +++ /dev/null @@ -1,83 +0,0 @@ -Writing an IDLE extension -========================= - -An IDLE extension can define new key bindings and menu entries for IDLE -edit windows. There is a simple mechanism to load extensions when IDLE -starts up and to attach them to each edit window. (It is also possible -to make other changes to IDLE, but this must be done by editing the IDLE -source code.) - -The list of extensions loaded at startup time is configured by editing -the file config-extensions.def. See below for details. - -An IDLE extension is defined by a class. Methods of the class define -actions that are invoked by event bindings or menu entries. Class (or -instance) variables define the bindings and menu additions; these are -automatically applied by IDLE when the extension is linked to an edit -window. - -An IDLE extension class is instantiated with a single argument, -`editwin', an EditorWindow instance. The extension cannot assume much -about this argument, but it is guarateed to have the following instance -variables: - - text a Text instance (a widget) - io an IOBinding instance (more about this later) - flist the FileList instance (shared by all edit windows) - -(There are a few more, but they are rarely useful.) - -The extension class must not directly bind Window Manager (e.g. X) events. -Rather, it must define one or more virtual events, e.g. <<zoom-height>>, and -corresponding methods, e.g. zoom_height_event(). The virtual events will be -bound to the corresponding methods, and Window Manager events can then be bound -to the virtual events. (This indirection is done so that the key bindings can -easily be changed, and so that other sources of virtual events can exist, such -as menu entries.) - -An extension can define menu entries. This is done with a class or instance -variable named menudefs; it should be a list of pairs, where each pair is a -menu name (lowercase) and a list of menu entries. Each menu entry is either -None (to insert a separator entry) or a pair of strings (menu_label, -virtual_event). Here, menu_label is the label of the menu entry, and -virtual_event is the virtual event to be generated when the entry is selected. -An underscore in the menu label is removed; the character following the -underscore is displayed underlined, to indicate the shortcut character (for -Windows). - -At the moment, extensions cannot define whole new menus; they must define -entries in existing menus. Some menus are not present on some windows; such -entry definitions are then ignored, but key bindings are still applied. (This -should probably be refined in the future.) - -Extensions are not required to define menu entries for all the events they -implement. (They are also not required to create keybindings, but in that -case there must be empty bindings in cofig-extensions.def) - -Here is a complete example example: - -class ZoomHeight: - - menudefs = [ - ('edit', [ - None, # Separator - ('_Zoom Height', '<<zoom-height>>'), - ]) - ] - - def __init__(self, editwin): - self.editwin = editwin - - def zoom_height_event(self, event): - "...Do what you want here..." - -The final piece of the puzzle is the file "config-extensions.def", which is -used to to configure the loading of extensions and to establish key (or, more -generally, event) bindings to the virtual events defined in the extensions. - -See the comments at the top of config-extensions.def for information. It's -currently necessary to manually modify that file to change IDLE's extension -loading or extension key bindings. - -For further information on binding refer to the Tkinter Resources web page at -python.org and to the Tk Command "bind" man page. diff --git a/sys/lib/python/idlelib/help.txt b/sys/lib/python/idlelib/help.txt deleted file mode 100644 index 6d2ba2fff..000000000 --- a/sys/lib/python/idlelib/help.txt +++ /dev/null @@ -1,213 +0,0 @@ -[See the end of this file for ** TIPS ** on using IDLE !!] - -Click on the dotted line at the top of a menu to "tear it off": a -separate window containing the menu is created. - -File Menu: - - New Window -- Create a new editing window - Open... -- Open an existing file - Recent Files... -- Open a list of recent files - Open Module... -- Open an existing module (searches sys.path) - Class Browser -- Show classes and methods in current file - Path Browser -- Show sys.path directories, modules, classes - and methods - --- - Save -- Save current window to the associated file (unsaved - windows have a * before and after the window title) - - Save As... -- Save current window to new file, which becomes - the associated file - Save Copy As... -- Save current window to different file - without changing the associated file - --- - Print Window -- Print the current window - --- - Close -- Close current window (asks to save if unsaved) - Exit -- Close all windows, quit (asks to save if unsaved) - -Edit Menu: - - Undo -- Undo last change to current window - (A maximum of 1000 changes may be undone) - Redo -- Redo last undone change to current window - --- - Cut -- Copy a selection into system-wide clipboard, - then delete the selection - Copy -- Copy selection into system-wide clipboard - Paste -- Insert system-wide clipboard into window - Select All -- Select the entire contents of the edit buffer - --- - Find... -- Open a search dialog box with many options - Find Again -- Repeat last search - Find Selection -- Search for the string in the selection - Find in Files... -- Open a search dialog box for searching files - Replace... -- Open a search-and-replace dialog box - Go to Line -- Ask for a line number and show that line - Expand Word -- Expand the word you have typed to match another - word in the same buffer; repeat to get a - different expansion - -Format Menu (only in Edit window): - - Indent Region -- Shift selected lines right 4 spaces - Dedent Region -- Shift selected lines left 4 spaces - Comment Out Region -- Insert ## in front of selected lines - Uncomment Region -- Remove leading # or ## from selected lines - Tabify Region -- Turns *leading* stretches of spaces into tabs - (Note: We recommend using 4 space blocks to indent Python code.) - Untabify Region -- Turn *all* tabs into the right number of spaces - New Indent Width... -- Open dialog to change indent width - Format Paragraph -- Reformat the current blank-line-separated - paragraph - -Run Menu (only in Edit window): - - Python Shell -- Open or wake up the Python shell window - --- - Check Module -- Run a syntax check on the module - Run Module -- Execute the current file in the __main__ namespace - -Shell Menu (only in Shell window): - - View Last Restart -- Scroll the shell window to the last restart - Restart Shell -- Restart the interpreter with a fresh environment - -Debug Menu (only in Shell window): - - Go to File/Line -- look around the insert point for a filename - and linenumber, open the file, and show the line - Debugger (toggle) -- Run commands in the shell under the debugger - Stack Viewer -- Show the stack traceback of the last exception - Auto-open Stack Viewer (toggle) -- Open stack viewer on traceback - -Options Menu: - - Configure IDLE -- Open a configuration dialog. Fonts, indentation, - keybindings, and color themes may be altered. - Startup Preferences may be set, and Additional Help - Souces can be specified. - --- - Code Context -- Open a pane at the top of the edit window which - shows the block context of the section of code - which is scrolling off the top or the window. - -Windows Menu: - - Zoom Height -- toggles the window between configured size - and maximum height. - --- - The rest of this menu lists the names of all open windows; - select one to bring it to the foreground (deiconifying it if - necessary). - -Help Menu: - - About IDLE -- Version, copyright, license, credits - IDLE Readme -- Background discussion and change details - --- - IDLE Help -- Display this file - Python Docs -- Access local Python documentation, if - installed. Otherwise, access www.python.org. - --- - (Additional Help Sources may be added here) - - -** TIPS ** -========== - -Additional Help Sources: - - Windows users can Google on zopeshelf.chm to access Zope help files in - the Windows help format. The Additional Help Sources feature of the - configuration GUI supports .chm, along with any other filetypes - supported by your browser. Supply a Menu Item title, and enter the - location in the Help File Path slot of the New Help Source dialog. Use - http:// and/or www. to identify external URLs, or download the file and - browse for its path on your machine using the Browse button. - - All users can access the extensive sources of help, including - tutorials, available at www.python.org/doc. Selected URLs can be added - or removed from the Help menu at any time using Configure IDLE. - -Basic editing and navigation: - - Backspace deletes char to the left; DEL deletes char to the right. - Control-backspace deletes word left, Control-DEL deletes word right. - Arrow keys and Page Up/Down move around. - Control-left/right Arrow moves by words in a strange but useful way. - Home/End go to begin/end of line. - Control-Home/End go to begin/end of file. - Some useful Emacs bindings (Control-a, Control-e, Control-k, etc.) - are inherited from Tcl/Tk. - Standard Windows bindings may work on that platform. - Keybindings are selected in the Settings Dialog, look there. - -Automatic indentation: - - After a block-opening statement, the next line is indented by 4 spaces - (in the Python Shell window by one tab). After certain keywords - (break, return etc.) the next line is dedented. In leading - indentation, Backspace deletes up to 4 spaces if they are there. Tab - inserts spaces (in the Python Shell window one tab), number depends on - Indent Width. (N.B. Currently tabs are restricted to four spaces due - to Tcl/Tk issues.) - - See also the indent/dedent region commands in the edit menu. - -Python Shell window: - - Control-c interrupts executing command. - Control-d sends end-of-file; closes window if typed at >>> prompt - (this is Control-z on Windows). - - Command history: - - Alt-p retrieves previous command matching what you have typed. - Alt-n retrieves next. - (These are Control-p, Control-n on the Mac) - Return while cursor is on a previous command retrieves that command. - Expand word is also useful to reduce typing. - - Syntax colors: - - The coloring is applied in a background "thread", so you may - occasionally see uncolorized text. To change the color - scheme, use the Configure IDLE / Highlighting dialog. - - Python default syntax colors: - - Keywords orange - Builtins royal purple - Strings green - Comments red - Definitions blue - - Shell default colors: - - Console output brown - stdout blue - stderr red - stdin black - -Other preferences: - - The font preferences, keybinding, and startup preferences can - be changed using the Settings dialog. - -Command line usage: - - Enter idle -h at the command prompt to get a usage message. - -Running without a subprocess: - - If IDLE is started with the -n command line switch it will run in a - single process and will not create the subprocess which runs the RPC - Python execution server. This can be useful if Python cannot create - the subprocess or the RPC socket interface on your platform. However, - in this mode user code is not isolated from IDLE itself. Also, the - environment is not restarted when Run/Run Module (F5) is selected. If - your code has been modified, you must reload() the affected modules and - re-import any specific items (e.g. from foo import baz) if the changes - are to take effect. For these reasons, it is preferable to run IDLE - with the default subprocess if at all possible. diff --git a/sys/lib/python/idlelib/idle.bat b/sys/lib/python/idlelib/idle.bat deleted file mode 100755 index c1b5fd28a..000000000 --- a/sys/lib/python/idlelib/idle.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off -rem Working IDLE bat for Windows - uses start instead of absolute pathname -start idle.pyw %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/sys/lib/python/idlelib/idle.py b/sys/lib/python/idlelib/idle.py deleted file mode 100644 index 537dd5a9a..000000000 --- a/sys/lib/python/idlelib/idle.py +++ /dev/null @@ -1,21 +0,0 @@ -try: - import idlelib.PyShell -except ImportError: - # IDLE is not installed, but maybe PyShell is on sys.path: - try: - import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() -else: - idlelib.PyShell.main() diff --git a/sys/lib/python/idlelib/idle.pyw b/sys/lib/python/idlelib/idle.pyw deleted file mode 100644 index 537dd5a9a..000000000 --- a/sys/lib/python/idlelib/idle.pyw +++ /dev/null @@ -1,21 +0,0 @@ -try: - import idlelib.PyShell -except ImportError: - # IDLE is not installed, but maybe PyShell is on sys.path: - try: - import PyShell - except ImportError: - raise - else: - import os - idledir = os.path.dirname(os.path.abspath(PyShell.__file__)) - if idledir != os.getcwd(): - # We're not in the IDLE directory, help the subprocess find run.py - pypath = os.environ.get('PYTHONPATH', '') - if pypath: - os.environ['PYTHONPATH'] = pypath + ':' + idledir - else: - os.environ['PYTHONPATH'] = idledir - PyShell.main() -else: - idlelib.PyShell.main() diff --git a/sys/lib/python/idlelib/idlever.py b/sys/lib/python/idlelib/idlever.py deleted file mode 100644 index 9f7fb5a5b..000000000 --- a/sys/lib/python/idlelib/idlever.py +++ /dev/null @@ -1 +0,0 @@ -IDLE_VERSION = "1.2.1" diff --git a/sys/lib/python/idlelib/keybindingDialog.py b/sys/lib/python/idlelib/keybindingDialog.py deleted file mode 100644 index aff9cac58..000000000 --- a/sys/lib/python/idlelib/keybindingDialog.py +++ /dev/null @@ -1,268 +0,0 @@ -""" -Dialog for building Tkinter accelerator key bindings -""" -from Tkinter import * -import tkMessageBox -import string, os - -class GetKeysDialog(Toplevel): - def __init__(self,parent,title,action,currentKeySequences): - """ - action - string, the name of the virtual event these keys will be - mapped to - currentKeys - list, a list of all key sequence lists currently mapped - to virtual events, for overlap checking - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE,width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.action=action - self.currentKeySequences=currentKeySequences - self.result='' - self.keyString=StringVar(self) - self.keyString.set('') - self.SetModifiersForPlatform() # set self.modifiers, self.modifier_label - self.modifier_vars = [] - for modifier in self.modifiers: - variable = StringVar(self) - variable.set('') - self.modifier_vars.append(variable) - self.advanced = False - self.CreateWidgets() - self.LoadFinalKeyList() - self.withdraw() #hide while setting geometry - self.update_idletasks() - self.geometry("+%d+%d" % - ((parent.winfo_rootx()+((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty()+((parent.winfo_height()/2) - -(self.winfo_reqheight()/2)) )) ) #centre dialog over parent - self.deiconify() #geometry set, unhide - self.wait_window() - - def CreateWidgets(self): - frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - frameButtons=Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - self.buttonOK = Button(frameButtons,text='OK', - width=8,command=self.OK) - self.buttonOK.grid(row=0,column=0,padx=5,pady=5) - self.buttonCancel = Button(frameButtons,text='Cancel', - width=8,command=self.Cancel) - self.buttonCancel.grid(row=0,column=1,padx=5,pady=5) - self.frameKeySeqBasic = Frame(frameMain) - self.frameKeySeqAdvanced = Frame(frameMain) - self.frameControlsBasic = Frame(frameMain) - self.frameHelpAdvanced = Frame(frameMain) - self.frameKeySeqAdvanced.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.lift() - self.frameHelpAdvanced.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.lift() - self.buttonLevel = Button(frameMain,command=self.ToggleLevel, - text='Advanced Key Binding Entry >>') - self.buttonLevel.grid(row=2,column=0,stick=EW,padx=5,pady=5) - labelTitleBasic = Label(self.frameKeySeqBasic, - text="New keys for '"+self.action+"' :") - labelTitleBasic.pack(anchor=W) - labelKeysBasic = Label(self.frameKeySeqBasic,justify=LEFT, - textvariable=self.keyString,relief=GROOVE,borderwidth=2) - labelKeysBasic.pack(ipadx=5,ipady=5,fill=X) - self.modifier_checkbuttons = {} - column = 0 - for modifier, variable in zip(self.modifiers, self.modifier_vars): - label = self.modifier_label.get(modifier, modifier) - check=Checkbutton(self.frameControlsBasic, - command=self.BuildKeyString, - text=label,variable=variable,onvalue=modifier,offvalue='') - check.grid(row=0,column=column,padx=2,sticky=W) - self.modifier_checkbuttons[modifier] = check - column += 1 - labelFnAdvice=Label(self.frameControlsBasic,justify=LEFT, - text=\ - "Select the desired modifier keys\n"+ - "above, and the final key from the\n"+ - "list on the right.\n\n" + - "Use upper case Symbols when using\n" + - "the Shift modifier. (Letters will be\n" + - "converted automatically.)") - labelFnAdvice.grid(row=1,column=0,columnspan=4,padx=2,sticky=W) - self.listKeysFinal=Listbox(self.frameControlsBasic,width=15,height=10, - selectmode=SINGLE) - self.listKeysFinal.bind('<ButtonRelease-1>',self.FinalKeySelected) - self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS) - scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL, - command=self.listKeysFinal.yview) - self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set) - scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS) - self.buttonClear=Button(self.frameControlsBasic, - text='Clear Keys',command=self.ClearKeySeq) - self.buttonClear.grid(row=2,column=0,columnspan=4) - labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT, - text="Enter new binding(s) for '"+self.action+"' :\n"+ - "(These bindings will not be checked for validity!)") - labelTitleAdvanced.pack(anchor=W) - self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced, - textvariable=self.keyString) - self.entryKeysAdvanced.pack(fill=X) - labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT, - text="Key bindings are specified using Tkinter keysyms as\n"+ - "in these samples: <Control-f>, <Shift-F2>, <F12>,\n" - "<Control-space>, <Meta-less>, <Control-Alt-Shift-X>.\n" - "Upper case is used when the Shift modifier is present!\n\n" + - "'Emacs style' multi-keystroke bindings are specified as\n" + - "follows: <Control-x><Control-y>, where the first key\n" + - "is the 'do-nothing' keybinding.\n\n" + - "Multiple separate bindings for one action should be\n"+ - "separated by a space, eg., <Alt-v> <Meta-v>." ) - labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW) - - def SetModifiersForPlatform(self): - """Determine list of names of key modifiers for this platform. - - The names are used to build Tk bindings -- it doesn't matter if the - keyboard has these keys, it matters if Tk understands them. The - order is also important: key binding equality depends on it, so - config-keys.def must use the same ordering. - """ - import sys - if sys.platform == 'darwin' and sys.argv[0].count('.app'): - self.modifiers = ['Shift', 'Control', 'Option', 'Command'] - else: - self.modifiers = ['Control', 'Alt', 'Shift'] - self.modifier_label = {'Control': 'Ctrl'} # short name - - def ToggleLevel(self): - if self.buttonLevel.cget('text')[:8]=='Advanced': - self.ClearKeySeq() - self.buttonLevel.config(text='<< Basic Key Binding Entry') - self.frameKeySeqAdvanced.lift() - self.frameHelpAdvanced.lift() - self.entryKeysAdvanced.focus_set() - self.advanced = True - else: - self.ClearKeySeq() - self.buttonLevel.config(text='Advanced Key Binding Entry >>') - self.frameKeySeqBasic.lift() - self.frameControlsBasic.lift() - self.advanced = False - - def FinalKeySelected(self,event): - self.BuildKeyString() - - def BuildKeyString(self): - keyList = modifiers = self.GetModifiers() - finalKey = self.listKeysFinal.get(ANCHOR) - if finalKey: - finalKey = self.TranslateKey(finalKey, modifiers) - keyList.append(finalKey) - self.keyString.set('<' + string.join(keyList,'-') + '>') - - def GetModifiers(self): - modList = [variable.get() for variable in self.modifier_vars] - return filter(None, modList) - - def ClearKeySeq(self): - self.listKeysFinal.select_clear(0,END) - self.listKeysFinal.yview(MOVETO, '0.0') - for variable in self.modifier_vars: - variable.set('') - self.keyString.set('') - - def LoadFinalKeyList(self): - #these tuples are also available for use in validity checks - self.functionKeys=('F1','F2','F2','F4','F5','F6','F7','F8','F9', - 'F10','F11','F12') - self.alphanumKeys=tuple(string.ascii_lowercase+string.digits) - self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?') - self.whitespaceKeys=('Tab','Space','Return') - self.editKeys=('BackSpace','Delete','Insert') - self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow', - 'Right Arrow','Up Arrow','Down Arrow') - #make a tuple of most of the useful common 'final' keys - keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+ - self.whitespaceKeys+self.editKeys+self.moveKeys) - self.listKeysFinal.insert(END, *keys) - - def TranslateKey(self, key, modifiers): - "Translate from keycap symbol to the Tkinter keysym" - translateDict = {'Space':'space', - '~':'asciitilde','!':'exclam','@':'at','#':'numbersign', - '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk', - '(':'parenleft',')':'parenright','_':'underscore','-':'minus', - '+':'plus','=':'equal','{':'braceleft','}':'braceright', - '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon', - ':':'colon',',':'comma','.':'period','<':'less','>':'greater', - '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next', - 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up', - 'Down Arrow': 'Down', 'Tab':'Tab'} - if key in translateDict.keys(): - key = translateDict[key] - if 'Shift' in modifiers and key in string.ascii_lowercase: - key = key.upper() - key = 'Key-' + key - return key - - def OK(self, event=None): - if self.advanced or self.KeysOK(): # doesn't check advanced string yet - self.result=self.keyString.get() - self.destroy() - - def Cancel(self, event=None): - self.result='' - self.destroy() - - def KeysOK(self): - '''Validity check on user's 'basic' keybinding selection. - - Doesn't check the string produced by the advanced dialog because - 'modifiers' isn't set. - - ''' - keys = self.keyString.get() - keys.strip() - finalKey = self.listKeysFinal.get(ANCHOR) - modifiers = self.GetModifiers() - # create a key sequence list for overlap check: - keySequence = keys.split() - keysOK = False - title = 'Key Sequence Error' - if not keys: - tkMessageBox.showerror(title=title, parent=self, - message='No keys specified.') - elif not keys.endswith('>'): - tkMessageBox.showerror(title=title, parent=self, - message='Missing the final Key') - elif (not modifiers - and finalKey not in self.functionKeys + self.moveKeys): - tkMessageBox.showerror(title=title, parent=self, - message='No modifier key(s) specified.') - elif (modifiers == ['Shift']) \ - and (finalKey not in - self.functionKeys + self.moveKeys + ('Tab', 'Space')): - msg = 'The shift modifier by itself may not be used with'\ - ' this key symbol.' - tkMessageBox.showerror(title=title, parent=self, message=msg) - elif keySequence in self.currentKeySequences: - msg = 'This key combination is already in use.' - tkMessageBox.showerror(title=title, parent=self, message=msg) - else: - keysOK = True - return keysOK - -if __name__ == '__main__': - #test the dialog - root=Tk() - def run(): - keySeq='' - dlg=GetKeysDialog(root,'Get Keys','find-again',[]) - print dlg.result - Button(root,text='Dialog',command=run).pack() - root.mainloop() diff --git a/sys/lib/python/idlelib/macosxSupport.py b/sys/lib/python/idlelib/macosxSupport.py deleted file mode 100644 index ad61fff46..000000000 --- a/sys/lib/python/idlelib/macosxSupport.py +++ /dev/null @@ -1,112 +0,0 @@ -""" -A number of function that enhance IDLE on MacOSX when it used as a normal -GUI application (as opposed to an X11 application). -""" -import sys - -def runningAsOSXApp(): - """ Returns True iff running from the IDLE.app bundle on OSX """ - return (sys.platform == 'darwin' and 'IDLE.app' in sys.argv[0]) - -def addOpenEventSupport(root, flist): - """ - This ensures that the application will respont to open AppleEvents, which - makes is feaseable to use IDLE as the default application for python files. - """ - def doOpenFile(*args): - for fn in args: - flist.open(fn) - - # The command below is a hook in aquatk that is called whenever the app - # receives a file open event. The callback can have multiple arguments, - # one for every file that should be opened. - root.createcommand("::tk::mac::OpenDocument", doOpenFile) - -def hideTkConsole(root): - root.tk.call('console', 'hide') - -def overrideRootMenu(root, flist): - """ - Replace the Tk root menu by something that's more appropriate for - IDLE. - """ - # The menu that is attached to the Tk root (".") is also used by AquaTk for - # all windows that don't specify a menu of their own. The default menubar - # contains a number of menus, none of which are appropriate for IDLE. The - # Most annoying of those is an 'About Tck/Tk...' menu in the application - # menu. - # - # This function replaces the default menubar by a mostly empty one, it - # should only contain the correct application menu and the window menu. - # - # Due to a (mis-)feature of TkAqua the user will also see an empty Help - # menu. - from Tkinter import Menu, Text, Text - from EditorWindow import prepstr, get_accelerator - import Bindings - import WindowList - from MultiCall import MultiCallCreator - - menubar = Menu(root) - root.configure(menu=menubar) - menudict = {} - - menudict['windows'] = menu = Menu(menubar, name='windows') - menubar.add_cascade(label='Window', menu=menu, underline=0) - - def postwindowsmenu(menu=menu): - end = menu.index('end') - if end is None: - end = -1 - - if end > 0: - menu.delete(0, end) - WindowList.add_windows_to_menu(menu) - WindowList.register_callback(postwindowsmenu) - - menudict['application'] = menu = Menu(menubar, name='apple') - menubar.add_cascade(label='IDLE', menu=menu) - - def about_dialog(event=None): - import aboutDialog - aboutDialog.AboutDialog(root, 'About IDLE') - - def config_dialog(event=None): - import configDialog - configDialog.ConfigDialog(root, 'Settings') - - root.bind('<<about-idle>>', about_dialog) - root.bind('<<open-config-dialog>>', config_dialog) - if flist: - root.bind('<<close-all-windows>>', flist.close_all_callback) - - for mname, entrylist in Bindings.menudefs: - menu = menudict.get(mname) - if not menu: - continue - for entry in entrylist: - if not entry: - menu.add_separator() - else: - label, eventname = entry - underline, label = prepstr(label) - accelerator = get_accelerator(Bindings.default_keydefs, - eventname) - def command(text=root, eventname=eventname): - text.event_generate(eventname) - menu.add_command(label=label, underline=underline, - command=command, accelerator=accelerator) - - - - - -def setupApp(root, flist): - """ - Perform setup for the OSX application bundle. - """ - if not runningAsOSXApp(): return - - hideTkConsole(root) - overrideRootMenu(root, flist) - addOpenEventSupport(root, flist) diff --git a/sys/lib/python/idlelib/rpc.py b/sys/lib/python/idlelib/rpc.py deleted file mode 100644 index 3bac6a30b..000000000 --- a/sys/lib/python/idlelib/rpc.py +++ /dev/null @@ -1,602 +0,0 @@ -"""RPC Implemention, originally written for the Python Idle IDE - -For security reasons, GvR requested that Idle's Python execution server process -connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. - - +---------------------------------+ +-------------+ - | SocketServer.BaseRequestHandler | | SocketIO | - +---------------------------------+ +-------------+ - ^ | register() | - | | unregister()| - | +-------------+ - | ^ ^ - | | | - | + -------------------+ | - | | | - +-------------------------+ +-----------------+ - | RPCHandler | | RPCClient | - | [attribute of RPCServer]| | | - +-------------------------+ +-----------------+ - -The RPCServer handler class is expected to provide register/unregister methods. -RPCHandler inherits the mix-in class SocketIO, which provides these methods. - -See the Idle run.main() docstring for further information on how this was -accomplished in Idle. - -""" - -import sys -import os -import socket -import select -import SocketServer -import struct -import cPickle as pickle -import threading -import Queue -import traceback -import copy_reg -import types -import marshal - - -def unpickle_code(ms): - co = marshal.loads(ms) - assert isinstance(co, types.CodeType) - return co - -def pickle_code(co): - assert isinstance(co, types.CodeType) - ms = marshal.dumps(co) - return unpickle_code, (ms,) - -# XXX KBK 24Aug02 function pickling capability not used in Idle -# def unpickle_function(ms): -# return ms - -# def pickle_function(fn): -# assert isinstance(fn, type.FunctionType) -# return repr(fn) - -copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) -# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) - -BUFSIZE = 8*1024 -LOCALHOST = '127.0.0.1' - -class RPCServer(SocketServer.TCPServer): - - def __init__(self, addr, handlerclass=None): - if handlerclass is None: - handlerclass = RPCHandler - SocketServer.TCPServer.__init__(self, addr, handlerclass) - - def server_bind(self): - "Override TCPServer method, no bind() phase for connecting entity" - pass - - def server_activate(self): - """Override TCPServer method, connect() instead of listen() - - Due to the reversed connection, self.server_address is actually the - address of the Idle Client to which we are connecting. - - """ - self.socket.connect(self.server_address) - - def get_request(self): - "Override TCPServer method, return already connected socket" - return self.socket, self.server_address - - def handle_error(self, request, client_address): - """Override TCPServer method - - Error message goes to __stderr__. No error message if exiting - normally or socket raised EOF. Other exceptions not handled in - server code will cause os._exit. - - """ - try: - raise - except SystemExit: - raise - except: - erf = sys.__stderr__ - print>>erf, '\n' + '-'*40 - print>>erf, 'Unhandled server exception!' - print>>erf, 'Thread: %s' % threading.currentThread().getName() - print>>erf, 'Client Address: ', client_address - print>>erf, 'Request: ', repr(request) - traceback.print_exc(file=erf) - print>>erf, '\n*** Unrecoverable, server exiting!' - print>>erf, '-'*40 - os._exit(0) - -#----------------- end class RPCServer -------------------- - -objecttable = {} -request_queue = Queue.Queue(0) -response_queue = Queue.Queue(0) - - -class SocketIO(object): - - nextseq = 0 - - def __init__(self, sock, objtable=None, debugging=None): - self.sockthread = threading.currentThread() - if debugging is not None: - self.debugging = debugging - self.sock = sock - if objtable is None: - objtable = objecttable - self.objtable = objtable - self.responses = {} - self.cvars = {} - - def close(self): - sock = self.sock - self.sock = None - if sock is not None: - sock.close() - - def exithook(self): - "override for specific exit action" - os._exit() - - def debug(self, *args): - if not self.debugging: - return - s = self.location + " " + str(threading.currentThread().getName()) - for a in args: - s = s + " " + str(a) - print>>sys.__stderr__, s - - def register(self, oid, object): - self.objtable[oid] = object - - def unregister(self, oid): - try: - del self.objtable[oid] - except KeyError: - pass - - def localcall(self, seq, request): - self.debug("localcall:", request) - try: - how, (oid, methodname, args, kwargs) = request - except TypeError: - return ("ERROR", "Bad request format") - if not self.objtable.has_key(oid): - return ("ERROR", "Unknown object id: %r" % (oid,)) - obj = self.objtable[oid] - if methodname == "__methods__": - methods = {} - _getmethods(obj, methods) - return ("OK", methods) - if methodname == "__attributes__": - attributes = {} - _getattributes(obj, attributes) - return ("OK", attributes) - if not hasattr(obj, methodname): - return ("ERROR", "Unsupported method name: %r" % (methodname,)) - method = getattr(obj, methodname) - try: - if how == 'CALL': - ret = method(*args, **kwargs) - if isinstance(ret, RemoteObject): - ret = remoteref(ret) - return ("OK", ret) - elif how == 'QUEUE': - request_queue.put((seq, (method, args, kwargs))) - return("QUEUED", None) - else: - return ("ERROR", "Unsupported message type: %s" % how) - except SystemExit: - raise - except socket.error: - raise - except: - msg = "*** Internal Error: rpc.py:SocketIO.localcall()\n\n"\ - " Object: %s \n Method: %s \n Args: %s\n" - print>>sys.__stderr__, msg % (oid, method, args) - traceback.print_exc(file=sys.__stderr__) - return ("EXCEPTION", None) - - def remotecall(self, oid, methodname, args, kwargs): - self.debug("remotecall:asynccall: ", oid, methodname) - seq = self.asynccall(oid, methodname, args, kwargs) - return self.asyncreturn(seq) - - def remotequeue(self, oid, methodname, args, kwargs): - self.debug("remotequeue:asyncqueue: ", oid, methodname) - seq = self.asyncqueue(oid, methodname, args, kwargs) - return self.asyncreturn(seq) - - def asynccall(self, oid, methodname, args, kwargs): - request = ("CALL", (oid, methodname, args, kwargs)) - seq = self.newseq() - if threading.currentThread() != self.sockthread: - cvar = threading.Condition() - self.cvars[seq] = cvar - self.debug(("asynccall:%d:" % seq), oid, methodname, args, kwargs) - self.putmessage((seq, request)) - return seq - - def asyncqueue(self, oid, methodname, args, kwargs): - request = ("QUEUE", (oid, methodname, args, kwargs)) - seq = self.newseq() - if threading.currentThread() != self.sockthread: - cvar = threading.Condition() - self.cvars[seq] = cvar - self.debug(("asyncqueue:%d:" % seq), oid, methodname, args, kwargs) - self.putmessage((seq, request)) - return seq - - def asyncreturn(self, seq): - self.debug("asyncreturn:%d:call getresponse(): " % seq) - response = self.getresponse(seq, wait=0.05) - self.debug(("asyncreturn:%d:response: " % seq), response) - return self.decoderesponse(response) - - def decoderesponse(self, response): - how, what = response - if how == "OK": - return what - if how == "QUEUED": - return None - if how == "EXCEPTION": - self.debug("decoderesponse: EXCEPTION") - return None - if how == "EOF": - self.debug("decoderesponse: EOF") - self.decode_interrupthook() - return None - if how == "ERROR": - self.debug("decoderesponse: Internal ERROR:", what) - raise RuntimeError, what - raise SystemError, (how, what) - - def decode_interrupthook(self): - "" - raise EOFError - - def mainloop(self): - """Listen on socket until I/O not ready or EOF - - pollresponse() will loop looking for seq number None, which - never comes, and exit on EOFError. - - """ - try: - self.getresponse(myseq=None, wait=0.05) - except EOFError: - self.debug("mainloop:return") - return - - def getresponse(self, myseq, wait): - response = self._getresponse(myseq, wait) - if response is not None: - how, what = response - if how == "OK": - response = how, self._proxify(what) - return response - - def _proxify(self, obj): - if isinstance(obj, RemoteProxy): - return RPCProxy(self, obj.oid) - if isinstance(obj, types.ListType): - return map(self._proxify, obj) - # XXX Check for other types -- not currently needed - return obj - - def _getresponse(self, myseq, wait): - self.debug("_getresponse:myseq:", myseq) - if threading.currentThread() is self.sockthread: - # this thread does all reading of requests or responses - while 1: - response = self.pollresponse(myseq, wait) - if response is not None: - return response - else: - # wait for notification from socket handling thread - cvar = self.cvars[myseq] - cvar.acquire() - while not self.responses.has_key(myseq): - cvar.wait() - response = self.responses[myseq] - self.debug("_getresponse:%s: thread woke up: response: %s" % - (myseq, response)) - del self.responses[myseq] - del self.cvars[myseq] - cvar.release() - return response - - def newseq(self): - self.nextseq = seq = self.nextseq + 2 - return seq - - def putmessage(self, message): - self.debug("putmessage:%d:" % message[0]) - try: - s = pickle.dumps(message) - except pickle.PicklingError: - print >>sys.__stderr__, "Cannot pickle:", repr(message) - raise - s = struct.pack("<i", len(s)) + s - while len(s) > 0: - try: - r, w, x = select.select([], [self.sock], []) - n = self.sock.send(s[:BUFSIZE]) - except (AttributeError, TypeError): - raise IOError, "socket no longer exists" - except socket.error: - raise - else: - s = s[n:] - - buffer = "" - bufneed = 4 - bufstate = 0 # meaning: 0 => reading count; 1 => reading data - - def pollpacket(self, wait): - self._stage0() - if len(self.buffer) < self.bufneed: - r, w, x = select.select([self.sock.fileno()], [], [], wait) - if len(r) == 0: - return None - try: - s = self.sock.recv(BUFSIZE) - except socket.error: - raise EOFError - if len(s) == 0: - raise EOFError - self.buffer += s - self._stage0() - return self._stage1() - - def _stage0(self): - if self.bufstate == 0 and len(self.buffer) >= 4: - s = self.buffer[:4] - self.buffer = self.buffer[4:] - self.bufneed = struct.unpack("<i", s)[0] - self.bufstate = 1 - - def _stage1(self): - if self.bufstate == 1 and len(self.buffer) >= self.bufneed: - packet = self.buffer[:self.bufneed] - self.buffer = self.buffer[self.bufneed:] - self.bufneed = 4 - self.bufstate = 0 - return packet - - def pollmessage(self, wait): - packet = self.pollpacket(wait) - if packet is None: - return None - try: - message = pickle.loads(packet) - except pickle.UnpicklingError: - print >>sys.__stderr__, "-----------------------" - print >>sys.__stderr__, "cannot unpickle packet:", repr(packet) - traceback.print_stack(file=sys.__stderr__) - print >>sys.__stderr__, "-----------------------" - raise - return message - - def pollresponse(self, myseq, wait): - """Handle messages received on the socket. - - Some messages received may be asynchronous 'call' or 'queue' requests, - and some may be responses for other threads. - - 'call' requests are passed to self.localcall() with the expectation of - immediate execution, during which time the socket is not serviced. - - 'queue' requests are used for tasks (which may block or hang) to be - processed in a different thread. These requests are fed into - request_queue by self.localcall(). Responses to queued requests are - taken from response_queue and sent across the link with the associated - sequence numbers. Messages in the queues are (sequence_number, - request/response) tuples and code using this module removing messages - from the request_queue is responsible for returning the correct - sequence number in the response_queue. - - pollresponse() will loop until a response message with the myseq - sequence number is received, and will save other responses in - self.responses and notify the owning thread. - - """ - while 1: - # send queued response if there is one available - try: - qmsg = response_queue.get(0) - except Queue.Empty: - pass - else: - seq, response = qmsg - message = (seq, ('OK', response)) - self.putmessage(message) - # poll for message on link - try: - message = self.pollmessage(wait) - if message is None: # socket not ready - return None - except EOFError: - self.handle_EOF() - return None - except AttributeError: - return None - seq, resq = message - how = resq[0] - self.debug("pollresponse:%d:myseq:%s" % (seq, myseq)) - # process or queue a request - if how in ("CALL", "QUEUE"): - self.debug("pollresponse:%d:localcall:call:" % seq) - response = self.localcall(seq, resq) - self.debug("pollresponse:%d:localcall:response:%s" - % (seq, response)) - if how == "CALL": - self.putmessage((seq, response)) - elif how == "QUEUE": - # don't acknowledge the 'queue' request! - pass - continue - # return if completed message transaction - elif seq == myseq: - return resq - # must be a response for a different thread: - else: - cv = self.cvars.get(seq, None) - # response involving unknown sequence number is discarded, - # probably intended for prior incarnation of server - if cv is not None: - cv.acquire() - self.responses[seq] = resq - cv.notify() - cv.release() - continue - - def handle_EOF(self): - "action taken upon link being closed by peer" - self.EOFhook() - self.debug("handle_EOF") - for key in self.cvars: - cv = self.cvars[key] - cv.acquire() - self.responses[key] = ('EOF', None) - cv.notify() - cv.release() - # call our (possibly overridden) exit function - self.exithook() - - def EOFhook(self): - "Classes using rpc client/server can override to augment EOF action" - pass - -#----------------- end class SocketIO -------------------- - -class RemoteObject(object): - # Token mix-in class - pass - -def remoteref(obj): - oid = id(obj) - objecttable[oid] = obj - return RemoteProxy(oid) - -class RemoteProxy(object): - - def __init__(self, oid): - self.oid = oid - -class RPCHandler(SocketServer.BaseRequestHandler, SocketIO): - - debugging = False - location = "#S" # Server - - def __init__(self, sock, addr, svr): - svr.current_handler = self ## cgt xxx - SocketIO.__init__(self, sock) - SocketServer.BaseRequestHandler.__init__(self, sock, addr, svr) - - def handle(self): - "handle() method required by SocketServer" - self.mainloop() - - def get_remote_proxy(self, oid): - return RPCProxy(self, oid) - -class RPCClient(SocketIO): - - debugging = False - location = "#C" # Client - - nextseq = 1 # Requests coming from the client are odd numbered - - def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM): - self.listening_sock = socket.socket(family, type) - self.listening_sock.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, 1) - self.listening_sock.bind(address) - self.listening_sock.listen(1) - - def accept(self): - working_sock, address = self.listening_sock.accept() - if self.debugging: - print>>sys.__stderr__, "****** Connection request from ", address - if address[0] == LOCALHOST: - SocketIO.__init__(self, working_sock) - else: - print>>sys.__stderr__, "** Invalid host: ", address - raise socket.error - - def get_remote_proxy(self, oid): - return RPCProxy(self, oid) - -class RPCProxy(object): - - __methods = None - __attributes = None - - def __init__(self, sockio, oid): - self.sockio = sockio - self.oid = oid - - def __getattr__(self, name): - if self.__methods is None: - self.__getmethods() - if self.__methods.get(name): - return MethodProxy(self.sockio, self.oid, name) - if self.__attributes is None: - self.__getattributes() - if self.__attributes.has_key(name): - value = self.sockio.remotecall(self.oid, '__getattribute__', - (name,), {}) - return value - else: - raise AttributeError, name - - def __getattributes(self): - self.__attributes = self.sockio.remotecall(self.oid, - "__attributes__", (), {}) - - def __getmethods(self): - self.__methods = self.sockio.remotecall(self.oid, - "__methods__", (), {}) - -def _getmethods(obj, methods): - # Helper to get a list of methods from an object - # Adds names to dictionary argument 'methods' - for name in dir(obj): - attr = getattr(obj, name) - if callable(attr): - methods[name] = 1 - if type(obj) == types.InstanceType: - _getmethods(obj.__class__, methods) - if type(obj) == types.ClassType: - for super in obj.__bases__: - _getmethods(super, methods) - -def _getattributes(obj, attributes): - for name in dir(obj): - attr = getattr(obj, name) - if not callable(attr): - attributes[name] = 1 - -class MethodProxy(object): - - def __init__(self, sockio, oid, name): - self.sockio = sockio - self.oid = oid - self.name = name - - def __call__(self, *args, **kwargs): - value = self.sockio.remotecall(self.oid, self.name, args, kwargs) - return value - - -# XXX KBK 09Sep03 We need a proper unit test for this module. Previously -# existing test code was removed at Rev 1.27. diff --git a/sys/lib/python/idlelib/run.py b/sys/lib/python/idlelib/run.py deleted file mode 100644 index ae810c4ec..000000000 --- a/sys/lib/python/idlelib/run.py +++ /dev/null @@ -1,327 +0,0 @@ -import sys -import os -import linecache -import time -import socket -import traceback -import thread -import threading -import Queue - -import CallTips -import AutoComplete - -import RemoteDebugger -import RemoteObjectBrowser -import StackViewer -import rpc - -import __main__ - -LOCALHOST = '127.0.0.1' - -try: - import warnings -except ImportError: - pass -else: - def idle_formatwarning_subproc(message, category, filename, lineno): - """Format warnings the IDLE way""" - s = "\nWarning (from warnings module):\n" - s += ' File \"%s\", line %s\n' % (filename, lineno) - line = linecache.getline(filename, lineno).strip() - if line: - s += " %s\n" % line - s += "%s: %s\n" % (category.__name__, message) - return s - warnings.formatwarning = idle_formatwarning_subproc - -# Thread shared globals: Establish a queue between a subthread (which handles -# the socket) and the main thread (which runs user code), plus global -# completion and exit flags: - -exit_now = False -quitting = False - -def main(del_exitfunc=False): - """Start the Python execution server in a subprocess - - In the Python subprocess, RPCServer is instantiated with handlerclass - MyHandler, which inherits register/unregister methods from RPCHandler via - the mix-in class SocketIO. - - When the RPCServer 'server' is instantiated, the TCPServer initialization - creates an instance of run.MyHandler and calls its handle() method. - handle() instantiates a run.Executive object, passing it a reference to the - MyHandler object. That reference is saved as attribute rpchandler of the - Executive instance. The Executive methods have access to the reference and - can pass it on to entities that they command - (e.g. RemoteDebugger.Debugger.start_debugger()). The latter, in turn, can - call MyHandler(SocketIO) register/unregister methods via the reference to - register and unregister themselves. - - """ - global exit_now - global quitting - global no_exitfunc - no_exitfunc = del_exitfunc - port = 8833 - #time.sleep(15) # test subprocess not responding - if sys.argv[1:]: - port = int(sys.argv[1]) - sys.argv[:] = [""] - sockthread = threading.Thread(target=manage_socket, - name='SockThread', - args=((LOCALHOST, port),)) - sockthread.setDaemon(True) - sockthread.start() - while 1: - try: - if exit_now: - try: - exit() - except KeyboardInterrupt: - # exiting but got an extra KBI? Try again! - continue - try: - seq, request = rpc.request_queue.get(block=True, timeout=0.05) - except Queue.Empty: - continue - method, args, kwargs = request - ret = method(*args, **kwargs) - rpc.response_queue.put((seq, ret)) - except KeyboardInterrupt: - if quitting: - exit_now = True - continue - except SystemExit: - raise - except: - type, value, tb = sys.exc_info() - try: - print_exception() - rpc.response_queue.put((seq, None)) - except: - # Link didn't work, print same exception to __stderr__ - traceback.print_exception(type, value, tb, file=sys.__stderr__) - exit() - else: - continue - -def manage_socket(address): - for i in range(3): - time.sleep(i) - try: - server = MyRPCServer(address, MyHandler) - break - except socket.error, err: - print>>sys.__stderr__,"IDLE Subprocess: socket error: "\ - + err[1] + ", retrying...." - else: - print>>sys.__stderr__, "IDLE Subprocess: Connection to "\ - "IDLE GUI failed, exiting." - show_socket_error(err, address) - global exit_now - exit_now = True - return - server.handle_request() # A single request only - -def show_socket_error(err, address): - import Tkinter - import tkMessageBox - root = Tkinter.Tk() - root.withdraw() - if err[0] == 61: # connection refused - msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\ - "to your personal firewall configuration. It is safe to "\ - "allow this internal connection because no data is visible on "\ - "external ports." % address - tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root) - else: - tkMessageBox.showerror("IDLE Subprocess Error", "Socket Error: %s" % err[1]) - root.destroy() - -def print_exception(): - import linecache - linecache.checkcache() - flush_stdout() - efile = sys.stderr - typ, val, tb = excinfo = sys.exc_info() - sys.last_type, sys.last_value, sys.last_traceback = excinfo - tbe = traceback.extract_tb(tb) - print>>efile, '\nTraceback (most recent call last):' - exclude = ("run.py", "rpc.py", "threading.py", "Queue.py", - "RemoteDebugger.py", "bdb.py") - cleanup_traceback(tbe, exclude) - traceback.print_list(tbe, file=efile) - lines = traceback.format_exception_only(typ, val) - for line in lines: - print>>efile, line, - -def cleanup_traceback(tb, exclude): - "Remove excluded traces from beginning/end of tb; get cached lines" - orig_tb = tb[:] - while tb: - for rpcfile in exclude: - if tb[0][0].count(rpcfile): - break # found an exclude, break for: and delete tb[0] - else: - break # no excludes, have left RPC code, break while: - del tb[0] - while tb: - for rpcfile in exclude: - if tb[-1][0].count(rpcfile): - break - else: - break - del tb[-1] - if len(tb) == 0: - # exception was in IDLE internals, don't prune! - tb[:] = orig_tb[:] - print>>sys.stderr, "** IDLE Internal Exception: " - rpchandler = rpc.objecttable['exec'].rpchandler - for i in range(len(tb)): - fn, ln, nm, line = tb[i] - if nm == '?': - nm = "-toplevel-" - if not line and fn.startswith("<pyshell#"): - line = rpchandler.remotecall('linecache', 'getline', - (fn, ln), {}) - tb[i] = fn, ln, nm, line - -def flush_stdout(): - try: - if sys.stdout.softspace: - sys.stdout.softspace = 0 - sys.stdout.write("\n") - except (AttributeError, EOFError): - pass - -def exit(): - """Exit subprocess, possibly after first deleting sys.exitfunc - - If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any - sys.exitfunc will be removed before exiting. (VPython support) - - """ - if no_exitfunc: - del sys.exitfunc - sys.exit(0) - -class MyRPCServer(rpc.RPCServer): - - def handle_error(self, request, client_address): - """Override RPCServer method for IDLE - - Interrupt the MainThread and exit server if link is dropped. - - """ - global quitting - try: - raise - except SystemExit: - raise - except EOFError: - global exit_now - exit_now = True - thread.interrupt_main() - except: - erf = sys.__stderr__ - print>>erf, '\n' + '-'*40 - print>>erf, 'Unhandled server exception!' - print>>erf, 'Thread: %s' % threading.currentThread().getName() - print>>erf, 'Client Address: ', client_address - print>>erf, 'Request: ', repr(request) - traceback.print_exc(file=erf) - print>>erf, '\n*** Unrecoverable, server exiting!' - print>>erf, '-'*40 - quitting = True - thread.interrupt_main() - - -class MyHandler(rpc.RPCHandler): - - def handle(self): - """Override base method""" - executive = Executive(self) - self.register("exec", executive) - sys.stdin = self.console = self.get_remote_proxy("stdin") - sys.stdout = self.get_remote_proxy("stdout") - sys.stderr = self.get_remote_proxy("stderr") - import IOBinding - sys.stdin.encoding = sys.stdout.encoding = \ - sys.stderr.encoding = IOBinding.encoding - self.interp = self.get_remote_proxy("interp") - rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05) - - def exithook(self): - "override SocketIO method - wait for MainThread to shut us down" - time.sleep(10) - - def EOFhook(self): - "Override SocketIO method - terminate wait on callback and exit thread" - global quitting - quitting = True - thread.interrupt_main() - - def decode_interrupthook(self): - "interrupt awakened thread" - global quitting - quitting = True - thread.interrupt_main() - - -class Executive(object): - - def __init__(self, rpchandler): - self.rpchandler = rpchandler - self.locals = __main__.__dict__ - self.calltip = CallTips.CallTips() - self.autocomplete = AutoComplete.AutoComplete() - - def runcode(self, code): - try: - self.usr_exc_info = None - exec code in self.locals - except: - self.usr_exc_info = sys.exc_info() - if quitting: - exit() - # even print a user code SystemExit exception, continue - print_exception() - jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>") - if jit: - self.rpchandler.interp.open_remote_stack_viewer() - else: - flush_stdout() - - def interrupt_the_server(self): - thread.interrupt_main() - - def start_the_debugger(self, gui_adap_oid): - return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid) - - def stop_the_debugger(self, idb_adap_oid): - "Unregister the Idb Adapter. Link objects and Idb then subject to GC" - self.rpchandler.unregister(idb_adap_oid) - - def get_the_calltip(self, name): - return self.calltip.fetch_tip(name) - - def get_the_completion_list(self, what, mode): - return self.autocomplete.fetch_completions(what, mode) - - def stackviewer(self, flist_oid=None): - if self.usr_exc_info: - typ, val, tb = self.usr_exc_info - else: - return None - flist = None - if flist_oid is not None: - flist = self.rpchandler.get_remote_proxy(flist_oid) - while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]: - tb = tb.tb_next - sys.last_type = typ - sys.last_value = val - item = StackViewer.StackTreeItem(flist, tb) - return RemoteObjectBrowser.remote_object_tree_item(item) diff --git a/sys/lib/python/idlelib/tabpage.py b/sys/lib/python/idlelib/tabpage.py deleted file mode 100644 index 12f89291d..000000000 --- a/sys/lib/python/idlelib/tabpage.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -a couple of classes for implementing partial tabbed-page like behaviour -""" - -from Tkinter import * - -class InvalidTabPage(Exception): pass -class AlreadyExists(Exception): pass - -class PageTab(Frame): - """ - a 'page tab' like framed button - """ - def __init__(self,parent): - Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) - self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, - indicatoron=FALSE,highlightthickness=0, - borderwidth=0,selectcolor=self.cget('bg')) - self.button.pack() - -class TabPageSet(Frame): - """ - a set of 'pages' with TabButtons for controlling their display - """ - def __init__(self,parent,pageNames=[],**kw): - """ - pageNames - a list of strings, each string will be the dictionary key - to a page's data, and the name displayed on the page's tab. Should be - specified in desired page order. The first page will be the default - and first active page. - """ - Frame.__init__(self, parent, kw) - self.grid_location(0,0) - self.columnconfigure(0,weight=1) - self.rowconfigure(1,weight=1) - self.tabBar=Frame(self) - self.tabBar.grid(row=0,column=0,sticky=EW) - self.activePage=StringVar(self) - self.defaultPage='' - self.pages={} - for name in pageNames: - self.AddPage(name) - - def ChangePage(self,pageName=None): - if pageName: - if pageName in self.pages.keys(): - self.activePage.set(pageName) - else: - raise InvalidTabPage, 'Invalid TabPage Name' - ## pop up the active 'tab' only - for page in self.pages.keys(): - self.pages[page]['tab'].config(relief=RIDGE) - self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) - ## switch page - self.pages[self.GetActivePage()]['page'].lift() - - def GetActivePage(self): - return self.activePage.get() - - def AddPage(self,pageName): - if pageName in self.pages.keys(): - raise AlreadyExists, 'TabPage Name Already Exists' - self.pages[pageName]={'tab':PageTab(self.tabBar), - 'page':Frame(self,borderwidth=2,relief=RAISED)} - self.pages[pageName]['tab'].button.config(text=pageName, - command=self.ChangePage,variable=self.activePage, - value=pageName) - self.pages[pageName]['tab'].pack(side=LEFT) - self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) - if len(self.pages)==1: # adding first page - self.defaultPage=pageName - self.activePage.set(self.defaultPage) - self.ChangePage() - - def RemovePage(self,pageName): - if not pageName in self.pages.keys(): - raise InvalidTabPage, 'Invalid TabPage Name' - self.pages[pageName]['tab'].pack_forget() - self.pages[pageName]['page'].grid_forget() - self.pages[pageName]['tab'].destroy() - self.pages[pageName]['page'].destroy() - del(self.pages[pageName]) - # handle removing last remaining, or default, or active page - if not self.pages: # removed last remaining page - self.defaultPage='' - return - if pageName==self.defaultPage: # set a new default page - self.defaultPage=\ - self.tabBar.winfo_children()[0].button.cget('text') - if pageName==self.GetActivePage(): # set a new active page - self.activePage.set(self.defaultPage) - self.ChangePage() - -if __name__ == '__main__': - #test dialog - root=Tk() - tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) - tabPage.pack(expand=TRUE,fill=BOTH) - Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() - Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() - Label(tabPage.pages['Baz']['page'],text='Baz').pack() - entryPgName=Entry(root) - buttonAdd=Button(root,text='Add Page', - command=lambda:tabPage.AddPage(entryPgName.get())) - buttonRemove=Button(root,text='Remove Page', - command=lambda:tabPage.RemovePage(entryPgName.get())) - labelPgName=Label(root,text='name of page to add/remove:') - buttonAdd.pack(padx=5,pady=5) - buttonRemove.pack(padx=5,pady=5) - labelPgName.pack(padx=5) - entryPgName.pack(padx=5) - tabPage.ChangePage() - root.mainloop() diff --git a/sys/lib/python/idlelib/testcode.py b/sys/lib/python/idlelib/testcode.py deleted file mode 100644 index 05eaa562c..000000000 --- a/sys/lib/python/idlelib/testcode.py +++ /dev/null @@ -1,31 +0,0 @@ -import string - -def f(): - a = 0 - b = 1 - c = 2 - d = 3 - e = 4 - g() - -def g(): - h() - -def h(): - i() - -def i(): - j() - -def j(): - k() - -def k(): - l() - -l = lambda: test() - -def test(): - string.capwords(1) - -f() diff --git a/sys/lib/python/idlelib/textView.py b/sys/lib/python/idlelib/textView.py deleted file mode 100644 index 917a6cc0c..000000000 --- a/sys/lib/python/idlelib/textView.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Simple text browser for IDLE - -""" - -from Tkinter import * -import tkMessageBox - -class TextViewer(Toplevel): - """ - simple text viewer dialog for idle - """ - def __init__(self, parent, title, fileName, data=None): - """If data exists, load it into viewer, otherwise try to load file. - - fileName - string, should be an absoulute filename - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("=%dx%d+%d+%d" % (625, 500, - parent.winfo_rootx() + 10, - parent.winfo_rooty() + 10)) - #elguavas - config placeholders til config stuff completed - self.bg = '#ffffff' - self.fg = '#000000' - - self.CreateWidgets() - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Ok) - self.parent = parent - self.textView.focus_set() - #key bindings for this dialog - self.bind('<Return>',self.Ok) #dismiss dialog - self.bind('<Escape>',self.Ok) #dismiss dialog - if data: - self.textView.insert(0.0, data) - else: - self.LoadTextFile(fileName) - self.textView.config(state=DISABLED) - self.wait_window() - - def LoadTextFile(self, fileName): - textFile = None - try: - textFile = open(fileName, 'r') - except IOError: - tkMessageBox.showerror(title='File Load Error', - message='Unable to load file %r .' % (fileName,)) - else: - self.textView.insert(0.0,textFile.read()) - - def CreateWidgets(self): - frameText = Frame(self, relief=SUNKEN, height=700) - frameButtons = Frame(self) - self.buttonOk = Button(frameButtons, text='Close', - command=self.Ok, takefocus=FALSE) - self.scrollbarView = Scrollbar(frameText, orient=VERTICAL, - takefocus=FALSE, highlightthickness=0) - self.textView = Text(frameText, wrap=WORD, highlightthickness=0, - fg=self.fg, bg=self.bg) - self.scrollbarView.config(command=self.textView.yview) - self.textView.config(yscrollcommand=self.scrollbarView.set) - self.buttonOk.pack() - self.scrollbarView.pack(side=RIGHT,fill=Y) - self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH) - frameButtons.pack(side=BOTTOM,fill=X) - frameText.pack(side=TOP,expand=TRUE,fill=BOTH) - - def Ok(self, event=None): - self.destroy() - -if __name__ == '__main__': - #test the dialog - root=Tk() - Button(root,text='View', - command=lambda:TextViewer(root,'Text','./textView.py')).pack() - root.mainloop() |