diff options
author | Helmut Grohne <helmut@subdivi.de> | 2016-12-09 11:54:25 +0100 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2016-12-09 11:54:25 +0100 |
commit | f6f8d6d50b7823266684807eb4cad1db3e74c0d9 (patch) | |
tree | 1ca6bc1647ae74f267c19afed0b25df042024ef5 | |
parent | c285a5ff7665f41684a1f100679b6361ad6383af (diff) | |
download | tcvt-f6f8d6d50b7823266684807eb4cad1db3e74c0d9.tar.gz |
push the refresh logic into the Terminal class
One advantage of doing so is that the main function becomes simpler.
Another advantage is that the Terminal class has better knowledge of
when refreshes are actually needed. It also means that one more refresh
call can be coalesced into the logic. The major downside is that it
requires annotating all screen operations.
-rwxr-xr-x | tcvt.py | 66 |
1 files changed, 50 insertions, 16 deletions
@@ -315,13 +315,14 @@ class Terminal: self.lastchar = ord(b' ') self.columns = columns self.reverse = reverse + self.need_refresh = None def switchmode(self): if isinstance(self.screen, Columns): self.screen = Simple(self.realscreen) else: self.screen = Columns(self.realscreen, self.columns) - self.screen.refresh() + self.request_refresh() def resized(self): # The refresh call causes curses to notice the new dimensions. @@ -332,15 +333,32 @@ class Terminal: reverse=self.reverse) except BadWidth: self.screen = Simple(self.realscreen) + self.request_refresh() def resizepty(self, ptyfd): ym, xm = self.screen.getmaxyx() fcntl.ioctl(ptyfd, termios.TIOCSWINSZ, struct.pack("HHHH", ym, xm, 0, 0)) + def refresh_needed(self): + return self.need_refresh is not None + + def request_refresh(self): + if self.need_refresh is None: + self.need_refresh = time.time() + + def refresh(self, minwait=0): + if self.need_refresh is None: + return + if minwait > 0 and self.need_refresh + minwait > time.time(): + return + self.screen.refresh() + self.need_refresh = None + def addch(self, char): self.lastchar = char self.screen.addch(char) + self.request_refresh() def __enter__(self): self.realscreen = curses.initscr() @@ -371,27 +389,32 @@ class Terminal: def do_cr(self): self.screen.relmove(0, -9999) + self.request_refresh() def do_cub(self, n): self.screen.relmove(0, -n) + self.request_refresh() def do_cub1(self): self.do_cub(1) def do_cud(self, n): self.screen.relmove(n, 0) + self.request_refresh() def do_cud1(self): self.do_cud(1) def do_cuf(self, n): self.screen.relmove(0, n) + self.request_refresh() def do_cuf1(self): self.do_cuf(1) def do_cuu(self, n): self.screen.relmove(-n, 0) + self.request_refresh() def do_cuu1(self): self.do_cuu(1) @@ -399,6 +422,7 @@ class Terminal: def do_dch(self, n): for _ in range(n): self.screen.delch() + self.request_refresh() def do_dch1(self): self.do_dch(1) @@ -406,6 +430,7 @@ class Terminal: def do_dl(self, n): for _ in range(n): self.screen.deleteln() + self.request_refresh() def do_dl1(self): self.do_dl(1) @@ -413,39 +438,49 @@ class Terminal: def do_ech(self, n): for _ in range(n): self.screen.addch(ord(b' ')) + self.request_refresh() def do_ed(self): self.screen.clrtobot() + self.request_refresh() def do_el(self): self.screen.clrtoeol() + self.request_refresh() def do_el1(self): y, x = self.screen.getyx() - self.screen.move(y, 0) - for _ in range(x): - self.screen.addch(ord(b' ')) + if x > 0: + self.screen.move(y, 0) + for _ in range(x): + self.screen.addch(ord(b' ')) + self.request_refresh() def do_home(self): self.screen.move(0, 0) + self.request_refresh() def do_hpa(self, n): y, _ = self.screen.getyx() self.screen.move(y, n) + self.request_refresh() def do_ht(self): y, x = self.screen.getyx() _, xm = self.screen.getmaxyx() x = min(x + 8 - x % 8, xm - 1) self.screen.move(y, x) + self.request_refresh() def do_ich(self, n): for _ in range(n): self.screen.insch(ord(b' ')) + self.request_refresh() def do_il(self, n): for _ in range(n): self.screen.insertln() + self.request_refresh() def do_il1(self): self.do_il(1) @@ -458,6 +493,7 @@ class Terminal: self.screen.move(y, 0) else: self.screen.move(y+1, 0) + self.request_refresh() def do_invis(self): self.screen.attron(curses.A_INVIS) @@ -468,6 +504,7 @@ class Terminal: def do_vpa(self, n): _, x = self.screen.getyx() self.screen.move(n, x) + self.request_refresh() def feed_reset(self): if self.graphics_font: @@ -595,14 +632,17 @@ class Terminal: if len(parts) != 2: raise ValueError("feed esc [ %r H" % parts) self.screen.move(*map((-1).__add__, map(int, parts))) + self.request_refresh() elif prev == bytearray(b'2') and char == ord(b'J'): self.screen.move(0, 0) self.screen.clrtobot() + self.request_refresh() elif char == ord(b'd') and prev.isdigit(): self.do_vpa(int(prev) - 1) elif char == ord(b'b') and prev.isdigit(): for _ in range(int(prev)): self.screen.addch(self.lastchar) + self.request_refresh() elif char == ord(b'G') and prev.isdigit(): self.do_hpa(int(prev) - 1) elif char == ord(b'K') and prev == b'1': @@ -705,11 +745,10 @@ def main(): with process as masterfd: with Terminal(acsc, options.columns, reverse=options.reverse) as t: t.resizepty(masterfd) - refreshpending = None while True: + timeout = 0 if t.refresh_needed() else None try: - res, _, _ = select.select([0, masterfd], [], [], - refreshpending and 0) + res = select.select([0, masterfd], [], [], timeout)[0] except select.error as err: if err.args[0] == errno.EINTR: t.resized() @@ -731,6 +770,7 @@ def main(): else: if "TCVT_DEVEL" in os.environ: raise ValueError("getch returned %d" % key) + t.refresh(0.1) elif masterfd in res: try: data = os.read(masterfd, 1024) @@ -746,15 +786,9 @@ def main(): t.feed(char) except ValueError: t.feed_reset() - if refreshpending is None: - refreshpending = time.time() + 0.1 - elif refreshpending is not None: - t.screen.refresh() - refreshpending = None - if refreshpending is not None and \ - refreshpending < time.time(): - t.screen.refresh() - refreshpending = None + t.refresh(0.1) + else: + t.refresh() except ExecutionError as err: print(str(err)) sys.exit(255) |