parent
3c344b66b9
commit
011a47e93d
5
.github/workflows/crossterm_test.yml
vendored
5
.github/workflows/crossterm_test.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
uses: hecrj/setup-rust-action@master
|
||||
with:
|
||||
rust-version: ${{ matrix.rust }}
|
||||
components: rustfmt
|
||||
components: rustfmt,clippy
|
||||
- name: Toolchain Information
|
||||
run: |
|
||||
rustc --version
|
||||
@ -44,6 +44,9 @@ jobs:
|
||||
if: matrix.rust == 'stable'
|
||||
run: cargo fmt --all -- --check
|
||||
continue-on-error: ${{ matrix.can-fail }}
|
||||
- name: Clippy
|
||||
run: cargo clippy -- -D clippy::all
|
||||
continue-on-error: ${{ matrix.can-fail }}
|
||||
- name: Test Build
|
||||
run: cargo build
|
||||
continue-on-error: ${{ matrix.can-fail }}
|
||||
|
@ -26,12 +26,14 @@ matrix:
|
||||
before_script:
|
||||
- export PATH=$PATH:/home/travis/.cargo/bin
|
||||
- rustup component add rustfmt
|
||||
- rustup component add clippy
|
||||
|
||||
script:
|
||||
- cargo fmt --version
|
||||
- rustup --version
|
||||
- rustc --version
|
||||
- if [ "$TRAVIS_RUST_VERSION" = "stable" ]; then cargo fmt --all -- --check; fi
|
||||
- cargo clippy -- -D clippy::all
|
||||
- cargo build
|
||||
- cargo test --all-features --no-default-features -- --nocapture --test-threads 1
|
||||
- cargo test --features cursor --no-default-features --lib -- --nocapture --test-threads 1
|
||||
|
@ -22,9 +22,9 @@ pub(crate) fn move_left_csi_sequence(count: u16) -> String {
|
||||
format!(csi!("{}D"), count)
|
||||
}
|
||||
|
||||
pub(crate) static SAVE_POSITION_CSI_SEQUENCE: &'static str = "\x1B7";
|
||||
pub(crate) static RESTORE_POSITION_CSI_SEQUENCE: &'static str = "\x1B8";
|
||||
pub(crate) static HIDE_CSI_SEQUENCE: &'static str = csi!("?25l");
|
||||
pub(crate) static SHOW_CSI_SEQUENCE: &'static str = csi!("?25h");
|
||||
pub(crate) static ENABLE_BLINKING_CSI_SEQUENCE: &'static str = csi!("?12h");
|
||||
pub(crate) static DISABLE_BLINKING_CSI_SEQUENCE: &'static str = csi!("?12l");
|
||||
pub(crate) const SAVE_POSITION_CSI_SEQUENCE: &str = "\x1B7";
|
||||
pub(crate) const RESTORE_POSITION_CSI_SEQUENCE: &str = "\x1B8";
|
||||
pub(crate) const HIDE_CSI_SEQUENCE: &str = csi!("?25l");
|
||||
pub(crate) const SHOW_CSI_SEQUENCE: &str = csi!("?25h");
|
||||
pub(crate) const ENABLE_BLINKING_CSI_SEQUENCE: &str = csi!("?12h");
|
||||
pub(crate) const DISABLE_BLINKING_CSI_SEQUENCE: &str = csi!("?12l");
|
||||
|
@ -38,18 +38,18 @@ fn read_position_raw() -> Result<(u16, u16)> {
|
||||
loop {
|
||||
match poll_internal(Some(Duration::from_millis(2000)), &CursorPositionFilter) {
|
||||
Ok(true) => {
|
||||
match read_internal(&CursorPositionFilter) {
|
||||
Ok(InternalEvent::CursorPosition(x, y)) => {
|
||||
if let Ok(InternalEvent::CursorPosition(x, y)) =
|
||||
read_internal(&CursorPositionFilter)
|
||||
{
|
||||
return Ok((x, y));
|
||||
}
|
||||
_ => { /* unreachable */ }
|
||||
};
|
||||
}
|
||||
Ok(false) => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"The cursor position could not be read within a normal duration",
|
||||
))?;
|
||||
)
|
||||
.into());
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
|
@ -85,24 +85,26 @@ impl ScreenBufferCursor {
|
||||
}
|
||||
|
||||
fn move_to(&self, x: i16, y: i16) -> Result<()> {
|
||||
if x < 0 || x >= <i16>::max_value() {
|
||||
Err(io::Error::new(
|
||||
if x < 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"Argument Out of Range Exception when setting cursor position to X: {}",
|
||||
x
|
||||
),
|
||||
))?;
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
if y < 0 || y >= <i16>::max_value() {
|
||||
Err(io::Error::new(
|
||||
if y < 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"Argument Out of Range Exception when setting cursor position to Y: {}",
|
||||
y
|
||||
),
|
||||
))?;
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let position = COORD { X: x, Y: y };
|
||||
@ -112,7 +114,7 @@ impl ScreenBufferCursor {
|
||||
**self.screen_buffer.handle(),
|
||||
position,
|
||||
)) {
|
||||
Err(io::Error::last_os_error())?;
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -129,7 +131,7 @@ impl ScreenBufferCursor {
|
||||
**self.screen_buffer.handle(),
|
||||
&cursor_info,
|
||||
)) {
|
||||
Err(io::Error::last_os_error())?;
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -189,15 +189,13 @@ fn parse_mouse_event_record(event: &MouseEvent) -> Result<Option<crate::event::M
|
||||
let ypos = parse_relative_y(event.mouse_position.y)? as u16;
|
||||
|
||||
let button_state = event.button_state;
|
||||
let mut button = MouseButton::Left;
|
||||
|
||||
if button_state.right_button() {
|
||||
button = MouseButton::Right;
|
||||
}
|
||||
|
||||
if button_state.middle_button() {
|
||||
button = MouseButton::Middle;
|
||||
}
|
||||
let button = if button_state.right_button() {
|
||||
MouseButton::Right
|
||||
} else if button_state.middle_button() {
|
||||
MouseButton::Middle
|
||||
} else {
|
||||
MouseButton::Left
|
||||
};
|
||||
|
||||
Ok(match event.event_flags {
|
||||
EventFlags::PressOrRelease => {
|
||||
@ -272,7 +270,7 @@ impl WinApiPoll {
|
||||
unsafe { WaitForMultipleObjects(handles.len() as u32, handles.as_ptr(), 0, dw_millis) };
|
||||
|
||||
let result = match output {
|
||||
output if output == WAIT_OBJECT_0 + 0 => {
|
||||
output if output == WAIT_OBJECT_0 => {
|
||||
// input handle triggered
|
||||
Ok(Some(true))
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ impl AlternateScreen {
|
||||
///
|
||||
/// You'll be automatically switched to the main screen if this function
|
||||
/// fails.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn to_alternate(raw_mode: bool) -> Result<AlternateScreen> {
|
||||
let alternate = alternate::alternate_screen();
|
||||
alternate.enter()?;
|
||||
|
@ -2,8 +2,8 @@ use crate::{csi, utils::Result, write_cout};
|
||||
|
||||
use super::AlternateScreen;
|
||||
|
||||
pub(crate) static ENTER_ALTERNATE_SCREEN_CSI_SEQUENCE: &'static str = csi!("?1049h");
|
||||
pub(crate) static LEAVE_ALTERNATE_SCREEN_CSI_SEQUENCE: &'static str = csi!("?1049l");
|
||||
pub(crate) const ENTER_ALTERNATE_SCREEN_CSI_SEQUENCE: &str = csi!("?1049h");
|
||||
pub(crate) const LEAVE_ALTERNATE_SCREEN_CSI_SEQUENCE: &str = csi!("?1049l");
|
||||
|
||||
pub(crate) struct AnsiAlternateScreen;
|
||||
|
||||
|
@ -35,6 +35,7 @@ impl RawModeCommand {
|
||||
}
|
||||
|
||||
/// Disables raw mode.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn disable(&self) -> Result<()> {
|
||||
let console_mode = ConsoleMode::from(Handle::input_handle()?);
|
||||
|
||||
@ -44,6 +45,6 @@ impl RawModeCommand {
|
||||
|
||||
console_mode.set_mode(new_mode)?;
|
||||
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ pub(crate) fn set_attr_csi_sequence(attribute: Attribute) -> String {
|
||||
format!(csi!("{}m"), attribute as i16)
|
||||
}
|
||||
|
||||
pub(crate) static RESET_CSI_SEQUENCE: &'static str = csi!("0m");
|
||||
pub(crate) const RESET_CSI_SEQUENCE: &str = csi!("0m");
|
||||
|
||||
impl From<Colored> for String {
|
||||
fn from(colored: Colored) -> Self {
|
||||
|
@ -37,7 +37,7 @@ pub(crate) fn set_foreground_color(fg_color: Color) -> Result<()> {
|
||||
// background intensity is a separate value in attrs,
|
||||
// wee need to check if this was applied to the current bg color.
|
||||
if (attrs & wincon::BACKGROUND_INTENSITY as u16) != 0 {
|
||||
color = color | wincon::BACKGROUND_INTENSITY as u16;
|
||||
color |= wincon::BACKGROUND_INTENSITY as u16;
|
||||
}
|
||||
|
||||
Console::from(screen_buffer.handle().clone()).set_text_attribute(color)?;
|
||||
@ -62,7 +62,7 @@ pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
|
||||
// Foreground intensity is a separate value in attrs,
|
||||
// So we need to check if this was applied to the current fg color.
|
||||
if (attrs & wincon::FOREGROUND_INTENSITY as u16) != 0 {
|
||||
color = color | wincon::FOREGROUND_INTENSITY as u16;
|
||||
color |= wincon::FOREGROUND_INTENSITY as u16;
|
||||
}
|
||||
|
||||
Console::from(screen_buffer.handle().clone()).set_text_attribute(color)?;
|
||||
@ -137,7 +137,7 @@ impl From<Colored> for u16 {
|
||||
}
|
||||
|
||||
/* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/
|
||||
Color::Rgb { r: _, g: _, b: _ } => 0,
|
||||
Color::Rgb { .. } => 0,
|
||||
Color::AnsiValue(_val) => 0,
|
||||
}
|
||||
}
|
||||
@ -168,7 +168,7 @@ impl From<Colored> for u16 {
|
||||
(original_color & !(REMOVE_FG_MASK))
|
||||
}
|
||||
/* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/
|
||||
Color::Rgb { r: _, g: _, b: _ } => 0,
|
||||
Color::Rgb { .. } => 0,
|
||||
Color::AnsiValue(_val) => 0,
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ impl Command for Clear {
|
||||
|
||||
#[cfg(windows)]
|
||||
fn execute_winapi(&self) -> Result<()> {
|
||||
sys::clear(self.0.clone())
|
||||
sys::clear(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
use crate::csi;
|
||||
|
||||
pub(crate) static CLEAR_ALL_CSI_SEQUENCE: &'static str = csi!("2J");
|
||||
pub(crate) static CLEAR_FROM_CURSOR_DOWN_CSI_SEQUENCE: &'static str = csi!("J");
|
||||
pub(crate) static CLEAR_FROM_CURSOR_UP_CSI_SEQUENCE: &'static str = csi!("1J");
|
||||
pub(crate) static CLEAR_FROM_CURRENT_LINE_CSI_SEQUENCE: &'static str = csi!("2K");
|
||||
pub(crate) static CLEAR_UNTIL_NEW_LINE_CSI_SEQUENCE: &'static str = csi!("K");
|
||||
pub(crate) const CLEAR_ALL_CSI_SEQUENCE: &str = csi!("2J");
|
||||
pub(crate) const CLEAR_FROM_CURSOR_DOWN_CSI_SEQUENCE: &str = csi!("J");
|
||||
pub(crate) const CLEAR_FROM_CURSOR_UP_CSI_SEQUENCE: &str = csi!("1J");
|
||||
pub(crate) const CLEAR_FROM_CURRENT_LINE_CSI_SEQUENCE: &str = csi!("2K");
|
||||
pub(crate) const CLEAR_UNTIL_NEW_LINE_CSI_SEQUENCE: &str = csi!("K");
|
||||
|
||||
pub(crate) fn scroll_up_csi_sequence(count: u16) -> String {
|
||||
format!(csi!("{}S"), count)
|
||||
|
@ -55,10 +55,8 @@ pub fn size() -> Result<(u16, u16)> {
|
||||
ws_ypixel: 0,
|
||||
};
|
||||
|
||||
if let Ok(true) =
|
||||
wrap_with_result(unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) })
|
||||
{
|
||||
return Ok((size.ws_col, size.ws_row));
|
||||
if let Ok(true) = wrap_with_result(unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut size) }) {
|
||||
Ok((size.ws_col, size.ws_row))
|
||||
} else {
|
||||
tput_size().ok_or_else(|| std::io::Error::last_os_error().into())
|
||||
}
|
||||
|
@ -75,13 +75,13 @@ pub(crate) fn scroll_down(row_count: u16) -> Result<()> {
|
||||
|
||||
/// Set the current terminal size
|
||||
pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
|
||||
if width <= 0 {
|
||||
if width <= 1 {
|
||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||
"Cannot set the terminal width lower than 1.",
|
||||
)));
|
||||
}
|
||||
|
||||
if height <= 0 {
|
||||
if height <= 1 {
|
||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||
"Cannot set the terminal height lower then 1.",
|
||||
)));
|
||||
@ -124,15 +124,17 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
|
||||
resize_buffer = true;
|
||||
}
|
||||
|
||||
if resize_buffer {
|
||||
if let Err(_) = screen_buffer.set_size(new_size.width - 1, new_size.height - 1) {
|
||||
if resize_buffer
|
||||
&& screen_buffer
|
||||
.set_size(new_size.width - 1, new_size.height - 1)
|
||||
.is_err()
|
||||
{
|
||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||
"Something went wrong when setting screen buffer size.",
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
let mut window = window.clone();
|
||||
let mut window = window;
|
||||
|
||||
// preserve the position, but change the size.
|
||||
window.bottom = window.top + height - 1;
|
||||
@ -140,13 +142,15 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
|
||||
console.set_console_info(true, window)?;
|
||||
|
||||
// if we resized the buffer, un-resize it.
|
||||
if resize_buffer {
|
||||
if let Err(_) = screen_buffer.set_size(current_size.width - 1, current_size.height - 1) {
|
||||
if resize_buffer
|
||||
&& screen_buffer
|
||||
.set_size(current_size.width - 1, current_size.height - 1)
|
||||
.is_err()
|
||||
{
|
||||
return Err(ErrorKind::ResizingTerminalFailure(String::from(
|
||||
"Something went wrong when setting screen buffer size.",
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
let bounds = console.largest_window_size();
|
||||
|
||||
|
@ -101,7 +101,7 @@ impl<T: Display + Clone> Command for Output<T> {
|
||||
type AnsiType = T;
|
||||
|
||||
fn ansi_code(&self) -> Self::AnsiType {
|
||||
return self.0.clone();
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -20,7 +20,7 @@ pub fn supports_ansi() -> bool {
|
||||
// I got the list of terminals from here: https://github.com/keqingrong/supports-ansi/blob/master/index.js
|
||||
#[cfg(windows)]
|
||||
fn is_specific_term() -> bool {
|
||||
const TERMS: [&'static str; 15] = [
|
||||
const TERMS: [&str; 15] = [
|
||||
"xterm", // xterm, PuTTY, Mintty
|
||||
"rxvt", // RXVT
|
||||
"eterm", // Eterm
|
||||
|
@ -80,28 +80,21 @@ macro_rules! queue {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if $crate::supports_ansi() {
|
||||
match write!($write, "{}", $command.ansi_code()) {
|
||||
Err(e) => {
|
||||
if let Err(e) = write!($write, "{}", $command.ansi_code()) {
|
||||
error = Some(Err($crate::ErrorKind::from(e)));
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
} else {
|
||||
match $command.execute_winapi() {
|
||||
Err(e) => {
|
||||
if let Err(e) = $command.execute_winapi() {
|
||||
error = Some(Err($crate::ErrorKind::from(e)));
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
};
|
||||
}
|
||||
#[cfg(unix)]
|
||||
match write!($write, "{}", $command.ansi_code()) {
|
||||
Err(e) => {
|
||||
{
|
||||
if let Err(e) = write!($write, "{}", $command.ansi_code()) {
|
||||
error = Some(Err($crate::ErrorKind::from(e)));
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
)*
|
||||
|
||||
if let Some(error) = error {
|
||||
|
Loading…
Reference in New Issue
Block a user