You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/WPy32-3720/python-3.7.2/Lib/site-packages/idlexlib/extensions/Terminal.py

278 lines
9.3 KiB

# IDLEX EXTENSION
## """
## Copyright(C) 2011 The Board of Trustees of the University of Illinois.
## All rights reserved.
##
## Developed by: Roger D. Serwy
## University of Illinois
##
## Permission is hereby granted, free of charge, to any person obtaining
## a copy of this software and associated documentation files (the
## "Software"), to deal with the Software without restriction, including
## without limitation the rights to use, copy, modify, merge, publish,
## distribute, sublicense, and/or sell copies of the Software, and to
## permit persons to whom the Software is furnished to do so, subject to
## the following conditions:
##
## + Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimers.
## + Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimers in the
## documentation and/or other materials provided with the distribution.
## + Neither the names of Roger D. Serwy, the University of Illinois, nor
## the names of its contributors may be used to endorse or promote
## products derived from this Software without specific prior written
## permission.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
## IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
## ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
## CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
## THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
##
##
##
##
## Terminal Mode Extension - makes PyShell behave more like a terminal
##
## This extension makes PyShell behave more like a terminal.
## The cursor is confined to the input area. Up and down arrow keys
## the navigate command history.
##
## Selected text in the Shell Window will not be copied to the
## input area when pressing enter.
##
## Part of Issue2704
##
## """
config_extension_def = """
[Terminal]
enable=1
enable_shell=1
enable_editor=0
terminal=True
[Terminal_cfgBindings]
terminal-toggle=
"""
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
from idlelib.configHandler import idleConf
class Terminal:
menudefs = [
('options', [
('!Terminal Mode', '<<terminal-toggle>>'),
]),]
def __init__(self, editwin):
self.editwin = editwin
self.text = self.editwin.text
self.enabled = idleConf.GetOption("extensions", "Terminal",
"terminal", type="bool", default=True)
self.editwin.setvar("<<terminal-toggle>>", not not self.enabled)
# this extension is loaded from EditorWindow.py, but before
# PyShell.py makes its changes. Will use tk .after to make
# changes
self.last_insert = 'end-1c'
if self.enabled:
self.text.after(10, self.delay_init)
def close(self):
self.editwin = None
self.text = None
def delay_init(self):
if hasattr(self.editwin, 'history'):
self.terminal_mode_init()
return
self.text.after(100, self.delay_init)
def terminal_toggle_event(self, event=None):
self.enabled = not self.enabled
self.editwin.setvar("<<terminal-toggle>>", not not self.enabled)
if self.enabled == False:
self.terminal_mode_exit()
else:
self.terminal_mode_init()
idleConf.SetOption("extensions", "Terminal", "terminal", '%s' % self.enabled)
def terminal_mode_init(self, event=None):
# redefine some key bindings
self.enabled = True
text = self.editwin.text
# up/down keys
text.bind("<<term-key-up-callback>>", self.key_up_callback)
text.bind("<<term-key-down-callback>>", self.key_down_callback)
text.event_add("<<term-key-up-callback>>", "<Key-Up>")
text.event_add("<<term-key-down-callback>>", "<Key-Down>")
# page up/down keys
text.bind("<<term-key-pgup-callback>>", self.key_pgup_callback, '+')
text.bind("<<term-key-pgdown-callback>>", self.key_pgdown_callback, '+')
text.event_add("<<term-key-pgup-callback>>", "<Key-Prior>")
text.event_add("<<term-key-pgdown-callback>>", "<Key-Next>")
# home
text.bind("<<term-home-callback>>", self.home_callback, '+')
text.event_add("<<term-home-callback>>", "<Key-Home>")
# keep the cursor in the input area
text.bind("<<key-in-input>>", self.key_in_input)
text.event_add("<<key-in-input>>", "<Key-Left>")
text.bind("<<mouse-press>>", self.mouse_press)
text.event_add("<<mouse-press>>", "<ButtonPress>")
text.bind("<<mouse-release>>", self.mouse_release)
text.event_add("<<mouse-release>>", "<ButtonRelease>")
# make sure cursor is in input
self.key_in_input(event)
# override the enter-recall functionality
text.bind('<Return>', self.enter_callback)
def enter_callback(self, ev=None):
if self.enabled:
self.text.tag_remove('sel', '1.0', 'end')
return self.editwin.enter_callback(ev)
def terminal_mode_exit(self, event=None):
self.enabled = False
text = self.editwin.text
text.unbind("<<term-key-up-callback>>")
text.unbind("<<term-key-down-callback>>")
text.unbind("<<key-in-input>>")
text.unbind("<<mouse-in-input>>")
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_press(self, event=None):
text = self.text
self.last_insert = text.index('insert')
if text.compare('insert', '<=', 'iomark'):
self.last_insert = text.index('end-1c')
def mouse_release(self, event=None):
if self.enabled == False: return
# a mouse click on the window
text = self.text
if text.compare('insert', '<=', 'iomark'):
text.mark_set('insert', self.last_insert)
def key_in_input(self, event=None):
if self.enabled == False: return
# some key stroke
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.editwin.history._get_source('iomark', 'end-1c')
return (s in self.editwin.history.history)
def key_up_callback(self, event):
if self.enabled == False: return
if self.editwin.executing:
return "break"
s = self.text.get('iomark', 'end-1c')
if '\n' not in s:
# single line input
if self.text.compare('insert', '==', 'end-1c'):
self.editwin.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():
self.editwin.history.history_prev(event)
return "break"
elif self.text.compare('insert', '<=', 'iomark'):
# don't leave the input area
self.text.mark_set('insert', 'iomark')
return "break"
elif self.text.compare('insert-1l', '<=', 'iomark'):
self.text.mark_set('insert', 'iomark')
return "break"
def key_down_callback(self, event):
if self.enabled == False: return
if self.editwin.executing:
return "break"
s = self.text.get('iomark', 'end-1c')
if '\n' not in s:
# single line input
if self.text.compare('insert', '==', 'end-1c'):
self.editwin.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():
if self.text.compare('insert', '==', 'end-1c'):
self.editwin.history.history_next(event)
return "break"
elif self.text.compare('insert lineend', '==', 'end-1c'):
return "break"