From 1d86047db2b7f85e3c9519c56364c2697b90a760 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Mon, 18 Dec 2023 09:30:32 +0000 Subject: [PATCH 1/7] Initial drop of the link escape sequence --- TermTk/TTkCore/TTkTerm/colors.py | 12 ++++++-- TermTk/TTkCore/canvas.py | 4 +++ TermTk/TTkCore/color.py | 29 ++++++++------------ docs/MDNotes/Resources.md | 3 ++ tests/t.ui/test.ui.031.link.py | 47 ++++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 20 deletions(-) create mode 100755 tests/t.ui/test.ui.031.link.py diff --git a/TermTk/TTkCore/TTkTerm/colors.py b/TermTk/TTkCore/TTkTerm/colors.py index 1c6f7d8a..762125ec 100644 --- a/TermTk/TTkCore/TTkTerm/colors.py +++ b/TermTk/TTkCore/TTkTerm/colors.py @@ -61,8 +61,14 @@ class TTkTermColor(): 29: ~STRIKETROUGH } # Ps = 2 9 ⇒ Not crossed-out, ECMA-48 3rd. @staticmethod - def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False): + def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False, cleanLink:bool=False): ret = [] + linkAnsi = "" + + if cleanLink: + linkAnsi = "\033]8;;\033\\" + if link: + linkAnsi = f"\033]8;;{link}\033\\" if clean: ret.append(0) @@ -89,9 +95,9 @@ class TTkTermColor(): if mod & TTkTermColor.STRIKETROUGH: ret.append('9') if ret: - return f'\033[{";".join(str(x) for x in ret)}m' + return f'\033[{";".join(str(x) for x in ret)}m{linkAnsi}' else: - return '\033[0m' + return '\033[0m'+linkAnsi def _256toRgb(val): pass diff --git a/TermTk/TTkCore/canvas.py b/TermTk/TTkCore/canvas.py index 7ffc0543..46cf7cd0 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -750,6 +750,8 @@ class TTkCanvas: empty=True # Reset the color at the end TTkTerm.push(TTkColor.RST) + if lastcolor._link: + TTkTerm.push("\033]8;;\033\\") # TTkTerm.flush() # Switch the buffer self._bufferedData, self._bufferedColors = data, colors @@ -800,6 +802,8 @@ class TTkCanvas: empty=True # Reset the color at the end TTkTerm.push(TTkColor.RST) + if lastcolor._link: + TTkTerm.push("\033]8;;\033\\") # Switch the buffer self._bufferedData, self._bufferedColors = data, colors self._data, self._colors = oldData, oldColors \ No newline at end of file diff --git a/TermTk/TTkCore/color.py b/TermTk/TTkCore/color.py index 19b4bae7..081f98fa 100644 --- a/TermTk/TTkCore/color.py +++ b/TermTk/TTkCore/color.py @@ -61,14 +61,15 @@ from TermTk.TTkCore.helper import TTkHelper # [49m 2.53 set background color to default (black) class _TTkColor: - __slots__ = ('_fg','_bg','_mod', '_colorMod', '_link', '_buffer', '_clean') + __slots__ = ('_fg','_bg','_mod', '_colorMod', '_link', '_buffer', '_clean', '_cleanLink') _fg: tuple; _bg: tuple; _mod: int - def __init__(self, fg:tuple=None, bg:tuple=None, mod:int=0, colorMod=None, link:str='', clean=False): + def __init__(self, fg:tuple=None, bg:tuple=None, mod:int=0, colorMod=None, link:str='', clean=False, cleanLink=False): self._fg = fg self._bg = bg self._mod = mod self._link = link self._clean = clean or not (fg or bg or mod) + self._cleanLink = cleanLink self._colorMod = colorMod self._buffer = None @@ -184,7 +185,7 @@ class _TTkColor: if not self._buffer: self._buffer = TTkHelper.Color.rgb2ansi( fg=self._fg, bg=self._bg, mod=self._mod, - link=self._link, clean=self._clean) + link=self._link, clean=self._clean, cleanLink=self._cleanLink) return self._buffer def __eq__(self, other): @@ -198,25 +199,17 @@ class _TTkColor: # self | other def __or__(self, other): # TTkLog.debug("__add__") - if other._clean: - return other.copy() - clean = self._clean - fg: str = self._fg or other._fg - bg: str = self._bg or other._bg - mod: str = self._mod + other._mod - link:str = self._link or other._link - colorMod = self._colorMod or other._colorMod - return TTkColor( - fg=fg, bg=bg, mod=mod, - colorMod=colorMod, link=link, - clean=clean) + return self + other # self + other def __add__(self, other): # TTkLog.debug("__add__") if other._clean: - return other.copy() + ret = other.copy() + ret._cleanLink |= self._cleanLink + return ret clean = self._clean + cleanLink = self._cleanLink fg: str = other._fg or self._fg bg: str = other._bg or self._bg mod: str = self._mod + other._mod @@ -225,7 +218,7 @@ class _TTkColor: return TTkColor( fg=fg, bg=bg, mod=mod, colorMod=colorMod, link=link, - clean=clean) + clean=clean, cleanLink=cleanLink) def __sub__(self, other): # TTkLog.debug("__sub__") @@ -236,6 +229,7 @@ class _TTkColor: self._mod != other._mod ): ret = self.copy() ret._clean = True + ret._cleanLink = self._link != other._link return ret return self @@ -256,6 +250,7 @@ class _TTkColor: ret._mod = self._mod ret._link = self._link ret._clean = self._clean + ret._cleanLink = self._cleanLink if modifier and self._colorMod: ret._colorMod = self._colorMod.copy() return ret diff --git a/docs/MDNotes/Resources.md b/docs/MDNotes/Resources.md index 9ac980e0..c089748f 100644 --- a/docs/MDNotes/Resources.md +++ b/docs/MDNotes/Resources.md @@ -26,6 +26,9 @@ https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#file-ansi-md https://conemu.github.io/en/AnsiEscapeCodes.html #### Hyperlink https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda +```bash +printf '\e]8;;http://example.com\e\\This is a link\e]8;;\e\\\n' +``` #### ANSI 16 256 24bit color conversion https://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html #### ANSI Colors diff --git a/tests/t.ui/test.ui.031.link.py b/tests/t.ui/test.ui.031.link.py new file mode 100755 index 00000000..b5a5040a --- /dev/null +++ b/tests/t.ui/test.ui.031.link.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 Eugenio Parodi +# +# 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 + + +sys.path.append(os.path.join(sys.path[0],'../..')) +import TermTk as ttk + +class WidLink1(ttk.TTkWidget): + def paintEvent(self, canvas: ttk.TTkCanvas): + canvas.drawText(pos=(0,0),text=ttk.TTkString('Link1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FFFF00', link="http://www.google.com"))) + canvas.drawText(pos=(0,1),text=ttk.TTkString('Link2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FFFF', link="http://www.reddit.com"))) + canvas.drawText(pos=(0,2),text=ttk.TTkString('Link3abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF00FF', link="http://www.github.com"))) + canvas.drawText(pos=(0,3),text=ttk.TTkString('Link4abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF0000', link="http://www.example.com"))) + canvas.drawText(pos=(0,4),text=ttk.TTkString('Link5abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FF00', link="file:///home/"))) + return super().paintEvent(canvas) + +root = ttk.TTk() + +win1 = ttk.TTkWindow(parent=root, layout=ttk.TTkGridLayout(), size=(50,10)) +WidLink1(parent=win1) +win1 = ttk.TTkWindow(parent=root, layout=ttk.TTkGridLayout(), size=(50,10)) +WidLink1(parent=win1) + +root.mainloop() \ No newline at end of file From 79339bf4fa0debbca2f1bce0ef1d546b7739a34b Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Mon, 18 Dec 2023 18:02:08 +0000 Subject: [PATCH 2/7] improved test --- tests/t.ui/test.ui.031.link.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/t.ui/test.ui.031.link.py b/tests/t.ui/test.ui.031.link.py index b5a5040a..fe30bd83 100755 --- a/tests/t.ui/test.ui.031.link.py +++ b/tests/t.ui/test.ui.031.link.py @@ -30,11 +30,12 @@ import TermTk as ttk class WidLink1(ttk.TTkWidget): def paintEvent(self, canvas: ttk.TTkCanvas): - canvas.drawText(pos=(0,0),text=ttk.TTkString('Link1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FFFF00', link="http://www.google.com"))) - canvas.drawText(pos=(0,1),text=ttk.TTkString('Link2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FFFF', link="http://www.reddit.com"))) - canvas.drawText(pos=(0,2),text=ttk.TTkString('Link3abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF00FF', link="http://www.github.com"))) - canvas.drawText(pos=(0,3),text=ttk.TTkString('Link4abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF0000', link="http://www.example.com"))) - canvas.drawText(pos=(0,4),text=ttk.TTkString('Link5abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FF00', link="file:///home/"))) + canvas.drawText(pos=( 0,0),text=ttk.TTkString('Link1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FFFF00', link="http://www.google.com"))) + canvas.drawText(pos=( 0,1),text=ttk.TTkString('Link2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FFFF', link="http://www.reddit.com"))) + canvas.drawText(pos=( 0,2),text=ttk.TTkString('Link3abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF00FF', link="http://www.github.com"))) + canvas.drawText(pos=( 0,3),text=ttk.TTkString('Link4abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#FF0000', link="http://www.example.com"))) + canvas.drawText(pos=( 0,4),text=ttk.TTkString('Link5abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',ttk.TTkColor.fg('#00FF00', link="file:///home/"))) + canvas.drawText(pos=(20,3),text=ttk.TTkString('',ttk.TTkColor.fg('#0000FF', link="http:///www.python.com/"))) return super().paintEvent(canvas) root = ttk.TTk() From 9c1fad229c86a69e53714c05840a6ed91225cb37 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sat, 16 Nov 2024 13:42:25 +0000 Subject: [PATCH 3/7] Added missing __all__ --- TermTk/TTkCore/TTkTerm/colors_ansi_map.py | 2 ++ TermTk/TTkCore/TTkTerm/input.py | 6 ++++-- TermTk/TTkCore/TTkTerm/term_base.py | 2 ++ TermTk/TTkCore/drivers/unix_thread.py | 2 ++ TermTk/TTkCore/timer_pyodide.py | 2 ++ TermTk/TTkCore/timer_unix.py | 2 ++ TermTk/TTkTheme/draw_ascii.py | 2 ++ TermTk/TTkTheme/draw_utf8.py | 2 ++ TermTk/TTkTheme/fileicon_ascii.py | 2 ++ TermTk/TTkTheme/fileicon_nerd.py | 3 ++- TermTk/TTkTheme/fileicon_utf8.py | 2 ++ TermTk/TTkTypes/viewitem.py | 1 + TermTk/TTkUiTools/properties/about.py | 2 ++ TermTk/TTkUiTools/properties/graph.py | 1 + TermTk/TTkUiTools/properties/image.py | 2 ++ TermTk/TTkUiTools/properties/listwidget.py | 2 ++ TermTk/TTkUiTools/properties/menubar.py | 2 ++ TermTk/TTkUiTools/properties/progressbar.py | 2 ++ TermTk/TTkUiTools/properties/scrollarea.py | 1 + TermTk/TTkUiTools/properties/spacer.py | 1 + TermTk/TTkUiTools/properties/tabwidget.py | 2 ++ TermTk/TTkWidgets/TTkPickers/dateTimePicker.py | 1 + TermTk/TTkWidgets/TTkTerminal/mode.py | 2 ++ 23 files changed, 43 insertions(+), 3 deletions(-) diff --git a/TermTk/TTkCore/TTkTerm/colors_ansi_map.py b/TermTk/TTkCore/TTkTerm/colors_ansi_map.py index d98fc4f7..09921e9e 100644 --- a/TermTk/TTkCore/TTkTerm/colors_ansi_map.py +++ b/TermTk/TTkCore/TTkTerm/colors_ansi_map.py @@ -26,6 +26,8 @@ # https://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html # https://en.wikipedia.org/wiki/ANSI_escape_code#Colors +__all__ = ['ansiMap16', 'ansiMap256'] + ansiMap16 = { # xterm Color Map # fg diff --git a/TermTk/TTkCore/TTkTerm/input.py b/TermTk/TTkCore/TTkTerm/input.py index 44a69504..2c595145 100644 --- a/TermTk/TTkCore/TTkTerm/input.py +++ b/TermTk/TTkCore/TTkTerm/input.py @@ -20,5 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# from .input_mono import * -from .input_thread import * \ No newline at end of file +__all__ = ['TTkInput'] + +# from .input_mono import TTkInput +from .input_thread import TTkInput \ No newline at end of file diff --git a/TermTk/TTkCore/TTkTerm/term_base.py b/TermTk/TTkCore/TTkTerm/term_base.py index 8054f3e7..a08ba7c9 100644 --- a/TermTk/TTkCore/TTkTerm/term_base.py +++ b/TermTk/TTkCore/TTkTerm/term_base.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTermBase'] + import os class TTkTermBase(): diff --git a/TermTk/TTkCore/drivers/unix_thread.py b/TermTk/TTkCore/drivers/unix_thread.py index c5502995..901decdd 100644 --- a/TermTk/TTkCore/drivers/unix_thread.py +++ b/TermTk/TTkCore/drivers/unix_thread.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] + import sys, os from select import select import threading diff --git a/TermTk/TTkCore/timer_pyodide.py b/TermTk/TTkCore/timer_pyodide.py index 342a7dc3..32427572 100644 --- a/TermTk/TTkCore/timer_pyodide.py +++ b/TermTk/TTkCore/timer_pyodide.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTimer'] + from TermTk.TTkCore.helper import TTkHelper from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal diff --git a/TermTk/TTkCore/timer_unix.py b/TermTk/TTkCore/timer_unix.py index e9d85711..68162d40 100644 --- a/TermTk/TTkCore/timer_unix.py +++ b/TermTk/TTkCore/timer_unix.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTimer'] + import threading from TermTk.TTkCore.signal import pyTTkSlot, pyTTkSignal diff --git a/TermTk/TTkTheme/draw_ascii.py b/TermTk/TTkTheme/draw_ascii.py index 8da96f1a..7f3f36fd 100644 --- a/TermTk/TTkTheme/draw_ascii.py +++ b/TermTk/TTkTheme/draw_ascii.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTheme'] + class TTkTheme(): hline = ('=','=','=') vline = ('|','|','|') diff --git a/TermTk/TTkTheme/draw_utf8.py b/TermTk/TTkTheme/draw_utf8.py index 88ffa97c..7b714a41 100644 --- a/TermTk/TTkTheme/draw_utf8.py +++ b/TermTk/TTkTheme/draw_utf8.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTheme'] + class TTkTheme(): ''' from: https://en.wikipedia.org/wiki/Box-drawing_character diff --git a/TermTk/TTkTheme/fileicon_ascii.py b/TermTk/TTkTheme/fileicon_ascii.py index bdda947e..eeb86ed7 100644 --- a/TermTk/TTkTheme/fileicon_ascii.py +++ b/TermTk/TTkTheme/fileicon_ascii.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['FileIcon'] + class FileIcon(): folderClose = '+' folderOpen = '-' diff --git a/TermTk/TTkTheme/fileicon_nerd.py b/TermTk/TTkTheme/fileicon_nerd.py index aaebf703..62db6cd8 100644 --- a/TermTk/TTkTheme/fileicon_nerd.py +++ b/TermTk/TTkTheme/fileicon_nerd.py @@ -28,10 +28,11 @@ # Extension/Matches list from: # https://github.com/ryanoasis/vim-devicons/blob/master/plugin/webdevicons.vim +__all__ = ['FileIcon'] + import re import os - class FileIcon(): folderClose = '' folderOpen = '' diff --git a/TermTk/TTkTheme/fileicon_utf8.py b/TermTk/TTkTheme/fileicon_utf8.py index 978f4d7f..8dc0fb98 100644 --- a/TermTk/TTkTheme/fileicon_utf8.py +++ b/TermTk/TTkTheme/fileicon_utf8.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['FileIcon'] + class FileIcon(): folderClose = '+' folderOpen = '-' diff --git a/TermTk/TTkTypes/viewitem.py b/TermTk/TTkTypes/viewitem.py index e69de29b..a9a2c5b3 100644 --- a/TermTk/TTkTypes/viewitem.py +++ b/TermTk/TTkTypes/viewitem.py @@ -0,0 +1 @@ +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/about.py b/TermTk/TTkUiTools/properties/about.py index 044a5b9e..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/about.py +++ b/TermTk/TTkUiTools/properties/about.py @@ -19,3 +19,5 @@ # 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. + +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/graph.py b/TermTk/TTkUiTools/properties/graph.py index ee0973b1..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/graph.py +++ b/TermTk/TTkUiTools/properties/graph.py @@ -20,3 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/image.py b/TermTk/TTkUiTools/properties/image.py index 044a5b9e..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/image.py +++ b/TermTk/TTkUiTools/properties/image.py @@ -19,3 +19,5 @@ # 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. + +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/listwidget.py b/TermTk/TTkUiTools/properties/listwidget.py index 044a5b9e..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/listwidget.py +++ b/TermTk/TTkUiTools/properties/listwidget.py @@ -19,3 +19,5 @@ # 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. + +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/menubar.py b/TermTk/TTkUiTools/properties/menubar.py index 044a5b9e..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/menubar.py +++ b/TermTk/TTkUiTools/properties/menubar.py @@ -19,3 +19,5 @@ # 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. + +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/progressbar.py b/TermTk/TTkUiTools/properties/progressbar.py index 044a5b9e..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/progressbar.py +++ b/TermTk/TTkUiTools/properties/progressbar.py @@ -19,3 +19,5 @@ # 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. + +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/scrollarea.py b/TermTk/TTkUiTools/properties/scrollarea.py index ee0973b1..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/scrollarea.py +++ b/TermTk/TTkUiTools/properties/scrollarea.py @@ -20,3 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/spacer.py b/TermTk/TTkUiTools/properties/spacer.py index ee0973b1..0d77e6f1 100644 --- a/TermTk/TTkUiTools/properties/spacer.py +++ b/TermTk/TTkUiTools/properties/spacer.py @@ -20,3 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] diff --git a/TermTk/TTkUiTools/properties/tabwidget.py b/TermTk/TTkUiTools/properties/tabwidget.py index ee0973b1..abafc69f 100644 --- a/TermTk/TTkUiTools/properties/tabwidget.py +++ b/TermTk/TTkUiTools/properties/tabwidget.py @@ -20,3 +20,5 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] + diff --git a/TermTk/TTkWidgets/TTkPickers/dateTimePicker.py b/TermTk/TTkWidgets/TTkPickers/dateTimePicker.py index 613023f1..e26d9aa4 100644 --- a/TermTk/TTkWidgets/TTkPickers/dateTimePicker.py +++ b/TermTk/TTkWidgets/TTkPickers/dateTimePicker.py @@ -20,3 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = [] \ No newline at end of file diff --git a/TermTk/TTkWidgets/TTkTerminal/mode.py b/TermTk/TTkWidgets/TTkTerminal/mode.py index a4170c84..c4de8190 100644 --- a/TermTk/TTkWidgets/TTkTerminal/mode.py +++ b/TermTk/TTkWidgets/TTkTerminal/mode.py @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +__all__ = ['TTkTerminalModes'] + class TTkTerminalModes(int): # define masks for keyboard flags MODE_KAM = 0x01 # mode 2: keyboard action mode From 0fee49e57b21ec45acee145709056d7c89684db4 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sat, 16 Nov 2024 14:32:35 +0000 Subject: [PATCH 4/7] improved init import modifier --- tools/process.__init__.import.py | 79 +++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 7 deletions(-) mode change 100644 => 100755 tools/process.__init__.import.py diff --git a/tools/process.__init__.import.py b/tools/process.__init__.import.py old mode 100644 new mode 100755 index ab8db3b7..173ab5ed --- a/tools/process.__init__.import.py +++ b/tools/process.__init__.import.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import os, sys +import os, sys, re import ast import _ast @@ -30,6 +30,26 @@ sys.path.append(os.path.join(sys.path[0],'..')) import TermTk as ttk +def find_init_and_files(folder_path): + """ + Recursively scan a folder to find __init__.py files and list all files in their directories. + + Args: + folder_path (str): The folder to scan. + + Returns: + dict: A dictionary with __init__.py paths as keys and arrays of files in their directories as values. + """ + init_files_dict = {} + + for root, _, files in os.walk(folder_path): + if "__init__.py" in files: + init_path = os.path.join(root, "__init__.py") + files_in_folder = [os.path.join(root, f) for f in files if f != "__init__.py"] + init_files_dict[init_path] = files_in_folder + + return init_files_dict + def find_init_and_files(folder_path): """ Recursively scan a folder to find __init__.py files and list all files in their directories. @@ -71,12 +91,57 @@ def get_variables2(tree): ret = find_init_and_files('TermTk') for init in ret: - print(f"{init}") - for file in ret[init]: - vars = get_variables(ast.parse(open(file).read())) - if '__all__' in vars: - print(ttk.TTkString(f" - {file}:{vars['__all__']}", ttk.TTkColor.GREEN).toAnsi()) + dirname = os.path.dirname(init) + initName = os.path.basename(init) + print(f"{dirname} - {initName}") + initLines = [] + with open(init) as fh: + initLines = fh.read().split('\n') + outLines = [] + for line in initLines: + if not (m := re.match('( *from *\.([^ ]*) *import *)\*', line)): + outLines.append(line) else: - print(ttk.TTkString(f" - {file}: No __all__ Found", ttk.TTkColor.RED).toAnsi()) + prefix = m.group(1) + fileName = f"{dirname}/{m.group(2)}.py" + print(f"{m.group(0)} | {m.group(1)} | {m.group(2)}") + if fileName in ret[init]: + vars = get_variables(ast.parse(open(fileName).read())) + if '__all__' in vars: + if _va:=vars['__all__']: + _line = f"{prefix}{', '.join(_va)}" + else: + _line = f"# {prefix}*" + print(_line) + print(ttk.TTkString(f" - {fileName}:{vars['__all__']}", ttk.TTkColor.GREEN).toAnsi()) + outLines.append(_line) + else: + print(ttk.TTkString(f" - {fileName}: No __all__ Found", ttk.TTkColor.RED).toAnsi()) + outLines.append(line) + else: + outLines.append(line) + print(f"{fileName} not in {ret[init]}") + print('\n'.join(outLines)) + with open(init, 'w') as fp: + fp.write('\n'.join(outLines)) + + + + + # with open(fileName, 'w') as fp: + # fp.write(textEdit.toPlainText()) + + # os.path.basename(init) + # for file in ret[init]: + # vars = get_variables(ast.parse(open(file).read())) + # if '__all__' in vars: + # print(ttk.TTkString(f" - {file}:{vars['__all__']}", ttk.TTkColor.GREEN).toAnsi()) + # else: + # print(ttk.TTkString(f" - {file}: No __all__ Found", ttk.TTkColor.RED).toAnsi()) +# for root, _, files in os.walk('TermTk'): +# for file in files: +# initLines = [] +# with open(f"{root}/{file}") as fh: +# initLines = fh.read().split('\n') From 968775d853511a1545c9daa9c6322c42275a7144 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Wed, 20 Nov 2024 10:15:52 +0000 Subject: [PATCH 5/7] Split the color in functinoal objecs, improved the rasterizer. Using the sub routine of color to reduce the footprint of the painting routine, this should speedup significantly the process for big and multicolor refresh. --- TermTk/TTkCore/TTkTerm/colors.py | 45 +-- TermTk/TTkCore/canvas.py | 6 +- TermTk/TTkCore/color.py | 317 ++++++++++++++---- TermTk/TTkCore/constant.py | 4 +- .../test.generic.008.class.override.01.py | 71 ++++ .../test.generic.008.class.override.02.py | 76 +++++ .../test.generic.008.class.override.03.py | 73 ++++ tests/timeit/25.comparison.04.overloading.py | 88 +++++ 8 files changed, 595 insertions(+), 85 deletions(-) create mode 100755 tests/t.generic/test.generic.008.class.override.01.py create mode 100755 tests/t.generic/test.generic.008.class.override.02.py create mode 100755 tests/t.generic/test.generic.008.class.override.03.py create mode 100755 tests/timeit/25.comparison.04.overloading.py diff --git a/TermTk/TTkCore/TTkTerm/colors.py b/TermTk/TTkCore/TTkTerm/colors.py index 762125ec..e4b83e21 100644 --- a/TermTk/TTkCore/TTkTerm/colors.py +++ b/TermTk/TTkCore/TTkTerm/colors.py @@ -63,6 +63,8 @@ class TTkTermColor(): @staticmethod def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False, cleanLink:bool=False): ret = [] + ret_append = ret.append + linkAnsi = "" if cleanLink: @@ -71,31 +73,32 @@ class TTkTermColor(): linkAnsi = f"\033]8;;{link}\033\\" if clean: - ret.append(0) + ret_append('0') if fg: - ret.append(f'38;2;{fg[0]};{fg[1]};{fg[2]}') + ret_append(f'38;2;{fg[0]};{fg[1]};{fg[2]}') if bg: - ret.append(f'48;2;{bg[0]};{bg[1]};{bg[2]}') - - 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.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') + ret_append(f'48;2;{bg[0]};{bg[1]};{bg[2]}') + + if mod: + 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.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{linkAnsi}' + return f'\033[{";".join(ret)}m{linkAnsi}' else: return '\033[0m'+linkAnsi diff --git a/TermTk/TTkCore/canvas.py b/TermTk/TTkCore/canvas.py index 24af7625..f4af7ace 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -743,16 +743,14 @@ class TTkCanvas(): ansi = TTkTerm.Cursor.moveTo(y+1,x+1) empty = False if color != lastcolor: - ansi += str(color-lastcolor) + ansi += color-lastcolor lastcolor = color ansi+=ch if not empty: TTkTerm.push(ansi) empty=True # Reset the color at the end - TTkTerm.push(TTkColor.RST) - if lastcolor._link: - TTkTerm.push("\033]8;;\033\\") + TTkTerm.push(TTkColor.RST-lastcolor) # TTkTerm.flush() # Switch the buffer self._bufferedData, self._bufferedColors = data, colors diff --git a/TermTk/TTkCore/color.py b/TermTk/TTkCore/color.py index 786bf0e3..4917860b 100644 --- a/TermTk/TTkCore/color.py +++ b/TermTk/TTkCore/color.py @@ -63,22 +63,16 @@ from TermTk.TTkCore.helper import TTkHelper # [49m 2.53 set background color to default (black) class _TTkColor: - __slots__ = ('_fg','_bg','_mod', '_colorMod', '_link', '_buffer', '_clean', '_cleanLink') - _fg: tuple[int]; _bg: tuple[int]; _mod: int + __slots__ = ('_fg','_bg', '_colorMod', '_buffer', '_clean') + _fg: tuple[int]; _bg: tuple[int]; def __init__(self, fg:tuple[int]=None, bg:tuple[int]=None, - mod:int=0, colorMod=None, - link:str='', - clean:bool=False, - cleanLink:bool=False) -> None: + clean=False) -> None: self._fg = fg self._bg = bg - self._mod = mod - self._link = link - self._clean = clean or not (fg or bg or mod) - self._cleanLink = cleanLink + self._clean = clean or not (fg or bg) self._colorMod = colorMod self._buffer = None @@ -95,25 +89,24 @@ class _TTkColor: return None def bold(self) -> bool: - return self._mod & TTkTermColor.BOLD + return False def italic(self) -> bool: - return self._mod & TTkTermColor.ITALIC + return False def underline(self) -> bool: - return self._mod & TTkTermColor.UNDERLINE + return False def strikethrough(self) -> bool: - return self._mod & TTkTermColor.STRIKETROUGH + return False def blinking(self) -> bool: - return self._mod & TTkTermColor.BLINKING + return False def colorType(self): - return \ - ( TTkK.Foreground if self._fg else TTkK.NONE ) | \ - ( TTkK.Background if self._bg else TTkK.NONE ) | \ - ( TTkK.Modifier if self._mod else TTkK.NONE ) + return ( + ( TTkK.Foreground if self._fg else TTkK.NONE ) | + ( TTkK.Background if self._bg else TTkK.NONE ) ) @staticmethod def rgb2hsl(rgb): @@ -193,54 +186,54 @@ class _TTkColor: def __str__(self): if not self._buffer: self._buffer = TTkTermColor.rgb2ansi( - fg=self._fg, bg=self._bg, mod=self._mod, - link=self._link, clean=self._clean, cleanLink=self._cleanLink) + fg=self._fg, bg=self._bg, + clean=self._clean) return self._buffer def __eq__(self, other): - if other is None: return False + if not other: return False return ( - self._fg == other._fg and - self._bg == other._bg and - self._mod == other._mod and - self._link == other._link ) + self._fg == other._fg and + self._bg == other._bg ) # self | other def __or__(self, other): # TTkLog.debug("__add__") - return self + other + if other._clean: + return other + clean = self._clean + fg: str = self._fg or other._fg + bg: str = self._bg or other._bg + colorMod = self._colorMod or other._colorMod + return _TTkColor( + fg=fg, bg=bg, + colorMod=colorMod, + clean=clean) # self + other def __add__(self, other): # TTkLog.debug("__add__") if other._clean: - ret = other.copy() - ret._cleanLink |= self._cleanLink - return ret + return other clean = self._clean - cleanLink = self._cleanLink fg: str = other._fg or self._fg bg: str = other._bg or self._bg - mod: str = self._mod + other._mod - link:str = self._link or other._link colorMod = other._colorMod or self._colorMod - return TTkColor( - fg=fg, bg=bg, mod=mod, - colorMod=colorMod, link=link, - clean=clean, cleanLink=cleanLink) + return _TTkColor( + fg=fg, bg=bg, + colorMod=colorMod, + clean=clean) - def __sub__(self, other): - # TTkLog.debug("__sub__") - # if other is None: return str(self) - if ( None == self._bg != other._bg or - None == self._fg != other._fg or - self._link != other._link or - self._mod != other._mod ): - ret = self.copy() - ret._clean = True - ret._cleanLink = self._link != other._link - return ret - return self + def __sub__(self, other) -> str: + ''' + I am abusing this operator in order to save time in the diff resolv between two adjacent colors + ''' + if ( None == self._bg != other._bg or + None == self._fg != other._fg ): + return TTkTermColor.rgb2ansi( + fg=self._fg, bg=self._bg, + clean=True) + return str(self) def modParam(self, *args, **kwargs) -> None: if not self._colorMod: return self @@ -256,14 +249,208 @@ class _TTkColor: ret = _TTkColor() ret._fg = self._fg ret._bg = self._bg + ret._clean = self._clean + if modifier and self._colorMod: + ret._colorMod = self._colorMod.copy() + return ret + +class _TTkColor_mod(_TTkColor): + __slots__ = ('_mod') + _mod: int + def __init__(self, *, + mod:int=0, + **kwargs + ) -> None: + self._mod = mod + super().__init__(**kwargs) + self._clean = self._clean or mod + + def bold(self) -> bool: + return self._mod & TTkTermColor.BOLD + + def italic(self) -> bool: + return self._mod & TTkTermColor.ITALIC + + def underline(self) -> bool: + return self._mod & TTkTermColor.UNDERLINE + + def strikethrough(self) -> bool: + return self._mod & TTkTermColor.STRIKETROUGH + + def blinking(self) -> bool: + return self._mod & TTkTermColor.BLINKING + + def colorType(self): + return ( + super().colorType() | + ( TTkK.Modifier if self._mod else TTkK.NONE )) + + def __str__(self): + if not self._buffer: + self._buffer = TTkTermColor.rgb2ansi( + fg=self._fg, bg=self._bg, mod=self._mod, + clean=self._clean) + return self._buffer + + def __eq__(self, other): + return ( + _TTkColor.__eq__(self,other) and + ( self._mod == (other._mod if isinstance(other,_TTkColor_mod) else 0)) + ) + + # self | other + def __or__(self, other): + # TTkLog.debug("__add__") + if other._clean: + return other + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + clean = self._clean + fg: str = self._fg or other._fg + bg: str = self._bg or other._bg + mod: str = self._mod + otherMod + colorMod = self._colorMod or other._colorMod + return _TTkColor_mod( + fg=fg, bg=bg, mod=mod, + colorMod=colorMod, + clean=clean) + + # self + other + def __add__(self, other): + # TTkLog.debug("__add__") + if other._clean: + return other + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + clean = self._clean + fg: str = other._fg or self._fg + bg: str = other._bg or self._bg + mod: str = self._mod + otherMod + colorMod = other._colorMod or self._colorMod + return _TTkColor_mod( + fg=fg, bg=bg, mod=mod, + colorMod=colorMod, + clean=clean) + + def __sub__(self, other) -> str: + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + if ( None == self._bg != other._bg or + None == self._fg != other._fg or + self._mod != otherMod ): + return TTkTermColor.rgb2ansi( + fg=self._fg, bg=self._bg, mod=self._mod, + clean=True) + return str(self) + + def __rsub__(self, other) -> str: + return TTkTermColor.rgb2ansi(fg=other._fg, bg=other._bg, clean=True) + + def copy(self, modifier=True): + ret = _TTkColor_mod() + ret._fg = self._fg + ret._bg = self._bg + ret._mod = self._mod + ret._clean = self._clean + if modifier and self._colorMod: + ret._colorMod = self._colorMod.copy() + return ret + + +class _TTkColor_mod_link(_TTkColor_mod): + __slots__ = ('_link') + _link: str + def __init__(self, *, + link:str='', + **kwargs + ) -> None: + self._link = link + super().__init__(**kwargs) + self._clean = self._clean or link + + def colorType(self): + return ( + super().colorType() | + ( TTkK.Link if self._link else TTkK.NONE )) + + def __str__(self): + if not self._buffer: + self._buffer = TTkTermColor.rgb2ansi( + fg=self._fg, bg=self._bg, mod=self._mod, + link=self._link, clean=self._clean) + return self._buffer + + def __eq__(self, other): + return ( + _TTkColor_mod.__eq__(self,other) and + ( self._link == (other._link if isinstance(other,_TTkColor_mod_link) else 0)) + ) + + # self | other + def __or__(self, other): + # TTkLog.debug("__add__") + if other._clean: + return other + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + otherLink = other._link if isinstance(other,_TTkColor_mod_link) else '' + clean = self._clean + fg: str = self._fg or other._fg + bg: str = self._bg or other._bg + mod: str = self._mod + otherMod + link:str = self._link or otherLink + colorMod = self._colorMod or other._colorMod + return _TTkColor_mod_link( + fg=fg, bg=bg, mod=mod, + colorMod=colorMod, link=link, + clean=clean) + + # self + other + def __add__(self, other): + # TTkLog.debug("__add__") + if other._clean: + return other + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + otherLink = other._link if isinstance(other,_TTkColor_mod_link) else '' + clean = self._clean + fg: str = other._fg or self._fg + bg: str = other._bg or self._bg + mod: str = self._mod + otherMod + link:str = self._link or otherLink + colorMod = other._colorMod or self._colorMod + return _TTkColor_mod_link( + fg=fg, bg=bg, mod=mod, + colorMod=colorMod, link=link, + clean=clean) + + def __sub__(self, other): + # TTkLog.debug("__sub__") + # if other is None: return str(self) + otherMod = other._mod if isinstance(other,_TTkColor_mod) else 0 + otherLink = other._link if isinstance(other,_TTkColor_mod_link) else '' + if ( None == self._bg != other._bg or + None == self._fg != other._fg or + self._link != otherLink or + self._mod != otherMod ): + return TTkTermColor.rgb2ansi( + fg=self._fg, bg=self._bg, mod=self._mod, + link=self._link, clean=True) + return '' + + def __rsub__(self, other) -> str: + if type(other) == _TTkColor: + return TTkTermColor.rgb2ansi(fg=other._fg, bg=other._bg, clean=True, cleanLink=True) + else: + return TTkTermColor.rgb2ansi(fg=other._fg, bg=other._bg, mod=other._mod, clean=True, cleanLink=True) + + def copy(self, modifier=True): + ret = _TTkColor_mod_link() + ret._fg = self._fg + ret._bg = self._bg ret._mod = self._mod ret._link = self._link ret._clean = self._clean - ret._cleanLink = self._cleanLink if modifier and self._colorMod: ret._colorMod = self._colorMod.copy() return ret + class _TTkColorModifier(): def __init__(self, *args, **kwargs) -> None: pass def setParam(self, *args, **kwargs) -> None: pass @@ -458,16 +645,16 @@ class TTkColor(_TTkColor): '''(bg) #FFFF00 - Yellow''' # Modifiers: - BOLD = _TTkColor(mod=TTkTermColor.BOLD) + BOLD = _TTkColor_mod(mod=TTkTermColor.BOLD) '''**Bold** modifier''' - ITALIC = _TTkColor(mod=TTkTermColor.ITALIC) + ITALIC = _TTkColor_mod(mod=TTkTermColor.ITALIC) '''*Italic* modifier''' - UNDERLINE = _TTkColor(mod=TTkTermColor.UNDERLINE) + UNDERLINE = _TTkColor_mod(mod=TTkTermColor.UNDERLINE) ''':underline:`Underline` modifier''' - STRIKETROUGH = _TTkColor(mod=TTkTermColor.STRIKETROUGH) + STRIKETROUGH = _TTkColor_mod(mod=TTkTermColor.STRIKETROUGH) ''':strike:`Striketrough` modifier''' - BLINKING = _TTkColor(mod=TTkTermColor.BLINKING) + BLINKING = _TTkColor_mod(mod=TTkTermColor.BLINKING) '''"Blinking" modifier''' @staticmethod @@ -480,7 +667,10 @@ class TTkColor(_TTkColor): @staticmethod def ansi(ansi): fg,bg,mod,clean = TTkTermColor.ansi2rgb(ansi) - return TTkColor(fg=fg, bg=bg, mod=mod, clean=clean) + if mod: + return _TTkColor_mod(fg=fg, bg=bg, mod=mod, clean=clean) + else: + return _TTkColor(fg=fg, bg=bg, clean=clean) @staticmethod def fg(*args, **kwargs) -> None: @@ -507,7 +697,10 @@ class TTkColor(_TTkColor): color = args[0] else: color = kwargs.get('color', "" ) - return TTkColor(fg=TTkColor.hexToRGB(color), colorMod=mod, link=link) + if link: + return _TTkColor_mod_link(fg=TTkColor.hexToRGB(color), colorMod=mod, link=link) + else: + return _TTkColor(fg=TTkColor.hexToRGB(color), colorMod=mod) @staticmethod def bg(*args, **kwargs) -> None: @@ -534,7 +727,10 @@ class TTkColor(_TTkColor): color = args[0] else: color = kwargs.get('color', "" ) - return TTkColor(bg=TTkColor.hexToRGB(color), colorMod=mod, link=link) + if link: + return _TTkColor_mod_link(bg=TTkColor.hexToRGB(color), colorMod=mod, link=link) + else: + return _TTkColor(bg=TTkColor.hexToRGB(color), colorMod=mod) @staticmethod def fgbg(fg:str='', bg:str='', link:str='', modifier:_TTkColorModifier=None): @@ -557,7 +753,10 @@ class TTkColor(_TTkColor): :return: :py:class:`TTkColor` ''' - return TTkColor(fg=TTkColor.hexToRGB(fg), bg=TTkColor.hexToRGB(bg), colorMod=modifier, link=link) + if link: + return _TTkColor_mod_link(fg=TTkColor.hexToRGB(fg), bg=TTkColor.hexToRGB(bg), colorMod=modifier, link=link) + else: + return _TTkColor(fg=TTkColor.hexToRGB(fg), bg=TTkColor.hexToRGB(bg), colorMod=modifier) class TTkAlternateColor(_TTkColorModifier): '''TTkAlternateColor''' diff --git a/TermTk/TTkCore/constant.py b/TermTk/TTkCore/constant.py index 96714ef3..6f3dbcde 100644 --- a/TermTk/TTkCore/constant.py +++ b/TermTk/TTkCore/constant.py @@ -37,10 +37,12 @@ class TTkConstant: class ColorType(int): Foreground = 0x01 Background = 0x02 - Modifier = 0x03 + Modifier = 0x04 + Link = 0x08 Foreground = ColorType.Foreground Background = ColorType.Background Modifier = ColorType.Modifier + Link = ColorType.Link class FocusPolicy(int): ''' diff --git a/tests/t.generic/test.generic.008.class.override.01.py b/tests/t.generic/test.generic.008.class.override.01.py new file mode 100755 index 00000000..3fa96def --- /dev/null +++ b/tests/t.generic/test.generic.008.class.override.01.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# 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 A(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __eq__(self, value: object) -> bool: + print(f"A.eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + +class B(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __eq__(self, value: object) -> bool: + print(f"B.eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + +class C(A): + def __eq__(self, value: object) -> bool: + print(f"C(A).eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + +class D(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + +a = A(1,2) +aa = a +b = B(1,2) +bb = b +c = C(1,2) +cc = c +d = D(1,2) + + +print(f"{(a==aa)=}") +print(f"{(aa==a)=}") +print(f"{(a==c )=}") +print(f"{(c==a )=}") +print(f"{(a==b )=}") +print(f"{(b==a )=}") +print(f"{(b==c )=}") +print(f"{(c==b )=}") +print(f"{(c==d )=}") +print(f"{(d==c )=}") \ No newline at end of file diff --git a/tests/t.generic/test.generic.008.class.override.02.py b/tests/t.generic/test.generic.008.class.override.02.py new file mode 100755 index 00000000..7fe2ad43 --- /dev/null +++ b/tests/t.generic/test.generic.008.class.override.02.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# 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 A(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __str__(self): + return f"a={self.a}, b={self.b}" + + def __sub__(self, other: object) -> bool: + return f"A( ). sub - {self=},{other=}" + +class B(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __sub__(self, other: object) -> bool: + return f"B( ). sub - {self=},{other=}" + +class C(A): + def __sub__(self, other: object) -> bool: + return f"C(A). sub - {self=},{other=}" + +class D(C): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + def __sub__(self, other: object) -> bool: + return f"D(C). sub - {self=},{other=}" + def __rsub__(self, other: object) -> bool: + return f"D(C).R-sub - {self=},{other=}" + +a = A(1,2) +aa = a +b = B(1,2) +bb = b +c = C(1,2) +cc = c +d = D(1,2) + + +print(f"{(a-aa)=}") +print(f"{(aa-a)=}") +print(f"{(a-c )=}") +print(f"{(c-a )=}") +print(f"{(a-b )=}") +print(f"{(b-a )=}") +print(f"{(b-c )=}") +print(f"{(c-b )=}") +print(f"{(c-d )=}") +print(f"{(d-c )=}") +print(f"{(d-d )=}") \ No newline at end of file diff --git a/tests/t.generic/test.generic.008.class.override.03.py b/tests/t.generic/test.generic.008.class.override.03.py new file mode 100755 index 00000000..961e938d --- /dev/null +++ b/tests/t.generic/test.generic.008.class.override.03.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# 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 A(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __str__(self): return f"a={self.a} {type(self).__name__} {type(other).__name__}, b={self.b}" + def __sub__(self, other): return f"A( ). sub {type(self).__name__} {type(other).__name__}" + def __or__( self, other): return f"A( ). or {type(self).__name__} {type(other).__name__}" + def __ror__(self, other): return f"A( ).R-or {type(self).__name__} {type(other).__name__}" + +class B(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __sub__(self, other): return f"B( ). sub {type(self).__name__} {type(other).__name__}" + +class C(A): + def __sub__(self, other): return f"C(A). sub {type(self).__name__} {type(other).__name__}" + def __or__( self, other): return f"C(C). or {type(self).__name__} {type(other).__name__}" + +class D(C): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + def __sub__( self, other): return f"D(C). sub {type(self).__name__} {type(other).__name__}" + def __rsub__(self, other): return f"D(C).R-sub {type(self).__name__} {type(other).__name__}" + def __or__( self, other): return f"D(C). or {type(self).__name__} {type(other).__name__}" + def __ror__( self, other): return f"D(C).R-or {type(self).__name__} {type(other).__name__}" +a = A(1,2) +aa = a +b = B(1,2) +bb = b +c = C(1,2) +cc = c +d = D(1,2) + + +print(f"{(a-aa)=} | {(a|aa)=}") +print(f"{(aa-a)=} | {(aa|a)=}") +print(f"{(a-c )=} | {(a|c )=}") +print(f"{(c-a )=} | {(c|a )=}") +print(f"{(a-b )=} | {(a|b )=}") +print(f"{(b-a )=} | {(b|a )=}") +print(f"{(b-c )=} | {(b|c )=}") +print(f"{(c-b )=} | {(c|b )=}") +print(f"{(c-d )=} | {(c|d )=}") +print(f"{(d-c )=} | {(d|c )=}") +print(f"{(d-d )=} | {(d|d )=}") \ No newline at end of file diff --git a/tests/timeit/25.comparison.04.overloading.py b/tests/timeit/25.comparison.04.overloading.py new file mode 100755 index 00000000..4ee42628 --- /dev/null +++ b/tests/timeit/25.comparison.04.overloading.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2023 Eugenio Parodi +# +# 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 timeit, pickle + +class A(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __eq__(self, value: object) -> bool: + # print(f"A.eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + +class B(): + def __init__(self,a,b) -> None: + self.a = a + self.b = b + + def __eq__(self, value: object) -> bool: + # print(f"B.eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + +class C(A): + def __eq__(self, value: object) -> bool: + # print(f"C(A).eq - {self=},{value=}") + return self.a==value.a and self.b==value.b + + +a = A(1,2) +aa = a +b = B(1,2) +bb = b +c = C(1,2) +cc = c + +print(f"{(a==aa)=}") +print(f"{(aa==a)=}") +print(f"{(a==c )=}") +print(f"{(c==a )=}") +print(f"{(a==b )=}") +print(f"{(b==a )=}") +print(f"{(b==c )=}") +print(f"{(c==b )=}") + +def test_ti_00_x000(a,aa,b,c): return len([a==aa for _ in range(1000)]) +def test_ti_00_x001(a,aa,b,c): return len([a==aa for _ in range(1000)]) +def test_ti_00_x002(a,aa,b,c): return len([a==aa for _ in range(1000)]) +def test_ti_00_x003(a,aa,b,c): return len([a==aa for _ in range(1000)]) +def test_ti_00_x004(a,aa,b,c): return len([a==aa for _ in range(100)]) +def test_ti_01_A_AA(a,aa,b,c): return len([a==aa for _ in range(1000)]) +def test_ti_01_AA_A(a,aa,b,c): return len([aa==a for _ in range(1000)]) +def test_ti_02_A_B_(a,aa,b,c): return len([a==b for _ in range(1000)]) +def test_ti_02_B_A_(a,aa,b,c): return len([b==a for _ in range(1000)]) +def test_ti_03_A_C_(a,aa,b,c): return len([a==c for _ in range(1000)]) +def test_ti_03_C_A_(a,aa,b,c): return len([c==a for _ in range(1000)]) +def test_ti_04_B_C_(a,aa,b,c): return len([b==c for _ in range(1000)]) +def test_ti_04_C_B_(a,aa,b,c): return len([c==b for _ in range(1000)]) + +loop = 1000 + +a = {'a':a,'aa':aa,'b':b,'c':c} + +for testName in sorted([tn for tn in globals() if tn.startswith('test_ti_')]): + 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"{testName} | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}") From c06d463f6a2e2e107f0bd335c5a8051c894ac771 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Wed, 20 Nov 2024 18:54:11 +0000 Subject: [PATCH 6/7] few minor fixes after the new color handling --- TermTk/TTkCore/color.py | 4 +-- TermTk/TTkWidgets/TTkTerminal/terminalview.py | 13 +++++++-- .../test.generic.008.class.override.03.py | 2 +- .../t.generic/test.generic.012.boolean.01.py | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100755 tests/t.generic/test.generic.012.boolean.01.py diff --git a/TermTk/TTkCore/color.py b/TermTk/TTkCore/color.py index 4917860b..da6c585b 100644 --- a/TermTk/TTkCore/color.py +++ b/TermTk/TTkCore/color.py @@ -263,7 +263,7 @@ class _TTkColor_mod(_TTkColor): ) -> None: self._mod = mod super().__init__(**kwargs) - self._clean = self._clean or mod + self._clean = self._clean and not mod def bold(self) -> bool: return self._mod & TTkTermColor.BOLD @@ -363,7 +363,7 @@ class _TTkColor_mod_link(_TTkColor_mod): ) -> None: self._link = link super().__init__(**kwargs) - self._clean = self._clean or link + self._clean = self._clean and not link def colorType(self): return ( diff --git a/TermTk/TTkWidgets/TTkTerminal/terminalview.py b/TermTk/TTkWidgets/TTkTerminal/terminalview.py index 4eec8983..e925e3cb 100644 --- a/TermTk/TTkWidgets/TTkTerminal/terminalview.py +++ b/TermTk/TTkWidgets/TTkTerminal/terminalview.py @@ -27,7 +27,7 @@ import re from dataclasses import dataclass from TermTk.TTkCore.canvas import TTkCanvas -from TermTk.TTkCore.color import TTkColor +from TermTk.TTkCore.color import TTkColor, _TTkColor, _TTkColor_mod, _TTkColor_mod_link from TermTk.TTkCore.log import TTkLog from TermTk.TTkCore.constant import TTkK from TermTk.TTkCore.string import TTkString @@ -354,6 +354,9 @@ class TTkTerminalView(TTkAbstractScrollView, _TTkTerminal_CSI_DEC): # CSI Color Functions # CSI Pm ; Pm ; ... m ################################################ + # TODO: Rework this routine to avoid the use + # of the internal color sub classes + ################################################ elif ((m := TTkTerminalView.re_CURSOR.match(slice)) and (mg := m.groups()) and mg[-1] == 'm' ): @@ -367,7 +370,7 @@ class TTkTerminalView(TTkAbstractScrollView, _TTkTerminal_CSI_DEC): color = self._screen_current.color() fg = color._fg bg = color._bg - mod = color._mod + mod = color._mod if hasattr(color,'_mod') else 0 clean = False while values: @@ -407,7 +410,11 @@ class TTkTerminalView(TTkAbstractScrollView, _TTkTerminal_CSI_DEC): mod &= _sgr else: _termLog.warn(f"Unhandled color: {slice}") - color = TTkColor(fg=fg, bg=bg, mod=mod, clean=clean) + if mod: + color = _TTkColor_mod(fg=fg, bg=bg, mod=mod, clean=clean) + else: + color = _TTkColor(fg=fg, bg=bg, clean=clean) + # color = TTkColor(fg=fg, bg=bg, mod=mod, clean=clean) self._screen_alt.setColor(color) self._screen_normal.setColor(color) diff --git a/tests/t.generic/test.generic.008.class.override.03.py b/tests/t.generic/test.generic.008.class.override.03.py index 961e938d..ea963a7a 100755 --- a/tests/t.generic/test.generic.008.class.override.03.py +++ b/tests/t.generic/test.generic.008.class.override.03.py @@ -27,7 +27,7 @@ class A(): self.a = a self.b = b - def __str__(self): return f"a={self.a} {type(self).__name__} {type(other).__name__}, b={self.b}" + def __str__(self): return f"a={self.a}, b={self.b}" def __sub__(self, other): return f"A( ). sub {type(self).__name__} {type(other).__name__}" def __or__( self, other): return f"A( ). or {type(self).__name__} {type(other).__name__}" def __ror__(self, other): return f"A( ).R-or {type(self).__name__} {type(other).__name__}" diff --git a/tests/t.generic/test.generic.012.boolean.01.py b/tests/t.generic/test.generic.012.boolean.01.py new file mode 100755 index 00000000..9de7239d --- /dev/null +++ b/tests/t.generic/test.generic.012.boolean.01.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2021 Eugenio Parodi +# +# 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. + + + +for i in range(0xF): + a,b,c,d = i&1,i&1<<1,i&1<<2,i&1<<3 + print(f"{a} {b} {c} {d} = {a or not (b or c or d)} -> {a or not (b or c) and not d}") From 050d7e2a5ec6ed750ee3951aedd1b3240fdc17ad Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Thu, 21 Nov 2024 16:46:59 +0000 Subject: [PATCH 7/7] separate the lnk routine to avind unnecessary loops --- TermTk/TTkCore/TTkTerm/colors.py | 22 +++++----- TermTk/TTkCore/color.py | 8 ++-- TermTk/TTkTestWidgets/testwidget.py | 6 ++- tests/timeit/30.rendering.02.Colors.py | 59 ++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 16 deletions(-) create mode 100755 tests/timeit/30.rendering.02.Colors.py diff --git a/TermTk/TTkCore/TTkTerm/colors.py b/TermTk/TTkCore/TTkTerm/colors.py index e4b83e21..8765c284 100644 --- a/TermTk/TTkCore/TTkTerm/colors.py +++ b/TermTk/TTkCore/TTkTerm/colors.py @@ -61,17 +61,10 @@ class TTkTermColor(): 29: ~STRIKETROUGH } # Ps = 2 9 ⇒ Not crossed-out, ECMA-48 3rd. @staticmethod - def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False, cleanLink:bool=False): + def rgb2ansi(fg: tuple=None, bg:tuple=None, mod:int=0, clean:bool=False): ret = [] ret_append = ret.append - linkAnsi = "" - - if cleanLink: - linkAnsi = "\033]8;;\033\\" - if link: - linkAnsi = f"\033]8;;{link}\033\\" - if clean: ret_append('0') @@ -98,9 +91,18 @@ class TTkTermColor(): if mod & TTkTermColor.STRIKETROUGH: ret_append('9') if ret: - return f'\033[{";".join(ret)}m{linkAnsi}' + return f'\033[{";".join(ret)}m' else: - return '\033[0m'+linkAnsi + return '\033[0m' + + @staticmethod + def rgb2ansi_link(fg: tuple=None, bg:tuple=None, mod:int=0, link:str='', clean:bool=False, cleanLink:bool=False): + linkAnsi = "" + if cleanLink: + linkAnsi = "\033]8;;\033\\" + if link: + linkAnsi = f"\033]8;id=1;{link}\033\\" + return TTkTermColor.rgb2ansi(fg=fg,bg=bg,mod=mod,clean=clean)+linkAnsi def _256toRgb(val): pass diff --git a/TermTk/TTkCore/color.py b/TermTk/TTkCore/color.py index da6c585b..8d9e7e19 100644 --- a/TermTk/TTkCore/color.py +++ b/TermTk/TTkCore/color.py @@ -372,7 +372,7 @@ class _TTkColor_mod_link(_TTkColor_mod): def __str__(self): if not self._buffer: - self._buffer = TTkTermColor.rgb2ansi( + self._buffer = TTkTermColor.rgb2ansi_link( fg=self._fg, bg=self._bg, mod=self._mod, link=self._link, clean=self._clean) return self._buffer @@ -428,16 +428,16 @@ class _TTkColor_mod_link(_TTkColor_mod): None == self._fg != other._fg or self._link != otherLink or self._mod != otherMod ): - return TTkTermColor.rgb2ansi( + return TTkTermColor.rgb2ansi_link( fg=self._fg, bg=self._bg, mod=self._mod, link=self._link, clean=True) return '' def __rsub__(self, other) -> str: if type(other) == _TTkColor: - return TTkTermColor.rgb2ansi(fg=other._fg, bg=other._bg, clean=True, cleanLink=True) + return TTkTermColor.rgb2ansi_link(fg=other._fg, bg=other._bg, clean=True, cleanLink=True) else: - return TTkTermColor.rgb2ansi(fg=other._fg, bg=other._bg, mod=other._mod, clean=True, cleanLink=True) + return TTkTermColor.rgb2ansi_link(fg=other._fg, bg=other._bg, mod=other._mod, clean=True, cleanLink=True) def copy(self, modifier=True): ret = _TTkColor_mod_link() diff --git a/TermTk/TTkTestWidgets/testwidget.py b/TermTk/TTkTestWidgets/testwidget.py index fc778461..41573623 100644 --- a/TermTk/TTkTestWidgets/testwidget.py +++ b/TermTk/TTkTestWidgets/testwidget.py @@ -31,8 +31,10 @@ from TermTk.TTkWidgets.label import * from TermTk.TTkWidgets.frame import * class _TestContent(TTkWidget): - t01 = TTkString(color=TTkColor.fg("#ff0000") ,text=" L😎rem ipsum dolor sit amet, ⌚ ❤ 💙 🙋'") - t02 = TTkString(color=TTkColor.fg("#ff8800") ,text="consectetur adipiscing elit,") + t01 = TTkString(color=TTkColor.fg("#ff0000", link="https://github.com/ceccopierangiolieugenio/pyTermTk") , + text=" L😎rem ipsum dolor sit amet, ⌚ ❤ 💙 🙋'") + t02 = TTkString(color=TTkColor.fg("#ff8800", link="https://ceccopierangiolieugenio.itch.io/dumb-paint-tool"), + text="consectetur adipiscing elit,") t03 = TTkString(color=TTkColor.fg("#ffff00") ,text="sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") t04 = TTkString(color=TTkColor.fg("#00ff00") ,text="Ut enim ad minim veniam,") t05 = TTkString(color=TTkColor.fg("#00ffff") ,text="quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.") diff --git a/tests/timeit/30.rendering.02.Colors.py b/tests/timeit/30.rendering.02.Colors.py new file mode 100755 index 00000000..0bd82d75 --- /dev/null +++ b/tests/timeit/30.rendering.02.Colors.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +# MIT License +# +# Copyright (c) 2024 Eugenio Parodi +# +# 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 os +import sys +import argparse +import operator +import json +import timeit + +sys.path.append(os.path.join(sys.path[0],'../..')) +import TermTk as ttk + +c01 = [ttk.TTkColor.fg( f'#0000{x:02X}') for x in range(200)] +c02 = [ttk.TTkColor.bg( f'#0000{x:02X}') for x in range(200)] +c03 = [ttk.TTkColor.fg( f'#0000{x:02X}')+ttk.TTkColor.UNDERLINE for x in range(200)] +c04 = [ttk.TTkColor.bg( f'#0000{x:02X}')+ttk.TTkColor.UNDERLINE for x in range(200)] +c10 = [ttk.TTkColor.fgbg(f'#0000{x:02X}',f'#0000{x:02X}') for x in range(200)] +c11 = [ttk.TTkColor.fgbg(f'#0000{x:02X}',f'#0000{x:02X}')+ttk.TTkColor.BOLD for x in range(200)] +c20 = [ttk.TTkColor.fgbg(f'#0000{x:02X}',f'#0000{x:02X}','http://www.example.com/{x:02X}')+ttk.TTkColor.UNDERLINE for x in range(200)] + +def test_ti_01(): return len(''.join([str(x) for x in c01])) +def test_ti_02(): return len(''.join([str(x) for x in c02])) +def test_ti_03(): return len(''.join([str(x) for x in c03])) +def test_ti_04(): return len(''.join([str(x) for x in c04])) +def test_ti_10(): return len(''.join([str(x) for x in c10])) +def test_ti_11(): return len(''.join([str(x) for x in c11])) +def test_ti_20(): return len(''.join([str(x) for x in c20])) + +loop = 10000 + +a = {} + +for testName in sorted([tn for tn in globals() if tn.startswith('test_ti_')]): + 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"{testName} | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}")