My program constantly outputs text to the terminal. I need the user input line to always stay below this output; if the user types something, it shouldn't jump over the output.
Is there any Ruby library that can provide this functionality?
There could not be any ruby library providing this functionality since none of the known terminals support splitting the areas inside themselves.
This is the terminal issue: they are not capable of dividing their internal window into two parts.
What you can do, though, it to use two different shells for input and for output with IO#popen.
Related
In a C# console application for Windows, I'm am using the Windows Console API WriteConsoleOutput (via PInvoke) to write an entire buffer in a single operation to prevent flickering. This works fine.
Microsoft recommends using virtual terminal sequences to interact with the console. These sequences are great, as they offer much better output, such as colors, etc.
But, as I understand it, WriteConsoleOutput cannot be used with escape sequences (see CHAR_INFO).
My question is,
How can I use virtual terminal sequences to write to the console flicker-free?
I'd like to update different parts of the screen with different characters and colors. Doing this by chaining a lot of Console.Write() and Console.SetCursorPosition will cause a lot of flickering and reduce framerate.
What is the virtual terminal equivalent of writing an entire buffer?
I hate to answer my own question, but I have found a solution after a couple of days' experimenting.
The answer to this question:
What is the virtual terminal equivalent of writing an entire buffer?
There is none.
Not exactly.
I haven't found anything similar to WriteConsoleOutput, which renders a pre-populated buffer of an arbitrary size.
However, virtual terminals have the concept of alternate screen buffers, which can be created by CreateConsoleScreenBuffer and switched with SetConsoleActiveScreenBuffer.
Using that, I came up with a solution for my first question:
How can I use virtual terminal sequences to write to the console flicker-free?
Basically, what I do is I create a new buffer and then use WriteConsole to write VT escape sequences to the back buffer before I switch the buffers.
The thing I don't like about this solution is the call to WriteConsole. There will be a lot of them (writing characters/sequences one by one), or there will be few of them when writing long pre-escaped strings.
In order to test flickering, I created a single string with 120 x 30 characters, with each character given a 256-color. This produced a string of over 41'000 characters, which was used as input to WriteConsole.
This actually seems to work pretty well!
This is the best solution I have found so far. If you find a better one, please write your own answer here!
I am writing a small shell in Rust on Linux as an exercise and I wanted to implement command history as well as cursor moving (i.e. moving back the cursor to edit a typo in the command).
I did not find a way in the Rust standard library to handle arrow key events, but I found the Termion crate which handles key events.
However, handling key events with Termion means entering "raw mode" for stdout, which overrides "legacy" functionalities, as described in this article about the crate:
Without raw mode, you cannot write a proper interactive TTY application. Raw mode gives you complete control over the TTY:
It disables the line buffering: As you might notice, your command-line application tends to behave like the command-line. The programs will first get the input when the user types \n. Raw mode makes the program get the input after every key stroke.
It disables displaying the input: Without raw mode, the things you type appear on the screen, making it insufficient for most interactive TTY applications, where keys can represent controls and not textual input.
It disables canonicalization of the output: For example, \n represents “go one cell down” not “break the line”, for line breaks \n\r is needed.
It disables scrolling.
I find this solution a bit overkill, as I want to retain most of the "legacy" I/O functionalities. Is there another way to handle arrow key input, or will I need to use the raw mode?
There are several crates that provide line editing features for interactive programs. Here are a few that I found by searching crates.io for "readline" (the name of a C library):
rustyline seems to be the most popular on crates.io.
liner
linefeed
linenoise-rust is a set of Rust bindings to the linenoise library written in C.
I haven't used any of them, so this list is not a recommendation. Take a look at a few of them and choose one that suits your needs.
I know how to make the last line of a terminal app refresh itself by clearing \r carriage return at the line.
How can I do this with more lines than just the last? (how do programs like vi do it?)
EDIT
Without externals such like ncurses, tput, etc
How can I do this with more lines than just the last? (how do programs
like vi do it?)
They're using ncurses, termcap, terminfo, the lot.
If you want to do it without using curses and the like, then you'll have to know which terminal control codes to send for each different terminal type that you plan to support.
You also need to know how to achieve the required effect in terms of the operations that each terminal does support. Some terminals may have a single 'clear to end of screen' command; others may require many characters to be written.
On the whole, it might be easier to use something designed to handle the job — and the terminfo terminal database.
I'm writing a command interpreter like BASH, and a \ followed by a newline implies a continuation of the input stream; how can I implement that in Win32?
If I use the console mode with ENABLE_LINE_INPUT, then the user can't press backspace in order to go back to the previous line; Windows prevents him from doing so. But if I don't set ENABLE_LINE_INPUT, then I have to manually reposition the cursor, which is rather tedious given that (1) the user might have redirected the input stream, and that (2) it might be prone to race conditions, and I'd rather have Windows do it if I can.
Any way to have my newline and eat it too?
Edit:
If this would require undocumented CSRSS port requests, then I'm still interested!
Assuming you want this to run in a window, like command prompt does by default, rather than full screen, you could create a GUI application with a large textbox. Users would type into the textbox, and you could parse whatever was entered, and output to the same box (effectively emulated the Win32 Console).
This way whatever rules you want to set for how the console behaves is completely up to you.
I might be mistaken is saying this, but I believe that the Win32 Console from XP onward works exactly like this, and it just listens for output on stdout; there shouldn't be any reason you can't do the same.
Hope this was helpful.
Is there a terminal program that shows the difference between input, standard output, error output, the prompt, and user-entered commands? It should also show when standard input is needed vs. running a command.
One way would be to highlight each differently. The cursor could change color depending on if it was waiting for a command, running a command, or waiting for standard input.
Another way would be to have 3 frames -- a large frame on the top for output (including prompt and commands running), a small frame near the bottom for standard input, and an one-line frame at the bottom for command line input. That would possibly even allow running another command to provide input while the previous command is still waiting for standard input.
From http://jamesjava.blogspot.com/2007/09/terminal-window-with-3-frames.html
Hotwire could be a good candidate, but it's not doing that out of the box, AFAIK
For now it appears that there is no such program.
My program gush (Graphical User SHell) does part of this.
It uses different colours for commands and program stdin/stdout/stderr.
Note that the traditional separation of shell and terminal makes this
impossible because the interface between them models an old serial
terminal connection and therefore only has a single input and single
output channel. I get around this problem by combining shell and
terminal into one program.
It would be nice to also indicate when a program is waiting for input,
but I don't think there's any way to detect this, unless you traced the
system calls of the child program to detect when it tries to read stdin.
For interactive programs, you can guess that if the last output did not
end with newline it's probably prompting for input, but this would not
work for non-interactive programs, eg. sed.