A semi-functional non-gui replacement for tkinter.Text text editors. The mock's data model is that a text is a list of \n-terminated lines. The mock adds an empty string at the beginning of the list so that the index of actual lines start at 1, as with Tk. The methods never see this.
| 92 | |
| 93 | |
| 94 | class Text: |
| 95 | """A semi-functional non-gui replacement for tkinter.Text text editors. |
| 96 | |
| 97 | The mock's data model is that a text is a list of \n-terminated lines. |
| 98 | The mock adds an empty string at the beginning of the list so that the |
| 99 | index of actual lines start at 1, as with Tk. The methods never see this. |
| 100 | Tk initializes files with a terminal \n that cannot be deleted. It is |
| 101 | invisible in the sense that one cannot move the cursor beyond it. |
| 102 | |
| 103 | This class is only tested (and valid) with strings of ascii chars. |
| 104 | For testing, we are not concerned with Tk Text's treatment of, |
| 105 | for instance, 0-width characters or character + accent. |
| 106 | """ |
| 107 | def __init__(self, master=None, cnf={}, **kw): |
| 108 | '''Initialize mock, non-gui, text-only Text widget. |
| 109 | |
| 110 | At present, all args are ignored. Almost all affect visual behavior. |
| 111 | There are just a few Text-only options that affect text behavior. |
| 112 | ''' |
| 113 | self.data = ['', '\n'] |
| 114 | |
| 115 | def index(self, index): |
| 116 | "Return string version of index decoded according to current text." |
| 117 | return "%s.%s" % self._decode(index, endflag=1) |
| 118 | |
| 119 | def _decode(self, index, endflag=0): |
| 120 | """Return a (line, char) tuple of int indexes into self.data. |
| 121 | |
| 122 | This implements .index without converting the result back to a string. |
| 123 | The result is constrained by the number of lines and linelengths of |
| 124 | self.data. For many indexes, the result is initially (1, 0). |
| 125 | |
| 126 | The input index may have any of several possible forms: |
| 127 | * line.char float: converted to 'line.char' string; |
| 128 | * 'line.char' string, where line and char are decimal integers; |
| 129 | * 'line.char lineend', where lineend='lineend' (and char is ignored); |
| 130 | * 'line.end', where end='end' (same as above); |
| 131 | * 'insert', the positions before terminal \n; |
| 132 | * 'end', whose meaning depends on the endflag passed to ._endex. |
| 133 | * 'sel.first' or 'sel.last', where sel is a tag -- not implemented. |
| 134 | """ |
| 135 | if isinstance(index, (float, bytes)): |
| 136 | index = str(index) |
| 137 | try: |
| 138 | index=index.lower() |
| 139 | except AttributeError: |
| 140 | raise TclError('bad text index "%s"' % index) from None |
| 141 | |
| 142 | lastline = len(self.data) - 1 # same as number of text lines |
| 143 | if index == 'insert': |
| 144 | return lastline, len(self.data[lastline]) - 1 |
| 145 | elif index == 'end': |
| 146 | return self._endex(endflag) |
| 147 | |
| 148 | line, char = index.split('.') |
| 149 | line = int(line) |
| 150 | |
| 151 | # Out of bounds line becomes first or last ('end') index |
no outgoing calls
searching dependent graphs…