Browse Source

Basic alt mode implementation

pull/161/head
Eugenio Parodi 3 years ago
parent
commit
779ecf291d
  1. 142
      TermTk/TTkWidgets/TTkTerminal/mode.py
  2. 136
      TermTk/TTkWidgets/TTkTerminal/terminal.py
  3. 176
      TermTk/TTkWidgets/TTkTerminal/terminal_alt.py
  4. 4
      TermTk/TTkWidgets/TTkTerminal/terminal_normal.py
  5. 2
      tests/test.pty.006.terminal.02.py

142
TermTk/TTkWidgets/TTkTerminal/mode.py

@ -0,0 +1,142 @@
# MIT License
#
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in 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:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# 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
# AUTHORS 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 IN THE
# SOFTWARE.
class TTkTerminalModes(int):
# Ps = 1 ⇒ Application Cursor Keys (DECCKM), VT100.
# Ps = 1 ⇒ Normal Cursor Keys (DECCKM), VT100.
# Ps = 2 ⇒ Designate VT52 mode (DECANM), VT100.
# Ps = 3 ⇒ 80 Column Mode (DECCOLM), VT100.
# Ps = 4 ⇒ Jump (Fast) Scroll (DECSCLM), VT100.
# Ps = 5 ⇒ Normal Video (DECSCNM), VT100.
# Ps = 6 ⇒ Normal Cursor Mode (DECOM), VT100.
# Ps = 7 ⇒ No Auto-Wrap Mode (DECAWM), VT100.
# Ps = 8 ⇒ No Auto-Repeat Keys (DECARM), VT100.
# Ps = 9 ⇒ Don't send Mouse X & Y on button press, xterm.
# Ps = 1 0 ⇒ Hide toolbar (rxvt).
# Ps = 1 2 ⇒ Stop blinking cursor (AT&T 610).
# Ps = 1 3 ⇒ Disable blinking cursor (reset only via
# resource or menu).
# Ps = 1 4 ⇒ Disable XOR of blinking cursor control sequence
# and menu.
# Ps = 1 8 ⇒ Don't Print Form Feed (DECPFF), VT220.
# Ps = 1 9 ⇒ Limit print to scrolling region (DECPEX),
# VT220.
# Ps = 2 5 ⇒ Hide cursor (DECTCEM), VT220.
# Ps = 3 0 ⇒ Don't show scrollbar (rxvt).
# Ps = 3 5 ⇒ Disable font-shifting functions (rxvt).
# Ps = 4 0 ⇒ Disallow 80 ⇒ 132 mode, xterm.
# Ps = 4 1 ⇒ No more(1) fix (see curses resource).
# Ps = 4 2 ⇒ Disable National Replacement Character sets
# (DECNRCM), VT220.
# Ps = 4 3 ⇒ Disable Graphic Expanded Print Mode (DECGEPM),
# VT340.
# Ps = 4 4 ⇒ Turn off margin bell, xterm.
# Ps = 4 4 ⇒ Disable Graphic Print Color Mode (DECGPCM),
# VT340.
# Ps = 4 5 ⇒ No Reverse-wraparound mode (XTREVWRAP), xterm.
# Ps = 4 5 ⇒ Disable Graphic Print Color Syntax (DECGPCS),
# VT340.
# Ps = 4 6 ⇒ Stop logging (XTLOGGING), xterm. This is
# normally disabled by a compile-time option.
# Ps = 4 7 ⇒ Use Normal Screen Buffer, xterm.
# Ps = 4 7 ⇒ Disable Graphic Rotated Print Mode (DECGRPM),
# VT340.
# Ps = 6 6 ⇒ Numeric keypad mode (DECNKM), VT320.
# Ps = 6 7 ⇒ Backarrow key sends delete (DECBKM), VT340,
# VT420. This sets the backarrowKey resource to "false".
# Ps = 6 9 ⇒ Disable left and right margin mode (DECLRMM),
# VT420 and up.
# Ps = 8 0 ⇒ Disable Sixel Display Mode (DECSDM), VT330,
# VT340, VT382. Turns on "Sixel Scrolling". See the section
# Sixel Graphics and mode 8 4 5 2 .
# Ps = 9 5 ⇒ Clear screen when DECCOLM is set/reset
# (DECNCSM), VT510 and up.
# Ps = 1 0 0 0 ⇒ Don't send Mouse X & Y on button press and
# release. See the section Mouse Tracking.
# Ps = 1 0 0 1 ⇒ Don't use Hilite Mouse Tracking, xterm.
# Ps = 1 0 0 2 ⇒ Don't use Cell Motion Mouse Tracking,
# xterm. See the section Button-event tracking.
# Ps = 1 0 0 3 ⇒ Don't use All Motion Mouse Tracking, xterm.
# See the section Any-event tracking.
# Ps = 1 0 0 4 ⇒ Don't send FocusIn/FocusOut events, xterm.
# Ps = 1 0 0 5 ⇒ Disable UTF-8 Mouse Mode, xterm.
# Ps = 1 0 0 6 ⇒ Disable SGR Mouse Mode, xterm.
# Ps = 1 0 0 7 ⇒ Disable Alternate Scroll Mode, xterm. This
# corresponds to the alternateScroll resource.
# Ps = 1 0 1 0 ⇒ Don't scroll to bottom on tty output
# (rxvt). This sets the scrollTtyOutput resource to "false".
# Ps = 1 0 1 1 ⇒ Don't scroll to bottom on key press (rxvt).
# This sets the scrollKey resource to "false".
# Ps = 1 0 1 5 ⇒ Disable urxvt Mouse Mode.
# Ps = 1 0 1 6 ⇒ Disable SGR Mouse Pixel-Mode, xterm.
# Ps = 1 0 3 4 ⇒ Don't interpret "meta" key, xterm. This
# disables the eightBitInput resource.
# Ps = 1 0 3 5 ⇒ Disable special modifiers for Alt and
# NumLock keys, xterm. This disables the numLock resource.
# Ps = 1 0 3 6 ⇒ Don't send ESC when Meta modifies a key,
# xterm. This disables the metaSendsEscape resource.
# Ps = 1 0 3 7 ⇒ Send VT220 Remove from the editing-keypad
# Delete key, xterm.
# Ps = 1 0 3 9 ⇒ Don't send ESC when Alt modifies a key,
# xterm. This disables the altSendsEscape resource.
# Ps = 1 0 4 0 ⇒ Do not keep selection when not highlighted,
# xterm. This disables the keepSelection resource.
# Ps = 1 0 4 1 ⇒ Use the PRIMARY selection, xterm. This
# disables the selectToClipboard resource.
# Ps = 1 0 4 2 ⇒ Disable Urgency window manager hint when
# Control-G is received, xterm. This disables the bellIsUrgent
# resource.
# Ps = 1 0 4 3 ⇒ Disable raising of the window when Control-
# G is received, xterm. This disables the popOnBell resource.
# Ps = 1 0 4 5 ⇒ No Extended Reverse-wraparound mode
# (XTREVWRAP2), xterm.
# Ps = 1 0 4 6 ⇒ Disable switching to/from Alternate Screen
# Buffer, xterm. This works for terminfo-based systems,
# updating the titeInhibit resource. If currently using the
# Alternate Screen Buffer, xterm switches to the Normal Screen
# Buffer.
# Ps = 1 0 4 7 ⇒ Use Normal Screen Buffer, xterm. Clear the
# screen first if in the Alternate Screen Buffer. This may be
# disabled by the titeInhibit resource.
# Ps = 1 0 4 8 ⇒ Restore cursor as in DECRC, xterm. This
# may be disabled by the titeInhibit resource.
# Ps = 1 0 4 9 ⇒ Use Normal Screen Buffer and restore cursor
# as in DECRC, xterm. This may be disabled by the titeInhibit
# resource. This combines the effects of the 1 0 4 7 and 1 0 4
# 8 modes. Use this with terminfo-based applications rather
# than the 4 7 mode.
# Ps = 1 0 5 0 ⇒ Reset terminfo/termcap function-key mode,
# xterm.
# Ps = 1 0 5 1 ⇒ Reset Sun function-key mode, xterm.
# Ps = 1 0 5 2 ⇒ Reset HP function-key mode, xterm.
# Ps = 1 0 5 3 ⇒ Reset SCO function-key mode, xterm.
# Ps = 1 0 6 0 ⇒ Reset legacy keyboard emulation, i.e,
# X11R6, xterm.
# Ps = 1 0 6 1 ⇒ Reset keyboard emulation to Sun/PC style,
# xterm.
# Ps = 2 0 0 1 ⇒ Disable readline mouse button-1, xterm.
# Ps = 2 0 0 2 ⇒ Disable readline mouse button-2, xterm.
# Ps = 2 0 0 3 ⇒ Disable readline mouse button-3, xterm.
# Ps = 2 0 0 4 ⇒ Reset bracketed paste mode, xterm.
# Ps = 2 0 0 5 ⇒ Disable readline character-quoting, xterm.
# Ps = 2 0 0 6 ⇒ Disable readline newline pasting, xterm.

