io::Result to crossterm::Result (#232)
This commit is contained in:
parent
e5ed617a7b
commit
05d28b4c5a
@ -25,14 +25,14 @@ pub fn show_cursor(show_cursor: bool) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pos() -> io::Result<(u16, u16)> {
|
pub fn pos() -> Result<(u16, u16)> {
|
||||||
unix::into_raw_mode()?;
|
unix::into_raw_mode()?;
|
||||||
let pos = pos_raw();
|
let pos = pos_raw();
|
||||||
unix::disable_raw_mode()?;
|
unix::disable_raw_mode()?;
|
||||||
pos
|
pos
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pos_raw() -> io::Result<(u16, u16)> {
|
pub fn pos_raw() -> Result<(u16, u16)> {
|
||||||
// Where is the cursor?
|
// Where is the cursor?
|
||||||
// Use `ESC [ 6 n`.
|
// Use `ESC [ 6 n`.
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module handles some logic for cursor interaction in the windows console.
|
//! This module handles some logic for cursor interaction in the windows console.
|
||||||
|
|
||||||
use std::io::{self, Result};
|
use std::io;
|
||||||
|
|
||||||
use winapi::{
|
use winapi::{
|
||||||
shared::minwindef::{FALSE, TRUE},
|
shared::minwindef::{FALSE, TRUE},
|
||||||
@ -8,6 +8,7 @@ use winapi::{
|
|||||||
um::winnt::HANDLE,
|
um::winnt::HANDLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crossterm_utils::Result;
|
||||||
pub use crossterm_winapi::{is_true, Coord, Handle, HandleType, ScreenBuffer};
|
pub use crossterm_winapi::{is_true, Coord, Handle, HandleType, ScreenBuffer};
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -32,7 +33,7 @@ pub struct Cursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor {
|
impl Cursor {
|
||||||
pub fn new() -> io::Result<Cursor> {
|
pub fn new() -> Result<Cursor> {
|
||||||
Ok(Cursor {
|
Ok(Cursor {
|
||||||
screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?),
|
screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?),
|
||||||
})
|
})
|
||||||
@ -44,25 +45,25 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the cursor position to the given x and y. Note that this is 0 based.
|
/// Set the cursor position to the given x and y. Note that this is 0 based.
|
||||||
pub fn goto(&self, x: i16, y: i16) -> io::Result<()> {
|
pub fn goto(&self, x: i16, y: i16) -> Result<()> {
|
||||||
if x < 0 || x >= <i16>::max_value() {
|
if x < 0 || x >= <i16>::max_value() {
|
||||||
return Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!(
|
format!(
|
||||||
"Argument Out of Range Exception when setting cursor position to X: {}",
|
"Argument Out of Range Exception when setting cursor position to X: {}",
|
||||||
x
|
x
|
||||||
),
|
),
|
||||||
));
|
))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if y < 0 || y >= <i16>::max_value() {
|
if y < 0 || y >= <i16>::max_value() {
|
||||||
return Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!(
|
format!(
|
||||||
"Argument Out of Range Exception when setting cursor position to Y: {}",
|
"Argument Out of Range Exception when setting cursor position to Y: {}",
|
||||||
y
|
y
|
||||||
),
|
),
|
||||||
));
|
))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let position = COORD { X: x, Y: y };
|
let position = COORD { X: x, Y: y };
|
||||||
@ -72,14 +73,14 @@ impl Cursor {
|
|||||||
**self.screen_buffer.get_handle(),
|
**self.screen_buffer.get_handle(),
|
||||||
position,
|
position,
|
||||||
)) {
|
)) {
|
||||||
return Err(io::Error::last_os_error());
|
Err(io::Error::last_os_error())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// change the cursor visibility.
|
/// change the cursor visibility.
|
||||||
pub fn set_visibility(&self, visable: bool) -> io::Result<()> {
|
pub fn set_visibility(&self, visable: bool) -> Result<()> {
|
||||||
let cursor_info = CONSOLE_CURSOR_INFO {
|
let cursor_info = CONSOLE_CURSOR_INFO {
|
||||||
dwSize: 100,
|
dwSize: 100,
|
||||||
bVisible: if visable { TRUE } else { FALSE },
|
bVisible: if visable { TRUE } else { FALSE },
|
||||||
@ -90,14 +91,14 @@ impl Cursor {
|
|||||||
**self.screen_buffer.get_handle(),
|
**self.screen_buffer.get_handle(),
|
||||||
&cursor_info,
|
&cursor_info,
|
||||||
)) {
|
)) {
|
||||||
return Err(io::Error::last_os_error());
|
Err(io::Error::last_os_error())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset to saved cursor position
|
/// Reset to saved cursor position
|
||||||
pub fn reset_to_saved_position() -> io::Result<()> {
|
pub fn reset_to_saved_position() -> Result<()> {
|
||||||
let cursor = Cursor::new()?;
|
let cursor = Cursor::new()?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -108,7 +109,7 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save current cursor position to recall later.
|
/// Save current cursor position to recall later.
|
||||||
pub fn save_cursor_pos() -> io::Result<()> {
|
pub fn save_cursor_pos() -> Result<()> {
|
||||||
let cursor = Cursor::new()?;
|
let cursor = Cursor::new()?;
|
||||||
let position = cursor.position()?;
|
let position = cursor.position()?;
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
//! A module that contains all the actions related to reading input from the terminal.
|
//! A module that contains all the actions related to reading input from the terminal.
|
||||||
//! Like reading a line, reading a character and reading asynchronously.
|
//! Like reading a line, reading a character and reading asynchronously.
|
||||||
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -31,7 +29,7 @@ mod windows_input;
|
|||||||
/// Unix is using the 'TTY' and windows is using 'libc' C functions to read the input.
|
/// Unix is using the 'TTY' and windows is using 'libc' C functions to read the input.
|
||||||
trait ITerminalInput {
|
trait ITerminalInput {
|
||||||
/// Read one character from the user input
|
/// Read one character from the user input
|
||||||
fn read_char(&self) -> io::Result<char>;
|
fn read_char(&self) -> Result<char>;
|
||||||
/// Read the input asynchronously from the user.
|
/// Read the input asynchronously from the user.
|
||||||
fn read_async(&self) -> AsyncReader;
|
fn read_async(&self) -> AsyncReader;
|
||||||
/// Read the input asynchronously until a certain character is hit.
|
/// Read the input asynchronously until a certain character is hit.
|
||||||
|
@ -57,7 +57,7 @@ impl TerminalInput {
|
|||||||
/// Err(e) => println!("error: {}", e),
|
/// Err(e) => println!("error: {}", e),
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn read_line(&self) -> io::Result<String> {
|
pub fn read_line(&self) -> Result<String> {
|
||||||
let mut rv = String::new();
|
let mut rv = String::new();
|
||||||
io::stdin().read_line(&mut rv)?;
|
io::stdin().read_line(&mut rv)?;
|
||||||
let len = rv.trim_end_matches(&['\r', '\n'][..]).len();
|
let len = rv.trim_end_matches(&['\r', '\n'][..]).len();
|
||||||
@ -74,7 +74,7 @@ impl TerminalInput {
|
|||||||
/// Err(e) => println!("error: {}", e),
|
/// Err(e) => println!("error: {}", e),
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn read_char(&self) -> io::Result<char> {
|
pub fn read_char(&self) -> Result<char> {
|
||||||
self.input.read_char()
|
self.input.read_char()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ impl UnixInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalInput for UnixInput {
|
impl ITerminalInput for UnixInput {
|
||||||
fn read_char(&self) -> io::Result<char> {
|
fn read_char(&self) -> Result<char> {
|
||||||
read_char_raw()
|
read_char_raw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,27 +42,23 @@ const ENABLE_MOUSE_MODE: u32 = 0x0010 | 0x0080 | 0x0008;
|
|||||||
static mut ORIG_MODE: u32 = 0;
|
static mut ORIG_MODE: u32 = 0;
|
||||||
|
|
||||||
impl ITerminalInput for WindowsInput {
|
impl ITerminalInput for WindowsInput {
|
||||||
fn read_char(&self) -> io::Result<char> {
|
fn read_char(&self) -> Result<char> {
|
||||||
// _getwch is without echo and _getwche is with echo
|
// _getwch is without echo and _getwche is with echo
|
||||||
let pressed_char = unsafe { _getwche() };
|
let pressed_char = unsafe { _getwche() };
|
||||||
|
|
||||||
// we could return error but maybe option to keep listening until valid character is inputted.
|
// we could return error but maybe option to keep listening until valid character is inputted.
|
||||||
if pressed_char == 0 || pressed_char == 0xe0 {
|
if pressed_char == 0 || pressed_char == 0xe0 {
|
||||||
return Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Given input char is not a valid char, mostly occurs when pressing special keys",
|
"Given input char is not a valid char, mostly occurs when pressing special keys",
|
||||||
));
|
))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
match char::from_u32(pressed_char as u32) {
|
let ch = char::from_u32(pressed_char as u32).ok_or_else(|| {
|
||||||
Some(c) => {
|
io::Error::new(io::ErrorKind::Other, "Could not parse given input to char")
|
||||||
return Ok(c);
|
})?;
|
||||||
}
|
|
||||||
None => Err(io::Error::new(
|
Ok(ch)
|
||||||
io::ErrorKind::Other,
|
|
||||||
"Could not parse given input to char",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_async(&self) -> AsyncReader {
|
fn read_async(&self) -> AsyncReader {
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
|
use crossterm_utils::Result;
|
||||||
|
|
||||||
/// Get the TTY device.
|
/// Get the TTY device.
|
||||||
///
|
///
|
||||||
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
|
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
|
||||||
pub fn get_tty() -> io::Result<fs::File> {
|
pub fn get_tty() -> Result<fs::File> {
|
||||||
fs::OpenOptions::new()
|
let file = fs::OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open("/dev/tty")
|
.open("/dev/tty")?;
|
||||||
|
|
||||||
|
Ok(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tty_fd() -> io::Result<i32> {
|
fn get_tty_fd() -> Result<i32> {
|
||||||
let fd = unsafe {
|
let fd = unsafe {
|
||||||
if libc::isatty(libc::STDIN_FILENO) == 1 {
|
if libc::isatty(libc::STDIN_FILENO) == 1 {
|
||||||
libc::STDIN_FILENO
|
libc::STDIN_FILENO
|
||||||
@ -23,7 +27,7 @@ fn get_tty_fd() -> io::Result<i32> {
|
|||||||
Ok(fd)
|
Ok(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_char_raw() -> io::Result<char> {
|
pub fn read_char_raw() -> Result<char> {
|
||||||
let mut buf = [0u8; 20];
|
let mut buf = [0u8; 20];
|
||||||
|
|
||||||
let fd = get_tty_fd()?;
|
let fd = get_tty_fd()?;
|
||||||
@ -50,7 +54,7 @@ pub fn read_char_raw() -> io::Result<char> {
|
|||||||
|
|
||||||
pressed_char
|
pressed_char
|
||||||
}
|
}
|
||||||
};
|
}?;
|
||||||
|
|
||||||
rv
|
Ok(rv)
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
//! For an example of this behavior, consider when vim is launched from bash.
|
//! For an example of this behavior, consider when vim is launched from bash.
|
||||||
//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
|
//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
|
||||||
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use crossterm_utils::supports_ansi;
|
use crossterm_utils::supports_ansi;
|
||||||
|
use crossterm_utils::Result;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use crate::sys::winapi::ToAlternateScreenCommand;
|
use crate::sys::winapi::ToAlternateScreenCommand;
|
||||||
@ -38,7 +37,7 @@ impl AlternateScreen {
|
|||||||
/// The alternate buffer dimensions are exactly the same as the window, without any scrollback region.
|
/// The alternate buffer dimensions are exactly the same as the window, without any scrollback region.
|
||||||
/// For an example of this behavior, consider when vim is launched from bash.
|
/// For an example of this behavior, consider when vim is launched from bash.
|
||||||
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
|
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
|
||||||
pub fn to_alternate(raw_mode: bool) -> io::Result<AlternateScreen> {
|
pub fn to_alternate(raw_mode: bool) -> Result<AlternateScreen> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let command = if supports_ansi() {
|
let command = if supports_ansi() {
|
||||||
Box::from(sys::ToAlternateScreenCommand::new())
|
Box::from(sys::ToAlternateScreenCommand::new())
|
||||||
@ -68,9 +67,8 @@ impl AlternateScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Switch the alternate screen back to the main screen.
|
/// Switch the alternate screen back to the main screen.
|
||||||
pub fn to_main(&self) -> io::Result<()> {
|
pub fn to_main(&self) -> Result<()> {
|
||||||
self.command.disable()?;
|
self.command.disable()
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,9 @@
|
|||||||
//!
|
//!
|
||||||
//! With these modes you can easier design the terminal screen.
|
//! With these modes you can easier design the terminal screen.
|
||||||
|
|
||||||
use std::io::{self, Stdout, Write};
|
use std::io::{Stdout, Write};
|
||||||
|
|
||||||
|
use crossterm_utils::Result;
|
||||||
|
|
||||||
use crate::sys;
|
use crate::sys;
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ pub struct RawScreen {
|
|||||||
|
|
||||||
impl RawScreen {
|
impl RawScreen {
|
||||||
/// Put terminal in raw mode.
|
/// Put terminal in raw mode.
|
||||||
pub fn into_raw_mode() -> io::Result<RawScreen> {
|
pub fn into_raw_mode() -> Result<RawScreen> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut command = sys::unix::RawModeCommand::new();
|
let mut command = sys::unix::RawModeCommand::new();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -39,7 +41,7 @@ impl RawScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Put terminal back in original modes.
|
/// Put terminal back in original modes.
|
||||||
pub fn disable_raw_mode() -> io::Result<()> {
|
pub fn disable_raw_mode() -> Result<()> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut command = sys::unix::RawModeCommand::new();
|
let mut command = sys::unix::RawModeCommand::new();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -67,11 +69,11 @@ pub trait IntoRawMode: Write + Sized {
|
|||||||
/// Raw mode means that stdin won't be printed (it will instead have to be written manually by
|
/// Raw mode means that stdin won't be printed (it will instead have to be written manually by
|
||||||
/// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
|
/// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
|
||||||
/// read from stdin one byte of a time). The output is neither modified in any way.
|
/// read from stdin one byte of a time). The output is neither modified in any way.
|
||||||
fn into_raw_mode(self) -> io::Result<RawScreen>;
|
fn into_raw_mode(self) -> Result<RawScreen>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoRawMode for Stdout {
|
impl IntoRawMode for Stdout {
|
||||||
fn into_raw_mode(self) -> io::Result<RawScreen> {
|
fn into_raw_mode(self) -> Result<RawScreen> {
|
||||||
RawScreen::into_raw_mode()?;
|
RawScreen::into_raw_mode()?;
|
||||||
// this make's sure that raw screen will be disabled when it goes out of scope.
|
// this make's sure that raw screen will be disabled when it goes out of scope.
|
||||||
Ok(RawScreen { drop: true })
|
Ok(RawScreen { drop: true })
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::io::Result;
|
use crossterm_utils::Result;
|
||||||
|
|
||||||
/// This command is used for enabling and disabling raw mode for the terminal.
|
/// This command is used for enabling and disabling raw mode for the terminal.
|
||||||
pub struct RawModeCommand;
|
pub struct RawModeCommand;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::io;
|
|
||||||
|
|
||||||
use winapi::shared::minwindef::DWORD;
|
use winapi::shared::minwindef::DWORD;
|
||||||
use winapi::um::wincon;
|
use winapi::um::wincon;
|
||||||
|
|
||||||
@ -27,7 +25,7 @@ impl RawModeCommand {
|
|||||||
|
|
||||||
impl RawModeCommand {
|
impl RawModeCommand {
|
||||||
/// Enables raw mode.
|
/// Enables raw mode.
|
||||||
pub fn enable(&mut self) -> io::Result<()> {
|
pub fn enable(&mut self) -> Result<()> {
|
||||||
let console_mode = ConsoleMode::new()?;
|
let console_mode = ConsoleMode::new()?;
|
||||||
|
|
||||||
let dw_mode = console_mode.mode()?;
|
let dw_mode = console_mode.mode()?;
|
||||||
@ -40,7 +38,7 @@ impl RawModeCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Disables raw mode.
|
/// Disables raw mode.
|
||||||
pub fn disable(&self) -> io::Result<()> {
|
pub fn disable(&self) -> Result<()> {
|
||||||
let console_mode = ConsoleMode::new()?;
|
let console_mode = ConsoleMode::new()?;
|
||||||
|
|
||||||
let dw_mode = console_mode.mode()?;
|
let dw_mode = console_mode.mode()?;
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
use std::clone::Clone;
|
use std::clone::Clone;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use crossterm_utils::supports_ansi;
|
use crossterm_utils::supports_ansi;
|
||||||
@ -67,7 +66,7 @@ impl TerminalColor {
|
|||||||
|
|
||||||
/// Get available color count.
|
/// Get available color count.
|
||||||
/// (This does not always provide a good result.)
|
/// (This does not always provide a good result.)
|
||||||
pub fn get_available_color_count(&self) -> io::Result<u16> {
|
pub fn get_available_color_count(&self) -> Result<u16> {
|
||||||
use std::env;
|
use std::env;
|
||||||
Ok(match env::var_os("TERM") {
|
Ok(match env::var_os("TERM") {
|
||||||
Some(val) => {
|
Some(val) => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
//! This is a `WinApi` specific implementation for styling related action.
|
//! This is a `WinApi` specific implementation for styling related action.
|
||||||
//! This module is used for non supporting `ANSI` Windows terminals.
|
//! This module is used for non supporting `ANSI` Windows terminals.
|
||||||
|
|
||||||
use std::io;
|
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
use winapi::um::wincon;
|
use winapi::um::wincon;
|
||||||
@ -173,7 +172,7 @@ fn color_value(color: Colored) -> String {
|
|||||||
winapi_color.to_string()
|
winapi_color.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_console_color() -> io::Result<()> {
|
fn init_console_color() -> Result<()> {
|
||||||
let screen_buffer = ScreenBuffer::current()?;
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
|
|
||||||
let attr = screen_buffer.info()?.attributes();
|
let attr = screen_buffer.info()?.attributes();
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::{execute, impl_display, queue, write_cout, Result};
|
||||||
use crate::{execute, impl_display, queue, write_cout};
|
|
||||||
|
|
||||||
/// A command is an action that can be performed on the terminal.
|
/// A command is an action that can be performed on the terminal.
|
||||||
///
|
///
|
||||||
|
@ -49,18 +49,3 @@ impl From<fmt::Error> for ErrorKind {
|
|||||||
ErrorKind::FmtError(e)
|
ErrorKind::FmtError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl From<std::result::::Error> for ErrorKind {
|
|
||||||
// fn from(e: fmt::Error) -> ErrorKind {
|
|
||||||
// ErrorKind::FmtError(e)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
impl From<ErrorKind> for io::Error {
|
|
||||||
fn from(e: ErrorKind) -> io::Error {
|
|
||||||
match e {
|
|
||||||
ErrorKind::IoError(io) => return io,
|
|
||||||
_ => io::Error::new(io::ErrorKind::Other, "can not convert error to IO error"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,12 +4,14 @@ use std::{io, mem};
|
|||||||
|
|
||||||
pub use libc::{c_int, termios as Termios};
|
pub use libc::{c_int, termios as Termios};
|
||||||
|
|
||||||
|
use crate::{ErrorKind, Result};
|
||||||
|
|
||||||
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
|
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
|
||||||
pub static mut RAW_MODE_ENABLED: bool = false;
|
pub static mut RAW_MODE_ENABLED: bool = false;
|
||||||
|
|
||||||
fn unwrap(t: i32) -> io::Result<()> {
|
fn unwrap(t: i32) -> Result<()> {
|
||||||
if t == -1 {
|
if t == -1 {
|
||||||
Err(io::Error::last_os_error())
|
Err(ErrorKind::IoError(io::Error::last_os_error()))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -23,7 +25,7 @@ pub fn raw_terminal_attr(termios: &mut Termios) {
|
|||||||
unsafe { cfmakeraw(termios) }
|
unsafe { cfmakeraw(termios) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_terminal_attr() -> io::Result<Termios> {
|
pub fn get_terminal_attr() -> Result<Termios> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn tcgetattr(fd: c_int, termptr: *mut Termios) -> c_int;
|
pub fn tcgetattr(fd: c_int, termptr: *mut Termios) -> c_int;
|
||||||
}
|
}
|
||||||
@ -34,14 +36,14 @@ pub fn get_terminal_attr() -> io::Result<Termios> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_terminal_attr(termios: &Termios) -> io::Result<()> {
|
pub fn set_terminal_attr(termios: &Termios) -> Result<()> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int;
|
pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int;
|
||||||
}
|
}
|
||||||
unwrap(unsafe { tcsetattr(0, 0, termios) }).and(Ok(()))
|
unwrap(unsafe { tcsetattr(0, 0, termios) }).and(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_raw_mode() -> io::Result<()> {
|
pub fn into_raw_mode() -> Result<()> {
|
||||||
let mut ios = get_terminal_attr()?;
|
let mut ios = get_terminal_attr()?;
|
||||||
let prev_ios = ios;
|
let prev_ios = ios;
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ pub fn into_raw_mode() -> io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_raw_mode() -> io::Result<()> {
|
pub fn disable_raw_mode() -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ORIGINAL_TERMINAL_MODE.is_some() {
|
if ORIGINAL_TERMINAL_MODE.is_some() {
|
||||||
set_terminal_attr(&ORIGINAL_TERMINAL_MODE.unwrap())?;
|
set_terminal_attr(&ORIGINAL_TERMINAL_MODE.unwrap())?;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
pub mod ansi {
|
pub mod ansi {
|
||||||
use std::io;
|
|
||||||
|
|
||||||
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
|
||||||
|
use crate::Result;
|
||||||
use crossterm_winapi::ConsoleMode;
|
use crossterm_winapi::ConsoleMode;
|
||||||
|
|
||||||
/// Toggle virtual terminal processing.
|
/// Toggle virtual terminal processing.
|
||||||
@ -14,7 +13,7 @@ pub mod ansi {
|
|||||||
/// When virtual terminal processing is enabled, characters emitted to the
|
/// When virtual terminal processing is enabled, characters emitted to the
|
||||||
/// console are parsed for VT100 and similar control character sequences
|
/// console are parsed for VT100 and similar control character sequences
|
||||||
/// that control color and other similar operations.
|
/// that control color and other similar operations.
|
||||||
pub fn set_virtual_terminal_processing(yes: bool) -> io::Result<()> {
|
pub fn set_virtual_terminal_processing(yes: bool) -> Result<()> {
|
||||||
let mask = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
let mask = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
|
||||||
let console_mode = ConsoleMode::new()?;
|
let console_mode = ConsoleMode::new()?;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::{io, thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm};
|
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm, Result};
|
||||||
|
|
||||||
fn print_wait_screen() -> io::Result<()> {
|
fn print_wait_screen() -> Result<()> {
|
||||||
let crossterm = Crossterm::new();
|
let crossterm = Crossterm::new();
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
@ -34,15 +34,12 @@ fn print_wait_screen() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// print wait screen on alternate screen, then switch back.
|
/// print wait screen on alternate screen, then switch back.
|
||||||
pub fn print_wait_screen_on_alternate_window() -> io::Result<()> {
|
fn print_wait_screen_on_alternate_window() -> Result<()> {
|
||||||
if let Ok(_alternate) = AlternateScreen::to_alternate(false) {
|
let _alt = AlternateScreen::to_alternate(false)?;
|
||||||
print_wait_screen()?;
|
print_wait_screen()
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cargo run --example alternate_screen
|
// cargo run --example alternate_screen
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
print_wait_screen_on_alternate_window().unwrap();
|
print_wait_screen_on_alternate_window()
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,7 @@ fn execute_command_directly_using_macros() -> Result<()> {
|
|||||||
stdout(),
|
stdout(),
|
||||||
Output("Text2 ".to_string()),
|
Output("Text2 ".to_string()),
|
||||||
Output("Text 3".to_string())
|
Output("Text 3".to_string())
|
||||||
)?;
|
)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// queue commands without executing them directly by using normal functions
|
/// queue commands without executing them directly by using normal functions
|
||||||
@ -81,4 +79,9 @@ fn later_execution_command_directly_using_macros() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cargo run --example command
|
// cargo run --example command
|
||||||
fn main() {}
|
fn main() -> Result<()> {
|
||||||
|
later_execution_command_directly_using_macros()
|
||||||
|
// later_execution_command_using_functions()
|
||||||
|
// execute_command_directly_using_macros()
|
||||||
|
// execute_command_directly_using_functions()
|
||||||
|
}
|
||||||
|
@ -2,14 +2,61 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor, input, terminal, ClearType, Crossterm, InputEvent, KeyEvent, RawScreen, Terminal,
|
cursor, input, terminal, ClearType, Crossterm, InputEvent, KeyEvent, RawScreen, Result,
|
||||||
TerminalCursor,
|
Terminal, TerminalCursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>> {
|
||||||
|
let mut threads = Vec::with_capacity(10);
|
||||||
|
|
||||||
|
let (_, term_height) = terminal().terminal_size();
|
||||||
|
|
||||||
|
for i in 0..1 {
|
||||||
|
let input_buffer = input_buf.clone();
|
||||||
|
|
||||||
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
|
let join = thread::spawn(move || {
|
||||||
|
let cursor = crossterm.cursor();
|
||||||
|
let terminal = crossterm.terminal();
|
||||||
|
|
||||||
|
for j in 0..1000 {
|
||||||
|
if let Err(_) = swap_write(
|
||||||
|
format!("Some output: {} from thread: {}", j, i).as_ref(),
|
||||||
|
&input_buffer.lock().unwrap(),
|
||||||
|
&terminal,
|
||||||
|
&cursor,
|
||||||
|
term_height,
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
thread::sleep(time::Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
threads.push(join);
|
||||||
|
}
|
||||||
|
|
||||||
|
threads
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swap_write(
|
||||||
|
msg: &str,
|
||||||
|
input_buf: &String,
|
||||||
|
terminal: &Terminal,
|
||||||
|
cursor: &TerminalCursor,
|
||||||
|
term_height: u16,
|
||||||
|
) -> Result<()> {
|
||||||
|
cursor.goto(0, term_height)?;
|
||||||
|
terminal.clear(ClearType::CurrentLine)?;
|
||||||
|
terminal.write(format!("{}\r\n", msg))?;
|
||||||
|
terminal.write(format!("> {}", input_buf)).map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
// cargo run --example command_bar
|
// cargo run --example command_bar
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
let _screen = RawScreen::into_raw_mode();
|
let _screen = RawScreen::into_raw_mode();
|
||||||
cursor().hide().expect("Couldn't hide cursor");
|
cursor().hide()?;
|
||||||
|
|
||||||
let input_buf = Arc::new(Mutex::new(String::new()));
|
let input_buf = Arc::new(Mutex::new(String::new()));
|
||||||
|
|
||||||
@ -43,56 +90,5 @@ fn main() {
|
|||||||
thread.join().expect("Couldn't join");
|
thread.join().expect("Couldn't join");
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor().show().expect("Couldn't show cursor");
|
cursor().show()
|
||||||
}
|
|
||||||
|
|
||||||
fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>> {
|
|
||||||
let mut threads = Vec::with_capacity(10);
|
|
||||||
|
|
||||||
let (_, term_height) = terminal().terminal_size();
|
|
||||||
|
|
||||||
for i in 0..1 {
|
|
||||||
let input_buffer = input_buf.clone();
|
|
||||||
|
|
||||||
let crossterm = Crossterm::new();
|
|
||||||
|
|
||||||
let join = thread::spawn(move || {
|
|
||||||
let cursor = crossterm.cursor();
|
|
||||||
let terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
for j in 0..1000 {
|
|
||||||
swap_write(
|
|
||||||
format!("Some output: {} from thread: {}", j, i).as_ref(),
|
|
||||||
&input_buffer.lock().unwrap(),
|
|
||||||
&terminal,
|
|
||||||
&cursor,
|
|
||||||
term_height,
|
|
||||||
);
|
|
||||||
thread::sleep(time::Duration::from_millis(100));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
threads.push(join);
|
|
||||||
}
|
|
||||||
|
|
||||||
return threads;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap_write(
|
|
||||||
msg: &str,
|
|
||||||
input_buf: &String,
|
|
||||||
terminal: &Terminal,
|
|
||||||
cursor: &TerminalCursor,
|
|
||||||
term_height: u16,
|
|
||||||
) {
|
|
||||||
cursor.goto(0, term_height).expect("Couldn't goto");
|
|
||||||
terminal
|
|
||||||
.clear(ClearType::CurrentLine)
|
|
||||||
.expect("Couldn't clear current line");
|
|
||||||
terminal
|
|
||||||
.write(format!("{}\r\n", msg))
|
|
||||||
.expect("Couldn't write message");
|
|
||||||
terminal
|
|
||||||
.write(format!("> {}", input_buf))
|
|
||||||
.expect("Couldn't write prompt");
|
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
//! Examples of actions that could be performed with the cursor.
|
//! Examples of actions that could be performed with the cursor.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::io;
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crossterm_cursor::cursor;
|
use crossterm::{cursor, Result};
|
||||||
|
|
||||||
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
||||||
pub fn goto() -> io::Result<()> {
|
fn goto() -> Result<()> {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
// Set the cursor to position X: 10, Y: 5 in the terminal
|
// Set the cursor to position X: 10, Y: 5 in the terminal
|
||||||
@ -17,7 +17,7 @@ pub fn goto() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// get the cursor position
|
/// get the cursor position
|
||||||
pub fn pos() {
|
fn pos() {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
// get the cursor position.
|
// get the cursor position.
|
||||||
@ -27,7 +27,7 @@ pub fn pos() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 up | demonstration.
|
/// Move the cursor 3 up | demonstration.
|
||||||
pub fn move_up() {
|
fn move_up() {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor();
|
||||||
|
|
||||||
@ -36,21 +36,21 @@ pub fn move_up() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 to the right | demonstration.
|
/// Move the cursor 3 to the right | demonstration.
|
||||||
pub fn move_right() {
|
fn move_right() {
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor();
|
||||||
// Move the cursor to position 3 times to the right in the terminal
|
// Move the cursor to position 3 times to the right in the terminal
|
||||||
cursor.move_right(3);
|
cursor.move_right(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 down | demonstration.
|
/// Move the cursor 3 down | demonstration.
|
||||||
pub fn move_down() {
|
fn move_down() {
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor();
|
||||||
// Move the cursor to position 3 times to the down in the terminal
|
// Move the cursor to position 3 times to the down in the terminal
|
||||||
cursor.move_down(3);
|
cursor.move_down(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save and reset cursor position | demonstration..
|
/// Save and reset cursor position | demonstration..
|
||||||
pub fn save_and_reset_position() -> io::Result<()> {
|
fn save_and_reset_position() -> Result<()> {
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
|
|
||||||
// Goto X: 5 Y: 5
|
// Goto X: 5 Y: 5
|
||||||
@ -72,25 +72,30 @@ pub fn save_and_reset_position() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Hide cursor display | demonstration.
|
/// Hide cursor display | demonstration.
|
||||||
pub fn hide_cursor() {
|
fn hide_cursor() -> Result<()> {
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
cursor.hide().unwrap();
|
cursor.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show cursor display | demonstration.
|
/// Show cursor display | demonstration.
|
||||||
pub fn show_cursor() {
|
fn show_cursor() -> Result<()> {
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
cursor.show().unwrap();
|
cursor.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show cursor display, only works on certain terminals.| demonstration
|
/// Show cursor display, only works on certain terminals.| demonstration
|
||||||
pub fn blink_cursor() {
|
fn blink_cursor(enable: bool) -> Result<()> {
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
cursor.blink(false).unwrap();
|
cursor.blink(enable)
|
||||||
cursor.blink(false).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cargo run --example cursor
|
// cargo run --example cursor
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
hide_cursor()
|
println!("Going to show cursor...");
|
||||||
|
show_cursor()?;
|
||||||
|
println!("Going to enable blinking cursor & sleep for 5s...");
|
||||||
|
blink_cursor(true)?;
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(5));
|
||||||
|
println!("Going to disable blinking cursor...");
|
||||||
|
blink_cursor(false)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crossterm::input;
|
use crossterm::input;
|
||||||
|
|
||||||
pub fn read_char() {
|
fn read_char() {
|
||||||
let input = input();
|
let input = input();
|
||||||
|
|
||||||
match input.read_char() {
|
match input.read_char() {
|
||||||
@ -9,7 +9,7 @@ pub fn read_char() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_line() {
|
fn read_line() {
|
||||||
let input = input();
|
let input = input();
|
||||||
|
|
||||||
match input.read_line() {
|
match input.read_line() {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
use crossterm::{input, InputEvent, KeyEvent, MouseButton, MouseEvent, RawScreen};
|
use crossterm::{input, InputEvent, KeyEvent, MouseButton, MouseEvent, RawScreen, Result};
|
||||||
|
|
||||||
fn process_input_event(key_event: InputEvent) -> bool {
|
fn process_input_event(key_event: InputEvent) -> bool {
|
||||||
match key_event {
|
match key_event {
|
||||||
@ -71,60 +73,60 @@ fn process_input_event(key_event: InputEvent) -> bool {
|
|||||||
_ => println!("Unknown!"),
|
_ => println!("Unknown!"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_asynchronously() {
|
fn read_asynchronously() -> Result<()> {
|
||||||
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
||||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
let _raw = RawScreen::into_raw_mode()?;
|
||||||
let input = input();
|
|
||||||
|
|
||||||
// enable mouse events to be captured.
|
let input = input();
|
||||||
input.enable_mouse_mode().unwrap();
|
|
||||||
|
|
||||||
let mut stdin = input.read_async();
|
// enable mouse events to be captured.
|
||||||
|
input.enable_mouse_mode()?;
|
||||||
|
|
||||||
loop {
|
let mut stdin = input.read_async();
|
||||||
if let Some(key_event) = stdin.next() {
|
|
||||||
if process_input_event(key_event) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thread::sleep(Duration::from_millis(50));
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable mouse events to be captured.
|
loop {
|
||||||
input.disable_mouse_mode().unwrap();
|
if let Some(key_event) = stdin.next() {
|
||||||
} // <=== raw modes will be disabled here
|
if process_input_event(key_event) {
|
||||||
} // <=== background reader will be disposed when dropped.
|
break;
|
||||||
|
|
||||||
pub fn read_synchronously() {
|
|
||||||
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
|
||||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
|
||||||
let input = input();
|
|
||||||
|
|
||||||
// enable mouse events to be captured.
|
|
||||||
input.enable_mouse_mode().unwrap();
|
|
||||||
|
|
||||||
let mut sync_stdin = input.read_sync();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let event = sync_stdin.next();
|
|
||||||
|
|
||||||
if let Some(key_event) = event {
|
|
||||||
if process_input_event(key_event) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
thread::sleep(Duration::from_millis(50));
|
||||||
|
}
|
||||||
|
|
||||||
// disable mouse events to be captured.
|
// disable mouse events to be captured.
|
||||||
input.disable_mouse_mode().unwrap();
|
input.disable_mouse_mode()
|
||||||
} // <=== raw modes will be disabled here
|
} // <=== raw modes will be disabled here
|
||||||
}
|
|
||||||
|
fn read_synchronously() -> Result<()> {
|
||||||
|
// make sure to enable raw mode, this will make sure key events won't be handled by the terminal it's self and allows crossterm to read the input and pass it back to you.
|
||||||
|
let _raw = RawScreen::into_raw_mode()?;
|
||||||
|
|
||||||
|
let input = input();
|
||||||
|
|
||||||
|
// enable mouse events to be captured.
|
||||||
|
input.enable_mouse_mode()?;
|
||||||
|
|
||||||
|
let mut sync_stdin = input.read_sync();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let event = sync_stdin.next();
|
||||||
|
|
||||||
|
if let Some(key_event) = event {
|
||||||
|
if process_input_event(key_event) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable mouse events to be captured.
|
||||||
|
input.disable_mouse_mode()
|
||||||
|
} // <=== raw modes will be disabled here
|
||||||
|
|
||||||
// cargo run --example key_events
|
// cargo run --example key_events
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
// read_synchronously();
|
read_synchronously()
|
||||||
// read_asynchronously();
|
// read_asynchronously()
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::io::{self, stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm};
|
use crossterm::{style, AlternateScreen, ClearType, Color, Crossterm, Result};
|
||||||
|
|
||||||
fn print_wait_screen() -> io::Result<()> {
|
fn print_wait_screen() -> Result<()> {
|
||||||
let crossterm = Crossterm::new();
|
let crossterm = Crossterm::new();
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
@ -39,16 +39,13 @@ fn print_wait_screen() -> io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_wait_screen_on_alternate_window() -> io::Result<()> {
|
fn print_wait_screen_on_alternate_window() -> Result<()> {
|
||||||
// by passing in 'true' the alternate screen will be in raw modes.
|
// by passing in 'true' the alternate screen will be in raw modes.
|
||||||
if let Ok(_alternate) = AlternateScreen::to_alternate(true) {
|
let _alt = AlternateScreen::to_alternate(true)?;
|
||||||
print_wait_screen()?;
|
print_wait_screen()
|
||||||
} // <- drop alternate screen; this will cause the alternate screen to drop.
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cargo run --example raw_mode
|
// cargo run --example raw_mode
|
||||||
fn main() {
|
fn main() -> Result<()> {
|
||||||
print_wait_screen_on_alternate_window().unwrap();
|
print_wait_screen_on_alternate_window()
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
//!
|
//!
|
||||||
//! Examples of coloring the terminal.
|
//! Examples of coloring the terminal.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crossterm::{color, Attribute, Color, Colored, Colorize, Styler};
|
use crossterm::{color, Attribute, Color, Colored, Colorize, Styler};
|
||||||
|
|
||||||
/// print some red text | demonstration.
|
/// print some red text | demonstration.
|
||||||
pub fn paint_foreground() {
|
fn paint_foreground() {
|
||||||
println!("{}", "Red foreground text: {}".red());
|
println!("{}", "Red foreground text: {}".red());
|
||||||
println!("{} Red foreground text", Colored::Fg(Color::Red));
|
println!("{} Red foreground text", Colored::Fg(Color::Red));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print some text on red background | demonstration.
|
/// print some text on red background | demonstration.
|
||||||
pub fn paint_background() {
|
fn paint_background() {
|
||||||
println!("{}", "Red background text: {}".on_red());
|
println!("{}", "Red background text: {}".on_red());
|
||||||
println!("{} Red background text", Colored::Bg(Color::Red));
|
println!("{} Red background text", Colored::Bg(Color::Red));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_foreground_colors_with_enum() {
|
fn print_all_foreground_colors_with_enum() {
|
||||||
// we use `Reset` to restore the foreground back to normal at the end of the line.
|
// we use `Reset` to restore the foreground back to normal at the end of the line.
|
||||||
println!(
|
println!(
|
||||||
"Black : \t\t {} ■ {}\n",
|
"Black : \t\t {} ■ {}\n",
|
||||||
@ -114,7 +117,7 @@ pub fn print_all_foreground_colors_with_enum() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_foreground_colors_with_method() {
|
fn print_all_foreground_colors_with_method() {
|
||||||
println!(
|
println!(
|
||||||
"Black : \t\t {} {}\n",
|
"Black : \t\t {} {}\n",
|
||||||
"■".black(),
|
"■".black(),
|
||||||
@ -182,7 +185,7 @@ pub fn print_all_foreground_colors_with_method() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_background_colors_with_enum() {
|
fn print_all_background_colors_with_enum() {
|
||||||
println!(
|
println!(
|
||||||
"Black : \t\t {} ■ {}\n",
|
"Black : \t\t {} ■ {}\n",
|
||||||
Colored::Bg(Color::Black),
|
Colored::Bg(Color::Black),
|
||||||
@ -279,7 +282,7 @@ pub fn print_all_background_colors_with_enum() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_background_colors_with_method() {
|
fn print_all_background_colors_with_method() {
|
||||||
println!(
|
println!(
|
||||||
"Black : \t\t {} {}\n",
|
"Black : \t\t {} {}\n",
|
||||||
"■".on_black(),
|
"■".on_black(),
|
||||||
@ -364,7 +367,7 @@ pub fn print_all_background_colors_with_method() {
|
|||||||
|
|
||||||
/// Print text with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
|
/// Print text with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn print_text_with_attributes() {
|
fn print_text_with_attributes() {
|
||||||
println!("{}", "Normal text");
|
println!("{}", "Normal text");
|
||||||
println!("{}", "Bold text".bold());
|
println!("{}", "Bold text".bold());
|
||||||
println!("{}", "Italic text".italic());
|
println!("{}", "Italic text".italic());
|
||||||
@ -387,7 +390,7 @@ pub fn print_text_with_attributes() {
|
|||||||
|
|
||||||
// Print text with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
|
// Print text with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn print_text_with_attributes() {
|
fn print_text_with_attributes() {
|
||||||
println!("{}", "Normal text");
|
println!("{}", "Normal text");
|
||||||
println!("{}", "Bold text".bold());
|
println!("{}", "Bold text".bold());
|
||||||
println!("{}", "Underlined text".underlined());
|
println!("{}", "Underlined text".underlined());
|
||||||
@ -395,7 +398,7 @@ pub fn print_text_with_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration.
|
/// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration.
|
||||||
pub fn print_supported_colors() {
|
fn print_supported_colors() {
|
||||||
let count = color().get_available_color_count().unwrap();
|
let count = color().get_available_color_count().unwrap();
|
||||||
|
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
@ -403,7 +406,7 @@ pub fn print_supported_colors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_fg_and_bg() {
|
fn reset_fg_and_bg() {
|
||||||
println!("{}", Colored::Fg(Color::Reset));
|
println!("{}", Colored::Fg(Color::Reset));
|
||||||
println!("{}", Colored::Bg(Color::Reset));
|
println!("{}", Colored::Bg(Color::Reset));
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
//! Terminal Examples
|
//! Terminal Examples
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::io;
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crossterm::{cursor, terminal, ClearType};
|
use crossterm::{cursor, terminal, ClearType, Result};
|
||||||
|
|
||||||
fn print_test_data() {
|
fn print_test_data() {
|
||||||
for i in 0..100 {
|
for i in 0..100 {
|
||||||
@ -13,19 +13,17 @@ fn print_test_data() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all lines in terminal | demonstration
|
/// Clear all lines in terminal | demonstration
|
||||||
pub fn clear_all_lines() -> io::Result<()> {
|
fn clear_all_lines() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Clear all lines in terminal;
|
// Clear all lines in terminal;
|
||||||
terminal.clear(ClearType::All)?;
|
terminal.clear(ClearType::All)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
||||||
pub fn clear_from_cursor_down() -> io::Result<()> {
|
fn clear_from_cursor_down() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
@ -34,13 +32,11 @@ pub fn clear_from_cursor_down() -> io::Result<()> {
|
|||||||
cursor().goto(4, 8)?;
|
cursor().goto(4, 8)?;
|
||||||
|
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorDown)?;
|
terminal.clear(ClearType::FromCursorDown)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_from_cursor_up() -> io::Result<()> {
|
fn clear_from_cursor_up() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
@ -49,13 +45,11 @@ pub fn clear_from_cursor_up() -> io::Result<()> {
|
|||||||
cursor().goto(4, 4)?;
|
cursor().goto(4, 4)?;
|
||||||
|
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorUp)?;
|
terminal.clear(ClearType::FromCursorUp)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_current_line() -> io::Result<()> {
|
fn clear_current_line() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
@ -64,13 +58,11 @@ pub fn clear_current_line() -> io::Result<()> {
|
|||||||
cursor().goto(4, 3)?;
|
cursor().goto(4, 3)?;
|
||||||
|
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine)?;
|
terminal.clear(ClearType::CurrentLine)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
||||||
pub fn clear_until_new_line() -> io::Result<()> {
|
fn clear_until_new_line() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
@ -79,13 +71,11 @@ pub fn clear_until_new_line() -> io::Result<()> {
|
|||||||
cursor().goto(4, 20)?;
|
cursor().goto(4, 20)?;
|
||||||
|
|
||||||
// Clear all the cells until next line.
|
// Clear all the cells until next line.
|
||||||
terminal.clear(ClearType::UntilNewLine)?;
|
terminal.clear(ClearType::UntilNewLine)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print the the current terminal size | demonstration.
|
/// Print the the current terminal size | demonstration.
|
||||||
pub fn print_terminal_size() {
|
fn print_terminal_size() {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
@ -96,47 +86,39 @@ pub fn print_terminal_size() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the terminal size to width 10, height: 10 | demonstration.
|
/// Set the terminal size to width 10, height: 10 | demonstration.
|
||||||
pub fn set_terminal_size() -> io::Result<()> {
|
fn set_terminal_size() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
terminal.set_size(10, 10)?;
|
terminal.set_size(10, 10)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_down() -> io::Result<()> {
|
fn scroll_down() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Scroll down 10 lines.
|
// Scroll down 10 lines.
|
||||||
terminal.scroll_down(10)?;
|
terminal.scroll_down(10)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_up() -> io::Result<()> {
|
fn scroll_up() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Scroll up 10 lines.
|
// Scroll up 10 lines.
|
||||||
terminal.scroll_up(5)?;
|
terminal.scroll_up(10)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// exit the current proccess.
|
/// exit the current proccess.
|
||||||
pub fn exit() {
|
fn exit() {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
terminal.exit();
|
terminal.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// cargo run --example terminal
|
// cargo run --example terminal
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> Result<()> {
|
||||||
scroll_down()?;
|
scroll_down()
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user