Exploring terminfo

Grant Edwards grant.b.edwards at gmail.com
Fri Jan 15 16:17:22 EST 2021


On 2021年01月15日, Alan Gauld via Python-list <python-list at python.org> wrote:
> On 15/01/2021 17:31, Grant Edwards wrote:
>>>>> cur.putp(cls)
>>>> name = input("Hello, what's your name? ")
>>>>>>>> cur.putp(bold)
>>>> print("Nice to meet you ", name)
>>>>> putp(clr);
>>> putp(bold);
>>> printf("Enter a name: ");
>>> fgets(line, sizeof(line),stdin);
>>>>>> printf("Hello %s\n", line);
>>> exit(0);
>>> One difference is that the name prompt is being written to stdout in
>> the C version and stderr in the Python version. But I don't see why
>> that would matter.
>> That could make a big difference, the putp() function specifically
> states that it writes to stdout.
>>> I suspect that the problem is that putp is writing to the libc
>> "stdout" FILE stream that's declaredin <stdio.h>. That stream
>> layer/object has buffering that is invisible to Python. 
>> That would indeed explain it.
>>> Now the question: is there a way to tell the curses module to flush
>> its stdout FILE stream?
>> Indeed. But unless it's trivial it rather defeats the concept of
> using the terminfo functions to create text effects without
> diving into full curses screen control! And that was what I
> was hoping to uncover.
>> I wonder if I can use the os module to mess with the
> file descriptors.... hmmm.

Yes, but that doesn't help. You need to flush the libc FILE *stdio not
the underlying file descriptor. Here's how you do it:
 import os,ctypes,sys,time
 
 libc = ctypes.CDLL(None, use_errno=True)
 
 import curses as cur
 cur.setupterm()
 
 bold = cur.tigetstr('bold')
 norm = cur.tigetstr('sgr0')
 cls = cur.tigetstr('clear')
 
 cur.putp(cls)
 libc.fflush(None)
 name = input("Enter your name: ")
 cur.putp(bold)
 libc.fflush(None)
 sys.stdout.write("\nNice to meet you " + name + "\n")
 cur.putp(norm);
 libc.fflush(None)
 input("Hit enter to exit")
The call to libc.fflush(None) flushes all output FILE * streams. If
you really just want to flush stdout, to flush just stdout:
 import os,ctypes,sys,time
 libc = ctypes.CDLL(None, use_errno=True)
 stdout = ctypes.c_void_p.in_dll(libc, 'stdout')
 import curses as cur
 cur.setupterm()
 bold = cur.tigetstr('bold')
 norm = cur.tigetstr('sgr0')
 cls = cur.tigetstr('clear')
 cur.putp(cls)
 libc.fflush(stdout)
 name = input("Enter your name: ")
 cur.putp(bold)
 libc.fflush(stdout)
 sys.stdout.write("\nNice to meet you " + name + "\n")
 cur.putp(norm);
 libc.fflush(stdout)
 input("Hit enter to exit")
I'd wrap cur.putp() to make it less ugly:
 import os,ctypes,sys,time
 libc = ctypes.CDLL(None, use_errno=True)
 stdout = ctypes.c_void_p.in_dll(libc, 'stdout')
 import curses as cur
 cur.setupterm()
 def putp(*args):
 sys.stderr.flush()
 sys.stdout.flush()
 cur.putp(*args)
 libc.fflush(stdout)
 bold = cur.tigetstr('bold')
 norm = cur.tigetstr('sgr0')
 cls = cur.tigetstr('clear')
 putp(cls)
 name = input("Enter your name: ")
 putp(bold)
 print("Nice to meet you",name)
 putp(norm);
 input("Hit enter to exit")


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /