Capabilities
A terminal will tell you about itself if you ask. Capabilities is where
Program keeps those answers, exactly as the
terminal gave them rather than boiled down to a verdict.
Asking is always something you do on purpose, and the answers come back as
ordinary events that Program notices on the way past. Querying the
terminal covers how to ask
and how long to wait.
Answers, not verdicts
“The terminal said no” and “the terminal never replied” are different things,
and a plain yes-or-no cannot tell them apart. Silence is common: terminals are
free to ignore a question they do not recognize. So anything that might go
unanswered comes back as an Option, and None always means you never heard
back.
use uncurses::ansi::mode::{Mode, ModeSetting};
use uncurses::program::Program;
fn main() -> std::io::Result<()> {
let mut program = Program::stdio()?;
program.init()?;
program.query_capabilities(&[])?;
// ... read events until the answers arrive ...
let caps = program.capabilities();
match caps.mode(Mode::SYNCHRONIZED_OUTPUT) {
Some(ModeSetting::NotRecognized) => {} // a definite no
Some(ModeSetting::PermanentlyReset) => {} // known, but never usable
Some(_) => {} // supported, in some form
None => {} // never answered
}
// Or just the yes-or-no question.
let _pixels = caps.supports(Mode::MOUSE_SGR_PIXEL);
program.finish()
}supports() collapses the five states into the one answer most callers want.
It is true where the mode is usable, so PermanentlyReset reads as a no: the
terminal knows the mode and will never let it be set.
A few answers are a plain bool, because for those the silence is the answer: a
terminal that does not support the feature simply never responds. The
Capabilities API
reference lists everything that
gets recorded.
One kind of question
Because it holds answers, Capabilities tells you one thing only: what the
terminal said. Anything that has to weigh a reply against other evidence lives
elsewhere.
Color is the case worth knowing. Whether the terminal handles full color is often clear from the environment alone, without asking it anything, so the answer lives with the color settings on the screen, which take everything into account. What the terminal actually replied stays here, for when you want to know how that conclusion was reached.
What the terminal can tell you
Every reply that says what it is about lands here, not just the answers the program acts on, so a question you send yourself is readable afterwards alongside the built-in ones. Where there are many answers of a kind, such as palette entries, you can read the whole set.
A DECRQSS setting report is the reply that cannot. A success repeats the setting
and its parameters together, so 0;1m and >4;2m carry nothing that could key
a record, and a refusal is empty. Only the request you sent says what was asked.
Program never sends DECRQSS, so it has no request to match against and hands
the reply through as Event::SettingReport untouched.
Sizes are the other exception, because they keep changing. The window and cell
dimensions arrive as replies too, but they are superseded by every resize, so
they live on Program as window_cells(), window_pixels() and
cell_pixels() rather than as a recorded answer.
The other half of what a program knows about its surroundings never arrives as
an answer at all. program.env() reads the environment, so TERM,
COLORTERM, and TERM_PROGRAM are readable without reaching for std::env.
program.terminal() gets you the terminal itself, for its size. Both are
read-only: an environment is only ever read, and the terminal is the program’s
to change, since it keeps its own record of what it changed so it can put
everything back.
Answers that keep arriving
Most questions are answered once. Three keep updating. The color scheme follows the user switching between dark and light mode, and terminal visibility follows the view being covered or uncovered, for as long as you leave those updates turned on, and graphics support is confirmed by any graphics response, including the ones a terminal sends back while you are transmitting an image.
The colors recorded here are the terminal’s own, which is the opposite of what
Program remembers. Set the background color and capabilities() still reports
what the terminal originally told you, while the value you sent is what
Program knows to undo.
Settings that wait for an answer
Some startup settings hold off until the terminal confirms it supports the feature, so they do nothing until you ask. The ones that switch on a terminal mode are switched on the same way you would switch them on yourself, so teardown puts them back like anything else. Synchronized output is the exception: adopting it sets a render property rather than a mode, so there is nothing to put back.
You can turn this off, in which case the answer is still recorded but acting on it is left to you. Querying the terminal has the details.