Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ include = ["CHANGELOG.md", "Cargo.toml", "LICENSE", "README.md", "src/**/*.rs"]

[features]
default = ["unicode-width", "ansi-parsing", "std"]
std = ["dep:libc", "dep:once_cell", "alloc"]
std = ["dep:libc", "alloc"]
alloc = []
windows-console-colors = ["ansi-parsing"]
ansi-parsing = []

[dependencies]
libc = { version = "0.2.99", optional = true }
once_cell = { version = "1.8", optional = true }
unicode-width = { version = "0.2", optional = true }

[target.'cfg(windows)'.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ lint:
@cargo clippy --examples --tests --all-features -- --deny warnings

msrv-lock:
@cargo update -p once_cell --precise 1.20.3
@# cargo update -p once_cell --precise 1.20.3
Comment thread
cuviper marked this conversation as resolved.
Outdated

.PHONY: all doc build check test format format-check lint check-minver msrv-lock
19 changes: 10 additions & 9 deletions src/ansi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,18 +292,19 @@ mod tests {
use super::*;

use core::fmt::Write;
use once_cell::sync::Lazy;
use proptest::prelude::*;
use regex::Regex;
use std::sync::OnceLock;

// The manual dfa `State` is a handwritten translation from the previously used regex. That
// regex is kept here and used to ensure that the new matches are the same as the old
static STRIP_ANSI_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(
fn strip_ansi_re() -> &'static Regex {
static RE: OnceLock<Regex> = OnceLock::new();

RE.get_or_init(|| Regex::new(
r"[\x1b\x9b]([()][012AB]|[\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><])",
)
.unwrap()
});
).unwrap())
}