136
TermTk/TTkWidgets/TTkTerminal/terminal.py

@ -67,6 +67,9 @@ class TTkTerminal(TTkWidget):
super().__init__(*args, **kwargs)
# self._screen_alt._CSI_MAP |= self._CSI_MAP
# self._screen_current._CSI_MAP |= self._CSI_MAP
w,h = self.size()
self._screen_alt.resize(w,h)
self._screen_normal.resize(w,h)
@ -86,7 +89,7 @@ class TTkTerminal(TTkWidget):
if pid == 0:
argv = [self._shell]
env = dict(TERM="screen", DISPLAY=":1")
env = os.environ
os.execvpe(argv[0], argv, env)
else:
self._inout = os.fdopen(self._fd, "w+b", 0)
@ -98,20 +101,21 @@ class TTkTerminal(TTkWidget):
# xterm escape sequences from:
# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
re_CURSOR = re.compile('^((\d*)(;(\d*))*)([@ABCDEFGIJKLMPSTXZ^`abcdeginmqxHf])')
re_CURSOR = re.compile('^\[((\d*)(;(\d*))*)([@^`A-Za-z])')
# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
# Basic Re for CSI Ps matches:
# CSI : Control Sequence Introducer "<ESC>[" = '\033['
# Ps : A single (usually optional) numeric parameter, composed of one or more digits.
# fn : the single char defining the function
re_CSI_Ps_fu = re.compile('^(\d*)([@ABCDEFGIJKLMPSTXZ^`abcdeginqx])')
re_CSI_Ps_Ps_fu = re.compile('^(\d*);(\d*)([Hf])')
re_DEC_SET_RST = re.compile('^\?(\d+)([lh])')
re_CSI_Ps_fu = re.compile('^\[(\d*)([@ABCDEFGIJKLMPSTXZ^`abcdeghinqx])')
re_CSI_Ps_Ps_fu = re.compile('^\[(\d*);(\d*)([Hf])')
re_DEC_SET_RST = re.compile('^\[\?(\d+)([lh])')
# re_CURSOR_1 = re.compile(r'^(\d+)([ABCDEFGIJKLMPSTXZHf])')
def loop(self, _):
while rs := select( [self._inout], [], [])[0]:
TTkLog.debug(f"Select - {rs=}")
# TTkLog.debug(f"Select - {rs=}")
for r in rs:
if r is self._inout:
try:
@ -119,39 +123,34 @@ class TTkTerminal(TTkWidget):
except Exception as e:
TTkLog.error(f"Error: {e=}")
return
out = out.decode('utf-8','ignore')
# out = out.decode('utf-8','ignore')
out = out.decode()
for bi, bout in enumerate(out.split('\a')): # grab the bells
# TTkLog.debug(f'Eugenio->{out}')
# sout = bout.decode('utf-8','ignore')
if bi:
TTkLog.debug("BELL!!! 🔔🔔🔔")
sout = bout.split('\033[')
self._screen_current.pushLine(sout[0])
sout = bout.split('\033')
TTkLog.debug(f"{sout[0]=}")
self._screen_current.pushLine(sout[0])
for slice in sout[1:]:
ssss = slice.replace('\033','<ESC>').replace('\n','\\n').replace('\r','\\r')
TTkLog.debug(f"slice: {ssss}")
if m := TTkTerminal.re_DEC_SET_RST.match(slice):
# l = len(m.group(0))
en = m.end()
ps = int(m.group(1))
sr = m.group(2)
if ps == 1049 and sr == 'l': # NORMAL SCREEN
self._screen_current = self._screen_normal
elif ps == 1049 and sr == 'h': # ALT SCREEN
self._screen_current = self._screen_alt
elif ps == 2004:
# Bracketedpaste ON
# Bracketedpaste OFF
pass
sr = (m.group(2) == 'h')
self._CSI_DEC_SET_RST(ps,sr)
slice = slice[en:]
elif ( (m := TTkTerminal.re_CURSOR.match(slice)) and
(mg := m.groups()) and
mg[-1] == 'm' ):
TTkLog.debug(f"Handle color {mg[0]=}")
# TTkLog.debug(f"Handle color {mg[0]=}")
en = m.end()
color=TTkColor.RST
if mg[0] != '0m':
if mg[0] not in ['0','']:
values = mg[0].split(';')
fg = None
@ -196,28 +195,47 @@ class TTkTerminal(TTkWidget):
self._screen_alt.setColor(color)
self._screen_normal.setColor(color)
TTkLog.debug(TTkString(f"color - <ESC>[{mg[0]}",color).toAnsi())
# TTkLog.debug(TTkString(f"color - <ESC>[{mg[0]}",color).toAnsi())
slice = slice[en:]
elif m:
en = m.end()
y = ps = int(y) if (y:=m.group(1)) else 1
sep = m.group(2)
x = int(x) if (x:=m.group(3)) else 1
fn = m.group(4)
TTkLog.debug(f"ps:{y=} {sep=} {x=} {fn=}")
_ex = self._screen_current._CSI_MAP.get(
fn,
lambda a,b,c: TTkLog.warn(f"Unhandled <ESC> {y=} {sep=} {x=} {fn=}"))
_ex(self._screen_current,y,x)
y = ps = int(y) if (y:=m.group(2)) else 1
sep = m.group(3)
x = int(x) if (x:=m.group(4)) else 1
fn = m.group(5)
TTkLog.debug(f"{mg[0]}{fn} = ps:{y=} {sep=} {x=} {fn=}")
if fn in ['n']:
_ex = self._CSI_MAP.get(
fn,
lambda a,b,c: TTkLog.warn(f"Unhandled <ESC>[{mg[0]}{fn} = ps:{y=} {sep=} {x=} {fn=}"))
_ex(self,y,x)
else:
_ex = self._screen_current._CSI_MAP.get(
fn,
lambda a,b,c: TTkLog.warn(f"Unhandled <ESC>[{mg[0]}{fn} = ps:{y=} {sep=} {x=} {fn=}"))
_ex(self._screen_current,y,x)
slice = slice[en:]
else:
slice = '\033[' + slice.replace('\r','')
slice = '\033' + slice.replace('\r','')
ssss = slice.replace('\033','<ESC>').replace('\n','\\n')
TTkLog.warn(f"Unhandled Slice:{ssss}")
# TTkLog.debug(f'Eugenio->{slice}')
self._screen_current.pushLine(slice)
slice = slice.replace('\033','<ESC>').replace('\n','\\n')
TTkLog.debug(f"{slice=}")
if '\033' in slice:
# import time
# ssss = slice.replace('\033','<ESC>').replace('\n','\\n')
# TTkLog.warn(f"WAIT FOR Unhandled Slice:{ssss}")
# time.sleep(0.5)
# self._screen_current.pushLine(slice)
# TTkLog.warn(f"DONE!!!! Unhandled Slice:{ssss}")
slice = slice.replace('\033','<ESC>').replace('\n','\\n')
TTkLog.warn(f"Unhandled slice: {slice=}")
# time.sleep(1.5)
else:
self._screen_current.pushLine(slice)
slice = slice.replace('\033','<ESC>').replace('\n','\\n')
# TTkLog.debug(f"{slice=}")
self.update()
self.setWidgetCursor(pos=self._screen_current.getCursor())
TTkLog.debug(f"wc:{self._screen_current.getCursor()}")
@ -242,3 +260,51 @@ class TTkTerminal(TTkWidget):
def paintEvent(self, canvas: TTkCanvas):
w,h = self.size()
self._screen_current.paintEvent(canvas,w,h)
# CSI Ps n Device Status Report (DSR).
# Ps = 5 ⇒ Status Report.
# Result ("OK") is CSI 0 n
# Ps = 6 ⇒ Report Cursor Position (CPR) [row;column].
# Result is CSI r ; c R
#
# Note: it is possible for this sequence to be sent by a
# function key. For example, with the default keyboard
# configuration the shifted F1 key may send (with shift-,
# control-, alt-modifiers)
#
# CSI 1 ; 2 R , or
# CSI 1 ; 5 R , or
# CSI 1 ; 6 R , etc.
#
# The second parameter encodes the modifiers; values range from
# 2 to 16. See the section PC-Style Function Keys for the
# codes. The modifyFunctionKeys and modifyKeyboard resources
# can change the form of the string sent from the modified F1
# key.
def _CSI_n_DSR(self, ps, _):
x,y = self._screen_current.getCursor()
if ps==6:
self._inout.write(f"\033[{y+1};{x+1}R".encode())
elif ps==5:
self._inout.write(f"\033[0n".encode())
_CSI_MAP = {
'n': _CSI_n_DSR,
}
def _CSI_DEC_SET_RST(self, ps, s):
_dec = self._CSI_DEC_SET_RST_MAP.get(
ps,
lambda a,b: TTkLog.warn(f"Unhandled DEC <ESC>[{ps}{'h' if s else 'l'}"))
_dec(self, s)
def _CSI_DEC_SR_1049(self, s):
if s:
self._screen_current = self._screen_alt
else:
self._screen_current = self._screen_normal
_CSI_DEC_SET_RST_MAP = {
1049: _CSI_DEC_SR_1049
}

