Is your feature request related to a problem? Please describe.
enable_raw_mode() goes through cfmakeraw() / Termios::make_raw(), which clears OPOST along with everything else. This is documented and, for a full-screen application, correct:
New line character will not be processed therefore
println!can't be used, usewrite!instead
It is a problem for a program that puts a line editor on the terminal rather than taking the whole screen over, because such a program does not own the terminal exclusively — other writers share it. Once OPOST is off, a bare \n moves down a row without returning to column 0, so anything writing to that terminal that isn't the crossterm application staircases:
AAA
BBB
CCCThe application's own output is fine, since it writes \r\n deliberately. The output that breaks belongs to whatever else has the same tty — for a shell, a background job and every process it spawns.
I hit this writing a shell. ( sleep 3; echo AAA; echo BBB; echo CCC ) & staircases exactly as above while the prompt is up. GNU readline has the same problem to solve and solves it by leaving output processing alone: it turns off echo and canonical input (ECHO, ICANON, ISIG, and input flags), but does not touch c_oflag. That's why background output under bash lands flush left.
Describe the solution you'd like
An opt-in raw mode that leaves output post-processing on — the input half of raw mode without the output half. Something like:
crossterm::terminal::enable_raw_mode_with(RawModeOptions { output_processing: true })or a separate enable_line_editing_mode(), whichever fits crossterm's API taste better. Concretely it is cfmakeraw() followed by restoring OPOST | ONLCR:
fn raw_terminal_attr(termios: &mut Termios) {
unsafe { cfmakeraw(termios) }
if keep_output_processing {
termios.c_oflag |= libc::OPOST | libc::ONLCR;
}
}with the equivalent on the rustix path (termios.output_modes |= OutputModes::OPOST | OutputModes::ONLCR). Windows needs nothing: ENABLE_VIRTUAL_TERMINAL_PROCESSING already handles \n as CR-LF, which is why this is a Unix-only difference.
Describe alternatives you've considered
- Translating in the application. Doesn't work — the output isn't the application's. It comes from unrelated processes writing to the shared tty.
- Setting termios directly around crossterm. Possible, but it means duplicating the raw-mode logic and fighting
enable_raw_mode's saved-state bookkeeping, and it is exactly the sort of thing #931 asks crossterm to make unnecessary. - Patching crossterm locally. What I'm doing now, which is why I'm raising it.
Additional context
Related to #931 in spirit: both are cases where a downstream program needs raw mode with one specific flag left alone, and currently has to go around crossterm to get it. If a general "raw mode with these termios adjustments" facility were preferable to a one-flag option, that would cover both.
I'm happy to open a PR for whichever shape you'd prefer.
Activity
0No activity yet.