diff --git a/Cargo.toml b/Cargo.toml
index 27d6448..f297af3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,10 +1,9 @@
[package]
-name = "crossterm"
+name = "minicrossterm"
version = "0.28.1"
-authors = ["T. Post"]
-description = "A crossplatform terminal library for manipulating terminals."
-repository = "https://github.com/crossterm-rs/crossterm"
-documentation = "https://docs.rs/crossterm/"
+authors = ["Blasthavers", "T. Post"]
+description = "A stripped back crossplatform terminal library for manipulating terminals asynchronously."
+repository = "https://git.blastmud.org/blasthavers/crossterm"
license = "MIT"
keywords = ["event", "color", "cli", "input", "terminal"]
exclude = ["target", "Cargo.lock"]
@@ -27,22 +26,10 @@ all-features = true
# Features
#
[features]
-default = ["bracketed-paste", "windows", "events"]
-windows = [
- "dep:winapi",
- "dep:crossterm_winapi",
-] # Disables winapi dependencies from being included into the binary (SHOULD NOT be disabled on windows).
+default = ["bracketed-paste", "events"]
bracketed-paste = [
] # Enables triggering a `Event::Paste` when pasting text into the terminal.
-event-stream = ["dep:futures-core", "events"] # Enables async events
-use-dev-tty = [
- "filedescriptor",
- "rustix/process",
-] # Enables raw file descriptor polling / selecting instead of mio.
events = [
- "dep:mio",
- "dep:signal-hook",
- "dep:signal-hook-mio",
] # Enables reading input/events from the system.
serde = ["dep:serde", "bitflags/serde"] # Enables 'serde' for various types.
@@ -51,85 +38,14 @@ serde = ["dep:serde", "bitflags/serde"] # Enables 'serde' for various types.
#
[dependencies]
bitflags = { version = "2.3" }
-parking_lot = "0.12"
# optional deps only added when requested
-futures-core = { version = "0.3", optional = true, default-features = false }
serde = { version = "1.0", features = ["derive"], optional = true }
-#
-# Windows dependencies
-#
-[target.'cfg(windows)'.dependencies.winapi]
-version = "0.3.9"
-features = ["winuser", "winerror"]
-optional = true
-
-[target.'cfg(windows)'.dependencies]
-crossterm_winapi = { version = "0.9.1", optional = true }
-
-#
-# UNIX dependencies
-#
-[target.'cfg(unix)'.dependencies]
-# Default to using rustix for UNIX systems, but provide an option to use libc for backwards
-# compatibility.
-libc = { version = "0.2", default-features = false, optional = true }
-rustix = { version = "0.38.34", default-features = false, features = [
- "std",
- "stdio",
- "termios",
-] }
-signal-hook = { version = "0.3.17", optional = true }
-filedescriptor = { version = "0.8", optional = true }
-mio = { version = "1.0", features = ["os-poll"], optional = true }
-signal-hook-mio = { version = "0.2.4", features = [
- "support-v1_0",
-], optional = true }
-
#
# Dev dependencies (examples, ...)
#
[dev-dependencies]
-tokio = { version = "1.25", features = ["full"] }
-futures = "0.3"
-futures-timer = "3.0"
-async-std = "1.12"
serde_json = "1.0"
serial_test = "2.0.0"
temp-env = "0.3.6"
-
-#
-# Examples
-#
-[[example]]
-name = "event-read"
-required-features = ["bracketed-paste", "events"]
-
-[[example]]
-name = "event-match-modifiers"
-required-features = ["bracketed-paste", "events"]
-
-[[example]]
-name = "event-poll-read"
-required-features = ["bracketed-paste", "events"]
-
-[[example]]
-name = "event-stream-async-std"
-required-features = ["event-stream", "events"]
-
-[[example]]
-name = "event-stream-tokio"
-required-features = ["event-stream", "events"]
-
-[[example]]
-name = "event-read-char-line"
-required-features = ["events"]
-
-[[example]]
-name = "stderr"
-required-features = ["events"]
-
-[[example]]
-name = "key-display"
-required-features = ["events"]
diff --git a/README.md b/README.md
index 1fabfe0..3c3f5df 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,20 @@
-
+# Minicrossterm
-[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z8QK6XU749JB2) ![Travis][s7] [![Latest Version][s1]][l1] [![MIT][s2]][l2] [![docs][s3]][l3] ![Lines of Code][s6] [![Join us on Discord][s5]][l5]
+Minicrossterm is a cut back fork of crossterm which doesn't depend on stdio, and is intended
+to only provide non-blocking functionality for applications without relying on standard IO (
+for example, from webassembly).
+
+It was created for Blasthavers Worldwideportal, and not by the original authors of crossterm.
+
+The following information applies to crossterm - some might not be up to date for minicrossterm.
# Cross-platform Terminal Manipulation Library
Crossterm is a pure-rust, terminal manipulation library that makes it possible to write cross-platform text-based interfaces (see [features](#features)). It supports all UNIX and Windows terminals down to Windows 7 (not all terminals are tested,
see [Tested Terminals](#tested-terminals) for more info).
+[![Donate to crossterm upstream](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z8QK6XU749JB2)]
+
## Table of Contents
- [Cross-platform Terminal Manipulation Library](#cross-platform-terminal-manipulation-library)
diff --git a/examples/README.md b/examples/README.md
deleted file mode 100644
index c9884ec..0000000
--- a/examples/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-![Lines of Code][s7] [![MIT][s2]][l2] [![Join us on Discord][s5]][l5]
-
-# Crossterm Examples
-
-The examples are compatible with the latest release.
-
-## Structure
-
-```
-├── examples
-│ └── interactive-test
-│ └── event-*
-│ └── stderr
-```
-| File Name | Description | Topics |
-|:----------------------------|:-------------------------------|:------------------------------------------|
-| `examples/interactive-test` | interactive, walk through, demo | cursor, style, event |
-| `event-*` | event reading demos | (async) event reading |
-| `stderr` | crossterm over stderr demo | raw mode, alternate screen, custom output |
-| `is_tty` | Is this instance a tty ? | tty |
-
-## Run examples
-
-```bash
-$ cargo run --example [file name]
-```
-
-To run the interactive-demo go into the folder `examples/interactive-demo` and run `cargo run`.
-
-## License
-
-This project is licensed under the MIT License - see the [LICENSE.md](LICENSE) file for details.
-
-[s2]: https://img.shields.io/badge/license-MIT-blue.svg
-[l2]: LICENSE
-
-[s5]: https://img.shields.io/discord/560857607196377088.svg?logo=discord
-[l5]: https://discord.gg/K4nyTDB
-
-[s7]: https://travis-ci.org/crossterm-rs/examples.svg?branch=master
diff --git a/examples/event-match-modifiers.rs b/examples/event-match-modifiers.rs
deleted file mode 100644
index c3f75e9..0000000
--- a/examples/event-match-modifiers.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Demonstrates how to match on modifiers like: Control, alt, shift.
-//!
-//! cargo run --example event-match-modifiers
-
-use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
-
-fn match_event(read_event: Event) {
- match read_event {
- // Match one one modifier:
- Event::Key(KeyEvent {
- modifiers: KeyModifiers::CONTROL,
- code,
- ..
- }) => {
- println!("Control + {:?}", code);
- }
- Event::Key(KeyEvent {
- modifiers: KeyModifiers::SHIFT,
- code,
- ..
- }) => {
- println!("Shift + {:?}", code);
- }
- Event::Key(KeyEvent {
- modifiers: KeyModifiers::ALT,
- code,
- ..
- }) => {
- println!("Alt + {:?}", code);
- }
-
- // Match on multiple modifiers:
- Event::Key(KeyEvent {
- code, modifiers, ..
- }) => {
- if modifiers == (KeyModifiers::ALT | KeyModifiers::SHIFT) {
- println!("Alt + Shift {:?}", code);
- } else {
- println!("({:?}) with key: {:?}", modifiers, code)
- }
- }
-
- _ => {}
- }
-}
-
-fn main() {
- match_event(Event::Key(KeyEvent::new(
- KeyCode::Char('z'),
- KeyModifiers::CONTROL,
- )));
- match_event(Event::Key(KeyEvent::new(
- KeyCode::Left,
- KeyModifiers::SHIFT,
- )));
- match_event(Event::Key(KeyEvent::new(
- KeyCode::Delete,
- KeyModifiers::ALT,
- )));
- match_event(Event::Key(KeyEvent::new(
- KeyCode::Right,
- KeyModifiers::ALT | KeyModifiers::SHIFT,
- )));
- match_event(Event::Key(KeyEvent::new(
- KeyCode::Home,
- KeyModifiers::ALT | KeyModifiers::CONTROL,
- )));
-}
diff --git a/examples/event-poll-read.rs b/examples/event-poll-read.rs
deleted file mode 100644
index df960ab..0000000
--- a/examples/event-poll-read.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-//! Demonstrates how to match on modifiers like: Control, alt, shift.
-//!
-//! cargo run --example event-poll-read
-
-use std::{io, time::Duration};
-
-use crossterm::{
- cursor::position,
- event::{poll, read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
- execute,
- terminal::{disable_raw_mode, enable_raw_mode},
-};
-
-const HELP: &str = r#"Blocking poll() & non-blocking read()
- - Keyboard, mouse and terminal resize events enabled
- - Prints "." every second if there's no event
- - Hit "c" to print current cursor position
- - Use Esc to quit
-"#;
-
-fn print_events() -> io::Result<()> {
- loop {
- // Wait up to 1s for another event
- if poll(Duration::from_millis(1_000))? {
- // It's guaranteed that read() won't block if `poll` returns `Ok(true)`
- let event = read()?;
-
- println!("Event::{:?}\r", event);
-
- if event == Event::Key(KeyCode::Char('c').into()) {
- println!("Cursor position: {:?}\r", position());
- }
-
- if event == Event::Key(KeyCode::Esc.into()) {
- break;
- }
- } else {
- // Timeout expired, no event for 1s
- println!(".\r");
- }
- }
-
- Ok(())
-}
-
-fn main() -> io::Result<()> {
- println!("{}", HELP);
-
- enable_raw_mode()?;
-
- let mut stdout = io::stdout();
- execute!(stdout, EnableMouseCapture)?;
-
- if let Err(e) = print_events() {
- println!("Error: {:?}\r", e);
- }
-
- execute!(stdout, DisableMouseCapture)?;
-
- disable_raw_mode()
-}
diff --git a/examples/event-read-char-line.rs b/examples/event-read-char-line.rs
deleted file mode 100644
index 5fa8349..0000000
--- a/examples/event-read-char-line.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Demonstrates how to block read characters or a full line.
-//! Just note that crossterm is not required to do this and can be done with `io::stdin()`.
-//!
-//! cargo run --example event-read-char-line
-
-use std::io;
-
-use crossterm::event::{self, Event, KeyCode, KeyEvent};
-
-pub fn read_char() -> io::Result {
- loop {
- if let Event::Key(KeyEvent {
- code: KeyCode::Char(c),
- ..
- }) = event::read()?
- {
- return Ok(c);
- }
- }
-}
-
-pub fn read_line() -> io::Result {
- let mut line = String::new();
- while let Event::Key(KeyEvent { code, .. }) = event::read()? {
- match code {
- KeyCode::Enter => {
- break;
- }
- KeyCode::Char(c) => {
- line.push(c);
- }
- _ => {}
- }
- }
-
- Ok(line)
-}
-
-fn main() {
- println!("read line:");
- println!("{:?}", read_line());
- println!("read char:");
- println!("{:?}", read_char());
-}
diff --git a/examples/event-read.rs b/examples/event-read.rs
deleted file mode 100644
index aaf74fe..0000000
--- a/examples/event-read.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! Demonstrates how to block read events.
-//!
-//! cargo run --example event-read
-
-use std::io;
-
-use crossterm::event::{
- poll, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
-};
-use crossterm::{
- cursor::position,
- event::{
- read, DisableBracketedPaste, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste,
- EnableFocusChange, EnableMouseCapture, Event, KeyCode,
- },
- execute, queue,
- terminal::{disable_raw_mode, enable_raw_mode},
-};
-use std::time::Duration;
-
-const HELP: &str = r#"Blocking read()
- - Keyboard, mouse, focus and terminal resize events enabled
- - Hit "c" to print current cursor position
- - Use Esc to quit
-"#;
-
-fn print_events() -> io::Result<()> {
- loop {
- // Blocking read
- let event = read()?;
-
- println!("Event: {:?}\r", event);
-
- if event == Event::Key(KeyCode::Char('c').into()) {
- println!("Cursor position: {:?}\r", position());
- }
-
- if let Event::Resize(x, y) = event {
- let (original_size, new_size) = flush_resize_events((x, y));
- println!("Resize from: {:?}, to: {:?}\r", original_size, new_size);
- }
-
- if event == Event::Key(KeyCode::Esc.into()) {
- break;
- }
- }
-
- Ok(())
-}
-
-// Resize events can occur in batches.
-// With a simple loop they can be flushed.
-// This function will keep the first and last resize event.
-fn flush_resize_events(first_resize: (u16, u16)) -> ((u16, u16), (u16, u16)) {
- let mut last_resize = first_resize;
- while let Ok(true) = poll(Duration::from_millis(50)) {
- if let Ok(Event::Resize(x, y)) = read() {
- last_resize = (x, y);
- }
- }
-
- (first_resize, last_resize)
-}
-
-fn main() -> io::Result<()> {
- println!("{}", HELP);
-
- enable_raw_mode()?;
-
- let mut stdout = io::stdout();
-
- let supports_keyboard_enhancement = matches!(
- crossterm::terminal::supports_keyboard_enhancement(),
- Ok(true)
- );
-
- if supports_keyboard_enhancement {
- queue!(
- stdout,
- PushKeyboardEnhancementFlags(
- KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
- | KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES
- | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
- | KeyboardEnhancementFlags::REPORT_EVENT_TYPES
- )
- )?;
- }
-
- execute!(
- stdout,
- EnableBracketedPaste,
- EnableFocusChange,
- EnableMouseCapture,
- )?;
-
- if let Err(e) = print_events() {
- println!("Error: {:?}\r", e);
- }
-
- if supports_keyboard_enhancement {
- queue!(stdout, PopKeyboardEnhancementFlags)?;
- }
-
- execute!(
- stdout,
- DisableBracketedPaste,
- DisableFocusChange,
- DisableMouseCapture
- )?;
-
- disable_raw_mode()
-}
diff --git a/examples/event-stream-async-std.rs b/examples/event-stream-async-std.rs
deleted file mode 100644
index abd5449..0000000
--- a/examples/event-stream-async-std.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Demonstrates how to read events asynchronously with async-std.
-//!
-//! cargo run --features="event-stream" --example event-stream-async-std
-
-use std::{io::stdout, time::Duration};
-
-use futures::{future::FutureExt, select, StreamExt};
-use futures_timer::Delay;
-
-use crossterm::{
- cursor::position,
- event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
- execute,
- terminal::{disable_raw_mode, enable_raw_mode},
-};
-
-const HELP: &str = r#"EventStream based on futures_util::stream::Stream with async-std
- - Keyboard, mouse and terminal resize events enabled
- - Prints "." every second if there's no event
- - Hit "c" to print current cursor position
- - Use Esc to quit
-"#;
-
-async fn print_events() {
- let mut reader = EventStream::new();
-
- loop {
- let mut delay = Delay::new(Duration::from_millis(1_000)).fuse();
- let mut event = reader.next().fuse();
-
- select! {
- _ = delay => { println!(".\r"); },
- maybe_event = event => {
- match maybe_event {
- Some(Ok(event)) => {
- println!("Event::{:?}\r", event);
-
- if event == Event::Key(KeyCode::Char('c').into()) {
- println!("Cursor position: {:?}\r", position());
- }
-
- if event == Event::Key(KeyCode::Esc.into()) {
- break;
- }
- }
- Some(Err(e)) => println!("Error: {:?}\r", e),
- None => break,
- }
- }
- };
- }
-}
-
-fn main() -> std::io::Result<()> {
- println!("{}", HELP);
-
- enable_raw_mode()?;
-
- let mut stdout = stdout();
- execute!(stdout, EnableMouseCapture)?;
-
- async_std::task::block_on(print_events());
-
- execute!(stdout, DisableMouseCapture)?;
-
- disable_raw_mode()
-}
diff --git a/examples/event-stream-tokio.rs b/examples/event-stream-tokio.rs
deleted file mode 100644
index 6cea39c..0000000
--- a/examples/event-stream-tokio.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Demonstrates how to read events asynchronously with tokio.
-//!
-//! cargo run --features="event-stream" --example event-stream-tokio
-
-use std::{io::stdout, time::Duration};
-
-use futures::{future::FutureExt, select, StreamExt};
-use futures_timer::Delay;
-
-use crossterm::{
- cursor::position,
- event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
- execute,
- terminal::{disable_raw_mode, enable_raw_mode},
-};
-
-const HELP: &str = r#"EventStream based on futures_util::Stream with tokio
- - Keyboard, mouse and terminal resize events enabled
- - Prints "." every second if there's no event
- - Hit "c" to print current cursor position
- - Use Esc to quit
-"#;
-
-async fn print_events() {
- let mut reader = EventStream::new();
-
- loop {
- let mut delay = Delay::new(Duration::from_millis(1_000)).fuse();
- let mut event = reader.next().fuse();
-
- select! {
- _ = delay => { println!(".\r"); },
- maybe_event = event => {
- match maybe_event {
- Some(Ok(event)) => {
- println!("Event::{:?}\r", event);
-
- if event == Event::Key(KeyCode::Char('c').into()) {
- println!("Cursor position: {:?}\r", position());
- }
-
- if event == Event::Key(KeyCode::Esc.into()) {
- break;
- }
- }
- Some(Err(e)) => println!("Error: {:?}\r", e),
- None => break,
- }
- }
- };
- }
-}
-
-#[tokio::main]
-async fn main() -> std::io::Result<()> {
- println!("{}", HELP);
-
- enable_raw_mode()?;
-
- let mut stdout = stdout();
- execute!(stdout, EnableMouseCapture)?;
-
- print_events().await;
-
- execute!(stdout, DisableMouseCapture)?;
-
- disable_raw_mode()
-}
diff --git a/examples/interactive-demo/Cargo.toml b/examples/interactive-demo/Cargo.toml
deleted file mode 100644
index f7a5134..0000000
--- a/examples/interactive-demo/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "interactive-demo"
-version = "0.0.1"
-authors = ["T. Post", "Robert Vojta "]
-edition = "2018"
-description = "Interactive demo for crossterm."
-license = "MIT"
-exclude = ["target", "Cargo.lock"]
-readme = "README.md"
-publish = false
-
-[dependencies]
-crossterm = { path = "../../" }
\ No newline at end of file
diff --git a/examples/interactive-demo/src/macros.rs b/examples/interactive-demo/src/macros.rs
deleted file mode 100644
index 02ce9e2..0000000
--- a/examples/interactive-demo/src/macros.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-macro_rules! run_tests {
- (
- $dst:expr,
- $(
- $testfn:ident
- ),*
- $(,)?
- ) => {
- use crossterm::{queue, style, terminal, cursor};
- $(
- queue!(
- $dst,
- style::ResetColor,
- terminal::Clear(terminal::ClearType::All),
- cursor::MoveTo(1, 1),
- cursor::Show,
- cursor::EnableBlinking
- )?;
-
- $testfn($dst)?;
-
- match $crate::read_char() {
- Ok('q') => return Ok(()),
- Err(e) => return Err(e),
- _ => { },
- };
- )*
- }
-}
diff --git a/examples/interactive-demo/src/main.rs b/examples/interactive-demo/src/main.rs
deleted file mode 100644
index 5eb1c73..0000000
--- a/examples/interactive-demo/src/main.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-#![allow(clippy::cognitive_complexity)]
-
-use std::io;
-
-use crossterm::event::KeyEventKind;
-pub use crossterm::{
- cursor,
- event::{self, Event, KeyCode, KeyEvent},
- execute, queue, style,
- terminal::{self, ClearType},
- Command,
-};
-
-#[macro_use]
-mod macros;
-mod test;
-
-const MENU: &str = r#"Crossterm interactive test
-
-Controls:
-
- - 'q' - quit interactive test (or return to this menu)
- - any other key - continue with next step
-
-Available tests:
-
-1. cursor
-2. color (foreground, background)
-3. attributes (bold, italic, ...)
-4. input
-5. synchronized output
-
-Select test to run ('1', '2', ...) or hit 'q' to quit.
-"#;
-
-fn run(w: &mut W) -> io::Result<()>
-where
- W: io::Write,
-{
- execute!(w, terminal::EnterAlternateScreen)?;
-
- terminal::enable_raw_mode()?;
-
- loop {
- queue!(
- w,
- style::ResetColor,
- terminal::Clear(ClearType::All),
- cursor::Hide,
- cursor::MoveTo(1, 1)
- )?;
-
- for line in MENU.split('\n') {
- queue!(w, style::Print(line), cursor::MoveToNextLine(1))?;
- }
-
- w.flush()?;
-
- match read_char()? {
- '1' => test::cursor::run(w)?,
- '2' => test::color::run(w)?,
- '3' => test::attribute::run(w)?,
- '4' => test::event::run(w)?,
- '5' => test::synchronized_output::run(w)?,
- 'q' => {
- execute!(w, cursor::SetCursorStyle::DefaultUserShape).unwrap();
- break;
- }
- _ => {}
- };
- }
-
- execute!(
- w,
- style::ResetColor,
- cursor::Show,
- terminal::LeaveAlternateScreen
- )?;
-
- terminal::disable_raw_mode()
-}
-
-pub fn read_char() -> std::io::Result {
- loop {
- if let Ok(Event::Key(KeyEvent {
- code: KeyCode::Char(c),
- kind: KeyEventKind::Press,
- modifiers: _,
- state: _,
- })) = event::read()
- {
- return Ok(c);
- }
- }
-}
-
-pub fn buffer_size() -> io::Result<(u16, u16)> {
- terminal::size()
-}
-
-fn main() -> std::io::Result<()> {
- let mut stdout = io::stdout();
- run(&mut stdout)
-}
diff --git a/examples/interactive-demo/src/test.rs b/examples/interactive-demo/src/test.rs
deleted file mode 100644
index 1db95a2..0000000
--- a/examples/interactive-demo/src/test.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-pub mod attribute;
-pub mod color;
-pub mod cursor;
-pub mod event;
-pub mod synchronized_output;
diff --git a/examples/interactive-demo/src/test/attribute.rs b/examples/interactive-demo/src/test/attribute.rs
deleted file mode 100644
index 6c06752..0000000
--- a/examples/interactive-demo/src/test/attribute.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#![allow(clippy::cognitive_complexity)]
-
-use crossterm::{cursor, queue, style};
-use std::io::Write;
-
-const ATTRIBUTES: [(style::Attribute, style::Attribute); 10] = [
- (style::Attribute::Bold, style::Attribute::NormalIntensity),
- (style::Attribute::Italic, style::Attribute::NoItalic),
- (style::Attribute::Underlined, style::Attribute::NoUnderline),
- (
- style::Attribute::DoubleUnderlined,
- style::Attribute::NoUnderline,
- ),
- (style::Attribute::Undercurled, style::Attribute::NoUnderline),
- (style::Attribute::Underdotted, style::Attribute::NoUnderline),
- (style::Attribute::Underdashed, style::Attribute::NoUnderline),
- (style::Attribute::Reverse, style::Attribute::NoReverse),
- (
- style::Attribute::CrossedOut,
- style::Attribute::NotCrossedOut,
- ),
- (style::Attribute::SlowBlink, style::Attribute::NoBlink),
-];
-
-fn test_set_display_attributes(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- queue!(
- w,
- style::Print("Display attributes"),
- cursor::MoveToNextLine(2)
- )?;
-
- for (on, off) in &ATTRIBUTES {
- queue!(
- w,
- style::SetAttribute(*on),
- style::Print(format!("{:>width$} ", format!("{:?}", on), width = 35)),
- style::SetAttribute(*off),
- style::Print(format!("{:>width$}", format!("{:?}", off), width = 35)),
- style::ResetColor,
- cursor::MoveToNextLine(1)
- )?;
- }
-
- w.flush()?;
-
- Ok(())
-}
-
-pub fn run(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- run_tests!(w, test_set_display_attributes,);
- Ok(())
-}
diff --git a/examples/interactive-demo/src/test/color.rs b/examples/interactive-demo/src/test/color.rs
deleted file mode 100644
index d34ac45..0000000
--- a/examples/interactive-demo/src/test/color.rs
+++ /dev/null
@@ -1,198 +0,0 @@
-#![allow(clippy::cognitive_complexity)]
-
-use crossterm::{cursor, queue, style, style::Color};
-use std::io::Write;
-
-const COLORS: [Color; 21] = [
- Color::Black,
- Color::DarkGrey,
- Color::Grey,
- Color::White,
- Color::DarkRed,
- Color::Red,
- Color::DarkGreen,
- Color::Green,
- Color::DarkYellow,
- Color::Yellow,
- Color::DarkBlue,
- Color::Blue,
- Color::DarkMagenta,
- Color::Magenta,
- Color::DarkCyan,
- Color::Cyan,
- Color::AnsiValue(0),
- Color::AnsiValue(15),
- Color::Rgb { r: 255, g: 0, b: 0 },
- Color::Rgb { r: 0, g: 255, b: 0 },
- Color::Rgb { r: 0, g: 0, b: 255 },
-];
-
-fn test_set_foreground_color(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- queue!(
- w,
- style::Print("Foreground colors on the black & white background"),
- cursor::MoveToNextLine(2)
- )?;
-
- for color in &COLORS {
- queue!(
- w,
- style::SetForegroundColor(*color),
- style::SetBackgroundColor(Color::Black),
- style::Print(format!(
- "{:>width$} ",
- format!("{:?} ████████████", color),
- width = 40
- )),
- style::SetBackgroundColor(Color::White),
- style::Print(format!(
- "{:>width$}",
- format!("{:?} ████████████", color),
- width = 40
- )),
- cursor::MoveToNextLine(1)
- )?;
- }
-
- w.flush()?;
-
- Ok(())
-}
-
-fn test_set_background_color(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- queue!(
- w,
- style::Print("Background colors with black & white foreground"),
- cursor::MoveToNextLine(2)
- )?;
-
- for color in &COLORS {
- queue!(
- w,
- style::SetBackgroundColor(*color),
- style::SetForegroundColor(Color::Black),
- style::Print(format!(
- "{:>width$} ",
- format!("{:?} ▒▒▒▒▒▒▒▒▒▒▒▒", color),
- width = 40
- )),
- style::SetForegroundColor(Color::White),
- style::Print(format!(
- "{:>width$}",
- format!("{:?} ▒▒▒▒▒▒▒▒▒▒▒▒", color),
- width = 40
- )),
- cursor::MoveToNextLine(1)
- )?;
- }
-
- w.flush()?;
-
- Ok(())
-}
-
-fn test_color_values_matrix_16x16(w: &mut W, title: &str, color: F) -> std::io::Result<()>
-where
- W: Write,
- F: Fn(u16, u16) -> Color,
-{
- queue!(w, style::Print(title))?;
-
- for idx in 0..=15 {
- queue!(
- w,
- cursor::MoveTo(1, idx + 4),
- style::Print(format!("{:>width$}", idx, width = 2))
- )?;
- queue!(
- w,
- cursor::MoveTo(idx * 3 + 3, 3),
- style::Print(format!("{:>width$}", idx, width = 3))
- )?;
- }
-
- for row in 0..=15u16 {
- queue!(w, cursor::MoveTo(4, row + 4))?;
- for col in 0..=15u16 {
- queue!(
- w,
- style::SetForegroundColor(color(col, row)),
- style::Print("███")
- )?;
- }
- queue!(
- w,
- style::SetForegroundColor(Color::White),
- style::Print(format!("{:>width$} ..= ", row * 16, width = 3)),
- style::Print(format!("{:>width$}", row * 16 + 15, width = 3))
- )?;
- }
-
- w.flush()?;
-
- Ok(())
-}
-
-fn test_color_ansi_values(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- test_color_values_matrix_16x16(w, "Color::Ansi values", |col, row| {
- Color::AnsiValue((row * 16 + col) as u8)
- })
-}
-
-fn test_rgb_red_values(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- test_color_values_matrix_16x16(w, "Color::Rgb red values", |col, row| Color::Rgb {
- r: (row * 16 + col) as u8,
- g: 0_u8,
- b: 0,
- })
-}
-
-fn test_rgb_green_values(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- test_color_values_matrix_16x16(w, "Color::Rgb green values", |col, row| Color::Rgb {
- r: 0,
- g: (row * 16 + col) as u8,
- b: 0,
- })
-}
-
-fn test_rgb_blue_values(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- test_color_values_matrix_16x16(w, "Color::Rgb blue values", |col, row| Color::Rgb {
- r: 0,
- g: 0,
- b: (row * 16 + col) as u8,
- })
-}
-
-pub fn run(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- run_tests!(
- w,
- test_set_foreground_color,
- test_set_background_color,
- test_color_ansi_values,
- test_rgb_red_values,
- test_rgb_green_values,
- test_rgb_blue_values,
- );
- Ok(())
-}
diff --git a/examples/interactive-demo/src/test/cursor.rs b/examples/interactive-demo/src/test/cursor.rs
deleted file mode 100644
index 9ad10d5..0000000
--- a/examples/interactive-demo/src/test/cursor.rs
+++ /dev/null
@@ -1,222 +0,0 @@
-#![allow(clippy::cognitive_complexity)]
-
-use std::io::Write;
-
-use crossterm::{cursor, execute, queue, style, style::Stylize, Command};
-use std::thread;
-use std::time::Duration;
-
-fn test_move_cursor_up(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "Move Up (2)", |_, _| cursor::MoveUp(2))
-}
-
-fn test_move_cursor_down(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "Move Down (2)", |_, _| cursor::MoveDown(2))
-}
-
-fn test_move_cursor_left(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "Move Left (2)", |_, _| cursor::MoveLeft(2))
-}
-
-fn test_move_cursor_right(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "Move Right (2)", |_, _| cursor::MoveRight(2))
-}
-
-fn test_move_cursor_to_previous_line(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "MoveToPreviousLine (1)", |_, _| {
- cursor::MoveToPreviousLine(1)
- })
-}
-
-fn test_move_cursor_to_next_line(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "MoveToNextLine (1)", |_, _| cursor::MoveToNextLine(1))
-}
-
-fn test_move_cursor_to_column(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(w, "MoveToColumn (1)", |center_x, _| {
- cursor::MoveToColumn(center_x + 1)
- })
-}
-
-fn test_hide_cursor(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(w, style::Print("HideCursor"), cursor::Hide)
-}
-
-fn test_show_cursor(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(w, style::Print("ShowCursor"), cursor::Show)
-}
-
-fn test_cursor_blinking_block(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(
- w,
- style::Print("Blinking Block:"),
- cursor::MoveLeft(2),
- cursor::SetCursorStyle::BlinkingBlock,
- )
-}
-
-fn test_cursor_blinking_underscore(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(
- w,
- style::Print("Blinking Underscore:"),
- cursor::MoveLeft(2),
- cursor::SetCursorStyle::BlinkingUnderScore,
- )
-}
-
-fn test_cursor_blinking_bar(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(
- w,
- style::Print("Blinking bar:"),
- cursor::MoveLeft(2),
- cursor::SetCursorStyle::BlinkingBar,
- )
-}
-
-fn test_move_cursor_to(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- draw_cursor_box(
- w,
- "MoveTo (x: 1, y: 1) removed from center",
- |center_x, center_y| cursor::MoveTo(center_x + 1, center_y + 1),
- )
-}
-
-fn test_save_restore_cursor_position(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(w,
- cursor::MoveTo(0, 0),
- style::Print("Save position, print character elsewhere, after three seconds restore to old position."),
- cursor::MoveToNextLine(2),
- style::Print("Save ->[ ]<- Position"),
- cursor::MoveTo(8, 2),
- cursor::SavePosition,
- cursor::MoveTo(10,10),
- style::Print("Move To ->[√]<- Position")
- )?;
-
- thread::sleep(Duration::from_secs(3));
-
- execute!(w, cursor::RestorePosition, style::Print("√"))
-}
-
-/// Draws a box with an colored center, this center can be taken as a reference point after running the given cursor command.
-fn draw_cursor_box(w: &mut W, description: &str, cursor_command: F) -> std::io::Result<()>
-where
- W: Write,
- F: Fn(u16, u16) -> T,
- T: Command,
-{
- execute!(
- w,
- cursor::Hide,
- cursor::MoveTo(0, 0),
- style::SetForegroundColor(style::Color::Red),
- style::Print(format!(
- "Red box is the center. After the action: '{}' '√' is drawn to reflect the action from the center.",
- description
- ))
- )?;
-
- let start_y = 2;
- let width = 21;
- let height = 11 + start_y;
- let center_x = width / 2;
- let center_y = (height + start_y) / 2;
-
- for row in start_y..=10 + start_y {
- for column in 0..=width {
- if (row == start_y || row == height - 1) || (column == 0 || column == width) {
- queue!(
- w,
- cursor::MoveTo(column, row),
- style::PrintStyledContent("▓".red()),
- )?;
- } else {
- queue!(
- w,
- cursor::MoveTo(column, row),
- style::PrintStyledContent("_".red().on_white())
- )?;
- }
- }
- }
-
- queue!(
- w,
- cursor::MoveTo(center_x, center_y),
- style::PrintStyledContent("▀".red().on_white()),
- cursor::MoveTo(center_x, center_y),
- )?;
- queue!(
- w,
- cursor_command(center_x, center_y),
- style::PrintStyledContent("√".magenta().on_white())
- )?;
- w.flush()?;
- Ok(())
-}
-
-pub fn run(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- run_tests!(
- w,
- test_hide_cursor,
- test_show_cursor,
- test_cursor_blinking_bar,
- test_cursor_blinking_block,
- test_cursor_blinking_underscore,
- test_move_cursor_left,
- test_move_cursor_right,
- test_move_cursor_up,
- test_move_cursor_down,
- test_move_cursor_to,
- test_move_cursor_to_next_line,
- test_move_cursor_to_previous_line,
- test_move_cursor_to_column,
- test_save_restore_cursor_position
- );
- Ok(())
-}
diff --git a/examples/interactive-demo/src/test/event.rs b/examples/interactive-demo/src/test/event.rs
deleted file mode 100644
index 50a797e..0000000
--- a/examples/interactive-demo/src/test/event.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#![allow(clippy::cognitive_complexity)]
-
-use crossterm::{
- cursor::position,
- event::{read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
- execute,
-};
-use std::io::{self, Write};
-
-fn test_event(w: &mut W) -> io::Result<()>
-where
- W: io::Write,
-{
- execute!(w, EnableMouseCapture)?;
-
- loop {
- // Blocking read
- let event = read()?;
-
- println!("Event::{:?}\r", event);
-
- if event == Event::Key(KeyCode::Char('c').into()) {
- println!("Cursor position: {:?}\r", position());
- }
-
- if event == Event::Key(KeyCode::Char('q').into()) {
- break;
- }
- }
-
- execute!(w, DisableMouseCapture)?;
-
- Ok(())
-}
-
-pub fn run(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- run_tests!(w, test_event);
- Ok(())
-}
diff --git a/examples/interactive-demo/src/test/synchronized_output.rs b/examples/interactive-demo/src/test/synchronized_output.rs
deleted file mode 100644
index 4fba674..0000000
--- a/examples/interactive-demo/src/test/synchronized_output.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use std::io::Write;
-
-use crossterm::{cursor, execute, style::Print, SynchronizedUpdate};
-
-fn render_slowly(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- for i in 1..10 {
- execute!(w, Print(format!("{}", i)))?;
- std::thread::sleep(std::time::Duration::from_millis(50));
- }
- Ok(())
-}
-
-fn test_slow_rendering(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- execute!(w, Print("Rendering without synchronized update:"))?;
- execute!(w, cursor::MoveToNextLine(1))?;
- std::thread::sleep(std::time::Duration::from_millis(50));
- render_slowly(w)?;
-
- execute!(w, cursor::MoveToNextLine(1))?;
- execute!(w, Print("Rendering with synchronized update:"))?;
- execute!(w, cursor::MoveToNextLine(1))?;
- std::thread::sleep(std::time::Duration::from_millis(50));
- w.sync_update(render_slowly)??;
-
- execute!(w, cursor::MoveToNextLine(1))?;
- Ok(())
-}
-
-pub fn run(w: &mut W) -> std::io::Result<()>
-where
- W: Write,
-{
- run_tests!(w, test_slow_rendering,);
- Ok(())
-}
diff --git a/examples/is_tty.rs b/examples/is_tty.rs
deleted file mode 100644
index 85770e2..0000000
--- a/examples/is_tty.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use crossterm::{
- execute,
- terminal::{size, SetSize},
- tty::IsTty,
-};
-use std::io::{stdin, stdout};
-
-pub fn main() {
- println!("size: {:?}", size().unwrap());
- execute!(stdout(), SetSize(10, 10)).unwrap();
- println!("resized: {:?}", size().unwrap());
-
- if stdin().is_tty() {
- println!("Is TTY");
- } else {
- println!("Is not TTY");
- }
-}
diff --git a/examples/key-display.rs b/examples/key-display.rs
deleted file mode 100644
index c5ea7b8..0000000
--- a/examples/key-display.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-//! Demonstrates the display format of key events.
-//!
-//! This example demonstrates the display format of key events, which is useful for displaying in
-//! the help section of a terminal application.
-//!
-//! cargo run --example key-display
-
-use std::io;
-
-use crossterm::event::{KeyEventKind, KeyModifiers};
-use crossterm::{
- event::{read, Event, KeyCode},
- terminal::{disable_raw_mode, enable_raw_mode},
-};
-
-const HELP: &str = r#"Key display
- - Press any key to see its display format
- - Use Esc to quit
-"#;
-
-fn main() -> io::Result<()> {
- println!("{}", HELP);
- enable_raw_mode()?;
- if let Err(e) = print_events() {
- println!("Error: {:?}\r", e);
- }
- disable_raw_mode()?;
- Ok(())
-}
-
-fn print_events() -> io::Result<()> {
- loop {
- let event = read()?;
- match event {
- Event::Key(event) if event.kind == KeyEventKind::Press => {
- print!("Key pressed: ");
- if event.modifiers != KeyModifiers::NONE {
- print!("{}+", event.modifiers);
- }
- println!("{}\r", event.code);
- if event.code == KeyCode::Esc {
- break;
- }
- }
- _ => {}
- }
- }
- Ok(())
-}
diff --git a/examples/stderr.rs b/examples/stderr.rs
deleted file mode 100644
index ce523c6..0000000
--- a/examples/stderr.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-//! This shows how an application can write on stderr
-//! instead of stdout, thus making it possible to
-//! the command API instead of the "old style" direct
-//! unbuffered API.
-//!
-//! This particular example is only suited to Unix
-//! for now.
-//!
-//! cargo run --example stderr
-
-use std::io;
-
-use crossterm::{
- cursor::{Hide, MoveTo, Show},
- event,
- event::{Event, KeyCode, KeyEvent},
- execute, queue,
- style::Print,
- terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
-};
-
-const TEXT: &str = r#"
-This screen is ran on stderr.
-And when you hit enter, it prints on stdout.
-This makes it possible to run an application and choose what will
-be sent to any application calling yours.
-
-For example, assuming you build this example with
-
- cargo build --bin stderr
-
-and then you run it with
-
- cd "$(target/debug/stderr)"
-
-what the application prints on stdout is used as argument to cd.
-
-Try it out.
-
-Hit any key to quit this screen:
-
-1 will print `..`
-2 will print `/`
-3 will print `~`
-Any other key will print this text (so that you may copy-paste)
-"#;
-
-fn run_app(write: &mut W) -> io::Result
-where
- W: io::Write,
-{
- queue!(
- write,
- EnterAlternateScreen, // enter alternate screen
- Hide // hide the cursor
- )?;
-
- let mut y = 1;
- for line in TEXT.split('\n') {
- queue!(write, MoveTo(1, y), Print(line.to_string()))?;
- y += 1;
- }
-
- write.flush()?;
-
- terminal::enable_raw_mode()?;
- let user_char = read_char()?; // we wait for the user to hit a key
- execute!(write, Show, LeaveAlternateScreen)?; // restore the cursor and leave the alternate screen
-
- terminal::disable_raw_mode()?;
-
- Ok(user_char)
-}
-
-pub fn read_char() -> io::Result {
- loop {
- if let Event::Key(KeyEvent {
- code: KeyCode::Char(c),
- ..
- }) = event::read()?
- {
- return Ok(c);
- }
- }
-}
-
-// cargo run --example stderr
-fn main() {
- match run_app(&mut io::stderr()).unwrap() {
- '1' => print!(".."),
- '2' => print!("/"),
- '3' => print!("~"),
- _ => println!("{}", TEXT),
- }
-}
diff --git a/src/cursor.rs b/src/cursor.rs
index 24796dc..d76c682 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -46,11 +46,6 @@ use std::fmt;
use crate::{csi, impl_display, Command};
-pub(crate) mod sys;
-
-#[cfg(feature = "events")]
-pub use sys::position;
-
/// A command that moves the terminal cursor to the given position (column, row).
///
/// # Notes
diff --git a/src/cursor/sys.rs b/src/cursor/sys.rs
deleted file mode 100644
index 1623740..0000000
--- a/src/cursor/sys.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//! This module provides platform related functions.
-
-#[cfg(unix)]
-#[cfg(feature = "events")]
-pub use self::unix::position;
-#[cfg(windows)]
-#[cfg(feature = "events")]
-pub use self::windows::position;
-#[cfg(windows)]
-pub(crate) use self::windows::{
- move_down, move_left, move_right, move_to, move_to_column, move_to_next_line,
- move_to_previous_line, move_to_row, move_up, restore_position, save_position, show_cursor,
-};
-
-#[cfg(windows)]
-pub(crate) mod windows;
-
-#[cfg(unix)]
-#[cfg(feature = "events")]
-pub(crate) mod unix;
diff --git a/src/cursor/sys/unix.rs b/src/cursor/sys/unix.rs
deleted file mode 100644
index 4734212..0000000
--- a/src/cursor/sys/unix.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-use std::{
- io::{self, Error, ErrorKind, Write},
- time::Duration,
-};
-
-use crate::{
- event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent},
- terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled},
-};
-
-/// Returns the cursor position (column, row).
-///
-/// The top left cell is represented as `(0, 0)`.
-///
-/// On unix systems, this function will block and possibly time out while
-/// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called.
-pub fn position() -> io::Result<(u16, u16)> {
- if is_raw_mode_enabled() {
- read_position_raw()
- } else {
- read_position()
- }
-}
-
-fn read_position() -> io::Result<(u16, u16)> {
- enable_raw_mode()?;
- let pos = read_position_raw();
- disable_raw_mode()?;
- pos
-}
-
-fn read_position_raw() -> io::Result<(u16, u16)> {
- // Use `ESC [ 6 n` to and retrieve the cursor position.
- let mut stdout = io::stdout();
- stdout.write_all(b"\x1B[6n")?;
- stdout.flush()?;
-
- loop {
- match poll_internal(Some(Duration::from_millis(2000)), &CursorPositionFilter) {
- Ok(true) => {
- if let Ok(InternalEvent::CursorPosition(x, y)) =
- read_internal(&CursorPositionFilter)
- {
- return Ok((x, y));
- }
- }
- Ok(false) => {
- return Err(Error::new(
- ErrorKind::Other,
- "The cursor position could not be read within a normal duration",
- ));
- }
- Err(_) => {}
- }
- }
-}
diff --git a/src/cursor/sys/windows.rs b/src/cursor/sys/windows.rs
deleted file mode 100644
index 84a4cd0..0000000
--- a/src/cursor/sys/windows.rs
+++ /dev/null
@@ -1,341 +0,0 @@
-//! WinAPI related logic to cursor manipulation.
-
-use std::convert::TryFrom;
-use std::io;
-use std::sync::atomic::{AtomicU64, Ordering};
-
-use crossterm_winapi::{result, Coord, Handle, HandleType, ScreenBuffer};
-use winapi::{
- shared::minwindef::{FALSE, TRUE},
- um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD},
-};
-
-/// The position of the cursor, written when you save the cursor's position.
-///
-/// This is `u64::MAX` initially. Otherwise, it stores the cursor's x position bit-shifted left 16
-/// times or-ed with the cursor's y position, where both are `i16`s.
-static SAVED_CURSOR_POS: AtomicU64 = AtomicU64::new(u64::MAX);
-
-// The 'y' position of the cursor is not relative to the window but absolute to screen buffer.
-// We can calculate the relative cursor position by subtracting the top position of the terminal window from the y position.
-// This results in an 1-based coord zo subtract 1 to make cursor position 0-based.
-pub fn parse_relative_y(y: i16) -> std::io::Result {
- let window = ScreenBuffer::current()?.info()?;
-
- let window_size = window.terminal_window();
- let screen_size = window.terminal_size();
-
- if y <= screen_size.height {
- Ok(y)
- } else {
- Ok(y - window_size.top)
- }
-}
-
-/// Returns the cursor position (column, row).
-///
-/// The top left cell is represented `0,0`.
-pub fn position() -> io::Result<(u16, u16)> {
- let cursor = ScreenBufferCursor::output()?;
- let mut position = cursor.position()?;
- // if position.y != 0 {
- position.y = parse_relative_y(position.y)?;
- // }
- Ok(position.into())
-}
-
-pub(crate) fn show_cursor(show_cursor: bool) -> std::io::Result<()> {
- ScreenBufferCursor::from(Handle::current_out_handle()?).set_visibility(show_cursor)
-}
-
-pub(crate) fn move_to(column: u16, row: u16) -> std::io::Result<()> {
- let cursor = ScreenBufferCursor::output()?;
- cursor.move_to(column as i16, row as i16)?;
- Ok(())
-}
-
-pub(crate) fn move_up(count: u16) -> std::io::Result<()> {
- let (column, row) = position()?;
- move_to(column, row - count)?;
- Ok(())
-}
-
-pub(crate) fn move_right(count: u16) -> std::io::Result<()> {
- let (column, row) = position()?;
- move_to(column + count, row)?;
- Ok(())
-}
-
-pub(crate) fn move_down(count: u16) -> std::io::Result<()> {
- let (column, row) = position()?;
- move_to(column, row + count)?;
- Ok(())
-}
-
-pub(crate) fn move_left(count: u16) -> std::io::Result<()> {
- let (column, row) = position()?;
- move_to(column - count, row)?;
- Ok(())
-}
-
-pub(crate) fn move_to_column(new_column: u16) -> std::io::Result<()> {
- let (_, row) = position()?;
- move_to(new_column, row)?;
- Ok(())
-}
-
-pub(crate) fn move_to_row(new_row: u16) -> std::io::Result<()> {
- let (col, _) = position()?;
- move_to(col, new_row)?;
- Ok(())
-}
-
-pub(crate) fn move_to_next_line(count: u16) -> std::io::Result<()> {
- let (_, row) = position()?;
- move_to(0, row + count)?;
- Ok(())
-}
-
-pub(crate) fn move_to_previous_line(count: u16) -> std::io::Result<()> {
- let (_, row) = position()?;
- move_to(0, row - count)?;
- Ok(())
-}
-
-pub(crate) fn save_position() -> std::io::Result<()> {
- ScreenBufferCursor::output()?.save_position()?;
- Ok(())
-}
-
-pub(crate) fn restore_position() -> std::io::Result<()> {
- ScreenBufferCursor::output()?.restore_position()?;
- Ok(())
-}
-
-/// WinAPI wrapper over terminal cursor behaviour.
-struct ScreenBufferCursor {
- screen_buffer: ScreenBuffer,
-}
-
-impl ScreenBufferCursor {
- fn output() -> std::io::Result {
- Ok(ScreenBufferCursor {
- screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?),
- })
- }
-
- fn position(&self) -> std::io::Result {
- Ok(self.screen_buffer.info()?.cursor_pos())
- }
-
- fn move_to(&self, x: i16, y: i16) -> std::io::Result<()> {
- if x < 0 {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- format!("Argument Out of Range Exception when setting cursor position to X: {x}"),
- ));
- }
-
- if y < 0 {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- format!("Argument Out of Range Exception when setting cursor position to Y: {y}"),
- ));
- }
-
- let position = COORD { X: x, Y: y };
-
- unsafe {
- if result(SetConsoleCursorPosition(
- **self.screen_buffer.handle(),
- position,
- ))
- .is_err()
- {
- return Err(io::Error::last_os_error());
- }
- }
- Ok(())
- }
-
- fn set_visibility(&self, visible: bool) -> std::io::Result<()> {
- let cursor_info = CONSOLE_CURSOR_INFO {
- dwSize: 100,
- bVisible: if visible { TRUE } else { FALSE },
- };
-
- unsafe {
- if result(SetConsoleCursorInfo(
- **self.screen_buffer.handle(),
- &cursor_info,
- ))
- .is_err()
- {
- return Err(io::Error::last_os_error());
- }
- }
- Ok(())
- }
-
- fn restore_position(&self) -> std::io::Result<()> {
- if let Ok(val) = u32::try_from(SAVED_CURSOR_POS.load(Ordering::Relaxed)) {
- let x = (val >> 16) as i16;
- let y = val as i16;
- self.move_to(x, y)?;
- }
-
- Ok(())
- }
-
- fn save_position(&self) -> std::io::Result<()> {
- let position = self.position()?;
-
- let bits = u64::from(u32::from(position.x as u16) << 16 | u32::from(position.y as u16));
- SAVED_CURSOR_POS.store(bits, Ordering::Relaxed);
-
- Ok(())
- }
-}
-
-impl From for ScreenBufferCursor {
- fn from(handle: Handle) -> Self {
- ScreenBufferCursor {
- screen_buffer: ScreenBuffer::from(handle),
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{
- move_down, move_left, move_right, move_to, move_to_column, move_to_next_line,
- move_to_previous_line, move_to_row, move_up, position, restore_position, save_position,
- };
- use crate::terminal::sys::temp_screen_buffer;
- use serial_test::serial;
-
- #[test]
- #[serial]
- fn test_move_to_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- let (saved_x, saved_y) = position().unwrap();
-
- move_to(saved_x + 1, saved_y + 1).unwrap();
- assert_eq!(position().unwrap(), (saved_x + 1, saved_y + 1));
-
- move_to(saved_x, saved_y).unwrap();
- assert_eq!(position().unwrap(), (saved_x, saved_y));
- }
-
- #[test]
- #[serial]
- fn test_move_right_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- let (saved_x, saved_y) = position().unwrap();
- move_right(1).unwrap();
- assert_eq!(position().unwrap(), (saved_x + 1, saved_y));
- }
-
- #[test]
- #[serial]
- fn test_move_left_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(2, 0).unwrap();
-
- move_left(2).unwrap();
-
- assert_eq!(position().unwrap(), (0, 0));
- }
-
- #[test]
- #[serial]
- fn test_move_up_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 2).unwrap();
-
- move_up(2).unwrap();
-
- assert_eq!(position().unwrap(), (0, 0));
- }
-
- #[test]
- #[serial]
- fn test_move_to_next_line_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 2).unwrap();
-
- move_to_next_line(2).unwrap();
-
- assert_eq!(position().unwrap(), (0, 4));
- }
-
- #[test]
- #[serial]
- fn test_move_to_previous_line_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 2).unwrap();
-
- move_to_previous_line(2).unwrap();
-
- assert_eq!(position().unwrap(), (0, 0));
- }
-
- #[test]
- #[serial]
- fn test_move_to_column_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 2).unwrap();
-
- move_to_column(12).unwrap();
-
- assert_eq!(position().unwrap(), (12, 2));
- }
-
- #[test]
- #[serial]
- fn test_move_to_row_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 2).unwrap();
-
- move_to_row(5).unwrap();
-
- assert_eq!(position().unwrap(), (0, 5));
- }
-
- #[test]
- #[serial]
- fn test_move_down_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- move_to(0, 0).unwrap();
-
- move_down(2).unwrap();
-
- assert_eq!(position().unwrap(), (0, 2));
- }
-
- #[test]
- #[serial]
- fn test_save_restore_position_winapi() {
- let _test_screen = temp_screen_buffer().unwrap();
-
- let (saved_x, saved_y) = position().unwrap();
-
- save_position().unwrap();
- move_to(saved_x + 1, saved_y + 1).unwrap();
- restore_position().unwrap();
-
- let (x, y) = position().unwrap();
-
- assert_eq!(x, saved_x);
- assert_eq!(y, saved_y);
- }
-}
diff --git a/src/event.rs b/src/event.rs
index 4d28dc1..cbba317 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -119,165 +119,18 @@
//! them (`event-*`).
pub(crate) mod filter;
-pub(crate) mod read;
-pub(crate) mod source;
-#[cfg(feature = "event-stream")]
-pub(crate) mod stream;
pub(crate) mod sys;
-pub(crate) mod timeout;
-#[cfg(feature = "event-stream")]
-pub use stream::EventStream;
-
-use crate::event::{
- filter::{EventFilter, Filter},
- read::InternalEventReader,
- timeout::PollTimeout,
-};
use crate::{csi, Command};
-use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
-use std::fmt::{self, Display};
-use std::time::Duration;
+use std::{
+ collections::VecDeque,
+ fmt::{self, Display},
+};
use bitflags::bitflags;
use std::hash::{Hash, Hasher};
-/// Static instance of `InternalEventReader`.
-/// This needs to be static because there can be one event reader.
-static INTERNAL_EVENT_READER: Mutex