176
TermTk/TTkWidgets/TTkTerminal/terminal_alt.py

@ -39,13 +39,14 @@ from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView, TTkAbst
from TermTk.TTkWidgets.widget import TTkWidget
class _TTkTerminalAltScreen():
__slots__ = ('_lines', '_terminalCursor', '_w', '_h', '_color')
__slots__ = ('_lines', '_terminalCursor', '_w', '_h', '_color', '_canvas')
def __init__(self, w=80, h=24, color=TTkColor.RST) -> None:
self._lines = [TTkString()]
self._terminalCursor = (0,0)
self._w = w
self._h = h
self._color = color
self._canvas = TTkCanvas(width=w, height=h)
def setColor(self, color):
self._color = color
@ -56,64 +57,129 @@ class _TTkTerminalAltScreen():
def resize(self, w, h):
self._w = w
self._h = h
newCanvas = TTkCanvas(width=w, height=h)
s = (0,0,w,h)
newCanvas.paintCanvas(self._canvas,s,s,s)
self._canvas = newCanvas
x,y = self._terminalCursor
self._terminalCursor = (min(x,w-1),min(y,h-1))
def _pushTxt(self, txt):
x,y = self._terminalCursor
w,h = self._w, self._h
txt = TTkString(txt, self._color)
self._terminalCursor = (min(w-1,x+len(txt)),y)
self._canvas.drawTTkString(text=txt, pos=(x,y))
def pushLine(self, line:str):
lines = line.replace('\r','').split('\n')
if not line: return
x,y = self._terminalCursor
w,h = self._w, self._h
lines = line.split('\n')
for i,l in enumerate(lines):
if i:
self._lines.append(TTkString(l))
else:
self._lines[-1] += TTkString(l)
self._terminalCursor = (x,y) = (0,min(h-1,y+1))
ls = l.split('\r')
for ii,ll in enumerate(ls):
if ii:
self._terminalCursor = (x,y) = (0,y)
lls = ll.split('\b') # 0x08 = Backspace
for iii,lll in enumerate(lls):
if iii:
self._terminalCursor = (max(0,x-1),y)
self._pushTxt(lll)
def paintEvent(self, canvas: TTkCanvas, w:int, h:int, ox:int=0, oy:int=0) -> None:
canvas.drawText(text="ALT Screen", pos=(0,0), width=w)
w,h = self._w, self._h
s = (0,0,w,h)
canvas.paintCanvas(self._canvas,s,s,s)
TTkLog.debug("Paint")
# CSI Ps @ Insert Ps (Blank) Character(s) (default = 1) (ICH).
def _CSI___ICH(self, ps, _): pass
def _CSI___ICH(self, ps, _):
x,y = self._terminalCursor
self._canvas.drawText(' '*ps,pos=(x,y))
# CSI Ps SP @ (SP = Space)
# Shift left Ps columns(s) (default = 1) (SL), ECMA-48.
def _CSI___SL( self, ps, _): pass
def _CSI___SL( self, ps, _):
x,y = self._terminalCursor
self._canvas.drawText(' '*ps,pos=(x,y))
# CSI Ps A Cursor Up Ps Times (default = 1) (CUU).
def _CSI_A_CUU(self, ps, _): pass
def _CSI_A_CUU(self, ps, _):
x,y = self._terminalCursor
self._terminalCursor = (x,max(0,y-ps))
# CSI Ps SP A (SP = Space)
# Shift right Ps columns(s) (default = 1) (SR), ECMA-48.
def _CSI_A_SR( self, ps, _): pass
# def _CSI_A_SR( self, ps, _):
# x,y = self._terminalCursor
# w,h = self._w, self._h
# self._terminalCursor = (min(x+ps,w-1),y)
# CSI Ps B Cursor Down Ps Times (default = 1) (CUD).
def _CSI_B_CUD(self, ps, _): pass
def _CSI_B_CUD(self, ps, _):
x,y = self._terminalCursor
w,h = self._w, self._h
self._terminalCursor = (x,min(y+ps,h-1))
# CSI Ps C Cursor Forward Ps Times (default = 1) (CUF).
def _CSI_C_CUF(self, ps, _): pass
def _CSI_C_CUF(self, ps, _):
x,y = self._terminalCursor
w,h = self._w, self._h
self._terminalCursor = (min(x+ps,w-1),y)
# CSI Ps D Cursor Backward Ps Times (default = 1) (CUB).
def _CSI_D_CUB(self, ps, _): pass
def _CSI_D_CUB(self, ps, _):
x,y = self._terminalCursor
self._terminalCursor = (max(0,x-ps),y)
# CSI Ps E Cursor Next Line Ps Times (default = 1) (CNL).
def _CSI_E_CNL(self, ps, _): pass
def _CSI_E_CNL(self, ps, _):
x,y = self._terminalCursor
w,h = self._w, self._h
self._terminalCursor = (0,min(y+ps,h-1))
# CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL).
def _CSI_F_CPL(self, ps, _): pass
def _CSI_F_CPL(self, ps, _):
x,y = self._terminalCursor
self._terminalCursor = (0,max(0,y-ps))
# CSI Ps G Cursor Character Absolute [column] (default = [row,1]) (CHA).
def _CSI_G_CHA(self, ps, _): pass
def _CSI_G_CHA(self, col, _):
x,y = self._terminalCursor
w,h = self._w, self._h
self._terminalCursor = (min(col-1,w-1),y)
# CSI Ps ; Ps H
# Cursor Position [row;column] (default = [1,1]) (CUP).
def _CSI_H_CUP(self, row, col): pass
def _CSI_H_CUP(self, row, col):
x,y = self._terminalCursor
w,h = self._w, self._h
self._terminalCursor = (min(col-1,w-1), min(row-1,h-1))
# CSI Ps I Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).
def _CSI_I_CHT(self, ps, _): pass
# def _CSI_I_CHT(self, ps, _): pass
# CSI Ps J Erase in Display (ED), VT100.
# Ps = 0 ⇒ Erase Below (default).
# Ps = 1 ⇒ Erase Above.
# Ps = 2 ⇒ Erase All.
# Ps = 3 ⇒ Erase Saved Lines, xterm.
def _CSI_J_ED(self, ps, _): pass
def _CSI_J_ED(self, ps, _):
x,y = self._terminalCursor
w,h = self._w,self._h
if ps == 0:
self._canvas.fill(char=' ', pos=(0,y+1),size=(w,h))
self._canvas.fill(char=' ', pos=(x,y),size=(w,1))
elif ps == 1:
self._canvas.fill(char=' ', pos=(0,0),size=(w,y-1))
self._canvas.fill(char=' ', pos=(0,y),size=(x,1))
elif ps == 2:
self._canvas.fill(char=' ', pos=(0,0),size=(w,h))
# CSI ? Ps J
# Erase in Display (DECSED), VT220.
@ -126,7 +192,15 @@ class _TTkTerminalAltScreen():
# Ps = 0 ⇒ Erase to Right (default).
# Ps = 1 ⇒ Erase to Left.
# Ps = 2 ⇒ Erase All.
def _CSI_K_EL(self, ps, _): pass
def _CSI_K_EL(self, ps, _):
x,y = self._terminalCursor
w,h = self._w,self._h
if ps == 0:
self._canvas.fill(char=' ', pos=(0,y),size=(x,1))
elif ps == 1:
self._canvas.fill(char=' ', pos=(x,y),size=(w,1))
elif ps == 2:
self._canvas.fill(char=' ', pos=(0,y),size=(w,1))
# CSI ? Ps K
# Erase in Line (DECSEL), VT220.
@ -135,13 +209,13 @@ class _TTkTerminalAltScreen():
# Ps = 2 ⇒ Selective Erase All.
# CSI Ps L Insert Ps Line(s) (default = 1) (IL).
def _CSI_L_IL(self, ps, _): pass
# def _CSI_L_IL(self, ps, _): pass
# CSI Ps M Delete Ps Line(s) (default = 1) (DL).
def _CSI_M_DL(self, ps, _): pass
# def _CSI_M_DL(self, ps, _): pass
# CSI Ps P Delete Ps Character(s) (default = 1) (DCH).
def _CSI_P_DCH(self, ps, _): pass
# def _CSI_P_DCH(self, ps, _): pass
# CSI # P
# CSI Pm # P
@ -841,7 +915,7 @@ class _TTkTerminalAltScreen():
# codes. The modifyFunctionKeys and modifyKeyboard resources
# can change the form of the string sent from the modified F1
# key.
def _CSI_n_DSR(self, ps, _): pass
# def _CSI_n_DSR(self, ps, _): pass
# CSI > Ps n
# Disable key modifier options, xterm. These modifiers may be
@ -1384,32 +1458,32 @@ class _TTkTerminalAltScreen():
'F': _CSI_F_CPL,
'G': _CSI_G_CHA,
'H': _CSI_H_CUP,
'I': _CSI_I_CHT,
# 'I': _CSI_I_CHT,
'J': _CSI_J_ED,
'K': _CSI_K_EL,
'L': _CSI_L_IL,
'M': _CSI_M_DL,
'P': _CSI_P_DCH,
'S': _CSI_S_SU,
'T': _CSI_T_SD,
'X': _CSI_X_ECH,
'Z': _CSI_Z_CBT,
'^': _CSI___SD,
'`': _CSI___HPA,
'a': _CSI_a_HPR,
'b': _CSI_b_REP,
'c': _CSI_c_Pri_DA,
'd': _CSI_d_VPA,
'e': _CSI_e_VPR,
'f': _CSI_f_HVP,
'g': _CSI_g_TBC,
'h': _CSI_h_SM,
'i': _CSI_i_MC,
'l': _CSI_l_RM,
'm': _CSI_m_SGR,
'n': _CSI_n_DSR,
'q': _CSI_q_DECLL,
's': _CSI_s_SCOSC,
'u': _CSI_u_SCORC,
'x': _CSI_x_DECREQTPARM
# 'L': _CSI_L_IL,
# 'M': _CSI_M_DL,
# 'P': _CSI_P_DCH,
# 'S': _CSI_S_SU,
# 'T': _CSI_T_SD,
# 'X': _CSI_X_ECH,
# 'Z': _CSI_Z_CBT,
# '^': _CSI___SD,
# '`': _CSI___HPA,
# 'a': _CSI_a_HPR,
# 'b': _CSI_b_REP,
# 'c': _CSI_c_Pri_DA,
# 'd': _CSI_d_VPA,
# 'e': _CSI_e_VPR,
# 'f': _CSI_f_HVP,
# 'g': _CSI_g_TBC,
# 'h': _CSI_h_SM,
# 'i': _CSI_i_MC,
# 'l': _CSI_l_RM,
# 'm': _CSI_m_SGR,
# 'n': _CSI_n_DSR,
# 'q': _CSI_q_DECLL,
# 's': _CSI_s_SCOSC,
# 'u': _CSI_u_SCORC,
# 'x': _CSI_x_DECREQTPARM
}

