Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raw Screen Cursor Position UNIX Bug Fix #134

Merged
merged 2 commits into from
May 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ members = [
]

[dependencies]
crossterm_screen = { optional = true, version = "0.2.1" }
crossterm_cursor = { optional = true, version = "0.2.1" }
crossterm_screen = { optional = true, path = "./crossterm_screen" }
crossterm_cursor = { optional = true, path = "./crossterm_cursor" }
crossterm_terminal = { optional = true, version = "0.2.2" }
crossterm_style = { optional = true, version = "0.3.1" }
crossterm_input = { optional = true, version = "0.3.3" }
crossterm_utils = { optional = false, version = "0.2.1" }
crossterm_style = { optional = true, path = "./crossterm_style" }
crossterm_input = { optional = true, path = "./crossterm_input" }
crossterm_utils = { optional = false, path = "./crossterm_utils" }

[lib]
name = "crossterm"
Expand Down
2 changes: 1 addition & 1 deletion crossterm_cursor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ winapi = { version = "0.3.7", features = ["wincon","winnt","minwindef"] }
crossterm_winapi = "0.1.2"

[dependencies]
crossterm_utils = "0.2.1"
crossterm_utils = { path = "../crossterm_utils" }
47 changes: 20 additions & 27 deletions crossterm_cursor/src/sys/unix.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
use crossterm_utils::sys::unix;
use crossterm_utils::sys::unix::{self, RAW_MODE_ENABLED};
use std::io::{self, Error, ErrorKind, Read, Write};

