2020-12-30 13:25:23 +01:00
|
|
|
use shell_words::ParseError;
|
|
|
|
use std::env;
|
|
|
|
|
2020-12-28 22:29:03 +01:00
|
|
|
/// If we use a pager, this enum tells us from where we were told to use it.
|
2020-11-26 22:46:24 +01:00
|
|
|
#[derive(Debug, PartialEq)]
|
2021-01-10 13:07:24 +01:00
|
|
|
pub(crate) enum PagerSource {
|
2020-12-28 22:29:03 +01:00
|
|
|
/// From --config
|
|
|
|
Config,
|
|
|
|
|
2020-11-26 22:46:24 +01:00
|
|
|
/// From the env var BAT_PAGER
|
2021-01-10 13:16:09 +01:00
|
|
|
EnvVarBatPager,
|
2020-11-26 22:46:24 +01:00
|
|
|
|
|
|
|
/// From the env var PAGER
|
2021-01-10 13:16:09 +01:00
|
|
|
EnvVarPager,
|
2020-11-26 22:46:24 +01:00
|
|
|
|
|
|
|
/// No pager was specified, default is used
|
|
|
|
Default,
|
|
|
|
}
|
|
|
|
|
2020-12-30 13:25:23 +01:00
|
|
|
/// We know about some pagers, for example 'less'. This is a list of all pagers we know about
|
|
|
|
#[derive(Debug, PartialEq)]
|
2021-01-10 13:07:24 +01:00
|
|
|
pub(crate) enum PagerKind {
|
2021-01-10 13:25:18 +01:00
|
|
|
/// bat
|
2020-12-30 13:25:23 +01:00
|
|
|
Bat,
|
|
|
|
|
|
|
|
/// less
|
|
|
|
Less,
|
|
|
|
|
|
|
|
/// more
|
|
|
|
More,
|
|
|
|
|
|
|
|
/// most
|
|
|
|
Most,
|
|
|
|
|
|
|
|
/// A pager we don't know about
|
|
|
|
Unknown,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PagerKind {
|
|
|
|
fn from_bin(bin: &str) -> PagerKind {
|
|
|
|
use std::ffi::OsStr;
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
let stem = Path::new(bin)
|
|
|
|
.file_stem()
|
|
|
|
.unwrap_or_else(|| OsStr::new("unknown"));
|
|
|
|
|
|
|
|
if stem == OsStr::new("bat") {
|
|
|
|
PagerKind::Bat
|
|
|
|
} else if stem == OsStr::new("less") {
|
|
|
|
PagerKind::Less
|
|
|
|
} else if stem == OsStr::new("more") {
|
|
|
|
PagerKind::More
|
|
|
|
} else if stem == OsStr::new("most") {
|
|
|
|
PagerKind::Most
|
|
|
|
} else {
|
|
|
|
PagerKind::Unknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-28 22:29:03 +01:00
|
|
|
/// A pager such as 'less', and from where we got it.
|
2020-12-30 13:25:23 +01:00
|
|
|
#[derive(Debug)]
|
2021-01-10 13:07:24 +01:00
|
|
|
pub(crate) struct Pager {
|
2021-01-10 13:25:18 +01:00
|
|
|
/// The pager binary
|
2020-12-30 13:25:23 +01:00
|
|
|
pub bin: String,
|
|
|
|
|
2021-01-10 13:25:18 +01:00
|
|
|
/// The pager binary arguments (that we might tweak)
|
2020-12-30 13:25:23 +01:00
|
|
|
pub args: Vec<String>,
|
|
|
|
|
2021-01-10 13:25:18 +01:00
|
|
|
/// What pager this is
|
2020-12-30 13:25:23 +01:00
|
|
|
pub kind: PagerKind,
|
|
|
|
|
2021-01-10 13:25:18 +01:00
|
|
|
/// From where this pager comes
|
2020-11-26 22:46:24 +01:00
|
|
|
pub source: PagerSource,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Pager {
|
2020-12-30 13:25:23 +01:00
|
|
|
fn new(bin: &str, args: &[String], kind: PagerKind, source: PagerSource) -> Pager {
|
2020-11-26 22:46:24 +01:00
|
|
|
Pager {
|
2020-12-30 13:25:23 +01:00
|
|
|
bin: String::from(bin),
|
|
|
|
args: args.to_vec(),
|
|
|
|
kind,
|
2020-11-26 22:46:24 +01:00
|
|
|
source,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-28 22:29:03 +01:00
|
|
|
/// Returns what pager to use, after looking at both config and environment variables.
|
2021-01-10 13:07:24 +01:00
|
|
|
pub(crate) fn get_pager(config_pager: Option<&str>) -> Result<Option<Pager>, ParseError> {
|
2020-12-30 13:25:23 +01:00
|
|
|
let bat_pager = env::var("BAT_PAGER");
|
|
|
|
let pager = env::var("PAGER");
|
|
|
|
|
|
|
|
let (cmd, source) = match (config_pager, &bat_pager, &pager) {
|
|
|
|
(Some(config_pager), _, _) => (config_pager, PagerSource::Config),
|
2021-01-10 13:16:09 +01:00
|
|
|
(_, Ok(bat_pager), _) => (bat_pager.as_str(), PagerSource::EnvVarBatPager),
|
|
|
|
(_, _, Ok(pager)) => (pager.as_str(), PagerSource::EnvVarPager),
|
2020-12-30 13:25:23 +01:00
|
|
|
_ => ("less", PagerSource::Default),
|
|
|
|
};
|
|
|
|
|
|
|
|
let parts = shell_words::split(cmd)?;
|
|
|
|
match parts.split_first() {
|
|
|
|
Some((bin, args)) => {
|
|
|
|
let kind = PagerKind::from_bin(bin);
|
|
|
|
|
2021-01-10 13:25:18 +01:00
|
|
|
// 'more' and 'most' do not supports colors; automatically use 'less' instead
|
2020-12-30 13:25:23 +01:00
|
|
|
// if the problematic pager came from the generic PAGER env var
|
|
|
|
let no_color_support = kind == PagerKind::More || kind == PagerKind::Most;
|
2021-01-10 13:16:09 +01:00
|
|
|
let use_less_instead = no_color_support && source == PagerSource::EnvVarPager;
|
2020-12-30 13:25:23 +01:00
|
|
|
|
|
|
|
Ok(Some(if use_less_instead {
|
|
|
|
let no_args = vec![];
|
2021-01-10 13:16:09 +01:00
|
|
|
Pager::new("less", &no_args, PagerKind::Less, PagerSource::EnvVarPager)
|
2020-12-30 13:25:23 +01:00
|
|
|
} else {
|
|
|
|
Pager::new(bin, args, kind, source)
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
None => Ok(None),
|
2020-11-26 22:46:24 +01:00
|
|
|
}
|
|
|
|
}
|