One step toward colors support
diff --git a/src/config.rs b/src/config.rs
index d1dbc42..f5199a8 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -20,6 +20,8 @@
/// If true, each nonblank line returned by `readline` will be
/// automatically added to the history.
auto_add_history: bool,
+ /// if colors should be enabled.
+ color_mode: ColorMode,
}
impl Config {
@@ -70,6 +72,13 @@
pub fn auto_add_history(&self) -> bool {
self.auto_add_history
}
+
+ /// Tell if colors should be enabled.
+ ///
+ /// By default, they are except if stdout is not a tty.
+ pub fn color_mode(&self) -> ColorMode {
+ self.color_mode
+ }
}
impl Default for Config {
@@ -83,6 +92,7 @@
keyseq_timeout: -1,
edit_mode: EditMode::Emacs,
auto_add_history: false,
+ color_mode: ColorMode::Enabled,
}
}
}
@@ -111,6 +121,14 @@
Vi,
}
+/// Colorization mode
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum ColorMode {
+ Enabled,
+ Forced,
+ Disabled,
+}
+
/// Configuration builder
#[derive(Debug, Default)]
pub struct Builder {
@@ -193,6 +211,14 @@
self
}
+ /// Forces colorization on or off.
+ ///
+ /// By default, colorization is on except if stdout is not a tty.
+ pub fn colors_enabled(mut self, color_mode: ColorMode) -> Builder {
+ self.p.color_mode = color_mode;
+ self
+ }
+
pub fn build(self) -> Config {
self.p
}
diff --git a/src/lib.rs b/src/lib.rs
index a5e72bb..41f224d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -656,7 +656,7 @@
/// Create an editor with a specific configuration.
pub fn with_config(config: Config) -> Editor<H> {
- let term = Terminal::new();
+ let term = Terminal::new(config.color_mode());
Editor {
term,
history: History::with_config(config),
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index e6c42dc..1047c42 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -3,7 +3,7 @@
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
-use config::Config;
+use config::{ColorMode, Config};
use consts::KeyPress;
use line_buffer::LineBuffer;
use Result;
@@ -120,14 +120,16 @@
type Writer: Renderer; // rl_outstream
type Mode: RawMode;
- fn new() -> Self;
+ fn new(color_mode: ColorMode) -> Self;
/// Check if current terminal can provide a rich line-editing user
/// interface.
fn is_unsupported(&self) -> bool;
/// check if stdin is connected to a terminal.
fn is_stdin_tty(&self) -> bool;
+ /// Check if output supports colors.
+ fn colors_enabled(&self) -> bool;
/// Enable RAW mode for the terminal.
- fn enable_raw_mode(&self) -> Result<Self::Mode>;
+ fn enable_raw_mode(&mut self) -> Result<Self::Mode>;
/// Create a RAW reader
fn create_reader(&self, config: &Config) -> Result<Self::Reader>;
/// Create a writer
diff --git a/src/tty/test.rs b/src/tty/test.rs
index 29a1e79..b8e5df5 100644
--- a/src/tty/test.rs
+++ b/src/tty/test.rs
@@ -4,7 +4,7 @@
use std::vec::IntoIter;
use super::{truncate, Position, RawMode, RawReader, Renderer, Term};
-use config::Config;
+use config::{ColorMode, Config};
use consts::KeyPress;
use error::ReadlineError;
use line_buffer::LineBuffer;
@@ -121,7 +121,7 @@
type Writer = Sink;
type Mode = Mode;
- fn new() -> DummyTerminal {
+ fn new(_color_mode: ColorMode) -> DummyTerminal {
DummyTerminal {
keys: Vec::new(),
cursor: 0,
@@ -138,9 +138,13 @@
true
}
+ fn colors_enabled(&self) -> bool {
+ false
+ }
+
// Interactive loop:
- fn enable_raw_mode(&self) -> Result<Mode> {
+ fn enable_raw_mode(&mut self) -> Result<Mode> {
Ok(())
}
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index b1d5b78..cd35e30 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -13,7 +13,7 @@
use unicode_segmentation::UnicodeSegmentation;
use super::{truncate, width, Position, RawMode, RawReader, Renderer, Term};
-use config::Config;
+use config::{ColorMode, Config};
use consts::{self, KeyPress};
use error;
use line_buffer::LineBuffer;
@@ -533,6 +533,8 @@
pub struct PosixTerminal {
unsupported: bool,
stdin_isatty: bool,
+ stdout_isatty: bool,
+ color_mode: ColorMode,
}
impl Term for PosixTerminal {
@@ -540,12 +542,14 @@
type Writer = PosixRenderer;
type Mode = Mode;
- fn new() -> PosixTerminal {
+ fn new(color_mode: ColorMode) -> PosixTerminal {
let term = PosixTerminal {
unsupported: is_unsupported_term(),
stdin_isatty: is_a_tty(STDIN_FILENO),
+ stdout_isatty: is_a_tty(STDOUT_FILENO),
+ color_mode,
};
- if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
+ if !term.unsupported && term.stdin_isatty && term.stdout_isatty {
install_sigwinch_handler();
}
term
@@ -564,9 +568,18 @@
self.stdin_isatty
}
+ /// Check if output supports colors.
+ fn colors_enabled(&self) -> bool {
+ match self.color_mode {
+ ColorMode::Enabled => self.stdout_isatty,
+ ColorMode::Forced => true,
+ ColorMode::Disabled => false,
+ }
+ }
+
// Interactive loop:
- fn enable_raw_mode(&self) -> Result<Mode> {
+ fn enable_raw_mode(&mut self) -> Result<Mode> {
use nix::errno::Errno::ENOTTY;
use nix::sys::termios::{ControlFlags, InputFlags, LocalFlags, SpecialCharacterIndices};
if !self.stdin_isatty {
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index 6d9fa36..2602767 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -9,7 +9,7 @@
use winapi::um::{consoleapi, handleapi, processenv, winbase, wincon, winuser};
use super::{truncate, Position, RawMode, RawReader, Renderer, Term};
-use config::Config;
+use config::{ColorMode, Config};
use consts::{self, KeyPress};
use error;
use line_buffer::LineBuffer;
@@ -65,7 +65,7 @@
pub struct ConsoleMode {
original_stdin_mode: DWORD,
stdin_handle: HANDLE,
- original_stdout_mode: DWORD,
+ original_stdout_mode: Option<DWORD>,
stdout_handle: HANDLE,
}
@@ -76,10 +76,12 @@
self.stdin_handle,
self.original_stdin_mode,
));
- check!(consoleapi::SetConsoleMode(
- self.stdout_handle,
- self.original_stdout_mode,
- ));
+ if let Some(original_stdout_mode) = self.original_stdout_mode {
+ check!(consoleapi::SetConsoleMode(
+ self.stdout_handle,
+ original_stdout_mode,
+ ));
+ }
Ok(())
}
}
@@ -396,7 +398,10 @@
pub struct Console {
stdin_isatty: bool,
stdin_handle: HANDLE,
+ stdout_isatty: bool,
stdout_handle: HANDLE,
+ color_mode: ColorMode,
+ ansi_colors_supported: bool,
}
impl Console {}
@@ -406,7 +411,7 @@
type Writer = ConsoleRenderer;
type Mode = Mode;
- fn new() -> Console {
+ fn new(color_mode: ColorMode) -> Console {
use std::ptr;
let stdin_handle = get_std_handle(STDIN_FILENO);
let stdin_isatty = match stdin_handle {
@@ -416,12 +421,22 @@
}
Err(_) => false,
};
+ let stdout_handle = get_std_handle(STDOUT_FILENO);
+ let stdout_isatty = match stdout_handle {
+ Ok(handle) => {
+ // If this function doesn't fail then fd is a TTY
+ get_console_mode(handle).is_ok()
+ }
+ Err(_) => false,
+ };
- let stdout_handle = get_std_handle(STDOUT_FILENO).unwrap_or(ptr::null_mut());
Console {
stdin_isatty,
stdin_handle: stdin_handle.unwrap_or(ptr::null_mut()),
- stdout_handle,
+ stdout_isatty,
+ stdout_handle: stdout_handle.unwrap_or(ptr::null_mut()),
+ color_mode,
+ ansi_colors_supported: false,
}
}
@@ -434,12 +449,20 @@
self.stdin_isatty
}
+ fn colors_enabled(&self) -> bool {
+ match self.color_mode {
+ ColorMode::Enabled => self.stdout_isatty,
+ ColorMode::Forced => true,
+ ColorMode::Disabled => false,
+ }
+ }
+
// pub fn install_sigwinch_handler(&mut self) {
// See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
// }
/// Enable RAW mode for the terminal.
- fn enable_raw_mode(&self) -> Result<Mode> {
+ fn enable_raw_mode(&mut self) -> Result<Mode> {
if !self.stdin_isatty {
try!(Err(io::Error::new(
io::ErrorKind::Other,
@@ -459,13 +482,19 @@
let raw = raw | wincon::ENABLE_WINDOW_INPUT;
check!(consoleapi::SetConsoleMode(self.stdin_handle, raw));
- let original_stdout_mode = try!(get_console_mode(self.stdout_handle));
- // To enable ANSI colors (Windows 10 only):
- // https://docs.microsoft.com/en-us/windows/console/setconsolemode
- if original_stdout_mode & wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
- let raw = original_stdout_mode | wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- check!(consoleapi::SetConsoleMode(self.stdout_handle, raw));
- }
+ let original_stdout_mode = if self.stdout_isatty {
+ let original_stdout_mode = try!(get_console_mode(self.stdout_handle));
+ // To enable ANSI colors (Windows 10 only):
+ // https://docs.microsoft.com/en-us/windows/console/setconsolemode
+ if original_stdout_mode & wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
+ let raw = original_stdout_mode | wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ self.ansi_colors_supported =
+ consoleapi::SetConsoleMode(self.stdout_handle, raw) != 0;
+ }
+ Some(original_stdout_mode)
+ } else {
+ None
+ };
Ok(Mode {
original_stdin_mode,