diff options
author | Guido van Rossum <guido@python.org> | 2003-06-14 00:08:37 +0000 |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2003-06-14 00:08:37 +0000 |
commit | 5db9ff42657d80a06fe28b0836bdd7bfd5fbdec8 (patch) | |
tree | 2bf9bb961941d2e1610ffe19e5d65586cdc220f4 /Tools | |
parent | 12c1bd4ab62db0259b8ee35ea546bd0a851124ea (diff) | |
download | cpython-5db9ff42657d80a06fe28b0836bdd7bfd5fbdec8.tar.gz |
Get rid of old IDLE. Lib/idlelib rules!
Diffstat (limited to 'Tools')
71 files changed, 0 insertions, 10925 deletions
diff --git a/Tools/README b/Tools/README index 5d20e9bd46..404ba4dbfc 100644 --- a/Tools/README +++ b/Tools/README @@ -24,8 +24,6 @@ i18n Tools for internationalization. pygettext.py and msgfmt.py generates a binary message catalog from a catalog in text format. -idle A Tkinter-based Python IDE. - modulator Interactively generate boiler plate for an extension module. Works easiest if you have Tk. diff --git a/Tools/idle/AutoExpand.py b/Tools/idle/AutoExpand.py deleted file mode 100644 index 40d39f3f42..0000000000 --- a/Tools/idle/AutoExpand.py +++ /dev/null @@ -1,91 +0,0 @@ -import string -import re - -###$ event <<expand-word>> -###$ win <Alt-slash> -###$ unix <Alt-slash> - -class AutoExpand: - - keydefs = { - '<<expand-word>>': ['<Alt-slash>'], - } - - unix_keydefs = { - '<<expand-word>>': ['<Meta-slash>', '<Alt-slash>'], - } - - 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/Tools/idle/AutoIndent.py b/Tools/idle/AutoIndent.py deleted file mode 100644 index 7bc195b19b..0000000000 --- a/Tools/idle/AutoIndent.py +++ /dev/null @@ -1,551 +0,0 @@ -#from Tkinter import TclError -#import tkMessageBox -#import tkSimpleDialog - -###$ event <<newline-and-indent>> -###$ win <Key-Return> -###$ win <KP_Enter> -###$ unix <Key-Return> -###$ unix <KP_Enter> - -###$ event <<indent-region>> -###$ win <Control-bracketright> -###$ unix <Alt-bracketright> -###$ unix <Control-bracketright> - -###$ event <<dedent-region>> -###$ win <Control-bracketleft> -###$ unix <Alt-bracketleft> -###$ unix <Control-bracketleft> - -###$ event <<comment-region>> -###$ win <Alt-Key-3> -###$ unix <Alt-Key-3> - -###$ event <<uncomment-region>> -###$ win <Alt-Key-4> -###$ unix <Alt-Key-4> - -###$ event <<tabify-region>> -###$ win <Alt-Key-5> -###$ unix <Alt-Key-5> - -###$ event <<untabify-region>> -###$ win <Alt-Key-6> -###$ unix <Alt-Key-6> - -import PyParse - -class AutoIndent: - - menudefs = [ - ('edit', [ - None, - ('_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>>'), - ]), - ] - - keydefs = { - '<<smart-backspace>>': ['<Key-BackSpace>'], - '<<newline-and-indent>>': ['<Key-Return>', '<KP_Enter>'], - '<<smart-indent>>': ['<Key-Tab>'] - } - - windows_keydefs = { - '<<indent-region>>': ['<Control-bracketright>'], - '<<dedent-region>>': ['<Control-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>'], - } - - unix_keydefs = { - '<<indent-region>>': ['<Alt-bracketright>', - '<Meta-bracketright>', - '<Control-bracketright>'], - '<<dedent-region>>': ['<Alt-bracketleft>', - '<Meta-bracketleft>', - '<Control-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>'], - '<<change-indentwidth>>': ['<Alt-Key-u>'], - } - - # usetabs true -> literal tab characters are used by indent and - # dedent cmds, possibly mixed with spaces if - # indentwidth is not a multiple of tabwidth - # false -> tab characters are converted to spaces by indent - # and dedent cmds, and ditto TAB keystrokes - # indentwidth is the number of characters per logical indent level. - # 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. - usetabs = 1 - indentwidth = 4 - tabwidth = 8 # for IDLE use, must remain 8 until Tk is fixed - - # If context_use_ps1 is true, parsing searches back for a ps1 line; - # else searches for a popular (if, def, ...) Python stmt. - context_use_ps1 = 0 - - # 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. - num_context_lines = 50, 500, 5000000 - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - - def config(self, **options): - for key, value in options.items(): - if key == 'usetabs': - self.usetabs = value - elif key == 'indentwidth': - self.indentwidth = value - elif key == 'tabwidth': - self.tabwidth = value - elif key == 'context_use_ps1': - self.context_use_ps1 = value - else: - raise KeyError, "bad option name: %s" % `key` - - # 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=1): - if guess and ispythonsource: - i = self.guess_indent() - if 2 <= i <= 8: - self.indentwidth = i - if self.indentwidth != self.tabwidth: - self.usetabs = 0 - - self.editwin.set_tabwidth(self.tabwidth) - - def smart_backspace_event(self, event): - text = self.text - first, last = self.editwin.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 - ncharsdeleted = 0 - while 1: - 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 & return - # indent one level - text = self.text - first, last = self.editwin.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: - 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.editwin.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; just inject - # an empty line at the start - text.insert("insert linestart", '\n') - return "break" - indent = line[:i] - # strip whitespace before insert point - i = 0 - while line and line[-1] in " \t": - 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) - 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) - c = y.get_continuation_type() - if c != PyParse.C_NONE: - # The current stmt hasn't ended yet. - if c == PyParse.C_STRING: - # inside a string; 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 " + `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() - - auto_indent = newline_and_indent_event - - # 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.editwin.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.editwin.askyesno( - "Toggle tabs", - "Turn tabs " + ("on", "off")[self.usetabs] + "?", - parent=self.text): - self.usetabs = not self.usetabs - return "break" - - # XXX this isn't bound to anything -- see class 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.editwin.askinteger( - "Indent width", - "New indent width (1-16)", - parent=self.text, - initialvalue=self.indentwidth, - minvalue=1, - maxvalue=16) - if new and new != self.indentwidth: - self.indentwidth = new - return "break" - - def get_region(self): - text = self.text - first, last = self.editwin.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.editwin.askinteger( - "Tab width", - "Spaces per tab?", - parent=self.text, - initialvalue=self.tabwidth, - minvalue=1, - 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: - - # .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 = `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 diff --git a/Tools/idle/Bindings.py b/Tools/idle/Bindings.py deleted file mode 100644 index a7d3802eb9..0000000000 --- a/Tools/idle/Bindings.py +++ /dev/null @@ -1,58 +0,0 @@ -# This file defines the menu contents and key bindings. Note that -# 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 by the code here. This makes it possible to define the -# Debug menu here, which is only present in the PythonShell window. - -import sys -from keydefs import * - -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>>'), - ('Python shell', '<<open-python-shell>>'), - None, - ('_Save', '<<save-window>>'), - ('Save _As...', '<<save-window-as-file>>'), - ('Save Co_py As...', '<<save-copy-of-window-as-file>>'), - None, - ('_Print 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>>'), - ]), - ('debug', [ - ('_Go to file/line', '<<goto-file-line>>'), - ('_Stack viewer', '<<open-stack-viewer>>'), - ('!_Debugger', '<<toggle-debugger>>'), - ('!_Auto-open stack viewer', '<<toggle-jit-stack-viewer>>' ), - ]), - ('help', [ - ('_Help...', '<<help>>'), - ('Python _Documentation...', '<<python-docs>>'), - None, - ('_About IDLE...', '<<about-idle>>'), - ]), -] - -if sys.platform == 'win32': - default_keydefs = windows_keydefs -else: - default_keydefs = unix_keydefs - -del sys diff --git a/Tools/idle/CallTipWindow.py b/Tools/idle/CallTipWindow.py deleted file mode 100644 index 24af6b0e46..0000000000 --- a/Tools/idle/CallTipWindow.py +++ /dev/null @@ -1,76 +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 * - -class CallTip: - - def __init__(self, widget): - self.widget = widget - self.tipwindow = None - self.id = None - self.x = self.y = 0 - - def showtip(self, text): - # SF bug 546078: IDLE calltips cause application error. - # There were crashes on various Windows flavors, and even a - # crashing X server on Linux, with very long calltips. - if len(text) >= 79: - text = text[:75] + ' ...' - self.text = text - - if self.tipwindow or not self.text: - return - self.widget.see("insert") - x, y, cx, cy = self.widget.bbox("insert") - x = x + self.widget.winfo_rootx() + 2 - y = y + cy + self.widget.winfo_rooty() - self.tipwindow = tw = Toplevel(self.widget) - tw.wm_overrideredirect(1) - tw.wm_geometry("+%d+%d" % (x, y)) - label = Label(tw, text=self.text, justify=LEFT, - background="#ffffe0", relief=SOLID, borderwidth=1, - font = self.widget['font']) - label.pack() - - def hidetip(self): - tw = self.tipwindow - self.tipwindow = None - if tw: - tw.destroy() - - -############################### -# -# 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() # not in idle - - 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/Tools/idle/CallTips.py b/Tools/idle/CallTips.py deleted file mode 100644 index 8d35d5c130..0000000000 --- a/Tools/idle/CallTips.py +++ /dev/null @@ -1,197 +0,0 @@ -# CallTips.py - An IDLE extension that provides "Call Tips" - ie, a floating window that -# displays parameter information as you open parens. - -import string -import types - -class CallTips: - - menudefs = [ - ] - - keydefs = { - '<<paren-open>>': ['<Key-parenleft>'], - '<<paren-close>>': ['<Key-parenright>'], - '<<check-calltip-cancel>>': ['<KeyRelease>'], - '<<calltip-cancel>>': ['<ButtonPress>', '<Key-Escape>'], - } - - windows_keydefs = { - } - - unix_keydefs = { - } - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - self.calltip = None - if hasattr(self.text, "make_calltip_window"): - self._make_calltip_window = self.text.make_calltip_window - else: - self._make_calltip_window = self._make_tk_calltip_window - - def close(self): - self._make_calltip_window = None - - # Makes a Tk based calltip window. Used by IDLE, but not Pythonwin. - # See __init__ above for how this is used. - def _make_tk_calltip_window(self): - import CallTipWindow - return CallTipWindow.CallTip(self.text) - - def _remove_calltip_window(self): - if self.calltip: - self.calltip.hidetip() - self.calltip = None - - def paren_open_event(self, event): - self._remove_calltip_window() - arg_text = get_arg_text(self.get_object_at_cursor()) - if arg_text: - self.calltip_start = self.text.index("insert") - self.calltip = self._make_calltip_window() - self.calltip.showtip(arg_text) - return "" #so the event is handled normally. - - def paren_close_event(self, event): - # Now just hides, but later we should check if other - # paren'd expressions remain open. - self._remove_calltip_window() - return "" #so the event is handled normally. - - def check_calltip_cancel_event(self, event): - if self.calltip: - # If we have moved before the start of the calltip, - # or off the calltip line, then cancel the tip. - # (Later need to be smarter about multi-line, etc) - if self.text.compare("insert", "<=", self.calltip_start) or \ - self.text.compare("insert", ">", self.calltip_start + " lineend"): - self._remove_calltip_window() - return "" #so the event is handled normally. - - def calltip_cancel_event(self, event): - self._remove_calltip_window() - return "" #so the event is handled normally. - - def get_object_at_cursor(self, - wordchars="._" + string.ascii_letters + string.digits): - # Usage of ascii_letters is necessary to avoid UnicodeErrors - # if chars contains non-ASCII. - - # XXX - This needs to be moved to a better place - # so the "." attribute lookup code can also use it. - text = self.text - chars = text.get("insert linestart", "insert") - i = len(chars) - while i and chars[i-1] in wordchars: - i = i-1 - word = chars[i:] - if word: - # How is this for a hack! - import sys, __main__ - namespace = sys.modules.copy() - namespace.update(__main__.__dict__) - try: - return eval(word, namespace) - except: - pass - return None # Can't find an object. - -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)==types.ClassType: - # 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" % 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: - while doc[:1] in " \t\n": - doc = doc[1:] - 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 ): - failed=[] - for t in tests: - expected = t.__doc__ + "\n" + t.__doc__ - if get_arg_text(t) != expected: - failed.append(t) - print "%s - expected %s, but got %s" % (t, `expected`, `get_arg_text(t)`) - 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/Tools/idle/ChangeLog b/Tools/idle/ChangeLog deleted file mode 100644 index b853a34af3..0000000000 --- a/Tools/idle/ChangeLog +++ /dev/null @@ -1,1017 +0,0 @@ -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/Tools/idle/ClassBrowser.py b/Tools/idle/ClassBrowser.py deleted file mode 100644 index 2d81f9eda0..0000000000 --- a/Tools/idle/ClassBrowser.py +++ /dev/null @@ -1,217 +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 - -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 - sc = ScrolledCanvas(top, bg="white", 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): - try: - return bool(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/Tools/idle/ColorDelegator.py b/Tools/idle/ColorDelegator.py deleted file mode 100644 index 059108f65c..0000000000 --- a/Tools/idle/ColorDelegator.py +++ /dev/null @@ -1,246 +0,0 @@ -import time -import re -import keyword -from Tkinter import * -from Delegator import Delegator -from IdleConf import idleconf - -#$ event <<toggle-auto-coloring>> -#$ win <Control-slash> -#$ unix <Control-slash> - -DEBUG = 0 - - -def any(name, list): - return "(?P<%s>" % name + "|".join(list) + ")" - -def make_pat(): - kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" - comment = any("COMMENT", [r"#[^\n]*"]) - sqstring = r"(\b[rR])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" - dqstring = r'(\b[rR])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' - sq3string = r"(\b[rR])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" - dq3string = r'(\b[rR])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' - string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) - return kw + "|" + 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", re.S) - -class ColorDelegator(Delegator): - - def __init__(self): - Delegator.__init__(self) - self.prog = prog - self.idprog = idprog - self.asprog = asprog - - 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: - apply(self.tag_configure, (tag,), cnf) - self.tag_raise('sel') - - cconf = idleconf.getsection('Colors') - - tagdefs = { - "COMMENT": cconf.getcolor("comment"), - "KEYWORD": cconf.getcolor("keyword"), - "STRING": cconf.getcolor("string"), - "DEFINITION": cconf.getcolor("definition"), - "SYNC": cconf.getcolor("sync"), - "TODO": cconf.getcolor("todo"), - "BREAK": cconf.getcolor("break"), - # The following is used by ReplaceDialog: - "hit": cconf.getcolor("hit"), - } - - 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 = 1 - colorizing = 0 - - 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 = 1 - 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 = 0 - self.stop_colorizing = 1 - 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 = 1 - 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 = 0 - self.colorizing = 1 - if DEBUG: print "colorizing..." - t0 = time.clock() - self.recolorize_main() - t1 = time.clock() - if DEBUG: print "%.3f seconds" % (t1-t0) - finally: - self.colorizing = 0 - 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 1: - 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 = 0 - 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, "->", `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; - # cheap approximation to the truth - while 1: - m1 = self.asprog.match(chars, b) - 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 = 0 - 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 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/Tools/idle/Debugger.py b/Tools/idle/Debugger.py deleted file mode 100644 index 0883597769..0000000000 --- a/Tools/idle/Debugger.py +++ /dev/null @@ -1,308 +0,0 @@ -import os -import bdb -from Tkinter import * -from WindowList import ListedToplevel - -import StackViewer - - -class Debugger(bdb.Bdb): - - interacting = 0 - - vstack = vsource = vlocals = vglobals = None - - def __init__(self, pyshell): - bdb.Bdb.__init__(self) - self.pyshell = pyshell - self.make_gui() - - def canonic(self, filename): - # Canonicalize filename -- called by Bdb - return os.path.normcase(os.path.abspath(filename)) - - def close(self, event=None): - if self.interacting: - self.top.bell() - return - if self.stackviewer: - self.stackviewer.close(); self.stackviewer = None - self.pyshell.close_debugger() - self.top.destroy() - - def run(self, *args): - try: - self.interacting = 1 - return apply(bdb.Bdb.run, (self,) + args) - finally: - self.interacting = 0 - - def user_line(self, frame): - self.interaction(frame) - - def user_return(self, frame, rv): - # XXX show rv? - ##self.interaction(frame) - pass - - def user_exception(self, frame, info): - self.interaction(frame, info) - - 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.vsource.set(1) - 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.vglobals.set(1) - 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() - - frame = None - - def interaction(self, frame, info=None): - self.frame = frame - code = frame.f_code - file = code.co_filename - base = os.path.basename(file) - lineno = frame.f_lineno - # - message = "%s:%s" % (base, lineno) - if code.co_name != "?": - message = "%s: %s()" % (message, code.co_name) - 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.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.tkraise() - 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 - code = frame.f_code - file = code.co_filename - lineno = frame.f_lineno - if file[:1] + file[-1:] != "<>" and os.path.exists(file): - edit = self.flist.open(file) - if edit: - edit.gotoline(lineno) - - def cont(self): - self.set_continue() - self.root.quit() - - def step(self): - self.set_step() - self.root.quit() - - def next(self): - self.set_next(self.frame) - self.root.quit() - - def ret(self): - self.set_return(self.frame) - self.root.quit() - - def quit(self): - self.set_quit() - self.root.quit() - - stackviewer = None - - def show_stack(self): - if not self.stackviewer and self.vstack.get(): - self.stackviewer = sv = StackViewer.StackViewer( - self.fstack, self.flist, self) - if self.frame: - stack, i = self.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 = StackViewer.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 = StackViewer.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) - if gv: - gv.load_dict(gdict, force) - - def set_breakpoint_here(self, edit): - text = edit.text - filename = edit.io.filename - if not filename: - text.bell() - return - lineno = int(float(text.index("insert"))) - msg = self.set_break(filename, lineno) - if msg: - text.bell() - return - text.tag_add("BREAK", "insert linestart", "insert lineend +1char") - - # A literal copy of Bdb.set_break() without the print statement at the end - def set_break(self, filename, lineno, temporary=0, cond = None): - import linecache # Import as late as possible - filename = self.canonic(filename) - line = linecache.getline(filename, lineno) - if not line: - return 'That line does not exist!' - if not self.breaks.has_key(filename): - self.breaks[filename] = [] - list = self.breaks[filename] - if not lineno in list: - list.append(lineno) - bp = bdb.Breakpoint(filename, lineno, temporary, cond) diff --git a/Tools/idle/Delegator.py b/Tools/idle/Delegator.py deleted file mode 100644 index 6125591fe0..0000000000 --- a/Tools/idle/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/Tools/idle/EditorWindow.py b/Tools/idle/EditorWindow.py deleted file mode 100644 index e8c310a1cc..0000000000 --- a/Tools/idle/EditorWindow.py +++ /dev/null @@ -1,756 +0,0 @@ -import sys -import os -import re -import imp -from Tkinter import * -import tkSimpleDialog -import tkMessageBox - -import webbrowser -import idlever -import WindowList -from IdleConf import idleconf - -# The default tab setting for a Text widget, in average-width characters. -TK_TABWIDTH_DEFAULT = 8 - -# File menu - -#$ event <<open-module>> -#$ win <Alt-m> -#$ unix <Control-x><Control-m> - -#$ event <<open-class-browser>> -#$ win <Alt-c> -#$ unix <Control-x><Control-b> - -#$ event <<open-path-browser>> - -#$ event <<close-window>> - -#$ unix <Control-x><Control-0> -#$ unix <Control-x><Key-0> -#$ win <Alt-F4> - -# Edit menu - -#$ event <<Copy>> -#$ win <Control-c> -#$ unix <Alt-w> - -#$ event <<Cut>> -#$ win <Control-x> -#$ unix <Control-w> - -#$ event <<Paste>> -#$ win <Control-v> -#$ unix <Control-y> - -#$ event <<select-all>> -#$ win <Alt-a> -#$ unix <Alt-a> - -# Help menu - -#$ event <<help>> -#$ win <F1> -#$ unix <F1> - -#$ event <<about-idle>> - -# Events without menu entries - -#$ event <<remove-selection>> -#$ win <Escape> - -#$ event <<center-insert>> -#$ win <Control-l> -#$ unix <Control-l> - -#$ event <<do-nothing>> -#$ unix <Control-x> - - -about_title = "About IDLE" -about_text = """\ -IDLE %s - -An Integrated DeveLopment Environment for Python - -by Guido van Rossum -""" % idlever.IDLE_VERSION - -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: - - from Percolator import Percolator - from ColorDelegator import ColorDelegator - from UndoDelegator import UndoDelegator - from IOBinding import IOBinding - import Bindings - from Tkinter import Toplevel - from MultiStatusBar import MultiStatusBar - - about_title = about_title - about_text = about_text - - vars = {} - runnable = False # Shell window cannot Import Module or Run Script - - def __init__(self, flist=None, filename=None, key=None, root=None): - edconf = idleconf.getsection('EditorWindow') - coconf = idleconf.getsection('Colors') - self.flist = flist - root = root or flist.root - self.root = root - if flist: - self.vars = flist.vars - self.menubar = Menu(root) - self.top = top = self.Toplevel(root, menu=self.menubar) - self.vbar = vbar = Scrollbar(top, name='vbar') - self.text_frame = text_frame = Frame(top) - self.text = text = Text(text_frame, name='text', padx=5, - foreground=coconf.getdef('normal-foreground'), - background=coconf.getdef('normal-background'), - highlightcolor=coconf.getdef('hilite-foreground'), - highlightbackground=coconf.getdef('hilite-background'), - insertbackground=coconf.getdef('cursor-background'), - width=edconf.getint('width'), - height=edconf.getint('height'), - wrap="none") - - self.createmenubar() - self.apply_bindings() - - self.top.protocol("WM_DELETE_WINDOW", self.close) - self.top.bind("<<close-window>>", self.close_event) - 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-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("<3>", self.right_menu_event) - if flist: - flist.inversedict[self] = key - if key: - flist.dict[key] = self - text.bind("<<open-new-window>>", self.flist.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) - - vbar['command'] = text.yview - vbar.pack(side=RIGHT, fill=Y) - - text['yscrollcommand'] = vbar.set - text['font'] = edconf.get('font-name'), edconf.get('font-size') - text_frame.pack(side=LEFT, fill=BOTH, expand=1) - text.pack(side=TOP, fill=BOTH, expand=1) - text.focus_set() - - self.per = per = self.Percolator(text) - if self.ispythonsource(filename): - self.color = color = self.ColorDelegator(); per.insertfilter(color) - ##print "Initial colorizer" - else: - ##print "No initial colorizer" - self.color = None - self.undo = undo = self.UndoDelegator(); per.insertfilter(undo) - self.io = io = self.IOBinding(self) - - 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) - io.set_filename_change_hook(self.filename_change_hook) - - if filename: - if os.path.exists(filename): - io.loadfile(filename) - else: - io.set_filename(filename) - - self.saved_change_hook() - - 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 - - if self.extensions.has_key('AutoIndent'): - self.extensions['AutoIndent'].set_indentation_params( - self.ispythonsource(filename)) - self.set_status_bar() - - def set_status_bar(self): - self.status_bar = self.MultiStatusBar(self.text_frame) - 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('<KeyRelease>', self.set_line_and_column) - self.text.bind('<ButtonRelease>', self.set_line_and_column) - 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) - - def wakeup(self): - if self.top.wm_state() == "iconic": - self.top.wm_deiconify() - else: - self.top.tkraise() - self.text.focus_set() - - menu_specs = [ - ("file", "_File"), - ("edit", "_Edit"), - ("windows", "_Windows"), - ("help", "_Help"), - ] - - 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) - self.fill_menus() - - def postwindowsmenu(self): - # Only called when Windows menu exists - # XXX Actually, this Just-In-Time updating interferes badly - # XXX with the tear-off feature. It would be better to update - # XXX all Windows menus whenever the list of windows changes. - 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): - tkMessageBox.showinfo(self.about_title, self.about_text, - master=self.text) - - helpfile = "help.txt" - - def help_dialog(self, event=None): - try: - helpfile = os.path.join(os.path.dirname(__file__), self.helpfile) - except NameError: - helpfile = self.helpfile - if self.flist: - self.flist.open(helpfile) - else: - self.io.loadfile(helpfile) - - help_url = "http://www.python.org/doc/current/" - if sys.platform[:3] == "win": - fn = os.path.dirname(__file__) - fn = os.path.join(fn, os.pardir, os.pardir, "pythlp.chm") - fn = os.path.normpath(fn) - if os.path.isfile(fn): - help_url = fn - else: - fn = os.path.dirname(__file__) - fn = os.path.join(fn, os.pardir, os.pardir, "Doc", "index.html") - fn = os.path.normpath(fn) - if os.path.isfile(fn): - help_url = fn - del fn - - def python_docs(self, event=None): - os.startfile(self.help_url) - else: - def python_docs(self, event=None): - webbrowser.open(self.help_url) - - 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 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() - if not name: - name = tkSimpleDialog.askstring("Module", - "Enter the name of a Python module\n" - "to search on sys.path and open:", - parent=self.text) - 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: - 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 'python' in line - - 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() - if self.ispythonsource(self.io.filename): - self.addcolorizer() - else: - self.rmcolorizer() - - def addcolorizer(self): - if self.color: - return - ##print "Add colorizer" - 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 - ##print "Remove colorizer" - self.per.removefilter(self.undo) - self.per.removefilter(self.color) - self.color = None - self.per.insertfilter(self.undo) - - 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 filename - - def long_title(self): - return 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 close_event(self, event): - self.close() - - def maybesave(self): - if self.io: - return self.io.maybesave() - - def close(self): - self.top.wm_deiconify() - self.top.tkraise() - reply = self.maybesave() - if reply != "cancel": - self._close() - return reply - - def _close(self): - 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.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", `name` - import traceback - traceback.print_exc() - - def get_standard_extension_names(self): - return idleconf.getextensions() - - def load_extension(self, name): - mod = __import__(name, globals(), locals(), []) - cls = getattr(mod, name) - ins = cls(self) - self.extensions[name] = ins - kdnames = ["keydefs"] - if sys.platform == 'win32': - kdnames.append("windows_keydefs") - elif sys.platform == 'mac': - kdnames.append("mac_keydefs") - else: - kdnames.append("unix_keydefs") - keydefs = {} - for kdname in kdnames: - if hasattr(ins, kdname): - keydefs.update(getattr(ins, kdname)) - 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)) - if hasattr(ins, "menudefs"): - self.fill_menus(ins.menudefs, keydefs) - return ins - - 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: - apply(text.event_add, (event,) + tuple(keylist)) - - def fill_menus(self, defs=None, keydefs=None): - # Fill the menus. Menus that are absent or None in - # self.menudict are ignored. - if defs is None: - defs = self.Bindings.menudefs - if keydefs is None: - keydefs = self.Bindings.default_keydefs - menudict = self.menudict - text = self.text - for mname, itemlist in defs: - menu = menudict.get(mname) - if not menu: - continue - for item in itemlist: - if not item: - menu.add_separator() - else: - label, event = item - checkbutton = (label[:1] == '!') - if checkbutton: - label = label[1:] - underline, label = prepstr(label) - accelerator = get_accelerator(keydefs, event) - def command(text=text, event=event): - text.event_generate(event) - if checkbutton: - var = self.getrawvar(event, 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.getrawvar(name) - if var: - return var.get() - - def setvar(self, name, value, vartype=None): - var = self.getrawvar(name, vartype) - if var: - var.set(value) - - def getrawvar(self, name, vartype=None): - var = self.vars.get(name) - if not var and vartype: - self.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) - -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, event): - keylist = keydefs.get(event) - 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("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/Tools/idle/FileList.py b/Tools/idle/FileList.py deleted file mode 100644 index 0a1c81a7ca..0000000000 --- a/Tools/idle/FileList.py +++ /dev/null @@ -1,138 +0,0 @@ -import os -from Tkinter import * -import tkMessageBox - -import WindowList - -#$ event <<open-new-window>> -#$ win <Control-n> -#$ unix <Control-x><Control-n> - -# (This is labeled as 'Exit'in the File menu) -#$ event <<close-all-windows>> -#$ win <Control-q> -#$ unix <Control-x><Control-c> - -class FileList: - - from EditorWindow import EditorWindow - EditorWindow.Toplevel = WindowList.ListedToplevel # XXX Patch it! - - def __init__(self, root): - self.root = root - self.dict = {} - self.inversedict = {} - self.vars = {} # For EditorWindow.getrawvar (shared Tcl variables) - - def open(self, filename): - assert filename - filename = self.canonize(filename) - if os.path.isdir(filename): - tkMessageBox.showerror( - "Is A Directory", - "The path %s 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.wakeup() - return edit - if not os.path.exists(filename): - tkMessageBox.showinfo( - "New File", - "Opening non-existent file %s" % `filename`, - master=self.root) - 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): - return self.EditorWindow(self) - - def new_callback(self, event): - self.new() - return "break" - - 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 %s" % `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/Tools/idle/FormatParagraph.py b/Tools/idle/FormatParagraph.py deleted file mode 100644 index c1bc769c22..0000000000 --- a/Tools/idle/FormatParagraph.py +++ /dev/null @@ -1,154 +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 - -class FormatParagraph: - - menudefs = [ - ('edit', [ - ('Format Paragraph', '<<format-paragraph>>'), - ]) - ] - - keydefs = { - '<<format-paragraph>>': ['<Alt-q>'], - } - - unix_keydefs = { - '<<format-paragraph>>': ['<Meta-q>'], - } - - def __init__(self, editwin): - self.editwin = editwin - - def close(self): - self.editwin = None - - def format_paragraph_event(self, event): - 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 70 chars or a 20 char width, whichever is greater. - format_width = max(70-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) - 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=70): - 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/Tools/idle/FrameViewer.py b/Tools/idle/FrameViewer.py deleted file mode 100644 index 2ce0935ba3..0000000000 --- a/Tools/idle/FrameViewer.py +++ /dev/null @@ -1,38 +0,0 @@ -from repr import Repr -from Tkinter import * - -class FrameViewer: - - def __init__(self, root, frame): - self.root = root - self.frame = frame - self.top = Toplevel(self.root) - self.repr = Repr() - self.repr.maxstring = 60 - self.load_variables() - - def load_variables(self): - row = 0 - if self.frame.f_locals is not self.frame.f_globals: - l = Label(self.top, text="Local Variables", - borderwidth=2, relief="raised") - l.grid(row=row, column=0, columnspan=2, sticky="ew") - row = self.load_names(self.frame.f_locals, row+1) - l = Label(self.top, text="Global Variables", - borderwidth=2, relief="raised") - l.grid(row=row, column=0, columnspan=2, sticky="ew") - row = self.load_names(self.frame.f_globals, row+1) - - def load_names(self, dict, row): - names = dict.keys() - names.sort() - for name in names: - value = dict[name] - svalue = self.repr.repr(value) - l = Label(self.top, text=name) - l.grid(row=row, column=0, sticky="w") - l = Entry(self.top, width=60, borderwidth=0) - l.insert(0, svalue) - l.grid(row=row, column=1, sticky="w") - row = row+1 - return row diff --git a/Tools/idle/GrepDialog.py b/Tools/idle/GrepDialog.py deleted file mode 100644 index 84cac0ea31..0000000000 --- a/Tools/idle/GrepDialog.py +++ /dev/null @@ -1,132 +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 - dialog.open(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, io=None): - SearchDialogBase.open(self, None) - 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 %s 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/Tools/idle/IOBinding.py b/Tools/idle/IOBinding.py deleted file mode 100644 index 8d654b9aec..0000000000 --- a/Tools/idle/IOBinding.py +++ /dev/null @@ -1,448 +0,0 @@ -import os -import types -import sys -import codecs -import re -import tempfile -import tkFileDialog -import tkMessageBox -from IdleConf import idleconf - -#$ event <<open-window-from-file>> -#$ win <Control-o> -#$ unix <Control-x><Control-f> - -#$ event <<save-window>> -#$ win <Control-s> -#$ unix <Control-x><Control-s> - -#$ event <<save-window-as-file>> -#$ win <Alt-s> -#$ unix <Control-x><Control-w> - -#$ event <<save-copy-of-window-as-file>> -#$ win <Alt-Shift-s> -#$ unix <Control-x><w> - -#$ event <<print-window>> -#$ win <Control-p> -#$ unix <Control-x><Control-p> - -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: - pass - -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) - 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] - codecs.lookup(encoding) - except (ValueError, LookupError): - pass - -encoding = encoding.lower() - -coding_re = re.compile("coding[:=]\s*([-\w_.]+)") -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.__id_print = self.text.bind("<<print-window>>", self.print_window) - self.fileencoding = None - - 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 - - def set_filename(self, filename): - self.filename = filename - self.set_saved(1) - if self.filename_change_hook: - self.filename_change_hook() - - def open(self, event): - if self.editwin.flist: - filename = self.askopenfile() - if filename: - 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" - filename = self.askopenfile() - if filename: - self.loadfile(filename) - else: - self.text.focus_set() - return "break" - - def loadfile(self, filename): - try: - f = open(filename) - chars = f.read() - f.close() - except IOError, msg: - tkMessageBox.showerror("I/O Error", str(msg), master=self.text) - return False - - chars = self.decode(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") - return True - - def decode(self, chars): - # Try to 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) - 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) - self.text.focus_set() - return "break" - - def save_a_copy(self, event): - filename = self.asksavefile() - if filename: - self.writefile(filename) - self.text.focus_set() - return "break" - - def print_window(self, event): - if self.get_saved(): - filename = self.filename - else: - (tfd, tfn) = tempfile.mkstemp() - os.close(tfd) - filename = tfn - if not self.writefile(filename): - os.unlink(tfn) - return "break" - edconf = idleconf.getsection('EditorWindow') - command = edconf.get('print-command') - command = command % filename - if os.name == 'posix': - command = command + " 2>&1" - pipe = os.popen(command, "r") - 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) - return "break" - - def writefile(self, filename): - self.fixlastline() - chars = self.encode(self.text.get("1.0", "end-1c")) - try: - f = open(filename, "w") - f.write(chars) - f.close() - ## print "saved to", `filename` - 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. - try: - chars = chars.encode(encoding) - enc = encoding - except UnicodeError: - chars = BOM_UTF8 + chars.encode("utf-8") - enc = "utf-8" - tkMessageBox.showerror( - "I/O Error", - "Non-ASCII found, yet no encoding declared. Add a line like\n" - "# -*- coding: %s -*- \nto your file" % enc, - master = self.text) - return chars - - def fixlastline(self): - c = self.text.get("end-2c") - if c != '\n': - self.text.insert("end-1c", "\n") - - 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) - return self.opendialog.show(initialdir=dir, initialfile=base) - - def defaultfilename(self, mode="open"): - if self.filename: - return os.path.split(self.filename) - 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) - return self.savedialog.show(initialdir=dir, initialfile=base) - - -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__": - from Tkinter import * - test() diff --git a/Tools/idle/Icons/folder.gif b/Tools/idle/Icons/folder.gif Binary files differdeleted file mode 100644 index effe8dc8a0..0000000000 --- a/Tools/idle/Icons/folder.gif +++ /dev/null diff --git a/Tools/idle/Icons/minusnode.gif b/Tools/idle/Icons/minusnode.gif Binary files differdeleted file mode 100644 index ceaaee18d1..0000000000 --- a/Tools/idle/Icons/minusnode.gif +++ /dev/null diff --git a/Tools/idle/Icons/openfolder.gif b/Tools/idle/Icons/openfolder.gif Binary files differdeleted file mode 100644 index 24aea1bebe..0000000000 --- a/Tools/idle/Icons/openfolder.gif +++ /dev/null diff --git a/Tools/idle/Icons/plusnode.gif b/Tools/idle/Icons/plusnode.gif Binary files differdeleted file mode 100644 index 13ace90eb3..0000000000 --- a/Tools/idle/Icons/plusnode.gif +++ /dev/null diff --git a/Tools/idle/Icons/python.gif b/Tools/idle/Icons/python.gif Binary files differdeleted file mode 100644 index 58271edec4..0000000000 --- a/Tools/idle/Icons/python.gif +++ /dev/null diff --git a/Tools/idle/Icons/tk.gif b/Tools/idle/Icons/tk.gif Binary files differdeleted file mode 100644 index a603f5ecb0..0000000000 --- a/Tools/idle/Icons/tk.gif +++ /dev/null diff --git a/Tools/idle/IdleConf.py b/Tools/idle/IdleConf.py deleted file mode 100644 index 8eaa8e06b5..0000000000 --- a/Tools/idle/IdleConf.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Provides access to configuration information""" - -import os -import sys -from ConfigParser import ConfigParser, NoOptionError, NoSectionError - -class IdleConfParser(ConfigParser): - - # these conf sections do not define extensions! - builtin_sections = {} - for section in ('EditorWindow', 'Colors'): - builtin_sections[section] = section - - def getcolor(self, sec, name): - """Return a dictionary with foreground and background colors - - The return value is appropriate for passing to Tkinter in, e.g., - a tag_config call. - """ - fore = self.getdef(sec, name + "-foreground") - back = self.getdef(sec, name + "-background") - return {"foreground": fore, - "background": back} - - def getdef(self, sec, options, raw=0, vars=None, default=None): - """Get an option value for given section or return default""" - try: - return self.get(sec, options, raw, vars) - except (NoSectionError, NoOptionError): - return default - - def getsection(self, section): - """Return a SectionConfigParser object""" - return SectionConfigParser(section, self) - - def getextensions(self): - exts = [] - for sec in self.sections(): - if self.builtin_sections.has_key(sec): - continue - # enable is a bool, but it may not be defined - if self.getdef(sec, 'enable') != '0': - exts.append(sec) - return exts - - def reload(self): - global idleconf - idleconf = IdleConfParser() - load(_dir) # _dir is a global holding the last directory loaded - -class SectionConfigParser: - """A ConfigParser object specialized for one section - - This class has all the get methods that a regular ConfigParser does, - but without requiring a section argument. - """ - def __init__(self, section, config): - self.section = section - self.config = config - - def options(self): - return self.config.options(self.section) - - def get(self, options, raw=0, vars=None): - return self.config.get(self.section, options, raw, vars) - - def getdef(self, options, raw=0, vars=None, default=None): - return self.config.getdef(self.section, options, raw, vars, default) - - def getint(self, option): - return self.config.getint(self.section, option) - - def getfloat(self, option): - return self.config.getint(self.section, option) - - def getboolean(self, option): - return self.config.getint(self.section, option) - - def getcolor(self, option): - return self.config.getcolor(self.section, option) - -def load(dir): - """Load IDLE configuration files based on IDLE install in dir - - Attempts to load two config files: - dir/config.txt - dir/config-[win/mac/unix].txt - dir/config-%(sys.platform)s.txt - ~/.idle - """ - global _dir - _dir = dir - - if sys.platform[:3] == 'win': - genplatfile = os.path.join(dir, "config-win.txt") - # XXX don't know what the platform string is on a Mac - elif sys.platform[:3] == 'mac': - genplatfile = os.path.join(dir, "config-mac.txt") - else: - genplatfile = os.path.join(dir, "config-unix.txt") - - platfile = os.path.join(dir, "config-%s.txt" % sys.platform) - - try: - homedir = os.environ['HOME'] - except KeyError: - homedir = os.getcwd() - - idleconf.read((os.path.join(dir, "config.txt"), genplatfile, platfile, - os.path.join(homedir, ".idle"))) - -idleconf = IdleConfParser() -load(os.path.dirname(__file__)) diff --git a/Tools/idle/IdleHistory.py b/Tools/idle/IdleHistory.py deleted file mode 100644 index 46e70e1224..0000000000 --- a/Tools/idle/IdleHistory.py +++ /dev/null @@ -1,86 +0,0 @@ -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 - 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: - pointer = -1 - nprefix = len(prefix) - while 1: - if reverse: - pointer = pointer - 1 - else: - pointer = pointer + 1 - if pointer < 0 or pointer >= nhist: - self.text.bell() - 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 - - def recall(self, s): - s = s.strip() - self.text.tag_remove("sel", "1.0", "end") - self.text.delete("iomark", "end-1c") - self.text.mark_set("insert", "end-1c") - self.text.insert("insert", s) - self.text.see("insert") diff --git a/Tools/idle/MANIFEST.in b/Tools/idle/MANIFEST.in deleted file mode 100644 index 440c9d1c81..0000000000 --- a/Tools/idle/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -include *.txt -include idle -include MANIFEST.in -include MANIFEST
\ No newline at end of file diff --git a/Tools/idle/MultiScrolledLists.py b/Tools/idle/MultiScrolledLists.py deleted file mode 100644 index 6398b86dd3..0000000000 --- a/Tools/idle/MultiScrolledLists.py +++ /dev/null @@ -1,137 +0,0 @@ -# One or more ScrolledLists with HSeparators between them. -# There is a hierarchical relationship between them: -# the right list displays the substructure of the selected item -# in the left list. - -from Tkinter import * -from WindowList import ListedToplevel -from Separator import HSeparator -from ScrolledList import ScrolledList - -class MultiScrolledLists: - - def __init__(self, root, nlists=2): - assert nlists >= 1 - self.root = root - self.nlists = nlists - self.path = [] - # create top - self.top = top = ListedToplevel(root) - top.protocol("WM_DELETE_WINDOW", self.close) - top.bind("<Escape>", self.close) - self.settitle() - # create frames and separators in between - self.frames = [] - self.separators = [] - last = top - for i in range(nlists-1): - sepa = HSeparator(last) - self.separators.append(sepa) - frame, last = sepa.parts() - self.frames.append(frame) - self.frames.append(last) - # create labels and lists - self.labels = [] - self.lists = [] - for i in range(nlists): - frame = self.frames[i] - label = Label(frame, text=self.subtitle(i), - relief="groove", borderwidth=2) - label.pack(fill="x") - self.labels.append(label) - list = ScrolledList(frame, width=self.width(i), - height=self.height(i)) - self.lists.append(list) - list.on_select = \ - lambda index, i=i, self=self: self.on_select(index, i) - list.on_double = \ - lambda index, i=i, self=self: self.on_double(index, i) - # fill leftmost list (rest get filled on demand) - self.fill(0) - # XXX one after_idle isn't enough; two are... - top.after_idle(self.call_pack_propagate_1) - - def call_pack_propagate_1(self): - self.top.after_idle(self.call_pack_propagate) - - def call_pack_propagate(self): - for frame in self.frames: - frame.pack_propagate(0) - - def close(self, event=None): - self.top.destroy() - - def settitle(self): - short = self.shorttitle() - long = self.longtitle() - if short and long: - title = short + " - " + long - elif short: - title = short - elif long: - title = long - else: - title = "Untitled" - icon = short or long or title - self.top.wm_title(title) - self.top.wm_iconname(icon) - - def longtitle(self): - # override this - return "Multi Scrolled Lists" - - def shorttitle(self): - # override this - return None - - def width(self, i): - # override this - return 20 - - def height(self, i): - # override this - return 10 - - def subtitle(self, i): - # override this - return "Column %d" % i - - def fill(self, i): - for k in range(i, self.nlists): - self.lists[k].clear() - self.labels[k].configure(text=self.subtitle(k)) - list = self.lists[i] - l = self.items(i) - for s in l: - list.append(s) - - def on_select(self, index, i): - item = self.lists[i].get(index) - del self.path[i:] - self.path.append(item) - if i+1 < self.nlists: - self.fill(i+1) - - def items(self, i): - # override this - l = [] - for k in range(10): - s = str(k) - if i > 0: - s = self.path[i-1] + "." + s - l.append(s) - return l - - def on_double(self, index, i): - pass - - -def main(): - root = Tk() - quit = Button(root, text="Exit", command=root.destroy) - quit.pack() - MultiScrolledLists(root, 4) - root.mainloop() - -if __name__ == "__main__": - main() diff --git a/Tools/idle/MultiStatusBar.py b/Tools/idle/MultiStatusBar.py deleted file mode 100644 index dd6d04145f..0000000000 --- a/Tools/idle/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() - apply(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/Tools/idle/NEWS.txt b/Tools/idle/NEWS.txt deleted file mode 100644 index 86cbc7609f..0000000000 --- a/Tools/idle/NEWS.txt +++ /dev/null @@ -1,130 +0,0 @@ -(For a more detailed change log, see the file ChangeLog.) - ----------------------------------------------------------------------- - -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/Tools/idle/ObjectBrowser.py b/Tools/idle/ObjectBrowser.py deleted file mode 100644 index 416be5a15f..0000000000 --- a/Tools/idle/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(`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/Tools/idle/OldStackViewer.py b/Tools/idle/OldStackViewer.py deleted file mode 100644 index 4f295e8dbe..0000000000 --- a/Tools/idle/OldStackViewer.py +++ /dev/null @@ -1,275 +0,0 @@ -import sys -import os -from Tkinter import * -import linecache -from repr import Repr -from WindowList import ListedToplevel - -from ScrolledList import ScrolledList - - -class StackBrowser: - - def __init__(self, root, flist, stack=None): - self.top = top = ListedToplevel(root) - top.protocol("WM_DELETE_WINDOW", self.close) - top.bind("<Key-Escape>", self.close) - top.wm_title("Stack viewer") - top.wm_iconname("Stack") - # Create help label - self.helplabel = Label(top, - text="Click once to view variables; twice for source", - borderwidth=2, relief="groove") - self.helplabel.pack(fill="x") - # - self.sv = StackViewer(top, flist, self) - if stack is None: - stack = get_stack() - self.sv.load_stack(stack) - - def close(self, event=None): - self.top.destroy() - - localsframe = None - localsviewer = None - localsdict = None - globalsframe = None - globalsviewer = None - globalsdict = None - curframe = None - - def show_frame(self, (frame, lineno)): - if frame is self.curframe: - return - self.curframe = None - if frame.f_globals is not self.globalsdict: - self.show_globals(frame) - self.show_locals(frame) - self.curframe = frame - - def show_globals(self, frame): - title = "Global Variables" - if frame.f_globals.has_key("__name__"): - try: - name = str(frame.f_globals["__name__"]) + "" - except: - name = "" - if name: - title = title + " in module " + name - self.globalsdict = None - if self.globalsviewer: - self.globalsviewer.close() - self.globalsviewer = None - if not self.globalsframe: - self.globalsframe = Frame(self.top) - self.globalsdict = frame.f_globals - self.globalsviewer = NamespaceViewer( - self.globalsframe, - title, - self.globalsdict) - self.globalsframe.pack(fill="both", side="bottom") - - def show_locals(self, frame): - self.localsdict = None - if self.localsviewer: - self.localsviewer.close() - self.localsviewer = None - if frame.f_locals is not frame.f_globals: - title = "Local Variables" - code = frame.f_code - funcname = code.co_name - if funcname not in ("?", "", None): - title = title + " in " + funcname - if not self.localsframe: - self.localsframe = Frame(self.top) - self.localsdict = frame.f_locals - self.localsviewer = NamespaceViewer( - self.localsframe, - title, - self.localsdict) - self.localsframe.pack(fill="both", side="top") - else: - if self.localsframe: - self.localsframe.forget() - - -class StackViewer(ScrolledList): - - def __init__(self, master, flist, browser): - ScrolledList.__init__(self, master, width=80) - self.flist = flist - self.browser = browser - self.stack = [] - - def load_stack(self, stack, index=None): - self.stack = stack - self.clear() -## if len(stack) > 10: -## l["height"] = 10 -## self.topframe.pack(expand=1) -## else: -## l["height"] = len(stack) -## self.topframe.pack(expand=0) - 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 - 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) - if i == index: - item = "> " + item - self.append(item) - if index is not None: - self.select(index) - - def popup_event(self, event): - if self.stack: - return ScrolledList.popup_event(self, event) - - def fill_menu(self): - 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): - if 0 <= index < len(self.stack): - self.browser.show_frame(self.stack[index]) - - def on_double(self, index): - 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.browser.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) - - -def get_stack(t=None, f=None): - if t is None: - t = sys.last_traceback - stack = [] - if t and t.tb_frame is f: - t = t.tb_next - while f is not None: - stack.append((f, f.f_lineno)) - if f is self.botframe: - break - f = f.f_back - stack.reverse() - while t is not None: - stack.append((t.tb_frame, t.tb_lineno)) - t = t.tb_next - return stack - - -def getexception(type=None, value=None): - if type is None: - 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 - - -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 - self.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): - 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) - l = Label(subframe, text=name) - l.grid(row=row, column=0, sticky="nw") - ## l = Label(subframe, text=svalue, justify="l", wraplength=300) - l = Entry(subframe, width=0, borderwidth=0) - l.insert(0, svalue) - ## l["state"] = "disabled" - 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/Tools/idle/OutputWindow.py b/Tools/idle/OutputWindow.py deleted file mode 100644 index 0e7fba231a..0000000000 --- a/Tools/idle/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): - apply(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: - apply(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/Tools/idle/ParenMatch.py b/Tools/idle/ParenMatch.py deleted file mode 100644 index 1be60c0fda..0000000000 --- a/Tools/idle/ParenMatch.py +++ /dev/null @@ -1,189 +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. - -WARNING: This extension will fight with the CallTips extension, -because they both are interested in the KeyRelease-parenright event. -We'll have to fix IDLE to do something reasonable when two or more -extensions what to capture the same event. -""" - -import PyParse -from AutoIndent import AutoIndent, index2line -from IdleConf import idleconf - -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: - - fix interaction with CallTips - - 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 = [] - - keydefs = { - '<<flash-open-paren>>' : ('<KeyRelease-parenright>', - '<KeyRelease-bracketright>', - '<KeyRelease-braceright>'), - '<<check-restore>>' : ('<KeyPress>',), - } - - windows_keydefs = {} - unix_keydefs = {} - - iconf = idleconf.getsection('ParenMatch') - STYLE = iconf.getdef('style', 'default') - FLASH_DELAY = iconf.getint('flash-delay') - HILITE_CONFIG = iconf.getcolor('hilite') - BELL = iconf.getboolean('bell') - del iconf - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - self.finder = LastOpenBracketFinder(editwin) - self.counter = 0 - self._restore = None - self.set_style(self.STYLE) - - 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_open_paren_event(self, event): - index = self.finder.find(keysym_type(event.keysym)) - if index is None: - self.warn_mismatched() - return - self._restore = 1 - self.create_tag(index) - self.set_timeout() - - def check_restore_event(self, event=None): - if self._restore: - self.text.tag_delete("paren") - self._restore = None - - def handle_restore_timer(self, timer_count): - if timer_count + 1 == self.counter: - self.check_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, index): - """Highlight the single paren that matches""" - self.text.tag_add("paren", index) - self.text.tag_config("paren", self.HILITE_CONFIG) - - def create_tag_expression(self, index): - """Highlight the entire expression""" - self.text.tag_add("paren", index, "insert") - 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""" - pass - - 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.editwin.text_frame.after(self.FLASH_DELAY, - lambda self=self, c=self.counter: \ - self.handle_restore_timer(c)) - self.counter = self.counter + 1 - -def keysym_type(ks): - # Not all possible chars or keysyms are checked because of the - # limited context in which the function is used. - if ks == "parenright" or ks == "(": - return "paren" - if ks == "bracketright" or ks == "[": - return "bracket" - if ks == "braceright" or ks == "{": - return "brace" - -class LastOpenBracketFinder: - num_context_lines = AutoIndent.num_context_lines - indentwidth = AutoIndent.indentwidth - tabwidth = AutoIndent.tabwidth - context_use_ps1 = AutoIndent.context_use_ps1 - - def __init__(self, editwin): - self.editwin = editwin - self.text = editwin.text - - def _find_offset_in_buf(self, lno): - y = PyParse.Parser(self.indentwidth, self.tabwidth) - for context in self.num_context_lines: - startat = max(lno - context, 1) - startatindex = `startat` + ".0" - # rawtext needs to contain everything up to the last - # character, which was the close paren. the parser also - # requires that the last line ends with "\n" - rawtext = self.text.get(startatindex, "insert")[:-1] + "\n" - 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) - i = y.get_last_open_bracket_pos() - return i, y.str - - def find(self, right_keysym_type): - """Return the location of the last open paren""" - lno = index2line(self.text.index("insert")) - i, buf = self._find_offset_in_buf(lno) - if i is None \ - or keysym_type(buf[i]) != right_keysym_type: - return None - lines_back = buf[i:].count("\n") - 1 - # subtract one for the "\n" added to please the parser - upto_open = buf[:i] - j = upto_open.rfind("\n") + 1 # offset of column 0 of line - offset = i - j - return "%d.%d" % (lno - lines_back, offset) - - def _build_char_in_string_func(self, startindex): - def inner(offset, startindex=startindex, - icis=self.editwin.is_char_in_string): - return icis(startindex + "%dc" % offset) - return inner diff --git a/Tools/idle/PathBrowser.py b/Tools/idle/PathBrowser.py deleted file mode 100644 index 86cd2707dc..0000000000 --- a/Tools/idle/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/Tools/idle/Percolator.py b/Tools/idle/Percolator.py deleted file mode 100644 index 5682111137..0000000000 --- a/Tools/idle/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 - apply(self.delegate.insert, args) - def delete(self, *args): - print self.name, ": delete", args - apply(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/Tools/idle/PyParse.py b/Tools/idle/PyParse.py deleted file mode 100644 index 422a86cc76..0000000000 --- a/Tools/idle/PyParse.py +++ /dev/null @@ -1,584 +0,0 @@ -import re -import sys - -# Reason last stmt is continued (or C_NONE if it's not). -C_NONE, C_BACKSLASH, C_STRING, C_BRACKET = range(4) - -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]* - (?: if - | for - | 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. - # - # Ack, hack: in the shell window this kills us, because there's - # no way to tell the differences between output, >>> etc and - # user input. Indeed, IDLE's first output line makes the rest - # look like it's in an unclosed paren!: - # Python 1.5.2 (#0, Apr 13 1999, ... - - def find_good_parse_start(self, use_ps1, is_char_in_string=None, - _synchre=_synchre): - str, pos = self.str, None - if use_ps1: - # shell window - ps1 = '\n' + sys.ps1 - i = str.rfind(ps1) - if i >= 0: - pos = i + len(ps1) - # make it look like there's a newline instead - # of ps1 at the start -- hacking here once avoids - # repeated hackery later - self.str = str[:pos-1] + '\n' + str[pos:] - return pos - - # File window -- real work. - 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 - 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 - continuation = C_STRING - 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 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.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 - 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) - lastch = ch - p = p+1 - continue - - if ch in ")]}": - if stack: - del stack[-1] - lastch = ch - p = p+1 - 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. - lastch = ch - p = _match_stringre(str, p, q).end() - continue - - if ch == '#': - # consume comment and trailing newline - p = str.find('\n', p, q) + 1 - assert p > 0 - 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] - - # 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 diff --git a/Tools/idle/PyShell.py b/Tools/idle/PyShell.py deleted file mode 100644 index 2eaf93623b..0000000000 --- a/Tools/idle/PyShell.py +++ /dev/null @@ -1,794 +0,0 @@ -#! /usr/bin/env python - -import os -import sys -import string -import getopt -import re -import warnings -import types - -import linecache -from code import InteractiveInterpreter - -from Tkinter import * -import tkMessageBox - -from EditorWindow import EditorWindow, fixwordbreaks -from FileList import FileList -from ColorDelegator import ColorDelegator -from UndoDelegator import UndoDelegator -from OutputWindow import OutputWindow -from IdleConf import idleconf -import idlever - -# We need to patch linecache.checkcache, because we don't want it -# to throw away our <pyshell#...> entries. -# Rather than repeating its code here, we save those entries, -# then call the original function, and then restore the saved entries. -def linecache_checkcache(orig_checkcache=linecache.checkcache): - cache = linecache.cache - save = {} - for filename in cache.keys(): - if filename[:1] + filename[-1:] == '<>': - save[filename] = cache[filename] - orig_checkcache() - cache.update(save) -linecache.checkcache = linecache_checkcache - - -IDENTCHARS = string.ascii_letters + string.digits + "_" - - -# Note: <<newline-and-indent>> event is defined in AutoIndent.py - -#$ event <<plain-newline-and-indent>> -#$ win <Control-j> -#$ unix <Control-j> - -#$ event <<beginning-of-line>> -#$ win <Control-a> -#$ win <Home> -#$ unix <Control-a> -#$ unix <Home> - -#$ event <<history-next>> -#$ win <Alt-n> -#$ unix <Alt-n> - -#$ event <<history-previous>> -#$ win <Alt-p> -#$ unix <Alt-p> - -#$ event <<interrupt-execution>> -#$ win <Control-c> -#$ unix <Control-c> - -#$ event <<end-of-file>> -#$ win <Control-d> -#$ unix <Control-d> - -#$ event <<open-stack-viewer>> - -#$ event <<toggle-debugger>> - - -class PyShellEditorWindow(EditorWindow): - - # Regular text edit window when a shell is present - # XXX ought to merge with regular editor window - runnable = True # Shell not present, enable Import Module and Run Script - - def __init__(self, *args): - apply(EditorWindow.__init__, (self,) + args) - self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here) - self.text.bind("<<open-python-shell>>", self.flist.open_shell) - - rmenu_specs = [ - ("Set breakpoint here", "<<set-breakpoint-here>>"), - ] - - def set_breakpoint_here(self, event=None): - if not self.flist.pyshell or not self.flist.pyshell.interp.debugger: - self.text.bell() - return - self.flist.pyshell.interp.debugger.set_breakpoint_here(self) - - -class PyShellFileList(FileList): - - # File list when a shell is present - - EditorWindow = PyShellEditorWindow - - pyshell = None - - def open_shell(self, event=None): - if self.pyshell: - self.pyshell.wakeup() - else: - self.pyshell = PyShell(self) - self.pyshell.begin() - return self.pyshell - - -class ModifiedColorDelegator(ColorDelegator): - - # Colorizer for the shell window itself - - def recolorize_main(self): - self.tag_remove("TODO", "1.0", "iomark") - self.tag_add("SYNC", "1.0", "iomark") - ColorDelegator.recolorize_main(self) - - tagdefs = ColorDelegator.tagdefs.copy() - cconf = idleconf.getsection('Colors') - - tagdefs.update({ - "stdin": cconf.getcolor("stdin"), - "stdout": cconf.getcolor("stdout"), - "stderr": cconf.getcolor("stderr"), - "console": cconf.getcolor("console"), - "ERROR": cconf.getcolor("ERROR"), - None: cconf.getcolor("normal"), - }) - - -class ModifiedUndoDelegator(UndoDelegator): - - # 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 ModifiedInterpreter(InteractiveInterpreter): - - def __init__(self, tkconsole): - self.tkconsole = tkconsole - locals = sys.modules['__main__'].__dict__ - InteractiveInterpreter.__init__(self, locals=locals) - self.save_warnings_filters = None - - 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() - InteractiveInterpreter.showsyntaxerror(self, filename) - else: - self.runcode(code) - - def runsource(self, source): - # Extend base class to 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") - return - try: - 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 showsyntaxerror(self, filename=None): - # Extend base class to color the offending position - # (instead of printing it and pointing at it with a caret) - text = self.tkconsole.text - stuff = self.unpackerror() - if not stuff: - self.tkconsole.resetoutput() - InteractiveInterpreter.showsyntaxerror(self, filename) - return - 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)) - - def unpackerror(self): - type, value, tb = sys.exc_info() - ok = type is SyntaxError - if ok: - try: - msg, (dummy_filename, lineno, offset, line) = value - 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) - - def checklinecache(self): - c = linecache.cache - for key in c.keys(): - if key[:1] + key[-1:] != "<>": - del c[key] - - debugger = None - - def setdebugger(self, debugger): - self.debugger = debugger - - def getdebugger(self): - return self.debugger - - def runcode(self, code): - # Override base class method - 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 debugger: - debugger.run(code, self.locals) - else: - exec code in self.locals - except SystemExit: - if tkMessageBox.askyesno( - "Exit?", - "Do you want to exit altogether?", - default="yes", - master=self.tkconsole.text): - raise - else: - self.showtraceback() - if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): - self.tkconsole.open_stack_viewer() - except: - self.showtraceback() - if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): - self.tkconsole.open_stack_viewer() - - finally: - self.tkconsole.endexecuting() - - def write(self, s): - # Override base class write - self.tkconsole.console.write(s) - - -class PyShell(OutputWindow): - - shell_title = "Python Shell" - - # Override classes - ColorDelegator = ModifiedColorDelegator - UndoDelegator = ModifiedUndoDelegator - - # Override menu bar specs - menu_specs = PyShellEditorWindow.menu_specs[:] - menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug")) - - # New classes - from IdleHistory import History - - def __init__(self, flist=None): - self.interp = ModifiedInterpreter(self) - if flist is None: - root = Tk() - fixwordbreaks(root) - root.withdraw() - flist = PyShellFileList(root) - - OutputWindow.__init__(self, flist, None, None) - - import __builtin__ - __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D." - - self.auto = self.extensions["AutoIndent"] # Required extension - self.auto.config(usetabs=1, indentwidth=8, context_use_ps1=1) - - 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("<<open-python-shell>>", self.flist.open_shell) - text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer) - - self.save_stdout = sys.stdout - self.save_stderr = sys.stderr - self.save_stdin = sys.stdin - sys.stdout = PseudoFile(self, "stdout") - sys.stderr = PseudoFile(self, "stderr") - sys.stdin = self - self.console = PseudoFile(self, "console") - - self.history = self.History(self.text) - - reading = 0 - executing = 0 - canceled = 0 - endoffile = 0 - - 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() - self.resetoutput() - self.console.write("[DEBUG OFF]\n") - sys.ps1 = ">>> " - self.showprompt() - self.set_debugger_indicator() - - def open_debugger(self): - import Debugger - self.interp.setdebugger(Debugger.Debugger(self)) - sys.ps1 = "[DEBUG ON]\n>>> " - self.showprompt() - self.set_debugger_indicator() - - def beginexecuting(self): - # Helper for ModifiedInterpreter - self.resetoutput() - self.executing = 1 - ##self._cancel_check = self.cancel_check - ##sys.settrace(self._cancel_check) - - def endexecuting(self): - # Helper for ModifiedInterpreter - ##sys.settrace(None) - ##self._cancel_check = None - self.executing = 0 - self.canceled = 0 - - def close(self): - # Extend base class method - if self.executing: - # XXX Need to ask a question here - if not tkMessageBox.askokcancel( - "Kill?", - "The program is still running; do you want to kill it?", - default="ok", - master=self.text): - return "cancel" - self.canceled = 1 - if self.reading: - self.top.quit() - return "cancel" - return OutputWindow.close(self) - - def _close(self): - self.close_debugger() - # 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.auto = None - self.flist.pyshell = None - self.history = None - OutputWindow._close(self) # Really EditorWindow._close - - def ispythonsource(self, filename): - # Override this so EditorWindow never removes the colorizer - return True - - def short_title(self): - return self.shell_title - - COPYRIGHT = \ - 'Type "copyright", "credits" or "license" for more information.' - - def begin(self): - self.resetoutput() - self.write("Python %s on %s\n%s\nIDLE %s -- press F1 for help\n" % - (sys.version, sys.platform, self.COPYRIGHT, - idlever.IDLE_VERSION)) - try: - sys.ps1 - except AttributeError: - sys.ps1 = ">>> " - self.showprompt() - import Tkinter - Tkinter._default_root = None - - def interact(self): - self.begin() - self.top.mainloop() - - def readline(self): - save = self.reading - try: - self.reading = 1 - self.top.mainloop() - finally: - self.reading = save - line = self.text.get("iomark", "end-1c") - self.resetoutput() - if self.canceled: - self.canceled = 0 - raise KeyboardInterrupt - if self.endoffile: - self.endoffile = 0 - return "" - return line - - def isatty(self): - return True - - def cancel_callback(self, event): - 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.write("KeyboardInterrupt\n") - self.showprompt() - return "break" - self.endoffile = 0 - self.canceled = 1 - if self.reading: - self.top.quit() - 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: -## if not tkMessageBox.askokcancel( -## "Exit?", -## "Are you sure you want to exit?", -## default="ok", master=self.text): -## return "break" - 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.auto.auto_indent(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) - 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])) - 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])) - return "break" - # No stdin mark -- just get the current line - self.recall(self.text.get("insert linestart", "insert lineend")) - return "break" - # 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.auto.auto_indent(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.auto.auto_indent(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): - if self.history: - self.history.recall(s) - - 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) - if not more: - self.showprompt() - - def cancel_check(self, frame, what, args, - dooneevent=tkinter.dooneevent, - dontwait=tkinter.DONT_WAIT): - # Hack -- use the debugger hooks to be able to handle events - # and interrupt execution at any time. - # This slows execution down quite a bit, so you may want to - # disable this (by not calling settrace() in runcode() above) - # for full-bore (uninterruptable) speed. - # XXX This should become a user option. - if self.canceled: - return - dooneevent(dontwait) - if self.canceled: - self.canceled = 0 - raise KeyboardInterrupt - return self._cancel_check - - def open_stack_viewer(self, event=None): - 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 showprompt(self): - self.resetoutput() - try: - s = str(sys.ps1) - except: - s = "" - self.console.write(s) - self.text.mark_set("insert", "end-1c") - - 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") - sys.stdout.softspace = 0 - - def write(self, s, tags=()): - self.text.mark_gravity("iomark", "right") - OutputWindow.write(self, s, tags, "iomark") - self.text.mark_gravity("iomark", "left") - if self.canceled: - self.canceled = 0 - raise KeyboardInterrupt - -class PseudoFile: - - def __init__(self, shell, tags): - self.shell = shell - self.tags = tags - - 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.py [-c command] [-d] [-e] [-s] [-t title] [arg] ... - --c command run this command --d enable debugger --e edit mode; arguments are files to be edited --s run $IDLESTARTUP or $PYTHONSTARTUP before anything else --t title set title of shell window - -When neither -c nor -e is used, and there are arguments, and the first -argument is not '-', the first argument is run as a script. Remaining -arguments are arguments to the script or to the command run by -c. -""" - -def main(): - cmd = None - edit = 0 - debug = 0 - startup = 0 - - try: - opts, args = getopt.getopt(sys.argv[1:], "c:deist:") - 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 - if o == '-d': - debug = 1 - if o == '-e': - edit = 1 - if o == '-s': - startup = 1 - if o == '-t': - PyShell.shell_title = a - - for i in range(len(sys.path)): - sys.path[i] = os.path.abspath(sys.path[i]) - - pathx = [] - if edit: - for filename in args: - pathx.append(os.path.dirname(filename)) - elif args and args[0] != "-": - pathx.append(os.path.dirname(args[0])) - else: - pathx.append(os.curdir) - for dir in pathx: - dir = os.path.abspath(dir) - if not dir in sys.path: - sys.path.insert(0, dir) - - global flist, root - root = Tk(className="Idle") - fixwordbreaks(root) - root.withdraw() - flist = PyShellFileList(root) - - if edit: - for filename in args: - flist.open(filename) - else: - if cmd: - sys.argv = ["-c"] + args - else: - sys.argv = args or [""] - - - shell = PyShell(flist) - interp = shell.interp - flist.pyshell = shell - - if startup: - filename = os.environ.get("IDLESTARTUP") or \ - os.environ.get("PYTHONSTARTUP") - if filename and os.path.isfile(filename): - interp.execfile(filename) - - if debug: - shell.open_debugger() - if cmd: - interp.execsource(cmd) - elif not edit and args and args[0] != "-": - interp.execfile(args[0]) - - shell.begin() - root.mainloop() - root.destroy() - - -if __name__ == "__main__": - main() diff --git a/Tools/idle/README.txt b/Tools/idle/README.txt deleted file mode 100644 index 782f6a7b76..0000000000 --- a/Tools/idle/README.txt +++ /dev/null @@ -1,53 +0,0 @@ -IDLE 0.5 - February 2000 ------------------------- - -This is an early release of IDLE, my own attempt at a Tkinter-based -IDE for Python. - -For news about this release, see the file NEWS.txt. (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 or later, so it is currently only usable -with a Python 1.5.2 (or later) 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). - -FEEDBACK - -For feedback, please use the Python Bugs List -(http://www.python.org/search/search_bugs.html). - ---Guido van Rossum (home page: http://www.python.org/~guido/) diff --git a/Tools/idle/RemoteInterp.py b/Tools/idle/RemoteInterp.py deleted file mode 100644 index e6f767102e..0000000000 --- a/Tools/idle/RemoteInterp.py +++ /dev/null @@ -1,341 +0,0 @@ -import select -import socket -import struct -import sys -import types - -VERBOSE = None - -class SocketProtocol: - """A simple protocol for sending strings across a socket""" - BUF_SIZE = 8192 - - def __init__(self, sock): - self.sock = sock - self._buffer = '' - self._closed = 0 - - def close(self): - self._closed = 1 - self.sock.close() - - def send(self, buf): - """Encode buf and write it on the socket""" - if VERBOSE: - VERBOSE.write('send %d:%s\n' % (len(buf), `buf`)) - self.sock.send('%d:%s' % (len(buf), buf)) - - def receive(self, timeout=0): - """Get next complete string from socket or return None - - Raise EOFError on EOF - """ - buf = self._read_from_buffer() - if buf is not None: - return buf - recvbuf = self._read_from_socket(timeout) - if recvbuf is None: - return None - if recvbuf == '' and self._buffer == '': - raise EOFError - if VERBOSE: - VERBOSE.write('recv %s\n' % `recvbuf`) - self._buffer = self._buffer + recvbuf - r = self._read_from_buffer() - return r - - def _read_from_socket(self, timeout): - """Does not block""" - if self._closed: - return '' - if timeout is not None: - r, w, x = select.select([self.sock], [], [], timeout) - if timeout is None or r: - return self.sock.recv(self.BUF_SIZE) - else: - return None - - def _read_from_buffer(self): - buf = self._buffer - i = buf.find(':') - if i == -1: - return None - buflen = int(buf[:i]) - enclen = i + 1 + buflen - if len(buf) >= enclen: - s = buf[i+1:enclen] - self._buffer = buf[enclen:] - return s - else: - self._buffer = buf - return None - -# helpers for registerHandler method below - -def get_methods(obj): - methods = [] - for name in dir(obj): - attr = getattr(obj, name) - if callable(attr): - methods.append(name) - if type(obj) == types.InstanceType: - methods = methods + get_methods(obj.__class__) - if type(obj) == types.ClassType: - for super in obj.__bases__: - methods = methods + get_methods(super) - return methods - -class CommandProtocol: - def __init__(self, sockp): - self.sockp = sockp - self.seqno = 0 - self.handlers = {} - - def close(self): - self.sockp.close() - self.handlers.clear() - - def registerHandler(self, handler): - """A Handler is an object with handle_XXX methods""" - for methname in get_methods(handler): - if methname[:7] == "handle_": - name = methname[7:] - self.handlers[name] = getattr(handler, methname) - - def send(self, cmd, arg='', seqno=None): - if arg: - msg = "%s %s" % (cmd, arg) - else: - msg = cmd - if seqno is None: - seqno = self.get_seqno() - msgbuf = self.encode_seqno(seqno) + msg - self.sockp.send(msgbuf) - if cmd == "reply": - return - reply = self.sockp.receive(timeout=None) - r_cmd, r_arg, r_seqno = self._decode_msg(reply) - assert r_seqno == seqno and r_cmd == "reply", "bad reply" - return r_arg - - def _decode_msg(self, msg): - seqno = self.decode_seqno(msg[:self.SEQNO_ENC_LEN]) - msg = msg[self.SEQNO_ENC_LEN:] - parts = msg.split(" ", 2) - if len(parts) == 1: - cmd = msg - arg = '' - else: - cmd = parts[0] - arg = parts[1] - return cmd, arg, seqno - - def dispatch(self): - msg = self.sockp.receive() - if msg is None: - return - cmd, arg, seqno = self._decode_msg(msg) - self._current_reply = seqno - h = self.handlers.get(cmd, self.default_handler) - try: - r = h(arg) - except TypeError, msg: - raise TypeError, "handle_%s: %s" % (cmd, msg) - if self._current_reply is None: - if r is not None: - sys.stderr.write("ignoring %s return value type %s\n" % \ - (cmd, type(r).__name__)) - return - if r is None: - r = '' - if type(r) != types.StringType: - raise ValueError, "invalid return type for %s" % cmd - self.send("reply", r, seqno=seqno) - - def reply(self, arg=''): - """Send a reply immediately - - otherwise reply will be sent when handler returns - """ - self.send("reply", arg, self._current_reply) - self._current_reply = None - - def default_handler(self, arg): - sys.stderr.write("WARNING: unhandled message %s\n" % arg) - return '' - - SEQNO_ENC_LEN = 4 - - def get_seqno(self): - seqno = self.seqno - self.seqno = seqno + 1 - return seqno - - def encode_seqno(self, seqno): - return struct.pack("I", seqno) - - def decode_seqno(self, buf): - return struct.unpack("I", buf)[0] - - -class StdioRedirector: - """Redirect sys.std{in,out,err} to a set of file-like objects""" - - def __init__(self, stdin, stdout, stderr): - self.stdin = stdin - self.stdout = stdout - self.stderr = stderr - - def redirect(self): - self.save() - sys.stdin = self.stdin - sys.stdout = self.stdout - sys.stderr = self.stderr - - def save(self): - self._stdin = sys.stdin - self._stdout = sys.stdout - self._stderr = sys.stderr - - def restore(self): - sys.stdin = self._stdin - sys.stdout = self._stdout - sys.stderr = self._stderr - -class IOWrapper: - """Send output from a file-like object across a SocketProtocol - - XXX Should this be more tightly integrated with the CommandProtocol? - """ - - def __init__(self, name, cmdp): - self.name = name - self.cmdp = cmdp - self.buffer = [] - -class InputWrapper(IOWrapper): - def write(self, buf): - # XXX what should this do on Windows? - raise IOError, (9, '[Errno 9] Bad file descriptor') - - def read(self, arg=None): - if arg is not None: - if arg <= 0: - return '' - else: - arg = 0 - return self.cmdp.send(self.name, "read,%s" % arg) - - def readline(self): - return self.cmdp.send(self.name, "readline") - -class OutputWrapper(IOWrapper): - def write(self, buf): - self.cmdp.send(self.name, buf) - - def read(self, arg=None): - return '' - -class RemoteInterp: - def __init__(self, sock): - self._sock = SocketProtocol(sock) - self._cmd = CommandProtocol(self._sock) - self._cmd.registerHandler(self) - - def run(self): - try: - while 1: - self._cmd.dispatch() - except EOFError: - pass - - def handle_execfile(self, arg): - self._cmd.reply() - io = StdioRedirector(InputWrapper("stdin", self._cmd), - OutputWrapper("stdout", self._cmd), - OutputWrapper("stderr", self._cmd)) - io.redirect() - execfile(arg, {'__name__':'__main__'}) - io.restore() - self._cmd.send("terminated") - - def handle_quit(self, arg): - self._cmd.reply() - self._cmd.close() - -def startRemoteInterp(id): - import os - # UNIX domain sockets are simpler for starters - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.bind("/var/tmp/ri.%s" % id) - try: - sock.listen(1) - cli, addr = sock.accept() - rinterp = RemoteInterp(cli) - rinterp.run() - finally: - os.unlink("/var/tmp/ri.%s" % id) - -class RIClient: - """Client of the remote interpreter""" - def __init__(self, sock): - self._sock = SocketProtocol(sock) - self._cmd = CommandProtocol(self._sock) - self._cmd.registerHandler(self) - - def execfile(self, file): - self._cmd.send("execfile", file) - - def run(self): - try: - while 1: - self._cmd.dispatch() - except EOFError: - pass - - def handle_stdout(self, buf): - sys.stdout.write(buf) -## sys.stdout.flush() - - def handle_stderr(self, buf): - sys.stderr.write(buf) - - def handle_stdin(self, arg): - if arg == "readline": - return sys.stdin.readline() - i = arg.find(",") + 1 - bytes = int(arg[i:]) - if bytes == 0: - return sys.stdin.read() - else: - return sys.stdin.read(bytes) - - def handle_terminated(self, arg): - self._cmd.reply() - self._cmd.send("quit") - self._cmd.close() - -def riExec(id, file): - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.connect("/var/tmp/ri.%s" % id) - cli = RIClient(sock) - cli.execfile(file) - cli.run() - -if __name__ == "__main__": - import getopt - - SERVER = 1 - opts, args = getopt.getopt(sys.argv[1:], 'cv') - for o, v in opts: - if o == '-c': - SERVER = 0 - elif o == '-v': - VERBOSE = sys.stderr - id = args[0] - - if SERVER: - startRemoteInterp(id) - else: - file = args[1] - riExec(id, file) diff --git a/Tools/idle/ReplaceDialog.py b/Tools/idle/ReplaceDialog.py deleted file mode 100644 index c8eb1c8c45..0000000000 --- a/Tools/idle/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/Tools/idle/ScriptBinding.py b/Tools/idle/ScriptBinding.py deleted file mode 100644 index 3e1279ccbc..0000000000 --- a/Tools/idle/ScriptBinding.py +++ /dev/null @@ -1,175 +0,0 @@ -"""Extension to execute code outside the Python shell window. - -This adds the following commands (to the Edit menu, until there's a -separate Python menu): - -- Check module (Alt-F5) does a full syntax check of the current module. -It also runs the tabnanny to catch any inconsistent tabs. - -- Import module (F5) is equivalent to either import or reload of the -current module. The window must have been saved previously. The -module is added to sys.modules, and is also added to the __main__ -namespace. Output goes to the shell window. - -- Run module (Control-F5) does the same but executes the module's -code in the __main__ namespace. - -""" - -import sys -import os -import imp -import tkMessageBox - -indent_message = """Error: Inconsistent indentation detected! - -This means that either: - -(1) your indentation is outright incorrect (easy to fix), or - -(2) your indentation mixes tabs and spaces in a way that depends on \ -how many spaces a tab is worth. - -To fix case 2, change all tabs to spaces by using Select All followed \ -by Untabify Region (both in the Edit menu).""" - -class ScriptBinding: - - keydefs = { - '<<check-module>>': ['<Alt-F5>', '<Meta-F5>'], - '<<import-module>>': ['<F5>'], - '<<run-script>>': ['<Control-F5>'], - } - - menudefs = [ - ('edit', [None, - ('Check module', '<<check-module>>'), - ('Import module', '<<import-module>>'), - ('Run script', '<<run-script>>'), - ] - ), - ] - - def __init__(self, editwin): - if not editwin.runnable: - self.menudefs = [] - self.keydefs = {} - self.editwin = editwin - # Provide instance variables referenced by Debugger - # XXX This should be done differently - self.flist = self.editwin.flist - self.root = self.flist.root - - def check_module_event(self, event): - filename = self.getfilename() - if not filename: - return - if not self.tabnanny(filename): - return - if not self.checksyntax(filename): - return - - def tabnanny(self, filename): - import tabnanny - import tokenize - f = open(filename, 'r') - try: - tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) - except tokenize.TokenError, msg: - self.errorbox("Token error", - "Token error:\n%s" % str(msg)) - return 0 - 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 0 - return 1 - - def checksyntax(self, filename): - f = open(filename, 'r') - source = f.read() - f.close() - if '\r' in source: - import re - source = re.sub(r"\r\n", "\n", source) - if source and source[-1] != '\n': - source = source + '\n' - try: - 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 - except: - lineno = None - msg = "*** " + str(err) - if lineno: - self.editwin.gotoline(lineno) - self.errorbox("Syntax error", - "There's an error in your program:\n" + msg) - return 1 - - def import_module_event(self, event): - filename = self.getfilename() - if not filename: - return - - modname, ext = os.path.splitext(os.path.basename(filename)) - if sys.modules.has_key(modname): - mod = sys.modules[modname] - else: - mod = imp.new_module(modname) - sys.modules[modname] = mod - mod.__file__ = filename - setattr(sys.modules['__main__'], modname, mod) - - dir = os.path.dirname(filename) - dir = os.path.normpath(os.path.abspath(dir)) - if dir not in sys.path: - sys.path.insert(0, dir) - - flist = self.editwin.flist - shell = flist.open_shell() - interp = shell.interp - interp.runcode("reload(%s)" % modname) - - def run_script_event(self, event): - filename = self.getfilename() - if not filename: - return - - flist = self.editwin.flist - shell = flist.open_shell() - interp = shell.interp - if (not sys.argv or - os.path.basename(sys.argv[0]) != os.path.basename(filename)): - # XXX Too often this discards arguments the user just set... - sys.argv = [filename] - interp.execfile(filename) - - def getfilename(self): - # Logic to make sure we have a saved filename - # XXX Better logic would offer to save! - if not self.editwin.get_saved(): - name = (self.editwin.short_title() or - self.editwin.long_title() or - "Untitled") - self.errorbox("Not saved", - "The buffer for %s is not saved.\n" % name + - "Please save it first!") - self.editwin.text.focus_set() - return - filename = self.editwin.io.filename - if not filename: - self.errorbox("No file name", - "This window has no file name") - return - return filename - - 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/Tools/idle/ScrolledList.py b/Tools/idle/ScrolledList.py deleted file mode 100644 index 9211936577..0000000000 --- a/Tools/idle/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/Tools/idle/SearchBinding.py b/Tools/idle/SearchBinding.py deleted file mode 100644 index 5943e3baec..0000000000 --- a/Tools/idle/SearchBinding.py +++ /dev/null @@ -1,97 +0,0 @@ -import tkSimpleDialog - -###$ event <<find>> -###$ win <Control-f> -###$ unix <Control-u><Control-u><Control-s> - -###$ event <<find-again>> -###$ win <Control-g> -###$ win <F3> -###$ unix <Control-u><Control-s> - -###$ event <<find-selection>> -###$ win <Control-F3> -###$ unix <Control-s> - -###$ event <<find-in-files>> -###$ win <Alt-F3> - -###$ event <<replace>> -###$ win <Control-h> - -###$ event <<goto-line>> -###$ win <Alt-g> -###$ unix <Alt-g> - -class SearchBinding: - - windows_keydefs = { - '<<find-again>>': ['<Control-g>', '<F3>'], - '<<find-in-files>>': ['<Alt-F3>'], - '<<find-selection>>': ['<Control-F3>'], - '<<find>>': ['<Control-f>'], - '<<replace>>': ['<Control-h>'], - '<<goto-line>>': ['<Alt-g>'], - } - - unix_keydefs = { - '<<find-again>>': ['<Control-u><Control-s>'], - '<<find-in-files>>': ['<Alt-s>', '<Meta-s>'], - '<<find-selection>>': ['<Control-s>'], - '<<find>>': ['<Control-u><Control-u><Control-s>'], - '<<replace>>': ['<Control-r>'], - '<<goto-line>>': ['<Alt-g>', '<Meta-g>'], - } - - menudefs = [ - ('edit', [ - 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>>'), - ]), - ] - - def __init__(self, editwin): - self.editwin = editwin - - def find_event(self, event): - import SearchDialog - SearchDialog.find(self.editwin.text) - return "break" - - def find_again_event(self, event): - import SearchDialog - SearchDialog.find_again(self.editwin.text) - return "break" - - def find_selection_event(self, event): - import SearchDialog - SearchDialog.find_selection(self.editwin.text) - return "break" - - def find_in_files_event(self, event): - import GrepDialog - GrepDialog.grep(self.editwin.text, self.editwin.io, self.editwin.flist) - return "break" - - def replace_event(self, event): - import ReplaceDialog - ReplaceDialog.replace(self.editwin.text) - return "break" - - def goto_line_event(self, event): - text = self.editwin.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") diff --git a/Tools/idle/SearchDialog.py b/Tools/idle/SearchDialog.py deleted file mode 100644 index 8d275c4437..0000000000 --- a/Tools/idle/SearchDialog.py +++ /dev/null @@ -1,67 +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): - return _setup(text).open(text) - -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/Tools/idle/SearchDialogBase.py b/Tools/idle/SearchDialogBase.py deleted file mode 100644 index 9a88e25f56..0000000000 --- a/Tools/idle/SearchDialogBase.py +++ /dev/null @@ -1,128 +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): - self.text = text - if not self.top: - self.create_widgets() - else: - self.top.deiconify() - self.top.tkraise() - 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, weight=0) - self.top.grid_columnconfigure(1, 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="w") - e = Entry(self.top, textvariable=var, exportselection=0) - e.grid(row=self.row, column=1, sticky="we") - self.row = self.row + 1 - return e - - def make_frame(self): - f = Frame(self.top) - f.grid(row=self.row, column=0, columnspan=2, sticky="we") - self.row = self.row + 1 - return f - - def make_button(self, label, command, isdef=0, side="left"): - b = Button(self.buttonframe, - text=label, command=command, - default=isdef and "active" or "normal") - b.pack(side=side) - return b - - def create_entries(self): - self.ent = self.make_entry("Find:", self.engine.patvar) - - def create_option_buttons(self): - f = self.make_frame() - - 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() - - 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): - f = self.buttonframe = self.make_frame() - b = self.make_button("close", self.close, side="right") - b.lower() diff --git a/Tools/idle/SearchEngine.py b/Tools/idle/SearchEngine.py deleted file mode 100644 index cc40a00c50..0000000000 --- a/Tools/idle/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/Tools/idle/Separator.py b/Tools/idle/Separator.py deleted file mode 100644 index 7145559c7b..0000000000 --- a/Tools/idle/Separator.py +++ /dev/null @@ -1,92 +0,0 @@ -from Tkinter import * - -class Separator: - - def __init__(self, master, orient, min=10, thickness=5, bg=None): - self.min = max(1, min) - self.thickness = max(1, thickness) - if orient in ("h", "horizontal"): - self.side = "left" - self.dim = "width" - self.dir = "x" - self.cursor = "sb_h_double_arrow" - elif orient in ("v", "vertical"): - self.side = "top" - self.dim = "height" - self.dir = "y" - self.cursor = "sb_v_double_arrow" - else: - raise ValueError, "Separator: orient should be h or v" - self.winfo_dim = "winfo_" + self.dim - self.master = master = Frame(master) - master.pack(expand=1, fill="both") - self.f1 = Frame(master) - self.f1.pack(expand=1, fill="both", side=self.side) - self.div = Frame(master, cursor=self.cursor) - self.div[self.dim] = self.thickness - self.div.pack(fill="both", side=self.side) - self.f2 = Frame(master) - self.f2.pack(expand=1, fill="both", side=self.side) - self.div.bind("<ButtonPress-1>", self.divider_press) - if bg: - ##self.f1["bg"] = bg - ##self.f2["bg"] = bg - self.div["bg"] = bg - - def parts(self): - return self.f1, self.f2 - - def divider_press(self, event): - self.press_event = event - self.f1.pack_propagate(0) - self.f2.pack_propagate(0) - for f in self.f1, self.f2: - for dim in "width", "height": - f[dim] = getattr(f, "winfo_"+dim)() - self.div.bind("<Motion>", self.div_motion) - self.div.bind("<ButtonRelease-1>", self.div_release) - self.div.grab_set() - - def div_motion(self, event): - delta = getattr(event, self.dir) - getattr(self.press_event, self.dir) - if delta: - dim1 = getattr(self.f1, self.winfo_dim)() - dim2 = getattr(self.f2, self.winfo_dim)() - delta = max(delta, self.min-dim1) - delta = min(delta, dim2-self.min) - dim1 = dim1 + delta - dim2 = dim2 - delta - self.f1[self.dim] = dim1 - self.f2[self.dim] = dim2 - - def div_release(self, event): - self.div_motion(event) - self.div.unbind("<Motion>") - self.div.grab_release() - -class VSeparator(Separator): - - def __init__(self, master, min=10, thickness=5, bg=None): - Separator.__init__(self, master, "v", min, thickness, bg) - -class HSeparator(Separator): - - def __init__(self, master, min=10, thickness=5, bg=None): - Separator.__init__(self, master, "h", min, thickness, bg) - -def main(): - root = Tk() - tlist = [] - outer = HSeparator(root, bg="red") - for part in outer.parts(): - inner = VSeparator(part, bg="blue") - for f in inner.parts(): - t = Text(f, width=40, height=10, borderwidth=0) - t.pack(fill="both", expand=1) - tlist.append(t) - tlist[0].insert("1.0", "Make your own Mondrian!") - tlist[1].insert("1.0", "Move the colored dividers...") - root.mainloop() - -if __name__ == '__main__': - main() diff --git a/Tools/idle/StackViewer.py b/Tools/idle/StackViewer.py deleted file mode 100644 index 7f57c0d385..0000000000 --- a/Tools/idle/StackViewer.py +++ /dev/null @@ -1,146 +0,0 @@ -import os -import sys -import linecache - -from TreeWidget import TreeNode, TreeItem, ScrolledCanvas -from ObjectBrowser import ObjectTreeItem, make_objecttreeitem -from OldStackViewer import StackViewer, NamespaceViewer - -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 = get_stack(tb) - self.text = get_exception() - - 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) -## if i == index: -## item = "> " + item - 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 get_stack(t=None, f=None): - if t is None: - t = sys.last_traceback - stack = [] - if t and t.tb_frame is f: - t = t.tb_next - while f is not None: - stack.append((f, f.f_lineno)) - if f is self.botframe: - break - f = f.f_back - stack.reverse() - while t is not None: - stack.append((t.tb_frame, t.tb_lineno)) - t = t.tb_next - return stack - -def get_exception(type=None, value=None): - if type is None: - 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 _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/Tools/idle/TODO.txt b/Tools/idle/TODO.txt deleted file mode 100644 index b5ec7e81cb..0000000000 --- a/Tools/idle/TODO.txt +++ /dev/null @@ -1,211 +0,0 @@ - -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) - - 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 -- 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 -- 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?) -- 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: - -- when there's a selection, left/right arrow should go to either - end of the selection -- ^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 - -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, - 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? - - 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) - -- Config files still editable outside the preferences dialog. -(Randall Hopper) - -- 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) - -- 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) - -- GUI form designer to kick VB's butt. (Robert Geiger) - -- Printing! Possibly via generation of PDF files which the user must -then send to the printer separately. (Dinu Gherman) diff --git a/Tools/idle/ToolTip.py b/Tools/idle/ToolTip.py deleted file mode 100644 index 77d18c2f56..0000000000 --- a/Tools/idle/ToolTip.py +++ /dev/null @@ -1,86 +0,0 @@ -# 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() # not in idle - -main() diff --git a/Tools/idle/TreeWidget.py b/Tools/idle/TreeWidget.py deleted file mode 100644 index d7132648ac..0000000000 --- a/Tools/idle/TreeWidget.py +++ /dev/null @@ -1,476 +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 - -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 (%s)" % `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 = 0 - 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 = 1 - self.canvas.delete(self.image_id) - self.drawicon() - self.drawtext() - - def deselect(self, event=None): - if not self.selected: - return - self.selected = 0 - 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) - if self.selected: - self.label.configure(fg="white", bg="darkblue") - else: - self.label.configure(fg="black", bg="white") - 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 = apply(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-F2>", 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/Tools/idle/UndoDelegator.py b/Tools/idle/UndoDelegator.py deleted file mode 100644 index 54b0851081..0000000000 --- a/Tools/idle/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 = 0 - 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=1): - 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 = 1 - 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 = 0 - 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 = 0 - 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 + `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 0 - if self.index2 != cmd.index1: - return 0 - if self.tags != cmd.tags: - return 0 - if len(cmd.chars) != 1: - return 0 - if self.chars and \ - self.classify(self.chars[-1]) != self.classify(cmd.chars): - return 0 - self.index2 = cmd.index2 - self.chars = self.chars + cmd.chars - return 1 - - 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(" " + `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/Tools/idle/WidgetRedirector.py b/Tools/idle/WidgetRedirector.py deleted file mode 100644 index b49ccf1c59..0000000000 --- a/Tools/idle/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 apply(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(%s, %s)" % (`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 - apply(orig_insert, args) - orig_insert = redir.register("insert", my_insert) - root.mainloop() - -if __name__ == "__main__": - main() diff --git a/Tools/idle/WindowList.py b/Tools/idle/WindowList.py deleted file mode 100644 index 7e05a57c03..0000000000 --- a/Tools/idle/WindowList.py +++ /dev/null @@ -1,85 +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: - if title == "Python Shell": - # Hack -- until we have a better way to this - continue - 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) - - def destroy(self): - registry.delete(self) - Toplevel.destroy(self) - - def get_title(self): - # Subclass can override - return self.wm_title() - - def wakeup(self): - try: - if self.wm_state() == "iconic": - self.wm_deiconify() - else: - self.tkraise() - self.focus_set() - except TclError: - # This can happen when the window menu was torn off. - # Simply ignore it. - pass diff --git a/Tools/idle/ZoomHeight.py b/Tools/idle/ZoomHeight.py deleted file mode 100644 index ecc306a733..0000000000 --- a/Tools/idle/ZoomHeight.py +++ /dev/null @@ -1,46 +0,0 @@ -# Sample extension: zoom a window to maximum height - -import re -import sys - -class ZoomHeight: - - menudefs = [ - ('windows', [ - ('_Zoom Height', '<<zoom-height>>'), - ]) - ] - - windows_keydefs = { - '<<zoom-height>>': ['<Alt-F2>'], - } - unix_keydefs = { - '<<zoom-height>>': ['<Control-x><Control-z>'], - } - - 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 - else: - newy = 24 - newheight = newheight - 96 - if height >= newheight: - newgeom = "" - else: - newgeom = "%dx%d+%d+%d" % (width, newheight, x, newy) - top.wm_geometry(newgeom) diff --git a/Tools/idle/__init__.py b/Tools/idle/__init__.py deleted file mode 100644 index 4c5b567c3a..0000000000 --- a/Tools/idle/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Dummy file to make this a potential package. diff --git a/Tools/idle/config-mac.txt b/Tools/idle/config-mac.txt deleted file mode 100644 index ee36e13fe7..0000000000 --- a/Tools/idle/config-mac.txt +++ /dev/null @@ -1,3 +0,0 @@ -[EditorWindow] -font-name= monaco -font-size= 9 diff --git a/Tools/idle/config-unix.txt b/Tools/idle/config-unix.txt deleted file mode 100644 index 782965f7d1..0000000000 --- a/Tools/idle/config-unix.txt +++ /dev/null @@ -1,4 +0,0 @@ -[EditorWindow] -font-name= courier -font-size= 10 -print-command=lpr %s diff --git a/Tools/idle/config-win.txt b/Tools/idle/config-win.txt deleted file mode 100644 index aeb6ab96c4..0000000000 --- a/Tools/idle/config-win.txt +++ /dev/null @@ -1,4 +0,0 @@ -[EditorWindow] -font-name: courier new -font-size: 10 -print-command=start /min notepad /p %s diff --git a/Tools/idle/config.txt b/Tools/idle/config.txt deleted file mode 100644 index 6f98a3e8e4..0000000000 --- a/Tools/idle/config.txt +++ /dev/null @@ -1,64 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file. When IDLE starts, it will look in -# the following four files in order: -# config.txt the default config file -# config-[win/unix/mac].txt the generic platform config file -# config-[sys.platform].txt the specific platform config file -# ~/.idle the user config file -# XXX what about Windows? -# -# The last definition of each option is used. For example, you can -# override the default window size (80x24) by defining width and -# height options in the EditorWindow section of your ~/.idle file -# -# IDLE extensions can be enabled and disabled by adding them to one of -# the config files. To enable an extension, create a section with the -# same name as the extension, e.g. the [ParenMatch] section below. To -# disable an extension, either remove the section or add the 'enable' -# option with the value 0. - -[EditorWindow] -width= 80 -height= 24 -# fonts defined in config-[win/unix].txt - -[Colors] -normal-foreground= black -normal-background= white -# These color types are not explicitly defined= sync, todo, stdin -keyword-foreground= #ff7700 -comment-foreground= #dd0000 -string-foreground= #00aa00 -definition-foreground= #0000ff -hilite-foreground= #000068 -hilite-background= #006868 -break-foreground= #ff7777 -hit-foreground= #ffffff -hit-background= #000000 -stdout-foreground= blue -stderr-foreground= red -console-foreground= #770000 -error-background= #ff7777 -cursor-background= black - -[SearchBinding] - -[AutoIndent] - -[AutoExpand] - -[FormatParagraph] - -[ZoomHeight] - -[ScriptBinding] - -[CallTips] - -[ParenMatch] -enable= 0 -style= expression -flash-delay= 500 -bell= 1 -hilite-foreground= black -hilite-background= #43cd80 diff --git a/Tools/idle/eventparse.py b/Tools/idle/eventparse.py deleted file mode 100644 index f253b2a984..0000000000 --- a/Tools/idle/eventparse.py +++ /dev/null @@ -1,89 +0,0 @@ -#! /usr/bin/env python - -"""Parse event definitions out of comments in source files.""" - -import sys -import glob -import fileinput -import pprint - -def main(): - hits = [] - sublist = [] - args = sys.argv[1:] - if not args: - args = filter(lambda s: 'A' <= s[0] <= 'Z', glob.glob("*.py")) - if not args: - print "No arguments, no [A-Z]*.py files." - return 1 - for line in fileinput.input(args): - if line[:2] == '#$': - if not sublist: - sublist.append('file %s' % fileinput.filename()) - sublist.append('line %d' % fileinput.lineno()) - sublist.append(line[2:-1].strip()) - else: - if sublist: - hits.append(sublist) - sublist = [] - if sublist: - hits.append(sublist) - sublist = [] - dd = {} - for sublist in hits: - d = {} - for line in sublist: - words = line.split(None, 1) - if len(words) != 2: - continue - tag = words[0] - l = d.get(tag, []) - l.append(words[1]) - d[tag] = l - if d.has_key('event'): - keys = d['event'] - if len(keys) != 1: - print "Multiple event keys in", d - print 'File "%s", line %d' % (d['file'], d['line']) - key = keys[0] - if dd.has_key(key): - print "Duplicate event in", d - print 'File "%s", line %d' % (d['file'], d['line']) - return - dd[key] = d - else: - print "No event key in", d - print 'File "%s", line %d' % (d['file'], d['line']) - winevents = getevents(dd, "win") - unixevents = getevents(dd, "unix") - save = sys.stdout - f = open("keydefs.py", "w") - try: - sys.stdout = f - print "windows_keydefs = \\" - pprint.pprint(winevents) - print - print "unix_keydefs = \\" - pprint.pprint(unixevents) - finally: - sys.stdout = save - f.close() - -def getevents(dd, key): - res = {} - events = dd.keys() - events.sort() - for e in events: - d = dd[e] - if d.has_key(key) or d.has_key("all"): - list = [] - for x in d.get(key, []) + d.get("all", []): - list.append(x) - if key == "unix" and x[:5] == "<Alt-": - x = "<Meta-" + x[5:] - list.append(x) - res[e] = list - return res - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Tools/idle/extend.txt b/Tools/idle/extend.txt deleted file mode 100644 index a1756f0dbe..0000000000 --- a/Tools/idle/extend.txt +++ /dev/null @@ -1,120 +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.txt; see below for details. - -An IDLE extension is defined by a class. Methods of the class define -actions that are invoked by those 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 bind key events. Rather, it must define -one or more virtual events, e.g. <<zoom-height>>, and corresponding -methods, e.g. zoom_height_event(), and have one or more class (or instance) -variables that define mappings between virtual events and key sequences, -e.g. <Alt-F2>. When the extension is loaded, these key sequences will -be bound to the corresponding virtual events, and the virtual events -will be bound to the corresponding methods. (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.) - -The following class or instance variables are used to define key -bindings for virtual events: - - keydefs for all platforms - mac_keydefs for Macintosh - windows_keydefs for Windows - unix_keydefs for Unix (and other platforms) - -Each of these variables, if it exists, must be a dictionary whose -keys are virtual events, and whose values are lists of key sequences. - -An extension can define menu entries in a similar fashion. This is done -with a class or instance variable named menudefs; it should be a list of -pair, 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 the key bindings -are still applied. (This should probably be refined in the future.) - -Here is a complete example example: - -class ZoomHeight: - - menudefs = [ - ('edit', [ - None, # Separator - ('_Zoom Height', '<<zoom-height>>'), - ]) - ] - - windows_keydefs = { - '<<zoom-height>>': ['<Alt-F2>'], - } - unix_keydefs = { - '<<zoom-height>>': ['<Control-z><Control-z>'], - } - - 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.txt", which is used -to to configure the loading of extensions. For each extension, -you must include a section in config.txt (or in any of the other -configuration files that are consulted at startup: config-unix.txt, -config-win.txt, or ~/.idle). A section is headed by the module name -in square brackets, e.g. - - [ZoomHeight] - -The section may be empty, or it may define configuration options for -the extension. (See ParenMatch.py for an example.) A special option -is 'enable': including - - enable = 0 - -in a section disables that extension. More than one configuration -file may specify options for the same extension, so a user may disable -an extension that is loaded by default, or enable an extension that is -disabled by default. - -Extensions can define key bindings and menu entries that reference -events they don't implement (including standard events); however this is -not recommended (and may be forbidden in the future). - -Extensions are not required to define menu entries for all events they -implement. - -Note: in order to change key bindings, you must currently edit the file -keydefs. It contains two dictionaries named and formatted like the -keydefs dictionaries described above, one for the Unix bindings and one -for the Windows bindings. In the future, a better mechanism will be -provided. diff --git a/Tools/idle/help.txt b/Tools/idle/help.txt deleted file mode 100644 index 63327d7d81..0000000000 --- a/Tools/idle/help.txt +++ /dev/null @@ -1,157 +0,0 @@ -[See end for tips.] - -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 - 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 - --- - Close -- close current window (asks to save if unsaved) - Exit -- close all windows and quit IDLE (asks to save if unsaved) - -Edit menu: - - Undo -- Undo last change to current window (max 1000 changes) - Redo -- Redo last undone change to current window - --- - Cut -- Copy selection into system-wide clipboard; then delete 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 - --- - 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 - Untabify region -- Turn *all* tabs into the right number of spaces - Expand word -- Expand the word you have typed to match another - word in the same buffer; repeat to get a different expansion - Format Paragraph -- Reformat the current blank-line-separated paragraph - --- - Import module -- Import or reload the current module - Run script -- Execute the current file in the __main__ namespace - -Windows menu: - - Zoom Height -- toggles the window between normal size (24x80) - 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). - -Debug menu (in the Python Shell window only): - - Go to file/line -- look around the insert point for a filename - and linenumber, open the file, and show the line - Open stack viewer -- show the stack traceback of the last exception - Debugger toggle -- Run commands in the shell under the debugger - JIT Stack viewer toggle -- Open stack viewer on traceback - -Basic editing and navigation: - - Backspace deletes to the left; DEL deletes to the right - Arrow keys and Page Up/Down to move around - Home/End go to begin/end of line - Control-Home/End go to begin/end of file - Some Emacs bindings may also work, e.g. ^B/^P/^A/^E/^D/^L - -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 1-4 spaces (in the - Python Shell window one tab). See also the indent/dedent - region commands in the edit menu. - -Python Shell window: - - ^C interrupts executing command - ^D sends end-of-file; closes window if typed at >>> prompt - - Command history: - - Alt-p retrieves previous command matching what you have typed - Alt-n retrieves next - Return while on any previous command retrieves that command - Alt-/ (Expand word) is also useful here - -Syntax colors: - - The coloring is applied in a background "thread", so you may - occasionally see uncolorized text. To change the color - scheme, edit the [Colors] section in config.txt (or add a - [Colors] section to ~/.idle). - - Python syntax colors: - - Keywords orange - Strings green - Comments red - Definitions blue - - Shell colors: - - Console output brown - stdout blue - stderr dark green - stdin black - -Other preferences: - - Most preferences can be changed by editing one of the - configuration text files: config.txt (generic) or one of - config-unix.txt, config-win.txt, config.mac.txt (platform - specific). User-specific preferences can be stored in - $HOME/.idle, which overrides the config*.txt files. - - To change keyboard bindings, edit Bindings.py - -Command line usage: - - idle.py [-c command] [-d] [-e] [-s] [-t title] [arg] ... - - -c command run this command - -d enable debugger - -e edit mode; arguments are files to be edited - -s run $IDLESTARTUP or $PYTHONSTARTUP first - -t title set title of shell window - - If there are arguments: - - If -e is used, arguments are files opened for editing and - sys.argv reflects the arguments passed to IDLE itself. - - Otherwise, if -c is used, all arguments are placed in - sys.argv[1:...], with sys.argv[0] set to '-c'. - - Otherwise, if neither -e nor -c is used, the first - argument is a script which is executed with the remaining - arguments in sys.argv[1:...] and sys.argv[0] set to the - script name. If the script name is '-', no script is - executed but an interactive Python session is started; the - arguments are still available in sys.argv. diff --git a/Tools/idle/idle b/Tools/idle/idle deleted file mode 100755 index 2a854978a5..0000000000 --- a/Tools/idle/idle +++ /dev/null @@ -1,12 +0,0 @@ -#! /usr/bin/env python - -import os -import sys -from idlelib import IdleConf - -idle_dir = os.path.dirname(IdleConf.__file__) -IdleConf.load(idle_dir) - -# defer importing Pyshell until IdleConf is loaded -from idlelib import PyShell -PyShell.main() diff --git a/Tools/idle/idle.bat b/Tools/idle/idle.bat deleted file mode 100644 index 9024d02e0d..0000000000 --- a/Tools/idle/idle.bat +++ /dev/null @@ -1,3 +0,0 @@ -rem idle.bat - -start idle.pyw %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/Tools/idle/idle.py b/Tools/idle/idle.py deleted file mode 100755 index 8638a165b4..0000000000 --- a/Tools/idle/idle.py +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env python - -import PyShell -PyShell.main() diff --git a/Tools/idle/idle.pyw b/Tools/idle/idle.pyw deleted file mode 100644 index 79fe26fef5..0000000000 --- a/Tools/idle/idle.pyw +++ /dev/null @@ -1,8 +0,0 @@ -try: - import idle -except SystemExit: - raise -except: - import traceback - traceback.print_exc() - raw_input("Hit return to exit...") diff --git a/Tools/idle/idlever.py b/Tools/idle/idlever.py deleted file mode 100644 index 82c5781d56..0000000000 --- a/Tools/idle/idlever.py +++ /dev/null @@ -1 +0,0 @@ -IDLE_VERSION = "0.8" diff --git a/Tools/idle/keydefs.py b/Tools/idle/keydefs.py deleted file mode 100644 index 9761258e5f..0000000000 --- a/Tools/idle/keydefs.py +++ /dev/null @@ -1,57 +0,0 @@ -windows_keydefs = \ -{'<<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>'], - '<<dump-undo-state>>': ['<Control-backslash>'], - '<<end-of-file>>': ['<Control-d>'], - '<<help>>': ['<F1>'], - '<<history-next>>': ['<Alt-n>'], - '<<history-previous>>': ['<Alt-p>'], - '<<interrupt-execution>>': ['<Control-c>'], - '<<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>>': ['<Control-a>'], - '<<toggle-auto-coloring>>': ['<Control-slash>'], - '<<undo>>': ['<Control-z>']} - -unix_keydefs = \ -{'<<Copy>>': ['<Alt-w>', '<Meta-w>'], - '<<Cut>>': ['<Control-w>'], - '<<Paste>>': ['<Control-y>'], - '<<beginning-of-line>>': ['<Control-a>', '<Home>'], - '<<center-insert>>': ['<Control-l>'], - '<<close-all-windows>>': ['<Control-x><Control-c>'], - '<<close-window>>': ['<Control-x><Control-0>', '<Control-x><Key-0>'], - '<<do-nothing>>': ['<Control-x>'], - '<<dump-undo-state>>': ['<Control-backslash>'], - '<<end-of-file>>': ['<Control-d>'], - '<<help>>': ['<F1>'], - '<<history-next>>': ['<Alt-n>', '<Meta-n>'], - '<<history-previous>>': ['<Alt-p>', '<Meta-p>'], - '<<interrupt-execution>>': ['<Control-c>'], - '<<open-class-browser>>': ['<Control-x><Control-b>'], - '<<open-module>>': ['<Control-x><Control-m>'], - '<<open-new-window>>': ['<Control-x><Control-n>'], - '<<open-window-from-file>>': ['<Control-x><Control-f>'], - '<<plain-newline-and-indent>>': ['<Control-j>'], - '<<print-window>>': ['<Control-x><Control-p>'], - '<<redo>>': ['<Alt-z>', '<Meta-z>'], - '<<save-copy-of-window-as-file>>': ['<Control-x><w>'], - '<<save-window-as-file>>': ['<Control-x><Control-w>'], - '<<save-window>>': ['<Control-x><Control-s>'], - '<<select-all>>': ['<Alt-a>', '<Meta-a>'], - '<<toggle-auto-coloring>>': ['<Control-slash>'], - '<<undo>>': ['<Control-z>']} diff --git a/Tools/idle/setup.py b/Tools/idle/setup.py deleted file mode 100644 index b96909244b..0000000000 --- a/Tools/idle/setup.py +++ /dev/null @@ -1,100 +0,0 @@ -import os, glob, sys -from distutils.core import setup -from distutils.command.build_py import build_py -from distutils.command.install_lib import install_lib -import idlever - -try: - pos = sys.argv.index("--check-tkinter") -except ValueError: - pass -else: - del sys.argv[pos] - try: - import _tkinter - except ImportError: - print >>sys.stderr, "Cannot install IDLE without _tkinter" - raise SystemExit - -try: - package_dir = os.path.join(os.environ["SRCDIR"], "Tools", "idle") -except KeyError: - package_dir = "." - -# name of idle package -idlelib = "idlelib" - -# the normal build_py would not incorporate the .txt files -txt_files = ['config-unix.txt','config-win.txt','config.txt', 'help.txt'] -Icons = glob.glob1(os.path.join(package_dir,"Icons"),"*.gif") -class idle_build_py(build_py): - def get_plain_outfile(self, build_dir, package, file): - # like get_module_outfile, but does not append .py - outfile_path = [build_dir] + list(package) + [file] - return apply(os.path.join, outfile_path) - - def run(self): - # Copies all .py files, then also copies the txt and gif files - build_py.run(self) - assert self.packages == [idlelib] - for name in txt_files: - outfile = self.get_plain_outfile(self.build_lib, [idlelib], name) - dir = os.path.dirname(outfile) - self.mkpath(dir) - self.copy_file(os.path.join(package_dir, name), outfile, - preserve_mode = 0) - for name in Icons: - outfile = self.get_plain_outfile(self.build_lib, - [idlelib,"Icons"], name) - dir = os.path.dirname(outfile) - self.mkpath(dir) - self.copy_file(os.path.join(package_dir, "Icons", name), - outfile, preserve_mode = 0) - - def get_source_files(self): - # returns the .py files, the .txt files, and the icons - icons = [os.path.join(package_dir, "Icons",name) for name in Icons] - txts = [os.path.join(package_dir, name) for name in txt_files] - return build_py.get_source_files(self)+txt_files+icons - - def get_outputs(self, include_bytecode=1): - # returns the built files - outputs = build_py.get_outputs(self, include_bytecode) - if not include_bytecode: - return outputs - for name in txt_files: - filename = self.get_plain_outfile(self.build_lib, - [idlelib], name) - outputs.append(filename) - for name in Icons: - filename = self.get_plain_outfile(self.build_lib, - [idlelib,"Icons"], name) - outputs.append(filename) - return outputs - -# Arghhh. install_lib thinks that all files returned from build_py's -# get_outputs are bytecode files -class idle_install_lib(install_lib): - def _bytecode_filenames(self, files): - files = [n for n in files if n.endswith('.py')] - return install_lib._bytecode_filenames(self,files) - - -setup(name="IDLE", - version = idlever.IDLE_VERSION, - description = "IDLE, the Python IDE", - author = "Guido van Rossum", - author_email = "guido@python.org", - #url = - long_description = -"""IDLE is a Tkinter based IDE for Python. It is written in 100% pure -Python and works both on Windows and Unix. It features a multi-window -text editor with multiple undo, Python colorizing, and many other things, -as well as a Python shell window and a debugger.""", - - cmdclass = {'build_py':idle_build_py, - 'install_lib':idle_install_lib}, - package_dir = {idlelib: package_dir}, - packages = [idlelib], - scripts = [os.path.join(package_dir, 'idle')] - ) diff --git a/Tools/idle/testcode.py b/Tools/idle/testcode.py deleted file mode 100644 index 05eaa562cd..0000000000 --- a/Tools/idle/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() |