1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-09-21 20:52:26 +01:00

Merge pull request #3402 from academician/minus-integration

Add --pager=builtin using the Minus library
This commit is contained in:
Keith Hall
2025-09-20 08:43:47 +03:00
committed by GitHub
15 changed files with 273 additions and 31 deletions

View File

@@ -6,6 +6,7 @@
- Add paging to `--list-themes`, see PR #3239 (@einfachIrgendwer0815) - Add paging to `--list-themes`, see PR #3239 (@einfachIrgendwer0815)
- Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow) - Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow)
- Support context in line ranges, e.g. `bat -r 30::5` / `bat -r 30:40:5`, see #3345 (@cavanaug) - Support context in line ranges, e.g. `bat -r 30::5` / `bat -r 30:40:5`, see #3345 (@cavanaug)
- Add built-in 'minus' pager, e.g. `bat --pager=builtin` see PR #3402 (@academician)
## Bugfixes ## Bugfixes

172
Cargo.lock generated
View File

@@ -135,6 +135,7 @@ dependencies = [
"indexmap", "indexmap",
"itertools 0.13.0", "itertools 0.13.0",
"itertools 0.14.0", "itertools 0.14.0",
"minus",
"nix", "nix",
"nu-ansi-term", "nu-ansi-term",
"once_cell", "once_cell",
@@ -339,6 +340,15 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.8.6" version = "0.8.6"
@@ -364,6 +374,31 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags 2.6.0",
"crossterm_winapi",
"libc",
"mio 0.8.11",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.20.10" version = "0.20.10"
@@ -983,6 +1018,33 @@ dependencies = [
"adler2", "adler2",
] ]
[[package]]
name = "minus"
version = "5.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "093bd0520d2a37943566a73750e6d44094dac75d66a978d1f0d97ffc78686832"
dependencies = [
"crossbeam-channel",
"crossterm",
"once_cell",
"parking_lot",
"regex",
"textwrap",
"thiserror 1.0.69",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.0.3" version = "1.0.3"
@@ -1050,6 +1112,9 @@ name = "once_cell"
version = "1.20.2" version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
dependencies = [
"parking_lot_core",
]
[[package]] [[package]]
name = "onig" name = "onig"
@@ -1428,6 +1493,36 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
dependencies = [
"libc",
"mio 0.8.11",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"
@@ -1543,7 +1638,7 @@ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"memchr", "memchr",
"mio", "mio 1.0.3",
"terminal-trx", "terminal-trx",
"windows-sys 0.59.0", "windows-sys 0.59.0",
"xterm-color", "xterm-color",
@@ -1576,6 +1671,15 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"unicode-width",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.69" version = "1.0.69"
@@ -1932,6 +2036,15 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
@@ -1959,6 +2072,21 @@ dependencies = [
"windows-targets 0.53.2", "windows-targets 0.53.2",
] ]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"
@@ -1991,6 +2119,12 @@ dependencies = [
"windows_x86_64_msvc 0.53.0", "windows_x86_64_msvc 0.53.0",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.6" version = "0.52.6"
@@ -2003,6 +2137,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.6" version = "0.52.6"
@@ -2015,6 +2155,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.6" version = "0.52.6"
@@ -2039,6 +2185,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.6" version = "0.52.6"
@@ -2051,6 +2203,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.6" version = "0.52.6"
@@ -2063,6 +2221,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.6" version = "0.52.6"
@@ -2075,6 +2239,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.6"

View File

@@ -33,7 +33,7 @@ minimal-application = [
"wild", "wild",
] ]
git = ["git2"] # Support indicating git modifications git = ["git2"] # Support indicating git modifications
paging = ["shell-words", "grep-cli"] # Support applying a pager on the output paging = [ "shell-words", "grep-cli", "minus"] # Support applying a pager on the output
lessopen = ["execute"] # Support $LESSOPEN preprocessor lessopen = ["execute"] # Support $LESSOPEN preprocessor
build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"] build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
@@ -52,6 +52,10 @@ thiserror = "2.0"
wild = { version = "2.2", optional = true } wild = { version = "2.2", optional = true }
content_inspector = "0.2.4" content_inspector = "0.2.4"
shell-words = { version = "1.1.0", optional = true } shell-words = { version = "1.1.0", optional = true }
minus = { version = "5.6", optional = true, features = [
"dynamic_output",
"search",
] }
unicode-width = "0.2.1" unicode-width = "0.2.1"
globset = "0.4" globset = "0.4"
serde = "1.0" serde = "1.0"

View File

@@ -635,9 +635,11 @@ syntax, use (this mapping is already built in):
### Using a different pager ### Using a different pager
`bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not `bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not
set, `less` is used by default. If you want to use a different pager, you can either modify the set, `less` is used by default. You can also use bat's built-in pager with `--pager=builtin` or
`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in by setting the `BAT_PAGER` environment variable to "builtin".
`PAGER`.
If you want to use a different pager, you can either modify the `PAGER` variable or set the
`BAT_PAGER` environment variable to override what is specified in `PAGER`.
>[!NOTE] >[!NOTE]
> If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors. > If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors.

View File

@@ -106,6 +106,7 @@ set -l pager_opts '
less\ -FR\t less\ -FR\t
more\t more\t
vimpager\t vimpager\t
builtin\t
' '
set -l italic_text_opts ' set -l italic_text_opts '

View File

@@ -149,8 +149,9 @@ which pager is used, see the '\-\-pager' option. Possible values: *auto*, never,
\fB\-\-pager\fR <command> \fB\-\-pager\fR <command>
.IP .IP
Determine which pager is used. This option will override the PAGER and BAT_PAGER Determine which pager is used. This option will override the PAGER and BAT_PAGER
environment variables. The default pager is 'less'. To control when the pager is used, see environment variables. The default pager is 'less'. If you provide '\-\-pager=builtin', use
the '\-\-paging' option. Example: '\-\-pager "less \fB\-RF\fR"'. the built-in 'minus' pager. To control when the pager is used, see the '\-\-paging' option.
Example: '\-\-pager "less \fB\-RF\fR"'.
Note: By default, if the pager is set to 'less' (and no command-line options are specified), 'bat' will pass the following command line options to the pager: '-R'/'--RAW-CONTROL-CHARS', '-F'/'--quit-if-one-screen' and '-X'/'--no-init'. The last option ('-X') is only used for 'less' versions older than 530. The '-R' option is needed to interpret ANSI colors correctly. The second option ('-F') instructs less to exit immediately if the output size is smaller than the vertical size of the terminal. This is convenient for small files because you do not have to press 'q' to quit the pager. The third option ('-X') is needed to fix a bug with the '--quit-if-one-screen' feature in old versions of 'less'. Unfortunately, it also breaks mouse-wheel support in 'less'. If you want to enable mouse-wheel scrolling on older versions of 'less', you can pass just '-R' (as in the example above, this will disable the quit-if-one-screen feature). For less 530 or newer, it should work out of the box. Note: By default, if the pager is set to 'less' (and no command-line options are specified), 'bat' will pass the following command line options to the pager: '-R'/'--RAW-CONTROL-CHARS', '-F'/'--quit-if-one-screen' and '-X'/'--no-init'. The last option ('-X') is only used for 'less' versions older than 530. The '-R' option is needed to interpret ANSI colors correctly. The second option ('-F') instructs less to exit immediately if the output size is smaller than the vertical size of the terminal. This is convenient for small files because you do not have to press 'q' to quit the pager. The third option ('-X') is needed to fix a bug with the '--quit-if-one-screen' feature in old versions of 'less'. Unfortunately, it also breaks mouse-wheel support in 'less'. If you want to enable mouse-wheel scrolling on older versions of 'less', you can pass just '-R' (as in the example above, this will disable the quit-if-one-screen feature). For less 530 or newer, it should work out of the box.
.HP .HP

View File

@@ -95,14 +95,15 @@ Options:
piped to another program, but you want to keep the colorization/decorations. piped to another program, but you want to keep the colorization/decorations.
--paging <when> --paging <when>
Specify when to use the pager. To disable the pager, use --paging=never' or its Specify when to use the pager. To disable the pager, use '--paging=never' or its
alias,'-P'. To disable the pager permanently, set BAT_PAGING to 'never'. To control which alias,'-P'. To disable the pager permanently, set BAT_PAGING to 'never'. To control which
pager is used, see the '--pager' option. Possible values: *auto*, never, always. pager is used, see the '--pager' option. Possible values: *auto*, never, always.
--pager <command> --pager <command>
Determine which pager is used. This option will override the PAGER and BAT_PAGER Determine which pager is used. This option will override the PAGER and BAT_PAGER
environment variables. The default pager is 'less'. To control when the pager is used, see environment variables. The default pager is 'less'. If you provide '--pager=builtin', use
the '--paging' option. Example: '--pager "less -RF"'. the built-in 'minus' pager. To control when the pager is used, see the '--paging' option.
Example: '--pager "less -RF"'.
-m, --map-syntax <glob:syntax> -m, --map-syntax <glob:syntax>
Map a glob pattern to an existing syntax name. The glob pattern is matched on the full Map a glob pattern to an existing syntax name. The glob pattern is matched on the full

View File

@@ -14,7 +14,7 @@ fn main() {
controller controller
.run( .run(
vec![input.into()], vec![input.into()],
Some(OutputHandle::FmtWrite(&mut buffer)), Some(&mut OutputHandle::FmtWrite(&mut buffer)),
) )
.unwrap(); .unwrap();

View File

@@ -328,7 +328,7 @@ pub fn build_app(interactive_output: bool) -> Command {
.help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).") .help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).")
.long_help( .long_help(
"Specify when to use the pager. To disable the pager, use \ "Specify when to use the pager. To disable the pager, use \
--paging=never' or its alias,'-P'. To disable the pager permanently, \ '--paging=never' or its alias,'-P'. To disable the pager permanently, \
set BAT_PAGING to 'never'. To control which pager is used, see the \ set BAT_PAGING to 'never'. To control which pager is used, see the \
'--pager' option. Possible values: *auto*, never, always." '--pager' option. Possible values: *auto*, never, always."
), ),
@@ -354,6 +354,7 @@ pub fn build_app(interactive_output: bool) -> Command {
.long_help( .long_help(
"Determine which pager is used. This option will override the \ "Determine which pager is used. This option will override the \
PAGER and BAT_PAGER environment variables. The default pager is 'less'. \ PAGER and BAT_PAGER environment variables. The default pager is 'less'. \
If you provide '--pager=builtin', use the built-in 'minus' pager. \
To control when the pager is used, see the '--paging' option. \ To control when the pager is used, see the '--paging' option. \
Example: '--pager \"less -RF\"'." Example: '--pager \"less -RF\"'."
), ),

View File

@@ -16,7 +16,7 @@ use std::io::{BufReader, Write};
use std::path::Path; use std::path::Path;
use std::process; use std::process;
use bat::output::{OutputHandle, OutputType}; use bat::output::OutputType;
use bat::theme::DetectColorScheme; use bat::theme::DetectColorScheme;
use nu_ansi_term::Color::Green; use nu_ansi_term::Color::Green;
use nu_ansi_term::Style; use nu_ansi_term::Style;
@@ -229,10 +229,7 @@ pub fn list_themes(
)?; )?;
config.theme = theme.to_string(); config.theme = theme.to_string();
Controller::new(&config, &assets) Controller::new(&config, &assets)
.run( .run(vec![theme_preview_file()], Some(&mut writer))
vec![theme_preview_file()],
Some(OutputHandle::IoWrite(&mut writer)),
)
.ok(); .ok();
writeln!(writer)?; writeln!(writer)?;
} else if config.loop_through { } else if config.loop_through {

View File

@@ -36,14 +36,18 @@ impl Controller<'_> {
} }
} }
pub fn run(&self, inputs: Vec<Input>, output_handle: Option<OutputHandle<'_>>) -> Result<bool> { pub fn run(
&self,
inputs: Vec<Input>,
output_handle: Option<&mut OutputHandle<'_>>,
) -> Result<bool> {
self.run_with_error_handler(inputs, output_handle, default_error_handler) self.run_with_error_handler(inputs, output_handle, default_error_handler)
} }
pub fn run_with_error_handler( pub fn run_with_error_handler(
&self, &self,
inputs: Vec<Input>, inputs: Vec<Input>,
output_handle: Option<OutputHandle<'_>>, output_handle: Option<&mut OutputHandle<'_>>,
mut handle_error: impl FnMut(&Error, &mut dyn Write), mut handle_error: impl FnMut(&Error, &mut dyn Write),
) -> Result<bool> { ) -> Result<bool> {
let mut output_type; let mut output_type;
@@ -88,7 +92,7 @@ impl Controller<'_> {
let mut writer = match output_handle { let mut writer = match output_handle {
Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w), Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w),
Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w), Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w),
None => OutputHandle::IoWrite(output_type.handle()?), None => output_type.handle()?,
}; };
let mut no_errors: bool = true; let mut no_errors: bool = true;
let stderr = io::stderr(); let stderr = io::stderr();

View File

@@ -28,6 +28,9 @@ pub enum Error {
InvalidPagerValueBat, InvalidPagerValueBat,
#[error("{0}")] #[error("{0}")]
Msg(String), Msg(String),
#[cfg(feature = "paging")]
#[error(transparent)]
MinusError(#[from] ::minus::MinusError),
#[cfg(feature = "lessopen")] #[cfg(feature = "lessopen")]
#[error(transparent)] #[error(transparent)]
VarError(#[from] ::std::env::VarError), VarError(#[from] ::std::env::VarError),

View File

@@ -1,7 +1,9 @@
use std::fmt; use std::fmt;
use std::io::{self, Write}; use std::io;
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
use std::process::Child; use std::process::Child;
#[cfg(feature = "paging")]
use std::thread::{spawn, JoinHandle};
use crate::error::*; use crate::error::*;
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
@@ -11,6 +13,36 @@ use crate::paging::PagingMode;
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
use crate::wrapping::WrappingMode; use crate::wrapping::WrappingMode;
#[cfg(feature = "paging")]
pub struct BuiltinPager {
pager: minus::Pager,
handle: Option<JoinHandle<Result<()>>>,
}
#[cfg(feature = "paging")]
impl BuiltinPager {
fn new() -> Self {
let pager = minus::Pager::new();
let handle = {
let pager = pager.clone();
Some(spawn(move || {
minus::dynamic_paging(pager).map_err(Error::from)
}))
};
Self { pager, handle }
}
}
#[cfg(feature = "paging")]
impl std::fmt::Debug for BuiltinPager {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BuiltinPager")
//.field("pager", &self.pager) /// minus::Pager doesn't implement fmt::Debug
.field("handle", &self.handle)
.finish()
}
}
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum SingleScreenAction { enum SingleScreenAction {
@@ -22,6 +54,8 @@ enum SingleScreenAction {
pub enum OutputType { pub enum OutputType {
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
Pager(Child), Pager(Child),
#[cfg(feature = "paging")]
BuiltinPager(BuiltinPager),
Stdout(io::Stdout), Stdout(io::Stdout),
} }
@@ -64,6 +98,10 @@ impl OutputType {
return Err(Error::InvalidPagerValueBat); return Err(Error::InvalidPagerValueBat);
} }
if pager.kind == PagerKind::Builtin {
return Ok(OutputType::BuiltinPager(BuiltinPager::new()));
}
let resolved_path = match grep_cli::resolve_binary(&pager.bin) { let resolved_path = match grep_cli::resolve_binary(&pager.bin) {
Ok(path) => path, Ok(path) => path,
Err(_) => { Err(_) => {
@@ -138,7 +176,7 @@ impl OutputType {
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
pub(crate) fn is_pager(&self) -> bool { pub(crate) fn is_pager(&self) -> bool {
matches!(self, OutputType::Pager(_)) matches!(self, OutputType::Pager(_) | OutputType::BuiltinPager(_))
} }
#[cfg(not(feature = "paging"))] #[cfg(not(feature = "paging"))]
@@ -146,14 +184,18 @@ impl OutputType {
false false
} }
pub fn handle(&mut self) -> Result<&mut dyn Write> { pub fn handle<'a>(&'a mut self) -> Result<OutputHandle<'a>> {
Ok(match *self { Ok(match *self {
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
OutputType::Pager(ref mut command) => command OutputType::Pager(ref mut command) => OutputHandle::IoWrite(
.stdin command
.as_mut() .stdin
.ok_or("Could not open stdin for pager")?, .as_mut()
OutputType::Stdout(ref mut handle) => handle, .ok_or("Could not open stdin for pager")?,
),
#[cfg(feature = "paging")]
OutputType::BuiltinPager(ref mut pager) => OutputHandle::FmtWrite(&mut pager.pager),
OutputType::Stdout(ref mut handle) => OutputHandle::IoWrite(handle),
}) })
} }
} }
@@ -161,8 +203,16 @@ impl OutputType {
#[cfg(feature = "paging")] #[cfg(feature = "paging")]
impl Drop for OutputType { impl Drop for OutputType {
fn drop(&mut self) { fn drop(&mut self) {
if let OutputType::Pager(ref mut command) = *self { match *self {
let _ = command.wait(); OutputType::Pager(ref mut command) => {
let _ = command.wait();
}
OutputType::BuiltinPager(ref mut pager) => {
if pager.handle.is_some() {
let _ = pager.handle.take().unwrap().join().unwrap();
}
}
OutputType::Stdout(_) => (),
} }
} }
} }

View File

@@ -32,6 +32,9 @@ pub(crate) enum PagerKind {
/// most /// most
Most, Most,
/// builtin
Builtin,
/// A pager we don't know about /// A pager we don't know about
Unknown, Unknown,
} }
@@ -40,6 +43,10 @@ impl PagerKind {
fn from_bin(bin: &str) -> PagerKind { fn from_bin(bin: &str) -> PagerKind {
use std::path::Path; use std::path::Path;
if bin == "builtin" {
return PagerKind::Builtin;
}
// Set to `less` by default on most Linux distros. // Set to `less` by default on most Linux distros.
let pager_bin = Path::new(bin).file_stem(); let pager_bin = Path::new(bin).file_stem();

View File

@@ -328,7 +328,7 @@ impl<'a> PrettyPrinter<'a> {
if let Some(mut w) = writer { if let Some(mut w) = writer {
controller.run( controller.run(
inputs.into_iter().map(|i| i.into()).collect(), inputs.into_iter().map(|i| i.into()).collect(),
Some(OutputHandle::FmtWrite(&mut w)), Some(&mut OutputHandle::FmtWrite(&mut w)),
) )
} else { } else {
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None) controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)