summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Peter <sharkdp@users.noreply.github.com>2024-02-23 21:48:44 +0100
committerGitHub <noreply@github.com>2024-02-23 21:48:44 +0100
commitb718889ba2a0fb734ad5ec55beab94849e6951f0 (patch)
treeba183170791d48195f9113d3db88e40eb626a6db
parent695cf1f387a970e2706c908d9597bfad85eb97ee (diff)
parent708c74f6af45ba8a56bab68d34e5aa12e1f44b25 (diff)
Merge branch 'master' into master
-rw-r--r--CHANGELOG.md10
-rw-r--r--Cargo.lock66
-rw-r--r--Cargo.toml17
-rw-r--r--README.md44
m---------assets/syntaxes/02_Extra/cmd-help0
m---------assets/themes/zenburn0
-rw-r--r--build/syntax_mapping.rs2
-rw-r--r--doc/long-help.txt3
-rw-r--r--src/assets/assets_metadata.rs2
-rw-r--r--src/assets/lazy_theme_set.rs3
-rw-r--r--src/bin/bat/app.rs1
-rw-r--r--src/bin/bat/clap_app.rs7
-rw-r--r--src/bin/bat/main.rs24
-rw-r--r--src/config.rs3
-rw-r--r--src/decorations.rs2
-rw-r--r--src/printer.rs67
-rw-r--r--src/syntax_mapping/builtins/common/50-aws-credentials.toml2
-rw-r--r--src/syntax_mapping/builtins/common/50-json.toml (renamed from src/syntax_mapping/builtins/common/50-jsonl.toml)2
-rw-r--r--src/vscreen.rs779
-rw-r--r--tests/examples/regression_tests/issue_2541.txt1
-rw-r--r--tests/integration_tests.rs82
-rw-r--r--tests/tester/mod.rs2
22 files changed, 1000 insertions, 119 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06db2cbb..a17726fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,15 @@
## Features
+- Set terminal title to file names when Paging is not Paging::Never #2807 (@Oliver-Looney)
+
## Bugfixes
- Fix long file name wrapping in header, see #2835 (@FilipRazek)
- Fix `NO_COLOR` support, see #2767 (@acuteenvy)
+- Fix handling of inputs with OSC ANSI escape sequences, see #2541 and #2544 (@eth-p)
+- Fix handling of inputs with combined ANSI color and attribute sequences, see #2185 and #2856 (@eth-p)
+- Fix panel width when line 10000 wraps, see #2854 (@eth-p)
## Other
@@ -20,12 +25,16 @@
- Use proper Architecture for Debian packages built for musl, see #2811 (@Enselic)
- Pull in fix for unsafe-libyaml security advisory, see #2812 (@dtolnay)
- Update git-version dependency to use Syn v2, see #2816 (@dtolnay)
+- Update git2 dependency to v0.18.2, see #2852 (@eth-p)
+- Apply clippy fixes #2864 (@cyqsimon)
## Syntaxes
- `cmd-help`: scope subcommands followed by other terms, and other misc improvements, see #2819 (@victor-gp)
- Upgrade JQ syntax, see #2820 (@dependabot[bot])
- Associate `xsh` files with `xonsh` syntax that is Python, see #2840 (@anki-code).
+- Added auto detect syntax for `.jsonc` #2795 (@mxaddict)
+- Added auto detect syntax for `.aws/{config,credentials}` #2795 (@mxaddict)
## Themes
@@ -36,6 +45,7 @@
- [BREAKING] `SyntaxMapping::{empty,builtin}` are removed; use `SyntaxMapping::new` instead
- [BREAKING] `SyntaxMapping::mappings` is replaced by `SyntaxMapping::{builtin,custom,all}_mappings`
- Make `Controller::run_with_error_handler`'s error handler `FnMut`, see #2831 (@rhysd)
+- Improve compile time by 20%, see #2815 (@dtolnay)
# v0.24.0
diff --git a/Cargo.lock b/Cargo.lock
index 4aaf7b32..ff674b9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -129,7 +129,7 @@ dependencies = [
"globset",
"grep-cli",
"home",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
"itertools",
"nix",
"nu-ansi-term",
@@ -142,6 +142,7 @@ dependencies = [
"run_script",
"semver",
"serde",
+ "serde_derive",
"serde_with",
"serde_yaml",
"serial_test",
@@ -272,13 +273,14 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "clircle"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e87cbed5354f17bd8ca8821a097fb62599787fe8f611743fad7ee156a0a600"
+checksum = "ec0b92245ea62a7a751db4b0e4a583f8978e508077ef6de24fcc0d0dc5311a8d"
dependencies = [
"cfg-if",
"libc",
"serde",
+ "serde_derive",
"winapi",
]
@@ -580,7 +582,7 @@ dependencies = [
"bstr",
"log",
"regex-automata",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
@@ -646,9 +648,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.1.0"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
dependencies = [
"equivalent",
"hashbrown 0.14.1",
@@ -693,9 +695,9 @@ checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "libgit2-sys"
-version = "0.16.1+1.7.1"
+version = "0.16.2+1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c"
+checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8"
dependencies = [
"cc",
"libc",
@@ -1027,7 +1029,7 @@ dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
@@ -1038,17 +1040,11 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
- "regex-syntax 0.8.2",
+ "regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
-
-[[package]]
-name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
@@ -1113,9 +1109,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
-version = "1.0.20"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
@@ -1150,28 +1146,29 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.4"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
dependencies = [
"serde",
]
[[package]]
name = "serde_with"
-version = "3.4.0"
+version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
+checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270"
dependencies = [
"serde",
+ "serde_derive",
"serde_with_macros",
]
[[package]]
name = "serde_with_macros"
-version = "3.4.0"
+version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
+checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d"
dependencies = [
"darling",
"proc-macro2",
@@ -1185,7 +1182,7 @@ version = "0.9.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
"itoa",
"ryu",
"serde",
@@ -1258,9 +1255,9 @@ dependencies = [
[[package]]
name = "syntect"
-version = "5.1.0"
+version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"
+checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
dependencies = [
"bincode",
"bitflags 1.3.2",
@@ -1270,8 +1267,9 @@ dependencies = [
"once_cell",
"onig",
"plist",
- "regex-syntax 0.7.5",
+ "regex-syntax",
"serde",
+ "serde_derive",
"serde_json",
"thiserror",
"walkdir",
@@ -1374,11 +1372,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "toml"
-version = "0.8.6"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc"
+checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
"serde",
"serde_spanned",
"toml_datetime",
@@ -1396,11 +1394,11 @@ dependencies = [
[[package]]
name = "toml_edit"
-version = "0.20.7"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
+checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
"serde",
"serde_spanned",
"toml_datetime",
diff --git a/Cargo.toml b/Cargo.toml
index 3b7f10e6..05a2acb7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -53,11 +53,12 @@ content_inspector = "0.2.4"
shell-words = { version = "1.1.0", optional = true }
unicode-width = "0.1.11"
globset = "0.4"
-serde = { version = "1.0", features = ["derive"] }
+serde = "1.0"
+serde_derive = "1.0"
serde_yaml = "0.9.28"
semver = "1.0"
path_abs = { version = "0.5", default-features = false }
-clircle = "0.4"
+clircle = "0.5"
bugreport = { version = "0.5.0", optional = true }
etcetera = { version = "0.8.0", optional = true }
grep-cli = { version = "0.1.10", optional = true }
@@ -74,7 +75,7 @@ optional = true
default-features = false
[dependencies.syntect]
-version = "5.1.0"
+version = "5.2.0"
default-features = false
features = ["parsing"]
@@ -94,19 +95,21 @@ serial_test = { version = "2.0.0", default-features = false }
predicates = "3.0.4"
wait-timeout = "0.2.0"
tempfile = "3.8.1"
+serde = { version = "1.0", features = ["derive"] }
[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.26.4", default-features = false, features = ["term"] }
[build-dependencies]
anyhow = "1.0.78"
-indexmap = { version = "2.1.0", features = ["serde"] }
+indexmap = { version = "2.2.2", features = ["serde"] }
itertools = "0.11.0"
once_cell = "1.18"
regex = "1.10.2"
-serde = { version = "1.0", features = ["derive"] }
-serde_with = { version = "3.4.0", default-features = false, features = ["macros"] }
-toml = { version = "0.8.6", features = ["preserve_order"] }
+serde = "1.0"
+serde_derive = "1.0"
+serde_with = { version = "3.6.1", default-features = false, features = ["macros"] }
+toml = { version = "0.8.9", features = ["preserve_order"] }
walkdir = "2.4"
[build-dependencies.clap]
diff --git a/README.md b/README.md
index 352ae64d..57baf2b0 100644
--- a/README.md
+++ b/README.md
@@ -602,7 +602,8 @@ set, `less` is used by default. If you want to use a different pager, you can ei
`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in
`PAGER`.
-**Note**: If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors.
+>[!NOTE]
+> If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors.
If you want to pass command-line arguments to the pager, you can also set them via the
`PAGER`/`BAT_PAGER` variables:
@@ -613,20 +614,37 @@ export BAT_PAGER="less -RF"
Instead of using environment variables, you can also use `bat`s [configuration file](https://github.com/sharkdp/bat#configuration-file) to configure the pager (`--pager` option).
-**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`.
+### Using `less` as a pager
-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.
+When using `less` as a pager, `bat` will automatically pass extra options along to `less`
+to improve the experience. Specifically, `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen`,
+and under certain conditions, `-X`/`--no-init` and/or `-S`/`--chop-long-lines`.
+
+>[!IMPORTANT]
+> These options will not be added if:
+> - The pager is not named `less`.
+> - The `--pager` argument contains any command-line arguments (e.g. `--pager="less -R"`).
+> - The `BAT_PAGER` environment variable contains any command-line arguments (e.g. `export BAT_PAGER="less -R"`)
+>
+> The `--quit-if-one-screen` option will not be added when:
+> - The `--paging=always` argument is used.
+> - The `BAT_PAGING` environment is set to `always`.
+
+The `-R` option is needed to interpret ANSI colors correctly.
+
+The `-F` option 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 `-X` option is needed to fix a bug with the `--quit-if-one-screen` feature in versions
+of `less` older than version 530. Unfortunately, it also breaks mouse-wheel support in `less`.
+If you want to enable mouse-wheel scrolling on older versions of `less` and do not mind losing
+the quit-if-one-screen feature, you can set the pager (via `--pager` or `BAT_PAGER`) to `less -R`.
+For `less` 530 or newer, it should work out of the box.
+
+The `-S` option is added when `bat`'s `-S`/`--chop-long-lines` option is used. This tells `less`
+to truncate any lines larger than the terminal width.
### Indentation
diff --git a/assets/syntaxes/02_Extra/cmd-help b/assets/syntaxes/02_Extra/cmd-help
-Subproject b150d84534dd060afdcaf3f58977faeaf5917e5
+Subproject 209559b72f7e8848c988828088231b3a4d8b683
diff --git a/assets/themes/zenburn b/assets/themes/zenburn
-Subproject e627f1cb223c1171ab0a6a48d166c87aeae2a1d
+Subproject 86d4ee7a1f884851a1d21d66249687f527fced3
diff --git a/build/syntax_mapping.rs b/build/syntax_mapping.rs
index c29b9225..959caea8 100644
--- a/build/syntax_mapping.rs
+++ b/build/syntax_mapping.rs
@@ -10,7 +10,7 @@ use indexmap::IndexMap;
use itertools::Itertools;
use once_cell::sync::Lazy;
use regex::Regex;
-use serde::Deserialize;
+use serde_derive::Deserialize;
use serde_with::DeserializeFromStr;
use walkdir::WalkDir;
diff --git a/doc/long-help.txt b/doc/long-help.txt
index 247120fb..3ac4a40f 100644
--- a/doc/long-help.txt
+++ b/doc/long-help.txt
@@ -160,6 +160,9 @@ Options:
--acknowledgements
Show acknowledgements.
+ --set-terminal-title
+ Sets terminal title to filenames when using a pager.
+
-h, --help
Print help (see a summary with '-h')
diff --git a/src/assets/assets_metadata.rs b/src/assets/assets_metadata.rs
index 700c4c3b..cfc7a9e0 100644
--- a/src/assets/assets_metadata.rs
+++ b/src/assets/assets_metadata.rs
@@ -3,7 +3,7 @@ use std::path::Path;
use std::time::SystemTime;
use semver::Version;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
use crate::error::*;
diff --git a/src/assets/lazy_theme_set.rs b/src/assets/lazy_theme_set.rs
index bf749154..fcc3eb46 100644
--- a/src/assets/lazy_theme_set.rs
+++ b/src/assets/lazy_theme_set.rs
@@ -3,8 +3,7 @@ use super::*;
use std::collections::BTreeMap;
use std::convert::TryFrom;
-use serde::Deserialize;
-use serde::Serialize;
+use serde_derive::{Deserialize, Serialize};
use once_cell::unsync::OnceCell;
diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs
index a2c09770..8843d53b 100644
--- a/src/bin/bat/app.rs
+++ b/src/bin/bat/app.rs
@@ -289,6 +289,7 @@ impl App {
use_custom_assets: !self.matches.get_flag("no-custom-assets"),
#[cfg(feature = "lessopen")]
use_lessopen: self.matches.get_flag("lessopen"),
+ set_terminal_title: self.matches.get_flag("set-terminal-title"),
})
}
diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs
index e8222a1d..6ceed784 100644
--- a/src/bin/bat/clap_app.rs
+++ b/src/bin/bat/clap_app.rs
@@ -567,6 +567,13 @@ pub fn build_app(interactive_output: bool) -> Command {
.action(ArgAction::SetTrue)
.hide_short_help(true)
.help("Show acknowledgements."),
+ )
+ .arg(
+ Arg::new("set-terminal-title")
+ .long("set-terminal-title")
+ .action(ArgAction::SetTrue)
+ .hide_short_help(true)
+ .help("Sets terminal title to filenames when using a pager."),
);
// Check if the current directory contains a file name cache. Otherwise,
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index f48abdc1..d877bb9b 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -229,9 +229,33 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
Ok(())
}
+fn set_terminal_title_to(new_terminal_title: String) {
+ let osc_command_for_setting_terminal_title = "\x1b]0;";
+ let osc_end_command = "\x07";
+ print!(
+ "{}{}{}",
+ osc_command_for_setting_terminal_title, new_terminal_title, osc_end_command
+ );
+ io::stdout().flush().unwrap();
+}
+
+fn get_new_terminal_title(inputs: &Vec<Input>) -> String {
+ let mut new_terminal_title = "bat: ".to_string();
+ for (index, input) in inputs.iter().enumerate() {
+ new_terminal_title += input.description().title();
+ if index < inputs.len() - 1 {
+ new_terminal_title += ", ";
+ }
+ }
+ new_terminal_title
+}
+
fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Result<bool> {
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
let controller = Controller::new(config, &assets);
+ if config.paging_mode != PagingMode::Never && config.set_terminal_title {
+ set_terminal_title_to(get_new_terminal_title(&inputs));
+ }
controller.run(inputs, None)
}
diff --git a/src/config.rs b/src/config.rs
index 83acc7df..c5cc2abd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -94,6 +94,9 @@ pub struct Config<'a> {
// Whether or not to use $LESSOPEN if set
#[cfg(feature = "lessopen")]
pub use_lessopen: bool,
+
+ // Weather or not to set terminal title when using a pager
+ pub set_terminal_title: bool,
}
#[cfg(all(feature = "minimal-application", feature = "paging"))]
diff --git a/src/decorations.rs b/src/decorations.rs
index d3ed9b34..85d8103a 100644
--- a/src/decorations.rs
+++ b/src/decorations.rs
@@ -46,7 +46,7 @@ impl Decoration for LineNumberDecoration {
_printer: &InteractivePrinter,
) -> DecorationText {
if continuation {
- if line_number > self.cached_wrap_invalid_at {
+ if line_number >= self.cached_wrap_invalid_at {
let new_width = self.cached_wrap.width + 1;
return DecorationText {
text: self.color.paint(" ".repeat(new_width)).to_string(),
diff --git a/src/printer.rs b/src/printer.rs
index 257cc766..f413fdc3 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -7,8 +7,6 @@ use nu_ansi_term::Style;
use bytesize::ByteSize;
-use console::AnsiCodeIterator;
-
use syntect::easy::HighlightLines;
use syntect::highlighting::Color;
use syntect::highlighting::Theme;
@@ -33,9 +31,23 @@ use crate::line_range::RangeCheckResult;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
-use crate::vscreen::AnsiStyle;
+use crate::vscreen::{AnsiStyle, EscapeSequence, EscapeSequenceIterator};
use crate::wrapping::WrappingMode;
+const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI {
+ raw_sequence: "\x1B[4m",
+ parameters: "4",
+ intermediates: "",
+ final_byte: "m",
+};
+
+const ANSI_UNDERLINE_DISABLE: EscapeSequence = EscapeSequence::CSI {
+ raw_sequence: "\x1B[24m",
+ parameters: "24",
+ intermediates: "",
+ final_byte: "m",
+};
+
pub enum OutputHandle<'a> {
IoWrite(&'a mut dyn io::Write),
FmtWrite(&'a mut dyn fmt::Write),
@@ -554,7 +566,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
if highlight_this_line && self.config.theme == "ansi" {
- self.ansi_style.update("^[4m");
+ self.ansi_style.update(ANSI_UNDERLINE_ENABLE);
}
let background_color = self
@@ -581,23 +593,17 @@ impl<'a> Printer for InteractivePrinter<'a> {
let italics = self.config.use_italic_text;
for &(style, region) in &regions {
- let ansi_iterator = AnsiCodeIterator::new(region);
+ let ansi_iterator = EscapeSequenceIterator::new(region);
for chunk in ansi_iterator {
match chunk {
- // ANSI escape passthrough.
- (ansi, true) => {
- self.ansi_style.update(ansi);
- write!(handle, "{}", ansi)?;
- }
-
// Regular text.
- (text, false) => {
- let text = &*self.preprocess(text, &mut cursor_total);
+ EscapeSequence::Text(text) => {
+ let text = self.preprocess(text, &mut cursor_total);
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
write!(
handle,
- "{}",
+ "{}{}",
as_terminal_escaped(
style,
&format!("{}{}", self.ansi_style, text_trimmed),
@@ -605,9 +611,11 @@ impl<'a> Printer for InteractivePrinter<'a> {
colored_output,
italics,
background_color
- )
+ ),
+ self.ansi_style.to_reset_sequence(),
)?;
+ // Pad the rest of the line.
if text.len() != text_trimmed.len() {
if let Some(background_color) = background_color {
let ansi_style = Style {
@@ -625,6 +633,12 @@ impl<'a> Printer for InteractivePrinter<'a> {
write!(handle, "{}", &text[text_trimmed.len()..])?;
}
}
+
+ // ANSI escape passthrough.
+ _ => {
+ write!(handle, "{}", chunk.raw())?;
+ self.ansi_style.update(chunk);
+ }
}
}
}
@@ -634,17 +648,11 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
} else {
for &(style, region) in &regions {
- let ansi_iterator = AnsiCodeIterator::new(region);
+ let ansi_iterator = EscapeSequenceIterator::new(region);
for chunk in ansi_iterator {
match chunk {
- // ANSI escape passthrough.
- (ansi, true) => {
- self.ansi_style.update(ansi);
- write!(handle, "{}", ansi)?;
- }
-
// Regular text.
- (text, false) => {
+ EscapeSequence::Text(text) => {
let text = self.preprocess(
text.trim_end_matches(|c| c == '\r' || c == '\n'),
&mut cursor_total,
@@ -687,7 +695,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
// It wraps.
write!(
handle,
- "{}\n{}",
+ "{}{}\n{}",
as_terminal_escaped(
style,
&format!("{}{}", self.ansi_style, line_buf),
@@ -696,6 +704,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
self.config.use_italic_text,
background_color
),
+ self.ansi_style.to_reset_sequence(),
panel_wrap.clone().unwrap()
)?;
@@ -724,6 +733,12 @@ impl<'a> Printer for InteractivePrinter<'a> {
)
)?;
}
+
+ // ANSI escape passthrough.
+ _ => {
+ write!(handle, "{}", chunk.raw())?;
+ self.ansi_style.update(chunk);
+ }
}
}
}
@@ -744,8 +759,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
if highlight_this_line && self.config.theme == "ansi" {
- self.ansi_style.update("^[24m");
- write!(handle, "\x1B[24m")?;
+ write!(handle, "{}", ANSI_UNDERLINE_DISABLE.raw())?;
+ self.ansi_style.update(ANSI_UNDERLINE_DISABLE);
}
Ok(())
diff --git a/src/syntax_mapping/builtins/common/50-aws-credentials.toml b/src/syntax_mapping/builtins/common/50-aws-credentials.toml
new file mode 100644
index 00000000..a16e6e8f
--- /dev/null
+++ b/src/syntax_mapping/builtins/common/50-aws-credentials.toml
@@ -0,0 +1,2 @@
+[mappings]
+"INI" = ["**/.aws/credentials", "**/.aws/config"]
diff --git a/src/syntax_mapping/builtins/common/50-jsonl.toml b/src/syntax_mapping/builtins/common/50-json.toml
index 4b70a4d0..e604868a 100644
--- a/src/syntax_mapping/builtins/common/50-jsonl.toml
+++ b/src/syntax_mapping/builtins/common/50-json.toml
@@ -1,3 +1,3 @@
# JSON Lines is a simple variation of JSON #2535
[mappings]
-"JSON" = ["*.jsonl"]
+"JSON" = ["*.jsonl", "*.jsonc"]
diff --git a/src/vscreen.rs b/src/vscreen.rs
index ea5d4da6..f7ba3f91 100644
--- a/src/vscreen.rs
+++ b/src/vscreen.rs
@@ -1,4 +1,8 @@
-use std::fmt::{Display, Formatter};
+use std::{
+ fmt::{Display, Formatter},
+ iter::Peekable,
+ str::CharIndices,
+};
// Wrapper to avoid unnecessary branching when input doesn't have ANSI escape sequences.
pub struct AnsiStyle {
@@ -10,7 +14,7 @@ impl AnsiStyle {
AnsiStyle { attributes: None }
}
- pub fn update(&mut self, sequence: &str) -> bool {
+ pub fn update(&mut self, sequence: EscapeSequence) -> bool {
match &mut self.attributes {
Some(a) => a.update(sequence),
None => {
@@ -19,6 +23,13 @@ impl AnsiStyle {
}
}
}
+
+ pub fn to_reset_sequence(&self) -> String {
+ match self.attributes {
+ Some(ref a) => a.to_reset_sequence(),
+ None => String::new(),
+ }
+ }
}
impl Display for AnsiStyle {
@@ -31,6 +42,8 @@ impl Display for AnsiStyle {
}
struct Attributes {
+ has_sgr_sequences: bool,
+
foreground: String,
background: String,
underlined: String,
@@ -61,11 +74,20 @@ struct Attributes {
/// ON: ^[9m
/// OFF: ^[29m
strike: String,
+
+ /// The hyperlink sequence.
+ /// FORMAT: \x1B]8;{ID};{URL}\e\\
+ ///
+ /// `\e\\` may be replaced with BEL `\x07`.
+ /// Setting both {ID} and {URL} to an empty string represents no hyperlink.
+ hyperlink: String,
}
impl Attributes {
pub fn new() -> Self {
Attributes {
+ has_sgr_sequences: false,
+
foreground: "".to_owned(),
background: "".to_owned(),
underlined: "".to_owned(),
@@ -76,34 +98,56 @@ impl Attributes {
underline: "".to_owned(),
italic: "".to_owned(),
strike: "".to_owned(),
+ hyperlink: "".to_owned(),
}
}
/// Update the attributes with an escape sequence.
/// Returns `false` if the sequence is unsupported.
- pub fn update(&mut self, sequence: &str) -> bool {
- let mut chars = sequence.char_indices().skip(1);
-
- if let Some((_, t)) = chars.next() {
- match t {
- '(' => self.update_with_charset('(', chars.map(|(_, c)| c)),
- ')' => self.update_with_charset(')', chars.map(|(_, c)| c)),
- '[' => {
- if let Some((i, last)) = chars.last() {
- // SAFETY: Always starts with ^[ and ends with m.
- self.update_with_csi(last, &sequence[2..i])
- } else {
- false
+ pub fn update(&mut self, sequence