This commit is contained in:
Timon 2022-02-06 14:21:19 +01:00 committed by GitHub
parent 979245da22
commit 9a50fd2ce2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 44 deletions

View File

@ -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 # Version 0.22.1
- Update yanked version crossterm-winapi and move to crossterm-winapi 0.9.0. - 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. - Changed panic to error when calling disable-mouse capture without setting it first.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "crossterm" name = "crossterm"
version = "0.22.1" version = "0.23.0"
authors = ["T. Post"] authors = ["T. Post"]
description = "A crossplatform terminal library for manipulating terminals." description = "A crossplatform terminal library for manipulating terminals."
repository = "https://github.com/crossterm-rs/crossterm" repository = "https://github.com/crossterm-rs/crossterm"
@ -9,7 +9,7 @@ license = "MIT"
keywords = ["event", "color", "cli", "input", "terminal"] keywords = ["event", "color", "cli", "input", "terminal"]
exclude = ["target", "Cargo.lock"] exclude = ["target", "Cargo.lock"]
readme = "README.md" readme = "README.md"
edition = "2018" edition = "2021"
categories = ["command-line-interface", "command-line-utilities"] categories = ["command-line-interface", "command-line-utilities"]
[lib] [lib]
@ -34,7 +34,7 @@ event-stream = ["futures-core"]
# #
[dependencies] [dependencies]
bitflags = "1.3" bitflags = "1.3"
parking_lot = "0.11" parking_lot = "0.12"
# optional deps only added when requested # optional deps only added when requested
futures-core = { version = "0.3", optional = true, default-features = false } 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] [target.'cfg(windows)'.dependencies.winapi]
version = "0.3.9" version = "0.3.9"
features = ["winuser"] features = ["winuser", "winerror"]
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
crossterm_winapi = "0.9" crossterm_winapi = "0.9"
@ -56,18 +56,18 @@ crossterm_winapi = "0.9"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
libc = "0.2" libc = "0.2"
mio = { version="0.7", features=["os-poll"] } 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"] } signal-hook-mio = { version = "0.2.1", features = ["support-v0_7"] }
# #
# Dev dependencies (examples, ...) # Dev dependencies (examples, ...)
# #
[dev-dependencies] [dev-dependencies]
tokio = { version = "1.5", features = ["full"] } tokio = { version = "1.16", features = ["full"] }
futures = "0.3" futures = "0.3"
futures-timer = "3.0" futures-timer = "3.0"
async-std = "1.9" async-std = "1.10"
serde_json = "1.0.45" serde_json = "1.0"
# #
# Examples # Examples

View File

@ -134,7 +134,10 @@ pub struct MoveToColumn(pub u16);
impl Command for MoveToColumn { impl Command for MoveToColumn {
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { 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)] #[cfg(windows)]
@ -153,7 +156,10 @@ pub struct MoveToRow(pub u16);
impl Command for MoveToRow { impl Command for MoveToRow {
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result { 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)] #[cfg(windows)]

View File

@ -264,23 +264,25 @@ pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> Result<Option<Inter
let keycode = { let keycode = {
if let Some(c) = char::from_u32(codepoint) { if let Some(c) = char::from_u32(codepoint) {
match c { match c {
'\x1B' => KeyCode::Esc.into(), '\x1B' => KeyCode::Esc,
'\r' => KeyCode::Enter.into(), '\r' => KeyCode::Enter,
// Issue #371: \n = 0xA, which is also the keycode for Ctrl+J. The only reason we get // 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 // 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 // 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 // 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(), '\n' if !crate::terminal::sys::is_raw_mode_enabled() => KeyCode::Enter,
'\t' => if modifiers.contains(KeyModifiers::SHIFT) { '\t' => {
KeyCode::BackTab.into() if modifiers.contains(KeyModifiers::SHIFT) {
} else { KeyCode::BackTab
KeyCode::Tab.into() } else {
}, KeyCode::Tab
'\x7F' => KeyCode::Backspace.into(), }
_ => KeyCode::Char(c).into(), }
'\x7F' => KeyCode::Backspace,
_ => KeyCode::Char(c),
} }
} else { } else {
return Err(could_not_parse_event_error()) return Err(could_not_parse_event_error());
} }
}; };

View File

@ -30,20 +30,18 @@ macro_rules! csi {
/// use std::io::{Write, stdout}; /// use std::io::{Write, stdout};
/// use crossterm::{queue, style::Print}; /// use crossterm::{queue, style::Print};
/// ///
/// fn main() { /// let mut stdout = stdout();
/// let mut stdout = stdout();
/// ///
/// // `Print` will executed executed when `flush` is called. /// // `Print` will executed executed when `flush` is called.
/// queue!(stdout, Print("foo".to_string())); /// 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. /// // when calling `flush` on `stdout`, all commands will be written to the stdout and therefore executed.
/// stdout.flush(); /// stdout.flush();
/// ///
/// // ==== Output ==== /// // ==== Output ====
/// // foo /// // foo
/// }
/// ``` /// ```
/// ///
/// Have a look over at the [Command API](./#command-api) for more details. /// 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 std::io::{Write, stdout};
/// use crossterm::{execute, style::Print}; /// use crossterm::{execute, style::Print};
/// ///
/// fn main() { /// // will be executed directly
/// // will be executed directly /// execute!(stdout(), Print("sum:\n".to_string()));
/// execute!(stdout(), Print("sum:\n".to_string()));
/// ///
/// // will be executed directly /// // will be executed directly
/// execute!(stdout(), Print("1 + 1= ".to_string()), Print((1+1).to_string())); /// execute!(stdout(), Print("1 + 1= ".to_string()), Print((1+1).to_string()));
/// ///
/// // ==== Output ==== /// // ==== Output ====
/// // sum: /// // sum:
/// // 1 + 1 = 2 /// // 1 + 1 = 2
/// }
/// ``` /// ```
/// ///
/// Have a look over at the [Command API](./#command-api) for more details. /// Have a look over at the [Command API](./#command-api) for more details.

View File

@ -414,7 +414,7 @@ mod tests {
#[test] #[test]
fn test_raw_mode() { fn test_raw_mode() {
// check we start from normal mode (may fail on some test harnesses) // 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 // enable the raw mode
if enable_raw_mode().is_err() { if enable_raw_mode().is_err() {
@ -425,18 +425,18 @@ mod tests {
// check it worked (on unix it doesn't really check the underlying // check it worked (on unix it doesn't really check the underlying
// tty but rather check that the code is consistent) // 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 it again, this should not change anything
enable_raw_mode().unwrap(); enable_raw_mode().unwrap();
// check we're still in raw mode // 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 // now let's disable it
disable_raw_mode().unwrap(); disable_raw_mode().unwrap();
// check we're back to normal mode // check we're back to normal mode
assert_eq!(is_raw_mode_enabled().unwrap(), false); assert!(!is_raw_mode_enabled().unwrap());
} }
} }