Skip to content

Commit 84b01f2

Browse files
committed
Fix bug where colours were incorrectly applied
exa assumed that the COLUMNS environment variable being present always meant that the output was to a terminal, so it should use colours. But because this variable can be overridden, colours were being incorrectly set! The ‘fix’ is to stop trying to be clever while only calculating the terminal width once, and instead just stick it in a lazy_static so it’s usable everywhere.
1 parent b8bb148 commit 84b01f2

File tree

5 files changed

+94
-62
lines changed

5 files changed

+94
-62
lines changed

Cargo.lock

Lines changed: 49 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ansi_term = "0.8.0"
1616
datetime = "0.4.3"
1717
getopts = "0.2.14"
1818
glob = "0.2"
19+
lazy_static = "0.2"
1920
libc = "0.2.9"
2021
locale = "0.2.1"
2122
natord = "1.0.7"

src/exa.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ extern crate zoneinfo_compiled;
1818

1919
#[cfg(feature="git")] extern crate git2;
2020

21+
#[macro_use]
22+
extern crate lazy_static;
23+
24+
2125
use std::ffi::OsStr;
2226
use std::io::{stderr, Write, Result as IOResult};
2327
use std::path::{Component, Path};

src/options/view.rs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use output::{Grid, Details, GridDetails};
77
use output::column::{Columns, TimeTypes, SizeFormat};
88
use output::file_name::Classify;
99
use options::{FileFilter, DirAction, Misfire};
10-
use term::dimensions;
1110
use fs::feature::xattr;
1211

1312

@@ -45,10 +44,6 @@ impl Mode {
4544
pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<(Mode, Colours), Misfire> {
4645
use options::misfire::Misfire::*;
4746

48-
let colour_scale = || {
49-
matches.opt_present("color-scale") || matches.opt_present("colour-scale")
50-
};
51-
5247
let long = || {
5348
if matches.opt_present("across") && !matches.opt_present("grid") {
5449
Err(Useless("across", true, "long"))
@@ -57,19 +52,7 @@ impl Mode {
5752
Err(Useless("oneline", true, "long"))
5853
}
5954
else {
60-
let term_colours = TerminalColours::deduce(matches)?;
61-
let colours = match term_colours {
62-
TerminalColours::Always => Colours::colourful(colour_scale()),
63-
TerminalColours::Never => Colours::plain(),
64-
TerminalColours::Automatic => {
65-
if dimensions().is_some() {
66-
Colours::colourful(colour_scale())
67-
}
68-
else {
69-
Colours::plain()
70-
}
71-
},
72-
};
55+
let colours = Colours::deduce(matches)?;
7356

7457
let details = Details {
7558
columns: Some(Columns::deduce(matches)?),
@@ -105,15 +88,8 @@ impl Mode {
10588
};
10689

10790
let other_options_scan = || {
108-
let term_colours = TerminalColours::deduce(matches)?;
109-
let term_width = TerminalWidth::deduce()?;
110-
111-
if let Some(width) = term_width.width() {
112-
let colours = match term_colours {
113-
TerminalColours::Always |
114-
TerminalColours::Automatic => Colours::colourful(colour_scale()),
115-
TerminalColours::Never => Colours::plain(),
116-
};
91+
if let Some(width) = TerminalWidth::deduce()?.width() {
92+
let colours = Colours::deduce(matches)?;
11793

11894
if matches.opt_present("oneline") {
11995
if matches.opt_present("across") {
@@ -148,10 +124,7 @@ impl Mode {
148124
// as the program’s stdout being connected to a file, then
149125
// fallback to the lines view.
150126

151-
let colours = match term_colours {
152-
TerminalColours::Always => Colours::colourful(colour_scale()),
153-
TerminalColours::Never | TerminalColours::Automatic => Colours::plain(),
154-
};
127+
let colours = Colours::deduce(matches)?;
155128

156129
if matches.opt_present("tree") {
157130
let details = Details {
@@ -222,7 +195,7 @@ impl TerminalWidth {
222195
Err(e) => Err(Misfire::FailedParse(e)),
223196
}
224197
}
225-
else if let Some((width, _)) = dimensions() {
198+
else if let Some(width) = *TERM_WIDTH {
226199
Ok(TerminalWidth::Terminal(width))
227200
}
228201
else {
@@ -373,10 +346,37 @@ impl TerminalColours {
373346
}
374347

375348

349+
impl Colours {
350+
fn deduce(matches: &getopts::Matches) -> Result<Colours, Misfire> {
351+
use self::TerminalColours::*;
352+
353+
let tc = TerminalColours::deduce(matches)?;
354+
if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
355+
let scale = matches.opt_present("color-scale") || matches.opt_present("colour-scale");
356+
Ok(Colours::colourful(scale))
357+
}
358+
else {
359+
Ok(Colours::plain())
360+
}
361+
}
362+
}
363+
364+
376365

377366
impl Classify {
378367
fn deduce(matches: &getopts::Matches) -> Classify {
379368
if matches.opt_present("classify") { Classify::AddFileIndicators }
380369
else { Classify::JustFilenames }
381370
}
382371
}
372+
373+
374+
// Gets, then caches, the width of the terminal that exa is running in.
375+
// This gets used multiple times above, with no real guarantee of order,
376+
// so it’s easier to just cache it the first time it runs.
377+
lazy_static! {
378+
static ref TERM_WIDTH: Option<usize> = {
379+
use term::dimensions;
380+
dimensions().map(|t| t.0)
381+
};
382+
}

xtests/run.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ $exa $testcases/files -lhB | diff -q - $results/files_lhb2 || exit 1
2929
$exa $testcases/attributes/dirs/empty-with-attribute -lh | diff -q - $results/empty || exit 1
3030

3131
$exa --color-scale $testcases/files -l | diff -q - $results/files_l_scale || exit 1
32-
$exa_binary $testcases/files -l | diff -q - $results/files_l_bw || exit 1
33-
$exa_binary --colour=never $testcases/files -l | diff -q - $results/files_l_bw || exit 1
3432

3533

3634
# Grid view tests
@@ -110,6 +108,14 @@ COLUMNS=80 $exa $testcases/links 2>&1 | diff -q - $results/links || ex
110108
$exa $testcases/links/* -1 | diff -q - $results/links_1_files || exit 1
111109

112110

111+
# Colours and terminals
112+
# Just because COLUMNS is present, doesn’t mean output is to a terminal
113+
COLUMNS=80 $exa_binary $testcases/files -l | diff -q - $results/files_l_bw || exit 1
114+
COLUMNS=80 $exa_binary --colour=always $testcases/files -l | diff -q - $results/files_l || exit 1
115+
COLUMNS=80 $exa_binary --colour=never $testcases/files -l | diff -q - $results/files_l_bw || exit 1
116+
COLUMNS=80 $exa_binary --colour=automatic $testcases/files -l | diff -q - $results/files_l_bw || exit 1
117+
118+
113119
# Git
114120
$exa $testcases/git/additions -l --git 2>&1 | diff -q - $results/git_additions || exit 1
115121
$exa $testcases/git/edits -l --git 2>&1 | diff -q - $results/git_edits || exit 1

0 commit comments

Comments
 (0)