4
TermTk/TTkWidgets/TTkTerminal/terminal_normal.py

@ -184,7 +184,7 @@ class _TTkTerminalNormalScreen():
# CSI Ps I Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).
def _CSI_I_CHT(self, ps, _): pass
# def _CSI_I_CHT(self, ps, _): pass
# CSI Ps J Erase in Display (ED), VT100.
# Ps = 0 ⇒ Erase Below (default).
@ -1510,7 +1510,7 @@ class _TTkTerminalNormalScreen():
'F': _CSI_F_CPL,
'G': _CSI_G_CHA,
'H': _CSI_H_CUP,
'I': _CSI_I_CHT,
# 'I': _CSI_I_CHT,
'J': _CSI_J_ED,
'K': _CSI_K_EL,
'L': _CSI_L_IL,

2
tests/test.pty.006.terminal.02.py

@ -54,7 +54,7 @@ split = ttk.TTkSplitter(parent=root, orientation=ttk.TTkK.VERTICAL)
split.addItem(top := ttk.TTkLayout())
split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log')
split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log', size=20)
win1 = ttk.TTkWindow(pos=(90,5), size=(70,15), title="Terminallo n.1", border=True, layout=ttk.TTkVBoxLayout(), flags = ttk.TTkK.WindowFlag.WindowMinMaxButtonsHint)
term1 = ttk.TTkTerminal(parent=win1)

Loading…
Cancel
Save