Skip to content

Commit e32ad0b

Browse files
Add $LESSOPEN and $LESSCLOSE support (#2444)
1 parent 3abc0c0 commit e32ad0b

File tree

16 files changed

+748
-4
lines changed

16 files changed

+748
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777

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

8182
## Bugfixes
8283

Cargo.lock

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

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ application = [
2121
"build-assets",
2222
"git",
2323
"minimal-application",
24+
"lessopen",
2425
]
2526
# Mainly for developers that want to iterate quickly
2627
# Be aware that the included features might change in the future
@@ -33,6 +34,7 @@ minimal-application = [
3334
]
3435
git = ["git2"] # Support indicating git modifications
3536
paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
37+
lessopen = ["run_script", "os_str_bytes"] # Support $LESSOPEN preprocessor
3638
build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
3739

3840
# You need to use one of these if you depend on bat as a library:
@@ -64,6 +66,8 @@ regex = { version = "1.8.3", optional = true }
6466
walkdir = { version = "2.3", optional = true }
6567
bytesize = { version = "1.2.0" }
6668
encoding_rs = "0.8.32"
69+
os_str_bytes = { version = "~6.4", optional = true }
70+
run_script = { version = "^0.10.0", optional = true}
6771

6872
[dependencies.git2]
6973
version = "0.18"

assets/completions/_bat.ps1.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
5959
[CompletionResult]::new('--unbuffered', 'unbuffered', [CompletionResultType]::ParameterName, 'unbuffered')
6060
[CompletionResult]::new('--no-config', 'no-config', [CompletionResultType]::ParameterName, 'Do not use the configuration file')
6161
[CompletionResult]::new('--no-custom-assets', 'no-custom-assets', [CompletionResultType]::ParameterName, 'Do not load custom assets')
62+
[CompletionResult]::new('--no-lessopen', 'no-lessopen', [CompletionResultType]::ParameterName, 'Do not use the $LESSOPEN preprocessor')
6263
[CompletionResult]::new('--config-file', 'config-file', [CompletionResultType]::ParameterName, 'Show path to the configuration file.')
6364
[CompletionResult]::new('--generate-config-file', 'generate-config-file', [CompletionResultType]::ParameterName, 'Generates a default configuration file.')
6465
[CompletionResult]::new('--config-dir', 'config-dir', [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.')

assets/completions/bat.zsh.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ _{{PROJECT_EXECUTABLE}}_main() {
4646
'(: --list-themes --list-languages -L)'{-L,--list-languages}'[Display all supported languages]'
4747
'(: --no-config)'--no-config'[Do not use the configuration file]'
4848
'(: --no-custom-assets)'--no-custom-assets'[Do not load custom assets]'
49+
'(: --no-lessopen)'--no-lessopen'[Do not use the $LESSOPEN preprocessor]'
4950
'(: --config-dir)'--config-dir'[Show bat'"'"'s configuration directory]'
5051
'(: --config-file)'--config-file'[Show path to the configuration file]'
5152
'(: --generate-config-file)'--generate-config-file'[Generates a default configuration file]'

assets/manual/bat.1.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@ If you ever want to remove the custom languages, you can clear the cache with `\
243243
Similarly to custom languages, {{PROJECT_EXECUTABLE}} supports Sublime Text \fB.tmTheme\fR themes.
244244
These can be installed to `\fB$({{PROJECT_EXECUTABLE}} --config-dir)/themes\fR`, and are added to the cache with
245245
`\fB{{PROJECT_EXECUTABLE}} cache --build`.
246+
247+
.SH "INPUT PREPROCESSOR"
248+
Much like less(1) does, {{PROJECT_EXECUTABLE}} supports input preprocessors via the LESSOPEN and LESSCLOSE environment variables.
249+
In addition, {{PROJECT_EXECUTABLE}} attempts to be as compatible with less's preprocessor implementation as possible.
250+
251+
To run {{PROJECT_EXECUTABLE}} without using the preprocessor, call:
252+
253+
\fB{{PROJECT_EXECUTABLE}} --no-lessopen\fR
254+
255+
For more information, see the "INPUT PREPROCESSOR" section of less(1).
256+
246257
.SH "MORE INFORMATION"
247258

248259
For more information and up-to-date documentation, visit the {{PROJECT_EXECUTABLE}} repo:

src/bin/bat/app.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ impl App {
281281
.map(HighlightedLineRanges)
282282
.unwrap_or_default(),
283283
use_custom_assets: !self.matches.get_flag("no-custom-assets"),
284+
#[cfg(feature = "lessopen")]
285+
use_lessopen: !self.matches.get_flag("no-lessopen"),
284286
})
285287
}
286288

src/bin/bat/clap_app.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,20 @@ pub fn build_app(interactive_output: bool) -> Command {
497497
.action(ArgAction::SetTrue)
498498
.hide(true)
499499
.help("Do not load custom assets"),
500+
);
501+
502+
#[cfg(feature = "lessopen")]
503+
{
504+
app = app.arg(
505+
Arg::new("no-lessopen")
506+
.long("no-lessopen")
507+
.action(ArgAction::SetTrue)
508+
.hide(true)
509+
.help("Do not use the $LESSOPEN preprocessor"),
500510
)
511+
}
512+
513+
app = app
501514
.arg(
502515
Arg::new("config-file")
503516
.long("config-file")
@@ -536,7 +549,7 @@ pub fn build_app(interactive_output: bool) -> Command {
536549
.alias("diagnostics")
537550
.action(ArgAction::SetTrue)
538551
.hide_short_help(true)
539-
.help("Show diagnostic information for bug reports.")
552+
.help("Show diagnostic information for bug reports."),
540553
)
541554
.arg(
542555
Arg::new("acknowledgements")

src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ pub struct Config<'a> {
9090
/// Whether or not to allow custom assets. If this is false or if custom assets (a.k.a.
9191
/// cached assets) are not available, assets from the binary will be used instead.
9292
pub use_custom_assets: bool,
93+
94+
// Whether or not to use $LESSOPEN if set
95+
#[cfg(feature = "lessopen")]
96+
pub use_lessopen: bool,
9397
}
9498

9599
#[cfg(all(feature = "minimal-application", feature = "paging"))]

src/controller.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::config::{Config, VisibleLines};
66
use crate::diff::{get_git_diff, LineChanges};
77
use crate::error::*;
88
use crate::input::{Input, InputReader, OpenedInput};
9+
#[cfg(feature = "lessopen")]
10+
use crate::lessopen::LessOpenPreprocessor;
911
#[cfg(feature = "git")]
1012
use crate::line_range::LineRange;
1113
use crate::line_range::{LineRanges, RangeCheckResult};
@@ -19,11 +21,18 @@ use clircle::{Clircle, Identifier};
1921
pub struct Controller<'a> {
2022
config: &'a Config<'a>,
2123
assets: &'a HighlightingAssets,
24+
#[cfg(feature = "lessopen")]
25+
preprocessor: Option<LessOpenPreprocessor>,
2226
}
2327

2428
impl<'b> Controller<'b> {
2529
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
26-
Controller { config, assets }
30+
Controller {
31+
config,
32+
assets,
33+
#[cfg(feature = "lessopen")]
34+
preprocessor: LessOpenPreprocessor::new().ok(),
35+
}
2736
}
2837

2938
pub fn run(
@@ -123,7 +132,18 @@ impl<'b> Controller<'b> {
123132
stdout_identifier: Option<&Identifier>,
124133
is_first: bool,
125134
) -> Result<()> {
126-
let mut opened_input = input.open(stdin, stdout_identifier)?;
135+
let mut opened_input = {
136+
#[cfg(feature = "lessopen")]
137+
match self.preprocessor {
138+
Some(ref preprocessor) if self.config.use_lessopen => {
139+
preprocessor.open(input, stdin, stdout_identifier)?
140+
}
141+
_ => input.open(stdin, stdout_identifier)?,
142+
}
143+
144+
#[cfg(not(feature = "lessopen"))]
145+
input.open(stdin, stdout_identifier)?
146+
};
127147
#[cfg(feature = "git")]
128148
let line_changes = if self.config.visible_lines.diff_mode()
129149
|| (!self.config.loop_through && self.config.style_components.changes())

0 commit comments

Comments
 (0)