2019-11-19 07:50:57 +11:00
|
|
|
use std::{fmt::Display, io::Write};
|
2019-10-23 01:33:38 +11:00
|
|
|
|
2019-12-05 03:26:57 +11:00
|
|
|
use crate::{execute, queue};
|
2019-10-23 01:33:38 +11:00
|
|
|
|
|
|
|
use super::error::Result;
|
|
|
|
|
2019-12-05 03:26:57 +11:00
|
|
|
/// An interface for a command that performs an action on the terminal.
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Crossterm provides a set of commands,
|
|
|
|
/// and there is no immediate reason to implement a command yourself.
|
|
|
|
/// In order to understand how to use and execute commands,
|
|
|
|
/// it is recommended that you take a look at [Command Api](../#command-api) chapter.
|
2019-10-23 01:33:38 +11:00
|
|
|
pub trait Command {
|
|
|
|
type AnsiType: Display;
|
|
|
|
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Returns an ANSI code representation of this command.
|
|
|
|
/// An ANSI code can manipulate the terminal by writing it to the terminal buffer.
|
|
|
|
/// However, only Windows 10 and UNIX systems support this.
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// This method does not need to be accessed manually, as it is used by the crossterm's [Command Api](../#command-api)
|
2019-10-23 01:33:38 +11:00
|
|
|
fn ansi_code(&self) -> Self::AnsiType;
|
|
|
|
|
|
|
|
/// Execute this command.
|
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Windows versions lower than windows 10 do not support ANSI escape codes,
|
|
|
|
/// therefore a direct WinAPI call is made.
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// This method does not need to be accessed manually, as it is used by the crossterm's [Command Api](../#command-api)
|
2019-10-23 01:33:38 +11:00
|
|
|
#[cfg(windows)]
|
2020-07-20 20:58:04 +10:00
|
|
|
fn execute_winapi(&self, writer: impl FnMut() -> Result<()>) -> Result<()>;
|
2019-12-05 03:26:57 +11:00
|
|
|
|
|
|
|
/// Returns whether the ansi code representation of this command is supported by windows.
|
|
|
|
///
|
|
|
|
/// A list of supported ANSI escape codes
|
|
|
|
/// can be found [here](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences).
|
|
|
|
#[cfg(windows)]
|
|
|
|
fn is_ansi_code_supported(&self) -> bool {
|
2019-12-12 03:10:34 +11:00
|
|
|
super::ansi_support::supports_ansi()
|
2019-12-05 03:26:57 +11:00
|
|
|
}
|
2019-10-23 01:33:38 +11:00
|
|
|
}
|
|
|
|
|
2020-01-15 03:47:32 +11:00
|
|
|
impl<T: Command> Command for &T {
|
|
|
|
type AnsiType = T::AnsiType;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn ansi_code(&self) -> Self::AnsiType {
|
|
|
|
T::ansi_code(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[cfg(windows)]
|
2020-07-20 20:58:04 +10:00
|
|
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
|
|
|
T::execute_winapi(self, _writer)
|
2020-01-15 03:47:32 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
#[inline]
|
|
|
|
fn is_ansi_code_supported(&self) -> bool {
|
|
|
|
T::is_ansi_code_supported(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 03:26:57 +11:00
|
|
|
/// An interface for commands that can be queued for further execution.
|
2019-10-23 01:33:38 +11:00
|
|
|
pub trait QueueableCommand<T: Display>: Sized {
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Queues the given command for further execution.
|
2019-10-23 01:33:38 +11:00
|
|
|
fn queue(&mut self, command: impl Command<AnsiType = T>) -> Result<&mut Self>;
|
|
|
|
}
|
|
|
|
|
2019-12-05 03:26:57 +11:00
|
|
|
/// An interface for commands that are directly executed.
|
2019-10-23 01:33:38 +11:00
|
|
|
pub trait ExecutableCommand<T: Display>: Sized {
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Executes the given command directly.
|
2019-10-23 01:33:38 +11:00
|
|
|
fn execute(&mut self, command: impl Command<AnsiType = T>) -> Result<&mut Self>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, A> QueueableCommand<A> for T
|
|
|
|
where
|
|
|
|
A: Display,
|
|
|
|
T: Write,
|
|
|
|
{
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Queues the given command for further execution.
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
|
|
|
/// Queued commands will be executed in the following cases:
|
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// * When `flush` is called manually on the given type implementing `io::Write`.
|
|
|
|
/// * The terminal will `flush` automatically if the buffer is full.
|
|
|
|
/// * Each line is flushed in case of `stdout`, because it is line buffered.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
2019-10-23 01:33:38 +11:00
|
|
|
/// - [Command](./trait.Command.html)
|
|
|
|
///
|
|
|
|
/// The command that you want to queue for later execution.
|
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::io::{Write, stdout};
|
|
|
|
/// use crossterm::{Result, QueueableCommand, style::Print};
|
|
|
|
///
|
|
|
|
/// fn main() -> Result<()> {
|
|
|
|
/// let mut stdout = stdout();
|
|
|
|
///
|
|
|
|
/// // `Print` will executed executed when `flush` is called.
|
|
|
|
/// stdout
|
|
|
|
/// .queue(Print("foo 1\n".to_string()))?
|
|
|
|
/// .queue(Print("foo 2".to_string()))?;
|
|
|
|
///
|
|
|
|
/// // some other code (no execution happening here) ...
|
|
|
|
///
|
|
|
|
/// // when calling `flush` on `stdout`, all commands will be written to the stdout and therefore executed.
|
|
|
|
/// stdout.flush()?;
|
|
|
|
///
|
|
|
|
/// Ok(())
|
|
|
|
///
|
|
|
|
/// // ==== Output ====
|
|
|
|
/// // foo 1
|
|
|
|
/// // foo 2
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Have a look over at the [Command API](./#command-api) for more details.
|
|
|
|
///
|
|
|
|
/// # Notes
|
|
|
|
///
|
|
|
|
/// * In the case of UNIX and Windows 10, ANSI codes are written to the given 'writer'.
|
|
|
|
/// * In case of Windows versions lower than 10, a direct WinApi call will be made.
|
|
|
|
/// The reason for this is that Windows versions lower than 10 do not support ANSI codes,
|
|
|
|
/// and can therefore not be written to the given `writer`.
|
|
|
|
/// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
|
|
|
|
/// and [queue](./trait.QueueableCommand.html) for those old Windows versions.
|
2019-10-23 01:33:38 +11:00
|
|
|
fn queue(&mut self, command: impl Command<AnsiType = A>) -> Result<&mut Self> {
|
|
|
|
queue!(self, command)?;
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, A> ExecutableCommand<A> for T
|
|
|
|
where
|
|
|
|
A: Display,
|
|
|
|
T: Write,
|
|
|
|
{
|
2019-12-05 03:26:57 +11:00
|
|
|
/// Executes the given command directly.
|
|
|
|
///
|
|
|
|
/// The given command its ANSI escape code will be written and flushed onto `Self`.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// - [Command](./trait.Command.html)
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// The command that you want to execute directly.
|
2019-10-23 01:33:38 +11:00
|
|
|
///
|
2019-12-05 03:26:57 +11:00
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::io::{Write, stdout};
|
|
|
|
/// use crossterm::{Result, ExecutableCommand, style::Print};
|
|
|
|
///
|
|
|
|
/// fn main() -> Result<()> {
|
|
|
|
/// // will be executed directly
|
|
|
|
/// stdout()
|
|
|
|
/// .execute(Print("sum:\n".to_string()))?
|
|
|
|
/// .execute(Print(format!("1 + 1= {} ", 1 + 1)))?;
|
|
|
|
///
|
|
|
|
/// Ok(())
|
|
|
|
///
|
|
|
|
/// // ==== Output ====
|
|
|
|
/// // sum:
|
|
|
|
/// // 1 + 1 = 2
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Have a look over at the [Command API](./#command-api) for more details.
|
|
|
|
///
|
|
|
|
/// # Notes
|
|
|
|
///
|
|
|
|
/// * In the case of UNIX and Windows 10, ANSI codes are written to the given 'writer'.
|
|
|
|
/// * In case of Windows versions lower than 10, a direct WinApi call will be made.
|
|
|
|
/// The reason for this is that Windows versions lower than 10 do not support ANSI codes,
|
|
|
|
/// and can therefore not be written to the given `writer`.
|
|
|
|
/// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
|
|
|
|
/// and [queue](./trait.QueueableCommand.html) for those old Windows versions.
|
2019-10-23 01:33:38 +11:00
|
|
|
fn execute(&mut self, command: impl Command<AnsiType = A>) -> Result<&mut Self> {
|
|
|
|
execute!(self, command)?;
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
}
|