diff --git a/TermTk/TTkWidgets/TTkTerminal/mode.py b/TermTk/TTkWidgets/TTkTerminal/mode.py index f55363f8..98f0aa70 100644 --- a/TermTk/TTkWidgets/TTkTerminal/mode.py +++ b/TermTk/TTkWidgets/TTkTerminal/mode.py @@ -21,6 +21,7 @@ # SOFTWARE. class TTkTerminalModes(int): + DECCKM = 1 # Ps = 1 ⇒ Application Cursor Keys (DECCKM), VT100. # Ps = 1 ⇒ Normal Cursor Keys (DECCKM), VT100. diff --git a/TermTk/TTkWidgets/TTkTerminal/terminal.py b/TermTk/TTkWidgets/TTkTerminal/terminal.py index e7cdb352..0f1e98e8 100644 --- a/TermTk/TTkWidgets/TTkTerminal/terminal.py +++ b/TermTk/TTkWidgets/TTkTerminal/terminal.py @@ -23,6 +23,8 @@ import os, pty, threading import struct, fcntl, termios +from dataclasses import dataclass + import re from select import select from TermTk.TTkCore.canvas import TTkCanvas @@ -46,6 +48,7 @@ from TermTk.TTkWidgets.widget import TTkWidget from TermTk.TTkWidgets.TTkTerminal.terminal_alt import _TTkTerminalAltScreen from TermTk.TTkWidgets.TTkTerminal.terminal_normal import _TTkTerminalNormalScreen +from TermTk.TTkWidgets.TTkTerminal.mode import TTkTerminalModes from TermTk.TTkWidgets.TTkTerminal.vt102 import TTkVT102 @@ -55,8 +58,13 @@ from TermTk.TTkCore.TTkTerm.colors_ansi_map import ansiMap16, ansiMap256 __all__ = ['TTkTerminal'] class TTkTerminal(TTkWidget): + @dataclass + class _Keyboard(): + flags: int = 0 + + __slots__ = ('_shell', '_fd', '_inout', '_proc', '_quit_pipe', '_mode_normal' - '_buffer_lines', '_buffer_screen', + '_buffer_lines', '_buffer_screen', '_keyboard', '_screen_current', '_screen_normal', '_screen_alt') def __init__(self, *args, **kwargs): self._shell = os.environ.get('SHELL', 'sh') @@ -64,6 +72,7 @@ class TTkTerminal(TTkWidget): self._proc = None self._mode_normal = True self._quit_pipe = None + self._keyboard = TTkTerminal._Keyboard() self._buffer_lines = [TTkString()] self._screen_normal = _TTkTerminalNormalScreen() self._screen_alt = _TTkTerminalAltScreen() @@ -93,6 +102,7 @@ class TTkTerminal(TTkWidget): # termios.tcsetwinsize(self._fd,(h,w)) self._screen_alt.resize(w,h) self._screen_normal.resize(w,h) + TTkLog.info(f"Resize Terminal: {w=} {h=}") return super().resizeEvent(w, h) def runShell(self, program=None): @@ -118,6 +128,8 @@ class TTkTerminal(TTkWidget): self._quit_pipe = os.pipe() threading.Thread(target=self.loop,args=[self]).start() + w,h = self.size() + self.resizeEvent(w,h) # xterm escape sequences from: # https://invisible-island.net/xterm/ctlseqs/ctlseqs.html @@ -148,12 +160,24 @@ class TTkTerminal(TTkWidget): if r is not self._inout: continue try: - out = self._inout.read(10240) + _fl = fcntl.fcntl(self._inout, fcntl.F_GETFL) + fcntl.fcntl(self._inout, fcntl.F_SETFL, _fl | os.O_NONBLOCK) # Set the input as NONBLOCK to read the full sequence + out = b"" + while _out := self._inout.read(): + out += _out + fcntl.fcntl(self._inout, fcntl.F_SETFL, _fl) except Exception as e: TTkLog.error(f"Error: {e=}") return + # out = out.decode('utf-8','ignore') - out = out.decode() + try: + out = out.decode() + except Exception as e: + TTkLog.error(f"{e=}") + TTkLog.error(f"Failed to decode {out}") + out = out.decode('utf-8','ignore') + for bi, bout in enumerate(out.split('\a')): # grab the bells # TTkLog.debug(f'Eugenio->{out}') # sout = bout.decode('utf-8','ignore') @@ -229,10 +253,11 @@ class TTkTerminal(TTkWidget): slice = slice[en:] elif m: en = m.end() - 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) + defval = self._CSI_Default_MAP.get(fn,(1,1)) + y = ps = int(y) if (y:=m.group(2)) else defval[0] + sep = m.group(3) + x = int(x) if (x:=m.group(4)) else defval[1] TTkLog.debug(f"{mg[0]}{fn} = ps:{y=} {sep=} {x=} {fn=}") if fn in ['n']: _ex = self._CSI_MAP.get( @@ -276,6 +301,13 @@ class TTkTerminal(TTkWidget): # TTkLog.debug(f"Key: {evt.code=}") TTkLog.debug(f"Key: {str(evt)=}") if evt.type == TTkK.SpecialKey: + if self._keyboard.flags & TTkTerminalModes.DECCKM: + if code := {TTkK.Key_Up: b"\033OA", + TTkK.Key_Down: b"\033OB", + TTkK.Key_Right: b"\033OC", + TTkK.Key_Left: b"\033OD"}.get(evt.key): + self._inout.write(code) + return True if evt.key == TTkK.Key_Enter: TTkLog.debug(f"Key: Enter") # self._inout.write(b'\n') @@ -290,6 +322,17 @@ class TTkTerminal(TTkWidget): w,h = self.size() self._screen_current.paintEvent(canvas,w,h) + + + # This map include the default values in case Ps or Row/Col are empty + # Since almost all the CSI use 1 as default, I am including here only + # the ones that are different + _CSI_Default_MAP = { + 'J' : (0,None), + 'K' : (0,None) + } + + # CSI Ps n Device Status Report (DSR). # Ps = 5 ⇒ Status Report. # Result ("OK") is CSI 0 n @@ -321,20 +364,83 @@ class TTkTerminal(TTkWidget): '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 [{ps}{'h' if s else 'l'}")) _dec(self, s) + + + # CSI ? Pm h + # DEC Private Mode Set (DECSET). + # Ps = 1 ⇒ Application Cursor Keys (DECCKM), VT100. + # UP = \0330A + # DOWN = \0330B + # LEFT = \0330C + # RIGHT = \0330D + # CSI ? Pm l + # DEC Private Mode Reset (DECRST). + # Ps = 1 ⇒ Normal Cursor Keys (DECCKM), VT100. + # UP = \033[A + # DOWN = \033[B + # LEFT = \033[C + # RIGHT = \033[D + def _CSI_DEC_SR_1_DECCKM(self, s): + if s: + self._keyboard.flags |= TTkTerminalModes.DECCKM + else: + self._keyboard.flags &= ~TTkTerminalModes.DECCKM + # CSI ? Pm h # DEC Private Mode Set (DECSET). # Ps = 2 5 ⇒ Show cursor (DECTCEM), VT220. # CSI ? Pm l # DEC Private Mode Reset (DECRST). # Ps = 2 5 ⇒ Hide cursor (DECTCEM), VT220. - def _CSI_DEC_SR_25(self, s): + def _CSI_DEC_SR_25_DECTCEM(self, s): self.enableWidgetCursor(enable=s) + # CSI ? Pm h + # DEC Private Mode Set (DECSET). + # Ps = 1 0 0 2 ⇒ Use Cell Motion Mouse Tracking, xterm. See + # the section Button-event tracking. + # CSI ? Pm l + # DEC Private Mode Reset (DECRST). + # Ps = 1 0 0 2 ⇒ Don't use Cell Motion Mouse Tracking, + # xterm. See the section Button-event tracking. + def _CSI_DEC_SR_1002(self, s): + pass + + # CSI ? Pm h + # DEC Private Mode Set (DECSET). + # Ps = 1 0 4 7 ⇒ Use Alternate Screen Buffer, xterm. This + # may be disabled by the titeInhibit resource. + # CSI ? Pm l + # DEC Private Mode Reset (DECRST). + # 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. + def _CSI_DEC_SR_1047(self, s): + if s: + self._screen_current = self._screen_alt + else: + self._screen_current = self._screen_normal + + # CSI ? Pm h + # DEC Private Mode Set (DECSET). + # Ps = 1 0 4 8 ⇒ Save cursor as in DECSC, xterm. This may + # be disabled by the titeInhibit resource. + # CSI ? Pm l + # DEC Private Mode Reset (DECRST). + # Ps = 1 0 4 8 ⇒ Restore cursor as in DECRC, xterm. This + # may be disabled by the titeInhibit resource. + def _CSI_DEC_SR_1048(self, s): + pass + # CSI ? Pm h # DEC Private Mode Set (DECSET). # Ps = 1 0 4 9 ⇒ Save cursor as in DECSC, xterm. After @@ -349,13 +455,21 @@ class TTkTerminal(TTkWidget): # 8 modes. Use this with terminfo-based applications rather # than the 4 7 mode. def _CSI_DEC_SR_1049(self, s): - if s: - self._screen_current = self._screen_alt - else: - self._screen_current = self._screen_normal + self._CSI_DEC_SR_1047(s) + self._CSI_DEC_SR_1048(s) + # CSI ? Pm h + # DEC Private Mode Set (DECSET). + # Ps = 2 0 0 4 ⇒ Set bracketed paste mode, xterm. + # CSI ? Pm l + # DEC Private Mode Reset (DECRST). + # Ps = 2 0 0 4 ⇒ Reset bracketed paste mode, xterm. + def _CSI_DEC_SR_2004(self, s): + pass _CSI_DEC_SET_RST_MAP = { - 25 : _CSI_DEC_SR_25, + 1 : _CSI_DEC_SR_1_DECCKM, + 25 : _CSI_DEC_SR_25_DECTCEM, + 1047: _CSI_DEC_SR_1047, 1049: _CSI_DEC_SR_1049 } \ No newline at end of file diff --git a/TermTk/TTkWidgets/TTkTerminal/terminal_alt.py b/TermTk/TTkWidgets/TTkTerminal/terminal_alt.py index 86ab5c1a..4e753e6a 100644 --- a/TermTk/TTkWidgets/TTkTerminal/terminal_alt.py +++ b/TermTk/TTkWidgets/TTkTerminal/terminal_alt.py @@ -39,12 +39,15 @@ from TermTk.TTkAbstract.abstractscrollview import TTkAbstractScrollView, TTkAbst from TermTk.TTkWidgets.widget import TTkWidget class _TTkTerminalAltScreen(): - __slots__ = ('_lines', '_terminalCursor', '_w', '_h', '_color', '_canvas') + __slots__ = ('_lines', '_terminalCursor', + '_scrollingRegion', + '_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._scrollingRegion = (0,h) self._color = color self._canvas = TTkCanvas(width=w, height=h) @@ -55,8 +58,15 @@ class _TTkTerminalAltScreen(): return self._terminalCursor def resize(self, w, h): - self._w = w - self._h = h + ow, oh = self._w, self._h + self._w, self._h = w, h + st,sb = self._scrollingRegion + # if oh <= h: # Terminal height decreasing + # sb = min(h,oh) + # else:# Terminal height increasing + # sb = h-oh+sb + self._scrollingRegion = (st,sb) + self._scrollingRegion = (1,h) newCanvas = TTkCanvas(width=w, height=h) s = (0,0,w,h) newCanvas.paintCanvas(self._canvas,s,s,s) @@ -195,9 +205,9 @@ class _TTkTerminalAltScreen(): 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 == 1: + self._canvas.fill(char=' ', pos=(0,y),size=(x,1)) elif ps == 2: self._canvas.fill(char=' ', pos=(0,y),size=(w,1)) @@ -208,7 +218,22 @@ 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, _): + x,y = self._terminalCursor + t,b = self._scrollingRegion + w,h = self._w, self._h + bkl = h-b + l = len(self._canvas._data) + #TODO: Avoid this HACK + baseData = [' ']*w + baseColors = [TTkColor.RST]*w + bkData = self._canvas._data[-bkl:] + bkColors = self._canvas._colors[-bkl:] + self._canvas._data[y:y] = [baseData.copy() for _ in range(ps)] + self._canvas._colors[y:y] = [baseColors.copy() for _ in range(ps)] + self._canvas._data = self._canvas._data[:h-bkl] + bkData + self._canvas._colors = self._canvas._colors[:h-bkl] + bkColors + # CSI Ps M Delete Ps Line(s) (default = 1) (DL). # def _CSI_M_DL(self, ps, _): pass @@ -1084,6 +1109,8 @@ class _TTkTerminalAltScreen(): # CSI Ps ; Ps r # Set Scrolling Region [top;bottom] (default = full size of # window) (DECSTBM), VT100. + def _CSI_r_DECSTBM(self, top, bottom): + self._scrollingRegion = (top-1, bottom-1) # CSI ? Pm r # Restore DEC Private Mode Values (XTRESTORE), xterm. The value @@ -1448,21 +1475,21 @@ class _TTkTerminalAltScreen(): # Ps = 2 ⇒ host-writable. _CSI_MAP = { - '@': _CSI___ICH, - # '@': _CSI___SL, - 'A': _CSI_A_CUU, - # 'A': _CSI_A_SR, - 'B': _CSI_B_CUD, - 'C': _CSI_C_CUF, - 'D': _CSI_D_CUB, - 'E': _CSI_E_CNL, - 'F': _CSI_F_CPL, - 'G': _CSI_G_CHA, - 'H': _CSI_H_CUP, + '@': _CSI___ICH, # CSI Ps @ Insert Ps (Blank) Character(s) (default = 1) (ICH). + # '@': _CSI___SL, # + 'A': _CSI_A_CUU, # CSI Ps A Cursor Up Ps Times (default = 1) (CUU). + # 'A': _CSI_A_SR, # + 'B': _CSI_B_CUD, # CSI Ps B Cursor Down Ps Times (default = 1) (CUD). + 'C': _CSI_C_CUF, # CSI Ps C Cursor Forward Ps Times (default = 1) (CUF). + 'D': _CSI_D_CUB, # CSI Ps D Cursor Backward Ps Times (default = 1) (CUB). + 'E': _CSI_E_CNL, # CSI Ps E Cursor Next Line Ps Times (default = 1) (CNL). + 'F': _CSI_F_CPL, # CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL). + 'G': _CSI_G_CHA, # CSI Ps G Cursor Character Absolute [column] (default = [row,1]) (CHA). + 'H': _CSI_H_CUP, # CSI Ps ; Ps H Cursor Position [row;column] (default = [1,1]) (CUP). # 'I': _CSI_I_CHT, - 'J': _CSI_J_ED, - 'K': _CSI_K_EL, - # 'L': _CSI_L_IL, + 'J': _CSI_J_ED, # CSI Ps J Erase in Display (ED), VT100. [0:Below, 1:Above, 2:All, 3:SavedLines] + 'K': _CSI_K_EL, # CSI Ps K Erase in Line (EL), VT100. [0:Right, 1:Left, 2:All] + 'L': _CSI_L_IL, # CSI Ps L Insert Ps Line(s) (default = 1) (IL). # 'M': _CSI_M_DL, # 'P': _CSI_P_DCH, # 'S': _CSI_S_SU, @@ -1476,7 +1503,7 @@ class _TTkTerminalAltScreen(): # 'c': _CSI_c_Pri_DA, # 'd': _CSI_d_VPA, # 'e': _CSI_e_VPR, - 'f': _CSI_f_HVP, + 'f': _CSI_f_HVP, # CSI Ps ; Ps f Horizontal and Vertical Position [row;column] (default = [1,1]) (HVP). # 'g': _CSI_g_TBC, # 'h': _CSI_h_SM, # 'i': _CSI_i_MC, @@ -1484,6 +1511,7 @@ class _TTkTerminalAltScreen(): # 'm': _CSI_m_SGR, # 'n': _CSI_n_DSR, # 'q': _CSI_q_DECLL, + 'r': _CSI_r_DECSTBM, # CSI Ps ; Ps r Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM), VT100. # 's': _CSI_s_SCOSC, # 'u': _CSI_u_SCORC, # 'x': _CSI_x_DECREQTPARM diff --git a/TermTk/TTkWidgets/TTkTerminal/terminal_normal.py b/TermTk/TTkWidgets/TTkTerminal/terminal_normal.py index 5a6f9417..6fd14043 100644 --- a/TermTk/TTkWidgets/TTkTerminal/terminal_normal.py +++ b/TermTk/TTkWidgets/TTkTerminal/terminal_normal.py @@ -197,11 +197,11 @@ class _TTkTerminalNormalScreen(): l = len(self._lines) # y = max(0,y-l-h) if ps == 0: - self._lines[y+1:] = [TTkString()]*(l-y-1) - self._lines[y] = self._lines[y].substring(to=x) - elif ps == 1: self._lines[-h:y-1] = [TTkString()]*(y-1-l+h) self._lines[y] = TTkString(' '*x) + self._lines[y].substring(fr=x) + elif ps == 1: + self._lines[y+1:] = [TTkString()]*(l-y-1) + self._lines[y] = self._lines[y].substring(to=x) elif ps == 2: self._lines[-h:] = [TTkString()]*(h) @@ -220,9 +220,9 @@ class _TTkTerminalNormalScreen(): x,y = self._terminalCursor line = self._lines[y] if ps == 0: - self._lines[y] = TTkString(' '*x) + self._lines[y].substring(fr=x) - elif ps == 1: self._lines[y] = line.substring(to=x) + elif ps == 1: + self._lines[y] = TTkString(' '*x) + self._lines[y].substring(fr=x) elif ps == 2: self._lines[y] = TTkString() diff --git a/tests/stupid.ansi.test.sh b/tests/stupid.ansi.test.sh index 0996ce13..75953857 100755 --- a/tests/stupid.ansi.test.sh +++ b/tests/stupid.ansi.test.sh @@ -2,39 +2,45 @@ echo -n -e "\033[2J\033[0;0H" -echo "(0, 0) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 0) n o p q r s t u v w x y z A B C D E F G H (100, 0) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 1) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 1) n o p q r s t u v w x y z A B C D E F G H (100, 1) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 2) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 2) n o p q r s t u v w x y z A B C D E F G H (100, 2) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 3) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 3) n o p q r s t u v w x y z A B C D E F G H (100, 3) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 4) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 4) n o p q r s t u v w x y z A B C D E F G H (100, 4) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 5) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 5) n o p q r s t u v w x y z A B C D E F G H (100, 5) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 6) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 6) n o p q r s t u v w x y z A B C D E F G H (100, 6) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 7) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 7) n o p q r s t u v w x y z A B C D E F G H (100, 7) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 8) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 8) n o p q r s t u v w x y z A B C D E F G H (100, 8) I J K L M N O P Q R S T U V W X Y Z" -echo "(0, 9) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 9) n o p q r s t u v w x y z A B C D E F G H (100, 9) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,10) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,10) n o p q r s t u v w x y z A B C D E F G H (100,10) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,11) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,11) n o p q r s t u v w x y z A B C D E F G H (100,11) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,12) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,12) n o p q r s t u v w x y z A B C D E F G H (100,12) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,13) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,13) n o p q r s t u v w x y z A B C D E F G H (100,13) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,14) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,14) n o p q r s t u v w x y z A B C D E F G H (100,14) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,15) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,15) n o p q r s t u v w x y z A B C D E F G H (100,15) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,16) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,16) n o p q r s t u v w x y z A B C D E F G H (100,16) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,17) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,17) n o p q r s t u v w x y z A B C D E F G H (100,17) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,18) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,18) n o p q r s t u v w x y z A B C D E F G H (100,18) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,19) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,19) n o p q r s t u v w x y z A B C D E F G H (100,19) I J K L M N O P Q R S T U V W X Y Z" -echo "(0,20) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,20) n o p q r s t u v w x y z A B C D E F G H (100,20) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,21) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,21) n o p q r s t u v w x y z A B C D E F G H (100,21) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,22) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,22) n o p q r s t u v w x y z A B C D E F G H (100,22) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,23) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,23) n o p q r s t u v w x y z A B C D E F G H (100,23) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,24) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,24) n o p q r s t u v w x y z A B C D E F G H (100,24) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,25) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,25) n o p q r s t u v w x y z A B C D E F G H (100,25) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,26) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,26) n o p q r s t u v w x y z A B C D E F G H (100,26) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,27) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,27) n o p q r s t u v w x y z A B C D E F G H (100,27) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,28) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,28) n o p q r s t u v w x y z A B C D E F G H (100,28) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,29) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,29) n o p q r s t u v w x y z A B C D E F G H (100,29) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,30) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,30) n o p q r s t u v w x y z A B C D E F G H (100,30) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,31) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,31) n o p q r s t u v w x y z A B C D E F G H (100,31) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,32) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,32) n o p q r s t u v w x y z A B C D E F G H (100,32) I J K L M N O P Q R S T U V W X Y Z" -# echo "(0,33) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,33) n o p q r s t u v w x y z A B C D E F G H (100,33) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[1;1H" "(0, 0) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 0) n o p q r s t u v w x y z A B C D E F G H (100, 0) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[2;1H" "(0, 1) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 1) n o p q r s t u v w x y z A B C D E F G H (100, 1) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[3;1H" "(0, 2) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 2) n o p q r s t u v w x y z A B C D E F G H (100, 2) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[4;1H" "(0, 3) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 3) n o p q r s t u v w x y z A B C D E F G H (100, 3) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[5;1H" "(0, 4) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 4) n o p q r s t u v w x y z A B C D E F G H (100, 4) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[6;1H" "(0, 5) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 5) n o p q r s t u v w x y z A B C D E F G H (100, 5) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[7;1H" "(0, 6) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 6) n o p q r s t u v w x y z A B C D E F G H (100, 6) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[8;1H" "(0, 7) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 7) n o p q r s t u v w x y z A B C D E F G H (100, 7) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[9;1H" "(0, 8) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 8) n o p q r s t u v w x y z A B C D E F G H (100, 8) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[10;1H" "(0, 9) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50, 9) n o p q r s t u v w x y z A B C D E F G H (100, 9) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[11;1H" "(0,10) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,10) n o p q r s t u v w x y z A B C D E F G H (100,10) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[12;1H" "(0,11) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,11) n o p q r s t u v w x y z A B C D E F G H (100,11) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[13;1H" "(0,12) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,12) n o p q r s t u v w x y z A B C D E F G H (100,12) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[14;1H" "(0,13) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,13) n o p q r s t u v w x y z A B C D E F G H (100,13) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[15;1H" "(0,14) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,14) n o p q r s t u v w x y z A B C D E F G H (100,14) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[16;1H" "(0,15) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,15) n o p q r s t u v w x y z A B C D E F G H (100,15) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[17;1H" "(0,16) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,16) n o p q r s t u v w x y z A B C D E F G H (100,16) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[18;1H" "(0,17) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,17) n o p q r s t u v w x y z A B C D E F G H (100,17) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[19;1H" "(0,18) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,18) n o p q r s t u v w x y z A B C D E F G H (100,18) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[20;1H" "(0,19) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,19) n o p q r s t u v w x y z A B C D E F G H (100,19) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[21;1H" "(0,20) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,20) n o p q r s t u v w x y z A B C D E F G H (100,20) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[22;1H" "(0,21) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,21) n o p q r s t u v w x y z A B C D E F G H (100,21) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[23;1H" "(0,22) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,22) n o p q r s t u v w x y z A B C D E F G H (100,22) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[24;1H" "(0,23) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,23) n o p q r s t u v w x y z A B C D E F G H (100,23) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[25;1H" "(0,24) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,24) n o p q r s t u v w x y z A B C D E F G H (100,24) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[26;1H" "(0,25) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,25) n o p q r s t u v w x y z A B C D E F G H (100,25) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[27;1H" "(0,26) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,26) n o p q r s t u v w x y z A B C D E F G H (100,26) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[28;1H" "(0,27) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,27) n o p q r s t u v w x y z A B C D E F G H (100,27) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[29;1H" "(0,28) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,28) n o p q r s t u v w x y z A B C D E F G H (100,28) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[30;1H" "(0,29) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,29) n o p q r s t u v w x y z A B C D E F G H (100,29) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[31;1H" "(0,30) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,30) n o p q r s t u v w x y z A B C D E F G H (100,30) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[32;1H" "(0,31) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,31) n o p q r s t u v w x y z A B C D E F G H (100,31) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[33;1H" "(0,32) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,32) n o p q r s t u v w x y z A B C D E F G H (100,32) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[34;1H" "(0,33) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,33) n o p q r s t u v w x y z A B C D E F G H (100,33) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[35;1H" "(0,34) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,34) n o p q r s t u v w x y z A B C D E F G H (100,34) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[36;1H" "(0,35) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,35) n o p q r s t u v w x y z A B C D E F G H (100,35) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[37;1H" "(0,36) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,36) n o p q r s t u v w x y z A B C D E F G H (100,36) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[38;1H" "(0,37) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,37) n o p q r s t u v w x y z A B C D E F G H (100,37) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[39;1H" "(0,38) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,38) n o p q r s t u v w x y z A B C D E F G H (100,38) I J K L M N O P Q R S T U V W X Y Z" +echo -n -e "\033[40;1H" "(0,39) 1 2 3 4 5 6 7 8 9 0 a b c d e f g j k l m (50,39) n o p q r s t u v w x y z A B C D E F G H (100,39) I J K L M N O P Q R S T U V W X Y Z" -echo -e "abcdefg--->\033[10;50H<-Eugenio->\033[${1}${2}${3}${4}${5}${6}${7}<----hijklm\n\n\n\n" \ No newline at end of file +echo -n -e "abcdefg--->\033[10;50H<-Eugenio->\033[${1}${2}${3}${4}${5}${6}${7}<----hijklm" \ No newline at end of file diff --git a/tests/test.input.raw.py b/tests/test.input.raw.py index bc362e6a..d47f6066 100755 --- a/tests/test.input.raw.py +++ b/tests/test.input.raw.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import sys, os, select +import sys, os, select, signal import logging try: import fcntl, termios, tty @@ -31,10 +31,10 @@ except Exception as e: exit(1) sys.path.append(os.path.join(sys.path[0],'..')) -from TermTk import TTkLog, TTkK, TTkInput, TTkTerm +from TermTk import TTkTerm -TTkLog.info("Retrieve Keyboard, Mouse press/drag/wheel Events") -TTkLog.info("Press q or to exit") +print("Retrieve Keyboard, Mouse press/drag/wheel Events") +print("Press q or to exit") TTkTerm.push(TTkTerm.Mouse.ON) # TTkTerm.push(TTkTerm.Mouse.DIRECT_ON) @@ -44,6 +44,12 @@ TTkTerm.setEcho(False) _attr = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin) +# Capture Terminal Resize: +def _sigwinch(a,b): + print(f"SIGWINCH: {os.get_terminal_size()=} {a=} {b=}") + +signal.signal(signal.SIGWINCH, _sigwinch) + def read(): rlist, _, _ = select.select( [sys.stdin], [], [] ) @@ -74,7 +80,7 @@ def read_new(): else: for ch in stdinRead: yield ch - +# print("--->\033[?1h<---") try: for stdinRead in read_new(): print(f"{stdinRead=}") diff --git a/tests/test.pty.006.terminal.02.py b/tests/test.pty.006.terminal.02.py index 419e7921..8b78aee6 100755 --- a/tests/test.pty.006.terminal.02.py +++ b/tests/test.pty.006.terminal.02.py @@ -41,20 +41,25 @@ import os import pty import sys import threading +import argparse from select import select - sys.path.append(os.path.join(sys.path[0],'..')) import TermTk as ttk -ttk.TTkLog.use_default_file_logging() +parser = argparse.ArgumentParser() +parser.add_argument('-d', help='Debug (Add LogViewer Panel)', action='store_true') +args = parser.parse_args() + +# ttk.TTkLog.use_default_file_logging() root = ttk.TTk(layout=ttk.TTkGridLayout()) split = ttk.TTkSplitter(parent=root, orientation=ttk.TTkK.VERTICAL) split.addItem(top := ttk.TTkLayout()) -split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log', size=20) +if args.d: + split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log', size=20) quitBtn = ttk.TTkButton(text="QUIT", border=True) quitBtn.clicked.connect(ttk.TTkHelper.quit)