Cleanup Some Mess for next Release (#304)
This commit is contained in:
parent
c23a6ddf38
commit
f2a4df20db
67
CHANGELOG.md
67
CHANGELOG.md
@ -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
|
||||
- Derive 'Copy' for 'KeyEvent'
|
||||
- Add the `EnableMouseCapture` and `EnableMouseCapture` commands
|
||||
- `cursor` module
|
||||
- Remove `TerminalCursor`, `cursor`, `Crossterm::cursor()`
|
||||
- Introduce static function `crossterm::cursor::position` in place of `TerminalCursor::pos`
|
||||
- Rename `Goto` to `MoveTo`
|
||||
- Rename `Up` to `MoveLeft`
|
||||
@ -14,34 +18,29 @@
|
||||
- Rename `BlinkOff` to `DisableBlinking`
|
||||
- Rename `ResetPos` to `ResetPosition`
|
||||
- Rename `SavePos` to `SavePosition`
|
||||
- Remove re-export cursor module types at root level, are now accessible from `crossterm::cursor`
|
||||
- `terminal`
|
||||
- Remove `Terminal`, `terminal`, `Crossterm::terminal()`
|
||||
- Introduce static function `crossterm::terminal::size` in place of `Terminal::size`
|
||||
- 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`
|
||||
- Rename `ObjectStyle` to `ContentStyle`. Now full names are used for methods.
|
||||
- Rename `StyledObject` to `StyledContent` and made members private.
|
||||
- Rename `ObjectStyle` to `ContentStyle`. Now full names are used for methods
|
||||
- Rename `StyledObject` to `StyledContent` and made members private
|
||||
- Rename `PrintStyledFont` to `PrintStyledContent`
|
||||
- Rename `attr` method to `attribute`.
|
||||
- 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
|
||||
- Made `Colored` private, user should use commands instead.
|
||||
- Made `Colored` private, user should use commands instead
|
||||
- Rename `SetFg` -> `SetForegroundColor`
|
||||
- Rename `SetBg` -> `SetBackgroundColor`
|
||||
- Rename `SetAttr` -> `SetAttribute`
|
||||
- Rename `ContentStyle::fg_color` -> `ContentStyle::foreground_color`
|
||||
- Rename `ContentStyle::bg_color` -> `ContentStyle::background_color`
|
||||
- Rename `ContentStyle::attrs` -> `ContentStyle::attributes`
|
||||
- Improve documentation
|
||||
- Unix terminal size calculation with TPUT
|
||||
|
||||
# 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.
|
||||
- All these modules are public
|
||||
- No public API breaking changes
|
||||
@ -58,34 +57,27 @@
|
||||
|
||||
## `crossterm_cursor` 0.4.0
|
||||
|
||||
- Internal refactoring ([PR #2](https://github.com/crossterm-rs/crossterm-cursor/pull/2))
|
||||
- Improved public documentation
|
||||
- `sys` module is no longer public
|
||||
- Fixed examples link ([PR #6](https://github.com/crossterm-rs/crossterm-cursor/pull/6))
|
||||
- Fix 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))
|
||||
- Removed 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))
|
||||
- Remove all references to the crossterm book ([PR #8](https://github.com/crossterm-rs/crossterm-cursor/pull/8))
|
||||
- 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))
|
||||
|
||||
## `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 `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))
|
||||
- Mouse coordinates synchronized with the cursor ([PR #7](https://github.com/crossterm-rs/crossterm-input/pull/7))
|
||||
- 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))
|
||||
- Refactored UNIX readers ([PR #9](https://github.com/crossterm-rs/crossterm-input/pull/9))
|
||||
- Fix bug that read sync didn't block (Windows) ([PR #8](https://github.com/crossterm-rs/crossterm-input/pull/8))
|
||||
- Refactor UNIX readers ([PR #9](https://github.com/crossterm-rs/crossterm-input/pull/9))
|
||||
- AsyncReader produces mouse events
|
||||
- One reading thread per application, not per `AsyncReader`
|
||||
- Cursor position no longer consumed by another `AsyncReader`
|
||||
- Implemented sync reader for read_char (requires raw mode)
|
||||
- Fixed `SIGTTIN` when executed under the LLDB
|
||||
- Added mio for reading from FD and more efficient polling (UNIX only)
|
||||
- Implement sync reader for read_char (requires raw mode)
|
||||
- Fix `SIGTTIN` when executed under the LLDB
|
||||
- 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))
|
||||
- Top is always reported as `0`
|
||||
|
||||
@ -103,10 +95,9 @@
|
||||
|
||||
## `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
|
||||
- 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 `StyledObject`, used stdout for resetting terminal color
|
||||
- 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`
|
||||
* Maybe I forgot something, a lot of functions have changed
|
||||
- Removed all unwraps/expects from library
|
||||
- Added KeyEvent::Enter and KeyEvent::Tab: [added-key-event-enter], [added-key-event-tab]
|
||||
- Synced set/get terminal size behaviour: [fixed-get-set-terminal-size]
|
||||
- Add KeyEvent::Enter and KeyEvent::Tab: [added-key-event-enter], [added-key-event-tab]
|
||||
- Sync set/get terminal size behaviour: [fixed-get-set-terminal-size]
|
||||
- Method renames:
|
||||
* `AsyncReader::stop_reading()` to `stop()`
|
||||
* `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.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)
|
||||
- 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)
|
||||
- Fix showing, hiding cursor windows implementation
|
||||
- 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)
|
||||
- Added some derive implementation
|
||||
- Add some derives
|
||||
|
||||
# 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
|
||||
|
||||
- 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
|
||||
|
||||
|
39
README.md
39
README.md
@ -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,
|
||||
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
|
||||
|
||||
* [Features](#features)
|
||||
@ -30,6 +43,7 @@ see [Tested Terminals](#tested-terminals) for more info).
|
||||
- Multi-threaded (send, sync)
|
||||
- Detailed documentation
|
||||
- Few dependencies
|
||||
- Full control over output buffer
|
||||
- Cursor (feature `cursor`)
|
||||
- Move the cursor N times (up, down, left, right)
|
||||
- Set/get the cursor position
|
||||
@ -94,22 +108,31 @@ crossterm = "0.12"
|
||||
```rust
|
||||
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<()> {
|
||||
// using the macro
|
||||
execute!(
|
||||
stdout(),
|
||||
// Blue foreground
|
||||
SetFg(Color::Blue),
|
||||
// Red background
|
||||
SetBg(Color::Red),
|
||||
Output("Styled text here.".to_string()),
|
||||
// Reset to default colors
|
||||
SetForegroundColor(Color::Blue),
|
||||
SetBackgroundColor(Color::Red),
|
||||
Output("Styled text here."),
|
||||
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
|
||||
|
||||
All features are enabled by default. You can disable default features and enable some of them only.
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
16
src/input.rs
16
src/input.rs
@ -205,7 +205,7 @@ impl From<InternalEvent> for Option<InputEvent> {
|
||||
/// ```no_run
|
||||
/// // You can replace the following line with `use crossterm::...;`
|
||||
/// // 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<()> {
|
||||
/// let input = TerminalInput::new();
|
||||
@ -261,7 +261,7 @@ impl TerminalInput {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// let input = crossterm::input();
|
||||
/// let input = crossterm::input::input();
|
||||
/// match input.read_line() {
|
||||
/// Ok(s) => println!("string typed: {}", s),
|
||||
/// Err(e) => println!("error: {}", e),
|
||||
@ -276,7 +276,7 @@ impl TerminalInput {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// let input = crossterm::input();
|
||||
/// let input = crossterm::input::input();
|
||||
/// match input.read_char() {
|
||||
/// Ok(c) => println!("character pressed: {}", c),
|
||||
/// Err(e) => println!("error: {}", e),
|
||||
@ -302,7 +302,7 @@ impl TerminalInput {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::{thread, time::Duration};
|
||||
/// use crossterm::input;
|
||||
/// use crossterm::input::input;
|
||||
///
|
||||
/// let mut async_stdin = input().read_async();
|
||||
///
|
||||
@ -335,8 +335,9 @@ impl TerminalInput {
|
||||
///
|
||||
/// ```no_run
|
||||
/// 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 {
|
||||
/// if let Some(key_event) = async_stdin.next() {
|
||||
@ -360,8 +361,9 @@ impl TerminalInput {
|
||||
///
|
||||
/// ```no_run
|
||||
/// 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 {
|
||||
/// if let Some(key_event) = sync_stdin.next() {
|
||||
@ -397,7 +399,7 @@ impl TerminalInput {
|
||||
/// ```no_run
|
||||
/// // You can replace the following line with `use crossterm::...;`
|
||||
/// // 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<()> {
|
||||
/// let input = input();
|
||||
|
@ -39,7 +39,7 @@ pub(crate) trait Input {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// let input = crossterm::input();
|
||||
/// let input = crossterm::input::input();
|
||||
/// match input.read_line() {
|
||||
/// Ok(s) => println!("string typed: {}", s),
|
||||
/// Err(e) => println!("error: {}", e),
|
||||
|
@ -92,7 +92,7 @@ impl Input for UnixInput {
|
||||
/// ```no_run
|
||||
/// use std::{thread, time::Duration};
|
||||
///
|
||||
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen};
|
||||
/// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("Press 'ESC' to quit.");
|
||||
@ -221,7 +221,7 @@ impl Iterator for AsyncReader {
|
||||
/// ```no_run
|
||||
/// use std::{thread, time::Duration};
|
||||
///
|
||||
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen};
|
||||
/// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("Press 'ESC' to quit.");
|
||||
|
@ -29,13 +29,9 @@ use winapi::um::{
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::input::{input::Input, InputEvent, KeyEvent, MouseButton};
|
||||
use crate::utils::Result;
|
||||
|
||||
use super::{
|
||||
super::{InputEvent, KeyEvent, MouseButton},
|
||||
Input,
|
||||
};
|
||||
|
||||
const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008;
|
||||
|
||||
lazy_static! {
|
||||
@ -172,7 +168,7 @@ impl Input for WindowsInput {
|
||||
/// ```no_run
|
||||
/// use std::{thread, time::Duration};
|
||||
///
|
||||
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen};
|
||||
/// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("Press 'ESC' to quit.");
|
||||
@ -245,7 +241,7 @@ impl Iterator for SyncReader {
|
||||
/// ```no_run
|
||||
/// use std::{thread, time::Duration};
|
||||
///
|
||||
/// use crossterm::{input, InputEvent, KeyEvent, RawScreen};
|
||||
/// use crossterm::{screen::RawScreen, input::{input, InputEvent, KeyEvent}};
|
||||
///
|
||||
/// fn main() {
|
||||
/// 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
|
||||
// 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
|
||||
@ -554,10 +550,12 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
|
||||
EventFlags::PressOrRelease => {
|
||||
// Single click
|
||||
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 => {
|
||||
// left click
|
||||
Some(crate::MouseEvent::Press(
|
||||
Some(crate::input::MouseEvent::Press(
|
||||
MouseButton::Left,
|
||||
xpos as u16,
|
||||
ypos as u16,
|
||||
@ -565,7 +563,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
|
||||
}
|
||||
ButtonState::RightmostButtonPressed => {
|
||||
// right click
|
||||
Some(crate::MouseEvent::Press(
|
||||
Some(crate::input::MouseEvent::Press(
|
||||
MouseButton::Right,
|
||||
xpos as u16,
|
||||
ypos as u16,
|
||||
@ -573,7 +571,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
|
||||
}
|
||||
ButtonState::FromLeft2ndButtonPressed => {
|
||||
// middle click
|
||||
Some(crate::MouseEvent::Press(
|
||||
Some(crate::input::MouseEvent::Press(
|
||||
MouseButton::Middle,
|
||||
xpos as u16,
|
||||
ypos as u16,
|
||||
@ -586,7 +584,7 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::MouseEve
|
||||
// Click + Move
|
||||
// NOTE (@imdaveho) only register when mouse is not released
|
||||
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 {
|
||||
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
|
||||
// if `button_state` is negative then the wheel was rotated backward, toward the user.
|
||||
if event.button_state != ButtonState::Negative {
|
||||
Some(crate::MouseEvent::Press(
|
||||
Some(crate::input::MouseEvent::Press(
|
||||
MouseButton::WheelUp,
|
||||
xpos as u16,
|
||||
ypos as u16,
|
||||
))
|
||||
} else {
|
||||
Some(crate::MouseEvent::Press(
|
||||
Some(crate::input::MouseEvent::Press(
|
||||
MouseButton::WheelDown,
|
||||
xpos as u16,
|
||||
ypos as u16,
|
||||
|
138
src/lib.rs
138
src/lib.rs
@ -16,7 +16,9 @@
|
||||
//! ## Command API
|
||||
//!
|
||||
//! 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.
|
||||
//! * 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
|
||||
//! 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
|
||||
//! 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
|
||||
//!
|
||||
//! Because `flush` is a heavy system call we can instead `write` the commands to the `stdout` without flushing.
|
||||
//! When can do a `flush` when we do want to execute the commands.
|
||||
//! Flushing bytes to the terminal buffer is a heavy system call. If we perform a lot of actions with the terminal,
|
||||
//! 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
|
||||
//! to the terminal `stdout` and `flush` the `stdout` at every frame. By doing this you can make efficient use of the
|
||||
//! terminal buffer and get better performance because you are not calling `flush` after every command.
|
||||
//! Crossterm offers the possibility to do this with `queue`.
|
||||
//! With `queue` you can queue commands, and when you call [Write::flush][flush] these commands will be executed.
|
||||
//!
|
||||
//! 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
|
||||
//! A simple demonstration that shows the command API in action with cursor commands.
|
||||
//!
|
||||
//! Functions:
|
||||
//! **Functions**
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::io::Write;
|
||||
//! use std::io::{Write, stdout};
|
||||
//! use crossterm::{QueueableCommand, cursor};
|
||||
//!
|
||||
//! let mut stdout = std::io::stdout();
|
||||
//! let mut stdout = stdout();
|
||||
//! stdout.queue(cursor::MoveTo(5,5));
|
||||
//!
|
||||
//! // some other code ...
|
||||
@ -62,58 +103,68 @@
|
||||
//! 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))`.
|
||||
//!
|
||||
//! Macros:
|
||||
//! **Macros**
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::io::Write;
|
||||
//! use std::io::{Write, stdout};
|
||||
//! use crossterm::{queue, QueueableCommand, cursor};
|
||||
//!
|
||||
//! let mut stdout = std::io::stdout();
|
||||
//! let mut stdout = stdout();
|
||||
//! queue!(stdout, cursor::MoveTo(5, 5));
|
||||
//!
|
||||
//! // some other code ...
|
||||
//!
|
||||
//! // move operation is performed only if we flush the buffer.
|
||||
//! 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.
|
||||
//!
|
||||
//! ## Direct Execution
|
||||
//!
|
||||
//! If you want to execute commands directly, this is also possible. You don't have to flush the 'stdout',
|
||||
//! as described above. This is fine if you are not executing lots of commands.
|
||||
//! For many applications it is not at all important to be efficient with 'flush' operations.
|
||||
//! 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
|
||||
//!
|
||||
//! Functions:
|
||||
//! **Functions**
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::io::Write;
|
||||
//! use std::io::{Write, stdout};
|
||||
//! use crossterm::{ExecutableCommand, cursor};
|
||||
//!
|
||||
//! let mut stdout = std::io::stdout();
|
||||
//! let mut stdout = stdout();
|
||||
//! 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
|
||||
//! use std::io::Write;
|
||||
//! use std::io::{Write, stdout};
|
||||
//! use crossterm::{execute, ExecutableCommand, cursor};
|
||||
//!
|
||||
//! let mut stdout = std::io::stdout();
|
||||
//! let mut stdout = stdout();
|
||||
//! 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
|
||||
//!
|
||||
//! Print a rectangle colored with magenta and use both direct execution and lazy execution.
|
||||
//!
|
||||
//! Functions:
|
||||
//! **Functions**
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::io::{stdout, Write};
|
||||
@ -130,6 +181,7 @@
|
||||
//! for y in 0..40 {
|
||||
//! for x in 0..150 {
|
||||
//! if (y == 0 || y == 40 - 1) || (x == 0 || x == 150 - 1) {
|
||||
//! // in this loop we are more efficient by not flushing the buffer.
|
||||
//! stdout
|
||||
//! .queue(cursor::MoveTo(x,y))?
|
||||
//! .queue(style::PrintStyledContent( "█".magenta()))?;
|
||||
@ -141,7 +193,7 @@
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Macros:
|
||||
//! **Macros:**
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::io::{stdout, Write};
|
||||
@ -158,6 +210,7 @@
|
||||
//! for y in 0..40 {
|
||||
//! for x in 0..150 {
|
||||
//! 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()))?;
|
||||
//! }
|
||||
//! }
|
||||
@ -166,35 +219,30 @@
|
||||
//! 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 self::crossterm::Crossterm;
|
||||
#[cfg(windows)]
|
||||
pub use utils::functions::supports_ansi;
|
||||
|
||||
mod crossterm;
|
||||
|
||||
/// A functionality to work with the terminal cursor
|
||||
/// A module to work with the terminal cursor
|
||||
#[cfg(feature = "cursor")]
|
||||
pub mod cursor;
|
||||
/// A functionality to read the input events.
|
||||
/// A module to read the input events.
|
||||
#[cfg(feature = "input")]
|
||||
pub mod input;
|
||||
/// A functionality to work with the terminal screen.
|
||||
/// A module to work with the terminal screen.
|
||||
#[cfg(feature = "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")]
|
||||
pub mod style;
|
||||
/// A functionality to work with the terminal.
|
||||
/// A module to work with the terminal.
|
||||
#[cfg(feature = "terminal")]
|
||||
pub mod terminal;
|
||||
/// Shared utilities.
|
||||
|
@ -76,7 +76,7 @@ mod sys;
|
||||
/// Alternate screen with raw mode enabled:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use crossterm::{AlternateScreen, Result};
|
||||
/// use crossterm::{screen::{AlternateScreen}, Result};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// let _alternate = AlternateScreen::to_alternate(true)?;
|
||||
@ -145,7 +145,7 @@ impl Drop for AlternateScreen {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::{stdout, Write};
|
||||
/// use crossterm::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen};
|
||||
/// use crossterm::{execute, Result,screen::{EnterAlternateScreen, LeaveAlternateScreen}};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// execute!(stdout(), EnterAlternateScreen)?;
|
||||
@ -181,7 +181,7 @@ impl Command for EnterAlternateScreen {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::{stdout, Write};
|
||||
/// use crossterm::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen};
|
||||
/// use crossterm::{execute, Result, screen::{EnterAlternateScreen, LeaveAlternateScreen}};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// execute!(stdout(), EnterAlternateScreen)?;
|
||||
|
@ -3,7 +3,7 @@ pub(crate) use ansi::AnsiAlternateScreen;
|
||||
pub(crate) use windows::WinApiAlternateScreen;
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate::utils::supports_ansi;
|
||||
use crate::supports_ansi;
|
||||
use crate::utils::Result;
|
||||
|
||||
pub(crate) mod ansi;
|
||||
|
@ -15,7 +15,7 @@ use super::sys;
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use crossterm::{RawScreen, Result};
|
||||
/// use crossterm::{screen::RawScreen, Result};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// let _raw = RawScreen::into_raw_mode()?;
|
||||
@ -27,7 +27,7 @@ use super::sys;
|
||||
/// Do not disable the raw mode implicitly:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use crossterm::{RawScreen, Result};
|
||||
/// use crossterm::{screen::RawScreen, Result};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// let mut raw = RawScreen::into_raw_mode()?;
|
||||
@ -93,7 +93,7 @@ impl RawScreen {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::stdout;
|
||||
/// use crossterm::{IntoRawMode, Result};
|
||||
/// use crossterm::{screen::IntoRawMode, Result};
|
||||
///
|
||||
/// fn main() -> Result<()> {
|
||||
/// let stdout = stdout();
|
||||
|
24
src/style.rs
24
src/style.rs
@ -16,10 +16,14 @@
|
||||
//! * [Attribute](enum.Attribute.html#platform-specific-notes)
|
||||
//!
|
||||
//! ## Examples
|
||||
//! A few examples of how to use the style module.
|
||||
//!
|
||||
//! ### Colors
|
||||
//! How to change the terminal text color.
|
||||
//!
|
||||
//! The command API:
|
||||
//! **Command API**
|
||||
//!
|
||||
//! Using the Command API to color text.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! 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
|
||||
//! use crossterm::style::Colorize;
|
||||
@ -51,8 +57,11 @@
|
||||
//! ```
|
||||
//!
|
||||
//! ### Attributes
|
||||
//! How to appy terminal attributes to text.
|
||||
//!
|
||||
//! The command API:
|
||||
//! **Command API**
|
||||
//!
|
||||
//! Using the Command API to set attributes.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! 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
|
||||
//! use crossterm::style::Styler;
|
||||
@ -82,7 +93,9 @@
|
||||
//! 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
|
||||
//! use crossterm::style::Attribute;
|
||||
@ -99,7 +112,6 @@ use std::fmt::Display;
|
||||
|
||||
use crate::impl_display;
|
||||
use crate::utils::Command;
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate::Result;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use std::fmt::Display;
|
||||
|
||||
use crate::style::{Attribute, Color, StyledContent};
|
||||
|
||||
/// A content style.
|
||||
/// The style that can be put on content.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ContentStyle {
|
||||
/// The foreground color.
|
||||
|
@ -4,13 +4,12 @@ use std::fmt::{self, Display, Formatter};
|
||||
use std::result;
|
||||
|
||||
use crate::queue;
|
||||
|
||||
use crate::style::{
|
||||
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor,
|
||||
SetForegroundColor, Styler,
|
||||
};
|
||||
|
||||
/// A styled content.
|
||||
/// The style with the content to be styled.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -180,10 +180,11 @@ impl From<Colored> for u16 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::style::sys::windows::set_foreground_color;
|
||||
|
||||
use super::{
|
||||
Color, Colored, BG_INTENSITY, BG_RED, FG_INTENSITY, FG_RED, ORIGINAL_CONSOLE_COLOR,
|
||||
};
|
||||
use crate::style::sys::windows::set_foreground_color;
|
||||
|
||||
#[test]
|
||||
fn test_parse_fg_color() {
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
pub use self::command::{Command, ExecutableCommand, Output, QueueableCommand};
|
||||
pub use self::error::{ErrorKind, Result};
|
||||
#[cfg(windows)]
|
||||
pub use self::functions::supports_ansi;
|
||||
|
||||
mod command;
|
||||
mod error;
|
||||
mod functions;
|
||||
pub(crate) mod functions;
|
||||
pub(crate) mod macros;
|
||||
pub(crate) mod sys;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::{execute, impl_display, queue, write_cout};
|
||||
use crate::{execute, queue, write_cout};
|
||||
|
||||
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.
|
||||
pub struct Output(pub String);
|
||||
pub struct Output<T: Display + Clone>(pub T);
|
||||
|
||||
impl Command for Output {
|
||||
type AnsiType = String;
|
||||
impl<T: Display + Clone> Command for Output<T> {
|
||||
type AnsiType = T;
|
||||
|
||||
fn ansi_code(&self) -> Self::AnsiType {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
/// Append a the first few characters of an ANSI escape code to the given string.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! csi {
|
||||
($( $l:expr ),*) => { concat!("\x1B[", $( $l ),*) };
|
||||
}
|
||||
|
||||
/// Write a string to standard output whereafter the stdout will be flushed.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! write_cout {
|
||||
($write:expr, $string:expr) => {{
|
||||
@ -77,7 +79,7 @@ macro_rules! queue {
|
||||
$(
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if $crate::utils::supports_ansi() {
|
||||
if $crate::supports_ansi() {
|
||||
match write!($write, "{}", $command.ansi_code()) {
|
||||
Err(e) => {
|
||||
error = Some(Err($crate::ErrorKind::from(e)));
|
||||
@ -149,7 +151,7 @@ macro_rules! execute {
|
||||
$(
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if $crate::utils::supports_ansi() {
|
||||
if $crate::supports_ansi() {
|
||||
if let Err(e) = write_cout!($write, $command.ansi_code()) {
|
||||
error = Some($crate::ErrorKind::from(e));
|
||||
};
|
||||
@ -175,6 +177,7 @@ macro_rules! execute {
|
||||
}}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_display {
|
||||
(for $($t:ty),+) => {
|
||||
@ -187,6 +190,7 @@ macro_rules! impl_display {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_from {
|
||||
($from:path, $to:expr) => {
|
||||
|
Loading…
Reference in New Issue
Block a user