diff --git a/.gitignore b/.gitignore
index d48314551..6696b1879 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
-target/
-.idea/
-.vscode/
+**/target/
+**/.idea/
+**/.vscode/
**/*.rs.bk
-Cargo.lock
+**/Cargo.lock
diff --git a/.travis.yml b/.travis.yml
index 4a119fad0..978cc69b1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,3 @@
-# Set up the Rust toolchain.
language: rust
rust:
@@ -28,5 +27,4 @@ script:
- rustc --version
- if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
- cargo build
- - cargo test --all -- --nocapture --test-threads 1
- - scripts/test-examples.sh
+ - cargo test --all-features -- --nocapture --test-threads 1
diff --git a/docs/CHANGELOG.md b/CHANGELOG.md
similarity index 95%
rename from docs/CHANGELOG.md
rename to CHANGELOG.md
index 945be3476..bc1023e56 100644
--- a/docs/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,20 @@
-# Changes crossterm 0.11.0
+# Version 0.11.1
+
+- Maintenance release
+- All sub-crates were moved to their own repositories in the `crossterm-rs` organization
+
+# Version 0.11.0
+
As a preparation for crossterm 0.1.0 we have moved crossterm to an organisation called 'crossterm-rs'.
### Code Quality
+
- Code Cleanup: [warning-cleanup], [crossterm_style-cleanup], [crossterm_screen-cleanup], [crossterm_terminal-cleanup], [crossterm_utils-cleanup], [2018-cleanup], [api-cleanup-1], [api-cleanup-2], [api-cleanup-3]
- Examples: [example-cleanup_1], [example-cleanup_2], [example-fix], [commandbar-fix], [snake-game-improved]
- Fixed all broken tests and added tests
### Important Changes
+
- Return written bytes: [return-written-bytes]
- Added derives: `Debug` for `ObjectStyle` [debug-derive], Serialize/Deserialize for key events [serde]
- Improved error handling:
@@ -65,45 +73,52 @@ As a preparation for crossterm 0.1.0 we have moved crossterm to an organisation
[added-key-event-enter]: https://github.com/crossterm-rs/crossterm/pull/236
[fixed-get-set-terminal-size]: https://github.com/crossterm-rs/crossterm/pull/242
-# Changes crossterm 0.10.1
+# Version 0.10.1
-# Changes crossterm 0.10.0 ~ yanked
+# Version 0.10.0 ~ yanked
- Implemented command API, to have better performance and more control over how and when commands are executed. [PR](https://github.com/crossterm-rs/crossterm/commit/1a60924abd462ab169b6706aab68f4cca31d7bc2), [issue](https://github.com/crossterm-rs/crossterm/issues/171)
- Fixed showing, hiding cursor windows implementation
- Removed some of the parsing logic from windows keys to ansi codes to key events [PR](https://github.com/crossterm-rs/crossterm/commit/762c3a9b8e3d1fba87acde237f8ed09e74cd9ecd)
- Made terminal size 1-based [PR](https://github.com/crossterm-rs/crossterm/commit/d689d7e8ed46a335474b8262bd76f21feaaf0c50)
- Added some derive implementation
-# Changes crossterm 0.9.6
+# Version 0.9.6
+
- Copy for KeyEvent
- CTRL + Left, Down, Up, Right key support
- SHIFT + Left, Down, Up, Right key support
- Fixed UNIX cursor position bug [issue](https://github.com/crossterm-rs/crossterm/issues/140), [PR](https://github.com/crossterm-rs/crossterm/pull/152)
-# Changes crossterm 0.9.5
+# Version 0.9.5
+
- Prefetching buffer size for more efficient windows input reads. [PR](https://github.com/crossterm-rs/crossterm/pull/144)
-# Changes crossterm 0.9.4
+# Version 0.9.4
+
- Reset foreground and background color individually. [PR](https://github.com/crossterm-rs/crossterm/pull/138)
- Backtap input support. [PR](https://github.com/crossterm-rs/crossterm/pull/129)
- Corrected white/grey and added dark grey.
- Fixed getting cursor position with raw screen enabled. [PR](https://github.com/crossterm-rs/crossterm/pull/134)
- Removed one redundant stdout lock
-# Changes crossterm 0.9.3
+# Version 0.9.3
+
- Removed println from `SyncReader`
-## Changes crossterm 0.9.2
+## Version 0.9.2
+
- Terminal size linux was not 0-based
- Windows mouse input event position was 0-based ans should be 1-based
- Result, ErrorKind are made re-exported
- Fixed some special key combination detections for UNIX systems
- Made FreeBSD compile
-## Changes crossterm 0.9.1
+## Version 0.9.1
+
- Fixed libc compile error
-## Changes crossterm 0.9.0 (yanked)
+## Version 0.9.0 (yanked)
+
This release is all about moving to a stabilized API for 1.0.
- Major refactor and cleanup.
@@ -123,23 +138,28 @@ This release is all about moving to a stabilized API for 1.0.
- Raw modes UNIX systems improved
- Added `NoItalic` attribute
-## Changes crossterm to 0.8.2
+## Version 0.8.2
+
- Bug fix for sync reader UNIX.
-## Changes crossterm to 0.8.1
+## Version 0.8.1
+
- Added public re-exports for input.
-# Changes crossterm 0.8.0
+# Version 0.8.0
+
- Introduced KeyEvents
- Introduced MouseEvents
- Upgraded crossterm_winapi 0.2
-# Changes crossterm 0.7.0
+# Version 0.7.0
+
- Introduced more `Attributes`
- Introduced easier ways to style text [issue 87](https://github.com/crossterm-rs/crossterm/issues/87).
- Removed `ColorType` since it was unnecessary.
-# Changes crossterm 0.6.0
+# Version 0.6.0
+
- Introduced feature flags; input, cursor, style, terminal, screen.
- All modules are moved to their own crate.
- Introduced crossterm workspace
@@ -148,10 +168,12 @@ This release is all about moving to a stabilized API for 1.0.
[PR 84](https://github.com/crossterm-rs/crossterm/pull/84)
-# Changes crossterm 0.5.5
+# Version 0.5.5
+
- Error module is made public [PR 78](https://github.com/crossterm-rs/crossterm/pull/78).
-# Changes crossterm 0.5.4
+# Version 0.5.4
+
- WinApi rewrite and correctly error handled [PR 67](https://github.com/crossterm-rs/crossterm/pull/67)
- Windows attribute support [PR 62](https://github.com/crossterm-rs/crossterm/pull/62)
- Readline bug fix windows systems [PR 62](https://github.com/crossterm-rs/crossterm/pull/62)
@@ -159,31 +181,37 @@ This release is all about moving to a stabilized API for 1.0.
- General refactoring, all warnings removed.
- Documentation improvement.
-# Changes crossterm 0.5.1
+# Version 0.5.1
+
- Documentation refactor.
- Fixed broken API documentation [PR 53](https://github.com/crossterm-rs/crossterm/pull/53).
-# Changes crossterm 0.5.0
+# Version 0.5.0
+
- Added ability to pause the terminal [issue](https://github.com/crossterm-rs/crossterm/issues/39)
- RGB support for Windows 10 systems
- ANSI color value (255) color support
- More convenient API, no need to care about `Screen` unless working with when working with alternate or raw screen [PR](https://github.com/crossterm-rs/crossterm/pull/44)
- Implemented Display for styled object
-# Changes crossterm to 0.4.3
+# Version 0.4.3
+
- Fixed bug [issue 41](https://github.com/crossterm-rs/crossterm/issues/41)
-# Changes crossterm to 0.4.2
+# Version 0.4.2
+
- Added functionality to make a styled object writable to screen [issue 33](https://github.com/crossterm-rs/crossterm/issues/33)
- Added unit tests.
- Bugfix with getting terminal size unix.
- Bugfix with returning written bytes [pull request 31](https://github.com/crossterm-rs/crossterm/pull/31)
- removed methods calls: `as_any()` and `as_any_mut()` from `TerminalOutput`
-# Bug fix crossterm to 0.4.1
+# Version 0.4.1
+
- Fixed resizing of ansi terminal with and height where in the wrong order.
-# Features / Fixes in crossterm 0.4.0
+# Version 0.4.0
+
- Input support (read_line, read_char, read_async, read_until_async)
- Styling module improved
- Everything is multithreaded (`Send`, `Sync`)
@@ -194,7 +222,7 @@ This release is all about moving to a stabilized API for 1.0.
- Overall commend improvement.
- Overall refactor of code.
-# Features in crossterm 0.3.0
+# Version 0.3.0
This version has some braking changes check [upgrade manual](UPGRADE%20Manual.md) for more information about what is changed.
I think you should not switch to version `0.3.0` if you aren't going to use the AlternateScreen feature.
@@ -209,6 +237,7 @@ Some Features crossterm 0.3.0
- exit the current process.
## Alternate screen
+
This create supports alternate screen for both windows and unix systems. You can use
*Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
@@ -219,6 +248,7 @@ Vim uses the entirety of the screen to edit the file, then returning to bash lea
I Highly recommend you to check the `examples/program_examples/first_depth_search` for seeing this in action.
## Raw screen
+
This crate now supports raw screen for both windows and unix systems.
What exactly is raw state:
- No line buffering.
@@ -232,6 +262,7 @@ What exactly is raw state:
With these modes you can easier design the terminal screen.
## Some functionalities added
+
- Hiding and showing terminal cursor
- Enable or disabling blinking of the cursor for unix systems (this is not widely supported)
- Restoring the terminal to original modes.
@@ -319,10 +350,11 @@ like demonstrated above, to get the functionalities of `cursor(), color(), termi
You need to pass it the same `Context` as you have passed to the previous three called functions,
If you don't use the same `Context` in `cursor(), color(), terminal()` than these modules will be using the main screen and you will not see anything at the alternate screen. If you use the [Crossterm](https://github.com/crossterm-rs/crossterm/blob/master/src/shared/crossterm.rs) type you can get the `Context` from it by calling the crossterm.get_context() whereafter you can create the AlternateScreen from it.
-# Fixes in crossterm 0.2.2
+# Version 0.2.2
+
- Bug see [issue 15](https://github.com/crossterm-rs/crossterm/issues/15)
-# Fixes in crossterm 0.2.1
+# Version 0.2.1
- Default ANSI escape codes for windows machines, if windows does not support ANSI switch back to WinApi.
- method grammar mistake fixed [Issue 3](https://github.com/crossterm-rs/crossterm/issues/3)
@@ -330,7 +362,7 @@ If you don't use the same `Context` in `cursor(), color(), terminal()` than thes
- Removed bin reference from crate [Issue 6](https://github.com/crossterm-rs/crossterm/issues/6)
- Get position unix fixed [issue 8](https://github.com/crossterm-rs/crossterm/issues/8)
-# Features crossterm 0.2
+# Version 0.2
- 256 color support.
- Text Attributes like: bold, italic, underscore and crossed word ect.
diff --git a/Cargo.toml b/Cargo.toml
index 5634b20ba..61c85121f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "crossterm"
-version = "0.11.0"
+version = "0.11.1"
authors = ["T. Post"]
description = "An crossplatform terminal library for manipulating terminals."
repository = "https://github.com/crossterm-rs/crossterm"
@@ -12,7 +12,7 @@ readme = "README.md"
edition = "2018"
[features]
-default = ["cursor", "style","terminal","screen","input"]
+default = ["cursor", "style", "terminal", "screen", "input"]
cursor = ["crossterm_cursor"]
style = ["crossterm_style"]
@@ -20,29 +20,13 @@ terminal = ["crossterm_terminal"]
screen = ["crossterm_screen"]
input = ["crossterm_input"]
-[workspace]
-
-members = [
- "crossterm_winapi",
- "crossterm_utils",
- "crossterm_cursor",
- "crossterm_style",
- "crossterm_terminal",
- "crossterm_input",
- "crossterm_screen"
-]
-
-exclude = [
- "examples/program_examples"
-]
-
[dependencies]
-crossterm_screen = { path = "./crossterm_screen", version = "0.3.0" , optional = true }
-crossterm_cursor = { path = "./crossterm_cursor", version = "0.3.0" , optional = true }
-crossterm_terminal = { path = "./crossterm_terminal", version = "0.3.0", optional = true }
-crossterm_style = { path = "./crossterm_style", version = "0.5.0" , optional = true }
-crossterm_input = { path = "./crossterm_input", version = "0.4.0" , optional = true }
-crossterm_utils = { path = "./crossterm_utils", version = "0.3.0" , optional = false }
+crossterm_screen = { version = "0.3.1" , optional = true }
+crossterm_cursor = { version = "0.3.1" , optional = true }
+crossterm_terminal = { version = "0.3.1", optional = true }
+crossterm_style = { version = "0.5.1" , optional = true }
+crossterm_input = { version = "0.4.1" , optional = true }
+crossterm_utils = { version = "0.3.1" , optional = false }
[lib]
name = "crossterm"
diff --git a/README.md b/README.md
index 4751057d1..350aa512a 100644
--- a/README.md
+++ b/README.md
@@ -1,81 +1,66 @@
-# cross-platform terminal manipulating library.
- [![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]
+[![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]
-[s1]: https://img.shields.io/crates/v/crossterm.svg
-[l1]: https://crates.io/crates/crossterm
-
-[s2]: https://img.shields.io/badge/license-MIT-blue.svg
-[l2]: crossterm/LICENSE
-
-[s3]: https://docs.rs/crossterm/badge.svg
-[l3]: https://docs.rs/crossterm/
-
-[s3]: https://docs.rs/crossterm/badge.svg
-[l3]: https://docs.rs/crossterm/
-
-[s5]: https://img.shields.io/discord/560857607196377088.svg?logo=discord
-[l5]: https://discord.gg/K4nyTDB
-
-[s6]: https://tokei.rs/b1/github/crossterm-rs/crossterm?category=code
-[s7]: https://travis-ci.org/crossterm-rs/crossterm.svg?branch=master
+# cross-platform terminal manipulating library.
Have you ever been disappointed when a terminal library for rust was only written for UNIX systems?
-Crossterm provides clearing, input handling, styling, cursor movement, and terminal actions for both Windows and UNIX systems.
+Crossterm provides clearing, input handling, styling, cursor movement, and terminal actions for both
+Windows and UNIX systems.
Crossterm aims to be simple and easy to call in code.
Through the simplicity of Crossterm, you do not have to worry about the platform you are working with.
-This crate supports all UNIX and Windows terminals down to Windows 7 (not all terminals are tested see [Tested Terminals](#tested-terminals) for more info).
+This crate supports all UNIX and Windows terminals down to Windows 7 (not all terminals are tested
+see [Tested Terminals](#tested-terminals) for more info).
-This crate consists of five modules that are provided behind [feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html) so that you can define which features you'd like to have; by default, all features are enabled.
-- [Crossterm Style](https://crates.io/crates/crossterm_style)
-- [Crossterm Input](https://crates.io/crates/crossterm_input)
-- [Crossterm Screen](https://crates.io/crates/crossterm_screen)
-- [Crossterm Cursor](https://crates.io/crates/crossterm_cursor)
-- [Crossterm Terminal](https://crates.io/crates/crossterm_terminal)
+This crate consists of five modules that are provided behind
+[feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html) so that you can define
+which features you'd like to have; by default, all features are enabled.
+
+- [crossterm_style](https://crates.io/crates/crossterm_style)
+- [crossterm_input](https://crates.io/crates/crossterm_input)
+- [crossterm_screen](https://crates.io/crates/crossterm_screen)
+- [crossterm_cursor](https://crates.io/crates/crossterm_cursor)
+- [crossterm_terminal](https://crates.io/crates/crossterm_terminal)
## Table of contents:
+
- [Getting started](#getting-started)
- [Useful links](#useful-links)
- [Features](#features)
- [Examples](#examples)
- - [Crossterm Type](#crossterm-type)
- [Styled Text](#styled-text)
- [Cursor](#cursor)
- [Terminal](#terminal)
- [Input Reading](#input-reading)
- [Tested Terminals](#tested-terminals)
-- [Notice](#notice)
-- [Todo](#todo)
- [Contributing](#contributing)
- [Authors](#authors)
- [License](#license)
## Getting Started
-All [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) of how crossterm works can be found in the example directory.
+All [examples](https://github.com/crossterm-rs/examples) of how crossterm works can be found in the example repository.
Add the Crossterm package to your `Cargo.toml` file.
```
[dependencies]
-crossterm = "^0.11"
+crossterm = "0.11"
```
### Useful Links
-- [Book](https://crossterm-rs.github.io/crossterm/docs//)
+- [Book](https://crossterm-rs.github.io/crossterm/docs/)
- [Documentation](https://docs.rs/crossterm/)
- [Crates.io](https://crates.io/crates/crossterm)
-- [Program Examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/program_examples)
-- [Examples](https://github.com/crossterm-rs/crossterm/tree/master/examples)
+- [Examples](https://github.com/crossterm-rs/examples)
## Features
- Cross-platform
-- Multithreaded (send, sync)
+- Multi-threaded (send, sync)
- Detailed Documentation
- Few Dependencies
- Cursor
@@ -104,19 +89,25 @@ crossterm = "^0.11"
- Read mouse input events (press, release, position, button)
## Examples
-These are some basic examples demonstrating how to use this crate. See [examples](https://github.com/crossterm-rs/crossterm/blob/master/examples/) for more.
+
+These are some basic examples demonstrating how to use this crate. See the
+[examples](https://github.com/crossterm-rs/examples) repository.
### Command API
-My first recommendation is to use the [command API](https://crossterm-rs.github.io/crossterm/docs/command.html) because this might replace some of the existing API in the future.
-Because it is more convenient, faster, and easier to use.
+My first recommendation is to use the [command API](https://crossterm-rs.github.io/crossterm/docs/command.html)
+because this might replace some of the existing API in the future. It is more convenient, faster, and easier to use.
### Styled Text
+
This module enables you to style the terminal text.
-Good documentation can be found at the following places: [docs](https://docs.rs/crossterm_style/), [book](https://crossterm-rs.github.io/crossterm/docs/styling.html), [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/key_events.rs)
+Good documentation can be found at the following places: [docs](https://docs.rs/crossterm_style/),
+[book](https://crossterm-rs.github.io/crossterm/docs/styling.html)
+and [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/key_events.rs).
_style text with attributes_
+
```rust
use crossterm::{Colored, Color, Colorize, Styler, Attribute};
@@ -129,6 +120,7 @@ println!("{}", styled_text);
```
_style text with colors_
+
```rust
println!("{} Red foreground color", Colored::Fg(Color::Red));
println!("{} Blue background color", Colored::Bg(Color::Blue));
@@ -137,7 +129,9 @@ println!("{} Blue background color", Colored::Bg(Color::Blue));
let styled_text = "Bold Underlined".red().on_blue();
println!("{}", styled_text);
```
+
_style text with RGB and ANSI Value_
+
```rust
// custom rgb value (Windows 10 and UNIX systems)
println!("{} some colored text", Colored::Fg(Color::Rgb {
@@ -150,11 +144,12 @@ println!("{} some colored text", Colored::Fg(Color::Rgb {
println!("{} some colored text", Colored::Fg(Color::AnsiValue(10)));
```
-
### Cursor
+
This module enables you to work with the terminal cursor.
-Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_cursor/), [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/cursor.rs)
+Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_cursor/) and
+[examples](https://github.com/crossterm-rs/examples).
```rust
use crossterm::cursor;
@@ -194,9 +189,11 @@ cursor.blink(true)
```
### Terminal
+
This module enables you to work with the terminal in general.
-Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_terminal/), [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/terminal.rs).
+Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_terminal/) and
+[examples](https://github.com/crossterm-rs/examples).
```rust
use crossterm::{terminal,ClearType};
@@ -233,9 +230,12 @@ terminal.write("Some text\n Some text on new line");
```
### Input Reading
+
This module enables you to read user input events.
-Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_input/), [book](https://crossterm-rs.github.io/crossterm/docs/input.html), [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples/key_events.rs)
+Good documentation could be found on the following places: [docs](https://docs.rs/crossterm_input/),
+[book](https://crossterm-rs.github.io/crossterm/docs/input.html) and
+[examples](https://github.com/crossterm-rs/examples).
_available imports_
```rust
@@ -245,6 +245,7 @@ use crossterm_input::{
```
_Simple Readings_
+
```rust
let mut input = input();
@@ -260,8 +261,10 @@ let mut input = input();
```
_Read input events synchronously or asynchronously._
+
```rust
-// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
+// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's
+// self and allows crossterm to read the input and pass it back to you.
let screen = RawScreen::into_raw_mode();
let mut input = input();
@@ -281,6 +284,7 @@ if let Some(key_event) = stdin.next() {
```
_Enable mouse input events._
+
```rust
let input = input();
@@ -292,9 +296,13 @@ input.disable_mouse_mode().unwrap();
```
### Alternate and Raw Screen
-These concepts are a little more complex and would take over the README, please check out the [docs](https://docs.rs/crossterm_screen/), [book](https://crossterm-rs.github.io/crossterm/docs/screen.html), and [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples).
-## Used By
+These concepts are a little more complex and would take over the README, please check out
+the [docs](https://docs.rs/crossterm_screen/), [book](https://crossterm-rs.github.io/crossterm/docs/screen.html)
+and [examples](https://github.com/crossterm-rs/examples).
+
+## Used by
+
- [Broot](https://dystroy.org/broot/)
- [Cursive](https://github.com/gyscos/Cursive)
- [TUI](https://github.com/fdehau/tui-rs)
@@ -312,8 +320,9 @@ These concepts are a little more complex and would take over the README, please
- (Arch, Manjaro) KDE Konsole
- Linux Mint
-This crate supports all Unix terminals and Windows terminals down to Windows 7; however, not all of the terminals have been tested.
-If you have used this library for a terminal other than the above list without issues, then feel free to add it to the above list - I really would appreciate it!
+This crate supports all Unix terminals and Windows terminals down to Windows 7; however, not all of the
+terminals have been tested. If you have used this library for a terminal other than the above list without
+issues, then feel free to add it to the above list - I really would appreciate it!
## Contributing
@@ -332,4 +341,24 @@ Would you like crossterm to be even more gorgeous and beautiful? You can help wi
## License
-This project, crossterm and all it's sub-modules: crossterm_screen, crossterm_cursor, crossterm_style, crossterm_input, crossterm_terminal, crossterm_winapi, crossterm_utils are licensed under the MIT License - see the [LICENSE.md](https://github.com/crossterm-rs/crossterm/blob/master/LICENSE) file for details
+This project, crossterm and all it's sub-modules: crossterm_screen, crossterm_cursor, crossterm_style,
+crossterm_input, crossterm_terminal, crossterm_winapi, crossterm_utils are licensed under the MIT License - see
+the [LICENSE](https://github.com/crossterm-rs/crossterm/blob/master/LICENSE) file for details
+
+[s1]: https://img.shields.io/crates/v/crossterm.svg
+[l1]: https://crates.io/crates/crossterm
+
+[s2]: https://img.shields.io/badge/license-MIT-blue.svg
+[l2]: crossterm/LICENSE
+
+[s3]: https://docs.rs/crossterm/badge.svg
+[l3]: https://docs.rs/crossterm/
+
+[s3]: https://docs.rs/crossterm/badge.svg
+[l3]: https://docs.rs/crossterm/
+
+[s5]: https://img.shields.io/discord/560857607196377088.svg?logo=discord
+[l5]: https://discord.gg/K4nyTDB
+
+[s6]: https://tokei.rs/b1/github/crossterm-rs/crossterm?category=code
+[s7]: https://travis-ci.org/crossterm-rs/crossterm.svg?branch=master
diff --git a/crossterm_cursor/.gitignore b/crossterm_cursor/.gitignore
deleted file mode 100644
index 53eaa2196..000000000
--- a/crossterm_cursor/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/target
-**/*.rs.bk
diff --git a/crossterm_cursor/CHANGELOG.md b/crossterm_cursor/CHANGELOG.md
deleted file mode 100644
index b53af9eda..000000000
--- a/crossterm_cursor/CHANGELOG.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Changes crossterm_cursor 0.3
-- `TerminalCursor::pos()` returns `crossterm::Result<(u16, u16)>`
-- `TerminalCursor::move_*` returns `crossterm::Result`
-- `TerminalCursor::reset_position()` to `restore_position()`
-- All `i16` values for indexing: set/get cursor pos synced to `u16` values
-- `Command::get_anis_code()` to `ansi_code()`
-- `ExecutableCommand::queue` returns `crossterm::Result`
-- `QueueableCommand::queue` returns `crossterm::Result`
-- Command API takes mutable self instead of self
-
-# Changes crossterm_cursor 0.2
-- Removed `TerminalCursor::from_output()`
-
-# Changes crossterm_cursor 0.1
-- Moved out of `crossterm` 5.4 crate.
\ No newline at end of file
diff --git a/crossterm_cursor/Cargo.toml b/crossterm_cursor/Cargo.toml
deleted file mode 100644
index ca93fcb46..000000000
--- a/crossterm_cursor/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "crossterm_cursor"
-version = "0.3.0"
-authors = ["T. Post"]
-description = "A cross-platform library for moving the terminal cursor."
-repository = "https://github.com/crossterm-rs/crossterm"
-documentation = "https://docs.rs/crossterm_cursor/"
-license = "MIT"
-keywords = ["cursor", "cli", "crossterm", "crossplatform", "terminal"]
-exclude = ["target", "Cargo.lock"]
-readme = "README.md"
-edition = "2018"
-
-[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3.8", features = ["wincon","winnt","minwindef"] }
-crossterm_winapi = { path="../crossterm_winapi", version = "0.2.0"}
-
-[dependencies]
-crossterm_utils = { path="../crossterm_utils", version = "0.3.0"}
diff --git a/crossterm_cursor/LICENSE b/crossterm_cursor/LICENSE
deleted file mode 100644
index 8b02a7fce..000000000
--- a/crossterm_cursor/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 Timon
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/crossterm_cursor/README.md b/crossterm_cursor/README.md
deleted file mode 100644
index d63754f47..000000000
--- a/crossterm_cursor/README.md
+++ /dev/null
@@ -1,141 +0,0 @@
-# Crossterm Cursor | cross-platform cursor movement.
- ![Lines of Code][s7] [![Latest Version][s1]][l1] [![MIT][s2]][l2] [![docs][s3]][l3] [![Join us on Discord][s5]][l5]
-
-[s1]: https://img.shields.io/crates/v/crossterm_cursor.svg
-[l1]: https://crates.io/crates/crossterm_cursor
-
-[s2]: https://img.shields.io/badge/license-MIT-blue.svg
-[l2]: ./LICENSE
-
-[s3]: https://docs.rs/crossterm_cursor/badge.svg
-[l3]: https://docs.rs/crossterm_cursor/
-
-[s5]: https://img.shields.io/discord/560857607196377088.svg?logo=discord
-[l5]: https://discord.gg/K4nyTDB
-
-[s7]: https://travis-ci.org/crossterm-rs/crossterm.svg?branch=master
-
-This crate allows you to move the terminal cursor cross-platform.
-It supports all UNIX and windows terminals down to windows 7 (not all terminals are tested see [Tested Terminals](#tested-terminals) for more info)
-
-This crate is a sub-crate of [crossterm](https://crates.io/crates/crossterm) to move the cursor, and can be use individually.
-
-Other sub-crates are:
-- [Crossterm Style](https://crates.io/crates/crossterm_style)
-- [Crossterm Terminal](https://crates.io/crates/crossterm_terminal)
-- [Crossterm Screen](https://crates.io/crates/crossterm_screen)
-- [Crossterm Input](https://crates.io/crates/crossterm_input)
-
-When you want to use other modules as well you might want to use crossterm with [feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html).
-
-## Table of contents:
-- [Getting started](#getting-started)
-- [Useful links](#useful-links)
-- [Features](#features)
-- [Examples](#examples)
-- [Tested Terminals](#tested-terminals)
-- [Authors](#authors)
-- [License](#license)
-
-## Getting Started
-
-All examples of how `crossterm_cursor` works can be found in the [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) directory.
-
-Add the `crossterm_cursor` package to your `Cargo.toml` file.
-
-```
-[dependencies]
-crossterm_cursor = "0.2"
-```
-Import the `crossterm_cursor` modules you want to use.
-
-```rust
-pub use crossterm_cursor::{cursor, TerminalCursor};
-```
-
-### Useful Links
-
-- [Documentation](https://docs.rs/crossterm_cursor/)
-- [Crates.io](https://crates.io/crates/crossterm_cursor)
-- [Examples](/examples)
-
-## Features
-These are the features of this crate:
-
-- Cross-platform
-- Multithreaded (send, sync)
-- Detailed Documentation
-- Few Dependencies
-- Cursor
- - Moving _n_ times (up, down, left, right)
- - Position (set/get)
- - Store cursor position and resetting to that later
- - Hiding/Showing
- - Blinking Cursor (only some terminals are supporting this)
-
-## Command API
-
-My first recommendation is to use the [command API](https://crossterm-rs.github.io/crossterm/docs/command.html) because this might replace some of the existing API in the future.
-Because it is more convenient, faster, and easier to use.
-
-## Examples
-The [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) folder has more complete and verbose examples.
-
-```rust
-use crossterm_cursor::cursor;
-
-let mut cursor = cursor();
-
-/// Moving the cursor
-// Set the cursor to position X: 10, Y: 5 in the terminal
-cursor.goto(10,5);
-
-// Move the cursor up,right,down,left 3 cells.
-cursor.move_up(3);
-cursor.move_right(3);
-cursor.move_down(3);
-cursor.move_left(3);
-
-/// Safe the current cursor position to recall later
-// Goto X: 5 Y: 5
-cursor.goto(5,5);
-// Safe cursor position: X: 5 Y: 5
-cursor.save_position();
-// Goto X: 5 Y: 20
-cursor.goto(5,20);
-// Print at X: 5 Y: 20.
-print!("Yea!");
-// Reset back to X: 5 Y: 5.
-cursor.restore_position();
-// Print 'Back' at X: 5 Y: 5.
-print!("Back");
-
-// hide cursor
-cursor.hide();
-// show cursor
-cursor.show();
-// blink or not blinking of the cursor (not widely supported)
-cursor.blink(true)
-
-```
-## Tested terminals
-
-- Windows Powershell
- - Windows 10 (pro)
-- Windows CMD
- - Windows 10 (pro)
- - Windows 8.1 (N)
-- Ubuntu Desktop Terminal
- - Ubuntu 17.10
-- (Arch, Manjaro) KDE Konsole
-- Linux Mint
-
-This crate supports all Unix terminals and windows terminals down to Windows 7 but not all of them have been tested.
-If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
-
-## Authors
-
-* **Timon Post** - *Project Owner & creator*
-
-## License
-This project is licensed under the MIT License - see the [LICENSE.md](./LICENSE) file for details
diff --git a/crossterm_cursor/src/cursor.rs b/crossterm_cursor/src/cursor.rs
deleted file mode 100644
index 56d41bfb2..000000000
--- a/crossterm_cursor/src/cursor.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-//! A module that contains all the actions related to cursor movement in the terminal.
-//! Like: moving the cursor position; saving and resetting the cursor position; hiding showing and control
-//! the blinking of the cursor.
-//!
-//! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
-
-use crossterm_utils::Result;
-
-pub use self::cursor::{
- cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
- TerminalCursor, Up,
-};
-
-mod cursor;
-
-mod ansi_cursor;
-#[cfg(windows)]
-mod winapi_cursor;
-
-///! This trait defines the actions that can be performed with the terminal cursor.
-///! This trait can be implemented so that a concrete implementation of the ITerminalCursor can fulfill
-///! the wishes to work on a specific platform.
-///!
-///! ## For example:
-///!
-///! This trait is implemented for `WinApi` (Windows specific) and `ANSI` (Unix specific),
-///! so that cursor related actions can be performed on both UNIX and Windows systems.
-trait ITerminalCursor: Sync + Send {
- /// Goto location (`x`, `y`) in the current terminal window.
- fn goto(&self, x: u16, y: u16) -> Result<()>;
- /// Get the cursor location `(x, y)` in the current terminal window.
- fn pos(&self) -> Result<(u16, u16)>;
- /// Move cursor `n` times up
- fn move_up(&self, count: u16) -> Result<()>;
- /// Move the cursor `n` times to the right.
- fn move_right(&self, count: u16) -> Result<()>;
- /// Move the cursor `n` times down.
- fn move_down(&self, count: u16) -> Result<()>;
- /// Move the cursor `n` times left.
- fn move_left(&self, count: u16) -> Result<()>;
- /// Save cursor position so that its saved position can be recalled later. Note that this position
- /// is stored program based not per instance of the cursor struct.
- fn save_position(&self) -> Result<()>;
- /// Return to saved cursor position
- fn restore_position(&self) -> Result<()>;
- /// Hide the terminal cursor.
- fn hide(&self) -> Result<()>;
- /// Show the terminal cursor
- fn show(&self) -> Result<()>;
- /// Enable or disable the blinking of the cursor.
- fn blink(&self, blink: bool) -> Result<()>;
-}
diff --git a/crossterm_cursor/src/cursor/ansi_cursor.rs b/crossterm_cursor/src/cursor/ansi_cursor.rs
deleted file mode 100644
index 68b7c54a8..000000000
--- a/crossterm_cursor/src/cursor/ansi_cursor.rs
+++ /dev/null
@@ -1,164 +0,0 @@
-//! This is an ANSI specific implementation for cursor related action.
-//! This module is used for windows 10 terminals and UNIX terminals by default.
-//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position etc.
-
-use crossterm_utils::{csi, write_cout, Result};
-
-use crate::sys::{get_cursor_position, show_cursor};
-
-use super::ITerminalCursor;
-
-pub fn get_goto_ansi(x: u16, y: u16) -> String {
- format!(csi!("{};{}H"), y + 1, x + 1)
-}
-
-pub fn get_move_up_ansi(count: u16) -> String {
- format!(csi!("{}A"), count)
-}
-
-pub fn get_move_right_ansi(count: u16) -> String {
- format!(csi!("{}C"), count)
-}
-
-pub fn get_move_down_ansi(count: u16) -> String {
- format!(csi!("{}B"), count)
-}
-
-pub fn get_move_left_ansi(count: u16) -> String {
- format!(csi!("{}D"), count)
-}
-
-pub static SAVE_POS_ANSI: &'static str = csi!("s");
-pub static RESTORE_POS_ANSI: &'static str = csi!("u");
-pub static HIDE_ANSI: &'static str = csi!("?25l");
-pub static SHOW_ANSI: &'static str = csi!("?25h");
-pub static BLINK_ON_ANSI: &'static str = csi!("?12h");
-pub static BLINK_OFF_ANSI: &'static str = csi!("?12l");
-
-/// This struct is an ANSI implementation for cursor related actions.
-pub struct AnsiCursor;
-
-impl AnsiCursor {
- pub fn new() -> AnsiCursor {
- AnsiCursor
- }
-}
-
-impl ITerminalCursor for AnsiCursor {
- fn goto(&self, x: u16, y: u16) -> Result<()> {
- write_cout!(get_goto_ansi(x, y))?;
- Ok(())
- }
-
- fn pos(&self) -> Result<(u16, u16)> {
- get_cursor_position()
- }
-
- fn move_up(&self, count: u16) -> Result<()> {
- write_cout!(get_move_up_ansi(count))?;
- Ok(())
- }
-
- fn move_right(&self, count: u16) -> Result<()> {
- write_cout!(get_move_right_ansi(count))?;
- Ok(())
- }
-
- fn move_down(&self, count: u16) -> Result<()> {
- write_cout!(get_move_down_ansi(count))?;
- Ok(())
- }
-
- fn move_left(&self, count: u16) -> Result<()> {
- write_cout!(get_move_left_ansi(count))?;
- Ok(())
- }
-
- fn save_position(&self) -> Result<()> {
- write_cout!(SAVE_POS_ANSI)?;
- Ok(())
- }
-
- fn restore_position(&self) -> Result<()> {
- write_cout!(RESTORE_POS_ANSI)?;
- Ok(())
- }
-
- fn hide(&self) -> Result<()> {
- show_cursor(false)?;
- Ok(())
- }
-
- fn show(&self) -> Result<()> {
- show_cursor(true)?;
- Ok(())
- }
-
- fn blink(&self, blink: bool) -> Result<()> {
- if blink {
- write_cout!(BLINK_ON_ANSI)?;
- } else {
- write_cout!(BLINK_OFF_ANSI)?;
- }
- Ok(())
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{AnsiCursor, ITerminalCursor};
-
- // TODO - Test is ingored, because it's stalled on Travis CI
- #[test]
- #[ignore]
- fn test_ansi_save_restore_position() {
- if try_enable_ansi() {
- let cursor = AnsiCursor::new();
-
- let (saved_x, saved_y) = cursor.pos().unwrap();
-
- cursor.save_position().unwrap();
- cursor.goto(saved_x + 1, saved_y + 1).unwrap();
- cursor.restore_position().unwrap();
-
- let (x, y) = cursor.pos().unwrap();
-
- assert_eq!(x, saved_x);
- assert_eq!(y, saved_y);
- }
- }
-
- // TODO - Test is ingored, because it's stalled on Travis CI
- #[test]
- #[ignore]
- fn test_ansi_goto() {
- if try_enable_ansi() {
- let cursor = AnsiCursor::new();
-
- let (saved_x, saved_y) = cursor.pos().unwrap();
-
- cursor.goto(saved_x + 1, saved_y + 1).unwrap();
- assert_eq!(cursor.pos().unwrap(), (saved_x + 1, saved_y + 1));
-
- cursor.goto(saved_x, saved_y).unwrap();
- assert_eq!(cursor.pos().unwrap(), (saved_x, saved_y));
- }
- }
-
- fn try_enable_ansi() -> bool {
- #[cfg(windows)]
- {
- if cfg!(target_os = "windows") {
- use crossterm_utils::sys::winapi::ansi::set_virtual_terminal_processing;
-
- // if it is not listed we should try with WinApi to check if we do support ANSI-codes.
- match set_virtual_terminal_processing(true) {
- Ok(_) => return true,
- Err(_) => return false,
- }
- }
- }
-
- true
- }
-}
diff --git a/crossterm_cursor/src/cursor/cursor.rs b/crossterm_cursor/src/cursor/cursor.rs
deleted file mode 100644
index 16cd04716..000000000
--- a/crossterm_cursor/src/cursor/cursor.rs
+++ /dev/null
@@ -1,342 +0,0 @@
-//! A module that contains all the actions related to cursor movement in the terminal.
-//! Like: moving the cursor position; saving and resetting the cursor position; hiding showing and control the blinking of the cursor.
-
-#[cfg(windows)]
-use crossterm_utils::supports_ansi;
-use crossterm_utils::{impl_display, Command, Result};
-
-use super::ansi_cursor::{self, AnsiCursor};
-#[cfg(windows)]
-use super::winapi_cursor::WinApiCursor;
-use super::ITerminalCursor;
-
-/// Allows you to preform actions with the terminal cursor.
-///
-/// # Features:
-///
-/// - Moving n times Up, Down, Left, Right
-/// - Goto a certain position
-/// - Get cursor position
-/// - Storing the current cursor position and resetting to that stored cursor position later
-/// - Hiding and showing the cursor
-/// - Control over blinking of the terminal cursor (only some terminals are supporting this)
-///
-/// Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
-///
-/// Check `/examples/cursor` in the library for more specific examples.
-pub struct TerminalCursor {
- #[cfg(windows)]
- cursor: Box<(dyn ITerminalCursor + Sync + Send)>,
- #[cfg(unix)]
- cursor: AnsiCursor,
-}
-
-impl TerminalCursor {
- /// Create new `TerminalCursor` instance whereon cursor related actions can be performed.
- pub fn new() -> TerminalCursor {
- #[cfg(windows)]
- let cursor = if supports_ansi() {
- Box::from(AnsiCursor::new()) as Box<(dyn ITerminalCursor + Sync + Send)>
- } else {
- WinApiCursor::new() as Box<(dyn ITerminalCursor + Sync + Send)>
- };
-
- #[cfg(unix)]
- let cursor = AnsiCursor::new();
-
- TerminalCursor { cursor }
- }
-
- /// Goto some position (x,y) in the terminal.
- ///
- /// # Remarks
- /// position is 0-based, which means we start counting at 0.
- pub fn goto(&self, x: u16, y: u16) -> Result<()> {
- self.cursor.goto(x, y)
- }
-
- /// Get current cursor position (x,y) in the terminal.
- ///
- /// # Remarks
- /// position is 0-based, which means we start counting at 0.
- pub fn pos(&self) -> Result<(u16, u16)> {
- self.cursor.pos()
- }
-
- /// Move the current cursor position `n` times up.
- pub fn move_up(&mut self, count: u16) -> Result<&mut TerminalCursor> {
- self.cursor.move_up(count)?;
- Ok(self)
- }
-
- /// Move the current cursor position `n` times right.
- pub fn move_right(&mut self, count: u16) -> Result<&mut TerminalCursor> {
- self.cursor.move_right(count)?;
- Ok(self)
- }
-
- /// Move the current cursor position `n` times down.
- pub fn move_down(&mut self, count: u16) -> Result<&mut TerminalCursor> {
- self.cursor.move_down(count)?;
- Ok(self)
- }
-
- /// Move the current cursor position `n` times left.
- pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> {
- self.cursor.move_left(count)?;
- Ok(self)
- }
-
- /// Save cursor position for recall later.
- ///
- /// Note that this position is stored program based not per instance of the `Cursor` struct.
- pub fn save_position(&self) -> Result<()> {
- self.cursor.save_position()
- }
-
- /// Return to saved cursor position
- pub fn restore_position(&self) -> Result<()> {
- self.cursor.restore_position()
- }
-
- /// Hide de cursor in the console.
- pub fn hide(&self) -> Result<()> {
- self.cursor.hide()
- }
-
- /// Show the cursor in the console.
- pub fn show(&self) -> Result<()> {
- self.cursor.show()
- }
-
- /// Enable or disable blinking of the terminal.
- ///
- /// # Remarks
- /// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
- pub fn blink(&self, blink: bool) -> Result<()> {
- self.cursor.blink(blink)
- }
-}
-
-/// Get a `TerminalCursor` instance whereon cursor related actions can be performed.
-pub fn cursor() -> TerminalCursor {
- TerminalCursor::new()
-}
-
-/// When executed, this command will move the cursor position to the given `x` and `y` in the terminal window.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Goto(pub u16, pub u16);
-
-impl Command for Goto {
- type AnsiType = String;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::get_goto_ansi(self.0, self.1)
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().goto(self.0, self.1)
- }
-}
-
-/// When executed, this command will move the current cursor position `n` times up.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Up(pub u16);
-
-impl Command for Up {
- type AnsiType = String;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::get_move_up_ansi(self.0)
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().move_up(self.0)
- }
-}
-
-/// When executed, this command will move the current cursor position `n` times down.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Down(pub u16);
-
-impl Command for Down {
- type AnsiType = String;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::get_move_down_ansi(self.0)
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().move_down(self.0)
- }
-}
-
-/// When executed, this command will move the current cursor position `n` times left.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Left(pub u16);
-
-impl Command for Left {
- type AnsiType = String;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::get_move_left_ansi(self.0)
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().move_left(self.0)
- }
-}
-
-/// When executed, this command will move the current cursor position `n` times right.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Right(pub u16);
-
-impl Command for Right {
- type AnsiType = String;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::get_move_right_ansi(self.0)
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().move_right(self.0)
- }
-}
-
-/// When executed, this command will save the cursor position for recall later.
-///
-/// Note that this position is stored program based not per instance of the `Cursor` struct.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct SavePos;
-
-impl Command for SavePos {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::SAVE_POS_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().save_position()
- }
-}
-
-/// When executed, this command will return the cursor position to the saved cursor position
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct ResetPos;
-
-impl Command for ResetPos {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::RESTORE_POS_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().restore_position()
- }
-}
-
-/// When executed, this command will hide de cursor in the console.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Hide;
-
-impl Command for Hide {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::HIDE_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().hide()
- }
-}
-
-/// When executed, this command will show de cursor in the console.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct Show;
-
-impl Command for Show {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::SHOW_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- WinApiCursor::new().show()
- }
-}
-
-/// When executed, this command will enable cursor blinking.
-///
-/// # Remarks
-/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct BlinkOn;
-
-impl Command for BlinkOn {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::BLINK_ON_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- Ok(())
- }
-}
-
-/// When executed, this command will disable cursor blinking.
-///
-/// # Remarks
-/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
-///
-/// See `crossterm/examples/command.rs` for more information on how to execute commands.
-pub struct BlinkOff;
-
-impl Command for BlinkOff {
- type AnsiType = &'static str;
-
- fn ansi_code(&self) -> Self::AnsiType {
- ansi_cursor::BLINK_OFF_ANSI
- }
-
- #[cfg(windows)]
- fn execute_winapi(&self) -> Result<()> {
- Ok(())
- }
-}
-
-impl_display!(for Goto);
-impl_display!(for Up);
-impl_display!(for Down);
-impl_display!(for Left);
-impl_display!(for Right);
-impl_display!(for SavePos);
-impl_display!(for ResetPos);
-impl_display!(for Hide);
-impl_display!(for Show);
-impl_display!(for BlinkOn);
-impl_display!(for BlinkOff);
diff --git a/crossterm_cursor/src/cursor/winapi_cursor.rs b/crossterm_cursor/src/cursor/winapi_cursor.rs
deleted file mode 100644
index 4b649e5cc..000000000
--- a/crossterm_cursor/src/cursor/winapi_cursor.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-//! This is a WINAPI specific implementation for cursor related actions.
-//! This module is used for Windows terminals that do not support ANSI escape codes.
-//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position.
-
-use crossterm_utils::Result;
-
-use crate::sys::winapi::{Cursor, Handle};
-
-use super::ITerminalCursor;
-
-/// This struct is a windows implementation for cursor related actions.
-pub struct WinApiCursor;
-
-impl WinApiCursor {
- pub fn new() -> Box {
- Box::from(WinApiCursor)
- }
-}
-
-impl ITerminalCursor for WinApiCursor {
- fn goto(&self, x: u16, y: u16) -> Result<()> {
- let cursor = Cursor::new()?;
- cursor.goto(x as i16, y as i16)?;
- Ok(())
- }
-
- fn pos(&self) -> Result<(u16, u16)> {
- let cursor = Cursor::new()?;
- Ok(cursor.position()?.into())
- }
-
- fn move_up(&self, count: u16) -> Result<()> {
- let (xpos, ypos) = self.pos()?;
- self.goto(xpos, ypos - count)?;
- Ok(())
- }
-
- fn move_right(&self, count: u16) -> Result<()> {
- let (xpos, ypos) = self.pos()?;
- self.goto(xpos + count, ypos)?;
- Ok(())
- }
-
- fn move_down(&self, count: u16) -> Result<()> {
- let (xpos, ypos) = self.pos()?;
- self.goto(xpos, ypos + count)?;
- Ok(())
- }
-
- fn move_left(&self, count: u16) -> Result<()> {
- let (xpos, ypos) = self.pos()?;
- self.goto(xpos - count, ypos)?;
- Ok(())
- }
-
- fn save_position(&self) -> Result<()> {
- Cursor::save_cursor_pos()?;
- Ok(())
- }
-
- fn restore_position(&self) -> Result<()> {
- Cursor::restore_cursor_pos()?;
- Ok(())
- }
-
- fn hide(&self) -> Result<()> {
- Cursor::from(Handle::current_out_handle()?).set_visibility(false)?;
- Ok(())
- }
-
- fn show(&self) -> Result<()> {
- Cursor::from(Handle::current_out_handle()?).set_visibility(true)?;
- Ok(())
- }
-
- fn blink(&self, _blink: bool) -> Result<()> {
- Ok(())
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{ITerminalCursor, WinApiCursor};
-
- #[test]
- fn test_winapi_goto() {
- let cursor = WinApiCursor::new();
-
- let (saved_x, saved_y) = cursor.pos().unwrap();
-
- cursor.goto(saved_x + 1, saved_y + 1).unwrap();
- assert_eq!(cursor.pos().unwrap(), (saved_x + 1, saved_y + 1));
-
- cursor.goto(saved_x, saved_y).unwrap();
- assert_eq!(cursor.pos().unwrap(), (saved_x, saved_y));
- }
-
- #[test]
- fn test_winapi_save_and_restore() {
- let cursor = WinApiCursor::new();
-
- let (saved_x, saved_y) = cursor.pos().unwrap();
-
- cursor.save_position().unwrap();
- cursor.goto(saved_x + 1, saved_y + 1).unwrap();
- cursor.restore_position().unwrap();
-
- let (x, y) = cursor.pos().unwrap();
-
- assert_eq!(x, saved_x);
- assert_eq!(y, saved_y);
- }
-}
diff --git a/crossterm_cursor/src/lib.rs b/crossterm_cursor/src/lib.rs
deleted file mode 100644
index a26743466..000000000
--- a/crossterm_cursor/src/lib.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![deny(unused_imports)]
-
-pub use crossterm_utils::{
- execute, queue, Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result,
-};
-
-pub use self::cursor::{
- cursor, BlinkOff, BlinkOn, Down, Goto, Hide, Left, ResetPos, Right, SavePos, Show,
- TerminalCursor, Up,
-};
-
-mod cursor;
-pub mod sys;
diff --git a/crossterm_cursor/src/sys.rs b/crossterm_cursor/src/sys.rs
deleted file mode 100644
index 91bd3be1a..000000000
--- a/crossterm_cursor/src/sys.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#[cfg(unix)]
-pub use self::unix::get_cursor_position;
-#[cfg(unix)]
-pub use self::unix::show_cursor;
-#[cfg(windows)]
-pub use self::winapi::get_cursor_position;
-#[cfg(windows)]
-pub use self::winapi::show_cursor;
-
-#[cfg(unix)]
-pub mod unix;
-
-#[cfg(windows)]
-pub mod winapi;
diff --git a/crossterm_cursor/src/sys/unix.rs b/crossterm_cursor/src/sys/unix.rs
deleted file mode 100644
index 672f7484c..000000000
--- a/crossterm_cursor/src/sys/unix.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use std::io::{self, BufRead, Write};
-
-use crossterm_utils::{
- csi,
- sys::unix::{self, RAW_MODE_ENABLED},
- write_cout, Result,
-};
-
-#[cfg(unix)]
-pub fn get_cursor_position() -> Result<(u16, u16)> {
- if unsafe { RAW_MODE_ENABLED } {
- pos_raw()
- } else {
- pos()
- }
-}
-
-#[cfg(unix)]
-pub fn show_cursor(show_cursor: bool) -> Result<()> {
- if show_cursor {
- write_cout!(csi!("?25h"))?;
- } else {
- write_cout!(csi!("?25l"))?;
- }
- Ok(())
-}
-
-pub fn pos() -> Result<(u16, u16)> {
- unix::enable_raw_mode()?;
- let pos = pos_raw();
- unix::disable_raw_mode()?;
- pos
-}
-
-pub fn pos_raw() -> Result<(u16, u16)> {
- // Where is the cursor?
- // Use `ESC [ 6 n`.
- let mut stdout = io::stdout();
- let stdin = io::stdin();
-
- // Write command
- stdout.write_all(b"\x1B[6n")?;
- stdout.flush()?;
-
- stdin.lock().read_until(b'[', &mut vec![])?;
-
- let mut rows = vec![];
- stdin.lock().read_until(b';', &mut rows)?;
-
- let mut cols = vec![];
- stdin.lock().read_until(b'R', &mut cols)?;
-
- // remove delimiter
- rows.pop();
- cols.pop();
-
- let rows = String::from_utf8(rows)?.parse::()?;
- let cols = String::from_utf8(cols)?.parse::()?;
-
- Ok((cols - 1, rows - 1))
-}
diff --git a/crossterm_cursor/src/sys/winapi.rs b/crossterm_cursor/src/sys/winapi.rs
deleted file mode 100644
index 85ca541df..000000000
--- a/crossterm_cursor/src/sys/winapi.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-//! This module handles some logic for cursor interaction in the windows console.
-
-use std::io;
-
-use winapi::{
- shared::minwindef::{FALSE, TRUE},
- um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD},
- um::winnt::HANDLE,
-};
-
-use crossterm_utils::Result;
-pub use crossterm_winapi::{is_true, Coord, Handle, HandleType, ScreenBuffer};
-
-#[cfg(windows)]
-pub fn get_cursor_position() -> Result<(u16, u16)> {
- let cursor = Cursor::new()?;
- Ok(cursor.position()?.into())
-}
-
-#[cfg(windows)]
-pub fn show_cursor(show_cursor: bool) -> Result<()> {
- Cursor::from(Handle::current_out_handle()?).set_visibility(show_cursor)
-}
-
-/// This stores the cursor pos, at program level. So it can be recalled later.
-static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
-
-pub struct Cursor {
- screen_buffer: ScreenBuffer,
-}
-
-impl Cursor {
- pub fn new() -> Result {
- Ok(Cursor {
- screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?),
- })
- }
-
- /// get the current cursor position.
- pub fn position(&self) -> Result {
- Ok(self.screen_buffer.info()?.cursor_pos())
- }
-
- /// Set the cursor position to the given x and y. Note that this is 0 based.
- pub fn goto(&self, x: i16, y: i16) -> Result<()> {
- if x < 0 || x >= ::max_value() {
- Err(io::Error::new(
- io::ErrorKind::Other,
- format!(
- "Argument Out of Range Exception when setting cursor position to X: {}",
- x
- ),
- ))?;
- }
-
- if y < 0 || y >= ::max_value() {
- 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 !is_true(SetConsoleCursorPosition(
- **self.screen_buffer.handle(),
- position,
- )) {
- Err(io::Error::last_os_error())?;
- }
- }
- Ok(())
- }
-
- /// change the cursor visibility.
- pub fn set_visibility(&self, visable: bool) -> Result<()> {
- let cursor_info = CONSOLE_CURSOR_INFO {
- dwSize: 100,
- bVisible: if visable { TRUE } else { FALSE },
- };
-
- unsafe {
- if !is_true(SetConsoleCursorInfo(
- **self.screen_buffer.handle(),
- &cursor_info,
- )) {
- Err(io::Error::last_os_error())?;
- }
- }
- Ok(())
- }
-
- /// Reset to saved cursor position
- pub fn restore_cursor_pos() -> Result<()> {
- let cursor = Cursor::new()?;
-
- unsafe {
- cursor.goto(SAVED_CURSOR_POS.0 as i16, SAVED_CURSOR_POS.1 as i16)?;
- }
-
- Ok(())
- }
-
- /// Save current cursor position to recall later.
- pub fn save_cursor_pos() -> Result<()> {
- let cursor = Cursor::new()?;
- let position = cursor.position()?;
-
- unsafe {
- SAVED_CURSOR_POS = (position.x as u16, position.y as u16);
- }
-
- Ok(())
- }
-}
-
-impl From for Cursor {
- fn from(handle: Handle) -> Self {
- Cursor {
- screen_buffer: ScreenBuffer::from(handle),
- }
- }
-}
-
-impl From for Cursor {
- fn from(handle: HANDLE) -> Self {
- Cursor {
- screen_buffer: ScreenBuffer::from(handle),
- }
- }
-}
diff --git a/crossterm_input/.gitignore b/crossterm_input/.gitignore
deleted file mode 100644
index 53eaa2196..000000000
--- a/crossterm_input/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/target
-**/*.rs.bk
diff --git a/crossterm_input/CHANGELOG.md b/crossterm_input/CHANGELOG.md
deleted file mode 100644
index 0dcb44ee0..000000000
--- a/crossterm_input/CHANGELOG.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# Changes crossterm_input 0.4.0
-- `TerminalInput::read_line` returns `crossterm::Result` instead of `io::Result`
-- `TerminalInput::read_char` returns `crossterm::Result` instead of `io::Result`
-- `Command::get_anis_code()` to `ansi_code()`
-- Added KeyEvent::Enter and KeyEvent::Tab: [added-key-event-enter], [added-key-event-tab]
-- `ExecutableCommand::queue` returns `crossterm::Result`
-- `QueueableCommand::queue` returns `crossterm::Result`
-- Added derives: Serialize/Deserialize for key events [serde]
-- Command API takes mutable self instead of self
-
-[added-key-event-tab]: https://github.com/crossterm-rs/crossterm/pull/239
-[added-key-event-enter]: https://github.com/crossterm-rs/crossterm/pull/236
-[serde]: https://github.com/crossterm-rs/crossterm/pull/190
-
-# Changes crossterm_input 0.3.3
-- Removed println from `SyncReader`
-
-# Changes crossterm_input 0.3.2
-- Fixed some special key combination detections for UNIX systems
-- Windows mouse input event position was 0-based and should be 1-based
-
-# Changes crossterm_input 0.3.1
-- Updated crossterm_utils
-
-# Changes crossterm_input 0.3
-- Removed `TerminalInput::from_output()`
-
-# Changes crossterm_input 0.2.1
-- Fixed SyncReade bug.
-
-# Changes crossterm_input 0.2.1
-- Introduced SyncReader
-
-# Changes crossterm_input 0.2
-- Introduced KeyEvents
-- Introduced MouseEvents
-
-# Changes crossterm_input 0.1
-- Moved out of `crossterm` 5.4 crate.
\ No newline at end of file
diff --git a/crossterm_input/Cargo.toml b/crossterm_input/Cargo.toml
deleted file mode 100644
index 2b0c68e3a..000000000
--- a/crossterm_input/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-name = "crossterm_input"
-version = "0.4.0"
-authors = ["T. Post"]
-description = "A cross-platform library for reading userinput."
-repository = "https://github.com/crossterm-rs/crossterm"
-documentation = "https://docs.rs/crossterm_input/"
-license = "MIT"
-keywords = ["input", "keys", "crossterm", "events", "terminal"]
-exclude = ["target", "Cargo.lock"]
-readme = "README.md"
-edition = "2018"
-
-[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3.8", features = ["winnt", "winuser"] }
-crossterm_winapi = { path="../crossterm_winapi", version = "0.2.0"}
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2.51"
-
-[dependencies]
-crossterm_utils = { path="../crossterm_utils", version = "0.3.0"}
-crossterm_screen = {path="../crossterm_screen", version = "0.3.0"}
-serde = { version = "1.0", features = ["derive"], optional = true }
diff --git a/crossterm_input/LICENSE b/crossterm_input/LICENSE
deleted file mode 100644
index 8b02a7fce..000000000
--- a/crossterm_input/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 Timon
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/crossterm_input/README.md b/crossterm_input/README.md
deleted file mode 100644
index 3966641e1..000000000
--- a/crossterm_input/README.md
+++ /dev/null
@@ -1,151 +0,0 @@
-# Crossterm Input | cross-platform input reading .
- ![Lines of Code][s7] [![Latest Version][s1]][l1] [![MIT][s2]][l2] [![docs][s3]][l3] [![Join us on Discord][s5]][l5]
-
-[s1]: https://img.shields.io/crates/v/crossterm_input.svg
-[l1]: https://crates.io/crates/crossterm_input
-
-[s2]: https://img.shields.io/badge/license-MIT-blue.svg
-[l2]: ./LICENSE
-
-[s3]: https://docs.rs/crossterm_input/badge.svg
-[l3]: https://docs.rs/crossterm_input/
-
-[s5]: https://img.shields.io/discord/560857607196377088.svg?logo=discord
-[l5]: https://discord.gg/K4nyTDB
-
-[s7]: https://travis-ci.org/crossterm-rs/crossterm.svg?branch=master
-
-This crate allows you to read the user input cross-platform.
-It supports all UNIX and windows terminals down to windows 7 (not all terminals are tested see [Tested Terminals](#tested-terminals) for more info)
-
-This crate is a sub-crate of [crossterm](https://crates.io/crates/crossterm) to read the user input and can be used individually.
-
-Other sub-crates are:
-- [Crossterm Style](https://crates.io/crates/crossterm_style)
-- [Crossterm Terminal](https://crates.io/crates/crossterm_terminal)
-- [Crossterm Screen](https://crates.io/crates/crossterm_screen)
-- [Crossterm Cursor](https://crates.io/crates/crossterm_cursor)
-
-When you want to use other modules as well you might want to use crossterm with [feature flags](https://crossterm-rs.github.io/crossterm/docs/feature_flags.html).
-
-## Table of contents:
-- [Getting started](#getting-started)
-- [Useful links](#useful-links)
-- [Features](#features)
-- [Examples](#examples)
-- [Tested Terminals](#tested-terminals)
-- [Notice](#notice)
-- [Contributing](#contributing)
-- [Authors](#authors)
-- [License](#license)
-
-## Getting Started
-
-All examples of how `crossterm_input` works can be found in the [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) directory.
-
-Add the `crossterm_input` package to your `Cargo.toml` file.
-
-```
-[dependencies]
-crossterm_input = "0.3"
-```
-Import the `crossterm_input` modules you want to use.
-
-```rust
-pub use crossterm_input::{input, AsyncReader, InputEvent, KeyEvent, MouseButton, MouseEvent, SyncReader, TerminalInput};
-```
-
-### Useful Links
-
-- [Documentation](https://docs.rs/crossterm_input/)
-- [Crates.io](https://crates.io/crates/crossterm_input)
-- [Book](https://crossterm-rs.github.io/crossterm/docs/input.html)
-- [Examples](./examples)
-
-## Features
-These are the features of this crate:
-
-- Cross-platform
-- Multithreaded (send, sync)
-- Detailed Documentation
-- Few Dependencies
-- Input
- - Read character
- - Read line
- - Read key input events (async / sync)
- - Read mouse input events (press, release, position, button)
- - RawScreen (from `crossterm_screen`)
-
-## Examples
-The [examples](https://github.com/crossterm-rs/crossterm/tree/master/examples) folder has more complete and verbose examples.
-
-_Simple Readings_
-```rust
-let mut input = input();
-
- match input.read_char() {
- Ok(s) => println!("char typed: {}", s),
- Err(e) => println!("char error : {}", e),
- }
-
- match input.read_line() {
- Ok(s) => println!("string typed: {}", s),
- Err(e) => println!("error: {}", e),
- }
-```
-
-_Read input events synchronously or asynchronously._
-```rust
-// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
-let screen = RawScreen::into_raw_mode();
-
-let mut input = input();
-
-// either read the input synchronously
-let stdin = input.read_sync();
-
-// or asynchronously
-let stdin = input.read_async();
-
-if let Some(key_event) = stdin.next() {
- match key_event {
- InputEvent::Keyboard(event: KeyEvent) => match event { /* check key event */ }
- InputEvent::Mouse(event: MouseEvent) => match event { /* check mouse event */ }
- }
- }
-```
-
-_Enable mouse input events._
-```rust
-let input = input();
-
-// enable mouse events to be captured.
-input.enable_mouse_mode().unwrap();
-
-// disable mouse events to be captured.
-input.disable_mouse_mode().unwrap();
-```
-
-## Tested terminals
-
-- Windows Powershell
- - Windows 10 (pro)
-- Windows CMD
- - Windows 10 (pro)
- - Windows 8.1 (N)
-- Ubuntu Desktop Terminal
- - Ubuntu 17.10
-- (Arch, Manjaro) KDE Konsole
-- Linux Mint
-
-This crate supports all Unix terminals and windows terminals down to Windows 7 but not all of them have been tested.
-If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
-
-## Authors
-
-* **Timon Post** - *Project Owner & creator*
-* **Dave Ho** - *Contributor*
-
-## License
-
-This project is licensed under the MIT License - see the [LICENSE.md](./LICENSE) file for details
diff --git a/crossterm_input/src/input.rs b/crossterm_input/src/input.rs
deleted file mode 100644
index 4f7cf3884..000000000
--- a/crossterm_input/src/input.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-//! A module that contains all the actions related to reading input from the terminal.
-//! Like reading a line, reading a character and reading asynchronously.
-
-#[cfg(feature = "serde")]
-use serde::{Deserialize, Serialize};
-
-use crossterm_utils::Result;
-
-pub use self::input::{input, TerminalInput};
-#[cfg(unix)]
-pub use self::unix_input::{AsyncReader, SyncReader};
-#[cfg(windows)]
-pub use self::windows_input::{AsyncReader, SyncReader};
-
-mod input;
-
-#[cfg(unix)]
-mod unix_input;
-#[cfg(windows)]
-mod windows_input;
-
-/// This trait defines the actions that can be performed with the terminal input.
-/// This trait can be implemented so that a concrete implementation of the ITerminalInput can fulfill
-/// the wishes to work on a specific platform.
-///
-/// ## For example:
-///
-/// This trait is implemented for Windows and UNIX systems.
-/// Unix is using the 'TTY' and windows is using 'libc' C functions to read the input.
-trait ITerminalInput {
- /// Read one character from the user input
- fn read_char(&self) -> Result;
- /// Read the input asynchronously from the user.
- fn read_async(&self) -> AsyncReader;
- /// Read the input asynchronously until a certain character is hit.
- fn read_until_async(&self, delimiter: u8) -> AsyncReader;
- /// Read the input synchronously from the user.
- fn read_sync(&self) -> SyncReader;
- fn enable_mouse_mode(&self) -> Result<()>;
- fn disable_mouse_mode(&self) -> Result<()>;
-}
-
-/// Enum to specify which input event has occurred.
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, PartialOrd, PartialEq, Hash, Clone)]
-pub enum InputEvent {
- /// A single key or a combination is pressed.
- Keyboard(KeyEvent),
- /// A mouse event occurred.
- Mouse(MouseEvent),
- /// A unsupported event has occurred.
- Unsupported(Vec),
- /// An unknown event has occurred.
- Unknown,
-}
-
-/// Enum to specify which mouse event has occurred.
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Copy)]
-pub enum MouseEvent {
- /// A mouse press has occurred, this contains the pressed button and the position of the press.
- Press(MouseButton, u16, u16),
- /// A mouse button was released.
- Release(u16, u16),
- /// A mouse button was hold.
- Hold(u16, u16),
- /// An unknown mouse event has occurred.
- Unknown,
-}
-
-/// Enum to define mouse buttons.
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Copy)]
-pub enum MouseButton {
- /// Left mouse button
- Left,
- /// Right mouse button
- Right,
- /// Middle mouse button
- Middle,
- /// Scroll up
- WheelUp,
- /// Scroll down
- WheelDown,
-}
-
-/// Enum with different key or key combinations.
-#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub enum KeyEvent {
- Backspace,
- Enter,
- Left,
- Right,
- Up,
- Down,
- Home,
- End,
- PageUp,
- PageDown,
- Tab,
- BackTab,
- Delete,
- Insert,
- F(u8),
- Char(char),
- Alt(char),
- Ctrl(char),
- Null,
- Esc,
- CtrlUp,
- CtrlDown,
- CtrlRight,
- CtrlLeft,
- ShiftUp,
- ShiftDown,
- ShiftRight,
- ShiftLeft,
-}
diff --git a/crossterm_input/src/input/input.rs b/crossterm_input/src/input/input.rs
deleted file mode 100644
index aa027c459..000000000
--- a/crossterm_input/src/input/input.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-//! A module that contains all the actions related to reading input from the terminal.
-//! Like reading a line, reading a character and reading asynchronously.
-
-use std::io;
-
-use crossterm_utils::Result;
-
-#[cfg(unix)]
-use super::unix_input::{AsyncReader, SyncReader, UnixInput};
-#[cfg(windows)]
-use super::windows_input::{AsyncReader, SyncReader, WindowsInput};
-use super::ITerminalInput;
-
-/// Allows you to read user input.
-///
-/// # Features:
-///
-/// - Read character
-/// - Read line
-/// - Read async
-/// - Read async until
-/// - Read sync
-/// - Wait for key event (terminal pause)
-///
-/// Check `/examples/` in the library for more specific examples.
-pub struct TerminalInput {
- #[cfg(windows)]
- input: WindowsInput,
- #[cfg(unix)]
- input: UnixInput,
-}
-
-impl TerminalInput {
- /// Create a new instance of `TerminalInput` whereon input related actions could be performed.
- pub fn new() -> TerminalInput {
- #[cfg(windows)]
- let input = WindowsInput::new();
-
- #[cfg(unix)]
- let input = UnixInput::new();
-
- TerminalInput { input }
- }
-
- /// Read one line from the user input.
- ///
- /// # Remark
- /// This function is not work when raw screen is turned on.
- /// When you do want to read a line in raw mode please, checkout `read_async`, `read_async_until` or `read_sync`.
- /// Not sure what 'raw mode' is, checkout the 'crossterm_screen' crate.
- ///
- /// # Example
- /// ```ignore
- /// let in = input();
- /// match in.read_line() {
- /// Ok(s) => println!("string typed: {}", s),
- /// Err(e) => println!("error: {}", e),
- /// }
- /// ```
- pub fn read_line(&self) -> Result {
- let mut rv = String::new();
- io::stdin().read_line(&mut rv)?;
- let len = rv.trim_end_matches(&['\r', '\n'][..]).len();
- rv.truncate(len);
- Ok(rv)
- }
-
- /// Read one character from the user input
- ///
- /// ```ignore
- /// let in = input();
- /// match in.read_char() {
- /// Ok(c) => println!("character pressed: {}", c),
- /// Err(e) => println!("error: {}", e),
- /// }
- /// ```
- pub fn read_char(&self) -> Result {
- self.input.read_char()
- }
-
- /// Read the input asynchronously, which means that input events are gathered on the background and will be queued for you to read.
- ///
- /// If you want a blocking, or less resource consuming read to happen use `read_sync()`, this will leave a way all the thread and queueing and will be a blocking read.
- ///
- /// This is the same as `read_async()` but stops reading when a certain character is hit.
- ///
- /// # Remarks
- /// - Readings won't be blocking calls.
- /// A thread will be fired to read input, on unix systems from TTY and on windows WinApi
- /// `ReadConsoleW` will be used.
- /// - Input events read from the user will be queued on a MPSC-channel.
- /// - The reading thread will be cleaned up when it drops.
- /// - Requires 'raw screen to be enabled'.
- /// Not sure what this is? Please checkout the 'crossterm_screen' crate.
- ///
- /// # Examples
- /// Please checkout the example folder in the repository.
- pub fn read_async(&self) -> AsyncReader {
- self.input.read_async()
- }
-
- /// Read the input asynchronously until a certain delimiter (character as byte) is hit, which means that input events are gathered on the background and will be queued for you to read.
- ///
- /// If you want a blocking or less resource consuming read to happen, use `read_sync()`. This will leave alone the background thread and queues and will be a blocking read.
- ///
- /// This is the same as `read_async()` but stops reading when a certain character is hit.
- ///
- /// # Remarks
- /// - Readings won't be blocking calls.
- /// A thread will be fired to read input, on unix systems from TTY and on windows WinApi
- /// `ReadConsoleW` will be used.
- /// - Input events read from the user will be queued on a MPSC-channel.
- /// - The reading thread will be cleaned up when it drops.
- /// - Requires 'raw screen to be enabled'.
- /// Not sure what this is? Please checkout the 'crossterm_screen' crate.
- ///
- /// # Examples
- /// Please checkout the example folder in the repository.
- pub fn read_until_async(&self, delimiter: u8) -> AsyncReader {
- self.input.read_until_async(delimiter)
- }
-
- /// Read the input synchronously from the user, which means that reading calls will block.
- /// It also uses less resources than the `AsyncReader` because the background thread and queues are left alone.
- ///
- /// Consider using `read_async` if you don't want the reading call to block your program.
- ///
- /// # Remark
- /// - Readings will be blocking calls.
- ///
- /// # Examples
- /// Please checkout the example folder in the repository.
- pub fn read_sync(&self) -> SyncReader {
- self.input.read_sync()
- }
-
- /// Enable mouse events to be captured.
- ///
- /// When enabling mouse input, you will be able to capture mouse movements, pressed buttons, and locations.
- ///
- /// # Remark
- /// - Mouse events will be send over the reader created with `read_async`, `read_async_until`, `read_sync`.
- pub fn enable_mouse_mode(&self) -> Result<()> {
- self.input.enable_mouse_mode()
- }
-
- /// Disable mouse events to be captured.
- ///
- /// When disabling mouse input, you won't be able to capture mouse movements, pressed buttons, and locations anymore.
- pub fn disable_mouse_mode(&self) -> Result<()> {
- self.input.disable_mouse_mode()
- }
-}
-
-/// Get a `TerminalInput` instance whereon input related actions can be performed.
-pub fn input() -> TerminalInput {
- TerminalInput::new()
-}
diff --git a/crossterm_input/src/input/unix_input.rs b/crossterm_input/src/input/unix_input.rs
deleted file mode 100644
index 7b54e89dc..000000000
--- a/crossterm_input/src/input/unix_input.rs
+++ /dev/null
@@ -1,506 +0,0 @@
-//! This is a UNIX specific implementation for input related action.
-
-use std::char;
-use std::sync::{
- atomic::{AtomicBool, Ordering},
- mpsc::{self, Receiver, Sender},
- Arc,
-};
-use std::{
- io::{self, Read},
- str, thread,
-};
-
-use crossterm_utils::{csi, write_cout, ErrorKind, Result};
-
-use crate::sys::unix::{get_tty, read_char_raw};
-
-use super::{ITerminalInput, InputEvent, KeyEvent, MouseButton, MouseEvent};
-
-pub struct UnixInput;
-
-impl UnixInput {
- pub fn new() -> UnixInput {
- UnixInput {}
- }
-}
-
-impl ITerminalInput for UnixInput {
- fn read_char(&self) -> Result {
- read_char_raw()
- }
-
- fn read_async(&self) -> AsyncReader {
- AsyncReader::new(Box::new(move |event_tx, cancellation_token| {
- for i in get_tty().unwrap().bytes() {
- if event_tx.send(i.unwrap()).is_err() {
- return;
- }
-
- if cancellation_token.load(Ordering::SeqCst) {
- return;
- }
- }
- }))
- }
-
- fn read_until_async(&self, delimiter: u8) -> AsyncReader {
- AsyncReader::new(Box::new(move |event_tx, cancellation_token| {
- for byte in get_tty().unwrap().bytes() {
- let byte = byte.unwrap();
- let end_of_stream = byte == delimiter;
- let send_error = event_tx.send(byte).is_err();
-
- if end_of_stream || send_error || cancellation_token.load(Ordering::SeqCst) {
- return;
- }
- }
- }))
- }
-
- fn read_sync(&self) -> SyncReader {
- SyncReader {
- source: Box::from(get_tty().unwrap()),
- leftover: None,
- }
- }
-
- fn enable_mouse_mode(&self) -> Result<()> {
- write_cout!(&format!(
- "{}h{}h{}h{}h",
- csi!("?1000"),
- csi!("?1002"),
- csi!("?1015"),
- csi!("?1006")
- ))?;
- Ok(())
- }
-
- fn disable_mouse_mode(&self) -> Result<()> {
- write_cout!(&format!(
- "{}l{}l{}l{}l",
- csi!("?1006"),
- csi!("?1015"),
- csi!("?1002"),
- csi!("?1000")
- ))?;
- Ok(())
- }
-}
-
-/// This type allows you to read the input asynchronously which means that input events are gathered on the background and will be queued for you to read.
-///
-/// **[SyncReader](./LINK)**
-/// If you want a blocking, or less resource consuming read to happen use `SyncReader`, this will leave a way all the thread and queueing and will be a blocking read.
-///
-/// This type is an iterator, and could be used to iterate over input events.
-///
-/// # Remarks
-/// - Threads spawned will be disposed of as soon the `AsyncReader` goes out of scope.
-/// - MPSC-channels are used to queue input events, this type implements an iterator of the rx side of the queue.
-pub struct AsyncReader {
- event_rx: Receiver,
- shutdown: Arc,
-}
-
-impl AsyncReader {
- /// Construct a new instance of the `AsyncReader`.
- /// The reading will immediately start when calling this function.
- pub fn new(function: Box, &Arc) + Send>) -> AsyncReader {
- let shutdown_handle = Arc::new(AtomicBool::new(false));
-
- let (event_tx, event_rx) = mpsc::channel();
- let thread_shutdown = shutdown_handle.clone();
-
- thread::spawn(move || loop {
- function(&event_tx, &thread_shutdown);
- });
-
- AsyncReader {
- event_rx,
- shutdown: shutdown_handle,
- }
- }
-
- /// Stop the input event reading.
- ///
- /// You don't necessarily have to call this function because it will automatically be called when this reader goes out of scope.
- ///
- /// # Remarks
- /// - Background thread will be closed.
- /// - This will consume the handle you won't be able to restart the reading with this handle, create a new `AsyncReader` instead.
- pub fn stop(&mut self) {
- self.shutdown.store(true, Ordering::SeqCst);
- }
-}
-
-impl Iterator for AsyncReader {
- type Item = InputEvent;
-
- /// Check if there are input events to read.
- ///
- /// It will return `None` when nothing is there to read, `Some(InputEvent)` if there are events to read.
- ///
- /// # Remark
- /// - This is **not** a blocking call.
- fn next(&mut self) -> Option {
- let mut iterator = self.event_rx.try_iter();
-
- match iterator.next() {
- Some(char_value) => {
- if let Ok(char_value) = parse_event(char_value, &mut iterator) {
- Some(char_value)
- } else {
- None
- }
- }
- None => None,
- }
- }
-}
-
-impl Drop for AsyncReader {
- fn drop(&mut self) {
- self.stop();
- }
-}
-
-/// This type allows you to read input synchronously, which means that reading calls will block.
-///
-/// This type is an iterator, and can be used to iterate over input events.
-///
-/// If you don't want to block your calls use [AsyncReader](./LINK), which will read input on the background and queue it for you to read.
-pub struct SyncReader {
- source: Box,
- leftover: Option,
-}
-
-impl Iterator for SyncReader {
- type Item = InputEvent;
- /// Read input from the user.
- ///
- /// If there are no keys pressed, this will be a blocking call until there is one.
- /// This will return `None` in case of a failure and `Some(InputEvent)` in case of an occurred input event.
- fn next(&mut self) -> Option {
- // TODO: Currently errors are consumed and converted to a `None`. Maybe we shouldn't be doing this?
- let source = &mut self.source;
-
- if let Some(c) = self.leftover {
- // we have a leftover byte, use it
- self.leftover = None;
- if let Ok(e) = parse_event(c, &mut source.bytes().flatten()) {
- return Some(e);
- } else {
- return None;
- }
- }
-
- // Here we read two bytes at a time. We need to distinguish between single ESC key presses,
- // and escape sequences (which start with ESC or a x1B byte). The idea is that if this is
- // an escape sequence, we will read multiple bytes (the first byte being ESC) but if this
- // is a single ESC keypress, we will only read a single byte.
- let mut buf = [0u8; 2];
-
- let res = match source.read(&mut buf) {
- Ok(0) => return None,
- Ok(1) => match buf[0] {
- b'\x1B' => return Some(InputEvent::Keyboard(KeyEvent::Esc)),
- c => {
- if let Ok(e) = parse_event(c, &mut source.bytes().flatten()) {
- return Some(e);
- } else {
- return None;
- }
- }
- },
- Ok(2) => {
- let option_iter = &mut Some(buf[1]).into_iter();
- let iter = option_iter.map(|c| Ok(c)).chain(source.bytes());
- if let Ok(e) = parse_event(buf[0], &mut iter.flatten()) {
- self.leftover = option_iter.next();
- Some(e)
- } else {
- None
- }
- }
- Ok(_) => unreachable!(),
- Err(_) => return None, /* maybe we should not throw away the error?*/
- };
-
- res
- }
-}
-
-/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
-pub(crate) fn parse_event(item: u8, iter: &mut I) -> Result
-where
- I: Iterator,
-{
- let error = ErrorKind::IoError(io::Error::new(
- io::ErrorKind::Other,
- "Could not parse an event",
- ));
- let input_event = match item {
- b'\x1B' => {
- let a = iter.next();
- // This is an escape character, leading a control sequence.
- match a {
- Some(b'O') => {
- match iter.next() {
- // F1-F4
- Some(val @ b'P'..=b'S') => {
- InputEvent::Keyboard(KeyEvent::F(1 + val - b'P'))
- }
- _ => return Err(error),
- }
- }
- Some(b'[') => {
- // This is a CSI sequence.
- parse_csi(iter)
- }
- Some(b'\x1B') => InputEvent::Keyboard(KeyEvent::Esc),
- Some(c) => {
- let ch = parse_utf8_char(c, iter);
- InputEvent::Keyboard(KeyEvent::Alt(ch?))
- }
- None => InputEvent::Keyboard(KeyEvent::Esc),
- }
- }
- b'\r' | b'\n' => InputEvent::Keyboard(KeyEvent::Enter),
- b'\t' => InputEvent::Keyboard(KeyEvent::Tab),
- b'\x7F' => InputEvent::Keyboard(KeyEvent::Backspace),
- c @ b'\x01'..=b'\x1A' => {
- InputEvent::Keyboard(KeyEvent::Ctrl((c as u8 - 0x1 + b'a') as char))
- }
- c @ b'\x1C'..=b'\x1F' => {
- InputEvent::Keyboard(KeyEvent::Ctrl((c as u8 - 0x1C + b'4') as char))
- }
- b'\0' => InputEvent::Keyboard(KeyEvent::Null),
- c => {
- let ch = parse_utf8_char(c, iter);
- InputEvent::Keyboard(KeyEvent::Char(ch?))
- }
- };
-
- Ok(input_event)
-}
-
-/// Parses a CSI sequence, just after reading ^[
-/// Returns Event::Unknown if an unrecognized sequence is found.
-/// Most of this parsing code is been taken over from 'termion`.
-fn parse_csi(iter: &mut I) -> InputEvent
-where
- I: Iterator,
-{
- match iter.next() {
- Some(b'[') => match iter.next() {
- // NOTE (@imdaveho): cannot find when this occurs;
- // having another '[' after ESC[ not a likely scenario
- Some(val @ b'A'..=b'E') => InputEvent::Keyboard(KeyEvent::F(1 + val - b'A')),
- _ => InputEvent::Unknown,
- },
- Some(b'D') => InputEvent::Keyboard(KeyEvent::Left),
- Some(b'C') => InputEvent::Keyboard(KeyEvent::Right),
- Some(b'A') => InputEvent::Keyboard(KeyEvent::Up),
- Some(b'B') => InputEvent::Keyboard(KeyEvent::Down),
- Some(b'H') => InputEvent::Keyboard(KeyEvent::Home),
- Some(b'F') => InputEvent::Keyboard(KeyEvent::End),
- Some(b'Z') => InputEvent::Keyboard(KeyEvent::BackTab),
- Some(b'M') => {
- // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
- // NOTE (@imdaveho): cannot find documentation on this
- let mut next = || iter.next().unwrap();
-
- let cb = next() as i8 - 32;
- // (1, 1) are the coords for upper left.
- let cx = next().saturating_sub(32) as u16;
- let cy = next().saturating_sub(32) as u16;
-
- InputEvent::Mouse(match cb & 0b11 {
- 0 => {
- if cb & 0x40 != 0 {
- MouseEvent::Press(MouseButton::WheelUp, cx, cy)
- } else {
- MouseEvent::Press(MouseButton::Left, cx, cy)
- }
- }
- 1 => {
- if cb & 0x40 != 0 {
- MouseEvent::Press(MouseButton::WheelDown, cx, cy)
- } else {
- MouseEvent::Press(MouseButton::Middle, cx, cy)
- }
- }
- 2 => MouseEvent::Press(MouseButton::Right, cx, cy),
- 3 => MouseEvent::Release(cx, cy),
- _ => MouseEvent::Unknown,
- })
- }
- Some(b'<') => {
- // xterm mouse handling:
- // ESC [ < Cb ; Cx ; Cy (;) (M or m)
- let mut buf = Vec::new();
- let mut c = iter.next().unwrap();
- while match c {
- b'm' | b'M' => false,
- _ => true,
- } {
- buf.push(c);
- c = iter.next().unwrap();
- }
- let str_buf = String::from_utf8(buf).unwrap();
- let nums = &mut str_buf.split(';');
-
- let cb = nums.next().unwrap().parse::().unwrap();
- let cx = nums.next().unwrap().parse::().unwrap();
- let cy = nums.next().unwrap().parse::().unwrap();
-
- match cb {
- 0..=2 | 64..=65 => {
- let button = match cb {
- 0 => MouseButton::Left,
- 1 => MouseButton::Middle,
- 2 => MouseButton::Right,
- 64 => MouseButton::WheelUp,
- 65 => MouseButton::WheelDown,
- _ => unreachable!(),
- };
- match c {
- b'M' => InputEvent::Mouse(MouseEvent::Press(button, cx, cy)),
- b'm' => InputEvent::Mouse(MouseEvent::Release(cx, cy)),
- _ => InputEvent::Unknown,
- }
- }
- 32 => InputEvent::Mouse(MouseEvent::Hold(cx, cy)),
- 3 => InputEvent::Mouse(MouseEvent::Release(cx, cy)),
- _ => InputEvent::Unknown,
- }
- }
- Some(c @ b'0'..=b'9') => {
- // Numbered escape code.
- let mut buf = Vec::new();
- buf.push(c);
- let mut character = iter.next().unwrap();
-
- // The final byte of a CSI sequence can be in the range 64-126, so
- // let's keep reading anything else.
- while character < 64 || character > 126 {
- buf.push(character);
- character = iter.next().unwrap();
- }
-
- match character {
- // rxvt mouse encoding:
- // ESC [ Cb ; Cx ; Cy ; M
- b'M' => {
- let str_buf = String::from_utf8(buf).unwrap();
-
- let nums: Vec = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
-
- let cb = nums[0];
- let cx = nums[1];
- let cy = nums[2];
-
- let event = match cb {
- 32 => MouseEvent::Press(MouseButton::Left, cx, cy),
- 33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
- 34 => MouseEvent::Press(MouseButton::Right, cx, cy),
- 35 => MouseEvent::Release(cx, cy),
- 64 => MouseEvent::Hold(cx, cy),
- 96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
- _ => MouseEvent::Unknown,
- };
-
- InputEvent::Mouse(event)
- }
- // Special key code.
- b'~' => {
- let str_buf = String::from_utf8(buf).unwrap();
-
- // This CSI sequence can be a list of semicolon-separated numbers.
- let nums: Vec = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
-
- if nums.is_empty() {
- return InputEvent::Unknown;
- }
-
- // TODO: handle multiple values for key modifiers (ex: values [3, 2] means Shift+Delete)
- if nums.len() > 1 {
- return InputEvent::Unknown;
- }
-
- match nums[0] {
- 1 | 7 => InputEvent::Keyboard(KeyEvent::Home),
- 2 => InputEvent::Keyboard(KeyEvent::Insert),
- 3 => InputEvent::Keyboard(KeyEvent::Delete),
- 4 | 8 => InputEvent::Keyboard(KeyEvent::End),
- 5 => InputEvent::Keyboard(KeyEvent::PageUp),
- 6 => InputEvent::Keyboard(KeyEvent::PageDown),
- v @ 11..=15 => InputEvent::Keyboard(KeyEvent::F(v - 10)),
- v @ 17..=21 => InputEvent::Keyboard(KeyEvent::F(v - 11)),
- v @ 23..=24 => InputEvent::Keyboard(KeyEvent::F(v - 12)),
- _ => InputEvent::Unknown,
- }
- }
- e => match (buf.last().unwrap(), e) {
- (53, 65) => InputEvent::Keyboard(KeyEvent::CtrlUp),
- (53, 66) => InputEvent::Keyboard(KeyEvent::CtrlDown),
- (53, 67) => InputEvent::Keyboard(KeyEvent::CtrlRight),
- (53, 68) => InputEvent::Keyboard(KeyEvent::CtrlLeft),
- (50, 65) => InputEvent::Keyboard(KeyEvent::ShiftUp),
- (50, 66) => InputEvent::Keyboard(KeyEvent::ShiftDown),
- (50, 67) => InputEvent::Keyboard(KeyEvent::ShiftRight),
- (50, 68) => InputEvent::Keyboard(KeyEvent::ShiftLeft),
- _ => InputEvent::Unknown,
- },
- }
- }
- _ => InputEvent::Unknown,
- }
-}
-
-/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
-fn parse_utf8_char(c: u8, iter: &mut I) -> Result
-where
- I: Iterator,
-{
- let error = Err(ErrorKind::IoError(io::Error::new(
- io::ErrorKind::Other,
- "Input character is not valid UTF-8",
- )));
-
- if c.is_ascii() {
- Ok(c as char)
- } else {
- let mut bytes = Vec::new();
- bytes.push(c);
-
- while let Some(next) = iter.next() {
- bytes.push(next);
- if let Ok(st) = str::from_utf8(&bytes) {
- return Ok(st.chars().next().unwrap());
- }
- if bytes.len() >= 4 {
- return error;
- }
- }
-
- return error;
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::parse_utf8_char;
-
- #[test]
- fn test_parse_utf8() {
- let st = "abcéŷ¤£€ù%323";
- let ref mut bytes = st.bytes();
- let chars = st.chars();
- for c in chars {
- let b = bytes.next().unwrap();
- assert_eq!(c, parse_utf8_char(b, bytes).unwrap());
- }
- }
-}
diff --git a/crossterm_input/src/input/windows_input.rs b/crossterm_input/src/input/windows_input.rs
deleted file mode 100644
index 41a71d618..000000000
--- a/crossterm_input/src/input/windows_input.rs
+++ /dev/null
@@ -1,486 +0,0 @@
-//! This is a WINDOWS specific implementation for input related action.
-
-use std::sync::{
- atomic::{AtomicBool, Ordering},
- mpsc::{self, Receiver, Sender},
- Arc,
-};
-use std::time::Duration;
-use std::{char, io, thread};
-
-use winapi::um::{
- wincon::{
- LEFT_ALT_PRESSED, LEFT_CTRL_PRESSED, RIGHT_ALT_PRESSED, RIGHT_CTRL_PRESSED, SHIFT_PRESSED,
- },
- winnt::INT,
- winuser::{
- VK_BACK, VK_CONTROL, VK_DELETE, VK_DOWN, VK_END, VK_ESCAPE, VK_F1, VK_F10, VK_F11, VK_F12,
- VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_HOME, VK_INSERT, VK_LEFT,
- VK_MENU, VK_NEXT, VK_PRIOR, VK_RETURN, VK_RIGHT, VK_SHIFT, VK_UP,
- },
-};
-
-use crossterm_utils::Result;
-use crossterm_winapi::{
- ButtonState, Console, ConsoleMode, EventFlags, Handle, InputEventType, KeyEventRecord,
- MouseEvent,
-};
-
-use super::{ITerminalInput, InputEvent, KeyEvent, MouseButton};
-
-pub struct WindowsInput;
-
-impl WindowsInput {
- pub fn new() -> WindowsInput {
- WindowsInput
- }
-}
-
-const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008;
-
-// NOTE (@imdaveho): this global var is terrible -> move it elsewhere...
-static mut ORIG_MODE: u32 = 0;
-
-impl ITerminalInput for WindowsInput {
- fn read_char(&self) -> Result {
- // _getwch is without echo and _getwche is with echo
- let pressed_char = unsafe { _getwche() };
-
- // we could return error but maybe option to keep listening until valid character is inputted.
- if pressed_char == 0 || pressed_char == 0xe0 {
- Err(io::Error::new(
- io::ErrorKind::Other,
- "Given input char is not a valid char, mostly occurs when pressing special keys",
- ))?;
- }
-
- let ch = char::from_u32(pressed_char as u32).ok_or_else(|| {
- io::Error::new(io::ErrorKind::Other, "Could not parse given input to char")
- })?;
-
- Ok(ch)
- }
-
- fn read_async(&self) -> AsyncReader {
- AsyncReader::new(Box::new(move |event_tx, cancellation_token| loop {
- for i in read_input_events().unwrap().1 {
- if event_tx.send(i).is_err() {
- return;
- }
- }
-
- if cancellation_token.load(Ordering::SeqCst) {
- return;
- }
-
- thread::sleep(Duration::from_millis(1));
- }))
- }
-
- fn read_until_async(&self, delimiter: u8) -> AsyncReader {
- AsyncReader::new(Box::new(move |event_tx, cancellation_token| loop {
- for event in read_input_events().unwrap().1 {
- if let InputEvent::Keyboard(KeyEvent::Char(key)) = event {
- if (key as u8) == delimiter {
- return;
- }
- }
-
- if cancellation_token.load(Ordering::SeqCst) {
- return;
- } else {
- if event_tx.send(event).is_err() {
- return;
- }
- }
-
- thread::sleep(Duration::from_millis(1));
- }
- }))
- }
-
- fn read_sync(&self) -> SyncReader {
- SyncReader
- }
-
- fn enable_mouse_mode(&self) -> Result<()> {
- let mode = ConsoleMode::from(Handle::current_in_handle()?);
-
- unsafe {
- ORIG_MODE = mode.mode()?;
- mode.set_mode(ENABLE_MOUSE_MODE)?;
- }
- Ok(())
- }
-
- fn disable_mouse_mode(&self) -> Result<()> {
- let mode = ConsoleMode::from(Handle::current_in_handle()?);
- mode.set_mode(unsafe { ORIG_MODE })?;
- Ok(())
- }
-}
-
-/// This type allows you to read input synchronously, which means that reading call will be blocking ones.
-///
-/// This type is an iterator, and could be used to iterate over input events.
-///
-/// If you don't want to block your calls use [AsyncReader](./LINK), which will read input on the background and queue it for you to read.
-pub struct SyncReader;
-
-impl Iterator for SyncReader {
- type Item = InputEvent;
-
- /// Read input from the user.
- ///
- /// If there are no keys pressed this will be a blocking call until there are.
- /// This will return `None` in case of a failure and `Some(InputEvent) in case of an occurred input event.`
- fn next(&mut self) -> Option {
- read_single_event().unwrap()
- }
-}
-
-/// This type allows you to read the input asynchronously which means that input events are gathered on the background and will be queued for you to read.
-///
-/// **[SyncReader](./LINK)**
-/// If you want a blocking, or less resource consuming read to happen use `SyncReader`, this will leave a way all the thread and queueing and will be a blocking read.
-///
-/// This type is an iterator, and could be used to iterate over input events.
-///
-/// # Remarks
-/// - Threads spawned will be disposed of as soon the `AsyncReader` goes out of scope.
-/// - MPSC-channels are used to queue input events, this type implements an iterator of the rx side of the queue.
-pub struct AsyncReader {
- event_rx: Receiver,
- shutdown: Arc,
-}
-
-impl AsyncReader {
- /// Construct a new instance of the `AsyncReader`.
- /// The reading will immediately start when calling this function.
- pub fn new(function: Box, &Arc) + Send>) -> AsyncReader {
- let shutdown_handle = Arc::new(AtomicBool::new(false));
-
- let (event_tx, event_rx) = mpsc::channel();
- let thread_shutdown = shutdown_handle.clone();
-
- thread::spawn(move || loop {
- function(&event_tx, &thread_shutdown);
- });
-
- AsyncReader {
- event_rx,
- shutdown: shutdown_handle,
- }
- }
-
- /// Stop the input event reading.
- ///
- /// You don't necessarily have to call this function because it will automatically be called when this reader goes out of scope.
- ///
- /// # Remarks
- /// - Background thread will be closed.
- /// - This will consume the handle you won't be able to restart the reading with this handle, create a new `AsyncReader` instead.
- pub fn stop(&mut self) {
- self.shutdown.store(true, Ordering::SeqCst);
- }
-}
-
-impl Drop for AsyncReader {
- fn drop(&mut self) {
- self.stop();
- }
-}
-
-impl Iterator for AsyncReader {
- type Item = InputEvent;
-
- /// Check if there are input events to read.
- ///
- /// It will return `None` when nothing is there to read, `Some(InputEvent)` if there are events to read.
- ///
- /// # Remark
- /// - This is **not** a blocking call.
- /// - When calling this method to fast after each other the reader might not have read a full byte sequence of some pressed key.
- /// Make sure that you have some delay of a few ms when calling this method.
- fn next(&mut self) -> Option {
- let mut iterator = self.event_rx.try_iter();
- iterator.next()
- }
-}
-
-extern "C" {
- fn _getwche() -> INT;
-}
-
-fn read_single_event() -> Result