diff -r 81083f8841fe Lib/idlelib/Terminal.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/Terminal.py Fri Mar 22 23:00:37 2013 -0400 @@ -0,0 +1,223 @@ +""" + +Terminal Mode Extension +Version: 0.5 + +Author: Roger D. Serwy + serwy@illinois.edu + Todd V. Rovito + rovitotv@gmail.com + -added small changes to make it work with Python 3.4 + -changed enabled to enable + -put in patch form + +Date: September 2008, March 2013 + +This extension makes PyShell behave more like a terminal. + +Add these lines to config-extensions.def + +[Terminal] +enable=1 +enable_shell=1 +enable_editor=0 + + +""" +from configHandler import idleConf +import sys + +if sys.version < '3': + from Tkinter import INSERT, END, SEL_FIRST, SEL_LAST, SEL +else: + from tkinter import INSERT, END, SEL_FIRST, SEL_LAST, SEL + + + +class Terminal: + + menudefs = [ + ('options', [ + ('!Terminal Mode', '<>'), + ]),] + + def __init__(self, editwin): + self.editwin = editwin + self.text = self.editwin.text + self.after = self.editwin.root.after + self.oldundo = None + + + self.enable = idleConf.GetOption("extensions", "Terminal", + "enable", type="bool", default=True) + self.editwin.setvar("<>", not not self.enable) + self.text.bind("<>", self.terminal_toggle) + + # this extension is loaded from EditorWindow.py, but before + # PyShell.py makes its changes. Will use tk .after to make + # changes + + if self.enable: + self.delay_init() + + def delay_init(self): + # wait on the history object to be added to the window. This is + # required for useful terminal-like behavior + + if hasattr(self.editwin, 'history') == True: + self.terminal_mode_init() + return + self.after(100, self.delay_init) + + def terminal_toggle(self, event=None): + self.enable = not self.enable + self.editwin.setvar("<>", not not self.enable) + + if self.enable == False: + self.terminal_mode_exit() + else: + self.terminal_mode_init() + + idleConf.SetOption("extensions", "Terminal", "enable", '%s' % self.enable) + idleConf.SaveUserCfgFiles() + + + def terminal_mode_init(self, event=None): + # redefine some key bindings + self.enable = True + + text = self.editwin.text + + # up/down keys + text.bind("<>", self.key_up_callback, '+') + text.bind("<>", self.key_down_callback, '+') + text.event_add("<>", "") + text.event_add("<>", "") + + # page up/down keys + text.bind("<>", self.key_pgup_callback, '+') + text.bind("<>", self.key_pgdown_callback, '+') + text.event_add("<>", "") + text.event_add("<>", "") + + # home + text.bind("<>", self.home_callback, '+') + text.event_add("<>", "") + + # keep the cursor in the input area + text.bind("<>", self.key_in_input, '+') + text.event_add("<>", "") + text.bind("<>", self.mouse_in_input, '+') + text.event_add("<>", "") + + # need history for up/down keys + self.history = self.editwin.history; + + # make sure cursor is in input + self.key_in_input(event) + + def terminal_mode_exit(self, event=None): + self.enable = False + text = self.editwin.text + text.unbind("<>") + text.unbind("<>") + text.unbind("<>") + text.unbind("<>") + text.unbind("<>") + text.unbind("<>") + text.unbind("<>") + + def home_callback(self, event): + text = self.text + if self.text.compare("insert", "<", "iomark"): + self.text.mark_set("insert", "iomark") + return "break" + if self.text.compare("iomark", "==", "insert"): + return "break" + return + + def mouse_in_input(self, event=None): + # a mouse click on the window + self.text.mark_set('insert', 'end-1c') + #return "break" # don't return break, otherwise selection will not clear. + + def key_in_input(self, event=None): + if self.text.compare('insert', '<=', 'iomark'): + self.text.mark_set('insert', 'iomark') + return "break" + + def key_pgup_callback(self, event): + text = self.text + text.yview_scroll(-1, 'pages') + return "break" + + def key_pgdown_callback(self, event): + + text = self.text + text.yview_scroll(1, 'pages') + return "break" + + def history_ismember(self): + """ if the current input is in the history, return true """ + s = self.history._get_source('iomark', 'end-1c') + for i in self.history.history: + if i == s: + return True + + return False + + def key_up_callback(self, event): + + s = self.text.get('iomark', 'end-1c') + + if s.find('\n') == -1: + # single line input + + if self.text.compare('insert', '==', 'end-1c'): + self.history.history_prev(event) + return "break" + else: + self.text.mark_set('insert', 'end-1c') + return "break" + + else: + # multiline input + if self.text.compare('insert', '==', 'end-1c'): + if self.history_ismember() == True: + self.history.history_prev(event) + return "break" + + elif self.text.compare('insert linestart', '<=', 'iomark'): + # don't leave the input area + self.text.mark_set('insert', 'end-1c') + return "break" + + + def key_down_callback(self, event): + + s = self.text.get('iomark', 'end-1c') + + if s.find('\n') == -1: + # single line input + if self.text.compare('insert', '==', 'end-1c'): + self.history.history_next(event) + return "break" + else: + self.text.mark_set('insert', 'end-1c') + return "break" + + else: + # multiline input + if self.text.compare('insert', '<', 'end-1c') and \ + self.text.compare('insert lineend', '==', 'end-1c'): + self.text.mark_set('insert', 'end-1c') + return "break" + + if self.history_ismember() == True: + if self.text.compare('insert', '==', 'end-1c'): + self.history.history_next(event) + return "break" + elif self.text.compare('insert lineend', '==', 'end-1c'): + return "break" + + diff -r 81083f8841fe Lib/idlelib/config-extensions.def --- a/Lib/idlelib/config-extensions.def Fri Mar 22 13:49:53 2013 -0700 +++ b/Lib/idlelib/config-extensions.def Fri Mar 22 23:00:37 2013 -0400 @@ -94,3 +94,7 @@ enable_shell=0 enable_editor=1 +[Terminal] +enable=1 +enable_shell=1 +enable_editor=0