Stop using errno for input_terminfo_get_sequence errors

Use a real error type. Fixes a TODO and cleans up the code.
This commit is contained in:
ridiculousfish 2024-02-11 15:03:27 -08:00
parent 5021639db1
commit e1d539c7b6
2 changed files with 34 additions and 40 deletions

View file

@ -7,10 +7,9 @@ use crate::common::{
use crate::highlight::{colorize, highlight_shell};
use crate::input::{
input_function_get_names, input_mappings, input_terminfo_get_name, input_terminfo_get_names,
input_terminfo_get_sequence, InputMappingSet,
input_terminfo_get_sequence, GetSequenceError, InputMappingSet,
};
use crate::nix::isatty;
use nix::errno::Errno;
use std::sync::MutexGuard;
const DEFAULT_BIND_MODE: &wstr = L!("default");
@ -195,35 +194,27 @@ impl BuiltinBind {
/// Wraps input_terminfo_get_sequence(), appending the correct error messages as needed.
fn get_terminfo_sequence(&self, seq: &wstr, streams: &mut IoStreams) -> Option<WString> {
let mut tseq = WString::new();
if input_terminfo_get_sequence(seq, &mut tseq) {
return Some(tseq);
}
let err = Errno::last();
if !self.opts.silent {
let eseq = escape_string(seq, EscapeStringStyle::Script(EscapeFlags::NO_PRINTABLES));
if err == Errno::ENOENT {
streams.err.append(wgettext_fmt!(
"%ls: No key with name '%ls' found\n",
"bind",
eseq
));
} else if err == Errno::EILSEQ {
streams.err.append(wgettext_fmt!(
"%ls: Key with name '%ls' does not have any mapping\n",
"bind",
eseq
));
} else {
streams.err.append(wgettext_fmt!(
"%ls: Unknown error trying to bind to key named '%ls'\n",
"bind",
eseq
));
match input_terminfo_get_sequence(seq) {
Ok(tseq) => Some(tseq),
Err(err) if !self.opts.silent => {
let eseq =
escape_string(seq, EscapeStringStyle::Script(EscapeFlags::NO_PRINTABLES));
match err {
GetSequenceError::NotFound => streams.err.append(wgettext_fmt!(
"%ls: No key with name '%ls' found\n",
"bind",
eseq
)),
GetSequenceError::NoSeq => streams.err.append(wgettext_fmt!(
"%ls: Key with name '%ls' does not have any mapping\n",
"bind",
eseq
)),
};
None
}
Err(_) => None,
}
None
}
/// Add specified key binding.

View file

@ -14,7 +14,6 @@ use crate::reader::{
use crate::signal::signal_clear_cancel;
use crate::threads::assert_is_main_thread;
use crate::wchar::prelude::*;
use errno::{set_errno, Errno};
use once_cell::sync::{Lazy, OnceCell};
use std::cell::RefCell;
use std::collections::VecDeque;
@ -1120,29 +1119,33 @@ fn create_input_terminfo() -> Box<[TerminfoMapping]> {
]);
}
/// Possible errors from from input_terminfo_get_sequence.
pub enum GetSequenceError {
/// The mapping was not found.
NotFound,
/// The terminfo variable does not have a value.
NoSeq,
}
/// Return the sequence for the terminfo variable of the specified name.
///
/// If no terminfo variable of the specified name could be found, return false and set errno to
/// ENOENT. If the terminfo variable does not have a value, return false and set errno to EILSEQ.
pub fn input_terminfo_get_sequence(name: &wstr, out_seq: &mut WString) -> bool {
// TODO: stop using errno for this.
pub fn input_terminfo_get_sequence(name: &wstr) -> Result<WString, GetSequenceError> {
let mappings = TERMINFO_MAPPINGS
.get()
.expect("TERMINFO_MAPPINGS not initialized");
for m in mappings.iter() {
if name == m.name {
// Found the mapping.
if m.seq.is_none() {
set_errno(Errno(libc::EILSEQ));
return false;
return if let Some(seq) = &m.seq {
Ok(str2wcstring(seq))
} else {
*out_seq = str2wcstring(m.seq.as_ref().unwrap());
return true;
}
Err(GetSequenceError::NoSeq)
};
}
}
set_errno(Errno(libc::ENOENT));
false
Err(GetSequenceError::NotFound)
}
/// Return the name of the terminfo variable with the specified sequence.