forked from Imagelibrary/littlefs
scripts: Fixed most flickering issues in RingIO
Two new tricks: 1. Hide the cursor while redrawing the ring buffer. 2. Build up the entire redraw in RAM first, and render everything in a single write call. These _mostly_ get rid of the cursor flickering issues in rapidly updating scripts.
This commit is contained in:
@@ -88,6 +88,7 @@ else:
|
||||
else:
|
||||
self.add_watch(path, flags)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -140,7 +141,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -158,24 +161,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
def iself(path):
|
||||
|
||||
@@ -3644,6 +3644,7 @@ else:
|
||||
else:
|
||||
self.add_watch(path, flags)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -3696,7 +3697,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -3714,24 +3717,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
# a representation of optionally key-mapped attrs
|
||||
|
||||
@@ -137,6 +137,7 @@ def rbydaddr(s):
|
||||
return tuple(addr)
|
||||
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -189,7 +190,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -207,24 +210,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
# a representation of optionally key-mapped attrs
|
||||
|
||||
@@ -171,6 +171,7 @@ else:
|
||||
else:
|
||||
self.add_watch(path, flags)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -223,7 +224,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -241,24 +244,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ def openio(path, mode='r', buffering=-1):
|
||||
else:
|
||||
return open(path, mode, buffering)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -86,7 +87,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -104,24 +107,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ else:
|
||||
else:
|
||||
self.add_watch(path, flags)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -133,7 +134,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -151,24 +154,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
# parse different data representations
|
||||
|
||||
@@ -72,6 +72,7 @@ else:
|
||||
else:
|
||||
self.add_watch(path, flags)
|
||||
|
||||
# a pseudo-stdout ring buffer
|
||||
class RingIO:
|
||||
def __init__(self, maxlen=None, head=False):
|
||||
self.maxlen = maxlen
|
||||
@@ -124,7 +125,9 @@ class RingIO:
|
||||
if lines[-1]:
|
||||
self.tail.write(lines[-1])
|
||||
|
||||
# keep track of maximum drawn canvas
|
||||
canvas_lines = 1
|
||||
|
||||
def draw(self):
|
||||
# did terminal size change?
|
||||
self.resize(self.maxlen)
|
||||
@@ -142,24 +145,44 @@ class RingIO:
|
||||
else:
|
||||
lines.popleft()
|
||||
|
||||
# first thing first, give ourself a canvas
|
||||
# build up the redraw in memory first and render in a single
|
||||
# write call, this minimizes flickering caused by the cursor
|
||||
# jumping around
|
||||
canvas = []
|
||||
|
||||
# hide the cursor
|
||||
canvas.append('\x1b[?25l')
|
||||
|
||||
# give ourself a canvas
|
||||
while RingIO.canvas_lines < len(lines):
|
||||
sys.stdout.write('\n')
|
||||
canvas.append('\n')
|
||||
RingIO.canvas_lines += 1
|
||||
|
||||
# write lines from top to bottom so later lines overwrite earlier
|
||||
# lines, note [xA/[xB stop at terminal boundaries
|
||||
# lines, note xA/xB stop at terminal boundaries
|
||||
for i, line in enumerate(lines):
|
||||
# move cursor, clear line, disable/reenable line wrapping
|
||||
sys.stdout.write('\r')
|
||||
# move to col 0
|
||||
canvas.append('\r')
|
||||
# move up to line
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dA' % (len(lines)-1-i))
|
||||
sys.stdout.write('\x1b[K')
|
||||
sys.stdout.write('\x1b[?7l')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\x1b[?7h')
|
||||
canvas.append('\x1b[%dA' % (len(lines)-1-i))
|
||||
# clear line
|
||||
canvas.append('\x1b[K')
|
||||
# disable line wrap
|
||||
canvas.append('\x1b[?7l')
|
||||
# print the line
|
||||
canvas.append(line)
|
||||
# enable line wrap
|
||||
canvas.append('\x1b[?7h') # enable line wrap
|
||||
# move back down
|
||||
if len(lines)-1-i > 0:
|
||||
sys.stdout.write('\x1b[%dB' % (len(lines)-1-i))
|
||||
canvas.append('\x1b[%dB' % (len(lines)-1-i))
|
||||
|
||||
# show the cursor again
|
||||
canvas.append('\x1b[?25h')
|
||||
|
||||
# write to stdout and flush
|
||||
sys.stdout.write(''.join(canvas))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user