Cleanup Some Mess for next Release (#304)

This commit is contained in:
Timon 2019-11-01 18:09:05 +01:00 committed by GitHub
parent c23a6ddf38
commit f2a4df20db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 227 additions and 159 deletions

View File

@ -1,10 +1,14 @@
# Master # Version 0.13.0
**Major API-change, removed old-api**
- Remove `Crossterm` type
- Remove `TerminalCursor`, `TerminalColor`, `Terminal`
- Remove `cursor()`, `color()` , `terminal()`
- Remove re-exports at root, accessible via `module::types` (`cursor::MoveTo`)
- `input` module - `input` module
- Derive 'Copy' for 'KeyEvent' - Derive 'Copy' for 'KeyEvent'
- Add the `EnableMouseCapture` and `EnableMouseCapture` commands - Add the `EnableMouseCapture` and `EnableMouseCapture` commands
- `cursor` module - `cursor` module
- Remove `TerminalCursor`, `cursor`, `Crossterm::cursor()`
- Introduce static function `crossterm::cursor::position` in place of `TerminalCursor::pos` - Introduce static function `crossterm::cursor::position` in place of `TerminalCursor::pos`
- Rename `Goto` to `MoveTo` - Rename `Goto` to `MoveTo`
- Rename `Up` to `MoveLeft` - Rename `Up` to `MoveLeft`
@ -14,34 +18,29 @@
- Rename `BlinkOff` to `DisableBlinking` - Rename `BlinkOff` to `DisableBlinking`
- Rename `ResetPos` to `ResetPosition` - Rename `ResetPos` to `ResetPosition`
- Rename `SavePos` to `SavePosition` - Rename `SavePos` to `SavePosition`
- Remove re-export cursor module types at root level, are now accessible from `crossterm::cursor`
- `terminal` - `terminal`
- Remove `Terminal`, `terminal`, `Crossterm::terminal()`
- Introduce static function `crossterm::terminal::size` in place of `Terminal::size` - Introduce static function `crossterm::terminal::size` in place of `Terminal::size`
- Introduce static function `crossterm::terminal::exit` in place of `Terminal::exit` - Introduce static function `crossterm::terminal::exit` in place of `Terminal::exit`
- Remove re-export terminal module types at root level, are move those to `crossterm::terminal`
- `style module` - `style module`
- Rename `ObjectStyle` to `ContentStyle`. Now full names are used for methods. - Rename `ObjectStyle` to `ContentStyle`. Now full names are used for methods
- Rename `StyledObject` to `StyledContent` and made members private. - Rename `StyledObject` to `StyledContent` and made members private
- Rename `PrintStyledFont` to `PrintStyledContent` - Rename `PrintStyledFont` to `PrintStyledContent`
- Rename `attr` method to `attribute`. - Rename `attr` method to `attribute`.
- Rename `Attribute::NoInverse` to `NoReverse` - Rename `Attribute::NoInverse` to `NoReverse`
- `Crossterm::style()` and `Crossterm::color()`
- Remove re-exports from style module at at root and only expose those in the `crossterm::style` module.
- Remove `TerminalColor` (/style.rs),
- Remove `color` (style.rs)
- Update documentation - Update documentation
- Made `Colored` private, user should use commands instead. - Made `Colored` private, user should use commands instead
- Rename `SetFg` -> `SetForegroundColor` - Rename `SetFg` -> `SetForegroundColor`
- Rename `SetBg` -> `SetBackgroundColor` - Rename `SetBg` -> `SetBackgroundColor`
- Rename `SetAttr` -> `SetAttribute` - Rename `SetAttr` -> `SetAttribute`
- Rename `ContentStyle::fg_color` -> `ContentStyle::foreground_color` - Rename `ContentStyle::fg_color` -> `ContentStyle::foreground_color`
- Rename `ContentStyle::bg_color` -> `ContentStyle::background_color` - Rename `ContentStyle::bg_color` -> `ContentStyle::background_color`
- Rename `ContentStyle::attrs` -> `ContentStyle::attributes` - Rename `ContentStyle::attrs` -> `ContentStyle::attributes`
- Improve documentation
- Unix terminal size calculation with TPUT
# Version 0.12.1 # Version 0.12.1
- All the `crossterm_` crates code was moved to the `crossterm` crate - Move all the `crossterm_` crates code was moved to the `crossterm` crate
- `crossterm_cursor` is in the `cursor` module, etc. - `crossterm_cursor` is in the `cursor` module, etc.
- All these modules are public - All these modules are public
- No public API breaking changes - No public API breaking changes
@ -58,34 +57,27 @@
## `crossterm_cursor` 0.4.0 ## `crossterm_cursor` 0.4.0
- Internal refactoring ([PR #2](https://github.com/crossterm-rs/crossterm-cursor/pull/2)) - Fix examples link ([PR #6](https://github.com/crossterm-rs/crossterm-cursor/pull/6))
- Improved public documentation
- `sys` module is no longer public
- Fixed examples link ([PR #6](https://github.com/crossterm-rs/crossterm-cursor/pull/6))
- Sync documentation style ([PR #7](https://github.com/crossterm-rs/crossterm-cursor/pull/7)) - Sync documentation style ([PR #7](https://github.com/crossterm-rs/crossterm-cursor/pull/7))
- Removed all references to the crossterm book ([PR #8](https://github.com/crossterm-rs/crossterm-cursor/pull/8)) - Remove all references to the crossterm book ([PR #8](https://github.com/crossterm-rs/crossterm-cursor/pull/8))
- Replaced `RAW_MODE_ENABLED` with `is_raw_mode_enabled` ([PR #9](https://github.com/crossterm-rs/crossterm-cursor/pull/9)) - Replace `RAW_MODE_ENABLED` with `is_raw_mode_enabled` ([PR #9](https://github.com/crossterm-rs/crossterm-cursor/pull/9))
- Use `SyncReader` & `InputEvent::CursorPosition` for `pos_raw()` ([PR #10](https://github.com/crossterm-rs/crossterm-cursor/pull/10)) - Use `SyncReader` & `InputEvent::CursorPosition` for `pos_raw()` ([PR #10](https://github.com/crossterm-rs/crossterm-cursor/pull/10))
## `crossterm_input` 0.5.0 ## `crossterm_input` 0.5.0
- Internal refactoring ([PR #3](https://github.com/crossterm-rs/crossterm-input/pull/3))
- Removed unsafe `static mut`
- Documentation update
- Remove all references to the crossterm book
- Sync documentation style ([PR #4](https://github.com/crossterm-rs/crossterm-input/pull/4)) - Sync documentation style ([PR #4](https://github.com/crossterm-rs/crossterm-input/pull/4))
- Sync `SyncReader::next()` Windows and UNIX behavior ([PR #5](https://github.com/crossterm-rs/crossterm-input/pull/5)) - Sync `SyncReader::next()` Windows and UNIX behavior ([PR #5](https://github.com/crossterm-rs/crossterm-input/pull/5))
- Remove all references to the crossterm book ([PR #6](https://github.com/crossterm-rs/crossterm-input/pull/6)) - Remove all references to the crossterm book ([PR #6](https://github.com/crossterm-rs/crossterm-input/pull/6))
- Mouse coordinates synchronized with the cursor ([PR #7](https://github.com/crossterm-rs/crossterm-input/pull/7)) - Mouse coordinates synchronized with the cursor ([PR #7](https://github.com/crossterm-rs/crossterm-input/pull/7))
- Upper/left reported as `(0, 0)` - Upper/left reported as `(0, 0)`
- Fixed bug that read sync didn't block (Windows) ([PR #8](https://github.com/crossterm-rs/crossterm-input/pull/8)) - Fix bug that read sync didn't block (Windows) ([PR #8](https://github.com/crossterm-rs/crossterm-input/pull/8))
- Refactored UNIX readers ([PR #9](https://github.com/crossterm-rs/crossterm-input/pull/9)) - Refactor UNIX readers ([PR #9](https://github.com/crossterm-rs/crossterm-input/pull/9))
- AsyncReader produces mouse events - AsyncReader produces mouse events
- One reading thread per application, not per `AsyncReader` - One reading thread per application, not per `AsyncReader`
- Cursor position no longer consumed by another `AsyncReader` - Cursor position no longer consumed by another `AsyncReader`
- Implemented sync reader for read_char (requires raw mode) - Implement sync reader for read_char (requires raw mode)
- Fixed `SIGTTIN` when executed under the LLDB - Fix `SIGTTIN` when executed under the LLDB
- Added mio for reading from FD and more efficient polling (UNIX only) - Add mio for reading from FD and more efficient polling (UNIX only)
- Sync UNIX and Windows vertical mouse position ([PR #11](https://github.com/crossterm-rs/crossterm-input/pull/11)) - Sync UNIX and Windows vertical mouse position ([PR #11](https://github.com/crossterm-rs/crossterm-input/pull/11))
- Top is always reported as `0` - Top is always reported as `0`
@ -103,10 +95,9 @@
## `crossterm_style` 0.5.2 ## `crossterm_style` 0.5.2
- Refactoring ([PR #2](https://github.com/crossterm-rs/crossterm-style/pull/2)) - Refactor ([PR #2](https://github.com/crossterm-rs/crossterm-style/pull/2))
- Added unit tests - Added unit tests
- Restructured files - Improved documentation and added book page to `lib.rs`
- Improved documentation and added book page to lib.rs
- Fixed bug with `SetBg` command, WinApi logic - Fixed bug with `SetBg` command, WinApi logic
- Fixed bug with `StyledObject`, used stdout for resetting terminal color - Fixed bug with `StyledObject`, used stdout for resetting terminal color
- Introduced `ResetColor` command - Introduced `ResetColor` command
@ -166,8 +157,8 @@ As a preparation for crossterm 0.1.0 we have moved crossterm to an organisation
* `TerminalInput::read_char` returns `crossterm::Result` instead of `io::Result` * `TerminalInput::read_char` returns `crossterm::Result` instead of `io::Result`
* Maybe I forgot something, a lot of functions have changed * Maybe I forgot something, a lot of functions have changed
- Removed all unwraps/expects from library - Removed all unwraps/expects from library
- Added KeyEvent::Enter and KeyEvent::Tab: [added-key-event-enter], [added-key-event-tab] - Add KeyEvent::Enter and KeyEvent::Tab: [added-key-event-enter], [added-key-event-tab]
- Synced set/get terminal size behaviour: [fixed-get-set-terminal-size] - Sync set/get terminal size behaviour: [fixed-get-set-terminal-size]
- Method renames: - Method renames:
* `AsyncReader::stop_reading()` to `stop()` * `AsyncReader::stop_reading()` to `stop()`
* `RawScreen::disable_raw_mode_on_drop` to `keep_raw_mode_on_drop` * `RawScreen::disable_raw_mode_on_drop` to `keep_raw_mode_on_drop`
@ -210,11 +201,11 @@ As a preparation for crossterm 0.1.0 we have moved crossterm to an organisation
# Version 0.10.1 # Version 0.10.1
# Version 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) - Implement 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 - Fix 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) - Remove 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) - Made terminal size 1-based [PR](https://github.com/crossterm-rs/crossterm/commit/d689d7e8ed46a335474b8262bd76f21feaaf0c50)
- Added some derive implementation - Add some derives
# Version 0.9.6 # Version 0.9.6
@ -225,7 +216,7 @@ As a preparation for crossterm 0.1.0 we have moved crossterm to an organisation
# Version 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) - Prefetch buffer size for more efficient windows input reads. [PR](https://github.com/crossterm-rs/crossterm/pull/144)
# Version 0.9.4 # Version 0.9.4

View File

@ -14,6 +14,19 @@ 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, 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). see [Tested Terminals](#tested-terminals) for more info).
## Note on Migration
You may have noticed that Crossterm has been [changing](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md) very quickly with the latest versions.
We have done a lot of API-breaking things by renaming functions, commands, changing the exports, improving the encapsulation, etc..
However, all of this happens to improve the library and make it ready for a possible [1.0 release](#287).
We want to stick to the [Command API](https://docs.rs/crossterm/#command-api) and remove all other ways to use crossterm.
Try to use this API and change your code accordingly.
This way you will survive or overcome major migration problems ;).
We want to reduce the ways crossterm can be used to make it simpler and easier to maintain.
We hope you can understand this, feel free to ask around in [discord ](https://discord.gg/K4nyTDB) if you have questions on how to migrate.
Also, for up-to-date examples, have a look at the [examples](https://github.com/crossterm-rs/examples/tree/masteri) repository.
## Table of Contents ## Table of Contents
* [Features](#features) * [Features](#features)
@ -30,6 +43,7 @@ see [Tested Terminals](#tested-terminals) for more info).
- Multi-threaded (send, sync) - Multi-threaded (send, sync)
- Detailed documentation - Detailed documentation
- Few dependencies - Few dependencies
- Full control over output buffer
- Cursor (feature `cursor`) - Cursor (feature `cursor`)
- Move the cursor N times (up, down, left, right) - Move the cursor N times (up, down, left, right)
- Set/get the cursor position - Set/get the cursor position
@ -94,22 +108,31 @@ crossterm = "0.12"
```rust ```rust
use std::io::{stdout, Write}; use std::io::{stdout, Write};
use crossterm::{execute, Attribute, Color, Output, ResetColor, Result, SetBg, SetFg}; use crossterm::{execute, ExecutableCommand, style::{Attribute, Color, SetForegroundColor, SetBackgroundColor, ResetColor}, Output, Result};
fn main() -> Result<()> { fn main() -> Result<()> {
// using the macro
execute!( execute!(
stdout(), stdout(),
// Blue foreground SetForegroundColor(Color::Blue),
SetFg(Color::Blue), SetBackgroundColor(Color::Red),
// Red background Output("Styled text here."),
SetBg(Color::Red),
Output("Styled text here.".to_string()),
// Reset to default colors
ResetColor ResetColor
) )?;
// or using functions
stdout()
.execute(SetForegroundColor(Color::Blue))?
.execute(SetBackgroundColor(Color::Red))?
.execute(Output("Styled text here."))?
.execute(ResetColor)?;
Ok(())
} }
``` ```
Checkout this [list](https://docs.rs/crossterm/0.13.0/crossterm/index.html#supported-commands) with all possible commands.
### Feature Flags ### Feature Flags
All features are enabled by default. You can disable default features and enable some of them only. All features are enabled by default. You can disable default features and enable some of them only.

View File

@ -1,15 +0,0 @@
/// A crossterm functionality wrapper.
pub struct Crossterm;
impl Crossterm {
/// Creates a new `Crossterm`.
pub fn new() -> Crossterm {
Crossterm
}
/// Creates a new `TerminalInput`.
#[cfg(feature = "input")]
pub fn input(&self) -> crate::input::TerminalInput {
crate::input::TerminalInput::new()
}
}

View File

@ -205,7 +205,7 @@ impl From<InternalEvent> for Option<InputEvent> {
/// ```no_run /// ```no_run
/// // You can replace the following line with `use crossterm::...;` /// // You can replace the following line with `use crossterm::...;`
/// // if you're using the `crossterm` crate with the `input` feature enabled. /// // if you're using the `crossterm` crate with the `input` feature enabled.
/// use crossterm::{Result, TerminalInput, RawScreen}; /// use crossterm::{Result, input::{TerminalInput}, screen::RawScreen};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let input = TerminalInput::new(); /// let input = TerminalInput::new();
@ -261,7 +261,7 @@ impl TerminalInput {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let input = crossterm::input(); /// let input = crossterm::input::input();
/// match input.read_line() { /// match input.read_line() {
/// Ok(s) => println!("string typed: {}", s), /// Ok(s) => println!("string typed: {}", s),
/// Err(e) => println!("error: {}", e), /// Err(e) => println!("error: {}", e),
@ -276,7 +276,7 @@ impl TerminalInput {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let input = crossterm::input(); /// let input = crossterm::input::input();
/// match input.read_char() { /// match input.read_char() {
/// Ok(c) => println!("character pressed: {}", c), /// Ok(c) => println!("character pressed: {}", c),
/// Err(e) => println!("error: {}", e), /// Err(e) => println!("error: {}", e),
@ -302,7 +302,7 @@ impl TerminalInput {
/// ///
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// use crossterm::input; /// use crossterm::input::input;
/// ///
/// let mut async_stdin = input().read_async(); /// let mut async_stdin = input().read_async();
/// ///
@ -335,8 +335,9 @@ impl TerminalInput {
/// ///
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// use crossterm::input::input;
/// ///
/// let mut async_stdin = crossterm::input().read_until_async(b'x'); /// let mut async_stdin = input().read_until_async(b'x');
/// ///
/// loop { /// loop {
/// if let Some(key_event) = async_stdin.next() { /// if let Some(key_event) = async_stdin.next() {
@ -360,8 +361,9 @@ impl TerminalInput {
/// ///
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// use crossterm::input::input;
/// ///
/// let mut sync_stdin = crossterm::input().read_sync(); /// let mut sync_stdin = input().read_sync();
/// ///
/// loop { /// loop {
/// if let Some(key_event) = sync_stdin.next() { /// if let Some(key_event) = sync_stdin.next() {
@ -397,7 +399,7 @@ impl TerminalInput {
/// ```no_run /// ```no_run
/// // You can replace the following line with `use crossterm::...;` /// // You can replace the following line with `use crossterm::...;`
/// // if you're using the `crossterm` crate with the `input` feature enabled. /// // if you're using the `crossterm` crate with the `input` feature enabled.
/// use crossterm::{input, RawScreen, Result}; /// use crossterm::{input::input, screen::RawScreen, Result};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let input = input(); /// let input = input();

View File

@ -39,7 +39,7 @@ pub(crate) trait Input {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// let input = crossterm::input(); /// let input = crossterm::input::input();
/// match input.read_line() { /// match input.read_line() {
/// Ok(s) => println!("string typed: {}", s), /// Ok(s) => println!("string typed: {}", s),
/// Err(e) => println!("error: {}", e), /// Err(e) => println!("error: {}", e),

View File

@ -92,7 +92,7 @@ impl Input for UnixInput {
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// ///
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen}; /// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
/// ///
/// fn main() { /// fn main() {
/// println!("Press 'ESC' to quit."); /// println!("Press 'ESC' to quit.");
@ -221,7 +221,7 @@ impl Iterator for AsyncReader {
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// ///
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen}; /// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
/// ///
/// fn main() { /// fn main() {
/// println!("Press 'ESC' to quit."); /// println!("Press 'ESC' to quit.");

View File

@ -29,13 +29,9 @@ use winapi::um::{
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::input::{input::Input, InputEvent, KeyEvent, MouseButton};
use crate::utils::Result; use crate::utils::Result;
use super::{
super::{InputEvent, KeyEvent, MouseButton},
Input,
};
const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008; const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008;
lazy_static! { lazy_static! {
@ -172,7 +168,7 @@ impl Input for WindowsInput {
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// ///
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen}; /// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
/// ///
/// fn main() { /// fn main() {
/// println!("Press 'ESC' to quit."); /// println!("Press 'ESC' to quit.");
@ -245,7 +241,7 @@ impl Iterator for SyncReader {
/// ```no_run /// ```no_run
/// use std::{thread, time::Duration}; /// use std::{thread, time::Duration};
/// ///
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen}; /// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
/// ///
/// fn main() { /// fn main() {
/// println!("Press 'ESC' to quit."); /// println!("Press 'ESC' to quit.");
@ -534,7 +530,7 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option<KeyEvent> {
} }
} }
fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEvent>> { fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::input::MouseEvent>> {
// NOTE (@imdaveho): xterm emulation takes the digits of the coords and passes them // NOTE (@imdaveho): xterm emulation takes the digits of the coords and passes them
// individually as bytes into a buffer; the below cxbs and cybs replicates that and // individually as bytes into a buffer; the below cxbs and cybs replicates that and
// mimicks the behavior; additionally, in xterm, mouse move is only handled when a // mimicks the behavior; additionally, in xterm, mouse move is only handled when a
@ -554,10 +550,12 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
EventFlags::PressOrRelease => { EventFlags::PressOrRelease => {
// Single click // Single click
match event.button_state { match event.button_state {
ButtonState::Release => Some(crate::MouseEvent::Release(xpos as u16, ypos as u16)), ButtonState::Release => {
Some(crate::input::MouseEvent::Release(xpos as u16, ypos as u16))
}
ButtonState::FromLeft1stButtonPressed => { ButtonState::FromLeft1stButtonPressed => {
// left click // left click
Some(crate::MouseEvent::Press( Some(crate::input::MouseEvent::Press(
MouseButton::Left, MouseButton::Left,
xpos as u16, xpos as u16,
ypos as u16, ypos as u16,
@ -565,7 +563,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
} }
ButtonState::RightmostButtonPressed => { ButtonState::RightmostButtonPressed => {
// right click // right click
Some(crate::MouseEvent::Press( Some(crate::input::MouseEvent::Press(
MouseButton::Right, MouseButton::Right,
xpos as u16, xpos as u16,
ypos as u16, ypos as u16,
@ -573,7 +571,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
} }
ButtonState::FromLeft2ndButtonPressed => { ButtonState::FromLeft2ndButtonPressed => {
// middle click // middle click
Some(crate::MouseEvent::Press( Some(crate::input::MouseEvent::Press(
MouseButton::Middle, MouseButton::Middle,
xpos as u16, xpos as u16,
ypos as u16, ypos as u16,
@ -586,7 +584,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
// Click + Move // Click + Move
// NOTE (@imdaveho) only register when mouse is not released // NOTE (@imdaveho) only register when mouse is not released
if event.button_state != ButtonState::Release { if event.button_state != ButtonState::Release {
Some(crate::MouseEvent::Hold(xpos as u16, ypos as u16)) Some(crate::input::MouseEvent::Hold(xpos as u16, ypos as u16))
} else { } else {
None None
} }
@ -596,13 +594,13 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
// NOTE (@imdaveho) from https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str // NOTE (@imdaveho) from https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str
// if `button_state` is negative then the wheel was rotated backward, toward the user. // if `button_state` is negative then the wheel was rotated backward, toward the user.
if event.button_state != ButtonState::Negative { if event.button_state != ButtonState::Negative {
Some(crate::MouseEvent::Press( Some(crate::input::MouseEvent::Press(
MouseButton::WheelUp, MouseButton::WheelUp,
xpos as u16, xpos as u16,
ypos as u16, ypos as u16,
)) ))
} else { } else {
Some(crate::MouseEvent::Press( Some(crate::input::MouseEvent::Press(
MouseButton::WheelDown, MouseButton::WheelDown,
xpos as u16, xpos as u16,
ypos as u16, ypos as u16,

View File

@ -16,7 +16,9 @@
//! ## Command API //! ## Command API
//! //!
//! The command API makes the use of `crossterm` much easier and offers more control over when and how a //! The command API makes the use of `crossterm` much easier and offers more control over when and how a
//! command such as moving the cursor is executed. The command API offers: //! command is executed. An command is just an action you can perform on the terminal e.g. cursor movement.
//!
//! The command API offers:
//! //!
//! * Better Performance. //! * Better Performance.
//! * Complete control over when to flush. //! * Complete control over when to flush.
@ -30,31 +32,70 @@
//! * Macros are generally seen as more difficult but offer an API with less boilerplate code. If you are //! * Macros are generally seen as more difficult but offer an API with less boilerplate code. If you are
//! not afraid of macros, this is a recommendation. //! not afraid of macros, this is a recommendation.
//! //!
//! Before `crossterm` 10.0 was released, `crossterm` had some performance issues. It did a `flush` after each command
//! (cursor movement). A `flush` is heavy action on the terminal, and if it is done more often the performance
//! will go down quickly.
//!
//! Linux and Windows 10 systems support ANSI escape codes. Those ANSI escape codes are strings or rather a //! Linux and Windows 10 systems support ANSI escape codes. Those ANSI escape codes are strings or rather a
//! byte sequence. When we `write` and `flush` those to the terminal we can perform some action. //! byte sequence. When we `write` and `flush` those to the terminal we can perform some action.
//! For older windows systems a WinApi call is made.
//!
//! ### Supported Commands
//!
//!| *Command Name* | *Description* |
//!| :------------------------------ | :---------------------------- |
//!| **crossterm::cursor module** | |
//!| `cursor::DisableBlinking` | disables blinking of the terminal cursor. |
//!| `cursor::EnableBlinking` | enables blinking of the terminal cursor. |
//!| `cursor::Hide` | hides the terminal cursor. |
//!| `cursor::MoveDown` | moves the terminal cursor a given number of rows down. |
//!| `cursor::MoveLeft` | moves the terminal cursor a given number of columns to the left. |
//!| `cursor::MoveRight` | moves the terminal cursor a given number of columns to the right. |
//!| `cursor::MoveTo` | moves the terminal cursor to the given position (column, row). |
//!| `cursor::MoveUp` | moves the terminal cursor a given number of rows up. |
//!| `cursor::RestorePosition` | restores the saved terminal cursor position. |
//!| `cursor::SavePosition` | saves the current terminal cursor position. |
//!| `cursor::Show` | shows the terminal cursor. |
//!| **crossterm::input module** | |
//!| `input::DisableMouseCapture` | disables mouse event monitoring. |
//!| `input::EnableMouseCapture` | enables mouse mode |
//!| | |
//!| `screen::EnterAlternateScreen` | switches to the alternate screen. |
//!| `screen::LeaveAlternateScreen` | switches back to the main screen. |
//!| **crossterm::style module** | |
//!| `style::PrintStyledContent` | prints styled content. |
//!| `style::ResetColor` | resets the colors back to default. |
//!| `style::SetAttribute` | sets an attribute. |
//!| `style::SetBackgroundColor` | sets the the background color. |
//!| `style::SetForegroundColor` | sets the the foreground color. |
//!| **crossterm::terminal module** | |
//!| `terminal::Clear` | clears the terminal screen buffer. |
//!| `terminal::ScrollDown` | scrolls the terminal screen a given number of rows down. |
//!| `terminal::ScrollUp` | scrolls the terminal screen a given number of rows up. |
//!| `terminal::SetSize` | sets the terminal size (columns, rows). |
//!
//! There are two different way's to execute commands.
//! * [Lazy Execution](#lazy-execution)
//! * [Direct Execution](#direct-execution)
//! //!
//! ## Lazy Execution //! ## Lazy Execution
//! //!
//! Because `flush` is a heavy system call we can instead `write` the commands to the `stdout` without flushing. //! Flushing bytes to the terminal buffer is a heavy system call. If we perform a lot of actions with the terminal,
//! When can do a `flush` when we do want to execute the commands. //! we want to do this periodically - like with a TUI editor - so that we can flush more data to the terminal buffer at the same time.
//! //!
//! If you create a terminal editor or TUI, it is wise to use this option. For example, you can `write` commands //! Crossterm offers the possibility to do this with `queue`.
//! to the terminal `stdout` and `flush` the `stdout` at every frame. By doing this you can make efficient use of the //! With `queue` you can queue commands, and when you call [Write::flush][flush] these commands will be executed.
//! terminal buffer and get better performance because you are not calling `flush` after every command. //!
//! You can pass a custom buffer implementing [std::io::Write][write] to this `queue` operation.
//! The commands will be executed on that buffer.
//! The most common buffer is [std::io::stdout][stdout] however, [std::io::stderr][stderr] is used sometimes as well.
//! //!
//! ### Examples //! ### Examples
//! A simple demonstration that shows the command API in action with cursor commands.
//! //!
//! Functions: //! **Functions**
//! //!
//! ```no_run //! ```no_run
//! use std::io::Write; //! use std::io::{Write, stdout};
//! use crossterm::{QueueableCommand, cursor}; //! use crossterm::{QueueableCommand, cursor};
//! //!
//! let mut stdout = std::io::stdout(); //! let mut stdout = stdout();
//! stdout.queue(cursor::MoveTo(5,5)); //! stdout.queue(cursor::MoveTo(5,5));
//! //!
//! // some other code ... //! // some other code ...
@ -62,58 +103,68 @@
//! stdout.flush(); //! stdout.flush();
//! ``` //! ```
//! //!
//! The `queue` function returns itself, therefore you can use this to queue another command. Like //! The [queue](./trait.QueueableCommand.html) function returns itself, therefore you can use this to queue another command. Like
//! `stdout.queue(Goto(5,5)).queue(Clear(ClearType::All))`. //! `stdout.queue(Goto(5,5)).queue(Clear(ClearType::All))`.
//! //!
//! Macros: //! **Macros**
//! //!
//! ```no_run //! ```no_run
//! use std::io::Write; //! use std::io::{Write, stdout};
//! use crossterm::{queue, QueueableCommand, cursor}; //! use crossterm::{queue, QueueableCommand, cursor};
//! //!
//! let mut stdout = std::io::stdout(); //! let mut stdout = stdout();
//! queue!(stdout, cursor::MoveTo(5, 5)); //! queue!(stdout, cursor::MoveTo(5, 5));
//! //!
//! // some other code ... //! // some other code ...
//! //!
//! // move operation is performed only if we flush the buffer.
//! stdout.flush(); //! stdout.flush();
//! ``` //! ```
//! //!
//! You can pass more than one command into the macro like `queue!(stdout, Goto(5, 5), Clear(ClearType::All))` and //! You can pass more than one command into the [queue](./macro.queue.html) macro like `queue!(stdout, MoveTo(5, 5), Clear(ClearType::All))` and
//! they will be executed in the given order from left to right. //! they will be executed in the given order from left to right.
//! //!
//! ## Direct Execution //! ## Direct Execution
//! //!
//! If you want to execute commands directly, this is also possible. You don't have to flush the 'stdout', //! For many applications it is not at all important to be efficient with 'flush' operations.
//! as described above. This is fine if you are not executing lots of commands. //! For this use case there is the `execute` operation.
//! This operation executes the command immediately, and calls the `flush` under water.
//!
//! You can pass a custom buffer implementing [std::io::Write][write] to this `execute` operation.
//! The commands will be executed on that buffer.
//! The most common buffer is [std::io::stdout][stdout] however, [std::io::stderr][stderr] is used sometimes as well.
//! //!
//! ### Examples //! ### Examples
//! //!
//! Functions: //! **Functions**
//! //!
//! ```no_run //! ```no_run
//! use std::io::Write; //! use std::io::{Write, stdout};
//! use crossterm::{ExecutableCommand, cursor}; //! use crossterm::{ExecutableCommand, cursor};
//! //!
//! let mut stdout = std::io::stdout(); //! let mut stdout = stdout();
//! stdout.execute(cursor::MoveTo(5,5)); //! stdout.execute(cursor::MoveTo(5,5));
//! ``` //! ```
//! The [execute](./trait.ExecutableCommand.html) function returns itself, therefore you can use this to queue another command. Like
//! `stdout.queue(Goto(5,5)).queue(Clear(ClearType::All))`.
//! //!
//! Macros: //! **Macros**
//! //!
//! ```no_run //! ```no_run
//! use std::io::Write; //! use std::io::{Write, stdout};
//! use crossterm::{execute, ExecutableCommand, cursor}; //! use crossterm::{execute, ExecutableCommand, cursor};
//! //!
//! let mut stdout = std::io::stdout(); //! let mut stdout = stdout();
//! execute!(stdout, cursor::MoveTo(5, 5)); //! execute!(stdout, cursor::MoveTo(5, 5));
//! ``` //! ```
//! You can pass more than one command into the [execute](./macro.execute.html) macro like `execute!(stdout, MoveTo(5, 5), Clear(ClearType::All))` and
//! they will be executed in the given order from left to right.
//! //!
//! ## Examples //! ## Examples
//! //!
//! Print a rectangle colored with magenta and use both direct execution and lazy execution. //! Print a rectangle colored with magenta and use both direct execution and lazy execution.
//! //!
//! Functions: //! **Functions**
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{stdout, Write};
@ -130,6 +181,7 @@
//! for y in 0..40 { //! for y in 0..40 {
//! for x in 0..150 { //! for x in 0..150 {
//! if (y == 0 || y == 40 - 1) || (x == 0 || x == 150 - 1) { //! if (y == 0 || y == 40 - 1) || (x == 0 || x == 150 - 1) {
//! // in this loop we are more efficient by not flushing the buffer.
//! stdout //! stdout
//! .queue(cursor::MoveTo(x,y))? //! .queue(cursor::MoveTo(x,y))?
//! .queue(style::PrintStyledContent( "█".magenta()))?; //! .queue(style::PrintStyledContent( "█".magenta()))?;
@ -141,7 +193,7 @@
//! } //! }
//! ``` //! ```
//! //!
//! Macros: //! **Macros:**
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{stdout, Write};
@ -158,6 +210,7 @@
//! for y in 0..40 { //! for y in 0..40 {
//! for x in 0..150 { //! for x in 0..150 {
//! if (y == 0 || y == 40 - 1) || (x == 0 || x == 150 - 1) { //! if (y == 0 || y == 40 - 1) || (x == 0 || x == 150 - 1) {
//! // in this loop we are more efficient by not flushing the buffer.
//! queue!(stdout, cursor::MoveTo(x,y), style::PrintStyledContent( "█".magenta()))?; //! queue!(stdout, cursor::MoveTo(x,y), style::PrintStyledContent( "█".magenta()))?;
//! } //! }
//! } //! }
@ -166,35 +219,30 @@
//! Ok(()) //! Ok(())
//! } //! }
//!``` //!```
//!
//! [write]: https://doc.rust-lang.org/std/io/trait.Write.html
//! [stdout]: https://doc.rust-lang.org/std/io/fn.stdout.html
//! [stderr]: https://doc.rust-lang.org/std/io/fn.stderr.html
//! [flush]: https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush
#[cfg(feature = "input")]
pub use input::{
input, AsyncReader, DisableMouseCapture, EnableMouseCapture, InputEvent, KeyEvent, MouseButton,
MouseEvent, SyncReader, TerminalInput,
};
#[cfg(feature = "screen")]
pub use screen::{
AlternateScreen, EnterAlternateScreen, IntoRawMode, LeaveAlternateScreen, RawScreen,
};
pub use utils::{Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result}; pub use utils::{Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result};
pub use self::crossterm::Crossterm; #[cfg(windows)]
pub use utils::functions::supports_ansi;
mod crossterm; /// A module to work with the terminal cursor
/// A functionality to work with the terminal cursor
#[cfg(feature = "cursor")] #[cfg(feature = "cursor")]
pub mod cursor; pub mod cursor;
/// A functionality to read the input events. /// A module to read the input events.
#[cfg(feature = "input")] #[cfg(feature = "input")]
pub mod input; pub mod input;
/// A functionality to work with the terminal screen. /// A module to work with the terminal screen.
#[cfg(feature = "screen")] #[cfg(feature = "screen")]
pub mod screen; pub mod screen;
/// A functionality to apply attributes and colors on your text. /// A module to apply attributes and colors on your text.
#[cfg(feature = "style")] #[cfg(feature = "style")]
pub mod style; pub mod style;
/// A functionality to work with the terminal. /// A module to work with the terminal.
#[cfg(feature = "terminal")] #[cfg(feature = "terminal")]
pub mod terminal; pub mod terminal;
/// Shared utilities. /// Shared utilities.

View File

@ -76,7 +76,7 @@ mod sys;
/// Alternate screen with raw mode enabled: /// Alternate screen with raw mode enabled:
/// ///
/// ```no_run /// ```no_run
/// use crossterm::{AlternateScreen, Result}; /// use crossterm::{screen::{AlternateScreen}, Result};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let _alternate = AlternateScreen::to_alternate(true)?; /// let _alternate = AlternateScreen::to_alternate(true)?;
@ -145,7 +145,7 @@ impl Drop for AlternateScreen {
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{stdout, Write};
/// use crossterm::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen}; /// use crossterm::{execute, Result,screen::{EnterAlternateScreen, LeaveAlternateScreen}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// execute!(stdout(), EnterAlternateScreen)?; /// execute!(stdout(), EnterAlternateScreen)?;
@ -181,7 +181,7 @@ impl Command for EnterAlternateScreen {
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{stdout, Write};
/// use crossterm::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen}; /// use crossterm::{execute, Result, screen::{EnterAlternateScreen, LeaveAlternateScreen}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// execute!(stdout(), EnterAlternateScreen)?; /// execute!(stdout(), EnterAlternateScreen)?;

View File

@ -3,7 +3,7 @@ pub(crate) use ansi::AnsiAlternateScreen;
pub(crate) use windows::WinApiAlternateScreen; pub(crate) use windows::WinApiAlternateScreen;
#[cfg(windows)] #[cfg(windows)]
use crate::utils::supports_ansi; use crate::supports_ansi;
use crate::utils::Result; use crate::utils::Result;
pub(crate) mod ansi; pub(crate) mod ansi;

View File

@ -15,7 +15,7 @@ use super::sys;
/// Basic usage: /// Basic usage:
/// ///
/// ```no_run /// ```no_run
/// use crossterm::{RawScreen, Result}; /// use crossterm::{screen::RawScreen, Result};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let _raw = RawScreen::into_raw_mode()?; /// let _raw = RawScreen::into_raw_mode()?;
@ -27,7 +27,7 @@ use super::sys;
/// Do not disable the raw mode implicitly: /// Do not disable the raw mode implicitly:
/// ///
/// ```no_run /// ```no_run
/// use crossterm::{RawScreen, Result}; /// use crossterm::{screen::RawScreen, Result};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let mut raw = RawScreen::into_raw_mode()?; /// let mut raw = RawScreen::into_raw_mode()?;
@ -93,7 +93,7 @@ impl RawScreen {
/// ///
/// ```no_run /// ```no_run
/// use std::io::stdout; /// use std::io::stdout;
/// use crossterm::{IntoRawMode, Result}; /// use crossterm::{screen::IntoRawMode, Result};
/// ///
/// fn main() -> Result<()> { /// fn main() -> Result<()> {
/// let stdout = stdout(); /// let stdout = stdout();

View File

@ -16,10 +16,14 @@
//! * [Attribute](enum.Attribute.html#platform-specific-notes) //! * [Attribute](enum.Attribute.html#platform-specific-notes)
//! //!
//! ## Examples //! ## Examples
//! A few examples of how to use the style module.
//! //!
//! ### Colors //! ### Colors
//! How to change the terminal text color.
//! //!
//! The command API: //! **Command API**
//!
//! Using the Command API to color text.
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{stdout, Write};
@ -42,7 +46,9 @@
//! } //! }
//! ``` //! ```
//! //!
//! The [`Colorize`](trait.Colorize.html) trait: //! **Functions**
//!
//! Using functions from [`Colorize`](trait.Colorize.html) on a `String` or `&'static str` to color it.
//! //!
//! ```no_run //! ```no_run
//! use crossterm::style::Colorize; //! use crossterm::style::Colorize;
@ -51,8 +57,11 @@
//! ``` //! ```
//! //!
//! ### Attributes //! ### Attributes
//! How to appy terminal attributes to text.
//! //!
//! The command API: //! **Command API**
//!
//! Using the Command API to set attributes.
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{stdout, Write};
@ -72,7 +81,9 @@
//! } //! }
//! ``` //! ```
//! //!
//! The [`Styler`](trait.Styler.html) trait: //! **Functions**:
//!
//! Using [`Styler`](trait.Styler.html) functions on a `String` or `&'static str` to set attributes to it.
//! //!
//! ```no_run //! ```no_run
//! use crossterm::style::Styler; //! use crossterm::style::Styler;
@ -82,7 +93,9 @@
//! println!("{}", "Negative".negative()); //! println!("{}", "Negative".negative());
//! ``` //! ```
//! //!
//! The [`Attribute`](enum.Attribute.html) enum: //! **Displayable**
//!
//! [`Attribute`](enum.Attribute.html) implements [Display](https://doc.rust-lang.org/beta/std/fmt/trait.Display.html) and therefore it can be formatted like:
//! //!
//! ```no_run //! ```no_run
//! use crossterm::style::Attribute; //! use crossterm::style::Attribute;
@ -99,7 +112,6 @@ use std::fmt::Display;
use crate::impl_display; use crate::impl_display;
use crate::utils::Command; use crate::utils::Command;
#[cfg(windows)] #[cfg(windows)]
use crate::Result; use crate::Result;

View File

@ -4,7 +4,7 @@ use std::fmt::Display;
use crate::style::{Attribute, Color, StyledContent}; use crate::style::{Attribute, Color, StyledContent};
/// A content style. /// The style that can be put on content.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ContentStyle { pub struct ContentStyle {
/// The foreground color. /// The foreground color.

View File

@ -4,13 +4,12 @@ use std::fmt::{self, Display, Formatter};
use std::result; use std::result;
use crate::queue; use crate::queue;
use crate::style::{ use crate::style::{
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor, Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor,
SetForegroundColor, Styler, SetForegroundColor, Styler,
}; };
/// A styled content. /// The style with the content to be styled.
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -180,10 +180,11 @@ impl From<Colored> for u16 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::style::sys::windows::set_foreground_color;
use super::{ use super::{
Color, Colored, BG_INTENSITY, BG_RED, FG_INTENSITY, FG_RED, ORIGINAL_CONSOLE_COLOR, Color, Colored, BG_INTENSITY, BG_RED, FG_INTENSITY, FG_RED, ORIGINAL_CONSOLE_COLOR,
}; };
use crate::style::sys::windows::set_foreground_color;
#[test] #[test]
fn test_parse_fg_color() { fn test_parse_fg_color() {

View File

@ -2,11 +2,9 @@
pub use self::command::{Command, ExecutableCommand, Output, QueueableCommand}; pub use self::command::{Command, ExecutableCommand, Output, QueueableCommand};
pub use self::error::{ErrorKind, Result}; pub use self::error::{ErrorKind, Result};
#[cfg(windows)]
pub use self::functions::supports_ansi;
mod command; mod command;
mod error; mod error;
mod functions; pub(crate) mod functions;
pub(crate) mod macros; pub(crate) mod macros;
pub(crate) mod sys; pub(crate) mod sys;

View File

@ -1,7 +1,7 @@
use std::fmt::Display; use std::fmt::Display;
use std::io::Write; use std::io::Write;
use crate::{execute, impl_display, queue, write_cout}; use crate::{execute, queue, write_cout};
use super::error::Result; use super::error::Result;
@ -93,13 +93,13 @@ where
} }
} }
/// When executed, this command will output the given string to the terminal. /// When executed, this command will output the given displayable to the buffer.
/// ///
/// See `crossterm/examples/command.rs` for more information on how to execute commands. /// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Output(pub String); pub struct Output<T: Display + Clone>(pub T);
impl Command for Output { impl<T: Display + Clone> Command for Output<T> {
type AnsiType = String; type AnsiType = T;
fn ansi_code(&self) -> Self::AnsiType { fn ansi_code(&self) -> Self::AnsiType {
return self.0.clone(); return self.0.clone();
@ -112,4 +112,11 @@ impl Command for Output {
} }
} }
impl_display!(for Output); impl<T: Display + Clone> Display for Output<T> {
fn fmt(
&self,
f: &mut ::std::fmt::Formatter<'_>,
) -> ::std::result::Result<(), ::std::fmt::Error> {
write!(f, "{}", self.ansi_code())
}
}

View File

@ -1,10 +1,12 @@
/// Append a the first few characters of an ANSI escape code to the given string. /// Append a the first few characters of an ANSI escape code to the given string.
#[macro_export] #[macro_export]
#[doc(hidden)]
macro_rules! csi { macro_rules! csi {
($( $l:expr ),*) => { concat!("\x1B[", $( $l ),*) }; ($( $l:expr ),*) => { concat!("\x1B[", $( $l ),*) };
} }
/// Write a string to standard output whereafter the stdout will be flushed. /// Write a string to standard output whereafter the stdout will be flushed.
#[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! write_cout { macro_rules! write_cout {
($write:expr, $string:expr) => {{ ($write:expr, $string:expr) => {{
@ -77,7 +79,7 @@ macro_rules! queue {
$( $(
#[cfg(windows)] #[cfg(windows)]
{ {
if $crate::utils::supports_ansi() { if $crate::supports_ansi() {
match write!($write, "{}", $command.ansi_code()) { match write!($write, "{}", $command.ansi_code()) {
Err(e) => { Err(e) => {
error = Some(Err($crate::ErrorKind::from(e))); error = Some(Err($crate::ErrorKind::from(e)));
@ -149,7 +151,7 @@ macro_rules! execute {
$( $(
#[cfg(windows)] #[cfg(windows)]
{ {
if $crate::utils::supports_ansi() { if $crate::supports_ansi() {
if let Err(e) = write_cout!($write, $command.ansi_code()) { if let Err(e) = write_cout!($write, $command.ansi_code()) {
error = Some($crate::ErrorKind::from(e)); error = Some($crate::ErrorKind::from(e));
}; };
@ -175,6 +177,7 @@ macro_rules! execute {
}} }}
} }
#[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! impl_display { macro_rules! impl_display {
(for $($t:ty),+) => { (for $($t:ty),+) => {
@ -187,6 +190,7 @@ macro_rules! impl_display {
} }
} }
#[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! impl_from { macro_rules! impl_from {
($from:path, $to:expr) => { ($from:path, $to:expr) => {