Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1063: Do not use 'more' or 'most' PAGER, as they are not compatible with bats output #1402

Merged
merged 21 commits into from
Jan 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f420236
Add Pager helper with info about where the value comes from
Enselic Nov 26, 2020
986d0e9
Ignore PAGER=most by default with a warning to stderr
Enselic Nov 27, 2020
cc0f8ca
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Dec 28, 2020
dcfe883
Simplify and polish pager.rs and related code
Enselic Dec 28, 2020
552545f
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Dec 28, 2020
22bdc7c
When PAGER=most, don't print a warning to stderr, silently use less i…
Enselic Dec 30, 2020
bfa5342
Also replace 'more' from PAGER with 'less'
Enselic Dec 30, 2020
c9efdd6
Add integration tests for 'more' and 'most' used as pagers
Enselic Jan 4, 2021
df33ed0
Run PATH-dependent tests serially
Enselic Jan 4, 2021
e87c554
tests: Make mocked pagers work on Windows
Enselic Jan 4, 2021
478233f
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Jan 4, 2021
46487b2
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Jan 6, 2021
da10166
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Jan 7, 2021
02e6ff4
Merge remote-tracking branch 'origin/master' into fix-1063
Enselic Jan 10, 2021
fc30277
pager.rs: Limit visibilities to pub(crate)
Enselic Jan 10, 2021
dfe7a60
PagerSource: [Bat]PagerEnvVar -> EnvVar[Bat]Pager
Enselic Jan 10, 2021
dd6f57e
pager.rs: Some comment fixups
Enselic Jan 10, 2021
c2c2b02
fn mocked_pager: Simplify with format!
Enselic Jan 10, 2021
7809008
PagerKind::from(): Simplify
Enselic Jan 10, 2021
eda72c3
tests: Move 'mocked pagers' utils to separate file
Enselic Jan 10, 2021
8dd67cc
Revert accidental change to assets/syntaxes/02_Extra/VimL
Enselic Jan 10, 2021
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- VimL syntax highlighting fix, see #1450 (@esensar)
- Print an 'Invalid syntax theme settings' error message if a custom theme is broken, see #614 (@Enselic)
- If plain mode is set and wrap is not explicitly opted in, long lines will no be truncated, see #1426
- If `PAGER` (but not `BAT_PAGER` or `--pager`) is `more` or `most`, silently use `less` instead to ensure support for colors, see #1063 (@Enselic)

## Other

Expand Down
78 changes: 78 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ default-features = false
[dev-dependencies]
tempdir = "0.3"
assert_cmd = "1.0.2"
serial_test = "0.5.1"
predicates = "1.0.6"
wait-timeout = "0.2.0"

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ mod less;
pub mod line_range;
mod output;
#[cfg(feature = "paging")]
mod pager;
#[cfg(feature = "paging")]
pub(crate) mod paging;
mod preprocessor;
mod pretty_printer;
Expand Down
135 changes: 53 additions & 82 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,100 +48,71 @@ impl OutputType {
wrapping_mode: WrappingMode,
pager_from_config: Option<&str>,
) -> Result<Self> {
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use crate::pager::{self, PagerKind, PagerSource};
use std::process::{Command, Stdio};

let mut replace_arguments_to_less = false;
let pager_opt =
pager::get_pager(pager_from_config).chain_err(|| "Could not parse pager command.")?;

let pager_from_env = match (env::var("BAT_PAGER"), env::var("PAGER")) {
(Ok(bat_pager), _) => Some(bat_pager),
(_, Ok(pager)) => {
// less needs to be called with the '-R' option in order to properly interpret the
// ANSI color sequences printed by bat. If someone has set PAGER="less -F", we
// therefore need to overwrite the arguments and add '-R'.
//
// We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER
// or bats '--pager' command line option.
replace_arguments_to_less = true;
Some(pager)
}
_ => None,
let pager = match pager_opt {
Some(pager) => pager,
None => return Ok(OutputType::stdout()),
};

let pager_from_config = pager_from_config.map(|p| p.to_string());

if pager_from_config.is_some() {
replace_arguments_to_less = false;
if pager.kind == PagerKind::Bat {
return Err(ErrorKind::InvalidPagerValueBat.into());
}

let pager = pager_from_config
.or(pager_from_env)
.unwrap_or_else(|| String::from("less"));

let pagerflags =
shell_words::split(&pager).chain_err(|| "Could not parse pager command.")?;

match pagerflags.split_first() {
Some((pager_name, args)) => {
let pager_path = PathBuf::from(pager_name);
let mut p = Command::new(pager.bin);
let args = pager.args;

if pager.kind == PagerKind::Less {
// less needs to be called with the '-R' option in order to properly interpret the
// ANSI color sequences printed by bat. If someone has set PAGER="less -F", we
// therefore need to overwrite the arguments and add '-R'.
//
// We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER
// or bats '--pager' command line option.
let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager;

if args.is_empty() || replace_arguments_to_less {
p.arg("--RAW-CONTROL-CHARS");
if single_screen_action == SingleScreenAction::Quit {
p.arg("--quit-if-one-screen");
}

if pager_path.file_stem() == Some(&OsString::from("bat")) {
return Err(ErrorKind::InvalidPagerValueBat.into());
if wrapping_mode == WrappingMode::NoWrapping(true) {
p.arg("--chop-long-lines");
}

let is_less = pager_path.file_stem() == Some(&OsString::from("less"));

let mut process = if is_less {
let mut p = Command::new(&pager_path);
if args.is_empty() || replace_arguments_to_less {
p.arg("--RAW-CONTROL-CHARS");
if single_screen_action == SingleScreenAction::Quit {
p.arg("--quit-if-one-screen");
}

if wrapping_mode == WrappingMode::NoWrapping(true) {
p.arg("--chop-long-lines");
}

// Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
// versions of 'less'. Unfortunately, it also breaks mouse-wheel support.
//
// See: http://www.greenwoodsoftware.com/less/news.530.html
//
// For newer versions (530 or 558 on Windows), we omit '--no-init' as it
// is not needed anymore.
match retrieve_less_version() {
None => {
p.arg("--no-init");
}
Some(version)
if (version < 530 || (cfg!(windows) && version < 558)) =>
{
p.arg("--no-init");
}
_ => {}
}
} else {
p.args(args);
// Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
// versions of 'less'. Unfortunately, it also breaks mouse-wheel support.
//
// See: http://www.greenwoodsoftware.com/less/news.530.html
//
// For newer versions (530 or 558 on Windows), we omit '--no-init' as it
// is not needed anymore.
match retrieve_less_version() {
None => {
p.arg("--no-init");
}
Some(version) if (version < 530 || (cfg!(windows) && version < 558)) => {
p.arg("--no-init");
}
p.env("LESSCHARSET", "UTF-8");
p
} else {
let mut p = Command::new(&pager_path);
p.args(args);
p
};

Ok(process
.stdin(Stdio::piped())
.spawn()
.map(OutputType::Pager)
.unwrap_or_else(|_| OutputType::stdout()))
_ => {}
}
} else {
p.args(args);
}
None => Ok(OutputType::stdout()),
}
p.env("LESSCHARSET", "UTF-8");
} else {
p.args(args);
};

Ok(p.stdin(Stdio::piped())
.spawn()
.map(OutputType::Pager)
.unwrap_or_else(|_| OutputType::stdout()))
}

pub(crate) fn stdout() -> Self {
Expand Down
Loading