Reputation: 46423
I'd like to have both:
Lines displayed each one after another (Blah 12, Blah 13, Blah 14, etc.) like in a normal terminal
Fixed position information (on right) : Date + fixed text "Bonjour"
It nearly works, until ~ Blah 250, when the look is destroyed! Why?
(source: gget.it)
from sys import stdout
import time
ESC = "\x1b"
CSI = ESC+"["
def movePos(row, col):
stdout.write("%s%d;%dH" % (CSI, row, col))
stdout.write("%s2J" % CSI) # CLEAR SCREEN
for i in range(1,1000):
movePos(i+1,60)
print time.strftime('%H:%M:%S', time.gmtime())
movePos(i+5,60)
print 'Bonjour'
movePos(24+i,0)
print "Blah %i" % i
time.sleep(0.01)
With an ANSI terminal, how to have both normal terminal behaviour (one new line for each print
) + fixed position display?
Note: On Windows, I use ansicon.exe to have ANSI support in Windows cmd.exe.
Upvotes: 0
Views: 862
Reputation: 46423
Here is a solution:
(source: gget.it)
The code is (check here for latest version):
"""
zeroterm is a light weight terminal allowing both:
* lines written one after another (normal terminal/console behaviour)
* fixed position text
Note: Requires an ANSI terminal. For Windows 7, please download https://github.com/downloads/adoxa/ansicon/ansi160.zip and run ansicon.exe -i to install it.
"""
from sys import stdout
import time
class zeroterm:
def __init__(self, nrow=24, ncol=50): # nrow, ncol determines the size of the scrolling (=normal terminal behaviour) part of the screen
stdout.write("\x1b[2J") # clear screen
self.nrow = nrow
self.ncol = ncol
self.buf = []
def write(self, s, x=None, y=None): # if no x,y specified, normal console behaviour
if x is not None and y is not None: # if x,y specified, fixed text position
self.movepos(x,y)
print s
else:
if len(self.buf) < self.nrow:
self.buf.append(s)
else:
self.buf[:-1] = self.buf[1:]
self.buf[-1] = s
for i, r in enumerate(self.buf):
self.movepos(i+1,0)
print r[:self.ncol].ljust(self.ncol)
def movepos(self, row, col):
stdout.write("\x1b[%d;%dH" % (row, col))
if __name__ == '__main__':
# An exemple
t = zeroterm()
t.write('zeroterm', 1, 60)
for i in range(1000):
t.write(time.strftime("%H:%M:%S"), 3, 60)
t.write("Hello %i" % i)
time.sleep(0.1)
Upvotes: 1
Reputation: 54505
From the given picture: ansicon appears to be allocating a console buffer to do its work; that has a limited size (due to the Windows console, which limits the buffer size to 64 kilobytes). Once your script reaches the end of the buffer and tries to move the cursor past the end, ansicon forces the whole buffer to scroll up. That makes the style of update change.
If your calls to movePos
were bounded within ansicon's workspace, you would get more consistent results.
Regarding the "multiple lines" for "Bonjour", this chunk
movePos(i+1,60)
print time.strftime('%H:%M:%S', time.gmtime())
movePos(i+5,60)
print 'Bonjour'
is printing the date on one line, and then moving forward 4 lines, printing "Bonjour" on the same column. It seems that there's enough space (10 columns) on the same line to do this:
movePos(i+1,60)
print time.strftime('%H:%M:%S', time.gmtime())
movePos(i+1,70)
print 'Bonjour'
which would at least make the text on the right look consistent. The scrolling from movePos
will cause some double-spacing at times though.
Upvotes: 0