impl<'a> PartialEq<Match<'a>> for regex::Match<'_> {
fn eq(&self, other: &Match<'a>) -> bool {
Expand All @@ -314,7 +315,7 @@ mod tests {
proptest! {
#[test]
fn dfa_matches_old_regex(s in r"([\x1b\x9b]?.*){0,5}") {
let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(&s).collect();
let old_matches: Vec<_> = strip_ansi_re().find_iter(&s).collect();
let new_matches: Vec<_> = Matches::new(&s).collect();
assert_eq!(old_matches, new_matches);
}
Expand All @@ -334,7 +335,7 @@ mod tests {
fn _check_all_strings_of_len(len: usize, chunk: &mut Vec<u8>) {
if len == 0 {
if let Ok(s) = core::str::from_utf8(chunk) {
let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(s).collect();
let old_matches: Vec<_> = strip_ansi_re().find_iter(s).collect();
let new_matches: Vec<_> = Matches::new(s).collect();
assert_eq!(old_matches, new_matches);
}
Expand Down Expand Up @@ -363,7 +364,7 @@ mod tests {
)
.unwrap();

let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(&s).collect();
let old_matches: Vec<_> = strip_ansi_re().find_iter(&s).collect();
let new_matches: Vec<_> = Matches::new(&s).collect();
assert_eq!(old_matches, new_matches);
}
Expand Down
15 changes: 7 additions & 8 deletions src/unix_term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::{self, BufRead, BufReader};
use std::os::fd::{AsRawFd, RawFd};

#[cfg(not(target_os = "macos"))]
use once_cell::sync::Lazy;
use std::sync::OnceLock;

use crate::kb::Key;
use crate::term::Term;
Expand Down Expand Up @@ -380,20 +380,19 @@ fn key_from_utf8(buf: &[u8]) -> Key {
Key::Unknown
}

#[cfg(not(target_os = "macos"))]
static IS_LANG_UTF8: Lazy<bool> = Lazy::new(|| match std::env::var("LANG") {
Ok(lang) => lang.to_uppercase().ends_with("UTF-8"),
_ => false,
});

#[cfg(target_os = "macos")]
pub(crate) fn wants_emoji() -> bool {
true
}

#[cfg(not(target_os = "macos"))]
pub(crate) fn wants_emoji() -> bool {
*IS_LANG_UTF8
static IS_LANG_UTF8: OnceLock<bool> = OnceLock::new();

*IS_LANG_UTF8.get_or_init(|| match std::env::var("LANG") {
Ok(lang) => lang.to_uppercase().ends_with("UTF-8"),
_ => false,
})
}

pub(crate) fn set_title<T: Display>(title: T) {
Expand Down
42 changes: 25 additions & 17 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::{
};
use std::env;

use once_cell::sync::Lazy;
use std::sync::OnceLock;

use crate::term::{wants_emoji, Term};

Expand All @@ -22,14 +22,22 @@ fn default_true_colors_enabled(out: &Term) -> bool {
out.features().true_colors_supported()
}

static STDOUT_COLORS: Lazy<AtomicBool> =
Lazy::new(|| AtomicBool::new(default_colors_enabled(&Term::stdout())));
static STDOUT_TRUE_COLORS: Lazy<AtomicBool> =
Lazy::new(|| AtomicBool::new(default_true_colors_enabled(&Term::stdout())));
static STDERR_COLORS: Lazy<AtomicBool> =
Lazy::new(|| AtomicBool::new(default_colors_enabled(&Term::stderr())));
static STDERR_TRUE_COLORS: Lazy<AtomicBool> =
Lazy::new(|| AtomicBool::new(default_true_colors_enabled(&Term::stderr())));
fn stdout_colors() -> &'static AtomicBool {
static ENABLED: OnceLock<AtomicBool> = OnceLock::new();
ENABLED.get_or_init(|| AtomicBool::new(default_colors_enabled(&Term::stdout())))
}
fn stdout_true_colors() -> &'static AtomicBool {
static ENABLED: OnceLock<AtomicBool> = OnceLock::new();
ENABLED.get_or_init(|| AtomicBool::new(default_true_colors_enabled(&Term::stdout())))
}
fn stderr_colors() -> &'static AtomicBool {
static ENABLED: OnceLock<AtomicBool> = OnceLock::new();
ENABLED.get_or_init(|| AtomicBool::new(default_colors_enabled(&Term::stderr())))
}
fn stderr_true_colors() -> &'static AtomicBool {
static ENABLED: OnceLock<AtomicBool> = OnceLock::new();
ENABLED.get_or_init(|| AtomicBool::new(default_true_colors_enabled(&Term::stderr())))
}

/// Returns `true` if colors should be enabled for stdout.
///
Expand All @@ -40,13 +48,13 @@ static STDERR_TRUE_COLORS: Lazy<AtomicBool> =
/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what.
#[inline]
pub fn colors_enabled() -> bool {
STDOUT_COLORS.load(Ordering::Relaxed)
stdout_colors().load(Ordering::Relaxed)
}

/// Returns `true` if true colors should be enabled for stdout.
#[inline]
pub fn true_colors_enabled() -> bool {
STDOUT_TRUE_COLORS.load(Ordering::Relaxed)
stdout_true_colors().load(Ordering::Relaxed)
}

/// Forces colorization on or off for stdout.
Expand All @@ -55,7 +63,7 @@ pub fn true_colors_enabled() -> bool {
/// `colors_enabled` function.
#[inline]
pub fn set_colors_enabled(val: bool) {
STDOUT_COLORS.store(val, Ordering::Relaxed)
stdout_colors().store(val, Ordering::Relaxed)
}

/// Forces true colorization on or off for stdout.
Expand All @@ -64,7 +72,7 @@ pub fn set_colors_enabled(val: bool) {
/// `true_colors_enabled` function.
#[inline]
pub fn set_true_colors_enabled(val: bool) {
STDOUT_TRUE_COLORS.store(val, Ordering::Relaxed)
stdout_true_colors().store(val, Ordering::Relaxed)
}

/// Returns `true` if colors should be enabled for stderr.
Expand All @@ -76,13 +84,13 @@ pub fn set_true_colors_enabled(val: bool) {
/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what.
#[inline]
pub fn colors_enabled_stderr() -> bool {
STDERR_COLORS.load(Ordering::Relaxed)
stderr_colors().load(Ordering::Relaxed)
}

/// Returns `true` if true colors should be enabled for stderr.
#[inline]
pub fn true_colors_enabled_stderr() -> bool {
STDERR_TRUE_COLORS.load(Ordering::Relaxed)
stderr_true_colors().load(Ordering::Relaxed)
}

/// Forces colorization on or off for stderr.
Expand All @@ -91,7 +99,7 @@ pub fn true_colors_enabled_stderr() -> bool {
/// `colors_enabled_stderr` function.
#[inline]
pub fn set_colors_enabled_stderr(val: bool) {
STDERR_COLORS.store(val, Ordering::Relaxed)
stderr_colors().store(val, Ordering::Relaxed)
}

/// Forces true colorization on or off for stderr.
Expand All @@ -100,7 +108,7 @@ pub fn set_colors_enabled_stderr(val: bool) {
/// `true_colors_enabled_stderr` function.
#[inline]
pub fn set_true_colors_enabled_stderr(val: bool) {
STDERR_TRUE_COLORS.store(val, Ordering::Relaxed)
stderr_true_colors().store(val, Ordering::Relaxed)
}

/// Measure the width of a string in terminal characters.
Expand Down
Loading