diff --git a/README.md b/README.md index 1b7edf4..66254fe 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ see [Tested Terminals](#tested-terminals) for more info). - Alternate screen - Raw screen - Set terminal title + - Enable/disable line wrapping - Event - Input Events - Mouse Events (press, release, position, button, drag) diff --git a/src/lib.rs b/src/lib.rs index 673171e..4be6f01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,8 @@ //! - Miscellaneous - [`Clear`](terminal/struct.Clear.html), //! [`SetSize`](terminal/struct.SetSize.html) //! [`SetTitle`](terminal/struct.SetTitle.html) +//! [`DisableLineWrap`](terminal/struct.DisableLineWrap.html) +//! [`EnableLineWrap`](terminal/struct.EnableLineWrap.html) //! - Alternate screen - [`EnterAlternateScreen`](terminal/struct.EnterAlternateScreen.html), //! [`LeaveAlternateScreen`](terminal/struct.LeaveAlternateScreen.html) //! diff --git a/src/terminal.rs b/src/terminal.rs index 94e8d35..650b569 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -82,9 +82,11 @@ //! For manual execution control check out [crossterm::queue](../macro.queue.html). #[cfg(windows)] -use crossterm_winapi::{Handle, ScreenBuffer}; +use crossterm_winapi::{ConsoleMode, Handle, ScreenBuffer}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(windows)] +use winapi::um::wincon::ENABLE_WRAP_AT_EOL_OUTPUT; #[doc(no_inline)] use crate::Command; @@ -114,6 +116,48 @@ pub fn size() -> Result<(u16, u16)> { sys::size() } +/// Disables line wrapping. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DisableLineWrap; + +impl Command for DisableLineWrap { + type AnsiType = &'static str; + + fn ansi_code(&self) -> Self::AnsiType { + ansi::DISABLE_LINE_WRAP_CSI_SEQUENCE + } + + #[cfg(windows)] + fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> { + let screen_buffer = ScreenBuffer::current()?; + let console_mode = ConsoleMode::from(screen_buffer.handle().clone()); + let new_mode = console_mode.mode()? & !ENABLE_WRAP_AT_EOL_OUTPUT; + console_mode.set_mode(new_mode)?; + Ok(()) + } +} + +/// Enable line wrapping. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct EnableLineWrap; + +impl Command for EnableLineWrap { + type AnsiType = &'static str; + + fn ansi_code(&self) -> Self::AnsiType { + ansi::ENABLE_LINE_WRAP_CSI_SEQUENCE + } + + #[cfg(windows)] + fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> { + let screen_buffer = ScreenBuffer::current()?; + let console_mode = ConsoleMode::from(screen_buffer.handle().clone()); + let new_mode = console_mode.mode()? | ENABLE_WRAP_AT_EOL_OUTPUT; + console_mode.set_mode(new_mode)?; + Ok(()) + } +} + /// A command that switches to alternate screen. /// /// # Notes diff --git a/src/terminal/ansi.rs b/src/terminal/ansi.rs index 55bcbde..513c4a1 100644 --- a/src/terminal/ansi.rs +++ b/src/terminal/ansi.rs @@ -9,6 +9,8 @@ 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) const ENTER_ALTERNATE_SCREEN_CSI_SEQUENCE: &str = csi!("?1049h"); pub(crate) const LEAVE_ALTERNATE_SCREEN_CSI_SEQUENCE: &str = csi!("?1049l"); +pub(crate) const DISABLE_LINE_WRAP_CSI_SEQUENCE: &str = csi!("?7l"); +pub(crate) const ENABLE_LINE_WRAP_CSI_SEQUENCE: &str = csi!("?7h"); pub(crate) fn scroll_up_csi_sequence(count: u16) -> String { format!(csi!("{}S"), count)