summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Samuelsson <msamuelsson@storvix.eu>2023-07-12 11:42:29 +0200
committerMartin Samuelsson <msamuelsson@storvix.eu>2023-07-12 11:53:05 +0200
commita2c20a841048d9a92f6069b50b0bf4738881ea3e (patch)
treef42d939d0b7ec3f3073701e930f18014f5bed2fd
parenta855443e93bc1b31cdcee84f8ed0aa55bdc55aa1 (diff)
downloadrustyline-a2c20a841048d9a92f6069b50b0bf4738881ea3e.zip
Use termios from termios cratefix/use_termios_crate
The termios interface from the nix crate is lacking a thought through design. Severely broken on at least one platform. Please see [#2071][] for details. The termios crate stays closer to the C API and thus both works with illumos and reduces the risk of bugs on other platforms. [#2071]: https://github.com/nix-rust/nix/issues/2071
-rw-r--r--Cargo.toml1
-rw-r--r--src/tty/unix.rs46
2 files changed, 25 insertions, 22 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c19750c..5be68e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -46,6 +46,7 @@ nix = { version = "0.26", default-features = false, features = ["fs", "ioctl", "
utf8parse = "0.2"
skim = { version = "0.10", optional = true, default-features = false }
signal-hook = { version = "0.3", optional = true, default-features = false }
+termios = "0.3.3"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["consoleapi", "handleapi", "synchapi", "minwindef", "processenv", "std", "winbase", "wincon", "winuser"] }
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 23bfcce..8166db7 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -13,7 +13,7 @@ use log::{debug, warn};
use nix::errno::Errno;
use nix::poll::{self, PollFlags};
use nix::sys::select::{self, FdSet};
-use nix::sys::termios::{self, SetArg, SpecialCharacterIndices as SCI, Termios};
+use termios::{tcsetattr, tcgetattr, Termios};
use nix::unistd::{close, isatty, read, write};
use unicode_segmentation::UnicodeSegmentation;
use utf8parse::{Parser, Receiver};
@@ -106,7 +106,8 @@ pub type Mode = PosixMode;
impl RawMode for PosixMode {
/// Disable RAW mode for the terminal.
fn disable_raw_mode(&self) -> Result<()> {
- termios::tcsetattr(self.tty_in, SetArg::TCSADRAIN, &self.termios)?;
+ let mut termios = self.termios;
+ tcgetattr(self.tty_in, &mut termios)?;
// disable bracketed paste
if let Some(out) = self.tty_out {
write_all(out, BRACKETED_PASTE_OFF)?;
@@ -1202,8 +1203,10 @@ impl SigWinCh {
}
}
-fn map_key(key_map: &mut HashMap<KeyEvent, Cmd>, raw: &Termios, index: SCI, name: &str, cmd: Cmd) {
- let cc = char::from(raw.control_chars[index as usize]);
+fn map_key(
+ key_map: &mut HashMap<KeyEvent, Cmd>, raw: &Termios, index: usize, name: &str, cmd: Cmd)
+{
+ let cc = char::from(raw.c_cc[index]);
let key = KeyEvent::new(cc, M::NONE);
debug!(target: "rustyline", "{}: {:?}", name, key);
key_map.insert(key, cmd);
@@ -1326,38 +1329,37 @@ impl Term for PosixTerminal {
fn enable_raw_mode(&mut self) -> Result<(Self::Mode, PosixKeyMap)> {
use nix::errno::Errno::ENOTTY;
- use nix::sys::termios::{ControlFlags, InputFlags, LocalFlags};
if !self.is_in_a_tty {
return Err(ENOTTY.into());
}
- let original_mode = termios::tcgetattr(self.tty_in)?;
- let mut raw = original_mode.clone();
+ let original_mode = Termios::from_fd(self.tty_in)?;
+ let mut raw = original_mode;
// disable BREAK interrupt, CR to NL conversion on input,
// input parity check, strip high bit (bit 8), output flow control
- raw.input_flags &= !(InputFlags::BRKINT
- | InputFlags::ICRNL
- | InputFlags::INPCK
- | InputFlags::ISTRIP
- | InputFlags::IXON);
+ raw.c_iflag &= !(termios::BRKINT
+ | termios::ICRNL
+ | termios::INPCK
+ | termios::ISTRIP
+ | termios::IXON);
// we don't want raw output, it turns newlines into straight line feeds
// disable all output processing
// raw.c_oflag = raw.c_oflag & !(OutputFlags::OPOST);
// character-size mark (8 bits)
- raw.control_flags |= ControlFlags::CS8;
+ raw.c_cflag |= termios::CS8;
// disable echoing, canonical mode, extended input processing and signals
- raw.local_flags &=
- !(LocalFlags::ECHO | LocalFlags::ICANON | LocalFlags::IEXTEN | LocalFlags::ISIG);
- raw.control_chars[SCI::VMIN as usize] = 1; // One character-at-a-time input
- raw.control_chars[SCI::VTIME as usize] = 0; // with blocking read
+ raw.c_lflag &=
+ !(termios::ECHO | termios::ICANON | termios::IEXTEN | termios::ISIG);
+ raw.c_cc[termios::VMIN] = 1; // One character-at-a-time input
+ raw.c_cc[termios::VTIME] = 0; // with blocking read
let mut key_map: HashMap<KeyEvent, Cmd> = HashMap::with_capacity(4);
- map_key(&mut key_map, &raw, SCI::VEOF, "VEOF", Cmd::EndOfFile);
- map_key(&mut key_map, &raw, SCI::VINTR, "VINTR", Cmd::Interrupt);
- map_key(&mut key_map, &raw, SCI::VQUIT, "VQUIT", Cmd::Interrupt);
- map_key(&mut key_map, &raw, SCI::VSUSP, "VSUSP", Cmd::Suspend);
+ map_key(&mut key_map, &raw, termios::VEOF, "VEOF", Cmd::EndOfFile);
+ map_key(&mut key_map, &raw, termios::VINTR, "VINTR", Cmd::Interrupt);
+ map_key(&mut key_map, &raw, termios::VQUIT, "VQUIT", Cmd::Interrupt);
+ map_key(&mut key_map, &raw, termios::VSUSP, "VSUSP", Cmd::Suspend);
- termios::tcsetattr(self.tty_in, SetArg::TCSADRAIN, &raw)?;
+ tcsetattr(self.tty_in, termios::TCSADRAIN, &raw)?;
self.raw_mode.store(true, Ordering::SeqCst);
// enable bracketed paste