diff --git a/TermTk/TTkCore/string.py b/TermTk/TTkCore/string.py index 606132d4..d3054cc1 100644 --- a/TermTk/TTkCore/string.py +++ b/TermTk/TTkCore/string.py @@ -171,15 +171,16 @@ class TTkString(): ret._colors += self._colors[0:pos] for s in slices[1:]: c = self._colors[pos] - lentxt = len(ret._text) + lentxt = ret.termWidth() spaces = tabSpaces - (lentxt+tabSpaces)%tabSpaces ret._text += " "*spaces + s ret._colors += [c]*spaces + self._colors[pos+1:pos+1+len(s)] + ret._checkWidth() pos+=len(s)+1 return ret def tabCharPos(self, pos, tabSpaces=4, alignTabRight=False): - '''Return the char position in the string from the position in its representation with the tab solved + '''Return the char position in the string from the position in its representation with the tab and variable char sizes are solved i.e. @@ -187,12 +188,14 @@ class TTkString(): pos X = 11 tab2Spaces |----------|---------------------| - Tabs |--| | |-| |-| | - _text Lorem ipsum dolor sit amet, - chars .....t .....t .....t ...t..... - ret x = 8 (tab is a char) + Tabs |-| | |-| |-| | + _text L😁rem ipsum dolor sit amet, + chars .. ...t .....t .....t ...t..... + ret x = 7 (tab is a char) + ''' - if not self._hasTab: return pos + if not self._hasTab and not self._hasSpecialWidth: return pos + if self._hasSpecialWidth: return self._tabCharPosWideChar(pos, tabSpaces, alignTabRight) slices = self._text.split("\t") postxt = 0 # position of the text lentxt = 0 # length of the text with resolved tabs @@ -213,6 +216,37 @@ class TTkString(): postxt += 1 return len(self._text) + def _tabCharPosWideChar(self, pos, tabSpaces=4, alignTabRight=False): + '''Return the char position in the string from the position in its representation with the tab and variable char sizes are solved + + i.e. + + :: + + pos X = 11 + tab2Spaces |----------|---------------------| + Tabs |-| | |-| |-| | + _text L😁rem ipsum dolor sit amet, + chars .. ...t .....t .....t ...t..... + ret x = 7 (tab is a char) + + ''' + # get pos in the slice: + dx = pos + pp = 0 + for i,ch in enumerate(self._text): + if ch=='\t': + pass + elif unicodedata.east_asian_width(ch) == 'W': + pp += 2 + elif unicodedata.category(ch) in ('Me','Mn'): + pass + else: + pp += 1 + if dx < pp: + return i + return len(self._text) + def toAscii(self): ''' Return the ascii representation of the string ''' return self._text @@ -476,6 +510,12 @@ class TTkString(): return ( unicodedata.east_asian_width(ch) == 'W' or unicodedata.category(ch) in ('Me','Mn') ) + @staticmethod + def _getWidthText(txt): + return ( len(txt) + + sum(unicodedata.east_asian_width(ch) == 'W' for ch in txt) - + sum(unicodedata.category(ch) in ('Me','Mn') for ch in txt) ) + def _checkWidth(self): self._hasSpecialWidth = ( any(unicodedata.east_asian_width(ch) == 'W' for ch in self._text) or @@ -487,8 +527,8 @@ class TTkString(): This value consider the displayed size (Zero, Half, Full) of each character. ''' return ( len(self._text) + - sum([unicodedata.east_asian_width(ch) == 'W' for ch in self._text]) - - sum([unicodedata.category(ch) in ('Me','Mn') for ch in self._text]) ) + sum(unicodedata.east_asian_width(ch) == 'W' for ch in self._text) - + sum(unicodedata.category(ch) in ('Me','Mn') for ch in self._text) ) def _getDataW(self): retTxt = [] diff --git a/TermTk/TTkGui/textwrap.py b/TermTk/TTkGui/textwrap.py index af957f1e..e74223c5 100644 --- a/TermTk/TTkGui/textwrap.py +++ b/TermTk/TTkGui/textwrap.py @@ -113,7 +113,7 @@ class TTkTextWrap(): for i, (dt, (fr, to)) in enumerate(self._lines): if dt == line and fr <= pos <= to: l = self._textDocument._dataLines[dt].substring(fr,pos).tab2spaces(self._tabSpaces) - return len(l), i + return l.termWidth(), i return 0,0 def screenToDataPosition(self, x, y): @@ -135,5 +135,5 @@ class TTkTextWrap(): x = max(0,x) s = self._textDocument._dataLines[dt].substring(fr,to) x = s.tabCharPos(x, self._tabSpaces) - x = len(s.substring(0,x).tab2spaces(self._tabSpaces)) + x = s.substring(0,x).tab2spaces(self._tabSpaces).termWidth() return x, y diff --git a/demo/showcase/textedit.py b/demo/showcase/textedit.py index 007aefb6..e6a0e4f2 100755 --- a/demo/showcase/textedit.py +++ b/demo/showcase/textedit.py @@ -96,6 +96,9 @@ def demoTextEdit(root=None, document=None): te.append( " - | | | | | -") te.append("") + te.append(f"Plus Tabs: -\t😁\t😍\to{zc1}{zc2}{zc3}\t😎\to{zc1}{zc2}{zc3}\tπŸ˜‚-") + te.append("") + # Test Tabs te.append(ttk.TTkString("Tabs Test\n",ttk.TTkColor.UNDERLINE+ttk.TTkColor.BOLD)) te.append("Word\tAnother Word\tYet more words") diff --git a/tests/test.draw.006.py b/tests/test.draw.006.py index d9708bdf..1e5bc2be 100755 --- a/tests/test.draw.006.py +++ b/tests/test.draw.006.py @@ -50,10 +50,17 @@ s3 = TTkString(f"Zero Size: - o{zc1} o{zc2} o{zc3} o{zc1}{zc2} o{zc1}{zc2}{z s4 = TTkString("This is a notmal string") +s5 = TTkString(f"-πŸ˜πŸ˜‚πŸ˜πŸ˜Ž- o{zc1} o{zc2} o{zc3} o{zc1}{zc2} o{zc1}{zc2}{zc3} -") + print(s1.getData()[0]) print(s2.getData()[0]) print(s3.getData()[0]) print(s4.getData()[0]) +print(s5.getData()[0]) + +s5.tabCharPos(1,tabSpaces=4) +s5.tabCharPos(5,tabSpaces=4) +s5.tabCharPos(9,tabSpaces=4) # time.sleep(5)