/// Get the cursor position based on the current platform.
#[cfg(unix)]
pub fn get_cursor_position() -> (u16, u16) {
if let Ok(pos) = pos() {
pos
if unsafe { RAW_MODE_ENABLED } {
if let Ok(pos) = pos_raw() {
pos
} else {
(0, 0)
}
} else {
(0, 0)
if let Ok(pos) = pos() {
pos
} else {
(0, 0)
}
}
}

pub fn pos() -> io::Result<(u16, u16)> {
// if we enable raw modes with screen, this could cause problems if raw mode is already enabled in application.
// I am not completely happy with this approach so feel free to find an other way.

unsafe {
if !unix::RAW_MODE_ENABLED_BY_USER || !unix::RAW_MODE_ENABLED_BY_SYSTEM {
// set this boolean so that we know that the systems has enabled raw mode.
unix::RAW_MODE_ENABLED_BY_SYSTEM = true;
unix::into_raw_mode()?;
}
}
unix::into_raw_mode()?;
let pos = pos_raw();
unix::disable_raw_mode()?;
pos
}

pub fn pos_raw() -> io::Result<(u16, u16)> {
// Where is the cursor?
// Use `ESC [ 6 n`.
let mut stdout = io::stdout();
Expand Down Expand Up @@ -69,21 +73,10 @@ pub fn pos() -> io::Result<(u16, u16)> {
let (cols, c) = read_num()?;

// Expect `R`
let res = if c == 'R' {
if c == 'R' {
// subtract one to get 0-based coords
Ok(((cols - 1) as u16, (rows - 1) as u16))
} else {
return Err(Error::new(ErrorKind::Other, "test"));
};

// If raw mode is enabled from else where in the application (by the user) we do not want to disable raw modes.
// I am not completely happy with this approach so feel free to find an other way.
unsafe {
if unix::RAW_MODE_ENABLED_BY_SYSTEM && !unix::RAW_MODE_ENABLED_BY_USER {
unix::RAW_MODE_ENABLED_BY_SYSTEM = false;
unix::disable_raw_mode()?;
}
Err(Error::new(ErrorKind::Other, "test"))
}

res
}
4 changes: 2 additions & 2 deletions crossterm_input/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ crossterm_winapi = "0.1.2"
libc = "0.2.51"

[dependencies]
crossterm_utils = "0.2.1"
crossterm_screen = "0.2.1"
crossterm_utils = {path = "../crossterm_utils"}
crossterm_screen = {path = "../crossterm_screen"}
2 changes: 1 addition & 1 deletion crossterm_input/src/input/unix_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Iterator for SyncReader {
},
Ok(2) => {
let option_iter = &mut Some(buf[1]).into_iter();
let mut iter = option_iter.map(|c| Ok(c)).chain(source.bytes());
let iter = option_iter.map(|c| Ok(c)).chain(source.bytes());
if let Ok(e) = parse_event(buf[0], &mut iter.flatten()) {
self.leftover = option_iter.next();
Some(e)
Expand Down
1 change: 0 additions & 1 deletion crossterm_input/src/sys/unix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crossterm_utils::sys::unix;
use std::fs;
use std::io;
use std::os::unix::io::AsRawFd;
Expand Down
2 changes: 1 addition & 1 deletion crossterm_screen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ readme = "README.md"
edition = "2018"

[dependencies]
crossterm_utils = "0.2.1"
crossterm_utils = {path = "../crossterm_utils"}

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.7", features = ["minwindef", "wincon"] }
Expand Down
6 changes: 3 additions & 3 deletions crossterm_screen/src/screen/alternate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct AlternateScreen {
command: Box<(dyn IAlternateScreenCommand + Sync + Send)>,
#[cfg(unix)]
command: sys::ToAlternateScreenCommand,
raw_screen: Option<RawScreen>,
_raw_screen: Option<RawScreen>,
}

impl AlternateScreen {
Expand Down Expand Up @@ -56,13 +56,13 @@ impl AlternateScreen {
let raw_screen = RawScreen::into_raw_mode()?;
return Ok(AlternateScreen {
command,
raw_screen: Some(raw_screen),
_raw_screen: Some(raw_screen),
});
}

Ok(AlternateScreen {
command,
raw_screen: None,
_raw_screen: None,
})
}

Expand Down
10 changes: 6 additions & 4 deletions crossterm_utils/src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ pub use libc::{c_int, termios as Termios};
use std::{io, mem};

static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
pub static mut RAW_MODE_ENABLED_BY_SYSTEM: bool = false;
pub static mut RAW_MODE_ENABLED_BY_USER: bool = false;
pub static mut RAW_MODE_ENABLED: bool = false;

fn unwrap(t: i32) -> io::Result<()> {
if t == -1 {
Expand Down Expand Up @@ -48,10 +47,11 @@ pub fn into_raw_mode() -> io::Result<()> {

unsafe {
if ORIGINAL_TERMINAL_MODE.is_none() {
ORIGINAL_TERMINAL_MODE = Some(prev_ios.clone())
ORIGINAL_TERMINAL_MODE = Some(prev_ios.clone());
}
}

RAW_MODE_ENABLED = true;
}
raw_terminal_attr(&mut ios);
set_terminal_attr(&ios)?;
Ok(())
Expand All @@ -61,6 +61,8 @@ pub fn disable_raw_mode() -> io::Result<()> {
unsafe {
if ORIGINAL_TERMINAL_MODE.is_some() {
set_terminal_attr(&ORIGINAL_TERMINAL_MODE.unwrap())?;

RAW_MODE_ENABLED = false;
}
}
Ok(())
Expand Down
86 changes: 15 additions & 71 deletions examples/crossterm.rs
Original file line number Diff line number Diff line change
@@ -1,76 +1,20 @@
extern crate crossterm;

//use crossterm::{Color, Crossterm};

use crossterm::{
AlternateScreen, Attribute, ClearType, Crossterm, InputEvent, KeyEvent, Styler, TerminalCursor,
};
use std::io::Write;
use std::{io, thread, time};
use crossterm::{Color, Crossterm};
// use the `Crossterm` to get an instance to the cursor module | demonstration.
pub fn main() {
// Create the crossterm type to access different modules.
let crossterm = Crossterm::new();

fn run() -> io::Result<()> {
let alternate_screen = AlternateScreen::to_alternate(true)?;
let crossterm = crossterm::Crossterm::new();
let input = crossterm.input();
let mut crossterm_events = input.read_sync();
loop {
if let Some(event) = crossterm_events.next() {
let terminal = crossterm.terminal();
let cursor = crossterm.cursor();
cursor.goto(1, 1)?;
terminal.clear(ClearType::UntilNewLine)?;
if let InputEvent::Keyboard(key) = &event {
match key {
KeyEvent::Ctrl('q') => {
println!("quitting...");
::std::io::stdout().flush();
break;
}
_ => {
let s = "event";
println!(
" {}{}{} : {:?}",
Attribute::Bold,
s,
Attribute::Reset,
event
);
}
}
} else {
println!("disregarding unrelevant event: {:?}", event);
}
}
}
thread::sleep(time::Duration::from_secs(1));
Ok(())
}
// pass a reference to the current screen.
let cursor = crossterm.cursor();
let color = crossterm.color();
let terminal = crossterm.terminal();
let terminal = crossterm.input();
let style = crossterm
.style("Black font on green background")
.with(Color::Black)
.on(Color::Green);

fn main() {
match run() {
Ok(_) => {
println!("ok");
}
Err(e) => {
println!("error {:?}", e);
}
}
// TODO: perform some actions with the instances above.
}

// use the `Crossterm` to get an instance to the cursor module | demonstration.
//pub fn main() {
// // Create the crossterm type to access different modules.
// let crossterm = Crossterm::new();
//
// // pass a reference to the current screen.
// let cursor = crossterm.cursor();
// let color = crossterm.color();
// let terminal = crossterm.terminal();
// let terminal = crossterm.input();
// let style = crossterm
// .style("Black font on green background")
// .with(Color::Black)
// .on(Color::Green);
//
// // TODO: perform some actions with the instances above.
//}
2 changes: 1 addition & 1 deletion examples/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ pub fn blink_cursor() {
}

fn main() {
save_and_reset_position().unwrap();
pos()
}