Browse Source

Improved the character attributes handlers

pull/172/head
Eugenio Parodi 3 years ago
parent
commit
361ed52fe0
  1. 53
      TermTk/TTkCore/TTkTerm/colors.py
  2. 37
      TermTk/TTkWidgets/TTkTerminal/terminal.py
  3. 2
      tests/test.pty.006.terminal.03.py
  4. 161
      tests/timeit/16.dict.02.get.py
  5. 0
      tests/timeit/17.conditional.01.py

53
TermTk/TTkCore/TTkTerm/colors.py

@ -30,12 +30,35 @@ import re
from .colors_ansi_map import ansiMap256, ansiMap16
class TTkTermColor():
BOLD = 0x01
ITALIC = 0x02
UNDERLINE = 0x04
STRIKETROUGH = 0x08
BLINKING = 0x10
REVERSED = 0x20
BOLD = 0x01 # <ESC>[1m
FAINT = 0x02 # <ESC>[2m
ITALIC = 0x04 # <ESC>[3m
UNDERLINE = 0x08 # <ESC>[4m
BLINKING = 0x10 # <ESC>[5m
REVERSED = 0x20 # <ESC>[7m
HIDDEN = 0x40 # <ESC>[8m
STRIKETROUGH = 0x80 # <ESC>[9m
SGR_SET = { # CSI Pm m Character Attributes (SGR).
# Ps = 0 ⇒ Normal (default), VT100.
1: BOLD , # Ps = 1 ⇒ Bold, VT100.
2: FAINT , # Ps = 2 ⇒ Faint, decreased intensity, ECMA-48 2nd.
3: ITALIC , # Ps = 3 ⇒ Italicized, ECMA-48 2nd.
4: UNDERLINE , # Ps = 4 ⇒ Underlined, VT100.
5: BLINKING , # Ps = 5 ⇒ Blink, VT100. - This appears as Bold in X11R6 xterm.
7: REVERSED , # Ps = 7 ⇒ Inverse, VT100.
8: HIDDEN , # Ps = 8 ⇒ Invisible, i.e., hidden, ECMA-48 2nd, VT300.
9: STRIKETROUGH } # Ps = 9 ⇒ Crossed-out characters, ECMA-48 3rd.
SGR_RST = { # CSI Pm m Character Attributes (SGR).
# Ps = 2 1 ⇒ Doubly-underlined, ECMA-48 3rd.
22: ~(BOLD|FAINT), # Ps = 2 2 ⇒ Normal (neither bold nor faint), ECMA-48 3rd.
23: ~ITALIC, # Ps = 2 3 ⇒ Not italicized, ECMA-48 3rd.
24: ~UNDERLINE, # Ps = 2 4 ⇒ Not underlined, ECMA-48 3rd.
25: ~BLINKING, # Ps = 2 5 ⇒ Steady (not blinking), ECMA-48 3rd.
27: ~REVERSED, # Ps = 2 7 ⇒ Positive (not inverse), ECMA-48 3rd.
28: ~HIDDEN, # Ps = 2 8 ⇒ Visible, i.e., not hidden, ECMA-48 3rd, VT300.
29: ~STRIKETROUGH } # Ps = 2 9 ⇒ Not crossed-out, ECMA-48 3rd.
@staticmethod
def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, clean:bool=False):
@ -51,17 +74,20 @@ class TTkTermColor():
if mod & TTkTermColor.BOLD:
ret.append('1')
if mod & TTkTermColor.FAINT:
ret.append('2')
if mod & TTkTermColor.ITALIC:
ret.append('3')
if mod & TTkTermColor.UNDERLINE:
ret.append('4')
if mod & TTkTermColor.STRIKETROUGH:
ret.append('9')
if mod & TTkTermColor.BLINKING:
ret.append('5')
if mod & TTkTermColor.REVERSED:
ret.append('7')
if mod & TTkTermColor.HIDDEN:
ret.append('8')
if mod & TTkTermColor.STRIKETROUGH:
ret.append('9')
if ret:
return f'\033[{";".join(str(x) for x in ret)}m'
else:
@ -111,11 +137,10 @@ class TTkTermColor():
bg = None
mod = 0
clean = True
elif s==1: mod |= TTkTermColor.BOLD
elif s==3: mod |= TTkTermColor.ITALIC
elif s==4: mod |= TTkTermColor.UNDERLINE
elif s==9: mod |= TTkTermColor.STRIKETROUGH
elif s==5: mod |= TTkTermColor.BLINKING
elif _sgr:=TTkTermColor.SGR_SET.get(s,None):
mod |= _sgr
elif _sgr:=TTkTermColor.SGR_RST.get(s,None):
mod &= _sgr
return fg,bg,mod,clean

37
TermTk/TTkWidgets/TTkTerminal/terminal.py

