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 $LESSOPEN tests and behavior #2662

Merged
merged 5 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Features

- Add environment variable `BAT_PAGING`, see #2629 (@einfachIrgendwer0815)
- Add support for `LESSOPEN` and `LESSCLOSE`. See #1597, #1739, #2444, #2602, and #2662 (@Anomalocaridid)

## Bugfixes

Expand Down Expand Up @@ -77,7 +78,6 @@

- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic)
- Support for separate system and user config files. See #668 (@patrickpichler)
- Add support for $LESSOPEN and $LESSCLOSE. See #1597, #1739, and #2444 (@Anomalocaridid)

## Bugfixes

Expand Down
3 changes: 2 additions & 1 deletion assets/completions/_bat.ps1.in
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
[CompletionResult]::new('--unbuffered', 'unbuffered', [CompletionResultType]::ParameterName, 'unbuffered')
[CompletionResult]::new('--no-config', 'no-config', [CompletionResultType]::ParameterName, 'Do not use the configuration file')
[CompletionResult]::new('--no-custom-assets', 'no-custom-assets', [CompletionResultType]::ParameterName, 'Do not load custom assets')
[CompletionResult]::new('--no-lessopen', 'no-lessopen', [CompletionResultType]::ParameterName, 'Do not use the $LESSOPEN preprocessor')
[CompletionResult]::new('--lessopen', 'lessopen', [CompletionResultType]::ParameterName, 'Enable the $LESSOPEN preprocessor')
[CompletionResult]::new('--no-lessopen', 'no-lessopen', [CompletionResultType]::ParameterName, 'Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)')
[CompletionResult]::new('--config-file', 'config-file', [CompletionResultType]::ParameterName, 'Show path to the configuration file.')
[CompletionResult]::new('--generate-config-file', 'generate-config-file', [CompletionResultType]::ParameterName, 'Generates a default configuration file.')
[CompletionResult]::new('--config-dir', 'config-dir', [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.')
Expand Down
2 changes: 2 additions & 0 deletions assets/completions/bat.bash.in
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ _bat() {
--list-themes | \
--line-range | \
-L | --list-languages | \
--lessopen | \
--diagnostic | \
--acknowledgements | \
-h | --help | \
Expand Down Expand Up @@ -171,6 +172,7 @@ _bat() {
--style
--line-range
--list-languages
--lessopen
--diagnostic
--acknowledgements
--help
Expand Down
2 changes: 2 additions & 0 deletions assets/completions/bat.fish.in
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ complete -c $bat -l italic-text -x -a "$italic_text_opts" -d "When to use italic

complete -c $bat -s l -l language -x -k -a "(__bat_complete_list_languages)" -d "Set the syntax highlighting language" -n __bat_no_excl_args

complete -c $bat -l lessopen -d "Enable the $LESSOPEN preprocessor" -n __fish_is_first_arg

complete -c $bat -s r -l line-range -x -d "Only print lines [M]:[N] (either optional)" -n __bat_no_excl_args

complete -c $bat -l list-languages -f -d "List syntax highlighting languages" -n __fish_is_first_arg
Expand Down
3 changes: 2 additions & 1 deletion assets/completions/bat.zsh.in
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ _{{PROJECT_EXECUTABLE}}_main() {
'(: --list-themes --list-languages -L)'{-L,--list-languages}'[Display all supported languages]'
'(: --no-config)'--no-config'[Do not use the configuration file]'
'(: --no-custom-assets)'--no-custom-assets'[Do not load custom assets]'
'(: --no-lessopen)'--no-lessopen'[Do not use the $LESSOPEN preprocessor]'
'(: --lessopen)'--lessopen'[Enable the $LESSOPEN preprocessor]'
'(: --no-lessopen)'--no-lessopen'[Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)]'
'(: --config-dir)'--config-dir'[Show bat'"'"'s configuration directory]'
'(: --config-file)'--config-file'[Show path to the configuration file]'
'(: --generate-config-file)'--generate-config-file'[Generates a default configuration file]'
Expand Down
8 changes: 7 additions & 1 deletion assets/manual/bat.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,13 @@ These can be installed to `\fB$({{PROJECT_EXECUTABLE}} --config-dir)/themes\fR`,
Much like less(1) does, {{PROJECT_EXECUTABLE}} supports input preprocessors via the LESSOPEN and LESSCLOSE environment variables.
In addition, {{PROJECT_EXECUTABLE}} attempts to be as compatible with less's preprocessor implementation as possible.

To run {{PROJECT_EXECUTABLE}} without using the preprocessor, call:
To use the preprocessor, call:

\fB{{PROJECT_EXECUTABLE}} --lessopen\fR

Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file.

To temporarily disable the preprocessor if it is enabled by default, call:

\fB{{PROJECT_EXECUTABLE}} --no-lessopen\fR

Expand Down
2 changes: 1 addition & 1 deletion src/bin/bat/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl App {
.unwrap_or_default(),
use_custom_assets: !self.matches.get_flag("no-custom-assets"),
#[cfg(feature = "lessopen")]
use_lessopen: !self.matches.get_flag("no-lessopen"),
use_lessopen: self.matches.get_flag("lessopen"),
})
}

Expand Down
22 changes: 15 additions & 7 deletions src/bin/bat/clap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,13 +501,21 @@ pub fn build_app(interactive_output: bool) -> Command {

#[cfg(feature = "lessopen")]
{
app = app.arg(
Arg::new("no-lessopen")
.long("no-lessopen")
.action(ArgAction::SetTrue)
.hide(true)
.help("Do not use the $LESSOPEN preprocessor"),
)
app = app
.arg(
Arg::new("lessopen")
.long("lessopen")
.action(ArgAction::SetTrue)
.help("Enable the $LESSOPEN preprocessor"),
)
.arg(
Arg::new("no-lessopen")
.long("no-lessopen")
.action(ArgAction::SetTrue)
.overrides_with("lessopen")
.hide(true)
.help("Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)"),
)
}

app = app
Expand Down
15 changes: 13 additions & 2 deletions src/lessopen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use os_str_bytes::RawOsString;
use run_script::{IoOptions, ScriptOptions};

use crate::error::Result;
use crate::input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind};
use crate::{
bat_warning,
input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind},
};

/// Preprocess files and/or stdin using $LESSOPEN and $LESSCLOSE
pub(crate) struct LessOpenPreprocessor {
Expand All @@ -32,10 +35,18 @@ enum LessOpenKind {

impl LessOpenPreprocessor {
/// Create a new instance of LessOpenPreprocessor
/// Will return Ok if and only if $LESSOPEN is set
/// Will return Ok if and only if $LESSOPEN is set and contains exactly one %s
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean with "exactly one %s"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say you want to use batpipe as to preprocess less or bat's input.

batpipe %s is a valid command for $LESSOPEN.

The following are not valid and will result in less/bat ignoring it and printing a warning:

  • batpipe
  • batpipe %s %s
  • batpipe %s %s (...) %s

pub(crate) fn new() -> Result<LessOpenPreprocessor> {
let lessopen = env::var("LESSOPEN")?;

// Ignore $LESSOPEN if it does not contains exactly one %s
// Note that $LESSCLOSE has no such requirement
if lessopen.match_indices("%s").count() != 1 {
let error_msg = "LESSOPEN ignored: must contain exactly one %s";
bat_warning!("{}", error_msg);
return Err(error_msg.into());
}

// "||" means pipe directly to bat without making a temporary file
// Also, if preprocessor output is empty and exit code is zero, use the empty output
// Otherwise, if output is empty and exit code is nonzero, use original file contents
Expand Down
4 changes: 4 additions & 0 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ impl OutputType {
p.args(args);
}
p.env("LESSCHARSET", "UTF-8");

#[cfg(feature = "lessopen")]
// Ensures that 'less' does not preprocess input again if '$LESSOPEN' is set.
p.arg("--no-lessopen");
} else {
p.args(args);
};
Expand Down