API Cleanup - part 1 (#235)
This commit is contained in:
parent
7d47354307
commit
41de9a63a1
10
.travis.yml
10
.travis.yml
@ -29,12 +29,4 @@ script:
|
|||||||
- if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
- if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
||||||
- cargo build
|
- cargo build
|
||||||
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then cargo test --all -- --nocapture --test-threads 1; else cargo test --all --exclude crossterm_winapi -- --nocapture --test-threads 1; fi
|
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then cargo test --all -- --nocapture --test-threads 1; else cargo test --all --exclude crossterm_winapi -- --nocapture --test-threads 1; fi
|
||||||
- |
|
- scripts/test-examples.sh
|
||||||
pushd examples/program_examples
|
|
||||||
for d in */ ; do
|
|
||||||
pushd "$d"
|
|
||||||
cargo build
|
|
||||||
if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
|
||||||
popd
|
|
||||||
done
|
|
||||||
popd
|
|
||||||
|
@ -29,9 +29,7 @@ trait ITerminalCursor: Sync + Send {
|
|||||||
/// Goto location (`x`, `y`) in the current terminal window.
|
/// Goto location (`x`, `y`) in the current terminal window.
|
||||||
fn goto(&self, x: u16, y: u16) -> Result<()>;
|
fn goto(&self, x: u16, y: u16) -> Result<()>;
|
||||||
/// Get the cursor location `(x, y)` in the current terminal window.
|
/// Get the cursor location `(x, y)` in the current terminal window.
|
||||||
///
|
fn pos(&self) -> Result<(u16, u16)>;
|
||||||
/// `(0, 0)` is returned in case of an error.
|
|
||||||
fn pos(&self) -> (u16, u16);
|
|
||||||
/// Move cursor `n` times up
|
/// Move cursor `n` times up
|
||||||
fn move_up(&self, count: u16) -> Result<()>;
|
fn move_up(&self, count: u16) -> Result<()>;
|
||||||
/// Move the cursor `n` times to the right.
|
/// Move the cursor `n` times to the right.
|
||||||
|
@ -51,7 +51,7 @@ impl ITerminalCursor for AnsiCursor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> (u16, u16) {
|
fn pos(&self) -> Result<(u16, u16)> {
|
||||||
get_cursor_position()
|
get_cursor_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,13 +115,17 @@ mod tests {
|
|||||||
fn reset_safe_ansi() {
|
fn reset_safe_ansi() {
|
||||||
if try_enable_ansi() {
|
if try_enable_ansi() {
|
||||||
let cursor = AnsiCursor::new();
|
let cursor = AnsiCursor::new();
|
||||||
let (x, y) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x, y) = pos.unwrap();
|
||||||
|
|
||||||
assert!(cursor.save_position().is_ok());
|
assert!(cursor.save_position().is_ok());
|
||||||
assert!(cursor.goto(5, 5).is_ok());
|
assert!(cursor.goto(5, 5).is_ok());
|
||||||
assert!(cursor.reset_position().is_ok());
|
assert!(cursor.reset_position().is_ok());
|
||||||
|
|
||||||
let (x_saved, y_saved) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x_saved, y_saved) = pos.unwrap();
|
||||||
|
|
||||||
assert_eq!(x, x_saved);
|
assert_eq!(x, x_saved);
|
||||||
assert_eq!(y, y_saved);
|
assert_eq!(y, y_saved);
|
||||||
@ -134,10 +138,14 @@ mod tests {
|
|||||||
fn goto_ansi() {
|
fn goto_ansi() {
|
||||||
if try_enable_ansi() {
|
if try_enable_ansi() {
|
||||||
let cursor = AnsiCursor::new();
|
let cursor = AnsiCursor::new();
|
||||||
let (x_saved, y_saved) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x_saved, y_saved) = pos.unwrap();
|
||||||
|
|
||||||
assert!(cursor.goto(5, 5).is_ok());
|
assert!(cursor.goto(5, 5).is_ok());
|
||||||
let (x, y) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x, y) = pos.unwrap();
|
||||||
|
|
||||||
assert!(cursor.goto(x_saved, y_saved).is_ok());
|
assert!(cursor.goto(x_saved, y_saved).is_ok());
|
||||||
|
|
||||||
|
@ -59,32 +59,32 @@ impl TerminalCursor {
|
|||||||
///
|
///
|
||||||
/// # Remarks
|
/// # Remarks
|
||||||
/// position is 0-based, which means we start counting at 0.
|
/// position is 0-based, which means we start counting at 0.
|
||||||
pub fn pos(&self) -> (u16, u16) {
|
pub fn pos(&self) -> Result<(u16, u16)> {
|
||||||
self.cursor.pos()
|
self.cursor.pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times up.
|
/// Move the current cursor position `n` times up.
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_up(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
||||||
self.cursor.move_up(count).unwrap();
|
self.cursor.move_up(count)?;
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times right.
|
/// Move the current cursor position `n` times right.
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_right(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
||||||
self.cursor.move_right(count).unwrap();
|
self.cursor.move_right(count)?;
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times down.
|
/// Move the current cursor position `n` times down.
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_down(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
||||||
self.cursor.move_down(count).unwrap();
|
self.cursor.move_down(count)?;
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times left.
|
/// Move the current cursor position `n` times left.
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
||||||
self.cursor.move_left(count).unwrap();
|
self.cursor.move_left(count).unwrap();
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save cursor position for recall later.
|
/// Save cursor position for recall later.
|
||||||
|
@ -24,31 +24,31 @@ impl ITerminalCursor for WinApiCursor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> (u16, u16) {
|
fn pos(&self) -> Result<(u16, u16)> {
|
||||||
let cursor = Cursor::new().unwrap();
|
let cursor = Cursor::new()?;
|
||||||
cursor.position().map(Into::into).unwrap_or((0, 0))
|
Ok(cursor.position()?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16) -> Result<()> {
|
fn move_up(&self, count: u16) -> Result<()> {
|
||||||
let (xpos, ypos) = self.pos();
|
let (xpos, ypos) = self.pos()?;
|
||||||
self.goto(xpos, ypos - count)?;
|
self.goto(xpos, ypos - count)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16) -> Result<()> {
|
fn move_right(&self, count: u16) -> Result<()> {
|
||||||
let (xpos, ypos) = self.pos();
|
let (xpos, ypos) = self.pos()?;
|
||||||
self.goto(xpos + count, ypos)?;
|
self.goto(xpos + count, ypos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16) -> Result<()> {
|
fn move_down(&self, count: u16) -> Result<()> {
|
||||||
let (xpos, ypos) = self.pos();
|
let (xpos, ypos) = self.pos()?;
|
||||||
self.goto(xpos, ypos + count)?;
|
self.goto(xpos, ypos + count)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16) -> Result<()> {
|
fn move_left(&self, count: u16) -> Result<()> {
|
||||||
let (xpos, ypos) = self.pos();
|
let (xpos, ypos) = self.pos()?;
|
||||||
self.goto(xpos - count, ypos)?;
|
self.goto(xpos - count, ypos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -87,7 +87,9 @@ mod tests {
|
|||||||
let cursor = WinApiCursor::new();
|
let cursor = WinApiCursor::new();
|
||||||
|
|
||||||
assert!(cursor.goto(5, 5).is_ok());
|
assert!(cursor.goto(5, 5).is_ok());
|
||||||
let (x, y) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x, y) = pos.unwrap();
|
||||||
|
|
||||||
assert_eq!(x, 5);
|
assert_eq!(x, 5);
|
||||||
assert_eq!(y, 5);
|
assert_eq!(y, 5);
|
||||||
@ -96,13 +98,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn reset_safe_winapi() {
|
fn reset_safe_winapi() {
|
||||||
let cursor = WinApiCursor::new();
|
let cursor = WinApiCursor::new();
|
||||||
let (x, y) = cursor.pos();
|
|
||||||
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x, y) = pos.unwrap();
|
||||||
|
|
||||||
assert!(cursor.save_position().is_ok());
|
assert!(cursor.save_position().is_ok());
|
||||||
assert!(cursor.goto(5, 5).is_ok());
|
assert!(cursor.goto(5, 5).is_ok());
|
||||||
assert!(cursor.reset_position().is_ok());
|
assert!(cursor.reset_position().is_ok());
|
||||||
|
|
||||||
let (x_saved, y_saved) = cursor.pos();
|
let pos = cursor.pos();
|
||||||
|
assert!(pos.is_ok());
|
||||||
|
let (x_saved, y_saved) = pos.unwrap();
|
||||||
|
|
||||||
assert_eq!(x, x_saved);
|
assert_eq!(x, x_saved);
|
||||||
assert_eq!(y, y_saved);
|
assert_eq!(y, y_saved);
|
||||||
|
@ -7,11 +7,11 @@ use crossterm_utils::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn get_cursor_position() -> (u16, u16) {
|
pub fn get_cursor_position() -> Result<(u16, u16)> {
|
||||||
if unsafe { RAW_MODE_ENABLED } {
|
if unsafe { RAW_MODE_ENABLED } {
|
||||||
pos_raw().unwrap_or((0, 0))
|
pos_raw()
|
||||||
} else {
|
} else {
|
||||||
pos().unwrap_or((0, 0))
|
pos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,33 +45,17 @@ pub fn pos_raw() -> Result<(u16, u16)> {
|
|||||||
stdin.lock().read_until(b'[', &mut vec![])?;
|
stdin.lock().read_until(b'[', &mut vec![])?;
|
||||||
|
|
||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
stdin.lock().read_until(b';', &mut rows).unwrap();
|
stdin.lock().read_until(b';', &mut rows)?;
|
||||||
|
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
stdin.lock().read_until(b'R', &mut cols).unwrap();
|
stdin.lock().read_until(b'R', &mut cols)?;
|
||||||
|
|
||||||
// remove delimiter
|
// remove delimiter
|
||||||
rows.pop();
|
rows.pop();
|
||||||
cols.pop();
|
cols.pop();
|
||||||
|
|
||||||
let rows = rows
|
let rows = String::from_utf8(rows)?.parse::<u16>()?;
|
||||||
.into_iter()
|
let cols = String::from_utf8(cols)?.parse::<u16>()?;
|
||||||
.map(|b| (b as char))
|
|
||||||
.fold(String::new(), |mut acc, n| {
|
|
||||||
acc.push(n);
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
.parse::<usize>()
|
|
||||||
.unwrap();
|
|
||||||
let cols = cols
|
|
||||||
.into_iter()
|
|
||||||
.map(|b| (b as char))
|
|
||||||
.fold(String::new(), |mut acc, n| {
|
|
||||||
acc.push(n);
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
.parse::<usize>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(((cols - 1) as u16, (rows - 1) as u16))
|
Ok((cols - 1, rows - 1))
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,9 @@ 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)]
|
||||||
pub fn get_cursor_position() -> (u16, u16) {
|
pub fn get_cursor_position() -> Result<(u16, u16)> {
|
||||||
if let Ok(cursor) = Cursor::new() {
|
let cursor = Cursor::new()?;
|
||||||
cursor.position().unwrap().into()
|
Ok(cursor.position()?.into())
|
||||||
} else {
|
|
||||||
(0, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -90,26 +90,26 @@ use crossterm::terminal::{terminal,ClearType};
|
|||||||
let mut terminal = terminal();
|
let mut terminal = terminal();
|
||||||
|
|
||||||
// Clear all lines in terminal;
|
// Clear all lines in terminal;
|
||||||
terminal.clear(ClearType::All);
|
terminal.clear(ClearType::All)?;
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorDown);
|
terminal.clear(ClearType::FromCursorDown)?;
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorUp);
|
terminal.clear(ClearType::FromCursorUp)?;
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine);
|
terminal.clear(ClearType::CurrentLine)?;
|
||||||
// Clear all the cells until next line.
|
// Clear all the cells until next line.
|
||||||
terminal.clear(ClearType::UntilNewLine);
|
terminal.clear(ClearType::UntilNewLine)?;
|
||||||
|
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let (width, height) = terminal.terminal_size();
|
let (width, height) = terminal.size()?;
|
||||||
print!("X: {}, y: {}", width, height);
|
print!("X: {}, y: {}", width, height);
|
||||||
|
|
||||||
// Scroll down, up 10 lines.
|
// Scroll down, up 10 lines.
|
||||||
terminal.scroll_down(10);
|
terminal.scroll_down(10)?;
|
||||||
terminal.scroll_up(10);
|
terminal.scroll_up(10)?;
|
||||||
|
|
||||||
// Set terminal size (width, height)
|
// Set terminal size (width, height)
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10)?;
|
||||||
|
|
||||||
// exit the current process.
|
// exit the current process.
|
||||||
terminal.exit();
|
terminal.exit();
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ};
|
use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ};
|
||||||
|
|
||||||
|
use crossterm_utils::Result;
|
||||||
|
|
||||||
pub fn exit() {
|
pub fn exit() {
|
||||||
::std::process::exit(0);
|
::std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current terminal size.
|
/// Get the current terminal size.
|
||||||
pub fn get_terminal_size() -> (u16, u16) {
|
pub fn get_terminal_size() -> Result<(u16, u16)> {
|
||||||
// http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
|
// http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
|
||||||
let mut size = winsize {
|
let mut size = winsize {
|
||||||
ws_row: 0,
|
ws_row: 0,
|
||||||
@ -16,8 +18,8 @@ pub fn get_terminal_size() -> (u16, u16) {
|
|||||||
let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) };
|
let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) };
|
||||||
|
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
(size.ws_col, size.ws_row)
|
Ok((size.ws_col, size.ws_row))
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
Err(std::io::Error::last_os_error().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crossterm_utils::Result;
|
||||||
use crossterm_winapi::ScreenBuffer;
|
use crossterm_winapi::ScreenBuffer;
|
||||||
|
|
||||||
/// Exit the current process.
|
/// Exit the current process.
|
||||||
@ -6,11 +7,7 @@ pub fn exit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn get_terminal_size() -> (u16, u16) {
|
pub fn get_terminal_size() -> Result<(u16, u16)> {
|
||||||
if let Ok(buffer) = ScreenBuffer::current() {
|
let buffer = ScreenBuffer::current()?;
|
||||||
let size = buffer.info().unwrap().terminal_size();
|
Ok(buffer.info()?.terminal_size().into())
|
||||||
((size.width + 1) as u16, (size.height + 1) as u16)
|
|
||||||
} else {
|
|
||||||
(0, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -43,11 +43,11 @@ trait ITerminal {
|
|||||||
/// Clear the current cursor by specifying the clear type
|
/// Clear the current cursor by specifying the clear type
|
||||||
fn clear(&self, clear_type: ClearType) -> Result<()>;
|
fn clear(&self, clear_type: ClearType) -> Result<()>;
|
||||||
/// Get the terminal size (x,y)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self) -> (u16, u16);
|
fn size(&self) -> Result<(u16, u16)>;
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
fn scroll_up(&self, count: i16) -> Result<()>;
|
fn scroll_up(&self, count: u16) -> Result<()>;
|
||||||
/// Scroll `n` lines down in the current terminal.
|
/// Scroll `n` lines down in the current terminal.
|
||||||
fn scroll_down(&self, count: i16) -> Result<()>;
|
fn scroll_down(&self, count: u16) -> Result<()>;
|
||||||
/// Resize terminal to the given width and height.
|
/// Resize terminal to the given width and height.
|
||||||
fn set_size(&self, width: i16, height: i16) -> Result<()>;
|
fn set_size(&self, width: u16, height: u16) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
@ -15,17 +15,17 @@ pub static CLEAR_FROM_CURRENT_LINE: &'static str = csi!("2K");
|
|||||||
pub static CLEAR_UNTIL_NEW_LINE: &'static str = csi!("K");
|
pub static CLEAR_UNTIL_NEW_LINE: &'static str = csi!("K");
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_scroll_up_ansi(count: i16) -> String {
|
pub fn get_scroll_up_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}S"), count)
|
format!(csi!("{}S"), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_scroll_down_ansi(count: i16) -> String {
|
pub fn get_scroll_down_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}T"), count)
|
format!(csi!("{}T"), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_set_size_ansi(width: i16, height: i16) -> String {
|
pub fn get_set_size_ansi(width: u16, height: u16) -> String {
|
||||||
format!(csi!("8;{};{}t"), height, width)
|
format!(csi!("8;{};{}t"), height, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,21 +61,21 @@ impl ITerminal for AnsiTerminal {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self) -> (u16, u16) {
|
fn size(&self) -> Result<(u16, u16)> {
|
||||||
get_terminal_size()
|
get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16) -> Result<()> {
|
fn scroll_up(&self, count: u16) -> Result<()> {
|
||||||
write_cout!(get_scroll_up_ansi(count))?;
|
write_cout!(get_scroll_up_ansi(count))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16) -> Result<()> {
|
fn scroll_down(&self, count: u16) -> Result<()> {
|
||||||
write_cout!(get_scroll_down_ansi(count))?;
|
write_cout!(get_scroll_down_ansi(count))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, width: i16, height: i16) -> Result<()> {
|
fn set_size(&self, width: u16, height: u16) -> Result<()> {
|
||||||
write_cout!(get_set_size_ansi(width, height))?;
|
write_cout!(get_set_size_ansi(width, height))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -100,7 +100,9 @@ mod tests {
|
|||||||
// see issue: https://github.com/eminence/terminal-size/issues/11
|
// see issue: https://github.com/eminence/terminal-size/issues/11
|
||||||
thread::sleep(time::Duration::from_millis(30));
|
thread::sleep(time::Duration::from_millis(30));
|
||||||
|
|
||||||
let (x, y) = terminal.terminal_size();
|
let size = terminal.size();
|
||||||
|
assert!(size.is_ok());
|
||||||
|
let (x, y) = size.unwrap();
|
||||||
|
|
||||||
assert_eq!(x, 50);
|
assert_eq!(x, 50);
|
||||||
assert_eq!(y, 50);
|
assert_eq!(y, 50);
|
||||||
|
@ -70,19 +70,16 @@ impl Terminal {
|
|||||||
self.terminal.clear(clear_type)
|
self.terminal.clear(clear_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the terminal size (x,y).
|
/// Get the terminal size `(x,y)`.
|
||||||
///
|
pub fn size(&self) -> Result<(u16, u16)> {
|
||||||
/// # Remark
|
self.terminal.size()
|
||||||
/// This will return a tuple of (x: u16, y: u16)
|
|
||||||
pub fn terminal_size(&self) -> (u16, u16) {
|
|
||||||
self.terminal.terminal_size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
///
|
///
|
||||||
/// # Parameter
|
/// # Parameter
|
||||||
/// - `count`: the number of rows should be shifted up.
|
/// - `count`: the number of rows should be shifted up.
|
||||||
pub fn scroll_up(&self, count: i16) -> Result<()> {
|
pub fn scroll_up(&self, count: u16) -> Result<()> {
|
||||||
self.terminal.scroll_up(count)
|
self.terminal.scroll_up(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +87,7 @@ impl Terminal {
|
|||||||
///
|
///
|
||||||
/// # Parameter
|
/// # Parameter
|
||||||
/// - `count`: the number of rows should be shifted down.
|
/// - `count`: the number of rows should be shifted down.
|
||||||
pub fn scroll_down(&self, count: i16) -> Result<()> {
|
pub fn scroll_down(&self, count: u16) -> Result<()> {
|
||||||
self.terminal.scroll_down(count)
|
self.terminal.scroll_down(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +100,7 @@ impl Terminal {
|
|||||||
/// // Set of the size to X: 10 and Y: 10
|
/// // Set of the size to X: 10 and Y: 10
|
||||||
/// let size = term.set_size(10,10);
|
/// let size = term.set_size(10,10);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_size(&self, width: i16, height: i16) -> Result<()> {
|
pub fn set_size(&self, width: u16, height: u16) -> Result<()> {
|
||||||
self.terminal.set_size(width, height)
|
self.terminal.set_size(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +140,7 @@ pub fn terminal() -> Terminal {
|
|||||||
/// When executed, this command will scroll up the terminal buffer by the given number of times.
|
/// When executed, this command will scroll up the terminal buffer by the given number of times.
|
||||||
///
|
///
|
||||||
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
||||||
pub struct ScrollUp(pub i16);
|
pub struct ScrollUp(pub u16);
|
||||||
|
|
||||||
impl Command for ScrollUp {
|
impl Command for ScrollUp {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
@ -161,7 +158,7 @@ impl Command for ScrollUp {
|
|||||||
/// When executed, this command will scroll down the terminal buffer by the given number of times.
|
/// When executed, this command will scroll down the terminal buffer by the given number of times.
|
||||||
///
|
///
|
||||||
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
||||||
pub struct ScrollDown(pub i16);
|
pub struct ScrollDown(pub u16);
|
||||||
|
|
||||||
impl Command for ScrollDown {
|
impl Command for ScrollDown {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
@ -209,7 +206,7 @@ impl Command for Clear {
|
|||||||
/// When executed, this command will set the terminal sie to the given (`width` and `height`)
|
/// When executed, this command will set the terminal sie to the given (`width` and `height`)
|
||||||
///
|
///
|
||||||
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
/// See `crossterm/examples/command.rs` for more information on how to execute commands.
|
||||||
pub struct SetSize(pub i16, pub i16);
|
pub struct SetSize(pub u16, pub u16);
|
||||||
|
|
||||||
impl Command for SetSize {
|
impl Command for SetSize {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
|
@ -41,15 +41,16 @@ impl ITerminal for WinApiTerminal {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self) -> (u16, u16) {
|
fn size(&self) -> Result<(u16, u16)> {
|
||||||
get_terminal_size()
|
get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16) -> Result<()> {
|
fn scroll_up(&self, count: u16) -> Result<()> {
|
||||||
let csbi = ScreenBuffer::current()?;
|
let csbi = ScreenBuffer::current()?;
|
||||||
let mut window = csbi.info()?.terminal_window();
|
let mut window = csbi.info()?.terminal_window();
|
||||||
|
|
||||||
// Check whether the window is too close to the screen buffer top
|
// Check whether the window is too close to the screen buffer top
|
||||||
|
let count = count as i16;
|
||||||
if window.top >= count {
|
if window.top >= count {
|
||||||
window.top -= count; // move top down
|
window.top -= count; // move top down
|
||||||
window.bottom = count; // move bottom down
|
window.bottom = count; // move bottom down
|
||||||
@ -59,13 +60,14 @@ impl ITerminal for WinApiTerminal {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16) -> Result<()> {
|
fn scroll_down(&self, count: u16) -> Result<()> {
|
||||||
let screen_buffer = ScreenBuffer::current()?;
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let csbi = screen_buffer.info()?;
|
let csbi = screen_buffer.info()?;
|
||||||
let mut window = csbi.terminal_window();
|
let mut window = csbi.terminal_window();
|
||||||
let buffer_size = csbi.buffer_size();
|
let buffer_size = csbi.buffer_size();
|
||||||
|
|
||||||
// Check whether the window is too close to the screen buffer top
|
// Check whether the window is too close to the screen buffer top
|
||||||
|
let count = count as i16;
|
||||||
if window.bottom < buffer_size.height - count {
|
if window.bottom < buffer_size.height - count {
|
||||||
window.top += count; // move top down
|
window.top += count; // move top down
|
||||||
window.bottom += count; // move bottom down
|
window.bottom += count; // move bottom down
|
||||||
@ -76,7 +78,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current terminal size
|
/// Set the current terminal size
|
||||||
fn set_size(&self, width: i16, height: i16) -> Result<()> {
|
fn set_size(&self, width: u16, height: u16) -> Result<()> {
|
||||||
if width <= 0 {
|
if width <= 0 {
|
||||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||||
"Cannot set the terminal width lower than 1",
|
"Cannot set the terminal width lower than 1",
|
||||||
@ -103,6 +105,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
// buffer to be large enough. Include window position.
|
// buffer to be large enough. Include window position.
|
||||||
let mut resize_buffer = false;
|
let mut resize_buffer = false;
|
||||||
|
|
||||||
|
let width = width as i16;
|
||||||
if current_size.width < window.left + width {
|
if current_size.width < window.left + width {
|
||||||
if window.left >= i16::max_value() - width {
|
if window.left >= i16::max_value() - width {
|
||||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||||
@ -113,6 +116,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
new_size.width = window.left + width;
|
new_size.width = window.left + width;
|
||||||
resize_buffer = true;
|
resize_buffer = true;
|
||||||
}
|
}
|
||||||
|
let height = height as i16;
|
||||||
if current_size.height < window.top + height {
|
if current_size.height < window.top + height {
|
||||||
if window.top >= i16::max_value() - height {
|
if window.top >= i16::max_value() - height {
|
||||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||||
@ -284,7 +288,9 @@ mod tests {
|
|||||||
|
|
||||||
assert!(terminal.set_size(30, 30).is_ok());
|
assert!(terminal.set_size(30, 30).is_ok());
|
||||||
|
|
||||||
let (x, y) = terminal.terminal_size();
|
let size = terminal.size();
|
||||||
|
assert!(size.is_ok());
|
||||||
|
let (x, y) = size.unwrap();
|
||||||
|
|
||||||
assert_eq!(x, 30);
|
assert_eq!(x, 30);
|
||||||
assert_eq!(y, 30);
|
assert_eq!(y, 30);
|
||||||
|
@ -13,6 +13,8 @@ pub type Result<T> = std::result::Result<T, ErrorKind>;
|
|||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
IoError(io::Error),
|
IoError(io::Error),
|
||||||
FmtError(fmt::Error),
|
FmtError(fmt::Error),
|
||||||
|
Utf8Error(std::string::FromUtf8Error),
|
||||||
|
ParseIntError(std::num::ParseIntError),
|
||||||
ResizingTerminalFailure(String),
|
ResizingTerminalFailure(String),
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -49,3 +51,15 @@ impl From<fmt::Error> for ErrorKind {
|
|||||||
ErrorKind::FmtError(e)
|
ErrorKind::FmtError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<std::string::FromUtf8Error> for ErrorKind {
|
||||||
|
fn from(e: std::string::FromUtf8Error) -> Self {
|
||||||
|
ErrorKind::Utf8Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::num::ParseIntError> for ErrorKind {
|
||||||
|
fn from(e: std::num::ParseIntError) -> Self {
|
||||||
|
ErrorKind::ParseIntError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,14 +17,14 @@ impl ScreenBufferInfo {
|
|||||||
|
|
||||||
/// This will return the buffer size.
|
/// This will return the buffer size.
|
||||||
///
|
///
|
||||||
/// Will take `dwSize`from the current screen buffer and convert it into the `Size`.
|
/// Will take `dwSize` from the current screen buffer and convert it into the `Size`.
|
||||||
pub fn buffer_size(&self) -> Size {
|
pub fn buffer_size(&self) -> Size {
|
||||||
Size::from(self.0.dwSize)
|
Size::from(self.0.dwSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will return the terminal size.
|
/// This will return the terminal size.
|
||||||
///
|
///
|
||||||
/// Will calculate the whit and height from `srWindow` and convert it into a `Size`.
|
/// Will calculate the width and height from `srWindow` and convert it into a `Size`.
|
||||||
pub fn terminal_size(&self) -> Size {
|
pub fn terminal_size(&self) -> Size {
|
||||||
(Size::new(
|
(Size::new(
|
||||||
self.0.srWindow.Right - self.0.srWindow.Left,
|
self.0.srWindow.Right - self.0.srWindow.Left,
|
||||||
|
@ -6,10 +6,10 @@ use crossterm::{
|
|||||||
Terminal, TerminalCursor,
|
Terminal, TerminalCursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>> {
|
fn log(input_buf: Arc<Mutex<String>>) -> Result<Vec<thread::JoinHandle<()>>> {
|
||||||
let mut threads = Vec::with_capacity(10);
|
let mut threads = Vec::with_capacity(10);
|
||||||
|
|
||||||
let (_, term_height) = terminal().terminal_size();
|
let (_, term_height) = terminal().size()?;
|
||||||
|
|
||||||
for i in 0..1 {
|
for i in 0..1 {
|
||||||
let input_buffer = input_buf.clone();
|
let input_buffer = input_buf.clone();
|
||||||
@ -37,7 +37,7 @@ fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>> {
|
|||||||
threads.push(join);
|
threads.push(join);
|
||||||
}
|
}
|
||||||
|
|
||||||
threads
|
Ok(threads)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swap_write(
|
fn swap_write(
|
||||||
@ -60,7 +60,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
let input_buf = Arc::new(Mutex::new(String::new()));
|
let input_buf = Arc::new(Mutex::new(String::new()));
|
||||||
|
|
||||||
let threads = log(input_buf.clone());
|
let threads = log(input_buf.clone())?;
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
|
@ -17,36 +17,48 @@ fn goto() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// get the cursor position
|
/// get the cursor position
|
||||||
fn pos() {
|
fn pos() -> Result<()> {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
// get the cursor position.
|
// get the cursor position.
|
||||||
let (x, y) = cursor.pos();
|
let (x, y) = cursor.pos()?;
|
||||||
|
|
||||||
println!("{} {}", x, y);
|
println!("{} {}", x, y);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 up | demonstration.
|
/// Move the cursor 3 up | demonstration.
|
||||||
fn move_up() {
|
fn move_up() -> Result<()> {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor();
|
||||||
|
|
||||||
// Move the cursor to position 3 times to the up in the terminal
|
// Move the cursor to position 3 times to the up in the terminal
|
||||||
cursor.move_up(10);
|
cursor.move_up(3)?;
|
||||||
}
|
Ok(())
|
||||||
|
|
||||||
/// Move the cursor 3 to the right | demonstration.
|
|
||||||
fn move_right() {
|
|
||||||
let mut cursor = cursor();
|
|
||||||
// Move the cursor to position 3 times to the right in the terminal
|
|
||||||
cursor.move_right(3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 down | demonstration.
|
/// Move the cursor 3 down | demonstration.
|
||||||
fn move_down() {
|
fn move_down() -> Result<()> {
|
||||||
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)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move the cursor 3 to the right | demonstration.
|
||||||
|
fn move_right() -> Result<()> {
|
||||||
|
let mut cursor = cursor();
|
||||||
|
// Move the cursor to position 3 times to the right in the terminal
|
||||||
|
cursor.move_right(3)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move the cursor 3 left | demonstration.
|
||||||
|
fn move_left() -> Result<()> {
|
||||||
|
let mut cursor = cursor();
|
||||||
|
// Move the cursor to position 3 times to the left in the terminal
|
||||||
|
cursor.move_left(3)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save and reset cursor position | demonstration..
|
/// Save and reset cursor position | demonstration..
|
||||||
|
@ -34,7 +34,7 @@ pub enum Event {
|
|||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
// Print the welcome screen and ask for the map size.
|
// Print the welcome screen and ask for the map size.
|
||||||
let crossterm = Crossterm::new();
|
let crossterm = Crossterm::new();
|
||||||
let (map_width, map_height) = ask_for_map_size(crossterm.terminal().terminal_size())?;
|
let (map_width, map_height) = ask_for_map_size(crossterm.terminal().size()?)?;
|
||||||
|
|
||||||
// Switch screen to the raw mode to avoid printing key presses on the screen
|
// Switch screen to the raw mode to avoid printing key presses on the screen
|
||||||
// and hide the cursor.
|
// and hide the cursor.
|
||||||
|
@ -75,14 +75,15 @@ fn clear_until_new_line() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Print the the current terminal size | demonstration.
|
/// Print the the current terminal size | demonstration.
|
||||||
fn print_terminal_size() {
|
fn print_terminal_size() -> Result<()> {
|
||||||
let terminal = terminal();
|
let terminal = terminal();
|
||||||
|
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let (width, height) = terminal.terminal_size();
|
let (width, height) = terminal.size()?;
|
||||||
|
|
||||||
// Print results
|
// Print results
|
||||||
print!("X: {}, y: {}", width, height);
|
print!("X: {}, y: {}", width, height);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the terminal size to width 10, height: 10 | demonstration.
|
/// Set the terminal size to width 10, height: 10 | demonstration.
|
||||||
|
13
scripts/test-examples.sh
Executable file
13
scripts/test-examples.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ev
|
||||||
|
pushd examples/program_examples
|
||||||
|
for d in */ ; do
|
||||||
|
pushd "$d"
|
||||||
|
cargo build
|
||||||
|
if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
fi
|
||||||
|
popd
|
||||||
|
done
|
||||||
|
popd
|
Loading…
Reference in New Issue
Block a user