windows changes
This commit is contained in:
parent
a367169bb7
commit
a8de072a0a
13
Cargo.toml
13
Cargo.toml
@ -11,22 +11,17 @@ exclude = ["target", "Cargo.lock"]
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.1.0"
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi"] }
|
winapi = { version = "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2.43"
|
||||||
termios = "0.3.0"
|
termios = "0.3.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
#[[bin]]
|
|
||||||
# name = "example_bin"
|
|
||||||
# path = "./examples/Crossterm 0.3.1/bin.rs"
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "examples"
|
name = "examples"
|
||||||
path = "examples/examples.rs"
|
path = "examples/examples.rs"
|
||||||
@ -36,5 +31,5 @@ name = "logging"
|
|||||||
path = "examples/program_examples/logging.rs"
|
path = "examples/program_examples/logging.rs"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "duplex"
|
name = "command_bar"
|
||||||
path = "examples/program_examples/duplex.rs"
|
path = "examples/program_examples/command_bar.rs"
|
||||||
|
33
README.md
33
README.md
@ -10,7 +10,7 @@ Crossterm aims to be simple and easy to call in code.
|
|||||||
Though the simplicity of Crossterm, you do not have to worry about the platform you are working with.
|
Though the simplicity of Crossterm, you do not have to worry about the platform you are working with.
|
||||||
You can just call whatever action you want and behind the scenes it will check what to do based on the current platform.
|
You can just call whatever action you want and behind the scenes it will check what to do based on the current platform.
|
||||||
|
|
||||||
This crate supports all unix and windows terminals down to windows XP (not all terminals are tested see [Tested Terminals](Link) for more info)
|
This crate supports all unix and windows terminals down to windows 7 (not all terminals are tested see [Tested Terminals](Link) for more info)
|
||||||
|
|
||||||
## Table of contents:
|
## Table of contents:
|
||||||
- [Getting started](https://github.com/TimonPost/crossterm#getting-started)
|
- [Getting started](https://github.com/TimonPost/crossterm#getting-started)
|
||||||
@ -167,7 +167,7 @@ This module provides the functionalities to work with the terminal cursor.
|
|||||||
```rust
|
```rust
|
||||||
|
|
||||||
use crossterm::Screen;
|
use crossterm::Screen;
|
||||||
use crossterm::cursor::cursor;
|
use crossterm::cursor;
|
||||||
|
|
||||||
// create Screen to wheron the `cursor()` should function.
|
// create Screen to wheron the `cursor()` should function.
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
@ -206,6 +206,32 @@ cursor.blink(true)
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Input | [see more](LINK)
|
||||||
|
This module provides the functionalities to work with terminal input.
|
||||||
|
|
||||||
|
Check [this](link) for handling async input.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
|
||||||
|
use crossterm::Screen;
|
||||||
|
use crossterm::input;
|
||||||
|
|
||||||
|
// create Screen to wheron the `cursor()` should function.
|
||||||
|
let screen = Screen::default();
|
||||||
|
let mut input = input(&screen);
|
||||||
|
|
||||||
|
match input.read_char() {
|
||||||
|
Ok(s) => println!("char typed: {}", s),
|
||||||
|
Err(e) => println!("char error : {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
match input.read_line() {
|
||||||
|
Ok(s) => println!("string typed: {}", s),
|
||||||
|
Err(e) => println!("error: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Terminal | [see more](LINK)
|
### Terminal | [see more](LINK)
|
||||||
This module provides the functionalities to work with the terminal in general.
|
This module provides the functionalities to work with the terminal in general.
|
||||||
|
|
||||||
@ -254,11 +280,12 @@ Check these links: [AlternateScreen](https://github.com/TimonPost/crossterm/blob
|
|||||||
- Windows 10 (pro)
|
- Windows 10 (pro)
|
||||||
- Windows CMD
|
- Windows CMD
|
||||||
- Windows 10 (pro)
|
- Windows 10 (pro)
|
||||||
|
- Windows 8.1 (N)
|
||||||
- Ubuntu Desktop Terminal
|
- Ubuntu Desktop Terminal
|
||||||
- Ubuntu 17.10
|
- Ubuntu 17.10
|
||||||
- Arch linux Konsole
|
- Arch linux Konsole
|
||||||
|
|
||||||
This crate supports all Unix terminals and windows terminals down to Windows XP but not all of them have been tested.
|
This crate supports all Unix terminals and windows terminals down to Windows 7 but not all of them have been tested.
|
||||||
If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
|
If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
|
||||||
|
|
||||||
## Notice
|
## Notice
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
//! - Run program with: `cargo run --example examples`
|
//! - Run program with: `cargo run --example examples`
|
||||||
|
|
||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
|
|
||||||
// modules that could be test
|
// modules that could be test
|
||||||
mod terminal;
|
mod terminal;
|
||||||
@ -17,62 +15,19 @@ mod cursor;
|
|||||||
mod some_types;
|
mod some_types;
|
||||||
mod input;
|
mod input;
|
||||||
|
|
||||||
use crossterm::{Screen, Crossterm};
|
use std::io::Write;
|
||||||
use crossterm::terminal::{Terminal, ClearType};
|
|
||||||
use crossterm::cursor::TerminalCursor;
|
|
||||||
|
|
||||||
use std::{time, thread};
|
fn main()
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::sync::{Arc,Mutex};
|
|
||||||
use crossterm::cursor::cursor;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
use crossterm::color;
|
|
||||||
|
|
||||||
let input = CROSSTERM.input();
|
|
||||||
let mut stdin = input.read_async().bytes();
|
|
||||||
CROSSTERM.cursor().hide();
|
|
||||||
|
|
||||||
let mut input_buf = Arc::new(Mutex::new(String::new()));
|
|
||||||
|
|
||||||
loop
|
|
||||||
{
|
{
|
||||||
let a = stdin.next();
|
use crossterm::screen::RawScreen;
|
||||||
|
use crossterm::Screen;
|
||||||
|
|
||||||
swap_write("dddd", &input_buf.lock().unwrap());
|
let mut screen = Screen::new(true);
|
||||||
|
|
||||||
match a {
|
write!(screen, "text \n\r");
|
||||||
Some(Ok(b'\r')) =>
|
let a = screen.enable_alternate_modes(true).unwrap();
|
||||||
{
|
|
||||||
input_buf.lock().unwrap().clear();
|
|
||||||
|
|
||||||
// need to start receiving again because if pressed enter then async reading will stop
|
write!(a, "text \n\r");
|
||||||
stdin = input.read_async().bytes();
|
|
||||||
}
|
|
||||||
Some(Ok(val)) =>
|
|
||||||
{
|
|
||||||
input_buf.lock().unwrap().push(val as char);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_millis(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap_write(msg: &str, input_buf: &String) {
|
|
||||||
let term = CROSSTERM.terminal();
|
|
||||||
let (_, term_height) = term.terminal_size();
|
|
||||||
CROSSTERM.cursor().goto(0, term_height);
|
|
||||||
term.clear(ClearType::CurrentLine);
|
|
||||||
term.write(format!("{}\r\n", msg));
|
|
||||||
term.write(format!(">{}", input_buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref CROSSTERM: Crossterm = {
|
|
||||||
let screen = Screen::new(true);
|
|
||||||
Crossterm::new(&screen)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,6 @@ pub fn async_reading_on_alternate_screen() {
|
|||||||
|
|
||||||
let screen = Screen::new(false);
|
let screen = Screen::new(false);
|
||||||
|
|
||||||
|
|
||||||
// switch to alternate screen
|
// switch to alternate screen
|
||||||
if let Ok(alternate) = screen.enable_alternate_modes(true)
|
if let Ok(alternate) = screen.enable_alternate_modes(true)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,17 @@ If you have created a game or something feel free to upload it, would be a great
|
|||||||
The programs are:
|
The programs are:
|
||||||
|
|
||||||
- First depth search:
|
- First depth search:
|
||||||
|
|
||||||
This is an search algorithm implemented visually. This program uses the following functionalities: cursor movement, coloring, alternate screen and terminal clearing.
|
This is an search algorithm implemented visually. This program uses the following functionalities: cursor movement, coloring, alternate screen and terminal clearing.
|
||||||
- Duplex: This is a terminal application where there is some kind of conterminous output and with async input. So you could type an command while text is being outputted.
|
|
||||||
- This is an async logging program to demonstrate asynchronous working with crossterm.
|
- Snake
|
||||||
|
|
||||||
|
This is a snake game implemented with this library.
|
||||||
|
|
||||||
|
- Command Bar:
|
||||||
|
|
||||||
|
This is a terminal application where multiple threads write to the output while you can enter commands asynchronously.
|
||||||
|
|
||||||
|
- Logging:
|
||||||
|
|
||||||
|
This is an async logging program to demonstrate asynchronous logging with an queue.
|
94
examples/program_examples/command_bar.rs
Normal file
94
examples/program_examples/command_bar.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
extern crate crossterm;
|
||||||
|
|
||||||
|
use crossterm::{Screen, Crossterm};
|
||||||
|
use crossterm::terminal::{terminal,Terminal, ClearType};
|
||||||
|
use crossterm::cursor::TerminalCursor;
|
||||||
|
|
||||||
|
use std::sync::{Arc,Mutex};
|
||||||
|
use std::io::Read;
|
||||||
|
use std::{thread,time};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use crossterm::color;
|
||||||
|
|
||||||
|
let screen = Screen::new(true);
|
||||||
|
let crossterm = Crossterm::new(&screen);
|
||||||
|
|
||||||
|
let input = crossterm.input();
|
||||||
|
let terminal = crossterm.terminal();
|
||||||
|
let cursor = crossterm.cursor();
|
||||||
|
|
||||||
|
let mut stdin = input.read_async().bytes();
|
||||||
|
cursor.hide();
|
||||||
|
|
||||||
|
let mut input_buf = Arc::new(Mutex::new(String::new()));
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
let threads = log(input_buf.clone());
|
||||||
|
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
let a = stdin.next();
|
||||||
|
|
||||||
|
match a {
|
||||||
|
Some(Ok(b'\r')) =>
|
||||||
|
{
|
||||||
|
input_buf.lock().unwrap().clear();
|
||||||
|
|
||||||
|
// need to start receiving again because if pressed enter then async reading will stop
|
||||||
|
stdin = input.read_async().bytes();
|
||||||
|
}
|
||||||
|
Some(Ok(val)) =>
|
||||||
|
{
|
||||||
|
input_buf.lock().unwrap().push(val as char);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::sleep(time::Duration::from_millis(100));
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for thread in threads
|
||||||
|
{
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>>
|
||||||
|
{
|
||||||
|
let mut threads = Vec::with_capacity(10);
|
||||||
|
let (_, term_height) = terminal(&Screen::default()).terminal_size();
|
||||||
|
|
||||||
|
for i in 0..10
|
||||||
|
{
|
||||||
|
let input_buffer = input_buf.clone();
|
||||||
|
|
||||||
|
let join = thread::spawn( move || {
|
||||||
|
|
||||||
|
let crossterm = Crossterm::new(&Screen::default());
|
||||||
|
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(300));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
terminal.clear(ClearType::CurrentLine);
|
||||||
|
terminal.write(format!("{}\r\n", msg));
|
||||||
|
terminal.write(format!(">{}", input_buf));
|
||||||
|
}
|
@ -1,76 +0,0 @@
|
|||||||
//! This bin folder can be used to try the examples out located in the examples directory.
|
|
||||||
//!
|
|
||||||
//! All you need to do is:
|
|
||||||
//!
|
|
||||||
//! - Download the crossterm source code.
|
|
||||||
//! - Add this in the Cargo.toml file:
|
|
||||||
//! ``` [[bin]]
|
|
||||||
//! name = "example_bin"
|
|
||||||
//! path = "./examples/bin.rs"
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! - Run program with: `cargo run`
|
|
||||||
extern crate crossterm;
|
|
||||||
|
|
||||||
use crossterm::style::Color;
|
|
||||||
use crossterm::Crossterm;
|
|
||||||
use crossterm::terminal::ClearType;
|
|
||||||
use std::thread::sleep;
|
|
||||||
use std::sync::{Arc,Mutex};
|
|
||||||
use std::io::Read;
|
|
||||||
use std::time::Duration;
|
|
||||||
// mod terminal;
|
|
||||||
// mod color;
|
|
||||||
// mod cursor;
|
|
||||||
// mod crossterm_type;
|
|
||||||
// mod input;
|
|
||||||
|
|
||||||
//use input::keyboard::{async_input, input as stdin};
|
|
||||||
|
|
||||||
use std::thread;
|
|
||||||
|
|
||||||
|
|
||||||
}fn main() {
|
|
||||||
let mut terminal = Arc::new(Mutex::new(Crossterm::new()));
|
|
||||||
let input = terminal.lock().unwrap().input().read_async();
|
|
||||||
terminal.lock().unwrap().enable_raw_mode();
|
|
||||||
let mut input_buf = Arc::new(Mutex::new(String::new()));
|
|
||||||
let mut key_buf = [0 as u8; 32];
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
swap_write(&mut terminal.lock().unwrap(), "random program output",&input_buf.lock().unwrap());
|
|
||||||
sleep(Duration::from_millis(100));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut term = terminal.lock().unwrap();
|
|
||||||
let (term_width, term_height) = term.terminal().terminal_size();
|
|
||||||
if let Ok(count) = input.read(&mut key_buf) {
|
|
||||||
for idx in 0..count {
|
|
||||||
let b = key_buf.get(idx).unwrap();
|
|
||||||
if *b == 3 {
|
|
||||||
std::process::exit(0); // Ctrl+C = exit immediate
|
|
||||||
} else if *b == 13 {
|
|
||||||
// The return key was pressed.
|
|
||||||
let mut input_buf_tmp = &mut input_buf.lock().unwrap();
|
|
||||||
input_buf.lock().unwrap().clear();
|
|
||||||
swap_write(&mut term, "", &input_buf_tmp);
|
|
||||||
} else {
|
|
||||||
let mut input_buf_tmp = &mut input_buf.lock().unwrap();
|
|
||||||
input_buf_tmp.push(*b as char);
|
|
||||||
swap_write(&mut term, "", &input_buf_tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap_write(terminal: &mut Crossterm, msg: &str, input_buf: &String) {
|
|
||||||
let (term_width, term_height) = terminal.terminal().terminal_size();
|
|
||||||
terminal.cursor().goto(0, term_height);
|
|
||||||
terminal.terminal().clear(ClearType::CurrentLine);
|
|
||||||
terminal
|
|
||||||
.terminal()
|
|
||||||
.write(format!("{}\n\r>{}", msg, input_buf));
|
|
||||||
}
|
|
@ -7,7 +7,9 @@ use winapi::um::wincon;
|
|||||||
use winapi::shared::minwindef::DWORD;
|
use winapi::shared::minwindef::DWORD;
|
||||||
use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING};
|
use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING};
|
||||||
|
|
||||||
|
use winapi::um::winnt::HANDLE;
|
||||||
use std::io::{Error, ErrorKind, Result};
|
use std::io::{Error, ErrorKind, Result};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// This command is used for enabling and disabling ANSI code support for windows systems,
|
/// This command is used for enabling and disabling ANSI code support for windows systems,
|
||||||
/// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
|
/// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
|
||||||
@ -72,14 +74,12 @@ impl IEnableAnsiCommand for EnableAnsiCommand {
|
|||||||
pub struct RawModeCommand {
|
pub struct RawModeCommand {
|
||||||
mask: DWORD,
|
mask: DWORD,
|
||||||
}
|
}
|
||||||
|
use self::wincon::{ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT, ENABLE_WRAP_AT_EOL_OUTPUT, ENABLE_PROCESSED_OUTPUT};
|
||||||
impl RawModeCommand
|
impl RawModeCommand
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
use self::wincon::{ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT};
|
|
||||||
|
|
||||||
RawModeCommand {
|
RawModeCommand {
|
||||||
mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT,
|
mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,10 +87,11 @@ impl RawModeCommand
|
|||||||
impl RawModeCommand {
|
impl RawModeCommand {
|
||||||
/// Enables raw mode.
|
/// Enables raw mode.
|
||||||
pub fn enable(&mut self) -> Result<()> {
|
pub fn enable(&mut self) -> Result<()> {
|
||||||
let input_handle = handle::get_input_handle()?;
|
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
|
let stdout = handle::get_output_handle().unwrap();
|
||||||
|
|
||||||
|
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
"Could not get console mode when enabling raw mode",
|
"Could not get console mode when enabling raw mode",
|
||||||
@ -99,7 +100,7 @@ impl RawModeCommand {
|
|||||||
|
|
||||||
let new_mode = dw_mode & !self.mask;
|
let new_mode = dw_mode & !self.mask;
|
||||||
|
|
||||||
if !kernel::set_console_mode(&input_handle, new_mode) {
|
if !kernel::set_console_mode(&stdout, new_mode) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
"Could not set console mode when enabling raw mode",
|
"Could not set console mode when enabling raw mode",
|
||||||
@ -111,10 +112,10 @@ impl RawModeCommand {
|
|||||||
|
|
||||||
/// Disables raw mode.
|
/// Disables raw mode.
|
||||||
pub fn disable(&self) -> Result<()> {
|
pub fn disable(&self) -> Result<()> {
|
||||||
let output_handle = handle::get_input_handle()?;
|
let stdout = handle::get_output_handle().unwrap();
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
"Could not get console mode when disabling raw mode",
|
"Could not get console mode when disabling raw mode",
|
||||||
@ -123,7 +124,7 @@ impl RawModeCommand {
|
|||||||
|
|
||||||
let new_mode = dw_mode | self.mask;
|
let new_mode = dw_mode | self.mask;
|
||||||
|
|
||||||
if !kernel::set_console_mode(&output_handle, new_mode) {
|
if !kernel::set_console_mode(&stdout, new_mode) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
"Could not set console mode when disabling raw mode",
|
"Could not set console mode when disabling raw mode",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//! 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 super::commands::{self, IAlternateScreenCommand};
|
use super::commands::{self, IAlternateScreenCommand};
|
||||||
use super::{functions, Screen, TerminalOutput};
|
use super::{functions, Screen, TerminalOutput,RawScreen};
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
@ -34,7 +34,8 @@ impl AlternateScreen {
|
|||||||
/// The alternate buffer is exactly the dimensions of the window, without any scrollback region.
|
/// The alternate buffer is exactly the dimensions of 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_screen(stdout: TerminalOutput) -> io::Result<AlternateScreen> {
|
pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> {
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>(
|
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>(
|
||||||
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
|
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
|
||||||
@ -46,7 +47,15 @@ impl AlternateScreen {
|
|||||||
|
|
||||||
let mut stdout = stdout;
|
let mut stdout = stdout;
|
||||||
command.enable(&mut stdout)?;
|
command.enable(&mut stdout)?;
|
||||||
return Ok(AlternateScreen::new(command, Screen::from(stdout)));
|
|
||||||
|
let screen = Screen::from(stdout);
|
||||||
|
|
||||||
|
if raw_mode
|
||||||
|
{
|
||||||
|
RawScreen::into_raw_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(AlternateScreen::new(command, screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch the alternate screen back to main screen.
|
/// Switch the alternate screen back to main screen.
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
//! With these modes you can easier design the terminal screen.
|
//! With these modes you can easier design the terminal screen.
|
||||||
|
|
||||||
use super::commands::*;
|
use super::commands::*;
|
||||||
|
use TerminalOutput;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A wrapper for the raw terminal state. Which can be used to write to.
|
/// A wrapper for the raw terminal state. Which can be used to write to.
|
||||||
pub struct RawScreen;
|
pub struct RawScreen;
|
||||||
|
@ -55,33 +55,13 @@ impl Screen
|
|||||||
{
|
{
|
||||||
if raw_mode
|
if raw_mode
|
||||||
{
|
{
|
||||||
RawScreen::into_raw_mode();;
|
let screen = Screen { stdout: Arc::new(TerminalOutput::new()), buffer: Vec::new() };
|
||||||
return Screen { stdout: Arc::new(TerminalOutput::new(true)), buffer: Vec::new() };
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Screen::default();
|
return Screen::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method could be used for enabling raw mode for the terminal.
|
|
||||||
///
|
|
||||||
/// What exactly is raw state:
|
|
||||||
/// - No line buffering.
|
|
||||||
/// Normally the terminals uses line buffering. This means that the input will be send to the terminal line by line.
|
|
||||||
/// With raw mode the input will be send one byte at a time.
|
|
||||||
/// - Input
|
|
||||||
/// All input has to be written manually by the programmer.
|
|
||||||
/// - Characters
|
|
||||||
/// The characters are not processed by the terminal driver, but are sent straight through.
|
|
||||||
/// Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal.
|
|
||||||
/// - Escape characters
|
|
||||||
/// Note that in raw modes `\n` will move to the new line but the cursor will be at the same position as before on the new line therefor use `\n\r` to start at the new line at the first cell.
|
|
||||||
///
|
|
||||||
/// With these modes you can easier design the terminal screen.
|
|
||||||
pub fn enable_raw_modes(&self) -> Result<()> {
|
|
||||||
RawScreen::into_raw_mode()?;
|
|
||||||
return Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
|
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
|
||||||
///
|
///
|
||||||
/// # What is Alternate screen?
|
/// # What is Alternate screen?
|
||||||
@ -90,14 +70,9 @@ impl Screen
|
|||||||
/// 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 enable_alternate_modes(&self, raw_mode: bool) -> Result<AlternateScreen> {
|
pub fn enable_alternate_modes(&self, raw_mode: bool) -> Result<AlternateScreen> {
|
||||||
let stdout = TerminalOutput::new(raw_mode);
|
let stdout = TerminalOutput::new();
|
||||||
|
|
||||||
if raw_mode
|
let alternate_screen = AlternateScreen::to_alternate_screen(stdout, raw_mode)?;
|
||||||
{
|
|
||||||
RawScreen::into_raw_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
let alternate_screen = AlternateScreen::to_alternate_screen(stdout)?;
|
|
||||||
return Ok(alternate_screen);
|
return Ok(alternate_screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +97,7 @@ impl Default for Screen
|
|||||||
{
|
{
|
||||||
/// Create an new screen which will not be in raw mode or alternate mode.
|
/// Create an new screen which will not be in raw mode or alternate mode.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
return Screen { stdout: Arc::new(TerminalOutput::new(false)), buffer: Vec::new() };
|
return Screen { stdout: Arc::new(TerminalOutput::new()), buffer: Vec::new() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use Screen;
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use self::crossterm::cursor::cursor;
|
/// use self::crossterm::cursor;
|
||||||
/// use self::crossterm::Screen;
|
/// use self::crossterm::Screen;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default();
|
||||||
|
@ -11,7 +11,7 @@ use Screen;
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use self::crossterm::Screen;
|
/// use self::crossterm::Screen;
|
||||||
/// use self::crossterm::input::input;
|
/// use self::crossterm::input;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default();
|
||||||
/// let input = input(&screen);
|
/// let input = input(&screen);
|
||||||
|
@ -22,6 +22,7 @@ use super::*;
|
|||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use screen::RawScreen;
|
||||||
|
|
||||||
/// Struct that is an handle to an terminal screen.
|
/// Struct that is an handle to an terminal screen.
|
||||||
/// This handle could be used to write to the current screen
|
/// This handle could be used to write to the current screen
|
||||||
@ -34,7 +35,7 @@ pub struct TerminalOutput {
|
|||||||
|
|
||||||
impl TerminalOutput {
|
impl TerminalOutput {
|
||||||
/// Create new screen write instance whereon screen related actions can be performed.
|
/// Create new screen write instance whereon screen related actions can be performed.
|
||||||
pub fn new(is_in_raw_mode: bool) -> Self {
|
pub fn new() -> Self {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let stdout: Box<IStdout + Send + Sync> = functions::get_module::<Box<IStdout + Send + Sync>>(
|
let stdout: Box<IStdout + Send + Sync> = functions::get_module::<Box<IStdout + Send + Sync>>(
|
||||||
Box::from(WinApiOutput::new()),
|
Box::from(WinApiOutput::new()),
|
||||||
@ -44,7 +45,7 @@ impl TerminalOutput {
|
|||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let stdout = Box::from(AnsiStdout::new()) as Box<IStdout + Send + Sync>;
|
let stdout = Box::from(AnsiStdout::new()) as Box<IStdout + Send + Sync>;
|
||||||
|
|
||||||
TerminalOutput { stdout , is_in_raw_mode}
|
TerminalOutput { stdout , is_in_raw_mode: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write String to the current screen.
|
/// Write String to the current screen.
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use super::IStdout;
|
use super::IStdout;
|
||||||
|
use screen::RawScreen;
|
||||||
|
use common::commands::win_commands::RawModeCommand;
|
||||||
use kernel::windows_kernel::{handle, writing};
|
use kernel::windows_kernel::{handle, writing};
|
||||||
use winapi::um::winnt::HANDLE;
|
use winapi::um::winnt::HANDLE;
|
||||||
|
|
||||||
@ -9,6 +11,7 @@ use std::io;
|
|||||||
/// This struct is a wrapper for WINAPI `HANDLE`
|
/// This struct is a wrapper for WINAPI `HANDLE`
|
||||||
pub struct WinApiOutput {
|
pub struct WinApiOutput {
|
||||||
pub handle: Mutex<HANDLE>,
|
pub handle: Mutex<HANDLE>,
|
||||||
|
raw_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IStdout for WinApiOutput {
|
impl IStdout for WinApiOutput {
|
||||||
@ -21,7 +24,6 @@ impl IStdout for WinApiOutput {
|
|||||||
writing::write_char_buffer(&self.handle.lock().unwrap(), buf)
|
writing::write_char_buffer(&self.handle.lock().unwrap(), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn flush(&self) -> io::Result<()> {
|
fn flush(&self) -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -37,7 +39,8 @@ impl IStdout for WinApiOutput {
|
|||||||
|
|
||||||
impl WinApiOutput {
|
impl WinApiOutput {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
WinApiOutput { handle: Mutex::new(handle::get_output_handle().unwrap()) }
|
let handle = handle::get_output_handle().unwrap();
|
||||||
|
WinApiOutput { raw_mode: false, handle: Mutex::new(handle) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, handle: HANDLE)
|
pub fn set(&mut self, handle: HANDLE)
|
||||||
@ -47,8 +50,7 @@ impl WinApiOutput {
|
|||||||
|
|
||||||
pub fn get_handle(&self) -> HANDLE
|
pub fn get_handle(&self) -> HANDLE
|
||||||
{
|
{
|
||||||
let gx = self.handle.lock();
|
return self.handle.lock().unwrap().clone();
|
||||||
gx.unwrap().clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,14 @@ use Screen;
|
|||||||
|
|
||||||
/// Struct that stores an specific platform implementation for color related actions.
|
/// Struct that stores an specific platform implementation for color related actions.
|
||||||
///
|
///
|
||||||
|
/// For styling text use the `::crossterm::style()` function. `TerminalColor` will set the colors of the screen permanently and the `style()` will only style the text given.
|
||||||
|
///
|
||||||
/// Check `/examples/color` in the library for more specific examples.
|
/// Check `/examples/color` in the library for more specific examples.
|
||||||
///
|
///
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use crossterm::{Screen}
|
/// use crossterm::{Screen}
|
||||||
/// use crossterm::color::color;
|
/// use crossterm::style::color;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default();
|
||||||
/// let colored_terminal = color(&screen);
|
/// let colored_terminal = color(&screen);
|
||||||
|
@ -140,7 +140,7 @@ impl<D: Display> StyledObject<D> {
|
|||||||
self.attr(Attribute::CrossedOut)
|
self.attr(Attribute::CrossedOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This could be used to paint the styled object on the screen. Pass a refrence to the screen whereon you want to perform the painting.
|
/// This could be used to paint the styled object on the screen. Pass a reference to the screen whereon you want to perform the painting.
|
||||||
///
|
///
|
||||||
/// ``` rust
|
/// ``` rust
|
||||||
/// style("Some colored text")
|
/// style("Some colored text")
|
||||||
|
@ -10,7 +10,7 @@ use std::fmt;
|
|||||||
/// Check `/examples/terminal` in the library for more specific examples.
|
/// Check `/examples/terminal` in the library for more specific examples.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use crossterm::terminal::terminal;
|
/// use crossterm::terminal;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default();
|
||||||
/// let term = terminal(&screen);
|
/// let term = terminal(&screen);
|
||||||
|
Loading…
Reference in New Issue
Block a user