diff --git a/CHANGELOG.md b/CHANGELOG.md index 5081818a5..16acb3e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Version 0.23 +- Update dependencies. +- Add 0 check for all cursor functions to prevent undefined behaviour. +- Add CSIu key parsing for unix. +- Improve control character window key parsing supporting (e.g. CTRL [ and ]) +- Update library to 2021 edition. + # Version 0.22.1 - Update yanked version crossterm-winapi and move to crossterm-winapi 0.9.0. - Changed panic to error when calling disable-mouse capture without setting it first. diff --git a/Cargo.toml b/Cargo.toml index 2b8bce40e..d34cf298b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crossterm" -version = "0.22.1" +version = "0.23.0" authors = ["T. Post"] description = "A crossplatform terminal library for manipulating terminals." repository = "https://github.com/crossterm-rs/crossterm" @@ -9,7 +9,7 @@ license = "MIT" keywords = ["event", "color", "cli", "input", "terminal"] exclude = ["target", "Cargo.lock"] readme = "README.md" -edition = "2018" +edition = "2021" categories = ["command-line-interface", "command-line-utilities"] [lib] @@ -34,7 +34,7 @@ event-stream = ["futures-core"] # [dependencies] bitflags = "1.3" -parking_lot = "0.11" +parking_lot = "0.12" # optional deps only added when requested futures-core = { version = "0.3", optional = true, default-features = false } @@ -45,7 +45,7 @@ serde = { version = "1.0", features = ["derive"], optional = true } # [target.'cfg(windows)'.dependencies.winapi] version = "0.3.9" -features = ["winuser"] +features = ["winuser", "winerror"] [target.'cfg(windows)'.dependencies] crossterm_winapi = "0.9" @@ -56,18 +56,18 @@ crossterm_winapi = "0.9" [target.'cfg(unix)'.dependencies] libc = "0.2" mio = { version="0.7", features=["os-poll"] } -signal-hook = { version = "0.3.8" } +signal-hook = { version = "0.3.13" } signal-hook-mio = { version = "0.2.1", features = ["support-v0_7"] } # # Dev dependencies (examples, ...) # [dev-dependencies] -tokio = { version = "1.5", features = ["full"] } +tokio = { version = "1.16", features = ["full"] } futures = "0.3" futures-timer = "3.0" -async-std = "1.9" -serde_json = "1.0.45" +async-std = "1.10" +serde_json = "1.0" # # Examples diff --git a/src/cursor.rs b/src/cursor.rs index a8a1ef2d6..63259f3a7 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -134,7 +134,10 @@ pub struct MoveToColumn(pub u16); impl Command for MoveToColumn { fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - write!(f, csi!("{}G"), self.0) + if self.0 != 0 { + write!(f, csi!("{}G"), self.0)?; + } + Ok(()) } #[cfg(windows)] @@ -153,7 +156,10 @@ pub struct MoveToRow(pub u16); impl Command for MoveToRow { fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { - write!(f, csi!("{}d"), self.0) + if self.0 != 0 { + write!(f, csi!("{}d"), self.0)? + } + Ok(()) } #[cfg(windows)] diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index 7e09f9a20..d957e09a9 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -264,23 +264,25 @@ pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> Result KeyCode::Esc.into(), - '\r' => KeyCode::Enter.into(), + '\x1B' => KeyCode::Esc, + '\r' => KeyCode::Enter, // Issue #371: \n = 0xA, which is also the keycode for Ctrl+J. The only reason we get // newlines as input is because the terminal converts \r into \n for us. When we // enter raw mode, we disable that, so \n no longer has any meaning - it's better to // use Ctrl+J. Waiting to handle it here means it gets picked up later - '\n' if !crate::terminal::sys::is_raw_mode_enabled() => KeyCode::Enter.into(), - '\t' => if modifiers.contains(KeyModifiers::SHIFT) { - KeyCode::BackTab.into() - } else { - KeyCode::Tab.into() - }, - '\x7F' => KeyCode::Backspace.into(), - _ => KeyCode::Char(c).into(), + '\n' if !crate::terminal::sys::is_raw_mode_enabled() => KeyCode::Enter, + '\t' => { + if modifiers.contains(KeyModifiers::SHIFT) { + KeyCode::BackTab + } else { + KeyCode::Tab + } + } + '\x7F' => KeyCode::Backspace, + _ => KeyCode::Char(c), } } else { - return Err(could_not_parse_event_error()) + return Err(could_not_parse_event_error()); } }; diff --git a/src/macros.rs b/src/macros.rs index 7ea4ac293..727869f18 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,20 +30,18 @@ macro_rules! csi { /// use std::io::{Write, stdout}; /// use crossterm::{queue, style::Print}; /// -/// fn main() { -/// let mut stdout = stdout(); +/// let mut stdout = stdout(); /// -/// // `Print` will executed executed when `flush` is called. -/// queue!(stdout, Print("foo".to_string())); +/// // `Print` will executed executed when `flush` is called. +/// queue!(stdout, Print("foo".to_string())); /// -/// // some other code (no execution happening here) ... +/// // some other code (no execution happening here) ... /// -/// // when calling `flush` on `stdout`, all commands will be written to the stdout and therefore executed. -/// stdout.flush(); +/// // when calling `flush` on `stdout`, all commands will be written to the stdout and therefore executed. +/// stdout.flush(); /// -/// // ==== Output ==== -/// // foo -/// } +/// // ==== Output ==== +/// // foo /// ``` /// /// Have a look over at the [Command API](./#command-api) for more details. @@ -86,17 +84,15 @@ macro_rules! queue { /// use std::io::{Write, stdout}; /// use crossterm::{execute, style::Print}; /// -/// fn main() { -/// // will be executed directly -/// execute!(stdout(), Print("sum:\n".to_string())); +/// // will be executed directly +/// execute!(stdout(), Print("sum:\n".to_string())); /// -/// // will be executed directly -/// execute!(stdout(), Print("1 + 1= ".to_string()), Print((1+1).to_string())); +/// // will be executed directly +/// execute!(stdout(), Print("1 + 1= ".to_string()), Print((1+1).to_string())); /// -/// // ==== Output ==== -/// // sum: -/// // 1 + 1 = 2 -/// } +/// // ==== Output ==== +/// // sum: +/// // 1 + 1 = 2 /// ``` /// /// Have a look over at the [Command API](./#command-api) for more details. diff --git a/src/terminal.rs b/src/terminal.rs index b5de2498a..eface2411 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -414,7 +414,7 @@ mod tests { #[test] fn test_raw_mode() { // check we start from normal mode (may fail on some test harnesses) - assert_eq!(is_raw_mode_enabled().unwrap(), false); + assert!(!is_raw_mode_enabled().unwrap()); // enable the raw mode if enable_raw_mode().is_err() { @@ -425,18 +425,18 @@ mod tests { // check it worked (on unix it doesn't really check the underlying // tty but rather check that the code is consistent) - assert_eq!(is_raw_mode_enabled().unwrap(), true); + assert!(is_raw_mode_enabled().unwrap()); // enable it again, this should not change anything enable_raw_mode().unwrap(); // check we're still in raw mode - assert_eq!(is_raw_mode_enabled().unwrap(), true); + assert!(is_raw_mode_enabled().unwrap()); // now let's disable it disable_raw_mode().unwrap(); // check we're back to normal mode - assert_eq!(is_raw_mode_enabled().unwrap(), false); + assert!(!is_raw_mode_enabled().unwrap()); } }