@ -219,6 +219,8 @@ class TTkTerminal(TTkWidget):
yield out
def loop(self, _):
SGR_SET = TTkTermColor.SGR_SET # Precacing those variables to
SGR_RST = TTkTermColor.SGR_RST # speedup the search
inputgenerator = self._inputGenerator()
for out in inputgenerator:
sout = out.split('\033')
@ -302,12 +304,12 @@ class TTkTerminal(TTkWidget):
bg = ansiMap256.get(int(values.pop(0)))
if t == 2:# 24 bit bg
bg = (int(values.pop(0)),int(values.pop(0)),int(values.pop(0)))
elif s==1: mod |= TTkTermColor.BOLD
elif s==3: mod |= TTkTermColor.ITALIC
elif s==4: mod |= TTkTermColor.UNDERLINE
elif s==9: mod |= TTkTermColor.STRIKETROUGH
elif s==5: mod |= TTkTermColor.BLINKING
elif s==7: mod |= TTkTermColor.REVERSED
elif _sgr:=SGR_SET.get(s,None):
mod |= _sgr
elif _sgr:=SGR_RST.get(s,None):
mod &= _sgr
else:
_termLog.warn(f"Unhandled color: <ESC>{slice}")
color = TTkColor(fg=fg, bg=bg, mod=mod, clean=clean)
self._screen_alt.setColor(color)
@ -551,7 +553,7 @@ class TTkTerminal(TTkWidget):
TTkK.WHEEL_Up: ( 0,'M'),
TTkK.WHEEL_Down:( 1,'M')}.get(
evt.evt,(0,'M'))
# _termLog.error(f'Mouse: <ESC>[<{k+km};{x};{y}{pr}')
self._inout.write(f'\033[<{k+km};{x};{y}{pr}'.encode())
else:
head = {
@ -566,16 +568,20 @@ class TTkTerminal(TTkWidget):
bah = bytearray(head)
bah.append((x+32)%0xff)
bah.append((y+32)%0xff)
# _termLog.error(f'Mouse: '+bah.decode().replace('\033','<ESC>'))
self._inout.write(bah)
return True
def mousePressEvent(self, evt): return self._sendMouse(evt)
def mouseReleaseEvent(self, evt): return self._sendMouse(evt)
def mouseDragEvent(self, evt): return self._sendMouse(evt)
def mouseMoveEvent(self, evt): return self._sendMouse(evt)
def wheelEvent(self, evt): return self._sendMouse(evt)
def mouseTapEvent(self, evt): return self._sendMouse(evt)
def mouseDoubleClickEvent(self, evt): return self._sendMouse(evt)
def mouseMoveEvent(self, evt):
if self._mouse.reportMove:
return self._sendMouse(evt)
return True
def paintEvent(self, canvas: TTkCanvas):
w,h = self.size()
@ -709,6 +715,20 @@ class TTkTerminal(TTkWidget):
self._mouse.reportMove = False
_termLog.info(f"1002 Mouse Tracking {s=}")
# CSI ? Pm h
# DEC Private Mode Set (DECSET).
# Ps = 1 0 0 3 ⇒ Use All Motion Mouse Tracking, xterm. See
# the section Any-event tracking.
# CSI ? Pm l
# DEC Private Mode Reset (DECRST).
# Ps = 1 0 0 3 ⇒ Don't use All Motion Mouse Tracking, xterm.
# See the section Any-event tracking.
def _CSI_DEC_SR_1003(self, s):
self._mouse.reportPress = s
self._mouse.reportDrag = s
self._mouse.reportMove = s
_termLog.info(f"1003 Mouse Tracking {s=}")
# CSI ? Pm h
# DEC Private Mode Set (DECSET).
# Ps = 1 0 0 6 ⇒ Enable SGR Mouse Mode, xterm.
@ -785,6 +805,7 @@ class TTkTerminal(TTkWidget):
25 : _CSI_DEC_SR_25_DECTCEM,
1000: _CSI_DEC_SR_1000,
1002: _CSI_DEC_SR_1002,
1003: _CSI_DEC_SR_1003,
1006: _CSI_DEC_SR_1006,
1015: _CSI_DEC_SR_1015,
1047: _CSI_DEC_SR_1047,

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

@ -52,7 +52,7 @@ parser.add_argument('-d', help='Debug (Add LogViewer Panel)', action='store_t
args = parser.parse_args()
# ttk.TTkLog.use_default_file_logging()
root = ttk.TTk(layout=ttk.TTkGridLayout())
root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True)
split = ttk.TTkSplitter(parent=root, orientation=ttk.TTkK.VERTICAL)

161
tests/timeit/16.dict.02.get.py

@ -0,0 +1,161 @@
#!/usr/bin/env python3
# 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.
import sys, os
import timeit
sys.path.append(os.path.join(sys.path[0],'../..'))
from TermTk import TTkTermColor
testInput = [0,1,2,3,4,5,6,7,8,9,10,20,21,22,23,24,25,26,27,28,29,30,31]
def test1(ttt=testInput):
mod = 0
for s in ttt:
if s==1: mod |= TTkTermColor.BOLD
elif s==2: mod += TTkTermColor.FAINT
elif s==3: mod += TTkTermColor.ITALIC
elif s==4: mod += TTkTermColor.UNDERLINE
elif s==5: mod += TTkTermColor.BLINKING
elif s==7: mod += TTkTermColor.REVERSED
elif s==8: mod += TTkTermColor.HIDDEN
elif s==9: mod += TTkTermColor.STRIKETROUGH
elif s==22: mod += ~(TTkTermColor.BOLD|TTkTermColor.FAINT)
elif s==23: mod += ~TTkTermColor.ITALIC
elif s==24: mod += ~TTkTermColor.UNDERLINE
elif s==25: mod += ~TTkTermColor.BLINKING
elif s==27: mod += ~TTkTermColor.REVERSED
elif s==28: mod += ~TTkTermColor.HIDDEN
elif s==29: mod += ~TTkTermColor.STRIKETROUGH
return mod
def test2(ttt=testInput):
mod = 0
for s in ttt:
if mm := {
1: TTkTermColor.BOLD ,
2: TTkTermColor.FAINT ,
3: TTkTermColor.ITALIC ,
4: TTkTermColor.UNDERLINE ,
5: TTkTermColor.BLINKING ,
7: TTkTermColor.REVERSED ,
8: TTkTermColor.HIDDEN ,
9: TTkTermColor.STRIKETROUGH
}.get(s,None):
mod += mm
elif mm := {
22: ~(TTkTermColor.BOLD|TTkTermColor.FAINT),
23: ~TTkTermColor.ITALIC,
24: ~TTkTermColor.UNDERLINE,
25: ~TTkTermColor.BLINKING,
27: ~TTkTermColor.REVERSED,
28: ~TTkTermColor.HIDDEN,
29: ~TTkTermColor.STRIKETROUGH,
}.get(s,None):
mod += mm
return mod
t3_or = {
1: TTkTermColor.BOLD ,
2: TTkTermColor.FAINT ,
3: TTkTermColor.ITALIC ,
4: TTkTermColor.UNDERLINE ,
5: TTkTermColor.BLINKING ,
7: TTkTermColor.REVERSED ,
8: TTkTermColor.HIDDEN ,
9: TTkTermColor.STRIKETROUGH }
t3_and = {
22: ~(TTkTermColor.BOLD|TTkTermColor.FAINT),
23: ~TTkTermColor.ITALIC,
24: ~TTkTermColor.UNDERLINE,
25: ~TTkTermColor.BLINKING,
27: ~TTkTermColor.REVERSED,
28: ~TTkTermColor.HIDDEN,
29: ~TTkTermColor.STRIKETROUGH }
def test3(ttt=testInput):
mod = 0
for s in ttt:
if mm := t3_or.get(s,None):
mod += mm
elif mm := t3_and.get(s,None):
mod += mm
return mod
class t4():
t4_or = {
1: TTkTermColor.BOLD ,
2: TTkTermColor.FAINT ,
3: TTkTermColor.ITALIC ,
4: TTkTermColor.UNDERLINE ,
5: TTkTermColor.BLINKING ,
7: TTkTermColor.REVERSED ,
8: TTkTermColor.HIDDEN ,
9: TTkTermColor.STRIKETROUGH }
t4_and = {
22: ~(TTkTermColor.BOLD|TTkTermColor.FAINT),
23: ~TTkTermColor.ITALIC,
24: ~TTkTermColor.UNDERLINE,
25: ~TTkTermColor.BLINKING,
27: ~TTkTermColor.REVERSED,
28: ~TTkTermColor.HIDDEN,
29: ~TTkTermColor.STRIKETROUGH }
def test4(ttt=testInput):
mod = 0
for s in ttt:
if mm := t4.t4_or.get(s,None):
mod += mm
elif mm := t4.t4_and.get(s,None):
mod += mm
return mod
def test5(ttt=testInput):
mod = 0
t5_or = t4.t4_or
t5_and = t4.t4_and
for s in ttt:
if mm := t5_or.get(s,None):
mod += mm
elif mm := t5_and.get(s,None):
mod += mm
return mod
def test6(): return 1
def test7(): return 1
def test8(): return 1
def test9(): return 1
loop = 150000
a={}
iii = 1
while (testName := f'test{iii}') and (testName in globals()):
result = timeit.timeit(f'{testName}(*a)', globals=globals(), number=loop)
# print(f"test{iii}) fps {loop / result :.3f} - s {result / loop:.10f} - {result / loop} {globals()[testName](*a)}")
print(f"test{iii:02}) | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}")
iii+=1

0
tests/timeit/conditional.py → tests/timeit/17.conditional.01.py

Loading…
Cancel
Save