minicrossterm/crossterm_cursor/src/cursor/cursor.rs
Timon ad74f6b524
Introduced: Crossterm Workspace and feature flags. (#84)
* Introduced: crossterm workspace, feature flags.
2019-01-27 21:16:14 +01:00

166 lines
5.6 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.
use super::*;
use std::sync::Arc;
use crossterm_utils::{Result, TerminalOutput};
#[cfg(windows)]
use crossterm_utils::get_module;
/// 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 an 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.
///
/// # Remarks
///
/// When you want to use 'cursor' on 'alternate screen' use the 'crossterm_screen' crate.
pub struct TerminalCursor<'stdout> {
terminal_cursor: Box<ITerminalCursor + Sync + Send>,
stdout: Option<&'stdout Arc<TerminalOutput>>,
}
impl<'stdout> TerminalCursor<'stdout> {
/// Create new `TerminalCursor` instance whereon cursor related actions can be performed.
pub fn new() -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")]
let cursor = get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(),
AnsiCursor::new(),
)
.unwrap();
#[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
TerminalCursor {
terminal_cursor: cursor,
stdout: None,
}
}
/// Create a new instance of `TerminalCursor` whereon cursor related actions could be preformed on the given output.
///
/// # Remarks
///
/// Use this function when you want your terminal to operate with a specific output.
/// This could be useful when you have a screen which is in 'alternate mode',
/// and you want your actions from the `TerminalCursor`, created by this function, to operate on the 'alternate screen'.
///
/// You should checkout the 'crossterm_screen' crate for more information about this.
///
/// # Example
/// ```
/// let screen = Screen::default();
//
/// if let Ok(alternate) = screen.enable_alternate_modes(false) {
/// let terminal = TerminalCursor::from_output(&alternate.screen.stdout);
/// }
/// ```
pub fn from_output(stdout: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")]
let cursor = get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(),
AnsiCursor::new(),
)
.unwrap();
#[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
TerminalCursor {
terminal_cursor: cursor,
stdout: Some(stdout),
}
}
/// 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.terminal_cursor.goto(x, y, &self.stdout)
}
/// 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) -> (u16, u16) {
self.terminal_cursor.pos()
}
/// Move the current cursor position `n` times up.
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
self.terminal_cursor.move_up(count, &self.stdout).unwrap();
self
}
/// Move the current cursor position `n` times right.
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
self.terminal_cursor
.move_right(count, &self.stdout)
.unwrap();
self
}
/// Move the current cursor position `n` times down.
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
self.terminal_cursor.move_down(count, &self.stdout).unwrap();
self
}
/// Move the current cursor position `n` times left.
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
self.terminal_cursor.move_left(count, &self.stdout).unwrap();
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.terminal_cursor.save_position(&self.stdout)
}
/// Return to saved cursor position
pub fn reset_position(&self) -> Result<()> {
self.terminal_cursor.reset_position(&self.stdout)
}
/// Hide de cursor in the console.
pub fn hide(&self) -> Result<()> {
self.terminal_cursor.hide(&self.stdout)
}
/// Show the cursor in the console.
pub fn show(&self) -> Result<()> {
self.terminal_cursor.show(&self.stdout)
}
/// 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.terminal_cursor.blink(blink, &self.stdout)
}
}
/// Get a `TerminalCursor` instance whereon cursor related actions can be performed.
pub fn cursor() -> TerminalCursor<'static> {
TerminalCursor::new()
}