Grand writer
access for winapi commands.
This commit is contained in:
parent
6326795700
commit
32215ec7f5
@ -27,7 +27,7 @@ pub trait Command {
|
|||||||
///
|
///
|
||||||
/// This method does not need to be accessed manually, as it is used by the crossterm's [Command Api](../#command-api)
|
/// This method does not need to be accessed manually, as it is used by the crossterm's [Command Api](../#command-api)
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()>;
|
fn execute_winapi(&self, writer: impl FnMut() -> Result<()>) -> Result<()>;
|
||||||
|
|
||||||
/// Returns whether the ansi code representation of this command is supported by windows.
|
/// Returns whether the ansi code representation of this command is supported by windows.
|
||||||
///
|
///
|
||||||
@ -49,8 +49,8 @@ impl<T: Command> Command for &T {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
T::execute_winapi(self)
|
T::execute_winapi(self, _writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -76,7 +76,7 @@ impl Command for MoveTo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_to(self.0, self.1)
|
sys::move_to(self.0, self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ impl Command for MoveToNextLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_to_next_line(self.0)
|
sys::move_to_next_line(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ impl Command for MoveToPreviousLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_to_previous_line(self.0)
|
sys::move_to_previous_line(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ impl Command for MoveToColumn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_to_column(self.0)
|
sys::move_to_column(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ impl Command for MoveUp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_up(self.0)
|
sys::move_up(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ impl Command for MoveRight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_right(self.0)
|
sys::move_right(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ impl Command for MoveDown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_down(self.0)
|
sys::move_down(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ impl Command for MoveLeft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::move_left(self.0)
|
sys::move_left(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +299,7 @@ impl Command for SavePosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::save_position()
|
sys::save_position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +324,7 @@ impl Command for RestorePosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::restore_position()
|
sys::restore_position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ impl Command for Hide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::show_cursor(false)
|
sys::show_cursor(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,7 +368,7 @@ impl Command for Show {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::show_cursor(true)
|
sys::show_cursor(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,7 +391,7 @@ impl Command for EnableBlinking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,7 +414,7 @@ impl Command for DisableBlinking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ impl Command for EnableMouseCapture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::windows::enable_mouse_capture()
|
sys::windows::enable_mouse_capture()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ impl Command for DisableMouseCapture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::windows::disable_mouse_capture()
|
sys::windows::disable_mouse_capture()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,40 @@ macro_rules! handle_command {
|
|||||||
if command.is_ansi_code_supported() {
|
if command.is_ansi_code_supported() {
|
||||||
write_ansi_code!($writer, command.ansi_code())
|
write_ansi_code!($writer, command.ansi_code())
|
||||||
} else {
|
} else {
|
||||||
command.execute_winapi().map_err($crate::ErrorKind::from)
|
command
|
||||||
|
.execute_winapi(|| {
|
||||||
|
write!($writer, "{}", command.ansi_code())?;
|
||||||
|
// winapi doesn't support queuing
|
||||||
|
$writer.flush()?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.map_err($crate::ErrorKind::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
write_ansi_code!($writer, $command.ansi_code())
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offer the same functionality as queue! macro, but is used only internally and with std::fmt::Write as $writer
|
||||||
|
// The difference is in case of winapi we ignore the $writer and use a fake one
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_fmt_command {
|
||||||
|
($writer:expr, $command:expr) => {{
|
||||||
|
use $crate::{write_ansi_code, Command};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
let command = $command;
|
||||||
|
if command.is_ansi_code_supported() {
|
||||||
|
write_ansi_code!($writer, command.ansi_code())
|
||||||
|
} else {
|
||||||
|
command
|
||||||
|
.execute_winapi(|| panic!("this writer should not be possible to use here"))
|
||||||
|
.map_err($crate::ErrorKind::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -160,7 +193,7 @@ macro_rules! impl_display {
|
|||||||
(for $($t:ty),+) => {
|
(for $($t:ty),+) => {
|
||||||
$(impl ::std::fmt::Display for $t {
|
$(impl ::std::fmt::Display for $t {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
|
||||||
$crate::queue!(f, self).map_err(|_| ::std::fmt::Error)
|
$crate::handle_fmt_command!(f, self).map_err(|_| ::std::fmt::Error)
|
||||||
}
|
}
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
@ -312,7 +345,10 @@ mod tests {
|
|||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_winapi(&self) -> CrosstermResult<()> {
|
fn execute_winapi(
|
||||||
|
&self,
|
||||||
|
_writer: impl FnMut() -> CrosstermResult<()>,
|
||||||
|
) -> CrosstermResult<()> {
|
||||||
self.stream.borrow_mut().push(self.value);
|
self.stream.borrow_mut().push(self.value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
18
src/style.rs
18
src/style.rs
@ -216,7 +216,7 @@ impl Command for SetForegroundColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::windows::set_foreground_color(self.0)
|
sys::windows::set_foreground_color(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ impl Command for SetBackgroundColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::windows::set_background_color(self.0)
|
sys::windows::set_background_color(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ impl Command for SetColors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
if let Some(color) = self.0.foreground {
|
if let Some(color) = self.0.foreground {
|
||||||
sys::windows::set_foreground_color(color)?;
|
sys::windows::set_foreground_color(color)?;
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ impl Command for SetAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
// attributes are not supported by WinAPI.
|
// attributes are not supported by WinAPI.
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -364,7 +364,7 @@ impl Command for SetAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
// attributes are not supported by WinAPI.
|
// attributes are not supported by WinAPI.
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -391,7 +391,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ impl Command for ResetColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::windows::reset()
|
sys::windows::reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,8 +431,8 @@ impl<T: Display + Clone> Command for Print<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, mut writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
print!("{}", self.0);
|
writer()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
queue,
|
handle_fmt_command,
|
||||||
style::{
|
style::{
|
||||||
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttributes, SetBackgroundColor,
|
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttributes, SetBackgroundColor,
|
||||||
SetForegroundColor, Styler,
|
SetForegroundColor, Styler,
|
||||||
@ -96,16 +96,16 @@ impl<D: Display> Display for StyledContent<D> {
|
|||||||
let mut reset = false;
|
let mut reset = false;
|
||||||
|
|
||||||
if let Some(bg) = self.style.background_color {
|
if let Some(bg) = self.style.background_color {
|
||||||
queue!(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
|
handle_fmt_command!(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
if let Some(fg) = self.style.foreground_color {
|
if let Some(fg) = self.style.foreground_color {
|
||||||
queue!(f, SetForegroundColor(fg)).map_err(|_| fmt::Error)?;
|
handle_fmt_command!(f, SetForegroundColor(fg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.style.attributes.is_empty() {
|
if !self.style.attributes.is_empty() {
|
||||||
queue!(f, SetAttributes(self.style.attributes)).map_err(|_| fmt::Error)?;
|
handle_fmt_command!(f, SetAttributes(self.style.attributes)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ impl<D: Display> Display for StyledContent<D> {
|
|||||||
// color (39m)" and "reset background color (49m)"; consider using
|
// color (39m)" and "reset background color (49m)"; consider using
|
||||||
// these.
|
// these.
|
||||||
if reset {
|
if reset {
|
||||||
queue!(f, ResetColor).map_err(|_| fmt::Error)?;
|
handle_fmt_command!(f, ResetColor).map_err(|_| fmt::Error)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -147,7 +147,7 @@ impl Command for EnterAlternateScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
let alternate_screen = ScreenBuffer::create();
|
let alternate_screen = ScreenBuffer::create();
|
||||||
alternate_screen.show()?;
|
alternate_screen.show()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -187,7 +187,7 @@ impl Command for LeaveAlternateScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
let screen_buffer = ScreenBuffer::from(Handle::current_out_handle()?);
|
let screen_buffer = ScreenBuffer::from(Handle::current_out_handle()?);
|
||||||
screen_buffer.show()?;
|
screen_buffer.show()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -226,7 +226,7 @@ impl Command for ScrollUp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::scroll_up(self.0)
|
sys::scroll_up(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,7 +247,7 @@ impl Command for ScrollDown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::scroll_down(self.0)
|
sys::scroll_down(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ impl Command for Clear {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::clear(self.0)
|
sys::clear(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ impl Command for SetSize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::set_size(self.0, self.1)
|
sys::set_size(self.0, self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ impl<'a> Command for SetTitle<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self, _writer: impl FnMut() -> Result<()>) -> Result<()> {
|
||||||
sys::set_window_title(self.0)
|
sys::set_window_title(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user