summaryrefslogtreecommitdiff
path: root/vendor/anstyle-wincon/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/anstyle-wincon/src')
-rw-r--r--vendor/anstyle-wincon/src/ansi.rs25
-rw-r--r--vendor/anstyle-wincon/src/lib.rs18
-rw-r--r--vendor/anstyle-wincon/src/stream.rs178
-rw-r--r--vendor/anstyle-wincon/src/windows.rs263
4 files changed, 484 insertions, 0 deletions
diff --git a/vendor/anstyle-wincon/src/ansi.rs b/vendor/anstyle-wincon/src/ansi.rs
new file mode 100644
index 0000000..6ac7193
--- /dev/null
+++ b/vendor/anstyle-wincon/src/ansi.rs
@@ -0,0 +1,25 @@
+//! Low-level ANSI-styling
+
+/// Write ANSI colored text to the stream
+pub fn write_colored<S: std::io::Write>(
+ stream: &mut S,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+) -> std::io::Result<usize> {
+ let non_default = fg.is_some() || bg.is_some();
+
+ if non_default {
+ if let Some(fg) = fg {
+ write!(stream, "{}", fg.render_fg())?;
+ }
+ if let Some(bg) = bg {
+ write!(stream, "{}", bg.render_bg())?;
+ }
+ }
+ let written = stream.write(data)?;
+ if non_default {
+ write!(stream, "{}", anstyle::Reset.render())?;
+ }
+ Ok(written)
+}
diff --git a/vendor/anstyle-wincon/src/lib.rs b/vendor/anstyle-wincon/src/lib.rs
new file mode 100644
index 0000000..e04fab6
--- /dev/null
+++ b/vendor/anstyle-wincon/src/lib.rs
@@ -0,0 +1,18 @@
+//! Styling legacy Windows terminals
+//!
+//! See [`WinconStream`]
+//!
+//! This fills a similar role as [`winapi-util`](https://crates.io/crates/winapi-util) does for
+//! [`termcolor`](https://crates.io/crates/termcolor) with the differences
+//! - Uses `windows-sys` rather than `winapi`
+//! - Uses [`anstyle`](https://crates.io/crates/termcolor) rather than defining its own types
+//! - More focused, smaller
+
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+pub mod ansi;
+mod stream;
+#[cfg(windows)]
+pub mod windows;
+
+pub use stream::WinconStream;
diff --git a/vendor/anstyle-wincon/src/stream.rs b/vendor/anstyle-wincon/src/stream.rs
new file mode 100644
index 0000000..9f10108
--- /dev/null
+++ b/vendor/anstyle-wincon/src/stream.rs
@@ -0,0 +1,178 @@
+/// Extend `std::io::Write` with wincon styling
+pub trait WinconStream {
+ /// Write colored text to the stream
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize>;
+}
+
+impl WinconStream for Box<dyn std::io::Write> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ crate::ansi::write_colored(self, fg, bg, data)
+ }
+}
+
+impl WinconStream for &'_ mut Box<dyn std::io::Write> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
+ }
+}
+
+impl WinconStream for std::fs::File {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ crate::ansi::write_colored(self, fg, bg, data)
+ }
+}
+
+impl WinconStream for &'_ mut std::fs::File {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
+ }
+}
+
+impl WinconStream for Vec<u8> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ crate::ansi::write_colored(self, fg, bg, data)
+ }
+}
+
+impl WinconStream for &'_ mut Vec<u8> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
+ }
+}
+
+impl WinconStream for std::io::Stdout {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ // Ensure exclusive access
+ self.lock().write_colored(fg, bg, data)
+ }
+}
+
+impl WinconStream for std::io::Stderr {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ // Ensure exclusive access
+ self.lock().write_colored(fg, bg, data)
+ }
+}
+
+#[cfg(not(windows))]
+mod platform {
+ use super::*;
+
+ impl WinconStream for std::io::StdoutLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ crate::ansi::write_colored(self, fg, bg, data)
+ }
+ }
+
+ impl WinconStream for std::io::StderrLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ crate::ansi::write_colored(self, fg, bg, data)
+ }
+ }
+}
+
+#[cfg(windows)]
+mod platform {
+ use super::*;
+
+ impl WinconStream for std::io::StdoutLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ let initial = crate::windows::stdout_initial_colors();
+ crate::windows::write_colored(self, fg, bg, data, initial)
+ }
+ }
+
+ impl WinconStream for std::io::StderrLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ let initial = crate::windows::stderr_initial_colors();
+ crate::windows::write_colored(self, fg, bg, data, initial)
+ }
+ }
+}
+
+impl WinconStream for &'_ mut std::io::StdoutLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
+ }
+}
+
+impl WinconStream for &'_ mut std::io::StderrLock<'_> {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
+ }
+}
diff --git a/vendor/anstyle-wincon/src/windows.rs b/vendor/anstyle-wincon/src/windows.rs
new file mode 100644
index 0000000..bf1cf56
--- /dev/null
+++ b/vendor/anstyle-wincon/src/windows.rs
@@ -0,0 +1,263 @@
+//! Low-level wincon-styling
+
+use std::os::windows::io::AsHandle;
+use std::os::windows::io::AsRawHandle;
+
+type StdioColorResult = std::io::Result<(anstyle::AnsiColor, anstyle::AnsiColor)>;
+type StdioColorInnerResult = Result<(anstyle::AnsiColor, anstyle::AnsiColor), inner::IoError>;
+
+/// Cached [`get_colors`] call for [`std::io::stdout`]
+pub fn stdout_initial_colors() -> StdioColorResult {
+ static INITIAL: std::sync::OnceLock<StdioColorInnerResult> = std::sync::OnceLock::new();
+ INITIAL
+ .get_or_init(|| get_colors_(&std::io::stdout()))
+ .clone()
+ .map_err(Into::into)
+}
+
+/// Cached [`get_colors`] call for [`std::io::stderr`]
+pub fn stderr_initial_colors() -> StdioColorResult {
+ static INITIAL: std::sync::OnceLock<StdioColorInnerResult> = std::sync::OnceLock::new();
+ INITIAL
+ .get_or_init(|| get_colors_(&std::io::stderr()))
+ .clone()
+ .map_err(Into::into)
+}
+
+/// Apply colors to future writes
+///
+/// **Note:** Make sure any buffers are first flushed or else these colors will apply
+pub fn set_colors<S: AsHandle>(
+ stream: &mut S,
+ fg: anstyle::AnsiColor,
+ bg: anstyle::AnsiColor,
+) -> std::io::Result<()> {
+ set_colors_(stream, fg, bg).map_err(Into::into)
+}
+
+fn set_colors_<S: AsHandle>(
+ stream: &mut S,
+ fg: anstyle::AnsiColor,
+ bg: anstyle::AnsiColor,
+) -> Result<(), inner::IoError> {
+ let handle = stream.as_handle();
+ let handle = handle.as_raw_handle();
+ let attributes = inner::set_colors(fg, bg);
+ inner::set_console_text_attributes(handle, attributes)
+}
+
+/// Get the colors currently active on the console
+pub fn get_colors<S: AsHandle>(stream: &S) -> StdioColorResult {
+ get_colors_(stream).map_err(Into::into)
+}
+
+fn get_colors_<S: AsHandle>(stream: &S) -> StdioColorInnerResult {
+ let handle = stream.as_handle();
+ let handle = handle.as_raw_handle();
+ let info = inner::get_screen_buffer_info(handle)?;
+ let (fg, bg) = inner::get_colors(&info);
+ Ok((fg, bg))
+}
+
+pub(crate) fn write_colored<S: AsHandle + std::io::Write>(
+ stream: &mut S,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ initial: StdioColorResult,
+) -> std::io::Result<usize> {
+ let (initial_fg, initial_bg) = initial?;
+ let non_default = fg.is_some() || bg.is_some();
+
+ if non_default {
+ let fg = fg.unwrap_or(initial_fg);
+ let bg = bg.unwrap_or(initial_bg);
+ // Ensure everything is written with the last set of colors before applying the next set
+ stream.flush()?;
+ set_colors(stream, fg, bg)?;
+ }
+ let written = stream.write(data)?;
+ if non_default {
+ // Ensure everything is written with the last set of colors before applying the next set
+ stream.flush()?;
+ set_colors(stream, initial_fg, initial_bg)?;
+ }
+ Ok(written)
+}
+
+mod inner {
+ use windows_sys::Win32::System::Console::CONSOLE_CHARACTER_ATTRIBUTES;
+ use windows_sys::Win32::System::Console::CONSOLE_SCREEN_BUFFER_INFO;
+ use windows_sys::Win32::System::Console::FOREGROUND_BLUE;
+ use windows_sys::Win32::System::Console::FOREGROUND_GREEN;
+ use windows_sys::Win32::System::Console::FOREGROUND_INTENSITY;
+ use windows_sys::Win32::System::Console::FOREGROUND_RED;
+
+ use std::os::windows::io::RawHandle;
+
+ const FOREGROUND_CYAN: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_BLUE | FOREGROUND_GREEN;
+ const FOREGROUND_MAGENTA: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_BLUE | FOREGROUND_RED;
+ const FOREGROUND_YELLOW: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_GREEN | FOREGROUND_RED;
+ const FOREGROUND_WHITE: CONSOLE_CHARACTER_ATTRIBUTES =
+ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
+
+ #[derive(Copy, Clone, Debug)]
+ pub(crate) enum IoError {
+ BrokenPipe,
+ RawOs(i32),
+ }
+
+ impl From<IoError> for std::io::Error {
+ fn from(io: IoError) -> Self {
+ match io {
+ IoError::BrokenPipe => {
+ std::io::Error::new(std::io::ErrorKind::BrokenPipe, "console is detached")
+ }
+ IoError::RawOs(code) => std::io::Error::from_raw_os_error(code),
+ }
+ }
+ }
+
+ impl IoError {
+ fn last_os_error() -> Self {
+ Self::RawOs(std::io::Error::last_os_error().raw_os_error().unwrap())
+ }
+ }
+
+ pub(crate) fn get_screen_buffer_info(
+ handle: RawHandle,
+ ) -> Result<CONSOLE_SCREEN_BUFFER_INFO, IoError> {
+ unsafe {
+ let handle = std::mem::transmute(handle);
+ if handle == 0 {
+ return Err(IoError::BrokenPipe);
+ }
+
+ let mut info: CONSOLE_SCREEN_BUFFER_INFO = std::mem::zeroed();
+ if windows_sys::Win32::System::Console::GetConsoleScreenBufferInfo(handle, &mut info)
+ != 0
+ {
+ Ok(info)
+ } else {
+ Err(IoError::last_os_error())
+ }
+ }
+ }
+
+ pub(crate) fn set_console_text_attributes(
+ handle: RawHandle,
+ attributes: CONSOLE_CHARACTER_ATTRIBUTES,
+ ) -> Result<(), IoError> {
+ unsafe {
+ let handle = std::mem::transmute(handle);
+ if handle == 0 {
+ return Err(IoError::BrokenPipe);
+ }
+
+ if windows_sys::Win32::System::Console::SetConsoleTextAttribute(handle, attributes) != 0
+ {
+ Ok(())
+ } else {
+ Err(IoError::last_os_error())
+ }
+ }
+ }
+
+ pub(crate) fn get_colors(
+ info: &CONSOLE_SCREEN_BUFFER_INFO,
+ ) -> (anstyle::AnsiColor, anstyle::AnsiColor) {
+ let attributes = info.wAttributes;
+ let bg = from_nibble(attributes >> 4);
+ let fg = from_nibble(attributes);
+ (fg, bg)
+ }
+
+ pub(crate) fn set_colors(
+ fg: anstyle::AnsiColor,
+ bg: anstyle::AnsiColor,
+ ) -> CONSOLE_CHARACTER_ATTRIBUTES {
+ to_nibble(bg) << 4 | to_nibble(fg)
+ }
+
+ fn from_nibble(color: CONSOLE_CHARACTER_ATTRIBUTES) -> anstyle::AnsiColor {
+ if color & FOREGROUND_WHITE == FOREGROUND_WHITE {
+ // 3 bits high
+ anstyle::AnsiColor::White
+ } else if color & FOREGROUND_CYAN == FOREGROUND_CYAN {
+ // 2 bits high
+ anstyle::AnsiColor::Cyan
+ } else if color & FOREGROUND_YELLOW == FOREGROUND_YELLOW {
+ // 2 bits high
+ anstyle::AnsiColor::Yellow
+ } else if color & FOREGROUND_MAGENTA == FOREGROUND_MAGENTA {
+ // 2 bits high
+ anstyle::AnsiColor::Magenta
+ } else if color & FOREGROUND_RED == FOREGROUND_RED {
+ // 1 bit high
+ anstyle::AnsiColor::Red
+ } else if color & FOREGROUND_GREEN == FOREGROUND_GREEN {
+ // 1 bit high
+ anstyle::AnsiColor::Green
+ } else if color & FOREGROUND_BLUE == FOREGROUND_BLUE {
+ // 1 bit high
+ anstyle::AnsiColor::Blue
+ } else {
+ // 0 bits high
+ anstyle::AnsiColor::Black
+ }
+ .bright(color & FOREGROUND_INTENSITY == FOREGROUND_INTENSITY)
+ }
+
+ fn to_nibble(color: anstyle::AnsiColor) -> CONSOLE_CHARACTER_ATTRIBUTES {
+ let mut attributes = 0;
+ attributes |= match color.bright(false) {
+ anstyle::AnsiColor::Black => 0,
+ anstyle::AnsiColor::Red => FOREGROUND_RED,
+ anstyle::AnsiColor::Green => FOREGROUND_GREEN,
+ anstyle::AnsiColor::Yellow => FOREGROUND_YELLOW,
+ anstyle::AnsiColor::Blue => FOREGROUND_BLUE,
+ anstyle::AnsiColor::Magenta => FOREGROUND_MAGENTA,
+ anstyle::AnsiColor::Cyan => FOREGROUND_CYAN,
+ anstyle::AnsiColor::White => FOREGROUND_WHITE,
+ anstyle::AnsiColor::BrightBlack
+ | anstyle::AnsiColor::BrightRed
+ | anstyle::AnsiColor::BrightGreen
+ | anstyle::AnsiColor::BrightYellow
+ | anstyle::AnsiColor::BrightBlue
+ | anstyle::AnsiColor::BrightMagenta
+ | anstyle::AnsiColor::BrightCyan
+ | anstyle::AnsiColor::BrightWhite => unreachable!("brights were toggled off"),
+ };
+ if color.is_bright() {
+ attributes |= FOREGROUND_INTENSITY;
+ }
+ attributes
+ }
+
+ #[test]
+ fn to_from_nibble() {
+ const COLORS: [anstyle::AnsiColor; 16] = [
+ anstyle::AnsiColor::Black,
+ anstyle::AnsiColor::Red,
+ anstyle::AnsiColor::Green,
+ anstyle::AnsiColor::Yellow,
+ anstyle::AnsiColor::Blue,
+ anstyle::AnsiColor::Magenta,
+ anstyle::AnsiColor::Cyan,
+ anstyle::AnsiColor::White,
+ anstyle::AnsiColor::BrightBlack,
+ anstyle::AnsiColor::BrightRed,
+ anstyle::AnsiColor::BrightGreen,
+ anstyle::AnsiColor::BrightYellow,
+ anstyle::AnsiColor::BrightBlue,
+ anstyle::AnsiColor::BrightMagenta,
+ anstyle::AnsiColor::BrightCyan,
+ anstyle::AnsiColor::BrightWhite,
+ ];
+ for expected in COLORS {
+ let nibble = to_nibble(expected);
+ let actual = from_nibble(nibble);
+ assert_eq!(expected, actual, "Intermediate: {}", nibble);
+ }
+ }
+}