diff --git a/TermTk/TTkCore/TTkTerm/colors.py b/TermTk/TTkCore/TTkTerm/colors.py index 1c6f7d8a..8765c284 100644 --- a/TermTk/TTkCore/TTkTerm/colors.py +++ b/TermTk/TTkCore/TTkTerm/colors.py @@ -61,38 +61,49 @@ 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, clean:bool=False): ret = [] + ret_append = ret.append 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' + return f'\033[{";".join(ret)}m' else: 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/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/canvas.py b/TermTk/TTkCore/canvas.py index ac3c094a..f4af7ace 100644 --- a/TermTk/TTkCore/canvas.py +++ b/TermTk/TTkCore/canvas.py @@ -743,14 +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) + TTkTerm.push(TTkColor.RST-lastcolor) # TTkTerm.flush() # Switch the buffer self._bufferedData, self._bufferedColors = data, colors @@ -801,6 +801,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 f9826cd9..8d9e7e19 100644 --- a/TermTk/TTkCore/color.py +++ b/TermTk/TTkCore/color.py @@ -63,20 +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') - _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=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._clean = clean or not (fg or bg) self._colorMod = colorMod self._buffer = None @@ -93,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): @@ -191,61 +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) + 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__") if other._clean: - return other.copy() + return other 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, + return _TTkColor( + fg=fg, bg=bg, + colorMod=colorMod, clean=clean) # self + other def __add__(self, other): # TTkLog.debug("__add__") if other._clean: - return other.copy() + return other clean = self._clean 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, + 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 - 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 @@ -261,6 +249,200 @@ 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 and not 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 and not 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_link( + 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_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_link(fg=other._fg, bg=other._bg, clean=True, cleanLink=True) + else: + 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() + ret._fg = self._fg + ret._bg = self._bg ret._mod = self._mod ret._link = self._link ret._clean = self._clean @@ -268,6 +450,7 @@ class _TTkColor: ret._colorMod = self._colorMod.copy() return ret + class _TTkColorModifier(): def __init__(self, *args, **kwargs) -> None: pass def setParam(self, *args, **kwargs) -> None: pass @@ -462,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 @@ -484,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: @@ -511,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: @@ -538,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): @@ -561,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/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/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/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 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/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.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..ea963a7a --- /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}, 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/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}") 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..fe30bd83 --- /dev/null +++ b/tests/t.ui/test.ui.031.link.py @@ -0,0 +1,48 @@ +#!/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/"))) + canvas.drawText(pos=(20,3),text=ttk.TTkString('',ttk.TTkColor.fg('#0000FF', link="http:///www.python.com/"))) + 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 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)}") 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)}") 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')