minicrossterm/crossterm_cursor/src/cursor/cursor.rs
2019-09-20 23:50:53 +02:00

343 lines
9.5 KiB
Rust

//! A module that contains all the actions related to cursor movement in the terminal.
//! Like: moving the cursor position; saving and resetting the cursor position; hiding showing and control the blinking of the cursor.
#[cfg(windows)]
use crossterm_utils::supports_ansi;
use crossterm_utils::{impl_display, Command, Result};
use super::ansi_cursor::{self, AnsiCursor};
#[cfg(windows)]
use super::winapi_cursor::WinApiCursor;
use super::ITerminalCursor;
/// Allows you to preform actions with the terminal cursor.
///
/// # Features:
///
/// - Moving n times Up, Down, Left, Right
/// - Goto a certain position
/// - Get cursor position
/// - Storing the current cursor position and resetting to that stored cursor position later
/// - Hiding and showing the cursor
/// - Control over blinking of the terminal cursor (only some terminals are supporting this)
///
/// Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
///
/// Check `/examples/cursor` in the library for more specific examples.
pub struct TerminalCursor {
#[cfg(windows)]
cursor: Box<(dyn ITerminalCursor + Sync + Send)>,
#[cfg(unix)]
cursor: AnsiCursor,
}
impl TerminalCursor {
/// Create new `TerminalCursor` instance whereon cursor related actions can be performed.
pub fn new() -> TerminalCursor {
#[cfg(windows)]
let cursor = if supports_ansi() {
Box::from(AnsiCursor::new()) as Box<(dyn ITerminalCursor + Sync + Send)>
} else {
WinApiCursor::new() as Box<(dyn ITerminalCursor + Sync + Send)>
};
#[cfg(unix)]
let cursor = AnsiCursor::new();
TerminalCursor { cursor }
}
/// Goto some position (x,y) in the terminal.
///
/// # Remarks
/// position is 0-based, which means we start counting at 0.
pub fn goto(&self, x: u16, y: u16) -> Result<()> {
self.cursor.goto(x, y)
}
/// Get current cursor position (x,y) in the terminal.
///
/// # Remarks
/// position is 0-based, which means we start counting at 0.
pub fn pos(&self) -> Result<(u16, u16)> {
self.cursor.pos()
}
/// Move the current cursor position `n` times up.
pub fn move_up(&mut self, count: u16) -> Result<&mut TerminalCursor> {
self.cursor.move_up(count)?;
Ok(self)
}
/// Move the current cursor position `n` times right.
pub fn move_right(&mut self, count: u16) -> Result<&mut TerminalCursor> {
self.cursor.move_right(count)?;
Ok(self)
}
/// Move the current cursor position `n` times down.
pub fn move_down(&mut self, count: u16) -> Result<&mut TerminalCursor> {
self.cursor.move_down(count)?;
Ok(self)
}
/// Move the current cursor position `n` times left.
pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> {
self.cursor.move_left(count)?;
Ok(self)
}
/// Save cursor position for recall later.
///
/// Note that this position is stored program based not per instance of the `Cursor` struct.
pub fn save_position(&self) -> Result<()> {
self.cursor.save_position()
}
/// Return to saved cursor position
pub fn restore_position(&self) -> Result<()> {
self.cursor.restore_position()
}
/// Hide de cursor in the console.
pub fn hide(&self) -> Result<()> {
self.cursor.hide()
}
/// Show the cursor in the console.
pub fn show(&self) -> Result<()> {
self.cursor.show()
}
/// Enable or disable blinking of the terminal.
///
/// # Remarks
/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
pub fn blink(&self, blink: bool) -> Result<()> {
self.cursor.blink(blink)
}
}
/// Get a `TerminalCursor` instance whereon cursor related actions can be performed.
pub fn cursor() -> TerminalCursor {
TerminalCursor::new()
}
/// When executed, this command will move the cursor position to the given `x` and `y` in the terminal window.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Goto(pub u16, pub u16);
impl Command for Goto {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::get_goto_ansi(self.0, self.1)
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().goto(self.0, self.1)
}
}
/// When executed, this command will move the current cursor position `n` times up.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Up(pub u16);
impl Command for Up {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::get_move_up_ansi(self.0)
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().move_up(self.0)
}
}
/// When executed, this command will move the current cursor position `n` times down.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Down(pub u16);
impl Command for Down {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::get_move_down_ansi(self.0)
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().move_down(self.0)
}
}
/// When executed, this command will move the current cursor position `n` times left.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Left(pub u16);
impl Command for Left {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::get_move_left_ansi(self.0)
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().move_left(self.0)
}
}
/// When executed, this command will move the current cursor position `n` times right.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Right(pub u16);
impl Command for Right {
type AnsiType = String;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::get_move_right_ansi(self.0)
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().move_right(self.0)
}
}
/// When executed, this command will save the cursor position for recall later.
///
/// Note that this position is stored program based not per instance of the `Cursor` struct.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct SavePos;
impl Command for SavePos {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::SAVE_POS_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().save_position()
}
}
/// When executed, this command will return the cursor position to the saved cursor position
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct ResetPos;
impl Command for ResetPos {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::RESTORE_POS_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().restore_position()
}
}
/// When executed, this command will hide de cursor in the console.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Hide;
impl Command for Hide {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::HIDE_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().hide()
}
}
/// When executed, this command will show de cursor in the console.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct Show;
impl Command for Show {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::SHOW_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
WinApiCursor::new().show()
}
}
/// When executed, this command will enable cursor blinking.
///
/// # Remarks
/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct BlinkOn;
impl Command for BlinkOn {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::BLINK_ON_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
Ok(())
}
}
/// When executed, this command will disable cursor blinking.
///
/// # Remarks
/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
///
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
pub struct BlinkOff;
impl Command for BlinkOff {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi_cursor::BLINK_OFF_ANSI
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
Ok(())
}
}
impl_display!(for Goto);
impl_display!(for Up);
impl_display!(for Down);
impl_display!(for Left);
impl_display!(for Right);
impl_display!(for SavePos);
impl_display!(for ResetPos);
impl_display!(for Hide);
impl_display!(for Show);
impl_display!(for BlinkOn);
impl_display!(for BlinkOff);