1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-09-01 19:02:22 +01:00

Compare commits

..

232 Commits

Author SHA1 Message Date
Keith Hall
25f4f96ea3 Release bat v0.25.0
Merge pull request #3166 from sharkdp/release_0_25
2025-01-07 21:05:49 +02:00
Keith Hall
5cfd22ee8b Bump version to 0.25.0 2025-01-07 20:44:21 +02:00
Keith Hall
ae07586fef Merge pull request #2805 from Anomalocaridid/refactor-lessopen
Rework `lessopen` implementation to use `execute` crate instead of `run_script`
2025-01-06 06:21:46 +02:00
Anomalocaridid
96e4882b5c tests: remove serial attribute on and un-ignore applicable lessopen tests 2025-01-05 21:36:33 +00:00
Anomalocaridid
a0a090c307 tests: disable lessopen for help tests 2025-01-05 21:36:33 +00:00
Anomalocaridid
bc61d84408 update CHANGELOG.md 2025-01-05 21:36:33 +00:00
Anomalocaridid
de8bb79a6f refactor lessopen implementation 2025-01-05 21:36:33 +00:00
Anomalocaridid
7bf459f0ff replace run_script with execute 2025-01-05 21:36:33 +00:00
Keith Hall
18ed69aff4 Merge pull request #3113 from niklasmohrin/bump-clircle
Bump clircle to 0.6.1
2025-01-05 22:10:45 +02:00
Niklas Mohrin
c9431933e5 Deactivate clircle default features and require 0.6.1
This release removes the dependency on `winapi`.
2025-01-05 16:50:45 +01:00
Keith Hall
2d3581e8c4 Merge pull request #2858 from eth-p/update-docs-for-manpager
Update README steps for using bat as MANPAGER
2025-01-03 09:07:57 +02:00
Ethan P.
8453bc93cc Update README steps for using bat as MANPAGER 2025-01-03 08:53:16 +02:00
Keith Hall
d1418a9ab0 Merge pull request #2994 from sharkdp/two_dark_manpage
Patch themes for better manpage syntax highlighting
2025-01-03 08:44:14 +02:00
Keith Hall
09bdcde6c5 Update changelog to mention theme improvements for Manpage 2025-01-03 08:31:05 +02:00
Keith Hall
0d2afe79af Improve base16 themes for better Man page syntax highlighting 2025-01-03 08:31:05 +02:00
Keith Hall
5a12f187fa Patch 1337 theme for better Man page syntax highlighting 2025-01-03 08:31:05 +02:00
Keith Hall
753bfaff49 Improve Ansi theme for better Man page syntax highlighting 2025-01-03 08:31:05 +02:00
Keith Hall
9744971b19 Patch OneHalfDark theme for better Man page syntax highlighting 2025-01-03 08:31:05 +02:00
Keith Hall
c8f7787281 Patch TwoDark theme for better Man page syntax highlighting 2025-01-03 08:31:05 +02:00
Keith Hall
26f19703d3 Merge pull request #3157 from sharkdp/man_gs
Manpage: Fix for OPTIONS consisting of a plain dash
2025-01-03 08:30:44 +02:00
Keith Hall
b7b05a3553 Fix for OPTIONS consisting of a plain dash 2025-01-03 08:20:40 +02:00
dependabot[bot]
caba54efc9 Bump clircle from 0.6.0 to 0.6.1 (#3161)
Bumps [clircle](https://github.com/niklasmohrin/clircle) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/niklasmohrin/clircle/releases)
- [Commits](https://github.com/niklasmohrin/clircle/compare/v0.6.0...v0.6.1)

---
updated-dependencies:
- dependency-name: clircle
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 04:43:24 +00:00
dependabot[bot]
e2528dff6d Bump serde_with from 3.8.1 to 3.12.0 (#3162)
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.8.1 to 3.12.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.8.1...v3.12.0)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 04:30:15 +00:00
dependabot[bot]
ad11fb815f Bump predicates from 3.1.0 to 3.1.3 (#3158)
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 3.1.0 to 3.1.3.
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v3.1.0...v3.1.3)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 04:15:10 +00:00
dependabot[bot]
305e8a4d84 Bump serde from 1.0.209 to 1.0.217 (#3160)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.209 to 1.0.217.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.209...v1.0.217)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 03:57:42 +00:00
dependabot[bot]
7e804b27a0 Bump console from 0.15.8 to 0.15.10 (#3159)
Bumps [console](https://github.com/console-rs/console) from 0.15.8 to 0.15.10.
- [Release notes](https://github.com/console-rs/console/releases)
- [Changelog](https://github.com/console-rs/console/blob/main/CHANGELOG.md)
- [Commits](https://github.com/console-rs/console/compare/0.15.8...0.15.10)

---
updated-dependencies:
- dependency-name: console
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 03:34:32 +00:00
Keith Hall
18d963f423 Merge pull request #3152 from liliwilson/markdown-puppet-syntax-highlighting
Added patch for puppet syntax highlighting in Markdown code snippets
2024-12-30 21:40:15 +02:00
Lili Wilson
9d91d22e29 changelog entry 2024-12-30 21:27:28 +02:00
Lili Wilson
3fa9044029 added patch for puppet syntax highlighting in markdown 2024-12-30 21:27:28 +02:00
Keith Hall
8a9821fa9a Merge pull request #3154 from sharkdp/fix_cargo_audit_ci
[CI] fix cargo audit failing to run successfully
2024-12-30 21:26:22 +02:00
Keith Hall
75fadb8d1c ignore warning for idna also 2024-12-30 21:12:48 +02:00
Keith Hall
63560c4733 add cargo audit config file
ignore yaml-rust advisory for now
2024-12-30 20:53:31 +02:00
Keith Hall
d660cca8a9 Bump MSRV to 1.74
released over a year ago
2024-12-26 21:30:16 +02:00
Keith Hall
be62a4cea4 Upgrade clap to fix cargo audit failure on anstream 0.6.4
which is provided by clap 4.4.12
2024-12-26 21:19:02 +02:00
Keith Hall
874448c112 [CI] fix cargo audit failing to run 2024-12-26 21:13:14 +02:00
Keith Hall
3e07483f7a Merge pull request #3133 from sharkdp/keith-hall-patch-1
Build with MacOS 13 instead of 12
2024-12-07 12:08:41 +02:00
Keith Hall
9859077306 Build with MacOS 13 instead of 12
MacOS 12 is deprecated in GitHub Actions and no longer usable
2024-12-07 11:04:53 +02:00
Keith Hall
0cde7167d6 Merge pull request #3126 from einfachIrgendwer0815/feature/included_completions
Add `--completion <SHELL>` to provide shell completions
2024-12-01 19:16:05 +02:00
einfachIrgendwer0815
7eff8b687c Update changelog 2024-12-01 09:39:17 +01:00
einfachIrgendwer0815
04c7d15084 Mention --completion in the README 2024-12-01 09:39:17 +01:00
einfachIrgendwer0815
dbe25ba5e6 Include shell completions in the executable 2024-12-01 09:39:17 +01:00
dependabot[bot]
f81d4dc321 Bump terminal-colorsaurus from 0.4.4 to 0.4.7 (#3140)
Bumps [terminal-colorsaurus](https://github.com/bash/terminal-colorsaurus) from 0.4.4 to 0.4.7.
- [Release notes](https://github.com/bash/terminal-colorsaurus/releases)
- [Changelog](https://github.com/bash/terminal-colorsaurus/blob/main/changelog.md)
- [Commits](https://github.com/bash/terminal-colorsaurus/compare/0.4.4...0.4.7)

---
updated-dependencies:
- dependency-name: terminal-colorsaurus
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 05:00:43 +00:00
dependabot[bot]
f1c5c02713 Bump once_cell from 1.20.1 to 1.20.2 (#3139)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.1 to 1.20.2.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.1...v1.20.2)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 04:47:55 +00:00
dependabot[bot]
6c25c693a8 Bump regex from 1.10.2 to 1.10.6 (#3137)
Bumps [regex](https://github.com/rust-lang/regex) from 1.10.2 to 1.10.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.2...1.10.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 04:30:40 +00:00
dependabot[bot]
4be55ead4d Bump flate2 from 1.0.34 to 1.0.35 (#3136)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.34 to 1.0.35.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.34...1.0.35)

---
updated-dependencies:
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 04:05:04 +00:00
Keith Hall
8df326aeed Merge pull request #3135 from leo9800/master
Update syntax mapping for Apache Conf
2024-12-01 05:40:59 +02:00
Leo
f87157d009 Update syntax mapping for apache conf 2024-12-01 11:15:17 +08:00
Keith Hall
0b4fe03ec3 Merge pull request #3132 from fepegar/3130-use-toml-for-uv-lock
Use TOML syntax highlighting for uv.lock
2024-11-25 20:49:37 +02:00
Fernando Pérez-García
1063264d88 Replace issue number with pull request number 2024-11-24 08:14:24 +00:00
Fernando Pérez-García
4bee858c78 Update CHANGELOG 2024-11-22 22:50:53 +00:00
Fernando Pérez-García
d832367d95 Use TOML syntax highlighting for uv.lock 2024-11-22 22:39:35 +00:00
Keith Hall
d89a20f8b4 Merge pull request #3016 from CosmicHorrorDev/update-sublime-snazzy-theme
Bump themes/sublime-snazzy from `7034320` `48f43a7`
2024-11-21 21:13:27 +02:00
Keith Hall
41ef01f25d Merge branch 'master' into update-sublime-snazzy-theme 2024-11-21 20:30:53 +02:00
Keith Hall
7b797fd830 Merge pull request #3131 from binchengqu/master
chore: remove redundant word in comment
2024-11-21 06:09:50 +02:00
binchengqu
d27064cea5 chore: remove redundant word in comment
Signed-off-by: binchengqu <bincheng@before.tech>
2024-11-21 11:55:43 +08:00
Keith Hall
c9aa8d59ef Merge pull request #3015 from CosmicHorrorDev/update-nord-theme
Bump themes/Nord-submlime from `0d655b2` `bf92a9e`
2024-11-21 05:29:12 +02:00
Cosmic Horror
57a8b10883 Bump themes/Nord-submlime from 0d655b2 bf92a9e 2024-11-21 05:19:56 +02:00
Keith Hall
e608b33142 Merge pull request #3070 from kojix2/print
Add print_with_writer to PrettyPrint
2024-11-16 21:52:51 +02:00
kojix2
6598442d41 Merge branch 'master' into print 2024-11-14 10:08:21 +09:00
Keith Hall
822eff6028 Merge pull request #3063 from volklord/master
bat.zsh.in: Remove duplicate word
2024-11-13 22:19:09 +02:00
Keith Hall
da4defad07 Merge branch 'master' into master 2024-11-13 21:59:48 +02:00
Keith Hall
9bed8adb16 Merge pull request #3095 from mhelsley/mhelsley-fix-lessopen
Fix lessopen feature
2024-11-13 21:58:02 +02:00
Keith Hall
2e836e9822 Merge branch 'master' into mhelsley-fix-lessopen 2024-11-13 21:42:36 +02:00
Keith Hall
07554b0c1d Merge pull request #3098 from adamperkowski/bat_config_dir_docs
📔 docs: mention `BAT_CONFIG_DIR` in the README
2024-11-13 21:37:40 +02:00
Keith Hall
022574314f Merge branch 'master' into bat_config_dir_docs 2024-11-13 21:25:59 +02:00
Keith Hall
8a4701f93f Merge pull request #2896 from bash/dark-light
Choose Theme Based on The Terminal's Color Scheme
2024-11-13 21:10:50 +02:00
Keith Hall
08047a6a2e Merge branch 'master' into dark-light 2024-11-13 20:54:57 +02:00
Adam Perkowski
2caeaef14b 📔 docs: mention BAT_CONFIG_DIR in the README 2024-11-13 20:53:45 +02:00
Keith Hall
d00e05643f Merge pull request #3103 from Ugzuzg/citation-mapping
Add syntax mapping for CITATION.cff
2024-11-13 20:41:44 +02:00
Keith Hall
60693db73f Merge branch 'master' into dark-light 2024-11-13 20:33:37 +02:00
volklord
15f2553a3d bat.zsh.in: Remove duplicate word
Remove the duplicate word `disable disable`
2024-11-13 20:30:04 +02:00
Keith Hall
dbe352d8b8 Merge branch 'master' into citation-mapping 2024-11-13 20:25:26 +02:00
Keith Hall
517ddd8e00 Merge pull request #3115 from pratik-m/add-pipe-delimter-to-csv-syntax
Adding pipe delimeter support for csv files
2024-11-13 20:24:20 +02:00
Pratik Munot
558b487c91 Merge branch 'master' into add-pipe-delimter-to-csv-syntax 2024-11-11 20:41:52 -08:00
David Peter
f8f12a7db5 Update sponsorship information 2024-11-10 20:02:58 +01:00
Pratik Munot
d725443116 Merge branch 'master' into add-pipe-delimter-to-csv-syntax 2024-11-02 22:41:52 -07:00
dependabot[bot]
dbaa0a6d9e Bump grep-cli from 0.1.10 to 0.1.11 (#3120)
Bumps [grep-cli](https://github.com/BurntSushi/ripgrep) from 0.1.10 to 0.1.11.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-cli-0.1.10...0.1.11)

---
updated-dependencies:
- dependency-name: grep-cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-01 05:02:22 +00:00
dependabot[bot]
6b2c5645d2 Bump toml from 0.8.9 to 0.8.19 (#3121)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.9 to 0.8.19.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.9...toml-v0.8.19)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-01 04:46:28 +00:00
dependabot[bot]
e7bef716c9 Bump encoding_rs from 0.8.34 to 0.8.35 (#3119)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.34 to 0.8.35.
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.34...v0.8.35)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-01 04:23:23 +00:00
dependabot[bot]
c627526f8c Bump clircle from 0.5.0 to 0.6.0 (#3117)
Bumps [clircle](https://github.com/niklasmohrin/clircle) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/niklasmohrin/clircle/releases)
- [Commits](https://github.com/niklasmohrin/clircle/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: clircle
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-01 03:57:52 +00:00
Keith Hall
95cb705ac0 Merge pull request #2947 from jacg/debdiff
Make .debdiff imply .diff using syntax_mapping toml
2024-10-31 08:13:35 +02:00
kojix2
ca43c7a8f8 Merge branch 'master' into print 2024-10-31 15:04:14 +09:00
Jacek Generowicz
0a8bfc52a6 Move from unix-family to common 2024-10-31 08:03:45 +02:00
Jacek Generowicz
d0ae2e6826 Add CHANGELOG entry for .debdiff => diff 2024-10-31 08:03:45 +02:00
Jacek Generowicz
9090fb75e0 Make .debdiff imply .diff using syntax_mapping toml
Closes #2940
2024-10-31 08:03:45 +02:00
Keith Hall
50fa25db60 Merge pull request #2961 from cyqsimon/pacman-conf
Add syntax mapping for `/etc/pacman.conf`
2024-10-31 05:20:09 +02:00
Keith Hall
bd3c49d234 Merge remote-tracking branch 'origin/master' into pacman-conf 2024-10-31 05:08:46 +02:00
Keith Hall
ce7a3d9f7d Merge pull request #3108 from einfachIrgendwer0815/fix/2731_plain_override
Fix override of --plain and --paging
2024-10-31 05:07:23 +02:00
einfachIrgendwer0815
3b71837174 Merge branch 'master' into fix/2731_plain_override 2024-10-30 13:06:13 +01:00
Keith Hall
2be3a14a7e Merge pull request #2976 from einfachIrgendwer0815/feature/binary_as_text
Allow printing binary content by treating it the same as text
2024-10-30 13:55:21 +02:00
einfachIrgendwer0815
8d82402d74 Merge branch 'master' into feature/binary_as_text 2024-10-30 12:46:11 +01:00
Pratik Munot
1942d40863 changelog updates 2024-10-29 22:36:43 -07:00
Pratik Munot
5042844342 Adding pipe delimeter support for csv files 2024-10-29 21:34:47 -07:00
Fabio Valentini
649fb05c58 Bump nix from 0.26.4 to 0.29 2024-10-25 09:16:21 +02:00
kojix2
c533a4aa14 Update CHANGELOG.md 2024-10-23 21:42:02 +09:00
kojix2
b93a41a9a3 Add print_with_writer to PrettyPrint 2024-10-23 21:21:15 +09:00
Keith Hall
937c59fca9 Merge pull request #3049 from cyqsimon/kubernetes
Add syntax mapping for kubernetes config files
2024-10-21 23:10:22 +03:00
Keith Hall
a80d5ea9f7 Merge branch 'master' into pacman-conf 2024-10-21 23:02:56 +03:00
Keith Hall
c11a7d9e41 Merge branch 'master' into kubernetes 2024-10-21 23:01:30 +03:00
einfachIrgendwer0815
ac082ab64b Update changelog 2024-10-18 12:44:53 +02:00
einfachIrgendwer0815
c9fd0f3cf0 Add partial override of -pp and --paging 2024-10-18 12:13:41 +02:00
einfachIrgendwer0815
e667415def Add tests against issue #2731 2024-10-18 12:13:41 +02:00
einfachIrgendwer0815
fd6c7637e4 Partially revert "Make -pp override --paging and vice versa when passed as a later argument. (#2660)"
This partially reverts commit e2bf85e749.
2024-10-18 11:46:51 +02:00
Jarasłaŭ Viktorčyk
9a816c9c68 Add syntax mapping for CITATION.cff 2024-10-13 11:47:31 +02:00
Matt Helsley
431344ba67 Merge branch 'master' into mhelsley-fix-lessopen 2024-10-06 21:52:34 -07:00
Keith Hall
eca6b8a376 Merge pull request #3075 from einfachIrgendwer0815/fix/3073_list_themes
Don't output default theme info to piped stdout
2024-10-06 22:27:18 +03:00
Keith Hall
b01ed8d773 Merge branch 'master' into fix/3073_list_themes 2024-10-06 22:08:00 +03:00
Matt Helsley
3e5f4266ce Fix lessopen feature
RawOsString API changed in os_str_bytes 7.0.0 and bat no longer builds
with the lessopen feature because:

- ::from_string() is deprecated and says to use new().
  The documentation says that new(), like from_string() no longer
  needs to copy the string.

- ::assert_from_raw_vec() is no longer merely deprecated and now
  requires selecting the "conversions" feature of os_str_bytes.

Replaces PR#2938
2024-10-03 16:32:23 -07:00
dependabot[bot]
61c9f312c9 Bump flate2 from 1.0.30 to 1.0.34 (#3093)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.30 to 1.0.34.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.30...1.0.34)

---
updated-dependencies:
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 03:36:57 +00:00
dependabot[bot]
c59dad0cae Bump git2 from 0.18.3 to 0.19.0 (#3092)
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.18.3 to 0.19.0.
- [Changelog](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.18.3...git2-0.19.0)

---
updated-dependencies:
- dependency-name: git2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 03:19:34 +00:00
dependabot[bot]
16a79d38c2 Bump once_cell from 1.19.0 to 1.20.1 (#3091)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.19.0 to 1.20.1.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.19.0...v1.20.1)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 03:02:02 +00:00
dependabot[bot]
9d635627dc Bump globset from 0.4.14 to 0.4.15 (#3090)
Bumps [globset](https://github.com/BurntSushi/ripgrep) from 0.4.14 to 0.4.15.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/globset-0.4.14...ignore-0.4.15)

---
updated-dependencies:
- dependency-name: globset
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 02:40:45 +00:00
einfachIrgendwer0815
bc69ffb0f0 Map *.mkd files to Markdown syntax (#3061) 2024-09-26 21:06:07 +02:00
flytam
a0226f5670 Update Chinese version translation of README.md 2024-09-20 06:28:20 +02:00
Mikael Vaaltola
ed7789d9b7 Associate GeoJSON .geojson files with json syntax (fixes #3083) 2024-09-20 06:14:26 +02:00
Tau Gärtli
b747184788 Accept impl Into<String> to avoid cloning strings 2024-09-08 17:11:11 +02:00
Tau Gärtli
02ae6ef348 Remove redundant guard 2024-09-07 22:59:27 +02:00
Tau Gärtli
0ebb9cbfe2 Add Display impl 2024-09-07 21:57:27 +02:00
Tau Gärtli
f6cbee9e27 Update docs 2024-09-07 21:36:03 +02:00
Tau Gärtli
10e823c4b7 Rename internal function 2024-09-07 21:36:03 +02:00
Tau Gärtli
60e4027332 Expose theme env vars 2024-09-07 21:36:02 +02:00
Tau Gärtli
e075fee5bf Add infallible constructor 2024-09-07 21:36:02 +02:00
Tau Gärtli
16d9b99f6c Flatten preference enum 2024-09-04 21:18:29 +02:00
dependabot[bot]
ffa74a7f49 Bump serde from 1.0.199 to 1.0.209 (#3077)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.199 to 1.0.209.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.199...v1.0.209)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 03:05:26 +00:00
dependabot[bot]
c1772b7793 Bump plist from 1.6.0 to 1.7.0 (#3076)
Bumps [plist](https://github.com/ebarnard/rust-plist) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/ebarnard/rust-plist/releases)
- [Commits](https://github.com/ebarnard/rust-plist/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: plist
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-01 02:45:53 +00:00
einfachIrgendwer0815
5be9d19500 Reinforce tests for --list-themes 2024-08-25 11:10:25 +02:00
einfachIrgendwer0815
0603f0b844 Don't output default theme info to piped stdout 2024-08-25 10:54:46 +02:00
Tau Gärtli
50958472e5 Return theme alongside detected color scheme 2024-08-23 18:03:07 +02:00
Tau Gärtli
89ce060183 Update help, man page and completions 2024-08-18 20:32:59 +02:00
Tau Gärtli
bc42149a72 Merge color scheme options into theme / BAT_THEME 2024-08-18 14:59:14 +02:00
einfachIrgendwer0815
0c3b22e0f0 Run syntax highlighting when --binary=as-text 2024-08-18 10:06:12 +02:00
einfachIrgendwer0815
a769a3d813 Update CHANGELOG 2024-08-18 10:06:09 +02:00
einfachIrgendwer0815
7cc231b82b Test --binary=as-text 2024-08-18 10:05:43 +02:00
einfachIrgendwer0815
7f089ead62 Add option --binary
`--binary` allows to specify how to deal with binary content. Current
options are not printing anything or treating the binary data as text.
2024-08-18 10:05:37 +02:00
Tau Gärtli
b9b981f657 Generalize --detect-color-scheme to --color-scheme 2024-08-16 14:14:30 +02:00
Tau Gärtli
abf9dada04 Remove HighlightingAssets::default_theme() 2024-08-16 14:13:58 +02:00
Tau Gärtli
5c6974703e Respect --detect-color-scheme flag when listing themes 2024-08-16 14:13:58 +02:00
Tau Gärtli
1b0a6da4be Use new default_theme fn for --list-themes 2024-08-16 14:13:58 +02:00
Tau Gärtli
06b645435a Add changelog entry 2024-08-16 14:13:57 +02:00
Tau Gärtli
c3b190d45b Disable color detection in test 2024-08-16 14:13:18 +02:00
Tau Gärtli
594b1417f1 Update readme 2024-08-16 14:13:18 +02:00
Tau Gärtli
e8ca6ec7c3 Remove cargo feature 2024-08-16 14:13:18 +02:00
Tau Gärtli
6498615f5f Improve upon the documentation 2024-08-16 14:13:18 +02:00
Tau Gärtli
30b0143ccf Make default_theme pub 2024-08-16 14:13:17 +02:00
Tau Gärtli
ff81cfd584 Move actual detection into library 2024-08-16 14:13:16 +02:00
Tau Gärtli
14ce668a1d Add generated powershell completion to ignore list 2024-08-16 14:12:23 +02:00
Tau Gärtli
9a1bfe946d Update completions and man page 2024-08-16 14:12:23 +02:00
Tau Gärtli
cea45e05f3 Expose new theme selection in CLI 2024-08-16 14:12:22 +02:00
Tau Gärtli
cda363a3f7 Use default_theme() function from theme module 2024-08-16 14:09:38 +02:00
Tau Gärtli
de796392cf Deprecate old default_theme function 2024-08-16 14:09:38 +02:00
Tau Gärtli
1423dd9440 Choose theme based on the terminal's color scheme 2024-08-16 14:09:35 +02:00
dependabot[bot]
b662fec214 Bump ansi_colours from 1.2.2 to 1.2.3 (#3058)
Bumps [ansi_colours](https://github.com/mina86/ansi_colours) from 1.2.2 to 1.2.3.
- [Commits](https://github.com/mina86/ansi_colours/commits)

---
updated-dependencies:
- dependency-name: ansi_colours
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 03:28:12 +00:00
dependabot[bot]
d8d0b77568 Bump indexmap from 2.2.6 to 2.3.0 (#3057)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.2.6 to 2.3.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.2.6...2.3.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 03:14:26 +00:00
dependabot[bot]
13317b0a3b Bump expect-test from 1.4.1 to 1.5.0 (#3055)
Bumps [expect-test](https://github.com/rust-analyzer/expect-test) from 1.4.1 to 1.5.0.
- [Changelog](https://github.com/rust-analyzer/expect-test/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-analyzer/expect-test/compare/v1.4.1...v1.5.0)

---
updated-dependencies:
- dependency-name: expect-test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-01 02:47:46 +00:00
Ethan P.
2616296183 Merge pull request #2929 from eth-p/add-remove-styles
Merge `--style`s from different places using `+`/`-`
2024-07-30 21:30:19 -07:00
Ethan P.
39684b85ad Update changelog 2024-07-30 21:22:05 -07:00
Ethan P.
aa3ec109b7 First StyleComponentList should remove from 'auto' style.
This happens when there are no `--style` arguments other than the one
passed in as a command line argument.

Prior to this change, removing a style component (e.g. `--style=-numbers`)
would remove the component from an empty style component set, resulting
in no styles at all. That behaviour was less intuitive than the new
behaviour, which starts out with the default components and
removes the line numbers.
2024-07-30 21:22:02 -07:00
Ethan P.
180a77ee99 Add integration tests for merging styles
A huge thanks to @einfachIrgendwer0815 for helping me make sure
these tests work under the MSRV CI job.
2024-07-30 21:22:00 -07:00
Ethan P.
93b25d75a0 Join env var options with "=" instead of " "
Joining them with a space was causing certain styles (e.g. `-grid`) to
be misinterpreted as a separate option.
2024-07-30 21:21:58 -07:00
Ethan P.
6e91ba83b7 Update clap/docs for merging --style arguments 2024-07-30 21:21:55 -07:00
Ethan P.
b74c125c43 Support merging --style arguments
The `overrides_with` clap builder option was removed
because it interfered with the matcher's ability to
retain all occurrences of `--style`.

The behavior it covered is expressed within the new
`forced_style_components` function.
2024-07-30 21:21:53 -07:00
Keith Hall
fd1e0d5876 Merge pull request #2995 from akinomyoga/update-man
Update the man page of bat (`assets/manual/bat.1.in`)
2024-07-29 07:14:31 +03:00
Koichi Murase
9a650e8279 Update CHANGELOG 2024-07-29 12:18:40 +09:00
Koichi Murase
d5aa9d8e05 Add options generated by completions to the man page 2024-07-29 12:18:40 +09:00
Koichi Murase
b1cdc06430 Add --no-* options to Bash/Zsh completions 2024-07-29 12:18:40 +09:00
Koichi Murase
83a15ac05f Add --cache-dir to Fish completion 2024-07-29 12:18:40 +09:00
Koichi Murase
43a77a42f8 Add options present in --help to Bash completion 2024-07-29 12:18:40 +09:00
Koichi Murase
44ca1e7df1 Add options present in --help to the man page 2024-07-29 12:18:40 +09:00
Michael Vorburger
23fd200482 Associate JSON-LD .jsonld files with json syntax (fixes #3036)
Use PR instead of Issue # number in CHANGELOG.

Clean up (unify) CHANGELOG.
2024-07-27 15:48:02 +02:00
Keith Hall
9f1c62b013 Merge pull request #3031 from brenton-at-pieces/add-cfml
add CFML syntax
2024-07-26 19:45:44 +03:00
cyqsimon
319b8868fc Write changelog 2024-07-26 23:39:27 +08:00
cyqsimon
7bd6cdbebc Add syntax mapping for kubernetes config files 2024-07-26 23:23:58 +08:00
Brenton Bostick
1488a4a006 Merge branch 'master' into add-cfml 2024-07-26 09:09:30 -04:00
Keith Hall
56d2823b0e Merge pull request #3045 from cyqsimon/time
Bump time to 0.3.36 (fixes #3043)
2024-07-26 12:12:57 +03:00
cyqsimon
1a11ba11e3 Write changelog 2024-07-26 16:18:16 +08:00
cyqsimon
c34bdb5e66 Bump time to 0.3.36 (fixes #3043) 2024-07-26 16:10:17 +08:00
Brenton Bostick
10456e1d51 Merge branch 'master' into add-cfml 2024-07-25 15:54:50 -04:00
Keith Hall
bbdadc7e38 Merge pull request #3038 from vorburger/bump-textproto
Update the Protobuf sobmodule in order to add `.textproto` support
2024-07-23 23:02:35 +03:00
Michael Vorburger
ff71e32c0f Update the Protobuf sobmodule (fixes #2542) 2024-07-21 23:14:12 +02:00
Brenton Bostick
50b01ea8da update CHANGELOG 2024-07-17 16:17:41 -04:00
Brenton Bostick
de697f7717 add CFML syntax 2024-07-17 15:46:38 -04:00
Cosmic Horror
575457c944 Bump themes/sublime-snazzy from 7034320 48f43a7 2024-06-30 23:43:32 -06:00
dependabot[bot]
6fc58821a5 Bump anyhow from 1.0.78 to 1.0.86 (#3021)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.78 to 1.0.86.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.78...1.0.86)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 03:34:46 +00:00
dependabot[bot]
7873b473e8 Bump unicode-width from 0.1.11 to 0.1.13 (#3019)
Bumps [unicode-width](https://github.com/unicode-rs/unicode-width) from 0.1.11 to 0.1.13.
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.11...v0.1.13)

---
updated-dependencies:
- dependency-name: unicode-width
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 03:16:35 +00:00
dependabot[bot]
609005a225 Bump encoding_rs from 0.8.33 to 0.8.34 (#3020)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.33 to 0.8.34.
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.33...v0.8.34)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 02:51:38 +00:00
dependabot[bot]
b9c74ab859 Bump walkdir from 2.4.0 to 2.5.0 (#3018)
Bumps [walkdir](https://github.com/BurntSushi/walkdir) from 2.4.0 to 2.5.0.
- [Commits](https://github.com/BurntSushi/walkdir/compare/2.4.0...2.5.0)

---
updated-dependencies:
- dependency-name: walkdir
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 02:29:47 +00:00
Driss Boumlik
cee5584daf Fix cmder link 2024-06-29 14:57:40 +02:00
Bryan Honof
b265b20721 Add flox install 2024-06-23 13:52:52 +02:00
Ethan P
a7a9727c11 Merge pull request #2999 from eth-p/strip-ansi-from-input-option
Add option to remove ANSI escape sequences from bat's input.
2024-06-17 18:37:22 -07:00
Ethan P.
90dfa7f18d Update README.md to mention --strip-ansi 2024-06-17 18:27:39 -07:00
Ethan P.
3f8d62e7d6 Update CHANGELOG.md 2024-06-17 18:27:39 -07:00
Ethan P.
3f22311ec8 Add ANSI stripping to bat-as-a-library 2024-06-17 18:27:39 -07:00
Ethan P.
9e8176b1c6 Add --strip-ansi=auto option
When using `auto`, escape sequences will be stripped unless printing
plain text.
2024-06-17 18:27:33 -07:00
Ethan P.
70ff93d238 Add --strip-ansi option 2024-06-16 16:49:07 -07:00
Tong Zhaoqi
c264ecd26b ci: support aarch64 statically-linked binary (#2992) 2024-06-16 20:16:11 +02:00
Ethan P
10a1b24191 Merge pull request #2998 from eth-p/improve-preprocessor
Update bat's tab expansion preprocessor to use bat's ANSI escape sequence iterator.
2024-06-15 16:28:05 -07:00
Ethan P.
243819ecdc Update CHANGELOG.md 2024-06-15 16:18:29 -07:00
Ethan P.
9c76b72825 Update expand_tabs to use bat's ANSI iterator 2024-06-10 20:07:54 -07:00
Ethan P.
b4fe182960 Make EscapeSequenceOffsetsIterator pub, add fns to get indices 2024-06-10 20:04:17 -07:00
dependabot[bot]
b7e44c76dc Bump semver from 1.0.21 to 1.0.23 (#2981)
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.21 to 1.0.23.
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.21...1.0.23)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-01 03:31:50 +00:00
dependabot[bot]
f3cc69733f Bump thiserror from 1.0.53 to 1.0.61 (#2979)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.53 to 1.0.61.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.53...1.0.61)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-01 03:18:21 +00:00
dependabot[bot]
3625f0ea1c Bump itertools from 0.12.1 to 0.13.0 (#2978)
Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.12.1 to 0.13.0.
- [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-itertools/itertools/compare/v0.12.1...v0.13.0)

---
updated-dependencies:
- dependency-name: itertools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-01 03:04:56 +00:00
dependabot[bot]
e6e2d4c65d Bump flate2 from 1.0.28 to 1.0.30 (#2980)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.28 to 1.0.30.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.28...1.0.30)

---
updated-dependencies:
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-01 02:48:23 +00:00
dependabot[bot]
340e873eff Bump git2 from 0.18.2 to 0.18.3 (#2977)
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.18.2 to 0.18.3.
- [Changelog](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.18.2...git2-0.18.3)

---
updated-dependencies:
- dependency-name: git2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-01 02:24:10 +00:00
Keith Hall
3407bf4bf6 Merge pull request #2970 from ccqpein/master
Patch the lisp syntax
2024-05-31 23:30:08 +03:00
ccQpein
25cd4991d2 update lisp test 2024-05-31 12:39:19 -04:00
ccQpein
503b2c5126 fix the prefix 2024-05-27 16:22:07 -04:00
ccQpein
026bc05d70 changelog 2024-05-27 15:58:04 -04:00
ccQpein
61005f19fa patch the lisp syntax 2024-05-27 15:52:26 -04:00
someposer
8f8c953ab6 Add support for Apple Silicon (#2967) 2024-05-27 06:14:11 +02:00
cyqsimon
f82487daf8 Write changelog 2024-05-15 14:35:47 +08:00
cyqsimon
3a9d574770 Add syntax mapping for /etc/pacman.conf 2024-05-15 14:31:25 +08:00
dependabot[bot]
b4e3a84e1a Bump serde from 1.0.197 to 1.0.199 (#2953)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.199.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.199)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 03:23:25 +00:00
dependabot[bot]
f7c39e8353 Bump os_str_bytes from 6.6.1 to 7.0.0 (#2952)
Bumps [os_str_bytes](https://github.com/dylni/os_str_bytes) from 6.6.1 to 7.0.0.
- [Release notes](https://github.com/dylni/os_str_bytes/releases)
- [Commits](https://github.com/dylni/os_str_bytes/compare/6.6.1...7.0.0)

---
updated-dependencies:
- dependency-name: os_str_bytes
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 03:10:09 +00:00
dependabot[bot]
37d9f0533c Bump indexmap from 2.2.2 to 2.2.6 (#2950)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.2.2 to 2.2.6.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.2.2...2.2.6)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 02:47:11 +00:00
dependabot[bot]
d560f2a515 Bump serde_with from 3.7.0 to 3.8.1 (#2949)
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.7.0 to 3.8.1.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.7.0...v3.8.1)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 02:27:04 +00:00
Stéphane Blondon
bb4d1cbd2e refactor: factorize constants by inverting loop and condition order 2024-04-19 11:44:47 +02:00
Stéphane Blondon
23ec433167 display which theme is the default one in basic output 2024-04-19 11:44:47 +02:00
Sharun
9eaed3e3f0 [JavaScript] Support bun in shebang for syntax highlighting (#2913)
* [JavaScript] Support bun in shebang for syntax highlighting

---------

Co-authored-by: Keith Hall <keith-hall@users.noreply.github.com>
2024-04-15 06:17:41 +00:00
sblondon
d5bd4aa93f display which theme is the default one in colored output (#2838) 2024-04-14 15:54:52 +02:00
Keith Hall
66b70dd8ed Merge pull request #2933 from vorburger/patch-1
Fix minor typo in GitHub Syntax Request Issue Template
2024-04-09 21:35:45 +03:00
Michael Vorburger
01731478a6 Fix minor typo in GitHub Syntax Request Issue Template 2024-04-09 19:54:46 +02:00
Rivera Calzadillas
f8c5429a6c Print $TERM with --diagnostic 2024-04-07 14:24:16 +02:00
Rivera Calzadillas
f71226adbb Sort env vars printed by --diagnostic 2024-04-07 14:24:16 +02:00
一个不知名の睡觉高手
e8d777b73a fix: some typos 2024-04-04 06:01:37 +02:00
dependabot[bot]
3cff44b652 Bump console from 0.15.7 to 0.15.8 (#2925)
Bumps [console](https://github.com/console-rs/console) from 0.15.7 to 0.15.8.
- [Changelog](https://github.com/console-rs/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/console-rs/console/compare/0.15.7...0.15.8)

---
updated-dependencies:
- dependency-name: console
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 04:11:21 +00:00
dependabot[bot]
26302a8b08 Bump serde from 1.0.193 to 1.0.197 (#2926)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.193 to 1.0.197.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.193...v1.0.197)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 03:58:57 +00:00
dependabot[bot]
adc5bd0402 Bump serde_with from 3.6.1 to 3.7.0 (#2923)
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.6.1 to 3.7.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.6.1...v3.7.0)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 03:44:58 +00:00
dependabot[bot]
e3c3be950a Bump predicates from 3.0.4 to 3.1.0 (#2924)
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 3.0.4 to 3.1.0.
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v3.0.4...v3.1.0)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 03:30:00 +00:00
dependabot[bot]
8d92dc2083 Bump wild from 2.2.0 to 2.2.1 (#2922)
Bumps [wild](https://gitlab.com/kornelski/wild) from 2.2.0 to 2.2.1.
- [Commits](https://gitlab.com/kornelski/wild/compare/v2.2.0...v2.2.1)

---
updated-dependencies:
- dependency-name: wild
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 03:11:04 +00:00
dependabot[bot]
a1f85b9e06 Bump assets/syntaxes/02_Extra/Julia from 98233f9 to 3366b10 (#2918)
Bumps [assets/syntaxes/02_Extra/Julia](https://github.com/JuliaEditorSupport/Julia-sublime) from `98233f9` to `3366b10`.
- [Release notes](https://github.com/JuliaEditorSupport/Julia-sublime/releases)
- [Commits](98233f96d4...3366b10be9)

---
updated-dependencies:
- dependency-name: assets/syntaxes/02_Extra/Julia
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 02:47:26 +00:00
dependabot[bot]
424c02dfa7 Bump softprops/action-gh-release from 1 to 2 (#2917)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 02:29:01 +00:00
70 changed files with 5031 additions and 728 deletions

2
.cargo/audit.toml Normal file
View File

@@ -0,0 +1,2 @@
[advisories]
ignore = ["RUSTSEC-2024-0320", "RUSTSEC-2024-0421"]

View File

@@ -26,4 +26,4 @@ guidelines for adding new syntaxes:
[Name or description of the syntax/language here]
**Guideline Criteria:**
[packagecontro.io link here]
[packagecontrol.io link here]

View File

@@ -152,6 +152,7 @@ jobs:
name: cargo audit
runs-on: ubuntu-latest
steps:
- run: cargo install cargo-audit --locked
- uses: actions/checkout@v4
- run: cargo audit
@@ -163,13 +164,15 @@ jobs:
fail-fast: false
matrix:
job:
- { target: aarch64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
- { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
- { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, dpkg_arch: armhf, use-cross: true }
- { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, dpkg_arch: musl-linux-armhf, use-cross: true }
- { target: i686-pc-windows-msvc , os: windows-2019, }
- { target: i686-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: i686, use-cross: true }
- { target: i686-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-i686, use-cross: true }
- { target: x86_64-apple-darwin , os: macos-12, }
- { target: x86_64-apple-darwin , os: macos-13, }
- { target: aarch64-apple-darwin , os: macos-14, }
- { target: x86_64-pc-windows-gnu , os: windows-2019, }
- { target: x86_64-pc-windows-msvc , os: windows-2019, }
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: amd64, use-cross: true }
@@ -444,7 +447,7 @@ jobs:
echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT
- name: Publish archives and packages
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: steps.is-release.outputs.IS_RELEASE
with:
files: |

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
**/*.rs.bk
# Generated files
/assets/completions/_bat.ps1
/assets/completions/bat.bash
/assets/completions/bat.fish
/assets/completions/bat.zsh

3
.gitmodules vendored
View File

@@ -260,3 +260,6 @@
[submodule "assets/syntaxes/02_Extra/vscode-wgsl"]
path = assets/syntaxes/02_Extra/vscode-wgsl
url = https://github.com/PolyMeilex/vscode-wgsl.git
[submodule "assets/syntaxes/02_Extra/CFML"]
path = assets/syntaxes/02_Extra/CFML
url = https://github.com/jcberquist/sublimetext-cfml.git

View File

@@ -1,4 +1,4 @@
# unreleased
# v0.25.0
## Features
@@ -6,6 +6,13 @@
- `bat --squeeze-blank`/`bat -s` will now squeeze consecutive empty lines, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
- `bat --squeeze-limit` to set the maximum number of empty consecutive when using `--squeeze-blank`, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
- `PrettyPrinter::squeeze_empty_lines` to support line squeezing for bat as a library, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
- Syntax highlighting for JavaScript files that start with `#!/usr/bin/env bun` #2913 (@sharunkumar)
- `bat --strip-ansi={never,always,auto}` to remove ANSI escape sequences from bat's input, see #2999 (@eth-p)
- Add or remove individual style components without replacing all styles #2929 (@eth-p)
- Automatically choose theme based on the terminal's color scheme, see #2896 (@bash)
- Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815)
- Make shell completions available via `--completion <shell>`, see issue #2057 and PR #3126 (@einfachIrgendwer0815)
- Syntax highlighting for puppet code blocks within Markdown files, see #3152 (@liliwilson)
## Bugfixes
@@ -14,6 +21,9 @@
- 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)
- Fix compile issue of `time` dependency caused by standard library regression #3045 (@cyqsimon)
- Fix override behavior of --plain and --paging, see issue #2731 and PR #3108 (@einfachIrgendwer0815)
- Fix bugs in `$LESSOPEN` support, see #2805 (@Anomalocaridid)
## Other
@@ -33,6 +43,16 @@
- Relax syntax mapping rule restrictions to allow brace expansion #2865 (@cyqsimon)
- Apply clippy fixes #2864 (@cyqsimon)
- Faster startup by offloading glob matcher building to a worker thread #2868 (@cyqsimon)
- Display which theme is the default one in basic output (no colors), see #2937 (@sblondon)
- Display which theme is the default one in colored output, see #2838 (@sblondon)
- Add aarch64-apple-darwin ("Apple Silicon") binary tarballs to releases, see #2967 (@someposer)
- Update the Lisp syntax, see #2970 (@ccqpein)
- Use bat's ANSI iterator during tab expansion, see #2998 (@eth-p)
- Support 'statically linked binary' for aarch64 in 'Release' page, see #2992 (@tzq0301)
- Update options in shell completions and the man page of `bat`, see #2995 (@akinomyoga)
- Update nix dev-dependency to v0.29.0, see #3112 (@decathorpe)
- Bump MSRV to [1.74](https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html), see #3154 (@keith-hall)
- Update clircle dependency to remove winapi transitive dependency, see #3113 (@niklasmohrin)
## Syntaxes
@@ -40,13 +60,25 @@
- Upgrade JQ syntax, see #2820 (@dependabot[bot])
- Add syntax mapping for quadman quadlets #2866 (@cyqsimon)
- Map containers .conf files to TOML syntax #2867 (@cyqsimon)
- 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)
- Add syntax mapping for Wireguard config #2874 (@cyqsimon)
- Associate `.xsh` files with `xonsh` syntax that is Python, see #2840 (@anki-code)
- Associate JSON with Comments `.jsonc` with `json` syntax, see #2795 (@mxaddict)
- Associate JSON-LD `.jsonld` files with `json` syntax, see #3037 (@vorburger)
- Associate `.textproto` files with `ProtoBuf` syntax, see #3038 (@vorburger)
- Associate GeoJSON `.geojson` files with `json` syntax, see #3084 (@mvaaltola)
- Associate `.aws/{config,credentials}`, see #2795 (@mxaddict)
- Associate Wireguard config `/etc/wireguard/*.conf`, see #2874 (@cyqsimon)
- Add support for [CFML](https://www.adobe.com/products/coldfusion-family.html), see #3031 (@brenton-at-pieces)
- Map `*.mkd` files to `Markdown` syntax, see issue #3060 and PR #3061 (@einfachIrgendwer0815)
- Add syntax mapping for CITATION.cff, see #3103 (@Ugzuzg)
- Add syntax mapping for kubernetes config files #3049 (@cyqsimon)
- Adds support for pipe delimiter for CSV #3115 (@pratik-m)
- Add syntax mapping for `/etc/pacman.conf` #2961 (@cyqsimon)
- Associate `uv.lock` with `TOML` syntax, see #3132 (@fepegar)
## Themes
- Patched/improved themes for better Manpage syntax highlighting support, see #2994 (@keith-hall).
## `bat` as a library
- Changes to `syntax_mapping::SyntaxMapping` #2755 (@cyqsimon)
@@ -55,6 +87,10 @@
- [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)
- Add `theme::theme` for choosing an appropriate theme based on the
terminal's color scheme, see #2896 (@bash)
- [BREAKING] Remove `HighlightingAssets::default_theme`. Use `theme::default_theme` instead.
- Add `PrettyPrinter::print_with_writer` for custom output destinations, see #3070 (@kojix2)
# v0.24.0
@@ -93,6 +129,7 @@
- Update `Julia` syntax, see #2553 (@dependabot)
- add `NSIS` support, see #2577 (@idleberg)
- Update `ssh-config`, see #2697 (@mrmeszaros)
- Add syntax mapping `*.debdiff` => `diff`, see #2947 (@jacg)
## `bat` as a library

598
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,11 +6,11 @@ homepage = "https://github.com/sharkdp/bat"
license = "MIT OR Apache-2.0"
name = "bat"
repository = "https://github.com/sharkdp/bat"
version = "0.24.0"
version = "0.25.0"
exclude = ["assets/syntaxes/*", "assets/themes/*"]
build = "build/main.rs"
edition = '2021'
rust-version = "1.70"
rust-version = "1.74"
[features]
default = ["application"]
@@ -33,7 +33,7 @@ minimal-application = [
]
git = ["git2"] # Support indicating git modifications
paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
lessopen = ["run_script", "os_str_bytes"] # Support $LESSOPEN preprocessor
lessopen = ["execute"] # Support $LESSOPEN preprocessor
build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
# You need to use one of these if you depend on bat as a library:
@@ -44,33 +44,33 @@ regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine
nu-ansi-term = "0.50.0"
ansi_colours = "^1.2"
bincode = "1.0"
console = "0.15.7"
console = "0.15.10"
flate2 = "1.0"
once_cell = "1.19"
once_cell = "1.20"
thiserror = "1.0"
wild = { version = "2.2", optional = true }
content_inspector = "0.2.4"
shell-words = { version = "1.1.0", optional = true }
unicode-width = "0.1.11"
unicode-width = "0.1.13"
globset = "0.4"
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.5"
clircle = { version = "0.6.1", default-features = false }
bugreport = { version = "0.5.0", optional = true }
etcetera = { version = "0.8.0", optional = true }
grep-cli = { version = "0.1.10", optional = true }
regex = { version = "1.10.2", optional = true }
walkdir = { version = "2.4", optional = true }
grep-cli = { version = "0.1.11", optional = true }
regex = { version = "1.10.6", optional = true }
walkdir = { version = "2.5", optional = true }
bytesize = { version = "1.3.0" }
encoding_rs = "0.8.33"
os_str_bytes = { version = "~6.6", optional = true }
run_script = { version = "^0.10.1", optional = true}
encoding_rs = "0.8.35"
execute = { version = "0.2.13", optional = true }
terminal-colorsaurus = "0.4"
[dependencies.git2]
version = "0.18"
version = "0.19"
optional = true
default-features = false
@@ -86,31 +86,31 @@ features = ["wrap_help", "cargo"]
[target.'cfg(target_os = "macos")'.dependencies]
home = "0.5.9"
plist = "1.6.0"
plist = "1.7.0"
[dev-dependencies]
assert_cmd = "2.0.12"
expect-test = "1.4.1"
expect-test = "1.5.0"
serial_test = { version = "2.0.0", default-features = false }
predicates = "3.0.4"
predicates = "3.1.3"
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"] }
nix = { version = "0.29", default-features = false, features = ["term"] }
[build-dependencies]
anyhow = "1.0.78"
indexmap = { version = "2.2.2", features = ["serde"] }
itertools = "0.12.1"
once_cell = "1.18"
regex = "1.10.2"
anyhow = "1.0.86"
indexmap = { version = "2.3.0", features = ["serde"] }
itertools = "0.13.0"
once_cell = "1.20"
regex = "1.10.6"
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"
serde_with = { version = "3.12.0", default-features = false, features = ["macros"] }
toml = { version = "0.8.19", features = ["preserve_order"] }
walkdir = "2.5"
[build-dependencies.clap]
version = "4.4.12"

View File

@@ -35,11 +35,11 @@ A special *thank you* goes to our biggest <a href="doc/sponsors.md">sponsors</a>
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=bat_20231001">
<img src="doc/sponsors/warp-logo.png" width="200" alt="Warp">
<br>
<strong>Warp is a modern, Rust-based terminal with AI built in<br>so you and your team can build great software, faster.</strong>
<strong>Warp, the intelligent terminal</strong>
<br>
<sub>Feel more productive on the command line with parameterized commands,</sub>
<sub>Run commands like a power user with AI and your dev teams</sub>
<br>
<sup>autosuggestions, and an IDE-like text editor.</sup>
<sup>knowledge in one fast, intuitive terminal. For MacOS or Linux.</sup>
</a>
### Syntax highlighting
@@ -204,19 +204,19 @@ bat main.cpp | xclip
`MANPAGER` environment variable:
```bash
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
export MANPAGER="sh -c 'sed -u -e \"s/\\x1B\[[0-9;]*m//g; s/.\\x08//g\" | bat -p -lman'"
man 2 select
```
(replace `bat` with `batcat` if you are on Debian or Ubuntu)
It might also be necessary to set `MANROFFOPT="-c"` if you experience
formatting problems.
If you prefer to have this bundled in a new command, you can also use [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md).
Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax) is developed in this repository and still needs some work.
> [!WARNING]
> This will [not work](https://github.com/sharkdp/bat/issues/1145) out of the box with Mandoc's `man` implementation.
>
> Please either use `batman`, or convert the shell script to a [shebang executable](https://en.wikipedia.org/wiki/Shebang_(Unix)) and point `MANPAGER` to that.
Also, note that this will [not work](https://github.com/sharkdp/bat/issues/1145) with Mandocs `man` implementation.
Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax) is developed in this repository and still needs some work.
#### `prettier` / `shfmt` / `rustfmt`
@@ -373,6 +373,14 @@ You can install `bat` using the [nix package manager](https://nixos.org/nix):
nix-env -i bat
```
### Via flox
You can install `bat` using [Flox](https://flox.dev)
```bash
flox install bat
```
### On openSUSE
You can install `bat` with zypper:
@@ -447,7 +455,7 @@ binaries are also available: look for archives with `musl` in the file name.
### From source
If you want to build `bat` from source, you need Rust 1.70.0 or
If you want to build `bat` from source, you need Rust 1.74.0 or
higher. You can then use `cargo` to build everything:
```bash
@@ -457,6 +465,12 @@ cargo install --locked bat
Note that additional files like the man page or shell completion
files can not be installed in this way. They will be generated by `cargo` and should be available in the cargo target folder (under `build`).
Shell completions are also available by running:
```bash
bat --completion <shell>
# see --help for supported shells
```
## Customization
### Highlighting theme
@@ -474,8 +488,10 @@ the following command (you need [`fzf`](https://github.com/junegunn/fzf) for thi
bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
```
`bat` looks good on a dark background by default. However, if your terminal uses a
light background, some themes like `GitHub` or `OneHalfLight` will work better for you.
`bat` automatically picks a fitting theme depending on your terminal's background color.
You can use the `--theme-light` / `--theme-light` options or the `BAT_THEME_DARK` / `BAT_THEME_LIGHT` environment variables
to customize the themes used. This is especially useful if you frequently switch between dark and light mode.
You can also use a custom theme by following the
['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes).
@@ -507,6 +523,16 @@ and line numbers but no grid and no file header. Set the `BAT_STYLE` environment
variable to make these changes permanent or use `bat`s
[configuration file](https://github.com/sharkdp/bat#configuration-file).
>[!tip]
> If you specify a default style in `bat`'s config file, you can change which components
> are displayed during a single run of `bat` using the `--style` command-line argument.
> By prefixing a component with `+` or `-`, it can be added or removed from the current style.
>
> For example, if your config contains `--style=full,-snip`, you can run bat with
> `--style=-grid,+snip` to remove the grid and add back the `snip` component.
> Or, if you want to override the styles completely, you use `--style=numbers` to
> only show the line numbers.
### Adding new syntaxes / language definitions
Should you find that a particular syntax is not available within `bat`, you can follow these
@@ -675,10 +701,11 @@ on your operating system. To get the default path for your system, call
bat --config-file
```
Alternatively, you can use the `BAT_CONFIG_PATH` environment variable to point `bat` to a
non-default location of the configuration file:
Alternatively, you can use `BAT_CONFIG_PATH` or `BAT_CONFIG_DIR` environment variables to point `bat`
to a non-default location of the configuration file or the configuration directory respectively:
```bash
export BAT_CONFIG_PATH="/path/to/bat.conf"
export BAT_CONFIG_PATH="/path/to/bat/bat.conf"
export BAT_CONFIG_DIR="/path/to/bat"
```
A default configuration file can be created with the `--generate-config-file` option.
@@ -729,7 +756,7 @@ your `PATH` or [define an environment variable](#using-a-different-pager). The [
Windows 10 natively supports colors in both `conhost.exe` (Command Prompt) and PowerShell since
[v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)), as
well as in newer versions of bash. On earlier versions of Windows, you can use
[Cmder](http://cmder.net/), which includes [ConEmu](https://conemu.github.io/).
[Cmder](http://cmder.app/), which includes [ConEmu](https://conemu.github.io/).
**Note:** Old versions of `less` do not correctly interpret colors on Windows. To fix this, you can add the optional Unix tools to your PATH when installing Git. If you dont have any other pagers installed, you can disable paging entirely by passing `--paging=never` or by setting `BAT_PAGER` to an empty string.
@@ -759,9 +786,14 @@ bat() {
If an input file contains color codes or other ANSI escape sequences or control characters, `bat` will have problems
performing syntax highlighting and text wrapping, and thus the output can become garbled.
When displaying such files it is recommended to disable both syntax highlighting and wrapping by
If your version of `bat` supports the `--strip-ansi=auto` option, it can be used to remove such sequences
before syntax highlighting. Alternatively, you may disable both syntax highlighting and wrapping by
passing the `--color=never --wrap=never` options to `bat`.
> [!NOTE]
> The `auto` option of `--strip-ansi` avoids removing escape sequences when the syntax is plain text.
### Terminals & colors
`bat` handles terminals *with* and *without* truecolor support. However, the colors in most syntax

Binary file not shown.

View File

@@ -37,6 +37,8 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
[CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
[CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.')
[CompletionResult]::new('--theme-dark', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for dark backgrounds.')
[CompletionResult]::new('--theme-light', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for light backgrounds.')
[CompletionResult]::new('--style', 'style', [CompletionResultType]::ParameterName, 'Comma-separated list of style elements to display (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).')
[CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
[CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')

View File

@@ -76,6 +76,7 @@ _bat() {
-m | --map-syntax | \
--ignored-suffix | \
--list-themes | \
--squeeze-limit | \
--line-range | \
-L | --list-languages | \
--lessopen | \
@@ -112,6 +113,13 @@ _bat() {
return 0
;;
--theme)
local IFS=$'\n'
COMPREPLY=($(compgen -W "auto${IFS}auto:always${IFS}auto:system${IFS}dark${IFS}light${IFS}$("$1" --list-themes)" -- "$cur"))
__bat_escape_completions
return 0
;;
--theme-dark | \
--theme-light)
local IFS=$'\n'
COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur"))
__bat_escape_completions
@@ -157,6 +165,7 @@ _bat() {
--diff-context
--tabs
--wrap
--chop-long-lines
--terminal-width
--number
--color
@@ -168,19 +177,27 @@ _bat() {
--map-syntax
--ignored-suffix
--theme
--theme-dark
--theme-light
--list-themes
--squeeze-blank
--squeeze-limit
--style
--line-range
--list-languages
--lessopen
--diagnostic
--acknowledgements
--set-terminal-title
--help
--version
--cache-dir
--config-dir
--config-file
--generate-config-file
--no-config
--no-custom-assets
--no-lessopen
" -- "$cur"))
return 0
fi

View File

@@ -129,10 +129,20 @@ set -l tabs_opts '
8\t
'
set -l special_themes '
auto\tdefault,\ Choose\ a\ theme\ based\ on\ dark\ or\ light\ mode
auto:always\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode
auto:system\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode
dark\tUse\ the\ theme\ specified\ by\ --theme-dark
light\tUse\ the\ theme\ specified\ by\ --theme-light
'
# Completions:
complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg
complete -c $bat -l cache-dir -f -d "Show bat's cache directory" -n __fish_is_first_arg
complete -c $bat -l color -x -a "$color_opts" -d "When to use colored output" -n __bat_no_excl_args
complete -c $bat -l config-dir -f -d "Display location of configuration directory" -n __fish_is_first_arg
@@ -201,7 +211,11 @@ complete -c $bat -l tabs -x -a "$tabs_opts" -d "Set tab width" -n __bat_no_excl_
complete -c $bat -l terminal-width -x -d "Set terminal <width>, +<offset>, or -<offset>" -n __bat_no_excl_args
complete -c $bat -l theme -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args
complete -c $bat -l theme -x -a "$special_themes(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args
complete -c $bat -l theme-dark -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for dark backgrounds" -n __bat_no_excl_args
complete -c $bat -l theme-light -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for light backgrounds" -n __bat_no_excl_args
complete -c $bat -s V -l version -f -d "Show version information" -n __fish_is_first_arg

View File

@@ -26,7 +26,7 @@ _{{PROJECT_EXECUTABLE}}_main() {
args=(
'(-A --show-all)'{-A,--show-all}'[show non-printable characters (space, tab, newline, ..)]'
--nonprintable-notation='[specify how to display non-printable characters when using --show-all]:notation:(caret unicode)'
\*{-p,--plain}'[show plain style (alias for `--style=plain`), repeat twice to disable disable automatic paging (alias for `--paging=never`)]'
\*{-p,--plain}'[show plain style (alias for `--style=plain`), repeat twice to disable automatic paging (alias for `--paging=never`)]'
'(-l --language)'{-l+,--language=}'[set the language for syntax highlighting]:language:->languages'
\*{-H+,--highlight-line=}'[highlight specified block of lines]:start\:end'
\*--file-name='[specify the name to display for a file]:name:_files'
@@ -42,12 +42,15 @@ _{{PROJECT_EXECUTABLE}}_main() {
--decorations='[specify when to show the decorations]:when:(auto never always)'
--paging='[specify when to use the pager]:when:(auto never always)'
'(-m --map-syntax)'{-m+,--map-syntax=}'[map a glob pattern to an existing syntax name]: :->syntax-maps'
'(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->themes'
'(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->theme_preferences'
'(--theme-dark)'--theme-dark='[set the color theme for syntax highlighting for dark backgrounds]:theme:->themes'
'(--theme-light)'--theme-light='[set the color theme for syntax highlighting for light backgrounds]:theme:->themes'
'(: --list-themes --list-languages -L)'--list-themes'[show all supported highlighting themes]'
--style='[comma-separated list of style elements to display]: : _values "style [default]"
default auto full plain changes header header-filename header-filesize grid rule numbers snip'
\*{-r+,--line-range=}'[only print the specified line range]:start\:end'
'(* -)'{-L,--list-languages}'[display all supported languages]'
-P'[disable paging]'
"--no-config[don't use the configuration file]"
"--no-custom-assets[don't load custom assets]"
'(--no-lessopen)'--lessopen'[enable the $LESSOPEN preprocessor]'
@@ -81,7 +84,13 @@ _{{PROJECT_EXECUTABLE}}_main() {
themes)
local -a themes expl
themes=( ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
themes=(${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
_wanted themes expl 'theme' compadd -a themes && ret=0
;;
theme_preferences)
local -a themes expl
themes=(auto dark light auto:always auto:system ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
_wanted themes expl 'theme' compadd -a themes && ret=0
;;

104
assets/manual/bat.1.in vendored
View File

@@ -87,6 +87,10 @@ Set the tab width to T spaces. Use a width of 0 to pass tabs through directly
Specify the text\-wrapping mode (*auto*, never, character). The '\-\-terminal\-width' option
can be used in addition to control the output width.
.HP
\fB\-S\fR, \fB\-\-chop\-long\-lines\fR
.IP
Truncate all lines longer than screen width. Alias for '\-\-wrap=never'.
.HP
\fB\-\-terminal\-width\fR <width>
.IP
Explicitly set the width of the terminal instead of determining it automatically. If
@@ -141,16 +145,58 @@ use -m '*.build:Python'. To highlight files named '.myignore' with the Git Ignor
syntax, use -m '.myignore:Git Ignore'.
Note that the right-hand side is the *name* of the syntax, not a file extension.
.HP
\fB\-\-ignored\-suffix\fR <ignored-suffix>
.IP
Ignore extension. For example: 'bat \-\-ignored-suffix ".dev" my_file.json.dev'
will use JSON syntax, and ignore '.dev'
.HP
\fB\-\-theme\fR <theme>
.IP
Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all available themes.
To set a default theme, add the '\-\-theme="..."' option to the configuration file or
export the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
Set the theme for syntax highlighting. Use \fB\-\-list\-themes\fP to see all available themes.
To set a default theme, add the \fB\-\-theme="..."\fP option to the configuration file or
export the \fBBAT_THEME\fP environment variable (e.g.: \fBexport BAT_THEME="..."\fP).
Special values:
.RS
.IP "auto (\fIdefault\fR)"
Picks a dark or light theme depending on the terminal's colors.
Use \fB-\-theme\-light\fR and \fB-\-theme\-dark\fR to customize the selected theme.
.IP "auto:always"
Variation of \fBauto\fR where where the terminal's colors are detected even when the output is redirected.
.IP "auto:system (macOS only)"
Variation of \fBauto\fR where the color scheme is detected from the system-wide preference instead.
.IP "dark"
Use the dark theme specified by \fB-\-theme-dark\fR.
.IP "light"
Use the light theme specified by \fB-\-theme-light\fR.
.RE
.HP
\fB\-\-theme\-dark\fR <theme>
.IP
Sets the theme name for syntax highlighting used when the terminal uses a dark background.
To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
export the \fBBAT_THEME_DARK\fP environment variable (e.g. \fBexport BAT_THEME_DARK="..."\fP).
This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBdark\fR.
.HP
\fB\-\-theme\-light\fR <theme>
.IP
Sets the theme name for syntax highlighting used when the terminal uses a dark background.
To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP).
This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR.
.HP
\fB\-\-list\-themes\fR
.IP
Display a list of supported themes for syntax highlighting.
.HP
\fB\-s\fR, \fB\-\-squeeze\-blank\fR
.IP
Squeeze consecutive empty lines into a single empty line.
.HP
\fB\-\-squeeze\-limit\fR <squeeze-limit>
.IP
Set the maximum number of consecutive empty lines to be printed.
.HP
\fB\-\-style\fR <style\-components>
.IP
Configure which elements (line numbers, file headers, grid borders, Git modifications,
@@ -184,6 +230,30 @@ Display a list of supported languages for syntax highlighting.
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered'). The output is
always unbuffered \- this option is simply ignored.
.HP
\fB\-\-no\-custom\-assets\fR
.IP
Do not load custom assets.
.HP
\fB\-\-config\-dir\fR
.IP
Show bat's configuration directory.
.HP
\fB\-\-cache\-dir\fR
.IP
Show bat's cache directory.
.HP
\fB\-\-diagnostic\fR
.IP
Show diagnostic information for bug reports.
.HP
\fB\-\-acknowledgements\fR
.IP
Show acknowledgements.
.HP
\fB\-\-set\-terminal\-title\fR
.IP
Sets terminal title to filenames when using a pager.
.HP
\fB\-h\fR, \fB\-\-help\fR
.IP
Print this help message.
@@ -212,6 +282,20 @@ location of the configuration file.
To generate a default configuration file, call:
\fB{{PROJECT_EXECUTABLE}} --generate-config-file\fR
These are related options:
.HP
\fB\-\-config\-file\fR
.IP
Show path to the configuration file.
.HP
\fB\-\-generate-config\-file\fR
.IP
Generates a default configuration file.
.HP
\fB\-\-no\-config\fR
.IP
Do not use the configuration file.
.SH "ADDING CUSTOM LANGUAGES"
{{PROJECT_EXECUTABLE}} supports Sublime Text \fB.sublime-syntax\fR language files, and can be
customized to add additional languages to your local installation. To do this, add the \fB.sublime-syntax\fR language
@@ -252,13 +336,23 @@ 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.
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
For more information, see the "INPUT PREPROCESSOR" section of less(1).
These are related options:
.HP
\fB\-\-lessopen\fR
.IP
Enable the $LESSOPEN preprocessor.
.HP
\fB\-\-no\-lessopen\fR
.IP
Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)
.PP
For more information, see the "INPUT PREPROCESSOR" section of less(1).
.SH "MORE INFORMATION"

22
assets/patches/1337.tmTheme.patch vendored Normal file
View File

@@ -0,0 +1,22 @@
diff --git themes/1337-Scheme/1337.tmTheme themes/1337-Scheme/1337.tmTheme
index fdff5bf..8cfc888 100644
--- themes/1337-Scheme/1337.tmTheme
+++ themes/1337-Scheme/1337.tmTheme
@@ -280,7 +280,7 @@ SOFTWARE.
<key>name</key>
<string>PHP Namespaces</string>
<key>scope</key>
- <string>support.other.namespace, entity.name.type.namespace</string>
+ <string>support.other.namespace, entity.name.type.namespace, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -561,7 +561,7 @@ SOFTWARE.
<key>name</key>
<string>diff.header</string>
<key>scope</key>
- <string>meta.diff, meta.diff.header</string>
+ <string>meta.diff, meta.diff.header, markup.heading</string>
<key>settings</key>
<dict>
<key>foreground</key>

View File

@@ -0,0 +1,14 @@
Submodule assets/syntaxes/01_Packages contains modified content
diff --git syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax
index 05a4fed6..78a7bf55 100644
--- syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax
+++ syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax
@@ -5,7 +5,7 @@ name: JavaScript
file_extensions:
- js
- htc
-first_line_match: ^#!\s*/.*\b(node|js)\b
+first_line_match: ^#!\s*/.*\b(node|bun|js)\b
scope: source.js
variables:
bin_digit: '[01_]'

2365
assets/patches/Lisp.sublime-syntax.patch vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
diff --git syntaxes/01_Packages/Markdown/Markdown.sublime-syntax syntaxes/01_Packages/Markdown/Markdown.sublime-syntax
index 19dc685d..44440c7f 100644
index 19dc685d..3a45ea05 100644
--- syntaxes/01_Packages/Markdown/Markdown.sublime-syntax
+++ syntaxes/01_Packages/Markdown/Markdown.sublime-syntax
@@ -24,7 +24,6 @@ variables:
@@ -166,7 +166,29 @@ index 19dc685d..44440c7f 100644
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.bold-italic.markdown
pop: true
@@ -1152,7 +1110,7 @@ contexts:
@@ -1073,6 +1031,21 @@ contexts:
escape: '{{code_fence_escape}}'
escape_captures:
0: meta.code-fence.definition.end.python.markdown-gfm
+ 1: punctuation.definition.raw.code-fence.end.markdown
+ - match: |-
+ (?x)
+ {{fenced_code_block_start}}
+ ((?i:puppet))
+ {{fenced_code_block_trailing_infostring_characters}}
+ captures:
+ 0: meta.code-fence.definition.begin.puppet.markdown-gfm
+ 2: punctuation.definition.raw.code-fence.begin.markdown
+ 5: constant.other.language-name.markdown
+ embed: scope:source.puppet
+ embed_scope: markup.raw.code-fence.puppet.markdown-gfm
+ escape: '{{code_fence_escape}}'
+ escape_captures:
+ 0: meta.code-fence.definition.end.puppet.markdown-gfm
1: punctuation.definition.raw.code-fence.end.markdown
- match: |-
(?x)
@@ -1152,7 +1125,7 @@ contexts:
- match: |-
(?x)
{{fenced_code_block_start}}

View File

@@ -0,0 +1,47 @@
diff --git themes/onehalf/sublimetext/OneHalfDark.tmTheme themes/onehalf/sublimetext/OneHalfDark.tmTheme
index b16050c..b021071 100644
--- themes/onehalf/sublimetext/OneHalfDark.tmTheme
+++ themes/onehalf/sublimetext/OneHalfDark.tmTheme
@@ -28,7 +28,7 @@
<plist version="1.0">
<dict>
<key>name</key>
- <string>OneHalfLight</string>
+ <string>OneHalfDark</string>
<key>semanticClass</key>
<string>theme.dark.one_half_dark</string>
<key>uuid</key>
@@ -155,7 +155,7 @@
<key>name</key>
<string>Classes</string>
<key>scope</key>
- <string>support.class, entity.name.class, entity.name.type.class</string>
+ <string>support.class, entity.name.class, entity.name.type.class, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -188,7 +188,7 @@
<key>name</key>
<string>Storage</string>
<key>scope</key>
- <string>storage</string>
+ <string>storage, meta.mapping.key string</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -309,7 +309,7 @@
<key>name</key>
<string>Markdown: Headings</string>
<key>scope</key>
- <string>markup.heading punctuation.definition.heading, entity.name.section</string>
+ <string>markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
@@ -660,4 +660,4 @@
</dict>
</array>
</dict>
-</plist>
\ No newline at end of file
+</plist>

View File

@@ -2,6 +2,24 @@ diff --git themes/TwoDark/TwoDark.tmTheme themes/TwoDark/TwoDark.tmTheme
index 87fd358..56376d3 100644
--- themes/TwoDark/TwoDark.tmTheme
+++ themes/TwoDark/TwoDark.tmTheme
@@ -125,7 +125,7 @@
<key>name</key>
<string>Classes</string>
<key>scope</key>
- <string>support.class, entity.name.class, entity.name.type.class</string>
+ <string>support.class, entity.name.class, entity.name.type.class, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -290,7 +290,7 @@
<key>name</key>
<string>Headings</string>
<key>scope</key>
- <string>markup.heading punctuation.definition.heading, entity.name.section</string>
+ <string>markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
@@ -533,7 +533,7 @@
<key>name</key>
<string>Json key</string>

BIN
assets/syntaxes.bin vendored

Binary file not shown.

View File

@@ -7,14 +7,14 @@ file_extensions:
- tsv
scope: text.csv
variables:
field_separator: (?:[,;\t])
field_separator: (?:[,;|\t])
record_separator: (?:$\n?)
contexts:
prototype:
- match: (?={{record_separator}})
pop: true
fields:
- match: ''
- match: ""
push:
- field_or_record_separator
- field4
@@ -26,15 +26,15 @@ contexts:
- field1
main:
- meta_include_prototype: false
- match: '^'
- match: "^"
set: fields
field_or_record_separator:
- meta_include_prototype: false
- match: '{{record_separator}}'
- match: "{{record_separator}}"
scope: punctuation.terminator.record.csv
pop: true
- match: '{{field_separator}}'
- match: "{{field_separator}}"
scope: punctuation.separator.sequence.csv
pop: true
@@ -56,23 +56,22 @@ contexts:
pop: true
field1:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-1.csv support.type
- include: field_contents
field2:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-2.csv support.function
- include: field_contents
field3:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-3.csv constant.numeric
- include: field_contents
field4:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-4.csv keyword.operator
- include: field_contents

View File

@@ -85,6 +85,9 @@ contexts:
options:
# command-line options like --option=value, --some-flag, or -x
- match: '^[ ]{7}(-)(?=\s)'
captures:
1: entity.name.command-line-option.man
- match: '^[ ]{7}(?=-|\+)'
push: expect-command-line-option
- match: '(?:[^a-zA-Z0-9_-]|^|\s){{command_line_option}}'

View File

@@ -131,6 +131,12 @@ OPTIONS
# ^^ - variable
output NUM (default 3) lines of copied context
- This is not really a switch, but indicates that standard input
# ^ entity.name.command-line-option.man
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - entity - variable
is coming from a file or a pipe and not interactively from the
command line.
EXAMPLE
#include <stdio.h>
# ^^^^^^^^ source.c meta.preprocessor.include keyword.control.import.include

BIN
assets/themes.bin vendored

Binary file not shown.

View File

@@ -69,7 +69,7 @@
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<string>entity.name.label, variable.parameter</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -80,7 +80,7 @@
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<string>support.class, entity.name.class, entity.name.type.class, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -234,7 +234,7 @@
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<string>markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>

View File

@@ -257,7 +257,7 @@
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<string>entity.name.tag, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -312,7 +312,7 @@
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<string>markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>

View File

@@ -256,7 +256,7 @@
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<string>entity.name.tag, entity.name</string>
<key>settings</key>
<dict>
<key>foreground</key>
@@ -311,7 +311,7 @@
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<string>markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>

View File

@@ -63,5 +63,22 @@ pub fn gen_man_and_comp() -> anyhow::Result<()> {
out_dir.join("assets/completions/bat.zsh"),
)?;
println!(
"cargo:rustc-env=BAT_GENERATED_COMPLETION_BASH={}",
out_dir.join("assets/completions/bat.bash").display()
);
println!(
"cargo:rustc-env=BAT_GENERATED_COMPLETION_FISH={}",
out_dir.join("assets/completions/bat.fish").display()
);
println!(
"cargo:rustc-env=BAT_GENERATED_COMPLETION_PS1={}",
out_dir.join("assets/completions/_bat.ps1").display()
);
println!(
"cargo:rustc-env=BAT_GENERATED_COMPLETION_ZSH={}",
out_dir.join("assets/completions/bat.zsh").display()
);
Ok(())
}

View File

@@ -366,7 +366,7 @@ ansible-galaxy install aeimer.install_bat
### From source
`bat` をソースからビルドしたいならば、Rust 1.70.0 以上の環境が必要です。
`bat` をソースからビルドしたいならば、Rust 1.74.0 以上の環境が必要です。
`cargo` を使用してビルドすることができます:
```bash

View File

@@ -416,7 +416,7 @@ scoop install bat
### 소스에서
`bat`의 소스를 빌드하기 위해서는, Rust 1.70.0 이상이 필요합니다.
`bat`의 소스를 빌드하기 위해서는, Rust 1.74.0 이상이 필요합니다.
`cargo`를 이용해 전부 빌드할 수 있습니다:
```bash

View File

@@ -344,7 +344,7 @@ ansible-galaxy install aeimer.install_bat
### Из исходников
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.70.0 или выше. После этого используйте `cargo`, чтобы все скомпилировать:
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.74.0 или выше. После этого используйте `cargo`, чтобы все скомпилировать:
```bash
cargo install --locked bat

View File

@@ -372,7 +372,7 @@ scoop install bat
### 从源码编译
如果你想要自己构建`bat`那么你需要安装有高于1.70.0版本的 Rust。
如果你想要自己构建`bat`那么你需要安装有高于1.74.0版本的 Rust。
使用以下命令编译。
@@ -412,7 +412,7 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
### 输出样式
你可以用`--style`参数来控制`bat`输出的样式。使用`--style=numbers,chanegs`可以只开启 Git 修改和行号显示而不添加其他内容。`BAT_STYLE`环境变量具有相同功能。
你可以用`--style`参数来控制`bat`输出的样式。使用`--style=numbers,changes`可以只开启 Git 修改和行号显示而不添加其他内容。`BAT_STYLE`环境变量具有相同功能。
### 添加新的语言和语法
@@ -616,63 +616,59 @@ iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat
注意: 当`bat`无法识别语言时你可能会需要`-l`/`--language`参数。
## Development
## 开发
```bash
# Recursive clone to retrieve all submodules
# 递归 clone 以获取所有子模块
git clone --recursive https://github.com/sharkdp/bat
# Build (debug version)
# 构建(调试版本)
cd bat
cargo build --bins
# Run unit tests and integration tests
# 运行单元测试和集成测试
cargo test
# Install (release version)
# 安装(发布版本)
cargo install --path . --locked
# Build a bat binary with modified syntaxes and themes
# 使用修改后的语法和主题构建一个 bat 二进制文件
bash assets/create.sh
cargo install --path . --locked --force
```
If you want to build an application that uses `bat`s pretty-printing
features as a library, check out the [the API documentation](https://docs.rs/bat/).
Note that you have to use either `regex-onig` or `regex-fancy` as a feature
when you depend on `bat` as a library.
如果你想构建一个使用 `bat` 美化打印功能的应用程序,请查看 [API 文档](https://docs.rs/bat/)。请注意,当你依赖 `bat` 作为库时,必须使用 `regex-onig` 或 `regex-fancy` 作为特性。
## Contributing
## 贡献指南
Take a look at the [`CONTRIBUTING.md`](CONTRIBUTING.md) guide.
请查看 [`CONTRIBUTING.md`](CONTRIBUTING.md) 指南。
## Maintainers
## 维护者
- [sharkdp](https://github.com/sharkdp)
- [eth-p](https://github.com/eth-p)
- [keith-hall](https://github.com/keith-hall)
- [Enselic](https://github.com/Enselic)
## Security vulnerabilities
## 安全漏洞
Please contact [David Peter](https://david-peter.de/) via email if you want to report a vulnerability in `bat`.
如果你想报告 `bat` 中的漏洞,请通过邮件联系 [David Peter](https://david-peter.de/)
## Project goals and alternatives
## 项目目标和替代方案
`bat` tries to achieve the following goals:
`bat` 试图实现以下目标:
- Provide beautiful, advanced syntax highlighting
- Integrate with Git to show file modifications
- Be a drop-in replacement for (POSIX) `cat`
- Offer a user-friendly command-line interface
- 提供美观的高级语法高亮
- 与 Git 集成以显示文件修改
- 成为 (POSIX) `cat` 的替代品
- 提供用户友好的命令行界面
There are a lot of alternatives, if you are looking for similar programs. See
[this document](doc/alternatives.md) for a comparison.
如果你在寻找类似的程序,有很多替代方案。请参阅[本文档](doc/alternatives.md)进行比较。
## License
## 许可证
Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat).
版权所有 (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat)
`bat` is made available under the terms of either the MIT License or the Apache License 2.0, at your option.
`bat` 可根据 MIT 许可证或 Apache 许可证 2.0 的条款使用,任选其一。
See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files for license details.
有关许可证的详细信息,请参阅 [LICENSE-APACHE](LICENSE-APACHE) [LICENSE-MIT](LICENSE-MIT) 文件。

View File

@@ -20,6 +20,13 @@ Options:
* unicode (␇, ␊, ␀, ..)
* caret (^G, ^J, ^@, ..)
--binary <behavior>
How to treat binary content. (default: no-printing)
Possible values:
* no-printing: do not print any binary content
* as-text: treat binary content as normal text
-p, --plain...
Only show plain style, no decorations. This is an alias for '--style=plain'. When '-p' is
used twice ('-pp'), it also disables automatic paging (alias for '--style=plain
@@ -112,6 +119,27 @@ Options:
Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To
set a default theme, add the '--theme="..."' option to the configuration file or export
the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
Special values:
* auto: Picks a dark or light theme depending on the terminal's colors (default).
Use '--theme-light' and '--theme-dark' to customize the selected theme.
* auto:always: Detect the terminal's colors even when the output is redirected.
* auto:system: Detect the color scheme from the system-wide preference (macOS only).
* dark: Use the dark theme specified by '--theme-dark'.
* light: Use the light theme specified by '--theme-light'.
--theme-light <theme>
Sets the theme name for syntax highlighting used when the terminal uses a light
background. Use '--list-themes' to see all available themes. To set a default theme, add
the '--theme-light="..." option to the configuration file or export the BAT_THEME_LIGHT
environment variable (e.g. export BAT_THEME_LIGHT="...").
--theme-dark <theme>
Sets the theme name for syntax highlighting used when the terminal uses a dark background.
Use '--list-themes' to see all available themes. To set a default theme, add the
'--theme-dark="..." option to the configuration file or export the BAT_THEME_DARK
environment variable (e.g. export BAT_THEME_DARK="...").
--list-themes
Display a list of supported themes for syntax highlighting.
@@ -122,6 +150,11 @@ Options:
--squeeze-limit <squeeze-limit>
Set the maximum number of consecutive empty lines to be printed.
--strip-ansi <when>
Specify when to strip ANSI escape sequences from the input. The automatic mode will remove
escape sequences unless the syntax highlighting language is plain text. Possible values:
auto, always, *never*.
--style <components>
Configure which elements (line numbers, file headers, grid borders, Git modifications, ..)
to display in addition to the file contents. The argument is a comma-separated list of
@@ -129,6 +162,12 @@ Options:
set a default style, add the '--style=".."' option to the configuration file or export the
BAT_STYLE environment variable (e.g.: export BAT_STYLE="..").
When styles are specified in multiple places, the "nearest" set of styles take precedence.
The command-line arguments are the highest priority, followed by the BAT_STYLE environment
variable, and then the configuration file. If any set of styles consists entirely of
components prefixed with "+" or "-", it will modify the previous set of styles instead of
replacing them.
By default, the following components are enabled:
changes, grid, header-filename, numbers, snip
@@ -163,6 +202,9 @@ Options:
This option exists for POSIX-compliance reasons ('u' is for 'unbuffered'). The output is
always unbuffered - this option is simply ignored.
--completion <SHELL>
Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]
--diagnostic
Show diagnostic information for bug reports.

View File

@@ -11,6 +11,8 @@ Options:
Show non-printable characters (space, tab, newline, ..).
--nonprintable-notation <notation>
Set notation for non-printable characters.
--binary <behavior>
How to treat binary content. (default: no-printing)
-p, --plain...
Show plain style (alias for '--style=plain').
-l, --language <language>
@@ -41,6 +43,10 @@ Options:
Use the specified syntax for files matching the glob pattern ('*.cpp:C++').
--theme <theme>
Set the color theme for syntax highlighting.
--theme-light <theme>
Sets the color theme for syntax highlighting used for light backgrounds.
--theme-dark <theme>
Sets the color theme for syntax highlighting used for dark backgrounds.
--list-themes
Display all supported highlighting themes.
-s, --squeeze-blank
@@ -52,6 +58,8 @@ Options:
Only print the lines from N to M.
-L, --list-languages
Display all supported languages.
--completion <SHELL>
Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]
-h, --help
Print help (see more with '--help')
-V, --version

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -13,6 +13,7 @@ use crate::error::*;
use crate::input::{InputReader, OpenedInput};
use crate::syntax_mapping::ignored_suffixes::IgnoredSuffixes;
use crate::syntax_mapping::MappingTarget;
use crate::theme::{default_theme, ColorScheme};
use crate::{bat_warning, SyntaxMapping};
use lazy_theme_set::LazyThemeSet;
@@ -69,57 +70,6 @@ impl HighlightingAssets {
}
}
/// The default theme.
///
/// ### Windows and Linux
///
/// Windows and most Linux distributions has a dark terminal theme by
/// default. On these platforms, this function always returns a theme that
/// looks good on a dark background.
///
/// ### macOS
///
/// On macOS the default terminal background is light, but it is common that
/// Dark Mode is active, which makes the terminal background dark. On this
/// platform, the default theme depends on
/// ```bash
/// defaults read -globalDomain AppleInterfaceStyle
/// ```
/// To avoid the overhead of the check on macOS, simply specify a theme
/// explicitly via `--theme`, `BAT_THEME`, or `~/.config/bat`.
///
/// See <https://github.com/sharkdp/bat/issues/1746> and
/// <https://github.com/sharkdp/bat/issues/1928> for more context.
pub fn default_theme() -> &'static str {
#[cfg(not(target_os = "macos"))]
{
Self::default_dark_theme()
}
#[cfg(target_os = "macos")]
{
if macos_dark_mode_active() {
Self::default_dark_theme()
} else {
Self::default_light_theme()
}
}
}
/**
* The default theme that looks good on a dark background.
*/
fn default_dark_theme() -> &'static str {
"Monokai Extended"
}
/**
* The default theme that looks good on a light background.
*/
#[cfg(target_os = "macos")]
fn default_light_theme() -> &'static str {
"Monokai Extended Light"
}
pub fn from_cache(cache_path: &Path) -> Result<Self> {
Ok(HighlightingAssets::new(
SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
@@ -248,7 +198,10 @@ impl HighlightingAssets {
bat_warning!("Unknown theme '{}', using default.", theme)
}
self.get_theme_set()
.get(self.fallback_theme.unwrap_or_else(Self::default_theme))
.get(
self.fallback_theme
.unwrap_or_else(|| default_theme(ColorScheme::Dark)),
)
.expect("something is very wrong if the default theme is missing")
}
}
@@ -399,26 +352,6 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
.map_err(|_| format!("Could not parse cached {description}").into())
}
#[cfg(target_os = "macos")]
fn macos_dark_mode_active() -> bool {
const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist";
const STYLE_KEY: &str = "AppleInterfaceStyle";
let preferences_file = home::home_dir()
.map(|home| home.join(PREFERENCES_FILE))
.expect("Could not get home directory");
match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) {
Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) {
Some(value) => value == "Dark",
// If the key does not exist, then light theme is currently in use.
None => false,
},
// Unreachable, in theory. All macOS users have a home directory and preferences file setup.
Ok(None) | Err(_) => true,
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -2,18 +2,22 @@ use std::collections::HashSet;
use std::env;
use std::io::IsTerminal;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use crate::{
clap_app,
config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars},
};
use bat::style::StyleComponentList;
use bat::theme::{theme, ThemeName, ThemeOptions, ThemePreference};
use bat::BinaryBehavior;
use bat::StripAnsiMode;
use clap::ArgMatches;
use console::Term;
use crate::input::{new_file_input, new_stdin_input};
use bat::{
assets::HighlightingAssets,
bat_warning,
config::{Config, VisibleLines},
error::*,
@@ -85,7 +89,6 @@ impl App {
// .. and the rest at the end
cli_args.for_each(|a| args.push(a));
args
};
@@ -95,12 +98,30 @@ impl App {
pub fn config(&self, inputs: &[Input]) -> Result<Config> {
let style_components = self.style_components()?;
let extra_plain = self.matches.get_count("plain") > 1;
let plain_last_index = self
.matches
.indices_of("plain")
.and_then(Iterator::max)
.unwrap_or_default();
let paging_last_index = self
.matches
.indices_of("paging")
.and_then(Iterator::max)
.unwrap_or_default();
let paging_mode = match self.matches.get_one::<String>("paging").map(|s| s.as_str()) {
Some("always") => PagingMode::Always,
Some("always") => {
// Disable paging if the second -p (or -pp) is specified after --paging=always
if extra_plain && plain_last_index > paging_last_index {
PagingMode::Never
} else {
PagingMode::Always
}
}
Some("never") => PagingMode::Never,
Some("auto") | None => {
// If we have -pp as an option when in auto mode, the pager should be disabled.
let extra_plain = self.matches.get_count("plain") > 1;
if extra_plain || self.matches.get_flag("no-paging") {
PagingMode::Never
} else if inputs.iter().any(Input::is_stdin) {
@@ -191,6 +212,11 @@ impl App {
Some("caret") => NonprintableNotation::Caret,
_ => unreachable!("other values for --nonprintable-notation are not allowed"),
},
binary: match self.matches.get_one::<String>("binary").map(|s| s.as_str()) {
Some("as-text") => BinaryBehavior::AsText,
Some("no-printing") => BinaryBehavior::NoPrinting,
_ => unreachable!("other values for --binary are not allowed"),
},
wrapping_mode: if self.interactive_output || maybe_term_width.is_some() {
if !self.matches.get_flag("chop-long-lines") {
match self.matches.get_one::<String>("wrap").map(|s| s.as_str()) {
@@ -242,18 +268,17 @@ impl App {
4
},
),
theme: self
strip_ansi: match self
.matches
.get_one::<String>("theme")
.map(String::from)
.map(|s| {
if s == "default" {
String::from(HighlightingAssets::default_theme())
} else {
s
}
})
.unwrap_or_else(|| String::from(HighlightingAssets::default_theme())),
.get_one::<String>("strip-ansi")
.map(|s| s.as_str())
{
Some("never") => StripAnsiMode::Never,
Some("always") => StripAnsiMode::Always,
Some("auto") => StripAnsiMode::Auto,
_ => unreachable!("other values for --strip-ansi are not allowed"),
},
theme: theme(self.theme_options()).to_string(),
visible_lines: match self.matches.try_contains_id("diff").unwrap_or_default()
&& self.matches.get_flag("diff")
{
@@ -353,34 +378,57 @@ impl App {
Ok(file_input)
}
fn forced_style_components(&self) -> Option<StyleComponents> {
// No components if `--decorations=never``.
if self
.matches
.get_one::<String>("decorations")
.map(|s| s.as_str())
== Some("never")
{
return Some(StyleComponents(HashSet::new()));
}
// Only line numbers if `--number`.
if self.matches.get_flag("number") {
return Some(StyleComponents(HashSet::from([
StyleComponent::LineNumbers,
])));
}
// Plain if `--plain` is specified at least once.
if self.matches.get_count("plain") > 0 {
return Some(StyleComponents(HashSet::from([StyleComponent::Plain])));
}
// Default behavior.
None
}
fn style_components(&self) -> Result<StyleComponents> {
let matches = &self.matches;
let mut styled_components = StyleComponents(
if matches.get_one::<String>("decorations").map(|s| s.as_str()) == Some("never") {
HashSet::new()
} else if matches.get_flag("number") {
[StyleComponent::LineNumbers].iter().cloned().collect()
} else if 0 < matches.get_count("plain") {
[StyleComponent::Plain].iter().cloned().collect()
} else {
matches
.get_one::<String>("style")
.map(|styles| {
styles
.split(',')
.map(|style| style.parse::<StyleComponent>())
.filter_map(|style| style.ok())
.collect::<Vec<_>>()
})
.unwrap_or_else(|| vec![StyleComponent::Default])
let mut styled_components = match self.forced_style_components() {
Some(forced_components) => forced_components,
// Parse the `--style` arguments and merge them.
None if matches.contains_id("style") => {
let lists = matches
.get_many::<String>("style")
.expect("styles present")
.map(|v| StyleComponentList::from_str(v))
.collect::<Result<Vec<StyleComponentList>>>()?;
StyleComponentList::to_components(lists, self.interactive_output, true)
}
// Use the default.
None => StyleComponents(HashSet::from_iter(
StyleComponent::Default
.components(self.interactive_output)
.into_iter()
.map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| {
acc.extend(components.iter().cloned());
acc
})
},
);
.cloned(),
)),
};
// If `grid` is set, remove `rule` as it is a subset of `grid`, and print a warning.
if styled_components.grid() && styled_components.0.remove(&StyleComponent::Rule) {
@@ -389,4 +437,25 @@ impl App {
Ok(styled_components)
}
fn theme_options(&self) -> ThemeOptions {
let theme = self
.matches
.get_one::<String>("theme")
.map(|t| ThemePreference::from_str(t).unwrap())
.unwrap_or_default();
let theme_dark = self
.matches
.get_one::<String>("theme-dark")
.map(|t| ThemeName::from_str(t).unwrap());
let theme_light = self
.matches
.get_one::<String>("theme-light")
.map(|t| ThemeName::from_str(t).unwrap());
ThemeOptions {
theme,
theme_dark,
theme_light,
}
}
}

View File

@@ -1,9 +1,11 @@
use bat::style::StyleComponentList;
use clap::{
crate_name, crate_version, value_parser, Arg, ArgAction, ArgGroup, ColorChoice, Command,
};
use once_cell::sync::Lazy;
use std::env;
use std::path::{Path, PathBuf};
use std::str::FromStr;
static VERSION: Lazy<String> = Lazy::new(|| {
#[cfg(feature = "bugreport")]
@@ -75,11 +77,26 @@ pub fn build_app(interactive_output: bool) -> Command {
* caret (^G, ^J, ^@, ..)",
),
)
.arg(
Arg::new("binary")
.long("binary")
.action(ArgAction::Set)
.default_value("no-printing")
.value_parser(["no-printing", "as-text"])
.value_name("behavior")
.hide_default_value(true)
.help("How to treat binary content. (default: no-printing)")
.long_help(
"How to treat binary content. (default: no-printing)\n\n\
Possible values:\n \
* no-printing: do not print any binary content\n \
* as-text: treat binary content as normal text",
),
)
.arg(
Arg::new("plain")
.overrides_with("plain")
.overrides_with("number")
.overrides_with("paging")
.short('p')
.long("plain")
.action(ArgAction::Count)
@@ -304,7 +321,6 @@ pub fn build_app(interactive_output: bool) -> Command {
.long("paging")
.overrides_with("paging")
.overrides_with("no-paging")
.overrides_with("plain")
.value_name("when")
.value_parser(["auto", "never", "always"])
.default_value("auto")
@@ -377,9 +393,40 @@ pub fn build_app(interactive_output: bool) -> Command {
see all available themes. To set a default theme, add the \
'--theme=\"...\"' option to the configuration file or export the \
BAT_THEME environment variable (e.g.: export \
BAT_THEME=\"...\").",
BAT_THEME=\"...\").\n\n\
Special values:\n\n \
* auto: Picks a dark or light theme depending on the terminal's colors (default).\n \
Use '--theme-light' and '--theme-dark' to customize the selected theme.\n \
* auto:always: Detect the terminal's colors even when the output is redirected.\n \
* auto:system: Detect the color scheme from the system-wide preference (macOS only).\n \
* dark: Use the dark theme specified by '--theme-dark'.\n \
* light: Use the light theme specified by '--theme-light'.",
),
)
.arg(
Arg::new("theme-light")
.long("theme-light")
.overrides_with("theme-light")
.value_name("theme")
.help("Sets the color theme for syntax highlighting used for light backgrounds.")
.long_help(
"Sets the theme name for syntax highlighting used when the terminal uses a light background. \
Use '--list-themes' to see all available themes. To set a default theme, add the \
'--theme-light=\"...\" option to the configuration file or export the BAT_THEME_LIGHT \
environment variable (e.g. export BAT_THEME_LIGHT=\"...\")."),
)
.arg(
Arg::new("theme-dark")
.long("theme-dark")
.overrides_with("theme-dark")
.value_name("theme")
.help("Sets the color theme for syntax highlighting used for dark backgrounds.")
.long_help(
"Sets the theme name for syntax highlighting used when the terminal uses a dark background. \
Use '--list-themes' to see all available themes. To set a default theme, add the \
'--theme-dark=\"...\" option to the configuration file or export the BAT_THEME_DARK \
environment variable (e.g. export BAT_THEME_DARK=\"...\")."),
)
.arg(
Arg::new("list-themes")
.long("list-themes")
@@ -402,37 +449,30 @@ pub fn build_app(interactive_output: bool) -> Command {
.long_help("Set the maximum number of consecutive empty lines to be printed.")
.hide_short_help(true)
)
.arg(
Arg::new("strip-ansi")
.long("strip-ansi")
.overrides_with("strip-ansi")
.value_name("when")
.value_parser(["auto", "always", "never"])
.default_value("never")
.hide_default_value(true)
.help("Strip colors from the input (auto, always, *never*)")
.long_help("Specify when to strip ANSI escape sequences from the input. \
The automatic mode will remove escape sequences unless the syntax highlighting \
language is plain text. Possible values: auto, always, *never*.")
.hide_short_help(true)
)
.arg(
Arg::new("style")
.long("style")
.action(ArgAction::Append)
.value_name("components")
.overrides_with("style")
.overrides_with("plain")
.overrides_with("number")
// Cannot use claps built in validation because we have to turn off clap's delimiters
.value_parser(|val: &str| {
let mut invalid_vals = val.split(',').filter(|style| {
!&[
"auto",
"full",
"default",
"plain",
"header",
"header-filename",
"header-filesize",
"grid",
"rule",
"numbers",
"snip",
#[cfg(feature = "git")]
"changes",
].contains(style)
});
if let Some(invalid) = invalid_vals.next() {
Err(format!("Unknown style, '{invalid}'"))
} else {
Ok(val.to_owned())
match StyleComponentList::from_str(val) {
Err(err) => Err(err),
Ok(_) => Ok(val.to_owned()),
}
})
.help(
@@ -447,6 +487,12 @@ pub fn build_app(interactive_output: bool) -> Command {
pre-defined style ('full'). To set a default style, add the \
'--style=\"..\"' option to the configuration file or export the \
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
When styles are specified in multiple places, the \"nearest\" set \
of styles take precedence. The command-line arguments are the highest \
priority, followed by the BAT_STYLE environment variable, and then \
the configuration file. If any set of styles consists entirely of \
components prefixed with \"+\" or \"-\", it will modify the \
previous set of styles instead of replacing them.\n\n\
By default, the following components are enabled:\n \
changes, grid, header-filename, numbers, snip\n\n\
Possible values:\n\n \
@@ -518,6 +564,17 @@ pub fn build_app(interactive_output: bool) -> Command {
.help("Do not load custom assets"),
);
#[cfg(feature = "application")]
{
app = app.arg(
Arg::new("completion")
.long("completion")
.value_name("SHELL")
.value_parser(["bash", "fish", "ps1", "zsh"])
.help("Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]"),
);
}
#[cfg(feature = "lessopen")]
{
app = app

View File

@@ -0,0 +1,6 @@
use std::env;
pub const BASH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_BASH"));
pub const FISH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_FISH"));
pub const PS1_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_PS1"));
pub const ZSH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_ZSH"));

View File

@@ -140,14 +140,19 @@ fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseE
pub fn get_args_from_env_vars() -> Vec<OsString> {
[
("--tabs", "BAT_TABS"),
("--theme", "BAT_THEME"),
("--theme", bat::theme::env::BAT_THEME),
("--theme-dark", bat::theme::env::BAT_THEME_DARK),
("--theme-light", bat::theme::env::BAT_THEME_LIGHT),
("--pager", "BAT_PAGER"),
("--paging", "BAT_PAGING"),
("--style", "BAT_STYLE"),
]
.iter()
.filter_map(|(flag, key)| env::var(key).ok().map(|var| [flag.to_string(), var]))
.flatten()
.filter_map(|(flag, key)| {
env::var(key)
.ok()
.map(|var| [flag.to_string(), var].join("="))
})
.map(|a| a.into())
.collect()
}

View File

@@ -3,6 +3,8 @@
mod app;
mod assets;
mod clap_app;
#[cfg(feature = "application")]
mod completions;
mod config;
mod directories;
mod input;
@@ -14,6 +16,7 @@ use std::io::{BufReader, Write};
use std::path::Path;
use std::process;
use bat::theme::DetectColorScheme;
use nu_ansi_term::Color::Green;
use nu_ansi_term::Style;
@@ -35,6 +38,7 @@ use bat::{
error::*,
input::Input,
style::{StyleComponent, StyleComponents},
theme::{color_scheme, default_theme, ColorScheme},
MappingTarget, PagingMode,
};
@@ -188,7 +192,12 @@ fn theme_preview_file<'a>() -> Input<'a> {
Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA)))
}
pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<()> {
pub fn list_themes(
cfg: &Config,
config_dir: &Path,
cache_dir: &Path,
detect_color_scheme: DetectColorScheme,
) -> Result<()> {
let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?;
let mut config = cfg.clone();
let mut style = HashSet::new();
@@ -199,19 +208,35 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
let stdout = io::stdout();
let mut stdout = stdout.lock();
if config.colored_output {
for theme in assets.themes() {
let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
for theme in assets.themes() {
let default_theme_info = if !config.loop_through && default_theme_name == theme {
" (default)"
} else if default_theme(ColorScheme::Dark) == theme {
" (default dark)"
} else if default_theme(ColorScheme::Light) == theme {
" (default light)"
} else {
""
};
if config.colored_output {
writeln!(
stdout,
"Theme: {}\n",
Style::new().bold().paint(theme.to_string())
"Theme: {}{}\n",
Style::new().bold().paint(theme.to_string()),
default_theme_info
)?;
config.theme = theme.to_string();
Controller::new(&config, &assets)
.run(vec![theme_preview_file()], None)
.ok();
writeln!(stdout)?;
} else {
writeln!(stdout, "{theme}{default_theme_info}")?;
}
}
if config.colored_output {
writeln!(
stdout,
"Further themes can be installed to '{}', \
@@ -220,10 +245,6 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
https://github.com/sharkdp/bat#adding-new-themes",
config_dir.join("themes").to_string_lossy()
)?;
} else {
for theme in assets.themes() {
writeln!(stdout, "{theme}")?;
}
}
Ok(())
@@ -272,24 +293,25 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
.info(OperatingSystem::default())
.info(CommandLine::default())
.info(EnvironmentVariables::list(&[
"SHELL",
"PAGER",
"LESS",
"LANG",
"LC_ALL",
"BAT_PAGER",
"BAT_PAGING",
"BAT_CACHE_PATH",
"BAT_CONFIG_PATH",
"BAT_OPTS",
"BAT_PAGER",
"BAT_PAGING",
"BAT_STYLE",
"BAT_TABS",
"BAT_THEME",
"XDG_CONFIG_HOME",
"XDG_CACHE_HOME",
"COLORTERM",
"NO_COLOR",
"LANG",
"LC_ALL",
"LESS",
"MANPAGER",
"NO_COLOR",
"PAGER",
"SHELL",
"TERM",
"XDG_CACHE_HOME",
"XDG_CONFIG_HOME",
]))
.info(FileContent::new("System Config file", system_config_file()))
.info(FileContent::new("Config file", config_file()))
@@ -327,6 +349,18 @@ fn run() -> Result<bool> {
return Ok(true);
}
#[cfg(feature = "application")]
if let Some(shell) = app.matches.get_one::<String>("completion") {
match shell.as_str() {
"bash" => println!("{}", completions::BASH_COMPLETION),
"fish" => println!("{}", completions::FISH_COMPLETION),
"ps1" => println!("{}", completions::PS1_COMPLETION),
"zsh" => println!("{}", completions::ZSH_COMPLETION),
_ => unreachable!("No completion for shell '{}' available.", shell),
}
return Ok(true);
}
match app.matches.subcommand() {
Some(("cache", cache_matches)) => {
// If there is a file named 'cache' in the current working directory,
@@ -361,7 +395,7 @@ fn run() -> Result<bool> {
};
run_controller(inputs, &plain_config, cache_dir)
} else if app.matches.get_flag("list-themes") {
list_themes(&config, config_dir, cache_dir)?;
list_themes(&config, config_dir, cache_dir, DetectColorScheme::default())?;
Ok(true)
} else if app.matches.get_flag("config-file") {
println!("{}", config_file().to_string_lossy());

View File

@@ -1,10 +1,11 @@
use crate::line_range::{HighlightedLineRanges, LineRanges};
use crate::nonprintable_notation::NonprintableNotation;
use crate::nonprintable_notation::{BinaryBehavior, NonprintableNotation};
#[cfg(feature = "paging")]
use crate::paging::PagingMode;
use crate::style::StyleComponents;
use crate::syntax_mapping::SyntaxMapping;
use crate::wrapping::WrappingMode;
use crate::StripAnsiMode;
#[derive(Debug, Clone)]
pub enum VisibleLines {
@@ -43,6 +44,9 @@ pub struct Config<'a> {
/// The configured notation for non-printable characters
pub nonprintable_notation: NonprintableNotation,
/// How to treat binary content
pub binary: BinaryBehavior,
/// The character width of the terminal
pub term_width: usize,
@@ -100,6 +104,9 @@ pub struct Config<'a> {
/// The maximum number of consecutive empty lines to display
pub squeeze_lines: Option<usize>,
// Weather or not to set terminal title when using a pager
pub strip_ansi: StripAnsiMode,
}
#[cfg(all(feature = "minimal-application", feature = "paging"))]

View File

@@ -3,13 +3,12 @@
use std::convert::TryFrom;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader, Cursor, Read, Write};
use std::io::{BufRead, BufReader, Cursor, Read};
use std::path::PathBuf;
use std::str;
use std::process::{ExitStatus, Stdio};
use clircle::{Clircle, Identifier};
use os_str_bytes::RawOsString;
use run_script::{IoOptions, ScriptOptions};
use execute::{shell, Execute};
use crate::error::Result;
use crate::{
@@ -21,7 +20,6 @@ use crate::{
pub(crate) struct LessOpenPreprocessor {
lessopen: String,
lessclose: Option<String>,
command_options: ScriptOptions,
kind: LessOpenKind,
/// Whether or not data piped via stdin is to be preprocessed
preprocess_stdin: bool,
@@ -52,7 +50,7 @@ impl LessOpenPreprocessor {
// Otherwise, if output is empty and exit code is nonzero, use original file contents
let (kind, lessopen) = if lessopen.starts_with("||") {
(LessOpenKind::Piped, lessopen.chars().skip(2).collect())
// "|" means pipe, but ignore exit code, always using preprocessor output
// "|" means pipe as above, but ignore exit code and always use preprocessor output even if empty
} else if lessopen.starts_with('|') {
(
LessOpenKind::PipedIgnoreExitCode,
@@ -70,16 +68,9 @@ impl LessOpenPreprocessor {
(false, lessopen)
};
let mut command_options = ScriptOptions::new();
command_options.runner = env::var("SHELL").ok();
command_options.input_redirection = IoOptions::Pipe;
Ok(Self {
lessopen: lessopen.replacen("%s", "$1", 1),
lessclose: env::var("LESSCLOSE")
.ok()
.map(|str| str.replacen("%s", "$1", 1).replacen("%s", "$2", 1)),
command_options,
lessopen,
lessclose: env::var("LESSCLOSE").ok(),
kind,
preprocess_stdin: stdin,
})
@@ -98,21 +89,21 @@ impl LessOpenPreprocessor {
None => return input.open(stdin, stdout_identifier),
};
let (exit_code, lessopen_stdout, _) = match run_script::run(
&self.lessopen,
&vec![path_str.to_string()],
&self.command_options,
) {
let mut lessopen_command = shell(self.lessopen.replacen("%s", path_str, 1));
lessopen_command.stdout(Stdio::piped());
let lessopen_output = match lessopen_command.execute_output() {
Ok(output) => output,
Err(_) => return input.open(stdin, stdout_identifier),
};
if self.fall_back_to_original_file(&lessopen_stdout, exit_code) {
if self.fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status)
{
return input.open(stdin, stdout_identifier);
}
(
RawOsString::from_string(lessopen_stdout),
lessopen_output.stdout,
path_str.to_string(),
OpenedInputKind::OrdinaryFile(path.to_path_buf()),
)
@@ -127,47 +118,31 @@ impl LessOpenPreprocessor {
}
}
// stdin isn't Clone, so copy it to a cloneable buffer
// stdin isn't Clone or AsRef<[u8]>, so move it into a cloneable buffer
// so the data can be used multiple times if necessary
// NOTE: stdin will be empty from this point onwards
let mut stdin_buffer = Vec::new();
stdin.read_to_end(&mut stdin_buffer).unwrap();
stdin.read_to_end(&mut stdin_buffer)?;
let mut lessopen_handle = match run_script::spawn(
&self.lessopen,
&vec!["-".to_string()],
&self.command_options,
) {
Ok(handle) => handle,
Err(_) => {
return input.open(stdin, stdout_identifier);
}
};
let mut lessopen_command = shell(self.lessopen.replacen("%s", "-", 1));
lessopen_command.stdout(Stdio::piped());
if lessopen_handle
.stdin
.as_mut()
.unwrap()
.write_all(&stdin_buffer.clone())
.is_err()
let lessopen_output = match lessopen_command.execute_input_output(&stdin_buffer)
{
return input.open(stdin, stdout_identifier);
}
let lessopen_output = match lessopen_handle.wait_with_output() {
Ok(output) => output,
Err(_) => {
return input.open(Cursor::new(stdin_buffer), stdout_identifier);
}
};
if lessopen_output.stdout.is_empty()
&& (!lessopen_output.status.success()
|| matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
if self
.fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status)
{
return input.open(Cursor::new(stdin_buffer), stdout_identifier);
}
(
RawOsString::assert_from_raw_vec(lessopen_output.stdout),
lessopen_output.stdout,
"-".to_string(),
OpenedInputKind::StdIn,
)
@@ -184,13 +159,17 @@ impl LessOpenPreprocessor {
kind,
reader: InputReader::new(BufReader::new(
if matches!(self.kind, LessOpenKind::TempFile) {
// Remove newline at end of temporary file path returned by $LESSOPEN
let stdout = match lessopen_stdout.strip_suffix("\n") {
Some(stripped) => stripped.to_owned(),
None => lessopen_stdout,
let lessopen_string = match String::from_utf8(lessopen_stdout) {
Ok(string) => string,
Err(_) => {
return input.open(stdin, stdout_identifier);
}
};
// Remove newline at end of temporary file path returned by $LESSOPEN
let stdout = match lessopen_string.strip_suffix("\n") {
Some(stripped) => stripped.to_owned(),
None => lessopen_string,
};
let stdout = stdout.into_os_string();
let file = match File::open(PathBuf::from(&stdout)) {
Ok(file) => file,
@@ -201,16 +180,18 @@ impl LessOpenPreprocessor {
Preprocessed {
kind: PreprocessedKind::TempFile(file),
lessclose: self.lessclose.clone(),
command_args: vec![path_str, stdout.to_str().unwrap().to_string()],
command_options: self.command_options.clone(),
lessclose: self
.lessclose
.as_ref()
.map(|s| s.replacen("%s", &path_str, 1).replacen("%s", &stdout, 1)),
}
} else {
Preprocessed {
kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout.into_raw_vec())),
lessclose: self.lessclose.clone(),
command_args: vec![path_str, "-".to_string()],
command_options: self.command_options.clone(),
kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout)),
lessclose: self
.lessclose
.as_ref()
.map(|s| s.replacen("%s", &path_str, 1).replacen("%s", "-", 1)),
}
},
)),
@@ -219,9 +200,9 @@ impl LessOpenPreprocessor {
})
}
fn fall_back_to_original_file(&self, lessopen_output: &str, exit_code: i32) -> bool {
lessopen_output.is_empty()
&& (exit_code != 0 || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
fn fall_back_to_original_file(&self, lessopen_stdout: &Vec<u8>, exit_code: ExitStatus) -> bool {
lessopen_stdout.is_empty()
&& (!exit_code.success() || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
}
#[cfg(test)]
@@ -261,8 +242,6 @@ impl Read for PreprocessedKind {
pub struct Preprocessed {
kind: PreprocessedKind,
lessclose: Option<String>,
command_args: Vec<String>,
command_options: ScriptOptions,
}
impl Read for Preprocessed {
@@ -273,11 +252,20 @@ impl Read for Preprocessed {
impl Drop for Preprocessed {
fn drop(&mut self) {
if let Some(ref command) = self.lessclose {
self.command_options.output_redirection = IoOptions::Inherit;
if let Some(lessclose) = self.lessclose.clone() {
let mut lessclose_command = shell(lessclose);
run_script::run(command, &self.command_args, &self.command_options)
.expect("failed to run $LESSCLOSE to clean up file");
let lessclose_output = match lessclose_command.execute_output() {
Ok(output) => output,
Err(_) => {
bat_warning!("failed to run $LESSCLOSE to clean up temporary file");
return;
}
};
if lessclose_output.status.success() {
bat_warning!("$LESSCLOSE exited with nonzero exit code",)
};
}
}
}
@@ -301,7 +289,7 @@ mod tests {
fn test_just_lessopen() -> Result<()> {
let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(preprocessor.lessclose.is_none());
reset_env_vars();
@@ -327,8 +315,8 @@ mod tests {
let preprocessor =
LessOpenPreprocessor::mock_new(Some("lessopen.sh %s"), Some("lessclose.sh %s %s"))?;
assert_eq!(preprocessor.lessopen, "lessopen.sh $1");
assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh $1 $2");
assert_eq!(preprocessor.lessopen, "lessopen.sh %s");
assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh %s %s");
reset_env_vars();
@@ -340,13 +328,13 @@ mod tests {
fn test_lessopen_prefixes() -> Result<()> {
let preprocessor = LessOpenPreprocessor::mock_new(Some("batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(preprocessor.kind, LessOpenKind::TempFile));
assert!(!preprocessor.preprocess_stdin);
let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(
preprocessor.kind,
LessOpenKind::PipedIgnoreExitCode
@@ -355,19 +343,19 @@ mod tests {
let preprocessor = LessOpenPreprocessor::mock_new(Some("||batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(preprocessor.kind, LessOpenKind::Piped));
assert!(!preprocessor.preprocess_stdin);
let preprocessor = LessOpenPreprocessor::mock_new(Some("-batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(preprocessor.kind, LessOpenKind::TempFile));
assert!(preprocessor.preprocess_stdin);
let preprocessor = LessOpenPreprocessor::mock_new(Some("|-batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(
preprocessor.kind,
LessOpenKind::PipedIgnoreExitCode
@@ -376,7 +364,7 @@ mod tests {
let preprocessor = LessOpenPreprocessor::mock_new(Some("||-batpipe %s"), None)?;
assert_eq!(preprocessor.lessopen, "batpipe $1");
assert_eq!(preprocessor.lessopen, "batpipe %s");
assert!(matches!(preprocessor.kind, LessOpenKind::Piped));
assert!(preprocessor.preprocess_stdin);
@@ -391,8 +379,8 @@ mod tests {
let preprocessor =
LessOpenPreprocessor::mock_new(Some("|echo File:%s"), Some("echo File:%s Temp:%s"))?;
assert_eq!(preprocessor.lessopen, "echo File:$1");
assert_eq!(preprocessor.lessclose.unwrap(), "echo File:$1 Temp:$2");
assert_eq!(preprocessor.lessopen, "echo File:%s");
assert_eq!(preprocessor.lessclose.unwrap(), "echo File:%s Temp:%s");
reset_env_vars();

View File

@@ -49,10 +49,12 @@ pub(crate) mod printer;
pub mod style;
pub(crate) mod syntax_mapping;
mod terminal;
pub mod theme;
mod vscreen;
pub(crate) mod wrapping;
pub use nonprintable_notation::NonprintableNotation;
pub use nonprintable_notation::{BinaryBehavior, NonprintableNotation};
pub use preprocessor::StripAnsiMode;
pub use pretty_printer::{Input, PrettyPrinter, Syntax};
pub use syntax_mapping::{MappingTarget, SyntaxMapping};
pub use wrapping::WrappingMode;

View File

@@ -10,3 +10,15 @@ pub enum NonprintableNotation {
#[default]
Unicode,
}
/// How to treat binary content
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BinaryBehavior {
/// Do not print any binary content
#[default]
NoPrinting,
/// Treat binary content as normal text
AsText,
}

View File

@@ -1,17 +1,18 @@
use std::fmt::Write;
use console::AnsiCodeIterator;
use crate::nonprintable_notation::NonprintableNotation;
use crate::{
nonprintable_notation::NonprintableNotation,
vscreen::{EscapeSequenceOffsets, EscapeSequenceOffsetsIterator},
};
/// Expand tabs like an ANSI-enabled expand(1).
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2);
for chunk in AnsiCodeIterator::new(line) {
match chunk {
(text, true) => buffer.push_str(text),
(mut text, false) => {
for seq in EscapeSequenceOffsetsIterator::new(line) {
match seq {
EscapeSequenceOffsets::Text { .. } => {
let mut text = &line[seq.index_of_start()..seq.index_past_end()];
while let Some(index) = text.find('\t') {
// Add previous text.
if index > 0 {
@@ -31,6 +32,10 @@ pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
*cursor += text.len();
buffer.push_str(text);
}
_ => {
// Copy the ANSI escape sequence.
buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()])
}
}
}
@@ -131,6 +136,27 @@ pub fn replace_nonprintable(
output
}
/// Strips ANSI escape sequences from the input.
pub fn strip_ansi(line: &str) -> String {
let mut buffer = String::with_capacity(line.len());
for seq in EscapeSequenceOffsetsIterator::new(line) {
if let EscapeSequenceOffsets::Text { .. } = seq {
buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()]);
}
}
buffer
}
#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub enum StripAnsiMode {
#[default]
Never,
Always,
Auto,
}
#[test]
fn test_try_parse_utf8_char() {
assert_eq!(try_parse_utf8_char(&[0x20]), Some((' ', 1)));
@@ -174,3 +200,14 @@ fn test_try_parse_utf8_char() {
assert_eq!(try_parse_utf8_char(&[0xef, 0x20]), None);
assert_eq!(try_parse_utf8_char(&[0xf0, 0xf0]), None);
}
#[test]
fn test_strip_ansi() {
// The sequence detection is covered by the tests in the vscreen module.
assert_eq!(strip_ansi("no ansi"), "no ansi");
assert_eq!(strip_ansi("\x1B[33mone"), "one");
assert_eq!(
strip_ansi("\x1B]1\x07multiple\x1B[J sequences"),
"multiple sequences"
);
}

View File

@@ -11,7 +11,7 @@ use crate::{
input,
line_range::{HighlightedLineRanges, LineRange, LineRanges},
style::StyleComponent,
SyntaxMapping, WrappingMode,
StripAnsiMode, SyntaxMapping, WrappingMode,
};
#[cfg(feature = "paging")]
@@ -182,6 +182,15 @@ impl<'a> PrettyPrinter<'a> {
self
}
/// Whether to remove ANSI escape sequences from the input (default: never)
///
/// If `Auto` is used, escape sequences will only be removed when the input
/// is not plain text.
pub fn strip_ansi(&mut self, mode: StripAnsiMode) -> &mut Self {
self.config.strip_ansi = mode;
self
}
/// Text wrapping mode (default: do not wrap)
pub fn wrapping_mode(&mut self, mode: WrappingMode) -> &mut Self {
self.config.wrapping_mode = mode;
@@ -236,7 +245,9 @@ impl<'a> PrettyPrinter<'a> {
self
}
/// Specify the highlighting theme
/// Specify the highlighting theme.
/// You can use [`crate::theme::theme`] to pick a theme based on user preferences
/// and the terminal's background color.
pub fn theme(&mut self, theme: impl AsRef<str>) -> &mut Self {
self.config.theme = theme.as_ref().to_owned();
self
@@ -270,6 +281,11 @@ impl<'a> PrettyPrinter<'a> {
/// If you want to call 'print' multiple times, you have to call the appropriate
/// input_* methods again.
pub fn print(&mut self) -> Result<bool> {
self.print_with_writer(None::<&mut dyn std::fmt::Write>)
}
/// Pretty-print all specified inputs to a specified writer.
pub fn print_with_writer<W: std::fmt::Write>(&mut self, writer: Option<W>) -> Result<bool> {
let highlight_lines = std::mem::take(&mut self.highlighted_lines);
self.config.highlighted_lines = HighlightedLineRanges(LineRanges::from(highlight_lines));
self.config.term_width = self
@@ -306,7 +322,13 @@ impl<'a> PrettyPrinter<'a> {
// Run the controller
let controller = Controller::new(&self.config, &self.assets);
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
// If writer is provided, pass it to the controller, otherwise pass None
if let Some(mut w) = writer {
controller.run(inputs.into_iter().map(|i| i.into()).collect(), Some(&mut w))
} else {
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
}
}
}

View File

@@ -29,11 +29,14 @@ use crate::diff::LineChanges;
use crate::error::*;
use crate::input::OpenedInput;
use crate::line_range::RangeCheckResult;
use crate::preprocessor::strip_ansi;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
use crate::vscreen::{AnsiStyle, EscapeSequence, EscapeSequenceIterator};
use crate::wrapping::WrappingMode;
use crate::BinaryBehavior;
use crate::StripAnsiMode;
const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI {
raw_sequence: "\x1B[4m",
@@ -207,6 +210,7 @@ pub(crate) struct InteractivePrinter<'a> {
highlighter_from_set: Option<HighlighterFromSet<'a>>,
background_color_highlight: Option<Color>,
consecutive_empty_lines: usize,
strip_ansi: bool,
}
impl<'a> InteractivePrinter<'a> {
@@ -265,20 +269,42 @@ impl<'a> InteractivePrinter<'a> {
.content_type
.map_or(false, |c| c.is_binary() && !config.show_nonprintable);
let highlighter_from_set = if is_printing_binary || !config.colored_output {
None
} else {
// Determine the type of syntax for highlighting
let syntax_in_set =
match assets.get_syntax(config.language, input, &config.syntax_mapping) {
Ok(syntax_in_set) => syntax_in_set,
Err(Error::UndetectedSyntax(_)) => assets
.find_syntax_by_name("Plain Text")?
.expect("A plain text syntax is available"),
Err(e) => return Err(e),
};
let needs_to_match_syntax = (!is_printing_binary
|| matches!(config.binary, BinaryBehavior::AsText))
&& (config.colored_output || config.strip_ansi == StripAnsiMode::Auto);
Some(HighlighterFromSet::new(syntax_in_set, theme))
let (is_plain_text, highlighter_from_set) = if needs_to_match_syntax {
// Determine the type of syntax for highlighting
const PLAIN_TEXT_SYNTAX: &str = "Plain Text";
match assets.get_syntax(config.language, input, &config.syntax_mapping) {
Ok(syntax_in_set) => (
syntax_in_set.syntax.name == PLAIN_TEXT_SYNTAX,
Some(HighlighterFromSet::new(syntax_in_set, theme)),
),
Err(Error::UndetectedSyntax(_)) => (
true,
Some(
assets
.find_syntax_by_name(PLAIN_TEXT_SYNTAX)?
.map(|s| HighlighterFromSet::new(s, theme))
.expect("A plain text syntax is available"),
),
),
Err(e) => return Err(e),
}
} else {
(false, None)
};
// Determine when to strip ANSI sequences
let strip_ansi = match config.strip_ansi {
_ if config.show_nonprintable => false,
StripAnsiMode::Always => true,
StripAnsiMode::Auto if is_plain_text => false, // Plain text may already contain escape sequences.
StripAnsiMode::Auto => true,
_ => false,
};
Ok(InteractivePrinter {
@@ -293,6 +319,7 @@ impl<'a> InteractivePrinter<'a> {
highlighter_from_set,
background_color_highlight,
consecutive_empty_lines: 0,
strip_ansi,
})
}
@@ -433,7 +460,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
if !self.config.style_components.header() {
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
if Some(ContentType::BINARY) == self.content_type
&& !self.config.show_nonprintable
&& !matches!(self.config.binary, BinaryBehavior::AsText)
{
writeln!(
handle,
"{}: Binary content from {} will not be printed to the terminal \
@@ -514,7 +544,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
})?;
if self.config.style_components.grid() {
if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable {
if self.content_type.map_or(false, |c| c.is_text())
|| self.config.show_nonprintable
|| matches!(self.config.binary, BinaryBehavior::AsText)
{
self.print_horizontal_line(handle, '┼')?;
} else {
self.print_horizontal_line(handle, '┴')?;
@@ -526,7 +559,9 @@ impl<'a> Printer for InteractivePrinter<'a> {
fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
if self.config.style_components.grid()
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
&& (self.content_type.map_or(false, |c| c.is_text())
|| self.config.show_nonprintable
|| matches!(self.config.binary, BinaryBehavior::AsText))
{
self.print_horizontal_line(handle, '┴')
} else {
@@ -573,8 +608,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
)
.into()
} else {
match self.content_type {
Some(ContentType::BINARY) | None => {
let mut line = match self.content_type {
Some(ContentType::BINARY) | None
if !matches!(self.config.binary, BinaryBehavior::AsText) =>
{
return Ok(());
}
Some(ContentType::UTF_16LE) => UTF_16LE.decode_with_bom_removal(line_buffer).0,
@@ -590,7 +627,14 @@ impl<'a> Printer for InteractivePrinter<'a> {
line
}
}
};
// If ANSI escape sequences are supposed to be stripped, do it before syntax highlighting.
if self.strip_ansi {
line = strip_ansi(&line).into()
}
line
};
let regions = self.highlight_regions_for_line(&line)?;

View File

@@ -138,3 +138,227 @@ impl StyleComponents {
self.0.clear();
}
}
#[derive(Debug, PartialEq)]
enum ComponentAction {
Override,
Add,
Remove,
}
impl ComponentAction {
fn extract_from_str(string: &str) -> (ComponentAction, &str) {
match string.chars().next() {
Some('-') => (ComponentAction::Remove, string.strip_prefix('-').unwrap()),
Some('+') => (ComponentAction::Add, string.strip_prefix('+').unwrap()),
_ => (ComponentAction::Override, string),
}
}
}
/// A list of [StyleComponent] that can be parsed from a string.
pub struct StyleComponentList(Vec<(ComponentAction, StyleComponent)>);
impl StyleComponentList {
fn expand_into(&self, components: &mut HashSet<StyleComponent>, interactive_terminal: bool) {
for (action, component) in self.0.iter() {
let subcomponents = component.components(interactive_terminal);
use ComponentAction::*;
match action {
Override | Add => components.extend(subcomponents),
Remove => components.retain(|c| !subcomponents.contains(c)),
}
}
}
/// Returns `true` if any component in the list was not prefixed with `+` or `-`.
fn contains_override(&self) -> bool {
self.0.iter().any(|(a, _)| *a == ComponentAction::Override)
}
/// Combines multiple [StyleComponentList]s into a single [StyleComponents] set.
///
/// ## Precedence
/// The most recent list will take precedence and override all previous lists
/// unless it only contains components prefixed with `-` or `+`. When this
/// happens, the list's components will be merged into the previous list.
///
/// ## Example
/// ```text
/// [numbers,grid] + [header,changes] -> [header,changes]
/// [numbers,grid] + [+header,-grid] -> [numbers,header]
/// ```
///
/// ## Parameters
/// - `with_default`: If true, the styles lists will build upon the StyleComponent::Auto style.
pub fn to_components(
lists: impl IntoIterator<Item = StyleComponentList>,
interactive_terminal: bool,
with_default: bool,
) -> StyleComponents {
let mut components: HashSet<StyleComponent> = HashSet::new();
if with_default {
components.extend(StyleComponent::Auto.components(interactive_terminal))
}
StyleComponents(lists.into_iter().fold(components, |mut components, list| {
if list.contains_override() {
components.clear();
}
list.expand_into(&mut components, interactive_terminal);
components
}))
}
}
impl Default for StyleComponentList {
fn default() -> Self {
StyleComponentList(vec![(ComponentAction::Override, StyleComponent::Default)])
}
}
impl FromStr for StyleComponentList {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
Ok(StyleComponentList(
s.split(",")
.map(|s| ComponentAction::extract_from_str(s)) // If the component starts with "-", it's meant to be removed
.map(|(a, s)| Ok((a, StyleComponent::from_str(s)?)))
.collect::<Result<Vec<(ComponentAction, StyleComponent)>>>()?,
))
}
}
#[cfg(test)]
mod test {
use std::collections::HashSet;
use std::str::FromStr;
use super::ComponentAction::*;
use super::StyleComponent;
use super::StyleComponent::*;
use super::StyleComponentList;
#[test]
pub fn style_component_list_parse() {
assert_eq!(
StyleComponentList::from_str("grid,+numbers,snip,-snip,header")
.expect("no error")
.0,
vec![
(Override, Grid),
(Add, LineNumbers),
(Override, Snip),
(Remove, Snip),
(Override, Header),
]
);
assert!(StyleComponentList::from_str("not-a-component").is_err());
assert!(StyleComponentList::from_str("grid,not-a-component").is_err());
assert!(StyleComponentList::from_str("numbers,-not-a-component").is_err());
}
#[test]
pub fn style_component_list_to_components() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("grid,numbers").expect("no error")],
false,
false
)
.0,
HashSet::from([Grid, LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_removes_negated() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("grid,numbers,-grid").expect("no error")],
false,
false
)
.0,
HashSet::from([LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_expands_subcomponents() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("full").expect("no error")],
false,
false
)
.0,
HashSet::from_iter(Full.components(true).to_owned())
);
}
#[test]
pub fn style_component_list_expand_negates_subcomponents() {
assert!(!StyleComponentList::to_components(
vec![StyleComponentList::from_str("full,-numbers").expect("no error")],
true,
false
)
.numbers());
}
#[test]
pub fn style_component_list_to_components_precedence_overrides_previous_lists() {
assert_eq!(
StyleComponentList::to_components(
vec![
StyleComponentList::from_str("grid").expect("no error"),
StyleComponentList::from_str("numbers").expect("no error"),
],
false,
false
)
.0,
HashSet::from([LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_precedence_merges_previous_lists() {
assert_eq!(
StyleComponentList::to_components(
vec![
StyleComponentList::from_str("grid,header").expect("no error"),
StyleComponentList::from_str("-grid").expect("no error"),
StyleComponentList::from_str("+numbers").expect("no error"),
],
false,
false
)
.0,
HashSet::from([HeaderFilename, LineNumbers])
);
}
#[test]
pub fn style_component_list_default_builds_on_auto() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("-numbers").expect("no error"),],
true,
true
)
.0,
{
let mut expected: HashSet<StyleComponent> = HashSet::new();
expected.extend(Auto.components(true));
expected.remove(&LineNumbers);
expected
}
);
}
}

View File

@@ -0,0 +1,2 @@
[mappings]
"YAML" = ["CITATION.cff"]

View File

@@ -0,0 +1,3 @@
# .debdiff is the extension used for diffs in Debian packaging
[mappings]
"Diff" = ["*.debdiff"]

View File

@@ -1,3 +1,3 @@
# JSON Lines is a simple variation of JSON #2535
[mappings]
"JSON" = ["*.jsonl", "*.jsonc"]
"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson"]

View File

@@ -0,0 +1,2 @@
[mappings]
"Markdown" = ["*.mkd"]

View File

@@ -0,0 +1,2 @@
[mappings]
"YAML" = ["/etc/kubernetes/*.conf"]

View File

@@ -1,3 +1,8 @@
[mappings]
# pacman hooks
"INI" = ["/usr/share/libalpm/hooks/*.hook", "/etc/pacman.d/hooks/*.hook"]
"INI" = [
# config
"/etc/pacman.conf",
# hooks
"/usr/share/libalpm/hooks/*.hook",
"/etc/pacman.d/hooks/*.hook",
]

View File

@@ -1,2 +1,2 @@
[mappings]
"Apache Conf" = ["/etc/apache2/**/*.conf", "/etc/apache2/sites-*/**/*"]
"Apache Conf" = ["/etc/apache2/**/*.conf", "/etc/apache2/sites-*/**/*", "/etc/httpd/conf/**/*.conf"]

571
src/theme.rs Normal file
View File

@@ -0,0 +1,571 @@
//! Utilities for choosing an appropriate theme for syntax highlighting.
use std::convert::Infallible;
use std::fmt;
use std::io::IsTerminal as _;
use std::str::FromStr;
/// Environment variable names.
pub mod env {
/// See [`crate::theme::ThemeOptions::theme`].
pub const BAT_THEME: &str = "BAT_THEME";
/// See [`crate::theme::ThemeOptions::theme_dark`].
pub const BAT_THEME_DARK: &str = "BAT_THEME";
/// See [`crate::theme::ThemeOptions::theme_light`].
pub const BAT_THEME_LIGHT: &str = "BAT_THEME";
}
/// Chooses an appropriate theme or falls back to a default theme
/// based on the user-provided options and the color scheme of the terminal.
///
/// Intentionally returns a [`ThemeResult`] instead of a simple string so
/// that downstream consumers such as `delta` can easily apply their own
/// default theme and can use the detected color scheme elsewhere.
pub fn theme(options: ThemeOptions) -> ThemeResult {
theme_impl(options, &TerminalColorSchemeDetector)
}
/// The default theme, suitable for the given color scheme.
/// Use [`theme`] if you want to automatically detect the color scheme from the terminal.
pub const fn default_theme(color_scheme: ColorScheme) -> &'static str {
match color_scheme {
ColorScheme::Dark => "Monokai Extended",
ColorScheme::Light => "Monokai Extended Light",
}
}
/// Detects the color scheme from the terminal.
pub fn color_scheme(when: DetectColorScheme) -> Option<ColorScheme> {
color_scheme_impl(when, &TerminalColorSchemeDetector)
}
/// Options for configuring the theme used for syntax highlighting.
/// Used together with [`theme`].
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ThemeOptions {
/// Configures how the theme is chosen. If set to a [`ThemePreference::Fixed`] value,
/// then the given theme is used regardless of the terminal's background color.
/// This corresponds with the `BAT_THEME` environment variable and the `--theme` option.
pub theme: ThemePreference,
/// The theme to use in case the terminal uses a dark background with light text.
/// This corresponds with the `BAT_THEME_DARK` environment variable and the `--theme-dark` option.
pub theme_dark: Option<ThemeName>,
/// The theme to use in case the terminal uses a light background with dark text.
/// This corresponds with the `BAT_THEME_LIGHT` environment variable and the `--theme-light` option.
pub theme_light: Option<ThemeName>,
}
/// What theme should `bat` use?
///
/// The easiest way to construct this is from a string:
/// ```
/// # use bat::theme::{ThemePreference, DetectColorScheme};
/// let preference = ThemePreference::new("auto:system");
/// assert_eq!(ThemePreference::Auto(DetectColorScheme::System), preference);
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ThemePreference {
/// Choose between [`ThemeOptions::theme_dark`] and [`ThemeOptions::theme_light`]
/// based on the terminal's color scheme.
Auto(DetectColorScheme),
/// Always use the same theme regardless of the terminal's color scheme.
Fixed(ThemeName),
/// Use a dark theme.
Dark,
/// Use a light theme.
Light,
}
impl Default for ThemePreference {
fn default() -> Self {
ThemePreference::Auto(Default::default())
}
}
impl ThemePreference {
/// Creates a theme preference from a string.
pub fn new(s: impl Into<String>) -> Self {
use ThemePreference::*;
let s = s.into();
match s.as_str() {
"auto" => Auto(Default::default()),
"auto:always" => Auto(DetectColorScheme::Always),
"auto:system" => Auto(DetectColorScheme::System),
"dark" => Dark,
"light" => Light,
_ => Fixed(ThemeName::new(s)),
}
}
}
impl FromStr for ThemePreference {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ThemePreference::new(s))
}
}
impl fmt::Display for ThemePreference {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ThemePreference::*;
match self {
Auto(DetectColorScheme::Auto) => f.write_str("auto"),
Auto(DetectColorScheme::Always) => f.write_str("auto:always"),
Auto(DetectColorScheme::System) => f.write_str("auto:system"),
Fixed(theme) => theme.fmt(f),
Dark => f.write_str("dark"),
Light => f.write_str("light"),
}
}
}
/// The name of a theme or the default theme.
///
/// ```
/// # use bat::theme::ThemeName;
/// assert_eq!(ThemeName::Default, ThemeName::new("default"));
/// assert_eq!(ThemeName::Named("example".to_string()), ThemeName::new("example"));
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ThemeName {
Named(String),
Default,
}
impl ThemeName {
/// Creates a theme name from a string.
pub fn new(s: impl Into<String>) -> Self {
let s = s.into();
if s == "default" {
ThemeName::Default
} else {
ThemeName::Named(s)
}
}
}
impl FromStr for ThemeName {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ThemeName::new(s))
}
}
impl fmt::Display for ThemeName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ThemeName::Named(t) => f.write_str(t),
ThemeName::Default => f.write_str("default"),
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DetectColorScheme {
/// Only query the terminal for its colors when appropriate (i.e. when the output is not redirected).
#[default]
Auto,
/// Always query the terminal for its colors.
Always,
/// Detect the system-wide dark/light preference (macOS only).
System,
}
/// The color scheme used to pick a fitting theme. Defaults to [`ColorScheme::Dark`].
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ColorScheme {
#[default]
Dark,
Light,
}
/// The resolved theme and the color scheme as determined from
/// the terminal, OS or fallback.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ThemeResult {
/// The theme selected according to the [`ThemeOptions`].
pub theme: ThemeName,
/// Either the user's chosen color scheme, the terminal's color scheme, the OS's
/// color scheme or `None` if the color scheme was not detected because the user chose a fixed theme.
pub color_scheme: Option<ColorScheme>,
}
impl fmt::Display for ThemeResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.theme {
ThemeName::Named(name) => f.write_str(name),
ThemeName::Default => f.write_str(default_theme(self.color_scheme.unwrap_or_default())),
}
}
}
fn theme_impl(options: ThemeOptions, detector: &dyn ColorSchemeDetector) -> ThemeResult {
// Implementation note: This function is mostly pure (i.e. it has no side effects) for the sake of testing.
// All the side effects (e.g. querying the terminal for its colors) are performed in the detector.
match options.theme {
ThemePreference::Fixed(theme) => ThemeResult {
theme,
color_scheme: None,
},
ThemePreference::Dark => choose_theme_opt(Some(ColorScheme::Dark), options),
ThemePreference::Light => choose_theme_opt(Some(ColorScheme::Light), options),
ThemePreference::Auto(when) => choose_theme_opt(color_scheme_impl(when, detector), options),
}
}
fn choose_theme_opt(color_scheme: Option<ColorScheme>, options: ThemeOptions) -> ThemeResult {
ThemeResult {
color_scheme,
theme: color_scheme
.and_then(|c| choose_theme(options, c))
.unwrap_or(ThemeName::Default),
}
}
fn choose_theme(options: ThemeOptions, color_scheme: ColorScheme) -> Option<ThemeName> {
match color_scheme {
ColorScheme::Dark => options.theme_dark,
ColorScheme::Light => options.theme_light,
}
}
fn color_scheme_impl(
when: DetectColorScheme,
detector: &dyn ColorSchemeDetector,
) -> Option<ColorScheme> {
let should_detect = match when {
DetectColorScheme::Auto => detector.should_detect(),
DetectColorScheme::Always => true,
DetectColorScheme::System => return color_scheme_from_system(),
};
should_detect.then(|| detector.detect()).flatten()
}
trait ColorSchemeDetector {
fn should_detect(&self) -> bool;
fn detect(&self) -> Option<ColorScheme>;
}
struct TerminalColorSchemeDetector;
impl ColorSchemeDetector for TerminalColorSchemeDetector {
fn should_detect(&self) -> bool {
// Querying the terminal for its colors via OSC 10 / OSC 11 requires "exclusive" access
// since we read/write from the terminal and enable/disable raw mode.
// This causes race conditions with pagers such as less when they are attached to the
// same terminal as us.
//
// This is usually only an issue when the output is manually piped to a pager.
// For example: `bat Cargo.toml | less`.
// Otherwise, if we start the pager ourselves, then there's no race condition
// since the pager is started *after* the color is detected.
std::io::stdout().is_terminal()
}
fn detect(&self) -> Option<ColorScheme> {
use terminal_colorsaurus::{color_scheme, ColorScheme as ColorsaurusScheme, QueryOptions};
match color_scheme(QueryOptions::default()).ok()? {
ColorsaurusScheme::Dark => Some(ColorScheme::Dark),
ColorsaurusScheme::Light => Some(ColorScheme::Light),
}
}
}
#[cfg(not(target_os = "macos"))]
fn color_scheme_from_system() -> Option<ColorScheme> {
crate::bat_warning!(
"Theme 'auto:system' is only supported on macOS, \
using default."
);
None
}
#[cfg(target_os = "macos")]
fn color_scheme_from_system() -> Option<ColorScheme> {
const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist";
const STYLE_KEY: &str = "AppleInterfaceStyle";
let preferences_file = home::home_dir()
.map(|home| home.join(PREFERENCES_FILE))
.expect("Could not get home directory");
match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) {
Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) {
Some("Dark") => Some(ColorScheme::Dark),
// If the key does not exist, then light theme is currently in use.
Some(_) | None => Some(ColorScheme::Light),
},
// Unreachable, in theory. All macOS users have a home directory and preferences file setup.
Ok(None) | Err(_) => None,
}
}
#[cfg(test)]
impl ColorSchemeDetector for Option<ColorScheme> {
fn should_detect(&self) -> bool {
true
}
fn detect(&self) -> Option<ColorScheme> {
*self
}
}
#[cfg(test)]
mod tests {
use super::ColorScheme::*;
use super::*;
use std::cell::Cell;
use std::iter;
mod color_scheme_detection {
use super::*;
#[test]
fn not_called_for_dark_or_light() {
for theme in [ThemePreference::Dark, ThemePreference::Light] {
let detector = DetectorStub::should_detect(Some(Dark));
let options = ThemeOptions {
theme,
..Default::default()
};
_ = theme_impl(options, &detector);
assert!(!detector.was_called.get());
}
}
#[test]
fn called_for_always() {
let detectors = [
DetectorStub::should_detect(Some(Dark)),
DetectorStub::should_not_detect(),
];
for detector in detectors {
let options = ThemeOptions {
theme: ThemePreference::Auto(DetectColorScheme::Always),
..Default::default()
};
_ = theme_impl(options, &detector);
assert!(detector.was_called.get());
}
}
#[test]
fn called_for_auto_if_should_detect() {
let detector = DetectorStub::should_detect(Some(Dark));
_ = theme_impl(ThemeOptions::default(), &detector);
assert!(detector.was_called.get());
}
#[test]
fn not_called_for_auto_if_not_should_detect() {
let detector = DetectorStub::should_not_detect();
_ = theme_impl(ThemeOptions::default(), &detector);
assert!(!detector.was_called.get());
}
}
mod precedence {
use super::*;
#[test]
fn theme_is_preferred_over_light_or_dark_themes() {
for color_scheme in optional(color_schemes()) {
for options in [
ThemeOptions {
theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
..Default::default()
},
ThemeOptions {
theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
theme_dark: Some(ThemeName::Named("Dark Theme".to_string())),
theme_light: Some(ThemeName::Named("Light Theme".to_string())),
..Default::default()
},
] {
let detector = ConstantDetector(color_scheme);
assert_eq!("Theme", theme_impl(options, &detector).to_string());
}
}
}
#[test]
fn detector_is_not_called_if_theme_is_present() {
let options = ThemeOptions {
theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
..Default::default()
};
let detector = DetectorStub::should_detect(Some(Dark));
_ = theme_impl(options, &detector);
assert!(!detector.was_called.get());
}
}
mod default_theme {
use super::*;
#[test]
fn default_dark_if_unable_to_detect_color_scheme() {
let detector = ConstantDetector(None);
assert_eq!(
default_theme(ColorScheme::Dark),
theme_impl(ThemeOptions::default(), &detector).to_string()
);
}
// For backwards compatibility, if the default theme is requested
// explicitly through BAT_THEME, we always pick the default dark theme.
#[test]
fn default_dark_if_requested_explicitly_through_theme() {
for color_scheme in optional(color_schemes()) {
let options = ThemeOptions {
theme: ThemePreference::Fixed(ThemeName::Default),
..Default::default()
};
let detector = ConstantDetector(color_scheme);
assert_eq!(
default_theme(ColorScheme::Dark),
theme_impl(options, &detector).to_string()
);
}
}
#[test]
fn varies_depending_on_color_scheme() {
for color_scheme in color_schemes() {
for options in [
ThemeOptions::default(),
ThemeOptions {
theme_dark: Some(ThemeName::Default),
theme_light: Some(ThemeName::Default),
..Default::default()
},
] {
let detector = ConstantDetector(Some(color_scheme));
assert_eq!(
default_theme(color_scheme),
theme_impl(options, &detector).to_string()
);
}
}
}
}
mod choosing {
use super::*;
#[test]
fn chooses_default_theme_if_unknown() {
let options = ThemeOptions {
theme_dark: Some(ThemeName::Named("Dark".to_string())),
theme_light: Some(ThemeName::Named("Light".to_string())),
..Default::default()
};
let detector = ConstantDetector(None);
assert_eq!(
default_theme(ColorScheme::default()),
theme_impl(options, &detector).to_string()
);
}
#[test]
fn chooses_dark_theme_if_dark_or_unknown() {
let options = ThemeOptions {
theme_dark: Some(ThemeName::Named("Dark".to_string())),
theme_light: Some(ThemeName::Named("Light".to_string())),
..Default::default()
};
let detector = ConstantDetector(Some(ColorScheme::Dark));
assert_eq!("Dark", theme_impl(options, &detector).to_string());
}
#[test]
fn chooses_light_theme_if_light() {
let options = ThemeOptions {
theme_dark: Some(ThemeName::Named("Dark".to_string())),
theme_light: Some(ThemeName::Named("Light".to_string())),
..Default::default()
};
let detector = ConstantDetector(Some(ColorScheme::Light));
assert_eq!("Light", theme_impl(options, &detector).to_string());
}
}
mod theme_preference {
use super::*;
#[test]
fn values_roundtrip_via_display() {
let prefs = [
ThemePreference::Auto(DetectColorScheme::Auto),
ThemePreference::Auto(DetectColorScheme::Always),
ThemePreference::Auto(DetectColorScheme::System),
ThemePreference::Fixed(ThemeName::Default),
ThemePreference::Fixed(ThemeName::new("foo")),
ThemePreference::Dark,
ThemePreference::Light,
];
for pref in prefs {
assert_eq!(pref, ThemePreference::new(&pref.to_string()));
}
}
}
struct DetectorStub {
should_detect: bool,
color_scheme: Option<ColorScheme>,
was_called: Cell<bool>,
}
impl DetectorStub {
fn should_detect(color_scheme: Option<ColorScheme>) -> Self {
DetectorStub {
should_detect: true,
color_scheme,
was_called: Cell::default(),
}
}
fn should_not_detect() -> Self {
DetectorStub {
should_detect: false,
color_scheme: None,
was_called: Cell::default(),
}
}
}
impl ColorSchemeDetector for DetectorStub {
fn should_detect(&self) -> bool {
self.should_detect
}
fn detect(&self) -> Option<ColorScheme> {
self.was_called.set(true);
self.color_scheme
}
}
struct ConstantDetector(Option<ColorScheme>);
impl ColorSchemeDetector for ConstantDetector {
fn should_detect(&self) -> bool {
true
}
fn detect(&self) -> Option<ColorScheme> {
self.0
}
}
fn optional<T>(value: impl Iterator<Item = T>) -> impl Iterator<Item = Option<T>> {
value.map(Some).chain(iter::once(None))
}
fn color_schemes() -> impl Iterator<Item = ColorScheme> {
[Dark, Light].into_iter()
}
}

View File

@@ -285,7 +285,7 @@ fn join(
/// A range of indices for a raw ANSI escape sequence.
#[derive(Debug, PartialEq)]
enum EscapeSequenceOffsets {
pub enum EscapeSequenceOffsets {
Text {
start: usize,
end: usize,
@@ -320,6 +320,32 @@ enum EscapeSequenceOffsets {
},
}
impl EscapeSequenceOffsets {
/// Returns the byte-index of the first character in the escape sequence.
pub fn index_of_start(&self) -> usize {
use EscapeSequenceOffsets::*;
match self {
Text { start, .. } => *start,
Unknown { start, .. } => *start,
NF { start_sequence, .. } => *start_sequence,
OSC { start_sequence, .. } => *start_sequence,
CSI { start_sequence, .. } => *start_sequence,
}
}
/// Returns the byte-index past the last character in the escape sequence.
pub fn index_past_end(&self) -> usize {
use EscapeSequenceOffsets::*;
match self {
Text { end, .. } => *end,
Unknown { end, .. } => *end,
NF { end, .. } => *end,
OSC { end, .. } => *end,
CSI { end, .. } => *end,
}
}
}
/// An iterator over the offests of ANSI/VT escape sequences within a string.
///
/// ## Example
@@ -327,7 +353,7 @@ enum EscapeSequenceOffsets {
/// ```ignore
/// let iter = EscapeSequenceOffsetsIterator::new("\x1B[33mThis is yellow text.\x1B[m");
/// ```
struct EscapeSequenceOffsetsIterator<'a> {
pub struct EscapeSequenceOffsetsIterator<'a> {
text: &'a str,
chars: Peekable<CharIndices<'a>>,
}

View File

@@ -9,7 +9,6 @@ use tempfile::tempdir;
mod unix {
pub use std::fs::File;
pub use std::io::{self, Write};
pub use std::os::unix::io::FromRawFd;
pub use std::path::PathBuf;
pub use std::process::Stdio;
pub use std::thread;
@@ -273,13 +272,60 @@ fn squeeze_limit_line_numbers() {
}
#[test]
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
fn list_themes_with_colors() {
let default_theme_chunk = "Monokai Extended\x1B[0m (default)";
let default_light_theme_chunk = "Monokai Extended Light\x1B[0m (default light)";
bat()
.arg("--color=always")
.arg("--list-themes")
.assert()
.success()
.stdout(predicate::str::contains("DarkNeon").normalize())
.stdout(predicate::str::contains(default_theme_chunk).normalize())
.stdout(predicate::str::contains(default_light_theme_chunk).normalize())
.stdout(predicate::str::contains("Output the square of a number.").normalize());
}
#[test]
fn list_themes_without_colors() {
let default_theme_chunk = "Monokai Extended (default)";
let default_light_theme_chunk = "Monokai Extended Light (default light)";
bat()
.arg("--color=never")
.arg("--decorations=always") // trick bat into setting `Config::loop_through` to false
.arg("--list-themes")
.assert()
.success()
.stdout(predicate::str::contains("DarkNeon").normalize())
.stdout(predicate::str::contains(default_theme_chunk).normalize())
.stdout(predicate::str::contains(default_light_theme_chunk).normalize());
}
#[test]
fn list_themes_to_piped_output() {
bat()
.arg("--list-themes")
.assert()
.success()
.stdout(predicate::str::contains("(default)").not());
}
#[test]
#[cfg_attr(
any(not(feature = "git"), feature = "lessopen", target_os = "windows"),
ignore
)]
fn short_help() {
test_help("-h", "../doc/short-help.txt");
}
#[test]
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
#[cfg_attr(
any(not(feature = "git"), feature = "lessopen", target_os = "windows"),
ignore
)]
fn long_help() {
test_help("--help", "../doc/long-help.txt");
}
@@ -370,9 +416,10 @@ fn no_args_doesnt_break() {
// as the slave end of a pseudo terminal. Although both point to the same "file", bat should
// not exit, because in this case it is safe to read and write to the same fd, which is why
// this test exists.
let OpenptyResult { master, slave } = openpty(None, None).expect("Couldn't open pty.");
let mut master = unsafe { File::from_raw_fd(master) };
let stdin_file = unsafe { File::from_raw_fd(slave) };
let mut master = File::from(master);
let stdin_file = File::from(slave);
let stdout_file = stdin_file.try_clone().unwrap();
let stdin = Stdio::from(stdin_file);
let stdout = Stdio::from(stdout_file);
@@ -380,6 +427,7 @@ fn no_args_doesnt_break() {
let mut child = bat_raw_command()
.stdin(stdin)
.stdout(stdout)
.env("TERM", "dumb") // Suppresses color detection
.spawn()
.expect("Failed to start.");
@@ -975,6 +1023,31 @@ fn enable_pager_if_pp_flag_comes_before_paging() {
.stdout(predicate::eq("pager-output\n").normalize());
}
#[test]
fn paging_does_not_override_simple_plain() {
bat()
.env("PAGER", "echo pager-output")
.arg("--decorations=always")
.arg("--plain")
.arg("--paging=never")
.arg("test.txt")
.assert()
.success()
.stdout(predicate::eq("hello world\n"));
}
#[test]
fn simple_plain_does_not_override_paging() {
bat()
.env("PAGER", "echo pager-output")
.arg("--paging=always")
.arg("--plain")
.arg("test.txt")
.assert()
.success()
.stdout(predicate::eq("pager-output\n"));
}
#[test]
fn pager_failed_to_parse() {
bat()
@@ -1894,6 +1967,16 @@ fn show_all_with_unicode() {
.stderr("");
}
#[test]
fn binary_as_text() {
bat()
.arg("--binary=as-text")
.arg("control_characters.txt")
.assert()
.stdout("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F")
.stderr("");
}
#[test]
fn no_paging_arg() {
bat()
@@ -2360,7 +2443,6 @@ fn lessopen_stdin_piped() {
#[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system
#[cfg(feature = "lessopen")]
#[test]
#[serial] // Randomly fails otherwise
fn lessopen_and_lessclose_file_temp() {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In this case, the original file and the temporary file returned by $LESSOPEN
@@ -2378,7 +2460,6 @@ fn lessopen_and_lessclose_file_temp() {
#[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system
#[cfg(feature = "lessopen")]
#[test]
#[serial] // Randomly fails otherwise
fn lessopen_and_lessclose_file_piped() {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In these cases, the original file and a dash
@@ -2405,8 +2486,6 @@ fn lessopen_and_lessclose_file_piped() {
#[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system
#[cfg(feature = "lessopen")]
#[test]
#[serial] // Randomly fails otherwise
#[ignore = "randomly failing on some systems"]
fn lessopen_and_lessclose_stdin_temp() {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In this case, a dash and the temporary file returned by $LESSOPEN
@@ -2424,7 +2503,6 @@ fn lessopen_and_lessclose_stdin_temp() {
#[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system
#[cfg(feature = "lessopen")]
#[test]
#[serial] // Randomly fails otherwise
fn lessopen_and_lessclose_stdin_piped() {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In these cases, two dashes
@@ -2631,3 +2709,215 @@ fn highlighting_independant_from_map_syntax_case() {
.stdout(expected)
.stderr("");
}
#[test]
fn strip_ansi_always_strips_ansi() {
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=always")
.write_stdin("\x1B[33mYellow\x1B[m")
.assert()
.success()
.stdout("Yellow");
}
#[test]
fn strip_ansi_never_does_not_strip_ansi() {
let output = String::from_utf8(
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=never")
.write_stdin("\x1B[33mYellow\x1B[m")
.assert()
.success()
.get_output()
.stdout
.clone(),
)
.expect("valid utf8");
assert!(output.contains("\x1B[33mYellow"))
}
#[test]
fn strip_ansi_does_not_affect_simple_printer() {
let output = String::from_utf8(
bat()
.arg("--style=plain")
.arg("--decorations=never")
.arg("--color=never")
.arg("--strip-ansi=always")
.write_stdin("\x1B[33mYellow\x1B[m")
.assert()
.success()
.get_output()
.stdout
.clone(),
)
.expect("valid utf8");
assert!(output.contains("\x1B[33mYellow"))
}
#[test]
fn strip_ansi_does_not_strip_when_show_nonprintable() {
let output = String::from_utf8(
bat()
.arg("--style=plain")
.arg("--decorations=never")
.arg("--color=always")
.arg("--strip-ansi=always")
.arg("--show-nonprintable")
.write_stdin("\x1B[33mY")
.assert()
.success()
.get_output()
.stdout
.clone(),
)
.expect("valid utf8");
assert!(output.contains(""))
}
#[test]
fn strip_ansi_auto_strips_ansi_when_detected_syntax_by_filename() {
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=auto")
.arg("--file-name=test.rs")
.write_stdin("fn \x1B[33mYellow\x1B[m() -> () {}")
.assert()
.success()
.stdout("fn Yellow() -> () {}");
}
#[test]
fn strip_ansi_auto_strips_ansi_when_provided_syntax_by_option() {
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=auto")
.arg("--language=rust")
.write_stdin("fn \x1B[33mYellow\x1B[m() -> () {}")
.assert()
.success()
.stdout("fn Yellow() -> () {}");
}
#[test]
fn strip_ansi_auto_does_not_strip_when_plain_text_by_filename() {
let output = String::from_utf8(
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=auto")
.arg("--file-name=ansi.txt")
.write_stdin("\x1B[33mYellow\x1B[m")
.assert()
.success()
.get_output()
.stdout
.clone(),
)
.expect("valid utf8");
assert!(output.contains("\x1B[33mYellow"))
}
#[test]
fn strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option() {
let output = String::from_utf8(
bat()
.arg("--style=plain")
.arg("--decorations=always")
.arg("--color=never")
.arg("--strip-ansi=auto")
.arg("--language=txt")
.write_stdin("\x1B[33mYellow\x1B[m")
.assert()
.success()
.get_output()
.stdout
.clone(),
)
.expect("valid utf8");
assert!(output.contains("\x1B[33mYellow"))
}
// Tests that style components can be removed with `-component`.
#[test]
fn style_components_can_be_removed() {
bat()
.arg({
#[cfg(not(feature = "git"))]
{
"--style=full,-grid"
}
#[cfg(feature = "git")]
{
"--style=full,-grid,-changes"
}
})
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n Size: -\n 1 test\n")
.stderr("");
}
// Tests that style components are chosen based on the rightmost `--style` argument.
#[test]
fn style_components_can_be_overidden() {
bat()
.arg("--style=full")
.arg("--style=header,numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}
// Tests that style components can be merged across multiple `--style` arguments.
#[test]
fn style_components_will_merge() {
bat()
.arg("--style=header,grid")
.arg("--style=-grid,+numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}
// Tests that style components can be merged with the `BAT_STYLE` environment variable.
#[test]
fn style_components_will_merge_with_env_var() {
bat()
.env("BAT_STYLE", "header,grid")
.arg("--style=-grid,+numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}

View File

@@ -0,0 +1,54 @@
<head> 
<title>Add New Employees</title> 
</head> 
<body> 
<h1>Add New Employees</h1> 
<!--- Action page code for the form at the bottom of this page. ---> 
<!--- Establish parameters for first time through ---> 
<cfparam name="Form.firstname" default=""> 
<cfparam name="Form.lastname" default=""> 
<cfparam name="Form.email" default=""> 
<cfparam name="Form.phone" default=""> 
<cfparam name="Form.department" default=""> 
<!--- If at least the firstname form field is passed, create 
a structure named employee and add values. ---> 
<cfif #Form.firstname# eq ""> 
<p>Please fill out the form.</p> 
<cfelse> 
<cfoutput> 
<cfscript> 
employee=StructNew(); 
employee.firstname = Form.firstname; 
employee.lastname = Form.lastname; 
employee.email = Form.email; 
employee.phone = Form.phone; 
employee.department = Form.department; 
</cfscript> 
<!--- Display results of creating the structure. ---> 
First name is #StructFind(employee, "firstname")#<br> 
Last name is #StructFind(employee, "lastname")#<br> 
EMail is #StructFind(employee, "email")#<br> 
Phone is #StructFind(employee, "phone")#<br> 
Department is #StructFind(employee, "department")#<br> 
</cfoutput> 
<!--- Call the custom tag that adds employees. ---> 
<cf_addemployee empinfo="#employee#"> 
</cfif> 
<!--- The form for adding the new employee information ---> 
<hr> 
<form action="newemployee.cfm" method="Post"> 
First Name:&nbsp; 
<input name="firstname" type="text" hspace="30" maxlength="30"><br> 
Last Name:&nbsp; 
<input name="lastname" type="text" hspace="30" maxlength="30"><br> 
EMail:&nbsp; 
<input name="email" type="text" hspace="30" maxlength="30"><br> 
Phone:&nbsp; 
<input name="phone" type="text" hspace="20" maxlength="20"><br> 
Department:&nbsp; 
<input name="department" type="text" hspace="30" maxlength="30"><br> 
<input type="Submit" value="OK"> 
</form> 
<br> 
</body> 
</html>

View File

@@ -1,80 +1,80 @@
(cl:defpackage :chillax.utils
 (:use :cl :alexandria)
 (:export
 :fun :mkhash :hashget :strcat :dequote :at))
(in-package :chillax.utils)
(cl:defpackage :chillax.utils
 (:use :cl :alexandria)
 (:export
 :fun :mkhash :hashget :strcat :dequote :at))
(in-package :chillax.utils)
;;; Functions
(defmacro fun (&body body)
;;; Functions
(defmacro fun (&body body)
 "This macro puts the FUN back in FUNCTION."
 `(lambda (&optional _) (declare (ignorable _)) ,@body))
 `(lambda (&optional _) (declare (ignorable _)) ,@body))
;;; Hash tables
(defun mkhash (&rest keys-and-values &aux (table (make-hash-table :test #'equal)))
;;; Hash tables
(defun mkhash (&rest keys-and-values &aux (table (make-hash-table :test #'equal)))
 "Convenience function for `literal' hash table definition."
 (loop for (key val) on keys-and-values by #'cddr do (setf (gethash key table) val)
 finally (return table)))
 (loop for (key val) on keys-and-values by #'cddr do (setf (gethash key table) val)
 finally (return table)))
(defun hashget (hash &rest keys)
(defun hashget (hash &rest keys)
 "Convenience function for recursively accessing hash tables."
 (reduce (lambda (h k) (gethash k h)) keys :initial-value hash))
 (reduce (lambda (h k) (gethash k h)) keys :initial-value hash))
(define-compiler-macro hashget (hash &rest keys)
 (if (null keys) hash
 (let ((hash-sym (make-symbol "HASH"))
 (key-syms (loop for i below (length keys)
 collect (make-symbol (format nil "~:@(~:R~)-KEY" i)))))
 `(let ((,hash-sym ,hash)
 ,@(loop for key in keys for sym in key-syms
 collect `(,sym ,key)))
 ,(reduce (lambda (hash key) `(gethash ,key ,hash))
 key-syms :initial-value hash-sym)))))
(define-compiler-macro hashget (hash &rest keys)
 (if (null keys) hash
 (let ((hash-sym (make-symbol "HASH"))
 (key-syms (loop for i below (length keys)
 collect (make-symbol (format nil "~:@(~:R~)-KEY" i)))))
 `(let ((,hash-sym ,hash)
 ,@(loop for key in keys for sym in key-syms
 collect `(,sym ,key)))
 ,(reduce (lambda (hash key) `(gethash ,key ,hash))
 key-syms :initial-value hash-sym)))))
(defun (setf hashget) (new-value hash key &rest more-keys)
(defun (setf hashget) (new-value hash key &rest more-keys)
 "Uses the last key given to hashget to insert NEW-VALUE into the hash table
returned by the second-to-last key.
tl;dr: DWIM SETF function for HASHGET."
 (if more-keys
 (setf (gethash (car (last more-keys))
 (apply #'hashget hash key (butlast more-keys)))
 new-value)
 (setf (gethash key hash) new-value)))
 (if more-keys
 (setf (gethash (car (last more-keys))
 (apply #'hashget hash key (butlast more-keys)))
 new-value)
 (setf (gethash key hash) new-value)))
;;; Strings
(defun strcat (string &rest more-strings)
 (apply #'concatenate 'string string more-strings))
;;; Strings
(defun strcat (string &rest more-strings)
 (apply #'concatenate 'string string more-strings))
(defun dequote (string)
 (let ((len (length string)))
 (if (and (> len 1) (starts-with #\" string) (ends-with #\" string))
 (subseq string 1 (- len 1))
 string)))
(defun dequote (string)
 (let ((len (length string)))
 (if (and (> len 1) (starts-with #\" string) (ends-with #\" string))
 (subseq string 1 (- len 1))
 string)))
;;;
;;; At
;;;
(defgeneric at (doc &rest keys))
(defgeneric (setf at) (new-value doc key &rest more-keys))
;;;
;;; At
;;;
(defgeneric at (doc &rest keys))
(defgeneric (setf at) (new-value doc key &rest more-keys))
(defmethod at ((doc hash-table) &rest keys)
 (apply #'hashget doc keys))
(defmethod (setf at) (new-value (doc hash-table) key &rest more-keys)
 (apply #'(setf hashget) new-value doc key more-keys))
(defmethod at ((doc hash-table) &rest keys)
 (apply #'hashget doc keys))
(defmethod (setf at) (new-value (doc hash-table) key &rest more-keys)
 (apply #'(setf hashget) new-value doc key more-keys))
(defmethod at ((doc list) &rest keys)
 (reduce (lambda (alist key)
 (cdr (assoc key alist :test #'equal)))
 keys :initial-value doc))
(defmethod (setf at) (new-value (doc list) key &rest more-keys)
 (if more-keys
 (setf (cdr (assoc (car (last more-keys))
 (apply #'at doc key (butlast more-keys))
 :test #'equal))
 new-value)
 (setf (cdr (assoc key doc :test #'equal)) new-value)))
(defmethod at ((doc list) &rest keys)
 (reduce (lambda (alist key)
 (cdr (assoc key alist :test #'equal)))
 keys :initial-value doc))
(defmethod (setf at) (new-value (doc list) key &rest more-keys)
 (if more-keys
 (setf (cdr (assoc (car (last more-keys))
 (apply #'at doc key (butlast more-keys))
 :test #'equal))
 new-value)
 (setf (cdr (assoc key doc :test #'equal)) new-value)))
;; A playful alias.
(defun @ (doc &rest keys)
 (apply #'at doc keys))
(defun (setf @) (new-value doc key &rest more-keys)
 (apply #'(setf at) new-value doc key more-keys))
;; A playful alias.
(defun @ (doc &rest keys)
 (apply #'at doc keys))
(defun (setf @) (new-value doc key &rest more-keys)
 (apply #'(setf at) new-value doc key more-keys))

View File

@@ -0,0 +1,54 @@
<head>
<title>Add New Employees</title>
</head>
<body>
<h1>Add New Employees</h1>
<!--- Action page code for the form at the bottom of this page. --->
<!--- Establish parameters for first time through --->
<cfparam name="Form.firstname" default="">
<cfparam name="Form.lastname" default="">
<cfparam name="Form.email" default="">
<cfparam name="Form.phone" default="">
<cfparam name="Form.department" default="">
<!--- If at least the firstname form field is passed, create
a structure named employee and add values. --->
<cfif #Form.firstname# eq "">
<p>Please fill out the form.</p>
<cfelse>
<cfoutput>
<cfscript>
employee=StructNew();
employee.firstname = Form.firstname;
employee.lastname = Form.lastname;
employee.email = Form.email;
employee.phone = Form.phone;
employee.department = Form.department;
</cfscript>
<!--- Display results of creating the structure. --->
First name is #StructFind(employee, "firstname")#<br>
Last name is #StructFind(employee, "lastname")#<br>
EMail is #StructFind(employee, "email")#<br>
Phone is #StructFind(employee, "phone")#<br>
Department is #StructFind(employee, "department")#<br>
</cfoutput>
<!--- Call the custom tag that adds employees. --->
<cf_addemployee empinfo="#employee#">
</cfif>
<!--- The form for adding the new employee information --->
<hr>
<form action="newemployee.cfm" method="Post">
First Name:&nbsp;
<input name="firstname" type="text" hspace="30" maxlength="30"><br>
Last Name:&nbsp;
<input name="lastname" type="text" hspace="30" maxlength="30"><br>
EMail:&nbsp;
<input name="email" type="text" hspace="30" maxlength="30"><br>
Phone:&nbsp;
<input name="phone" type="text" hspace="20" maxlength="20"><br>
Department:&nbsp;
<input name="department" type="text" hspace="30" maxlength="30"><br>
<input type="Submit" value="OK">
</form>
<br>
</body>
</html>