I would like to read from stdin
on a per character basis without the stdin
being flushed. I could not find how to do that after tweaking for hours. Tcl always seems to wait for the channel to be flushed even in fconfigure stdin -blocking 0 -buffering none
. Is that true? How would I otherwise approach this?
More explanation:
Imagine a Tcl program that makes its own prompt with some threads running code in the background. I would like this prompt to react to single keystrokes, for example: when you press 'p' (without pressing enter
) the prompt reads that character and pauses the threads, when you press 'q' the prompt kills the threads and stops the program. The cleanest and closest solution is shortly demonstrated in the following code snippet.
proc readPrompt { } {
set in [ read stdin 1 ]
if { $in eq "q" } {
puts "Quitting..."
set ::x 1
} {
puts "Given unknown command $in"
}
}
fconfigure stdin -blocking 0 -buffering none
fileevent stdin readable { readPrompt }
vwait x
The result from running this is:
a
Given unknown command a
Given unknown command
After pressing the 'a', nothing happens. My guess is that the stdin
is not flushed or something. Pressing enter
or CTRL-d
triggers the fileevent and the prompt then reads both the characters 'a' and 'enter
'.
Ideally, I want the enter
-press not to be needed. How could I accomplish this?
EDIT: I found this question and solution about a related use in Python: Determine the terminal cursor position with an ANSI sequence in Python 3 This is approximately the behaviour I'm looking for, but in Tcl.