pager: refactor pager config (no-op)

In the future, we could consider adding a few more
special configs, e.g. `:pagerenv` that strictly uses
the `PAGER` environment variable, and `:unix` that
mimics Git's algorithm of trying `PAGER`, defaulting
to `less`, and setting `LESS`.
This commit is contained in:
Ilya Grigoriev 2025-01-13 23:07:28 -08:00
parent 891fe085a6
commit 8aa29169ea

View file

@ -201,8 +201,7 @@ impl Write for UiStderr<'_> {
pub struct Ui {
quiet: bool,
pager_cmd: CommandNameAndArgs,
paginate: PaginationChoice,
pager: PagerConfig,
progress_indicator: bool,
formatter_factory: FormatterFactory,
output: UiOutput,
@ -258,12 +257,31 @@ pub enum PaginationChoice {
Auto,
}
enum PagerConfig {
Disabled,
Builtin,
External(CommandNameAndArgs),
}
impl PagerConfig {
fn from_config(config: &StackedConfig) -> Result<PagerConfig, ConfigGetError> {
if matches!(config.get("ui.paginate")?, PaginationChoice::Never) {
return Ok(PagerConfig::Disabled);
};
match config.get("ui.pager")? {
CommandNameAndArgs::String(name) if name == BUILTIN_PAGER_NAME => {
Ok(PagerConfig::Builtin)
}
_ => Ok(PagerConfig::External(config.get("ui.pager")?)),
}
}
}
impl Ui {
pub fn null() -> Ui {
Ui {
quiet: true,
pager_cmd: CommandNameAndArgs::String(String::new()),
paginate: PaginationChoice::Never,
pager: PagerConfig::Disabled,
progress_indicator: false,
formatter_factory: FormatterFactory::plain_text(),
output: UiOutput::Null,
@ -275,8 +293,7 @@ impl Ui {
Ok(Ui {
quiet: config.get("ui.quiet")?,
formatter_factory,
pager_cmd: config.get("ui.pager")?,
paginate: config.get("ui.paginate")?,
pager: PagerConfig::from_config(config)?,
progress_indicator: config.get("ui.progress-indicator")?,
output: UiOutput::new_terminal(),
})
@ -284,8 +301,7 @@ impl Ui {
pub fn reset(&mut self, config: &StackedConfig) -> Result<(), CommandError> {
self.quiet = config.get("ui.quiet")?;
self.paginate = config.get("ui.paginate")?;
self.pager_cmd = config.get("ui.pager")?;
self.pager = PagerConfig::from_config(config)?;
self.progress_indicator = config.get("ui.progress-indicator")?;
self.formatter_factory = prepare_formatter_factory(config, &io::stdout())?;
Ok(())
@ -294,18 +310,15 @@ impl Ui {
/// Switches the output to use the pager, if allowed.
#[instrument(skip_all)]
pub fn request_pager(&mut self) {
match self.paginate {
PaginationChoice::Never => return,
PaginationChoice::Auto => {}
}
if !matches!(&self.output, UiOutput::Terminal { stdout, .. } if stdout.is_terminal()) {
return;
}
let use_builtin_pager = matches!(
&self.pager_cmd, CommandNameAndArgs::String(name) if name == BUILTIN_PAGER_NAME);
let new_output = if use_builtin_pager {
UiOutput::new_builtin_paged()
let new_output = match &self.pager {
PagerConfig::Disabled => {
return;
}
PagerConfig::Builtin => UiOutput::new_builtin_paged()
.inspect_err(|err| {
writeln!(
self.warning_default(),
@ -314,21 +327,22 @@ impl Ui {
)
.ok();
})
.ok()
} else {
UiOutput::new_paged(&self.pager_cmd)
.inspect_err(|err| {
// The pager executable couldn't be found or couldn't be run
writeln!(
self.warning_default(),
"Failed to spawn pager '{name}': {err}",
name = self.pager_cmd.split_name(),
err = format_error_with_sources(err),
)
.ok();
writeln!(self.hint_default(), "Consider using the `:builtin` pager.").ok();
})
.ok()
.ok(),
PagerConfig::External(command_name_and_args) => {
UiOutput::new_paged(command_name_and_args)
.inspect_err(|err| {
// The pager executable couldn't be found or couldn't be run
writeln!(
self.warning_default(),
"Failed to spawn pager '{name}': {err}",
name = command_name_and_args.split_name(),
err = format_error_with_sources(err),
)
.ok();
writeln!(self.hint_default(), "Consider using the `:builtin` pager.").ok();
})
.ok()
}
};
if let Some(output) = new_output {
self.output = output;