mirror of
https://github.com/sharkdp/bat.git
synced 2025-09-01 10:52:24 +01:00
Compare commits
267 Commits
v0.25.0
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
|
869deabcc9 | ||
|
d291b3e5fa | ||
|
6772225477 | ||
|
339e7df0bc | ||
|
297e8280d9 | ||
|
d397bea6dc | ||
|
3d174b8c09 | ||
|
d9dd9729b8 | ||
|
c657b18efd | ||
|
c9b41b1df7 | ||
|
45efc4117e | ||
|
6a74283289 | ||
|
120c39429f | ||
|
1c6ad4d514 | ||
|
36d25c8642 | ||
|
caf6fa369f | ||
|
503c50b1ec | ||
|
d9fbd18541 | ||
|
9824090654 | ||
|
bdaf25793d | ||
|
96ce80d0e2 | ||
|
40c4c8e542 | ||
|
6675153460 | ||
|
76e6a49a2e | ||
|
1bcf760d90 | ||
|
94f1035c08 | ||
|
3516a3311a | ||
|
f79adaf607 | ||
|
d9ac757b6a | ||
|
58bfcd9051 | ||
|
67e3e42531 | ||
|
3fd3f1def8 | ||
|
6d849e53d2 | ||
|
7fc3d6b588 | ||
|
1a931224eb | ||
|
60833ae5ec | ||
|
183def9569 | ||
|
77cfca1aff | ||
|
d9cc01b50c | ||
|
466087156f | ||
|
a8d610c6e8 | ||
|
30b42149aa | ||
|
c25e005c87 | ||
|
c4d7451841 | ||
|
d4fc07a347 | ||
|
0238473868 | ||
|
4363ddf0fb | ||
|
43c5fef70a | ||
|
7e436e307d | ||
|
b4d529402a | ||
|
b47338ec75 | ||
|
bd782ab228 | ||
|
4c2b20fedd | ||
|
9d3245eebe | ||
|
369ea67ad3 | ||
|
c56ce6ad36 | ||
|
4f0a3f5766 | ||
|
bac58be1ee | ||
|
20caaf26c8 | ||
|
3574118e17 | ||
|
847b717cdf | ||
|
3dfb51b25d | ||
|
d0b5dd8977 | ||
|
23d97eb4a8 | ||
|
8bc4e76e47 | ||
|
38762724f5 | ||
|
feb0bc1ae6 | ||
|
872d0baafb | ||
|
35c3f065a3 | ||
|
8b12191bda | ||
|
90b2c57951 | ||
|
f484a9dfce | ||
|
b97c275de5 | ||
|
91c95d8ba7 | ||
|
2015c99e65 | ||
|
eadf15d9c0 | ||
|
bb8c5657e1 | ||
|
dc2eae08a6 | ||
|
6c13a98f01 | ||
|
1ad294dcd3 | ||
|
806df574e7 | ||
|
9b580c7a98 | ||
|
7c8e2324ab | ||
|
555933315d | ||
|
9121746f05 | ||
|
f1d45da676 | ||
|
cf147a440e | ||
|
a3a23e5759 | ||
|
bc7d1cd44a | ||
|
735fb7be0e | ||
|
4661f22e81 | ||
|
bfd8776042 | ||
|
e8ff13cd53 | ||
|
1771f6da8d | ||
|
e888e968b6 | ||
|
68df079c0e | ||
|
563c4c290d | ||
|
ffbcfd53f9 | ||
|
fd12328293 | ||
|
b387abea6b | ||
|
efdd038fa4 | ||
|
94b699d8df | ||
|
226efecdd6 | ||
|
a0b4397ddf | ||
|
c18f5e054e | ||
|
360d43dd4d | ||
|
e0165a2d6a | ||
|
9776ebfa0f | ||
|
eda3ecb0b3 | ||
|
cf7631d469 | ||
|
185a2f3437 | ||
|
bdc971eca3 | ||
|
288b7e9ca3 | ||
|
a9d5880dc8 | ||
|
0918984249 | ||
|
e2aa4bc33c | ||
|
9d3db318e3 | ||
|
5aa123b4f0 | ||
|
f11d34997a | ||
|
510814410c | ||
|
e4bae61393 | ||
|
4cfc50c358 | ||
|
6886cdaace | ||
|
17e6952ab8 | ||
|
0da4084064 | ||
|
4c9a51990c | ||
|
36a86d34e8 | ||
|
fb514ca90f | ||
|
aa5e28bef5 | ||
|
5dc3d8c936 | ||
|
a4ffe2fdbf | ||
|
c32fa662d5 | ||
|
0a9588a866 | ||
|
861b868416 | ||
|
b7f9662097 | ||
|
79ecb11ce2 | ||
|
4e9bb610b3 | ||
|
c88faf8cfa | ||
|
0b48eab7a6 | ||
|
ccfbd1ee31 | ||
|
98c9a5d948 | ||
|
96ea42e5f4 | ||
|
2ff2a818ef | ||
|
dd694c266e | ||
|
c4461f7d78 | ||
|
77de5160ac | ||
|
b9fcc5ae2d | ||
|
e42883bf2c | ||
|
5c41a45931 | ||
|
ba49ba0acd | ||
|
5d75632c8e | ||
|
e202a33ea1 | ||
|
93be82ebc9 | ||
|
0bf4753ff1 | ||
|
fbb07a1494 | ||
|
debb66f8b0 | ||
|
45185b36fb | ||
|
e761d79512 | ||
|
14064dd987 | ||
|
3eef8590f4 | ||
|
3e7ad18fe3 | ||
|
80a38590b8 | ||
|
44a6e29da7 | ||
|
a6e847e267 | ||
|
2f70906665 | ||
|
c4c919aa31 | ||
|
51491c3c08 | ||
|
ea17f6ad28 | ||
|
3691c9945a | ||
|
57629bcaca | ||
|
b38ee77628 | ||
|
b5413cc015 | ||
|
5edaa96164 | ||
|
12a2a451b4 | ||
|
fc7dff50b0 | ||
|
9272e09058 | ||
|
b13c4d5f8d | ||
|
d7b10b4352 | ||
|
05cddff72d | ||
|
a55d23aaa4 | ||
|
18b71743c8 | ||
|
f761ff6824 | ||
|
8e2d233445 | ||
|
59b1f362f6 | ||
|
a73c641a0f | ||
|
3d4c72da0b | ||
|
71547b3fb3 | ||
|
ad8da94d2a | ||
|
5ea762a46c | ||
|
bbb5829ad9 | ||
|
c00b382f13 | ||
|
964e2bdac3 | ||
|
2e7ab99099 | ||
|
4175f28979 | ||
|
207f90f01b | ||
|
5c43ddb56c | ||
|
3838766dd4 | ||
|
a006457a72 | ||
|
0449107230 | ||
|
75313d886b | ||
|
4998f58847 | ||
|
ffc094bd91 | ||
|
343326eacf | ||
|
d31bc4347a | ||
|
adfb951e51 | ||
|
2843a2c0e8 | ||
|
94d3dc254e | ||
|
915eb55779 | ||
|
547bc38118 | ||
|
93fd013aa1 | ||
|
512bfde7ce | ||
|
27ba45ded7 | ||
|
c0898dedb1 | ||
|
b82b920420 | ||
|
ac40f7cfd8 | ||
|
330c51de9f | ||
|
0ed527f0d1 | ||
|
7df1dec65c | ||
|
61d42ee87b | ||
|
a95e65eea1 | ||
|
71dce0e7f3 | ||
|
53af1dc32d | ||
|
52252b15d6 | ||
|
bc24ce9ad4 | ||
|
625e986552 | ||
|
095442191c | ||
|
cc46282866 | ||
|
cbc9c3629d | ||
|
2c49d905e4 | ||
|
f0e2f642e0 | ||
|
3d0f0c0565 | ||
|
3d442cdf98 | ||
|
b009fee5ea | ||
|
6cf747678c | ||
|
db812e1179 | ||
|
995f23b58f | ||
|
ef3830234d | ||
|
4fc55cfcec | ||
|
487ac3bc48 | ||
|
d6cb3ba747 | ||
|
a9a2dceb72 | ||
|
bee08e48ae | ||
|
b14fb9db24 | ||
|
91acb0d16f | ||
|
4f161705a3 | ||
|
f8c6e90647 | ||
|
dd9dc4f76b | ||
|
94f49fd99b | ||
|
498df11a50 | ||
|
db7da314e7 | ||
|
33aabc696a | ||
|
648bedf290 | ||
|
dd3d1b8cdb | ||
|
b39a156d57 | ||
|
b6158c09b4 | ||
|
8a11a46f66 | ||
|
4d73c1e511 | ||
|
280f3eeb4e | ||
|
1321160203 | ||
|
01680e444b | ||
|
2435453c33 | ||
|
6e466e5ab4 | ||
|
004d2d5122 | ||
|
60b3428ad7 | ||
|
571970f8ff | ||
|
18a0653ce8 | ||
|
569286055c |
23
.github/workflows/Auto-merge-dependabot-PRs.yml
vendored
23
.github/workflows/Auto-merge-dependabot-PRs.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
# This workflow triggers auto-merge of any PR that dependabot creates so that
|
|
||||||
# PRs will be merged automatically without maintainer intervention if CI passes
|
|
||||||
name: Auto-merge dependabot PRs
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
auto-merge:
|
|
||||||
if: github.repository == 'sharkdp/bat' && startsWith(github.head_ref, 'dependabot/')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment:
|
|
||||||
name: auto-merge
|
|
||||||
url: https://github.com/sharkdp/bat/blob/main/.github/workflows/Auto-merge-dependabot-PRs.yml
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.AUTO_MERGE_GITHUB_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
gh pr review ${{ github.event.pull_request.number }} --comment --body "If CI passes, this dependabot PR will be [auto-merged](https://github.com/sharkdp/bat/blob/main/.github/workflows/Auto-merge-dependabot-PRs.yml) 🚀"
|
|
||||||
- run: |
|
|
||||||
gh pr merge --auto --squash ${{ github.event.pull_request.number }}
|
|
67
.github/workflows/CICD.yml
vendored
67
.github/workflows/CICD.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- crate_metadata
|
- crate_metadata
|
||||||
- ensure_cargo_fmt
|
- lint
|
||||||
- min_version
|
- min_version
|
||||||
- license_checks
|
- license_checks
|
||||||
- test_with_new_syntaxes_and_themes
|
- test_with_new_syntaxes_and_themes
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
name: Extract crate metadata
|
name: Extract crate metadata
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- name: Extract crate information
|
- name: Extract crate information
|
||||||
id: crate_metadata
|
id: crate_metadata
|
||||||
run: |
|
run: |
|
||||||
@@ -51,49 +51,46 @@ jobs:
|
|||||||
homepage: ${{ steps.crate_metadata.outputs.homepage }}
|
homepage: ${{ steps.crate_metadata.outputs.homepage }}
|
||||||
msrv: ${{ steps.crate_metadata.outputs.msrv }}
|
msrv: ${{ steps.crate_metadata.outputs.msrv }}
|
||||||
|
|
||||||
ensure_cargo_fmt:
|
lint:
|
||||||
name: Ensure 'cargo fmt' has been run
|
name: Ensure code quality
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
components: rustfmt
|
components: rustfmt,clippy
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- run: cargo fmt -- --check
|
- run: cargo fmt -- --check
|
||||||
|
- run: cargo clippy --locked --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
min_version:
|
min_version:
|
||||||
name: Minimum supported rust version
|
name: Minimum supported rust version
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
needs: crate_metadata
|
needs: crate_metadata
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
|
- name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ needs.crate_metadata.outputs.msrv }}
|
toolchain: ${{ needs.crate_metadata.outputs.msrv }}
|
||||||
components: clippy
|
|
||||||
- name: Run clippy (on minimum supported rust version to prevent warnings we can't fix)
|
|
||||||
run: cargo clippy --locked --all-targets ${{ env.MSRV_FEATURES }}
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --locked ${{ env.MSRV_FEATURES }}
|
run: cargo test --locked ${{ env.MSRV_FEATURES }}
|
||||||
|
|
||||||
license_checks:
|
license_checks:
|
||||||
name: License checks
|
name: License checks
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true # we especially want to perform license checks on submodules
|
submodules: true # we especially want to perform license checks on submodules
|
||||||
- run: tests/scripts/license-checks.sh
|
- run: tests/scripts/license-checks.sh
|
||||||
|
|
||||||
test_with_new_syntaxes_and_themes:
|
test_with_new_syntaxes_and_themes:
|
||||||
name: Run tests with updated syntaxes and themes
|
name: Run tests with updated syntaxes and themes
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: true # we need all syntax and theme submodules
|
submodules: true # we need all syntax and theme submodules
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
@@ -119,10 +116,10 @@ jobs:
|
|||||||
|
|
||||||
test_with_system_config:
|
test_with_system_config:
|
||||||
name: Run tests with system wide configuration
|
name: Run tests with system wide configuration
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- name: Prepare environment variables
|
- name: Prepare environment variables
|
||||||
run: |
|
run: |
|
||||||
echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV
|
echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV
|
||||||
@@ -135,10 +132,10 @@ jobs:
|
|||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
name: Documentation
|
name: Documentation
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
- name: Check documentation
|
- name: Check documentation
|
||||||
@@ -153,7 +150,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- run: cargo install cargo-audit --locked
|
- run: cargo install cargo-audit --locked
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- run: cargo audit
|
- run: cargo audit
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@@ -164,24 +161,24 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
- { target: aarch64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
|
- { target: aarch64-unknown-linux-musl , os: ubuntu-latest, dpkg_arch: arm64, use-cross: true }
|
||||||
- { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
|
- { target: aarch64-unknown-linux-gnu , os: ubuntu-latest, 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-gnueabihf , os: ubuntu-latest, dpkg_arch: armhf, use-cross: true }
|
||||||
- { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, dpkg_arch: musl-linux-armhf, use-cross: true }
|
- { target: arm-unknown-linux-musleabihf, os: ubuntu-latest, dpkg_arch: musl-linux-armhf, use-cross: true }
|
||||||
- { target: i686-pc-windows-msvc , os: windows-2019, }
|
- { target: i686-pc-windows-msvc , os: windows-2025, }
|
||||||
- { target: i686-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: i686, use-cross: true }
|
- { target: i686-unknown-linux-gnu , os: ubuntu-latest, dpkg_arch: i686, use-cross: true }
|
||||||
- { target: i686-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-i686, use-cross: true }
|
- { target: i686-unknown-linux-musl , os: ubuntu-latest, dpkg_arch: musl-linux-i686, use-cross: true }
|
||||||
- { target: x86_64-apple-darwin , os: macos-13, }
|
- { target: x86_64-apple-darwin , os: macos-13, }
|
||||||
- { target: aarch64-apple-darwin , os: macos-14, }
|
- { target: aarch64-apple-darwin , os: macos-14, }
|
||||||
- { target: x86_64-pc-windows-gnu , os: windows-2019, }
|
- { target: x86_64-pc-windows-msvc , os: windows-2025, }
|
||||||
- { target: x86_64-pc-windows-msvc , os: windows-2019, }
|
- { target: aarch64-pc-windows-msvc , os: windows-11-arm, }
|
||||||
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: amd64, use-cross: true }
|
- { target: x86_64-unknown-linux-gnu , os: ubuntu-latest, dpkg_arch: amd64, use-cross: true }
|
||||||
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-amd64, use-cross: true }
|
- { target: x86_64-unknown-linux-musl , os: ubuntu-latest, dpkg_arch: musl-linux-amd64, use-cross: true }
|
||||||
env:
|
env:
|
||||||
BUILD_CMD: cargo
|
BUILD_CMD: cargo
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -462,7 +459,7 @@ jobs:
|
|||||||
needs: build
|
needs: build
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
steps:
|
steps:
|
||||||
- uses: vedantmgoyal2009/winget-releaser@v2
|
- uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f
|
||||||
with:
|
with:
|
||||||
identifier: sharkdp.bat
|
identifier: sharkdp.bat
|
||||||
installers-regex: '-pc-windows-msvc\.zip$'
|
installers-regex: '-pc-windows-msvc\.zip$'
|
||||||
|
@@ -30,4 +30,4 @@ jobs:
|
|||||||
echo "Added lines in CHANGELOG.md:"
|
echo "Added lines in CHANGELOG.md:"
|
||||||
echo "$ADDED"
|
echo "$ADDED"
|
||||||
echo "Grepping for PR info (see CONTRIBUTING.md):"
|
echo "Grepping for PR info (see CONTRIBUTING.md):"
|
||||||
grep "#${PR_NUMBER}\\b.*@${PR_SUBMITTER}\\b" <<< "$ADDED"
|
grep "#${PR_NUMBER}\\b.*${PR_SUBMITTER}\\b" <<< "$ADDED"
|
||||||
|
39
.gitmodules
vendored
39
.gitmodules
vendored
@@ -65,7 +65,7 @@
|
|||||||
path = assets/themes/onehalf
|
path = assets/themes/onehalf
|
||||||
url = https://github.com/sonph/onehalf
|
url = https://github.com/sonph/onehalf
|
||||||
[submodule "assets/syntaxes/JavaScript (Babel)"]
|
[submodule "assets/syntaxes/JavaScript (Babel)"]
|
||||||
path = assets/syntaxes/02_Extra/JavaScript (Babel)
|
path = assets/syntaxes/02_Extra/JavaScript_(Babel)
|
||||||
url = https://github.com/babel/babel-sublime
|
url = https://github.com/babel/babel-sublime
|
||||||
[submodule "assets/syntaxes/FSharp"]
|
[submodule "assets/syntaxes/FSharp"]
|
||||||
path = assets/syntaxes/02_Extra/FSharp
|
path = assets/syntaxes/02_Extra/FSharp
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
path = assets/themes/sublime-snazzy
|
path = assets/themes/sublime-snazzy
|
||||||
url = https://github.com/greggb/sublime-snazzy
|
url = https://github.com/greggb/sublime-snazzy
|
||||||
[submodule "assets/syntaxes/Assembly (ARM)"]
|
[submodule "assets/syntaxes/Assembly (ARM)"]
|
||||||
path = assets/syntaxes/02_Extra/Assembly (ARM)
|
path = assets/syntaxes/02_Extra/Assembly_(ARM)
|
||||||
url = https://github.com/tvi/Sublime-ARM-Assembly
|
url = https://github.com/tvi/Sublime-ARM-Assembly
|
||||||
[submodule "assets/syntaxes/protobuf-syntax-highlighting"]
|
[submodule "assets/syntaxes/protobuf-syntax-highlighting"]
|
||||||
path = assets/syntaxes/02_Extra/Protobuf
|
path = assets/syntaxes/02_Extra/Protobuf
|
||||||
@@ -108,14 +108,11 @@
|
|||||||
path = assets/syntaxes/02_Extra/Fish
|
path = assets/syntaxes/02_Extra/Fish
|
||||||
url = https://github.com/Phidica/sublime-fish.git
|
url = https://github.com/Phidica/sublime-fish.git
|
||||||
[submodule "assets/syntaxes/Org mode"]
|
[submodule "assets/syntaxes/Org mode"]
|
||||||
path = assets/syntaxes/02_Extra/Org mode
|
path = assets/syntaxes/02_Extra/Org_mode
|
||||||
url = https://github.com/jezcope/Org.tmbundle.git
|
url = https://github.com/jezcope/Org.tmbundle.git
|
||||||
[submodule "assets/syntaxes/DotENV"]
|
[submodule "assets/syntaxes/DotENV"]
|
||||||
path = assets/syntaxes/02_Extra/DotENV
|
path = assets/syntaxes/02_Extra/DotENV
|
||||||
url = https://github.com/zaynali53/DotENV
|
url = https://github.com/zaynali53/DotENV
|
||||||
[submodule "assets/syntaxes/hosts"]
|
|
||||||
path = assets/syntaxes/02_Extra/hosts
|
|
||||||
url = https://github.com/brandonwamboldt/sublime-hosts
|
|
||||||
[submodule "assets/syntaxes/ssh-config"]
|
[submodule "assets/syntaxes/ssh-config"]
|
||||||
path = assets/syntaxes/02_Extra/ssh-config
|
path = assets/syntaxes/02_Extra/ssh-config
|
||||||
url = https://github.com/robballou/sublimetext-sshconfig.git
|
url = https://github.com/robballou/sublimetext-sshconfig.git
|
||||||
@@ -142,7 +139,7 @@
|
|||||||
path = assets/themes/dracula-sublime
|
path = assets/themes/dracula-sublime
|
||||||
url = https://github.com/dracula/sublime.git
|
url = https://github.com/dracula/sublime.git
|
||||||
[submodule "assets/syntaxes/HTML (Twig)"]
|
[submodule "assets/syntaxes/HTML (Twig)"]
|
||||||
path = assets/syntaxes/02_Extra/HTML (Twig)
|
path = assets/syntaxes/02_Extra/HTML_(Twig)
|
||||||
url = https://github.com/Anomareh/PHP-Twig.tmbundle.git
|
url = https://github.com/Anomareh/PHP-Twig.tmbundle.git
|
||||||
[submodule "assets/themes/Nord-sublime"]
|
[submodule "assets/themes/Nord-sublime"]
|
||||||
path = assets/themes/Nord-sublime
|
path = assets/themes/Nord-sublime
|
||||||
@@ -177,7 +174,7 @@
|
|||||||
url = https://github.com/euler0/sublime-glsl
|
url = https://github.com/euler0/sublime-glsl
|
||||||
[submodule "assets/syntaxes/02_Extra/Nginx"]
|
[submodule "assets/syntaxes/02_Extra/Nginx"]
|
||||||
path = assets/syntaxes/02_Extra/Nginx
|
path = assets/syntaxes/02_Extra/Nginx
|
||||||
url = https://github.com/brandonwamboldt/sublime-nginx
|
url = https://github.com/SublimeText/nginx
|
||||||
[submodule "assets/syntaxes/02_Extra/Apache"]
|
[submodule "assets/syntaxes/02_Extra/Apache"]
|
||||||
path = assets/syntaxes/02_Extra/Apache
|
path = assets/syntaxes/02_Extra/Apache
|
||||||
url = https://github.com/colinta/ApacheConf.tmLanguage
|
url = https://github.com/colinta/ApacheConf.tmLanguage
|
||||||
@@ -196,10 +193,7 @@
|
|||||||
branch = bat-source
|
branch = bat-source
|
||||||
[submodule "assets/syntaxes/02_Extra/Lean"]
|
[submodule "assets/syntaxes/02_Extra/Lean"]
|
||||||
path = assets/syntaxes/02_Extra/Lean
|
path = assets/syntaxes/02_Extra/Lean
|
||||||
url = https://github.com/leanprover/vscode-lean.git
|
url = https://github.com/leanprover/vscode-lean4.git
|
||||||
[submodule "assets/syntaxes/02_Extra/LiveScript"]
|
|
||||||
path = assets/syntaxes/02_Extra/LiveScript
|
|
||||||
url = https://github.com/paulmillr/LiveScript.tmbundle
|
|
||||||
[submodule "assets/syntaxes/02_Extra/Zig"]
|
[submodule "assets/syntaxes/02_Extra/Zig"]
|
||||||
path = assets/syntaxes/02_Extra/Zig
|
path = assets/syntaxes/02_Extra/Zig
|
||||||
url = https://github.com/ziglang/sublime-zig-language.git
|
url = https://github.com/ziglang/sublime-zig-language.git
|
||||||
@@ -263,3 +257,24 @@
|
|||||||
[submodule "assets/syntaxes/02_Extra/CFML"]
|
[submodule "assets/syntaxes/02_Extra/CFML"]
|
||||||
path = assets/syntaxes/02_Extra/CFML
|
path = assets/syntaxes/02_Extra/CFML
|
||||||
url = https://github.com/jcberquist/sublimetext-cfml.git
|
url = https://github.com/jcberquist/sublimetext-cfml.git
|
||||||
|
[submodule "assets/syntaxes/02_Extra/Idris2"]
|
||||||
|
path = assets/syntaxes/02_Extra/Idris2
|
||||||
|
url = https://github.com/buzden/sublime-syntax-idris2
|
||||||
|
[submodule "assets/syntaxes/02_Extra/GDScript-sublime"]
|
||||||
|
path = assets/syntaxes/02_Extra/GDScript-sublime
|
||||||
|
url = https://github.com/beefsack/GDScript-sublime
|
||||||
|
[submodule "assets/syntaxes/02_Extra/sublime-odin"]
|
||||||
|
path = assets/syntaxes/02_Extra/sublime-odin
|
||||||
|
url = https://github.com/odin-lang/sublime-odin
|
||||||
|
[submodule "assets/syntaxes/02_Extra/typst-syntax-highlight"]
|
||||||
|
path = assets/syntaxes/02_Extra/typst-syntax-highlight
|
||||||
|
url = https://github.com/hyrious/typst-syntax-highlight
|
||||||
|
[submodule "assets/themes/Catppuccin"]
|
||||||
|
path = assets/themes/Catppuccin
|
||||||
|
url = https://github.com/SchweGELBin/catppuccin-bat-sub.git
|
||||||
|
[submodule "assets/syntaxes/02_Extra/SmartVHDL"]
|
||||||
|
path = assets/syntaxes/02_Extra/SmartVHDL
|
||||||
|
url = https://github.com/TheClams/SmartVHDL
|
||||||
|
[submodule "assets/syntaxes/02_Extra/hosts"]
|
||||||
|
path = assets/syntaxes/02_Extra/hosts
|
||||||
|
url = https://github.com/tijn/hosts.tmLanguage
|
||||||
|
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,3 +1,68 @@
|
|||||||
|
# unreleased
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Add build for windows/ARM64 platform. #3190 (@alcroito)
|
||||||
|
|
||||||
|
- Add paging to `--list-themes`, see PR #3239 (@einfachIrgendwer0815)
|
||||||
|
- Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow)
|
||||||
|
- Support context in line ranges, e.g. `bat -r 30::5` / `bat -r 30:40:5`, see #3345 (@cavanaug)
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
- Fix UTF-8 BOM not being stripped for syntax detection, see #3314 (@krikera)
|
||||||
|
- Fix `BAT_THEME_DARK` and `BAT_THEME_LIGHT` being ignored, see issue #3171 and PR #3168 (@bash)
|
||||||
|
- Prevent `--list-themes` from outputting default theme info to stdout when it is piped, see #3189 (@einfachIrgendwer0815)
|
||||||
|
- Rename some submodules to fix Dependabot submodule updates, see issue #3198 and PR #3201 (@victor-gp)
|
||||||
|
- Make highlight tests fail when new syntaxes don't have fixtures PR #3255 (@dan-hipschman)
|
||||||
|
- Fix crash for multibyte characters in file path, see issue #3230 and PR #3245 (@HSM95)
|
||||||
|
- Add missing mappings for various bash/zsh files, see PR #3262 (@AdamGaskins)
|
||||||
|
- Send all bat errors to stderr by default, see #3336 (@JerryImMouse)
|
||||||
|
- Make --map-syntax target case insensitive to match --language, see #3206 (@keith-hall)
|
||||||
|
- Correctly determine the end of the line in UTF16LE/BE input #3369 (@keith-hall)
|
||||||
|
|
||||||
|
## Other
|
||||||
|
|
||||||
|
- Update base16 README links to community driven base16 work #2871 (@JamyGolden)
|
||||||
|
- Work around build failures when building `bat` from vendored sources #3179 (@dtolnay)
|
||||||
|
- CICD: Stop building for x86_64-pc-windows-gnu which fails #3261 (Enselic)
|
||||||
|
- CICD: CICD: replace windows-2019 runners with windows-2025 #3339 (@cyqsimon)
|
||||||
|
- Build script: replace string-based codegen with quote-based codegen #3340 (@cyqsimon)
|
||||||
|
- Improve code coverage of `--list-languages` parameter #2942 (@sblondon)
|
||||||
|
- Only start offload worker thread when there's more than 1 core #2956 (@cyqsimon)
|
||||||
|
- Update terminal-colorsaurus (the library used for dark/light detection) to 1.0, see #3347 (@bash)
|
||||||
|
- Update console dependency to 0.16, see #3351 (@musicinmybrain)
|
||||||
|
- Fixed some typos #3244 (@ssbarnea)
|
||||||
|
|
||||||
|
## Syntaxes
|
||||||
|
|
||||||
|
- Add syntax mapping for `paru` configuration files #3182 (@cyqsimon)
|
||||||
|
- Add support for [Idris 2 programming language](https://www.idris-lang.org/) #3150 (@buzden)
|
||||||
|
- Add syntax mapping for `nix`'s '`flake.lock` lockfiles #3196 (@odilf)
|
||||||
|
- Improvements to CSV/TSV highlighting, with autodetection of delimiter and support for TSV files, see #3186 (@keith-
|
||||||
|
- Improve (Sys)log error highlighting, see #3205 (@keith-hall)
|
||||||
|
- Map `ndjson` extension to JSON syntax, see #3209 (@keith-hall)
|
||||||
|
- Map files with `csproj`, `vbproj`, `props` and `targets` extensions to XML syntax, see #3213 (@keith-hall)
|
||||||
|
- Add debsources syntax to highlight `/etc/apt/sources.list` files, see #3215 (@keith-hall)
|
||||||
|
- Add syntax definition and test file for GDScript highlighting, see #3236 (@chetanjangir0)
|
||||||
|
- Add syntax test file for Odin highlighting, see #3241 (@chetanjangir0)
|
||||||
|
- Update quadlet syntax mapping rules to cover quadlets in subdirectories #3299 (@cyqsimon)
|
||||||
|
- Add syntax Typst #3300 (@cskeeters)
|
||||||
|
- Map `.mill` files to Scala syntax for Mill build tool configuration files #3311 (@krikera)
|
||||||
|
- Add syntax highlighting for VHDL, see #3337 (@JerryImMouse)
|
||||||
|
- Add syntax mapping for certbot certificate configuration #3338 (@cyqsimon)
|
||||||
|
- Update Lean syntax from Lean 3 to Lean 4 #3322 (@YDX-2147483647)
|
||||||
|
- Map `.flatpakref` and `.flatpakrepo` files to INI syntax #3353 (@Ferenc-)
|
||||||
|
- Update hosts syntax #3368 (@keith-hall)
|
||||||
|
|
||||||
|
## Themes
|
||||||
|
|
||||||
|
- Add Catppuccin, see #3317 (@SchweGELBin)
|
||||||
|
- Updated Catppuccin, see #3333 (@SchweGELBin)
|
||||||
|
- Updated gruvbox, see #3372 (@Nicholas42)
|
||||||
|
- Updated GitHub theme, see #3382 (@CosmicHorrorDev)
|
||||||
|
|
||||||
|
## `bat` as a library
|
||||||
|
|
||||||
# v0.25.0
|
# v0.25.0
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
1133
Cargo.lock
generated
1133
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
33
Cargo.toml
33
Cargo.toml
@@ -10,6 +10,7 @@ version = "0.25.0"
|
|||||||
exclude = ["assets/syntaxes/*", "assets/themes/*"]
|
exclude = ["assets/syntaxes/*", "assets/themes/*"]
|
||||||
build = "build/main.rs"
|
build = "build/main.rs"
|
||||||
edition = '2021'
|
edition = '2021'
|
||||||
|
# You are free to bump MSRV as soon as a reason for bumping emerges.
|
||||||
rust-version = "1.74"
|
rust-version = "1.74"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -44,14 +45,14 @@ regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine
|
|||||||
nu-ansi-term = "0.50.0"
|
nu-ansi-term = "0.50.0"
|
||||||
ansi_colours = "^1.2"
|
ansi_colours = "^1.2"
|
||||||
bincode = "1.0"
|
bincode = "1.0"
|
||||||
console = "0.15.10"
|
console = "0.16.0"
|
||||||
flate2 = "1.0"
|
flate2 = "1.1"
|
||||||
once_cell = "1.20"
|
once_cell = "1.20"
|
||||||
thiserror = "1.0"
|
thiserror = "2.0"
|
||||||
wild = { version = "2.2", optional = true }
|
wild = { version = "2.2", optional = true }
|
||||||
content_inspector = "0.2.4"
|
content_inspector = "0.2.4"
|
||||||
shell-words = { version = "1.1.0", optional = true }
|
shell-words = { version = "1.1.0", optional = true }
|
||||||
unicode-width = "0.1.13"
|
unicode-width = "0.2.1"
|
||||||
globset = "0.4"
|
globset = "0.4"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
@@ -60,17 +61,19 @@ semver = "1.0"
|
|||||||
path_abs = { version = "0.5", default-features = false }
|
path_abs = { version = "0.5", default-features = false }
|
||||||
clircle = { version = "0.6.1", default-features = false }
|
clircle = { version = "0.6.1", default-features = false }
|
||||||
bugreport = { version = "0.5.0", optional = true }
|
bugreport = { version = "0.5.0", optional = true }
|
||||||
etcetera = { version = "0.8.0", optional = true }
|
etcetera = { version = "0.10.0", optional = true }
|
||||||
grep-cli = { version = "0.1.11", optional = true }
|
grep-cli = { version = "0.1.11", optional = true }
|
||||||
regex = { version = "1.10.6", optional = true }
|
regex = { version = "1.10.6", optional = true }
|
||||||
walkdir = { version = "2.5", optional = true }
|
walkdir = { version = "2.5", optional = true }
|
||||||
bytesize = { version = "1.3.0" }
|
bytesize = { version = "1.3.0" }
|
||||||
encoding_rs = "0.8.35"
|
encoding_rs = "0.8.35"
|
||||||
execute = { version = "0.2.13", optional = true }
|
execute = { version = "0.2.13", optional = true }
|
||||||
terminal-colorsaurus = "0.4"
|
terminal-colorsaurus = "1.0"
|
||||||
|
unicode-segmentation = "1.12.0"
|
||||||
|
itertools = "0.13.0"
|
||||||
|
|
||||||
[dependencies.git2]
|
[dependencies.git2]
|
||||||
version = "0.19"
|
version = "0.20"
|
||||||
optional = true
|
optional = true
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
@@ -94,22 +97,26 @@ expect-test = "1.5.0"
|
|||||||
serial_test = { version = "2.0.0", default-features = false }
|
serial_test = { version = "2.0.0", default-features = false }
|
||||||
predicates = "3.1.3"
|
predicates = "3.1.3"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.0"
|
||||||
tempfile = "3.8.1"
|
tempfile = "3.16.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
nix = { version = "0.29", default-features = false, features = ["term"] }
|
nix = { version = "0.30", default-features = false, features = ["term"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.97"
|
||||||
indexmap = { version = "2.3.0", features = ["serde"] }
|
indexmap = { version = "2.8.0", features = ["serde"] }
|
||||||
itertools = "0.13.0"
|
itertools = "0.14.0"
|
||||||
once_cell = "1.20"
|
once_cell = "1.20"
|
||||||
|
prettyplease = "0.2.35"
|
||||||
|
proc-macro2 = "1.0.95"
|
||||||
|
quote = "1.0.40"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_with = { version = "3.12.0", default-features = false, features = ["macros"] }
|
serde_with = { version = "3.12.0", default-features = false, features = ["macros"] }
|
||||||
toml = { version = "0.8.19", features = ["preserve_order"] }
|
syn = { version = "2.0.104", features = ["full"] }
|
||||||
|
toml = { version = "0.9.1", features = ["preserve_order"] }
|
||||||
walkdir = "2.5"
|
walkdir = "2.5"
|
||||||
|
|
||||||
[build-dependencies.clap]
|
[build-dependencies.clap]
|
||||||
|
182
README.md
182
README.md
@@ -22,25 +22,22 @@
|
|||||||
### Sponsors
|
### Sponsors
|
||||||
|
|
||||||
A special *thank you* goes to our biggest <a href="doc/sponsors.md">sponsors</a>:<br>
|
A special *thank you* goes to our biggest <a href="doc/sponsors.md">sponsors</a>:<br>
|
||||||
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=bat&utm_source=github">
|
|
||||||
<img src="doc/sponsors/workos-logo-white-bg.svg" width="200" alt="WorkOS">
|
|
||||||
<br>
|
|
||||||
<strong>Your app, enterprise-ready.</strong>
|
|
||||||
<br>
|
|
||||||
<sub>Start selling to enterprise customers with just a few lines of code.</sub>
|
|
||||||
<br>
|
|
||||||
<sup>Add Single Sign-On (and more) in minutes instead of months.</sup>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=bat_20231001">
|
<p>
|
||||||
|
<a href="https://www.warp.dev/bat">
|
||||||
<img src="doc/sponsors/warp-logo.png" width="200" alt="Warp">
|
<img src="doc/sponsors/warp-logo.png" width="200" alt="Warp">
|
||||||
<br>
|
<br>
|
||||||
<strong>Warp, the intelligent terminal</strong>
|
<strong>Warp, the intelligent terminal</strong>
|
||||||
<br>
|
<br>
|
||||||
<sub>Run commands like a power user with AI and your dev team’s</sub>
|
<sub>Available on MacOS, Linux, Windows</sub>
|
||||||
<br>
|
|
||||||
<sup>knowledge in one fast, intuitive terminal. For MacOS or Linux.</sup>
|
|
||||||
</a>
|
</a>
|
||||||
|
</p><p>
|
||||||
|
<a href="https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=bat">
|
||||||
|
<img src="doc/sponsors/graphite-logo.jpeg" width="200" alt="Graphite">
|
||||||
|
<br>
|
||||||
|
<strong>Graphite is the AI developer productivity platform helping<br>teams on GitHub ship higher quality software, faster</strong>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
### Syntax highlighting
|
### Syntax highlighting
|
||||||
|
|
||||||
@@ -124,7 +121,7 @@ bat f - g # output 'f', then stdin, then 'g'.
|
|||||||
#### `fzf`
|
#### `fzf`
|
||||||
|
|
||||||
You can use `bat` as a previewer for [`fzf`](https://github.com/junegunn/fzf). To do this,
|
You can use `bat` as a previewer for [`fzf`](https://github.com/junegunn/fzf). To do this,
|
||||||
use `bat`s `--color=always` option to force colorized output. You can also use `--line-range`
|
use `bat`'s `--color=always` option to force colorized output. You can also use `--line-range`
|
||||||
option to restrict the load times for long files:
|
option to restrict the load times for long files:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -181,7 +178,7 @@ You can combine `bat` with `git diff` to view lines around code changes with pro
|
|||||||
highlighting:
|
highlighting:
|
||||||
```bash
|
```bash
|
||||||
batdiff() {
|
batdiff() {
|
||||||
git diff --name-only --relative --diff-filter=d | xargs bat --diff
|
git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras).
|
If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras).
|
||||||
@@ -204,7 +201,7 @@ bat main.cpp | xclip
|
|||||||
`MANPAGER` environment variable:
|
`MANPAGER` environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MANPAGER="sh -c 'sed -u -e \"s/\\x1B\[[0-9;]*m//g; s/.\\x08//g\" | bat -p -lman'"
|
export MANPAGER="sh -c 'awk '\''{ gsub(/\x1B\[[0-9;]*m/, \"\", \$0); gsub(/.\x08/, \"\", \$0); print }'\'' | bat -p -lman'"
|
||||||
man 2 select
|
man 2 select
|
||||||
```
|
```
|
||||||
(replace `bat` with `batcat` if you are on Debian or Ubuntu)
|
(replace `bat` with `batcat` if you are on Debian or Ubuntu)
|
||||||
@@ -222,6 +219,12 @@ Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax)
|
|||||||
|
|
||||||
The [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) script is a wrapper that will format code and print it with `bat`.
|
The [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) script is a wrapper that will format code and print it with `bat`.
|
||||||
|
|
||||||
|
#### `Warp`
|
||||||
|
|
||||||
|
<a href="https://app.warp.dev/drive/folder/-Bat-Warp-Pack-lxhe7HrEwgwpG17mvrFSz1">
|
||||||
|
<img src="doc/sponsors/warp-pack-header.png" alt="Warp">
|
||||||
|
</a>
|
||||||
|
|
||||||
#### Highlighting `--help` messages
|
#### Highlighting `--help` messages
|
||||||
|
|
||||||
You can use `bat` to colorize help text: `$ cp --help | bat -plhelp`
|
You can use `bat` to colorize help text: `$ cp --help | bat -plhelp`
|
||||||
@@ -245,15 +248,32 @@ alias -g -- -h='-h 2>&1 | bat --language=help --style=plain'
|
|||||||
alias -g -- --help='--help 2>&1 | bat --language=help --style=plain'
|
alias -g -- --help='--help 2>&1 | bat --language=help --style=plain'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For `fish`, you can use abbreviations:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
abbr -a --position anywhere -- --help '--help | bat -plhelp'
|
||||||
|
abbr -a --position anywhere -- -h '-h | bat -plhelp'
|
||||||
|
```
|
||||||
|
|
||||||
This way, you can keep on using `cp --help`, but get colorized help pages.
|
This way, you can keep on using `cp --help`, but get colorized help pages.
|
||||||
|
|
||||||
Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`).
|
Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`). In cases where you need to use `-h`
|
||||||
|
as a command argument you can prepend `\` to the arguement (eg. `ls \-h`) to escape the aliasing defined above.
|
||||||
|
|
||||||
Please report any issues with the help syntax in [this repository](https://github.com/victor-gp/cmd-help-sublime-syntax).
|
Please report any issues with the help syntax in [this repository](https://github.com/victor-gp/cmd-help-sublime-syntax).
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Installation instructions need to:
|
||||||
|
* be for widely used systems
|
||||||
|
* be non-obvious
|
||||||
|
* be from somewhat official sources
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
[](https://repology.org/project/bat-cat/versions)
|
[](https://repology.org/project/bat-cat/versions)
|
||||||
|
|
||||||
### On Ubuntu (using `apt`)
|
### On Ubuntu (using `apt`)
|
||||||
@@ -274,6 +294,11 @@ mkdir -p ~/.local/bin
|
|||||||
ln -s /usr/bin/batcat ~/.local/bin/bat
|
ln -s /usr/bin/batcat ~/.local/bin/bat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
an example alias for `batcat` as `bat`:
|
||||||
|
```bash
|
||||||
|
alias bat="batcat"
|
||||||
|
```
|
||||||
|
|
||||||
### On Ubuntu (using most recent `.deb` packages)
|
### On Ubuntu (using most recent `.deb` packages)
|
||||||
*... and other Debian-based Linux distributions.*
|
*... and other Debian-based Linux distributions.*
|
||||||
|
|
||||||
@@ -311,14 +336,6 @@ You can install [the `bat` package](https://koji.fedoraproject.org/koji/packagei
|
|||||||
dnf install bat
|
dnf install bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### On Funtoo Linux
|
|
||||||
|
|
||||||
You can install [the `bat` package](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/bat) from dev-kit.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
emerge sys-apps/bat
|
|
||||||
```
|
|
||||||
|
|
||||||
### On Gentoo Linux
|
### On Gentoo Linux
|
||||||
|
|
||||||
You can install [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat)
|
You can install [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat)
|
||||||
@@ -328,20 +345,6 @@ from the official sources:
|
|||||||
emerge sys-apps/bat
|
emerge sys-apps/bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### On Void Linux
|
|
||||||
|
|
||||||
You can install `bat` via xbps-install:
|
|
||||||
```bash
|
|
||||||
xbps-install -S bat
|
|
||||||
```
|
|
||||||
|
|
||||||
### On Termux
|
|
||||||
|
|
||||||
You can install `bat` via pkg:
|
|
||||||
```bash
|
|
||||||
pkg install bat
|
|
||||||
```
|
|
||||||
|
|
||||||
### On FreeBSD
|
### On FreeBSD
|
||||||
|
|
||||||
You can install a precompiled [`bat` package](https://www.freshports.org/textproc/bat) with pkg:
|
You can install a precompiled [`bat` package](https://www.freshports.org/textproc/bat) with pkg:
|
||||||
@@ -373,14 +376,6 @@ You can install `bat` using the [nix package manager](https://nixos.org/nix):
|
|||||||
nix-env -i bat
|
nix-env -i bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### Via flox
|
|
||||||
|
|
||||||
You can install `bat` using [Flox](https://flox.dev)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flox install bat
|
|
||||||
```
|
|
||||||
|
|
||||||
### On openSUSE
|
### On openSUSE
|
||||||
|
|
||||||
You can install `bat` with zypper:
|
You can install `bat` with zypper:
|
||||||
@@ -417,7 +412,7 @@ take a look at the ["Using `bat` on Windows"](#using-bat-on-windows) section.
|
|||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package.
|
You will need to install the [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
|
||||||
|
|
||||||
#### With WinGet
|
#### With WinGet
|
||||||
|
|
||||||
@@ -458,14 +453,25 @@ binaries are also available: look for archives with `musl` in the file name.
|
|||||||
If you want to build `bat` from source, you need Rust 1.74.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:
|
higher. You can then use `cargo` to build everything:
|
||||||
|
|
||||||
|
#### From local source
|
||||||
|
```bash
|
||||||
|
cargo install --path . --locked
|
||||||
|
```
|
||||||
|
> [!NOTE]
|
||||||
|
> The `--path .` above specifies the directory of the source code and NOT where `bat` will be installed.
|
||||||
|
> For more information see the docs for [`cargo install`](https://doc.rust-lang.org/cargo/commands/cargo-install.html).
|
||||||
|
|
||||||
|
#### From `crates.io`
|
||||||
```bash
|
```bash
|
||||||
cargo install --locked bat
|
cargo install --locked bat
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that additional files like the man page or shell completion
|
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`).
|
files can not be installed automatically in both these ways.
|
||||||
|
If installing from a local source, they will be generated by `cargo`
|
||||||
|
and should be available in the cargo target folder under `build`.
|
||||||
|
|
||||||
Shell completions are also available by running:
|
Furthermore, shell completions are also available by running:
|
||||||
```bash
|
```bash
|
||||||
bat --completion <shell>
|
bat --completion <shell>
|
||||||
# see --help for supported shells
|
# see --help for supported shells
|
||||||
@@ -476,11 +482,12 @@ bat --completion <shell>
|
|||||||
### Highlighting theme
|
### Highlighting theme
|
||||||
|
|
||||||
Use `bat --list-themes` to get a list of all available themes for syntax
|
Use `bat --list-themes` to get a list of all available themes for syntax
|
||||||
highlighting. To select the `TwoDark` theme, call `bat` with the
|
highlighting. By default, `bat` uses `Monokai Extended` or `Monokai Extended Light`
|
||||||
`--theme=TwoDark` option or set the `BAT_THEME` environment variable to
|
for dark and light themes respectively. To select the `TwoDark` theme, call `bat`
|
||||||
|
with the `--theme=TwoDark` option or set the `BAT_THEME` environment variable to
|
||||||
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to
|
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to
|
||||||
make the change permanent. Alternatively, use `bat`s
|
make the change permanent. Alternatively, use `bat`'s
|
||||||
[configuration file](https://github.com/sharkdp/bat#configuration-file).
|
[configuration file](#configuration-file).
|
||||||
|
|
||||||
If you want to preview the different themes on a custom file, you can use
|
If you want to preview the different themes on a custom file, you can use
|
||||||
the following command (you need [`fzf`](https://github.com/junegunn/fzf) for this):
|
the following command (you need [`fzf`](https://github.com/junegunn/fzf) for this):
|
||||||
@@ -489,11 +496,11 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
|
|||||||
```
|
```
|
||||||
|
|
||||||
`bat` automatically picks a fitting theme depending on your terminal's background color.
|
`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
|
You can use the `--theme-dark` / `--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.
|
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
|
You can also use a custom theme by following the
|
||||||
['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes).
|
['Adding new themes' section below](#adding-new-themes).
|
||||||
|
|
||||||
### 8-bit themes
|
### 8-bit themes
|
||||||
|
|
||||||
@@ -502,12 +509,12 @@ even when truecolor support is available:
|
|||||||
|
|
||||||
- `ansi` looks decent on any terminal. It uses 3-bit colors: black, red, green,
|
- `ansi` looks decent on any terminal. It uses 3-bit colors: black, red, green,
|
||||||
yellow, blue, magenta, cyan, and white.
|
yellow, blue, magenta, cyan, and white.
|
||||||
- `base16` is designed for [base16](https://github.com/chriskempson/base16) terminal themes. It uses
|
- `base16` is designed for [base16](https://github.com/tinted-theming/home) terminal themes. It uses
|
||||||
4-bit colors (3-bit colors plus bright variants) in accordance with the
|
4-bit colors (3-bit colors plus bright variants) in accordance with the
|
||||||
[base16 styling guidelines](https://github.com/chriskempson/base16/blob/master/styling.md).
|
[base16 styling guidelines](https://github.com/tinted-theming/home/blob/main/styling.md).
|
||||||
- `base16-256` is designed for [base16-shell](https://github.com/chriskempson/base16-shell).
|
- `base16-256` is designed for [tinted-shell](https://github.com/tinted-theming/tinted-shell).
|
||||||
It replaces certain bright colors with 8-bit colors from 16 to 21. **Do not** use this simply
|
It replaces certain bright colors with 8-bit colors from 16 to 21. **Do not** use this simply
|
||||||
because you have a 256-color terminal but are not using base16-shell.
|
because you have a 256-color terminal but are not using tinted-shell.
|
||||||
|
|
||||||
Although these themes are more restricted, they have three advantages over truecolor themes. They:
|
Although these themes are more restricted, they have three advantages over truecolor themes. They:
|
||||||
|
|
||||||
@@ -517,11 +524,11 @@ Although these themes are more restricted, they have three advantages over truec
|
|||||||
|
|
||||||
### Output style
|
### Output style
|
||||||
|
|
||||||
You can use the `--style` option to control the appearance of `bat`s output.
|
You can use the `--style` option to control the appearance of `bat`'s output.
|
||||||
You can use `--style=numbers,changes`, for example, to show only Git changes
|
You can use `--style=numbers,changes`, for example, to show only Git changes
|
||||||
and line numbers but no grid and no file header. Set the `BAT_STYLE` environment
|
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
|
variable to make these changes permanent or use `bat`'s
|
||||||
[configuration file](https://github.com/sharkdp/bat#configuration-file).
|
[configuration file](#configuration-file).
|
||||||
|
|
||||||
>[!tip]
|
>[!tip]
|
||||||
> If you specify a default style in `bat`'s config file, you can change which components
|
> If you specify a default style in `bat`'s config file, you can change which components
|
||||||
@@ -578,6 +585,8 @@ syntax:
|
|||||||
### Adding new themes
|
### Adding new themes
|
||||||
|
|
||||||
This works very similar to how we add new syntax definitions.
|
This works very similar to how we add new syntax definitions.
|
||||||
|
> [!NOTE]
|
||||||
|
> Themes are stored in [`.tmTheme` files](https://www.sublimetext.com/docs/color_schemes_tmtheme.html).
|
||||||
|
|
||||||
First, create a folder with the new syntax highlighting themes:
|
First, create a folder with the new syntax highlighting themes:
|
||||||
```bash
|
```bash
|
||||||
@@ -592,6 +601,8 @@ bat cache --build
|
|||||||
```
|
```
|
||||||
|
|
||||||
Finally, use `bat --list-themes` to check if the new themes are available.
|
Finally, use `bat --list-themes` to check if the new themes are available.
|
||||||
|
> [!NOTE]
|
||||||
|
> `bat` uses the name of the `.tmTheme` file for the theme's name.
|
||||||
|
|
||||||
### Adding or changing file type associations
|
### Adding or changing file type associations
|
||||||
|
|
||||||
@@ -635,17 +646,17 @@ If you want to pass command-line arguments to the pager, you can also set them v
|
|||||||
`PAGER`/`BAT_PAGER` variables:
|
`PAGER`/`BAT_PAGER` variables:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export BAT_PAGER="less -RF"
|
export BAT_PAGER="less -RFK"
|
||||||
```
|
```
|
||||||
|
|
||||||
Instead of using environment variables, you can also use `bat`s [configuration file](https://github.com/sharkdp/bat#configuration-file) to configure the pager (`--pager` option).
|
Instead of using environment variables, you can also use `bat`'s [configuration file](#configuration-file) to configure the pager (`--pager` option).
|
||||||
|
|
||||||
|
|
||||||
### Using `less` as a pager
|
### Using `less` as a pager
|
||||||
|
|
||||||
When using `less` as a pager, `bat` will automatically pass extra options along to `less`
|
When using `less` as a pager, `bat` will automatically pass extra options along to `less`
|
||||||
to improve the experience. Specifically, `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen`,
|
to improve the experience. Specifically, `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen`,
|
||||||
and under certain conditions, `-X`/`--no-init` and/or `-S`/`--chop-long-lines`.
|
`-K`/`--quit-on-intr` and under certain conditions, `-X`/`--no-init` and/or `-S`/`--chop-long-lines`.
|
||||||
|
|
||||||
>[!IMPORTANT]
|
>[!IMPORTANT]
|
||||||
> These options will not be added if:
|
> These options will not be added if:
|
||||||
@@ -663,6 +674,9 @@ The `-F` option instructs `less` to exit immediately if the output size is small
|
|||||||
the vertical size of the terminal. This is convenient for small files because you do not
|
the vertical size of the terminal. This is convenient for small files because you do not
|
||||||
have to press `q` to quit the pager.
|
have to press `q` to quit the pager.
|
||||||
|
|
||||||
|
The `-K` option instructs `less` to exit immediately when an interrupt signal is received.
|
||||||
|
This is useful to ensure that `less` quits together with `bat` on SIGINT.
|
||||||
|
|
||||||
The `-X` option is needed to fix a bug with the `--quit-if-one-screen` feature in versions
|
The `-X` option is needed to fix a bug with the `--quit-if-one-screen` feature in versions
|
||||||
of `less` older than version 530. Unfortunately, it also breaks mouse-wheel support in `less`.
|
of `less` older than version 530. Unfortunately, it also breaks mouse-wheel support in `less`.
|
||||||
If you want to enable mouse-wheel scrolling on older versions of `less` and do not mind losing
|
If you want to enable mouse-wheel scrolling on older versions of `less` and do not mind losing
|
||||||
@@ -684,12 +698,40 @@ sidebar. Calling `bat` with `--tabs=0` will override it and let tabs be consumed
|
|||||||
|
|
||||||
### Dark mode
|
### Dark mode
|
||||||
|
|
||||||
If you make use of the dark mode feature in macOS, you might want to configure `bat` to use a different
|
If you make use of the dark mode feature in **macOS**, you might want to configure `bat` to use a different
|
||||||
theme based on the OS theme. The following snippet uses the `default` theme when in the _dark mode_
|
theme based on the OS theme. The following snippet uses the `default` theme when in the _dark mode_
|
||||||
and the `GitHub` theme when in the _light mode_.
|
and the `GitHub` theme when in the _light mode_.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)"
|
alias cat="bat --theme auto:system --theme-dark default --theme-light GitHub"
|
||||||
|
```
|
||||||
|
|
||||||
|
The same dark mode feature is now available in **GNOME** and affects the `org.gnome.desktop.interface color-scheme` setting. The following code converts the above to use said setting.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .bashrc
|
||||||
|
sys_color_scheme_is_dark() {
|
||||||
|
condition=$(gsettings get org.gnome.desktop.interface color-scheme)
|
||||||
|
condition=$(echo "$condition" | tr -d "[:space:]'")
|
||||||
|
if [ $condition == "prefer-dark" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
bat_alias_wrapper() {
|
||||||
|
#get color scheme
|
||||||
|
sys_color_scheme_is_dark
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
# bat command with dark color scheme
|
||||||
|
bat --theme=default "$@"
|
||||||
|
else
|
||||||
|
# bat command with light color scheme
|
||||||
|
bat --theme=GitHub "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
alias cat='bat_alias_wrapper'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -845,7 +887,7 @@ bash assets/create.sh
|
|||||||
cargo install --path . --locked --force
|
cargo install --path . --locked --force
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to build an application that uses `bat`s pretty-printing
|
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/).
|
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
|
Note that you have to use either `regex-onig` or `regex-fancy` as a feature
|
||||||
when you depend on `bat` as a library.
|
when you depend on `bat` as a library.
|
||||||
@@ -863,7 +905,7 @@ Take a look at the [`CONTRIBUTING.md`](CONTRIBUTING.md) guide.
|
|||||||
|
|
||||||
## Security vulnerabilities
|
## Security vulnerabilities
|
||||||
|
|
||||||
Please contact [David Peter](https://david-peter.de/) via email if you want to report a vulnerability in `bat`.
|
See [`SECURITY.md`](SECURITY.md).
|
||||||
|
|
||||||
## Project goals and alternatives
|
## Project goals and alternatives
|
||||||
|
|
||||||
|
3
SECURITY.md
Normal file
3
SECURITY.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Security Vulnerabilities
|
||||||
|
|
||||||
|
To report a security vulnerability, please contact [David Peter](https://david-peter.de/) via email.
|
BIN
assets/acknowledgements.bin
vendored
BIN
assets/acknowledgements.bin
vendored
Binary file not shown.
237
assets/completions/_bat.ps1.in
vendored
237
assets/completions/_bat.ps1.in
vendored
@@ -5,6 +5,24 @@ using namespace System.Management.Automation.Language
|
|||||||
Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -ScriptBlock {
|
Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -ScriptBlock {
|
||||||
param($wordToComplete, $commandAst, $cursorPosition)
|
param($wordToComplete, $commandAst, $cursorPosition)
|
||||||
|
|
||||||
|
$ArrayStyle = @('default', 'auto', 'full', 'plain', 'changes', 'header', 'header-filename', 'header-filesize', 'grid', 'rule', 'numbers', 'snip')
|
||||||
|
$ArrayCompletion = @('bash', 'fish', 'zsh', 'ps1')
|
||||||
|
$ArrayWhen = @('auto', 'never', 'always')
|
||||||
|
$ArrayYesNo = @('never', 'always')
|
||||||
|
$ArrayWrap = @('always', 'never', 'character')
|
||||||
|
$ArrayBinary = @('no-printing', 'as-text')
|
||||||
|
$ArrayPrint = @('unicode', 'caret')
|
||||||
|
|
||||||
|
function Get-MyThemes(){
|
||||||
|
$themes = {{PROJECT_EXECUTABLE}} --list-themes | ForEach-Object {$_ -replace "^(.*)$", '''$1'''} | select-object
|
||||||
|
return $themes
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MyLanguages(){
|
||||||
|
$themes = {{PROJECT_EXECUTABLE}} --list-languages | ForEach-Object{[pscustomobject]@{MyParameter=$_.Substring(0,$_.IndexOf(":")).Trim();MyDescription=$_.Substring($_.IndexOf(":")+1)}} | select-object
|
||||||
|
return $themes
|
||||||
|
}
|
||||||
|
|
||||||
$commandElements = $commandAst.CommandElements
|
$commandElements = $commandAst.CommandElements
|
||||||
$command = @(
|
$command = @(
|
||||||
'{{PROJECT_EXECUTABLE}}'
|
'{{PROJECT_EXECUTABLE}}'
|
||||||
@@ -12,86 +30,167 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
|
|||||||
$element = $commandElements[$i]
|
$element = $commandElements[$i]
|
||||||
if ($element -isnot [StringConstantExpressionAst] -or
|
if ($element -isnot [StringConstantExpressionAst] -or
|
||||||
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
||||||
$element.Value.StartsWith('-')) {
|
#$element.Value.StartsWith('-') -or
|
||||||
|
$element.Value -eq $wordToComplete) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
$element.Value
|
$element.Value
|
||||||
}) -join ';'
|
}) -join ';'
|
||||||
|
|
||||||
$completions = @(switch ($command) {
|
$completions = @(switch -Wildcard ($command) {
|
||||||
'{{PROJECT_EXECUTABLE}}' {
|
'*;--help' {
|
||||||
[CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.')
|
break
|
||||||
[CompletionResult]::new('--language', 'language', [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.')
|
}
|
||||||
[CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Highlight lines N through M.')
|
'*;--version' {
|
||||||
[CompletionResult]::new('--highlight-line', 'highlight-line', [CompletionResultType]::ParameterName, 'Highlight lines N through M.')
|
break
|
||||||
[CompletionResult]::new('--file-name', 'file-name', [CompletionResultType]::ParameterName, 'Specify the name to display for a file.')
|
}
|
||||||
[CompletionResult]::new('--diff-context', 'diff-context', [CompletionResultType]::ParameterName, 'diff-context')
|
'*;--acknowledgements' {
|
||||||
[CompletionResult]::new('--tabs', 'tabs', [CompletionResultType]::ParameterName, 'Set the tab width to T spaces.')
|
break
|
||||||
[CompletionResult]::new('--wrap', 'wrap', [CompletionResultType]::ParameterName, 'Specify the text-wrapping mode (*auto*, never, character).')
|
}
|
||||||
[CompletionResult]::new('--terminal-width', 'terminal-width', [CompletionResultType]::ParameterName, 'Explicitly set the width of the terminal instead of determining it automatically. If prefixed with ''+'' or ''-'', the value will be treated as an offset to the actual terminal width. See also: ''--wrap''.')
|
'*;--language' {
|
||||||
[CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'When to use colors (*auto*, never, always).')
|
Get-MyLanguages |
|
||||||
[CompletionResult]::new('--italic-text', 'italic-text', [CompletionResultType]::ParameterName, 'Use italics in output (always, *never*)')
|
ForEach-Object {[CompletionResult]::new(($_.MyParameter -replace "^(.*)$", '''$1'''), $_.MyParameter, [CompletionResultType]::ParameterName, $_.MyDescription ?? '_no value_')}
|
||||||
[CompletionResult]::new('--decorations', 'decorations', [CompletionResultType]::ParameterName, 'When to show the decorations (*auto*, never, always).')
|
break
|
||||||
[CompletionResult]::new('--paging', 'paging', [CompletionResultType]::ParameterName, 'Specify when to use the pager, or use `-P` to disable (*auto*, never, always).')
|
}
|
||||||
[CompletionResult]::new('--pager', 'pager', [CompletionResultType]::ParameterName, 'Determine which pager to use.')
|
'*;--theme' {
|
||||||
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
|
Get-MyThemes |
|
||||||
[CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterName, $_)}
|
||||||
[CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.')
|
break
|
||||||
[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.')
|
'*;--binary' {
|
||||||
[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).')
|
$ArrayBinary |
|
||||||
[CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
|
break
|
||||||
[CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
|
}
|
||||||
[CompletionResult]::new('--show-all', 'show-all', [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
|
'*;--style' {
|
||||||
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').')
|
$ArrayStyle |
|
||||||
[CompletionResult]::new('--plain', 'plain', [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.')
|
break
|
||||||
[CompletionResult]::new('--diff', 'diff', [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.')
|
}
|
||||||
[CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').')
|
'*;--wrap' {
|
||||||
[CompletionResult]::new('--number', 'number', [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').')
|
$ArrayWrap |
|
||||||
[CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'f')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--force-colorization', 'force-colorization', [CompletionResultType]::ParameterName, 'force-colorization')
|
break
|
||||||
[CompletionResult]::new('-P', 'P', [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''')
|
}
|
||||||
[CompletionResult]::new('--no-paging', 'no-paging', [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''')
|
'*;--color' {
|
||||||
[CompletionResult]::new('--list-themes', 'list-themes', [CompletionResultType]::ParameterName, 'Display all supported highlighting themes.')
|
$ArrayWhen |
|
||||||
[CompletionResult]::new('-L', 'L', [CompletionResultType]::ParameterName, 'Display all supported languages.')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--list-languages', 'list-languages', [CompletionResultType]::ParameterName, 'Display all supported languages.')
|
break
|
||||||
[CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'u')
|
}
|
||||||
[CompletionResult]::new('--unbuffered', 'unbuffered', [CompletionResultType]::ParameterName, 'unbuffered')
|
'*;--italic-text' {
|
||||||
[CompletionResult]::new('--no-config', 'no-config', [CompletionResultType]::ParameterName, 'Do not use the configuration file')
|
$ArrayYesNo |
|
||||||
[CompletionResult]::new('--no-custom-assets', 'no-custom-assets', [CompletionResultType]::ParameterName, 'Do not load custom assets')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--lessopen', 'lessopen', [CompletionResultType]::ParameterName, 'Enable the $LESSOPEN preprocessor')
|
break
|
||||||
[CompletionResult]::new('--no-lessopen', 'no-lessopen', [CompletionResultType]::ParameterName, 'Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)')
|
}
|
||||||
[CompletionResult]::new('--config-file', 'config-file', [CompletionResultType]::ParameterName, 'Show path to the configuration file.')
|
'*;--paging' {
|
||||||
[CompletionResult]::new('--generate-config-file', 'generate-config-file', [CompletionResultType]::ParameterName, 'Generates a default configuration file.')
|
$ArrayWhen |
|
||||||
[CompletionResult]::new('--config-dir', 'config-dir', [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--cache-dir', 'cache-dir', [CompletionResultType]::ParameterName, 'Show bat''s cache directory.')
|
break
|
||||||
[CompletionResult]::new('--diagnostic', 'diagnostic', [CompletionResultType]::ParameterName, 'Show diagnostic information for bug reports.')
|
}
|
||||||
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print this help message.')
|
'*;--decorations' {
|
||||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print this help message.')
|
$ArrayWhen |
|
||||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Show version information.')
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Show version information.')
|
break
|
||||||
## Completion of the 'cache' command itself is removed for better UX
|
}
|
||||||
## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802
|
'*;--completion' {
|
||||||
|
$ArrayCompletion |
|
||||||
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
'*;--strip-ansi' {
|
||||||
|
$ArrayWhen |
|
||||||
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
'*;--nonprintable-notation' {
|
||||||
|
$ArrayPrint |
|
||||||
|
ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
'*;--generate-config-file' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
'{{PROJECT_EXECUTABLE}};cache' {
|
'{{PROJECT_EXECUTABLE}};cache' {
|
||||||
[CompletionResult]::new('--source', 'source', [CompletionResultType]::ParameterName, 'Use a different directory to load syntaxes and themes from.')
|
[CompletionResult]::new('--source' , 'source' , [CompletionResultType]::ParameterName, 'Use a different directory to load syntaxes and themes from.')
|
||||||
[CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'Use a different directory to store the cached syntax and theme set.')
|
[CompletionResult]::new('--target' , 'target' , [CompletionResultType]::ParameterName, 'Use a different directory to store the cached syntax and theme set.')
|
||||||
[CompletionResult]::new('-b', 'b', [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.')
|
# [CompletionResult]::new('-b' , 'b' , [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.')
|
||||||
[CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.')
|
[CompletionResult]::new('--build' , 'build' , [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.')
|
||||||
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.')
|
# [CompletionResult]::new('-c' , 'c' , [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.')
|
||||||
[CompletionResult]::new('--clear', 'clear', [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.')
|
[CompletionResult]::new('--clear' , 'clear' , [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.')
|
||||||
[CompletionResult]::new('--blank', 'blank', [CompletionResultType]::ParameterName, 'Create completely new syntax and theme sets (instead of appending to the default sets).')
|
[CompletionResult]::new('--blank' , 'blank' , [CompletionResultType]::ParameterName, 'Create completely new syntax and theme sets (instead of appending to the default sets).')
|
||||||
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')
|
# [CompletionResult]::new('-h' , 'h' , [CompletionResultType]::ParameterName, 'Prints help information')
|
||||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')
|
[CompletionResult]::new('--help' , 'help' , [CompletionResultType]::ParameterName, 'Prints help information')
|
||||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')
|
# [CompletionResult]::new('-V' , 'V' , [CompletionResultType]::ParameterName, 'Prints version information')
|
||||||
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')
|
# [CompletionResult]::new('--version' , 'version' , [CompletionResultType]::ParameterName, 'Prints version information')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
# [CompletionResult]::new('-l' , 'l' , [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.')
|
||||||
|
[CompletionResult]::new('--language' , 'language' , [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.')
|
||||||
|
# [CompletionResult]::new('-H' , 'H' , [CompletionResultType]::ParameterName, 'Highlight lines N through M.')
|
||||||
|
[CompletionResult]::new('--highlight-line' , 'highlight-line' , [CompletionResultType]::ParameterName, 'Highlight lines N through M.')
|
||||||
|
[CompletionResult]::new('--file-name' , 'file-name' , [CompletionResultType]::ParameterName, 'Specify the name to display for a file.')
|
||||||
|
[CompletionResult]::new('--diff-context' , 'diff-context' , [CompletionResultType]::ParameterName, 'diff-context')
|
||||||
|
[CompletionResult]::new('--tabs' , 'tabs' , [CompletionResultType]::ParameterName, 'Set the tab width to T spaces.')
|
||||||
|
[CompletionResult]::new('--wrap' , 'wrap' , [CompletionResultType]::ParameterName, 'Specify the text-wrapping mode (*auto*, character).')
|
||||||
|
[CompletionResult]::new('--terminal-width' , 'terminal-width' , [CompletionResultType]::ParameterName, 'Explicitly set the width of the terminal instead of determining it automatically. If prefixed with ''+'' or ''-'', the value will be treated as an offset to the actual terminal width. See also: ''--wrap''.')
|
||||||
|
[CompletionResult]::new('--color' , 'color' , [CompletionResultType]::ParameterName, 'When to use colors (*auto*, never, always).')
|
||||||
|
[CompletionResult]::new('--italic-text' , 'italic-text' , [CompletionResultType]::ParameterName, 'Use italics in output (always, *never*)')
|
||||||
|
[CompletionResult]::new('--decorations' , 'decorations' , [CompletionResultType]::ParameterName, 'When to show the decorations (*auto*, never, always).')
|
||||||
|
[CompletionResult]::new('--paging' , 'paging' , [CompletionResultType]::ParameterName, 'Specify when to use the pager, or use ''-P'' to disable (*auto*, never, always).')
|
||||||
|
[CompletionResult]::new('--pager' , 'pager' , [CompletionResultType]::ParameterName, 'Determine which pager to use.')
|
||||||
|
# [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' , 'themedark' , [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for dark backgrounds.')
|
||||||
|
[CompletionResult]::new('--theme-light' , 'themelight' , [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.')
|
||||||
|
# [CompletionResult]::new('-A' , 'A' , [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
|
||||||
|
[CompletionResult]::new('--show-all' , 'show-all' , [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
|
||||||
|
[CompletionResult]::new('--nonprintable-notation' , 'nonprintable-notation' , [CompletionResultType]::ParameterName, 'Set notation for non-printable characters. (unicode, caret)')
|
||||||
|
[CompletionResult]::new('--chop-long-lines' , 'chop-long-lines' , [CompletionResultType]::ParameterName, 'Truncate all lines longer than screen width. Alias for ''--wrap=never''.')
|
||||||
|
[CompletionResult]::new('--binary' , 'binary' , [CompletionResultType]::ParameterName, 'How to treat binary content. (*no-printing*, as-text)')
|
||||||
|
[CompletionResult]::new('--ignored-suffix' , 'ignored-suffix' , [CompletionResultType]::ParameterName, 'Ignore extension. For example: ''bat --ignored-suffix ".dev" my_file.json.dev'' will use JSON syntax, and ignore ''.dev''')
|
||||||
|
[CompletionResult]::new('--squeeze-blank' , 'squeeze-blank' , [CompletionResultType]::ParameterName, 'Squeeze consecutive empty lines into a single empty line.')
|
||||||
|
[CompletionResult]::new('--squeeze-limit' , 'squeeze-limit' , [CompletionResultType]::ParameterName, 'Set the maximum number of consecutive empty lines to be printed.')
|
||||||
|
[CompletionResult]::new('--strip-ansi' , 'strip-ansi' , [CompletionResultType]::ParameterName, '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. (auto, always, *never*).')
|
||||||
|
# [CompletionResult]::new('-p' , 'p' , [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').')
|
||||||
|
[CompletionResult]::new('--plain' , 'plain' , [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').')
|
||||||
|
# [CompletionResult]::new('-d' , 'd' , [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.')
|
||||||
|
[CompletionResult]::new('--diff' , 'diff' , [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.')
|
||||||
|
# [CompletionResult]::new('-n' , 'n' , [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').')
|
||||||
|
[CompletionResult]::new('--number' , 'number' , [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').')
|
||||||
|
# [CompletionResult]::new('-f' , 'f' , [CompletionResultType]::ParameterName, 'f')
|
||||||
|
[CompletionResult]::new('--force-colorization' , 'force-colorization' , [CompletionResultType]::ParameterName, 'force-colorization')
|
||||||
|
# [CompletionResult]::new('-P' , 'P' , [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''')
|
||||||
|
[CompletionResult]::new('--no-paging' , 'no-paging' , [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''')
|
||||||
|
[CompletionResult]::new('--list-themes' , 'list-themes' , [CompletionResultType]::ParameterName, 'Display all supported highlighting themes.')
|
||||||
|
# [CompletionResult]::new('-L' , 'L' , [CompletionResultType]::ParameterName, 'Display all supported languages.')
|
||||||
|
[CompletionResult]::new('--list-languages' , 'list-languages' , [CompletionResultType]::ParameterName, 'Display all supported languages.')
|
||||||
|
# [CompletionResult]::new('-u' , 'u' , [CompletionResultType]::ParameterName, 'u')
|
||||||
|
[CompletionResult]::new('--unbuffered' , 'unbuffered' , [CompletionResultType]::ParameterName, 'unbuffered')
|
||||||
|
[CompletionResult]::new('--completion' , 'completion' , [CompletionResultType]::ParameterName, 'Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]')
|
||||||
|
[CompletionResult]::new('--no-config' , 'no-config' , [CompletionResultType]::ParameterName, 'Do not use the configuration file')
|
||||||
|
[CompletionResult]::new('--no-custom-assets' , 'no-custom-assets' , [CompletionResultType]::ParameterName, 'Do not load custom assets')
|
||||||
|
[CompletionResult]::new('--lessopen' , 'lessopen' , [CompletionResultType]::ParameterName, 'Enable the $LESSOPEN preprocessor')
|
||||||
|
[CompletionResult]::new('--no-lessopen' , 'no-lessopen' , [CompletionResultType]::ParameterName, 'Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)')
|
||||||
|
[CompletionResult]::new('--config-file' , 'config-file' , [CompletionResultType]::ParameterName, 'Show path to the configuration file.')
|
||||||
|
[CompletionResult]::new('--generate-config-file' , 'generate-config-file' , [CompletionResultType]::ParameterName, 'Generates a default configuration file.')
|
||||||
|
[CompletionResult]::new('--config-dir' , 'config-dir' , [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.')
|
||||||
|
[CompletionResult]::new('--cache-dir' , 'cache-dir' , [CompletionResultType]::ParameterName, 'Show bat''s cache directory.')
|
||||||
|
[CompletionResult]::new('--acknowledgements' , 'acknowledgements' , [CompletionResultType]::ParameterName, 'Show acknowledgements.')
|
||||||
|
[CompletionResult]::new('--set-terminal-title' , 'set-terminal-title' , [CompletionResultType]::ParameterName, 'Sets terminal title to filenames when using a pager.')
|
||||||
|
[CompletionResult]::new('--diagnostic' , 'diagnostic' , [CompletionResultType]::ParameterName, 'Show diagnostic information for bug reports.')
|
||||||
|
# [CompletionResult]::new('-h' , 'h' , [CompletionResultType]::ParameterName, 'Print this help message.')
|
||||||
|
[CompletionResult]::new('--help' , 'help' , [CompletionResultType]::ParameterName, 'Print this help message.')
|
||||||
|
# [CompletionResult]::new('-V' , 'V' , [CompletionResultType]::ParameterName, 'Show version information.')
|
||||||
|
[CompletionResult]::new('--version' , 'version' , [CompletionResultType]::ParameterName, 'Show version information.')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
|
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
|
||||||
Sort-Object -Property ListItemText
|
Sort-Object -Property CompletionText
|
||||||
}
|
}
|
||||||
|
41
assets/manual/bat.1.in
vendored
41
assets/manual/bat.1.in
vendored
@@ -37,6 +37,23 @@ Use character sequences like ^G, ^J, ^@, .. to identify non-printable characters
|
|||||||
Use special Unicode code points to identify non-printable characters
|
Use special Unicode code points to identify non-printable characters
|
||||||
.RE
|
.RE
|
||||||
.HP
|
.HP
|
||||||
|
\fB\-\-binary\fR <behavior>
|
||||||
|
.IP
|
||||||
|
How to treat binary content.
|
||||||
|
|
||||||
|
Possible values:
|
||||||
|
.RS
|
||||||
|
.IP "no\-printing"
|
||||||
|
Do not print any binary content (default)
|
||||||
|
.IP "as\-text"
|
||||||
|
Treat binary content as normal text
|
||||||
|
.RE
|
||||||
|
.HP
|
||||||
|
\fB\-\-completion\fR <SHELL>
|
||||||
|
.IP
|
||||||
|
Show shell completion for a certain shell.
|
||||||
|
Possible values: bash, fish, zsh, ps1
|
||||||
|
.HP
|
||||||
\fB\-p\fR, \fB\-\-plain\fR
|
\fB\-p\fR, \fB\-\-plain\fR
|
||||||
.IP
|
.IP
|
||||||
Only show plain style, no decorations. This is an alias for
|
Only show plain style, no decorations. This is an alias for
|
||||||
@@ -180,8 +197,8 @@ This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR
|
|||||||
.HP
|
.HP
|
||||||
\fB\-\-theme\-light\fR <theme>
|
\fB\-\-theme\-light\fR <theme>
|
||||||
.IP
|
.IP
|
||||||
Sets the theme name for syntax highlighting used when the terminal uses a dark background.
|
Sets the theme name for syntax highlighting used when the terminal uses a light background.
|
||||||
To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
|
To set a default theme, add the \fB\-\-theme-light="..."\fP option to the configuration file or
|
||||||
export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP).
|
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.
|
This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR.
|
||||||
.HP
|
.HP
|
||||||
@@ -197,14 +214,30 @@ Squeeze consecutive empty lines into a single empty line.
|
|||||||
.IP
|
.IP
|
||||||
Set the maximum number of consecutive empty lines to be printed.
|
Set the maximum number of consecutive empty lines to be printed.
|
||||||
.HP
|
.HP
|
||||||
|
\fB\-\-strip\-ansi\fR <when>
|
||||||
|
.IP
|
||||||
|
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*.
|
||||||
|
.HP
|
||||||
\fB\-\-style\fR <style\-components>
|
\fB\-\-style\fR <style\-components>
|
||||||
.IP
|
.IP
|
||||||
Configure which elements (line numbers, file headers, grid borders, Git modifications,
|
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
|
\&..) to display in addition to the file contents. The argument is a comma\-separated list
|
||||||
of components to display (e.g. 'numbers,changes,grid') or a pre\-defined style ('full').
|
of components to display (e.g. 'numbers,changes,grid') or a pre\-defined style ('full').
|
||||||
To set a default style, add the '\-\-style=".."' option to the configuration file or
|
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=".."). Possible
|
export the BAT_STYLE environment variable (e.g.: export BAT_STYLE="..").
|
||||||
values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid,
|
.IP
|
||||||
|
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.
|
||||||
|
.IP
|
||||||
|
By default, the following components are enabled:
|
||||||
|
changes, grid, header\-filename, numbers, snip
|
||||||
|
.IP
|
||||||
|
Possible values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid,
|
||||||
rule, numbers, snip.
|
rule, numbers, snip.
|
||||||
.HP
|
.HP
|
||||||
\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
|
\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
|
||||||
|
19
assets/patches/Monokai-Extended.tmTheme.patch
vendored
19
assets/patches/Monokai-Extended.tmTheme.patch
vendored
@@ -21,11 +21,26 @@ index 9c2aa3e..180cbbf 100644
|
|||||||
<string>Invalid</string>
|
<string>Invalid</string>
|
||||||
<key>scope</key>
|
<key>scope</key>
|
||||||
- <string>invalid</string>
|
- <string>invalid</string>
|
||||||
+ <string>invalid, markup.error</string>
|
+ <string>invalid, meta.annotation.error-line</string>
|
||||||
<key>settings</key>
|
<key>settings</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>background</key>
|
<key>background</key>
|
||||||
@@ -1042,7 +1042,7 @@
|
@@ -1038,11 +1038,22 @@
|
||||||
|
<string>#f8f8f0</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
+ <dict>
|
||||||
|
+ <key>name</key>
|
||||||
|
+ <string>Error</string>
|
||||||
|
+ <key>scope</key>
|
||||||
|
+ <string>markup.error</string>
|
||||||
|
+ <key>settings</key>
|
||||||
|
+ <dict>
|
||||||
|
+ <key>foreground</key>
|
||||||
|
+ <string>#dd2020</string>
|
||||||
|
+ </dict>
|
||||||
|
+ </dict>
|
||||||
|
<dict>
|
||||||
<key>name</key>
|
<key>name</key>
|
||||||
<string>Invalid deprecated</string>
|
<string>Invalid deprecated</string>
|
||||||
<key>scope</key>
|
<key>scope</key>
|
||||||
|
BIN
assets/syntaxes.bin
vendored
BIN
assets/syntaxes.bin
vendored
Binary file not shown.
2
assets/syntaxes/02_Extra/Apache
vendored
2
assets/syntaxes/02_Extra/Apache
vendored
Submodule assets/syntaxes/02_Extra/Apache updated: 163bc03ae8...c438c352db
@@ -1,5 +1,6 @@
|
|||||||
%YAML 1.2
|
%YAML 1.2
|
||||||
---
|
---
|
||||||
|
name: x86_64 Assembly
|
||||||
file_extensions: [yasm, nasm, asm, inc, mac]
|
file_extensions: [yasm, nasm, asm, inc, mac]
|
||||||
scope: source.asm.x86_64
|
scope: source.asm.x86_64
|
||||||
|
|
||||||
@@ -1364,4 +1365,3 @@ contexts:
|
|||||||
scope: invalid.keyword.operator.word.mnemonic.sse5.packed-arithmetic
|
scope: invalid.keyword.operator.word.mnemonic.sse5.packed-arithmetic
|
||||||
- match: '(?i)\b(pcmov|permp[ds]|pperm|prot[bdqw]|psh[al][bdqw])\b'
|
- match: '(?i)\b(pcmov|permp[ds]|pperm|prot[bdqw]|psh[al][bdqw])\b'
|
||||||
scope: invalid.keyword.operator.word.mnemonic.sse5.simd-integer
|
scope: invalid.keyword.operator.word.mnemonic.sse5.simd-integer
|
||||||
...
|
|
@@ -2,20 +2,21 @@
|
|||||||
---
|
---
|
||||||
# See http://www.sublimetext.com/docs/3/syntax.html
|
# See http://www.sublimetext.com/docs/3/syntax.html
|
||||||
name: Comma Separated Values
|
name: Comma Separated Values
|
||||||
file_extensions:
|
scope: text.csv.comma
|
||||||
- csv
|
|
||||||
- tsv
|
|
||||||
scope: text.csv
|
|
||||||
variables:
|
variables:
|
||||||
field_separator: (?:[,;|\t])
|
field_separator: (?:,)
|
||||||
record_separator: (?:$\n?)
|
record_separator: (?:$\n?)
|
||||||
contexts:
|
contexts:
|
||||||
prototype:
|
main:
|
||||||
- match: (?={{record_separator}})
|
- match: '^'
|
||||||
pop: true
|
push: fields
|
||||||
|
|
||||||
fields:
|
fields:
|
||||||
- match: ""
|
- include: record_separator
|
||||||
|
- match: ''
|
||||||
push:
|
push:
|
||||||
|
- field_or_record_separator
|
||||||
|
- field5
|
||||||
- field_or_record_separator
|
- field_or_record_separator
|
||||||
- field4
|
- field4
|
||||||
- field_or_record_separator
|
- field_or_record_separator
|
||||||
@@ -24,54 +25,55 @@ contexts:
|
|||||||
- field2
|
- field2
|
||||||
- field_or_record_separator
|
- field_or_record_separator
|
||||||
- field1
|
- field1
|
||||||
main:
|
|
||||||
|
record_separator_pop:
|
||||||
|
- match: (?={{record_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
record_separator:
|
||||||
- meta_include_prototype: false
|
- meta_include_prototype: false
|
||||||
- match: "^"
|
- match: '{{record_separator}}'
|
||||||
set: fields
|
scope: punctuation.terminator.record.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
field_or_record_separator:
|
field_or_record_separator:
|
||||||
- meta_include_prototype: false
|
- meta_include_prototype: false
|
||||||
- match: "{{record_separator}}"
|
- include: record_separator_pop
|
||||||
scope: punctuation.terminator.record.csv
|
- match: '{{field_separator}}'
|
||||||
pop: true
|
|
||||||
- match: "{{field_separator}}"
|
|
||||||
scope: punctuation.separator.sequence.csv
|
scope: punctuation.separator.sequence.csv
|
||||||
pop: true
|
pop: true
|
||||||
|
|
||||||
field_contents:
|
field_contents:
|
||||||
- match: '"'
|
- match: '"'
|
||||||
scope: punctuation.definition.string.begin.csv
|
scope: punctuation.definition.string.begin.csv
|
||||||
push: double_quoted_string
|
push: scope:text.csv#double_quoted_string
|
||||||
|
|
||||||
- match: (?={{field_separator}}|{{record_separator}})
|
- include: record_separator_pop
|
||||||
pop: true
|
- match: (?={{field_separator}})
|
||||||
|
|
||||||
double_quoted_string:
|
|
||||||
- meta_include_prototype: false
|
|
||||||
- meta_scope: string.quoted.double.csv
|
|
||||||
- match: '""'
|
|
||||||
scope: constant.character.escape.csv
|
|
||||||
- match: '"'
|
|
||||||
scope: punctuation.definition.string.end.csv
|
|
||||||
pop: true
|
pop: true
|
||||||
|
|
||||||
field1:
|
field1:
|
||||||
- match: ""
|
- match: ''
|
||||||
set:
|
set:
|
||||||
- meta_content_scope: meta.field-1.csv support.type
|
- meta_content_scope: meta.field-1.csv variable.parameter
|
||||||
- include: field_contents
|
- include: field_contents
|
||||||
field2:
|
field2:
|
||||||
- match: ""
|
- match: ''
|
||||||
set:
|
set:
|
||||||
- meta_content_scope: meta.field-2.csv support.function
|
- meta_content_scope: meta.field-2.csv support.function
|
||||||
- include: field_contents
|
- include: field_contents
|
||||||
field3:
|
field3:
|
||||||
- match: ""
|
- match: ''
|
||||||
set:
|
set:
|
||||||
- meta_content_scope: meta.field-3.csv constant.numeric
|
- meta_content_scope: meta.field-3.csv constant.numeric
|
||||||
- include: field_contents
|
- include: field_contents
|
||||||
field4:
|
field4:
|
||||||
- match: ""
|
- match: ''
|
||||||
set:
|
set:
|
||||||
- meta_content_scope: meta.field-4.csv keyword.operator
|
- meta_content_scope: meta.field-4.csv keyword.operator
|
||||||
- include: field_contents
|
- include: field_contents
|
||||||
|
field5:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-5.csv string.unquoted
|
||||||
|
- include: field_contents
|
80
assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax
vendored
Normal file
80
assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# See http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Pipe Separated Values
|
||||||
|
scope: text.csv.pipe
|
||||||
|
variables:
|
||||||
|
field_separator: (?:\|)
|
||||||
|
record_separator: (?:$\n?)
|
||||||
|
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: '^'
|
||||||
|
push: fields
|
||||||
|
|
||||||
|
fields:
|
||||||
|
- include: record_separator
|
||||||
|
- match: ''
|
||||||
|
push:
|
||||||
|
- field_or_record_separator
|
||||||
|
- field5
|
||||||
|
- field_or_record_separator
|
||||||
|
- field4
|
||||||
|
- field_or_record_separator
|
||||||
|
- field3
|
||||||
|
- field_or_record_separator
|
||||||
|
- field2
|
||||||
|
- field_or_record_separator
|
||||||
|
- field1
|
||||||
|
|
||||||
|
record_separator_pop:
|
||||||
|
- match: (?={{record_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- match: '{{record_separator}}'
|
||||||
|
scope: punctuation.terminator.record.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_or_record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: '{{field_separator}}'
|
||||||
|
scope: punctuation.separator.sequence.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_contents:
|
||||||
|
- match: '"'
|
||||||
|
scope: punctuation.definition.string.begin.csv
|
||||||
|
push: scope:text.csv#double_quoted_string
|
||||||
|
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: (?={{field_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field1:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-1.csv variable.parameter
|
||||||
|
- include: field_contents
|
||||||
|
field2:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-2.csv support.function
|
||||||
|
- include: field_contents
|
||||||
|
field3:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-3.csv constant.numeric
|
||||||
|
- include: field_contents
|
||||||
|
field4:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-4.csv keyword.operator
|
||||||
|
- include: field_contents
|
||||||
|
field5:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-5.csv string.unquoted
|
||||||
|
- include: field_contents
|
79
assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax
vendored
Normal file
79
assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# See http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Semi-Colon Separated Values
|
||||||
|
scope: text.csv.semi-colon
|
||||||
|
variables:
|
||||||
|
field_separator: (?:;)
|
||||||
|
record_separator: (?:$\n?)
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: '^'
|
||||||
|
push: fields
|
||||||
|
|
||||||
|
fields:
|
||||||
|
- include: record_separator
|
||||||
|
- match: ''
|
||||||
|
push:
|
||||||
|
- field_or_record_separator
|
||||||
|
- field5
|
||||||
|
- field_or_record_separator
|
||||||
|
- field4
|
||||||
|
- field_or_record_separator
|
||||||
|
- field3
|
||||||
|
- field_or_record_separator
|
||||||
|
- field2
|
||||||
|
- field_or_record_separator
|
||||||
|
- field1
|
||||||
|
|
||||||
|
record_separator_pop:
|
||||||
|
- match: (?={{record_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- match: '{{record_separator}}'
|
||||||
|
scope: punctuation.terminator.record.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_or_record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: '{{field_separator}}'
|
||||||
|
scope: punctuation.separator.sequence.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_contents:
|
||||||
|
- match: '"'
|
||||||
|
scope: punctuation.definition.string.begin.csv
|
||||||
|
push: scope:text.csv#double_quoted_string
|
||||||
|
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: (?={{field_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field1:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-1.csv variable.parameter
|
||||||
|
- include: field_contents
|
||||||
|
field2:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-2.csv support.function
|
||||||
|
- include: field_contents
|
||||||
|
field3:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-3.csv constant.numeric
|
||||||
|
- include: field_contents
|
||||||
|
field4:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-4.csv keyword.operator
|
||||||
|
- include: field_contents
|
||||||
|
field5:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-5.csv string.unquoted
|
||||||
|
- include: field_contents
|
113
assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax
vendored
Normal file
113
assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax
vendored
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# See http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Separated Values
|
||||||
|
file_extensions:
|
||||||
|
- csv
|
||||||
|
scope: text.csv
|
||||||
|
variables:
|
||||||
|
field_separator_chars: ',;\t|'
|
||||||
|
field_separator: (?:[{{field_separator_chars}}])
|
||||||
|
record_separator: (?:$\n?)
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- include: three_field_separators
|
||||||
|
- include: single_separator_type_on_line
|
||||||
|
- match: '^'
|
||||||
|
push: unknown-separated-main
|
||||||
|
|
||||||
|
three_field_separators:
|
||||||
|
- match: ^(?=(?:[^,]*,){3})
|
||||||
|
set: scope:text.csv.comma
|
||||||
|
- match: ^(?=(?:[^;]*;){3})
|
||||||
|
set: scope:text.csv.semi-colon
|
||||||
|
- match: ^(?=(?:[^\t]*\t){3})
|
||||||
|
set: scope:text.csv.tab
|
||||||
|
- match: ^(?=(?:[^|]*\|){3})
|
||||||
|
set: scope:text.csv.pipe
|
||||||
|
|
||||||
|
single_separator_type_on_line:
|
||||||
|
- match: ^(?=[^{{field_separator_chars}}]*,[^;\t|]*$)
|
||||||
|
set: scope:text.csv.comma
|
||||||
|
- match: ^(?=[^{{field_separator_chars}}]*;[^,\t|]*$)
|
||||||
|
set: scope:text.csv.semi-colon
|
||||||
|
- match: ^(?=[^{{field_separator_chars}}]*\t[^,;|]*$)
|
||||||
|
set: scope:text.csv.tab
|
||||||
|
- match: ^(?=[^{{field_separator_chars}}]*\|[^,;\t]*$)
|
||||||
|
set: scope:text.csv.pipe
|
||||||
|
|
||||||
|
unknown-separated-main:
|
||||||
|
- include: record_separator
|
||||||
|
- match: ''
|
||||||
|
push:
|
||||||
|
- field_or_record_separator
|
||||||
|
- field5
|
||||||
|
- field_or_record_separator
|
||||||
|
- field4
|
||||||
|
- field_or_record_separator
|
||||||
|
- field3
|
||||||
|
- field_or_record_separator
|
||||||
|
- field2
|
||||||
|
- field_or_record_separator
|
||||||
|
- field1
|
||||||
|
|
||||||
|
record_separator_pop:
|
||||||
|
- match: (?={{record_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- match: '{{record_separator}}'
|
||||||
|
scope: punctuation.terminator.record.csv
|
||||||
|
|
||||||
|
field_or_record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: '{{field_separator}}'
|
||||||
|
scope: punctuation.separator.sequence.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_contents:
|
||||||
|
- match: '"'
|
||||||
|
scope: punctuation.definition.string.begin.csv
|
||||||
|
push: double_quoted_string
|
||||||
|
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: (?={{field_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
double_quoted_string:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- meta_scope: string.quoted.double.csv
|
||||||
|
- match: '""'
|
||||||
|
scope: constant.character.escape.csv
|
||||||
|
- match: '"'
|
||||||
|
scope: punctuation.definition.string.end.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field1:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-1.csv variable.parameter
|
||||||
|
- include: field_contents
|
||||||
|
field2:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-2.csv support.function
|
||||||
|
- include: field_contents
|
||||||
|
field3:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-3.csv constant.numeric
|
||||||
|
- include: field_contents
|
||||||
|
field4:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-4.csv keyword.operator
|
||||||
|
- include: field_contents
|
||||||
|
field5:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-5.csv string.unquoted
|
||||||
|
- include: field_contents
|
83
assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax
vendored
Normal file
83
assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# See http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Tab Separated Values
|
||||||
|
scope: text.csv.tab
|
||||||
|
file_extensions:
|
||||||
|
- tsv
|
||||||
|
|
||||||
|
variables:
|
||||||
|
field_separator: (?:\t)
|
||||||
|
record_separator: (?:$\n?)
|
||||||
|
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: '^'
|
||||||
|
push: fields
|
||||||
|
|
||||||
|
fields:
|
||||||
|
- include: record_separator
|
||||||
|
- match: ''
|
||||||
|
push:
|
||||||
|
- field_or_record_separator
|
||||||
|
- field5
|
||||||
|
- field_or_record_separator
|
||||||
|
- field4
|
||||||
|
- field_or_record_separator
|
||||||
|
- field3
|
||||||
|
- field_or_record_separator
|
||||||
|
- field2
|
||||||
|
- field_or_record_separator
|
||||||
|
- field1
|
||||||
|
|
||||||
|
record_separator_pop:
|
||||||
|
- match: (?={{record_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- match: '{{record_separator}}'
|
||||||
|
scope: punctuation.terminator.record.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_or_record_separator:
|
||||||
|
- meta_include_prototype: false
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: '{{field_separator}}'
|
||||||
|
scope: punctuation.separator.sequence.csv
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field_contents:
|
||||||
|
- match: '"'
|
||||||
|
scope: punctuation.definition.string.begin.csv
|
||||||
|
push: scope:text.csv#double_quoted_string
|
||||||
|
|
||||||
|
- include: record_separator_pop
|
||||||
|
- match: (?={{field_separator}})
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
field1:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-1.csv variable.parameter
|
||||||
|
- include: field_contents
|
||||||
|
field2:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-2.csv support.function
|
||||||
|
- include: field_contents
|
||||||
|
field3:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-3.csv constant.numeric
|
||||||
|
- include: field_contents
|
||||||
|
field4:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-4.csv keyword.operator
|
||||||
|
- include: field_contents
|
||||||
|
field5:
|
||||||
|
- match: ''
|
||||||
|
set:
|
||||||
|
- meta_content_scope: meta.field-5.csv string.unquoted
|
||||||
|
- include: field_contents
|
2
assets/syntaxes/02_Extra/Docker
vendored
2
assets/syntaxes/02_Extra/Docker
vendored
Submodule assets/syntaxes/02_Extra/Docker updated: 0f6b7bc87a...c001fb2805
2
assets/syntaxes/02_Extra/Fish
vendored
2
assets/syntaxes/02_Extra/Fish
vendored
Submodule assets/syntaxes/02_Extra/Fish updated: 98316d4332...ef510fd759
1
assets/syntaxes/02_Extra/GDScript-sublime
vendored
Submodule
1
assets/syntaxes/02_Extra/GDScript-sublime
vendored
Submodule
Submodule assets/syntaxes/02_Extra/GDScript-sublime added at 96f5dcf297
23
assets/syntaxes/02_Extra/Hosts.sublime-syntax
vendored
23
assets/syntaxes/02_Extra/Hosts.sublime-syntax
vendored
@@ -1,23 +0,0 @@
|
|||||||
%YAML 1.2
|
|
||||||
---
|
|
||||||
# http://www.sublimetext.com/docs/3/syntax.html
|
|
||||||
name: hosts
|
|
||||||
file_extensions:
|
|
||||||
- hosts
|
|
||||||
scope: source.hosts
|
|
||||||
|
|
||||||
contexts:
|
|
||||||
main:
|
|
||||||
- scope: comment.line.number-sign
|
|
||||||
match: \#.*
|
|
||||||
comment: comment
|
|
||||||
|
|
||||||
- match: ^\s*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-f:]+)
|
|
||||||
comment: ipaddress
|
|
||||||
scope: constant.numeric.ipaddress
|
|
||||||
|
|
||||||
|
|
||||||
- match: \s(localhost|ip6-loopback|ip6-localhost|ip6-localnet|ip6-mcastprefix|ip6-allnodes|ip6-allrouters|ip6-allhosts|broadcasthost)\b
|
|
||||||
scope: keyword.host.predefined}
|
|
||||||
comment: prefdfined
|
|
||||||
|
|
1
assets/syntaxes/02_Extra/Idris2
vendored
Submodule
1
assets/syntaxes/02_Extra/Idris2
vendored
Submodule
Submodule assets/syntaxes/02_Extra/Idris2 added at 7c1bf44c4f
2
assets/syntaxes/02_Extra/Lean
vendored
2
assets/syntaxes/02_Extra/Lean
vendored
Submodule assets/syntaxes/02_Extra/Lean updated: 29a03a8aba...514362b5c7
145
assets/syntaxes/02_Extra/Lean.sublime-syntax
vendored
145
assets/syntaxes/02_Extra/Lean.sublime-syntax
vendored
@@ -1,125 +1,130 @@
|
|||||||
%YAML 1.2
|
%YAML 1.2
|
||||||
---
|
---
|
||||||
# http://www.sublimetext.com/docs/3/syntax.html
|
# http://www.sublimetext.com/docs/syntax.html
|
||||||
name: Lean
|
name: Lean 4
|
||||||
file_extensions:
|
file_extensions:
|
||||||
- lean
|
- lean
|
||||||
scope: source.lean
|
scope: source.lean4
|
||||||
contexts:
|
contexts:
|
||||||
main:
|
main:
|
||||||
- include: comments
|
- include: comments
|
||||||
- match: '\b(?<!\.)(inductive|coinductive|structure|theorem|axiom|axioms|abbreviation|lemma|definition|def|instance|class|constant)\b\s+(\{[^}]*\})?'
|
- match: \b(Prop|Type|Sort)\b
|
||||||
|
scope: storage.type.lean4
|
||||||
|
- match: '\battribute\b\s*\[[^\]]*\]'
|
||||||
|
scope: storage.modifier.lean4
|
||||||
|
- match: '@\[[^\]]*\]'
|
||||||
|
scope: storage.modifier.lean4
|
||||||
|
- match: \b(?<!\.)(global|local|scoped|partial|unsafe|private|protected|noncomputable)(?!\.)\b
|
||||||
|
scope: storage.modifier.lean4
|
||||||
|
- match: \b(sorry|admit|stop)\b
|
||||||
|
scope: invalid.illegal.lean4
|
||||||
|
- match: '#(print|eval|reduce|check|check_failure)\b'
|
||||||
|
scope: keyword.other.lean4
|
||||||
|
- match: \bderiving\s+instance\b
|
||||||
|
scope: keyword.other.command.lean4
|
||||||
|
- match: '\b(?<!\.)(inductive|coinductive|structure|theorem|axiom|abbrev|lemma|def|instance|class|constant)\b\s+(\{[^}]*\})?'
|
||||||
captures:
|
captures:
|
||||||
1: keyword.other.definitioncommand.lean
|
1: keyword.other.definitioncommand.lean4
|
||||||
push:
|
push:
|
||||||
- meta_scope: meta.definitioncommand.lean
|
- meta_scope: meta.definitioncommand.lean4
|
||||||
- match: '(?=\bwith\b|\bextends\b|[:\|\(\[\{⦃<>])'
|
- match: '(?=\bwith\b|\bextends\b|\bwhere\b|[:\|\(\[\{⦃<>])'
|
||||||
pop: true
|
pop: true
|
||||||
- include: comments
|
- include: comments
|
||||||
- include: definitionName
|
- include: definitionName
|
||||||
- match: ","
|
- match: ','
|
||||||
- match: \b(Prop|Type|Sort)\b
|
- match: \b(?<!\.)(theorem|show|have|from|suffices|nomatch|def|class|structure|instance|set_option|initialize|builtin_initialize|example|inductive|coinductive|axiom|constant|universe|universes|variable|variables|import|open|export|theory|prelude|renaming|hiding|exposing|do|by|let|extends|mutual|mut|where|rec|syntax|macro_rules|macro|deriving|fun|section|namespace|end|infix|infixl|infixr|postfix|prefix|notation|abbrev|if|then|else|calc|match|with|for|in|unless|try|catch|finally|return|continue|break)(?!\.)\b
|
||||||
scope: storage.type.lean
|
scope: keyword.other.lean4
|
||||||
- match: '\battribute\b\s*\[[^\]]*\]'
|
|
||||||
scope: storage.modifier.lean
|
|
||||||
- match: '@\[[^\]]*\]'
|
|
||||||
scope: storage.modifier.lean
|
|
||||||
- match: \b(?<!\.)(private|meta|mutual|protected|noncomputable)\b
|
|
||||||
scope: keyword.control.definition.modifier.lean
|
|
||||||
- match: \b(sorry)\b
|
|
||||||
scope: invalid.illegal.lean
|
|
||||||
- match: '#print\s+(def|definition|inductive|instance|structure|axiom|axioms|class)\b'
|
|
||||||
scope: keyword.other.command.lean
|
|
||||||
- match: '#(print|eval|reduce|check|help|exit|find|where)\b'
|
|
||||||
scope: keyword.other.command.lean
|
|
||||||
- match: \b(?<!\.)(import|export|prelude|theory|definition|def|abbreviation|instance|renaming|hiding|exposing|parameter|parameters|begin|constant|constants|lemma|variable|variables|theorem|example|open|axiom|inductive|coinductive|with|structure|universe|universes|alias|precedence|reserve|postfix|prefix|infix|infixl|infixr|notation|end|using|namespace|section|local|set_option|extends|include|omit|class|classes|instances|raw|run_cmd|restate_axiom)(?!\.)\b
|
|
||||||
scope: keyword.other.lean
|
|
||||||
- match: \b(?<!\.)(calc|have|this|match|do|suffices|show|by|in|at|let|forall|fun|exists|assume|from|obtain|haveI|λ)(?!\.)\b
|
|
||||||
scope: keyword.other.lean
|
|
||||||
- match: «
|
- match: «
|
||||||
push:
|
push:
|
||||||
- meta_content_scope: entity.name.lean
|
- meta_content_scope: entity.name.lean4
|
||||||
- match: »
|
- match: »
|
||||||
pop: true
|
pop: true
|
||||||
- match: \b(?<!\.)(if|then|else)\b
|
- match: (s!)"
|
||||||
scope: keyword.control.lean
|
|
||||||
- match: '"'
|
|
||||||
captures:
|
captures:
|
||||||
0: punctuation.definition.string.begin.lean
|
1: keyword.other.lean4
|
||||||
push:
|
push:
|
||||||
- meta_scope: string.quoted.double.lean
|
- meta_scope: string.interpolated.lean4
|
||||||
- match: '"'
|
- match: '"'
|
||||||
captures:
|
|
||||||
0: punctuation.definition.string.end.lean
|
|
||||||
pop: true
|
pop: true
|
||||||
- match: '\\[\\"nt'']'
|
- match: '(\{)'
|
||||||
scope: constant.character.escape.lean
|
captures:
|
||||||
|
1: keyword.other.lean4
|
||||||
|
push:
|
||||||
|
- match: '(\})'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.lean4
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: '\\[\\"ntr'']'
|
||||||
|
scope: constant.character.escape.lean4
|
||||||
- match: '\\x[0-9A-Fa-f][0-9A-Fa-f]'
|
- match: '\\x[0-9A-Fa-f][0-9A-Fa-f]'
|
||||||
scope: constant.character.escape.lean
|
scope: constant.character.escape.lean4
|
||||||
- match: '\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]'
|
- match: '\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]'
|
||||||
scope: constant.character.escape.lean
|
scope: constant.character.escape.lean4
|
||||||
|
- match: '"'
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.lean4
|
||||||
|
- match: '"'
|
||||||
|
pop: true
|
||||||
|
- match: '\\[\\"ntr'']'
|
||||||
|
scope: constant.character.escape.lean4
|
||||||
|
- match: '\\x[0-9A-Fa-f][0-9A-Fa-f]'
|
||||||
|
scope: constant.character.escape.lean4
|
||||||
|
- match: '\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]'
|
||||||
|
scope: constant.character.escape.lean4
|
||||||
|
- match: \b(true|false)\b
|
||||||
|
scope: constant.language.lean4
|
||||||
- match: '''[^\\'']'''
|
- match: '''[^\\'']'''
|
||||||
scope: string.quoted.single.lean
|
scope: string.quoted.single.lean4
|
||||||
- match: '''(\\(x..|u....|.))'''
|
- match: '''(\\(x[0-9A-Fa-f][0-9A-Fa-f]|u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]|.))'''
|
||||||
scope: string.quoted.single.lean
|
scope: string.quoted.single.lean4
|
||||||
captures:
|
captures:
|
||||||
1: constant.character.escape.lean
|
1: constant.character.escape.lean4
|
||||||
- match: '`+[^\[(]\S+'
|
- match: '`+[^\[(]\S+'
|
||||||
scope: entity.name.lean
|
scope: entity.name.lean4
|
||||||
- match: '\b([0-9]+|0([xX][0-9a-fA-F]+))\b'
|
- match: '\b([0-9]+|0([xX][0-9a-fA-F]+)|[-]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?)\b'
|
||||||
scope: constant.numeric.lean
|
scope: constant.numeric.lean4
|
||||||
blockComment:
|
blockComment:
|
||||||
- match: /-
|
- match: /-
|
||||||
push:
|
push:
|
||||||
- meta_scope: comment.block.lean
|
- meta_scope: comment.block.lean4
|
||||||
- match: "-/"
|
- match: '-/'
|
||||||
pop: true
|
pop: true
|
||||||
- include: scope:source.lean.markdown
|
- include: scope:source.lean4.markdown
|
||||||
- include: blockComment
|
- include: blockComment
|
||||||
comments:
|
comments:
|
||||||
- include: dashComment
|
- include: dashComment
|
||||||
- include: docComment
|
- include: docComment
|
||||||
- include: stringBlock
|
|
||||||
- include: modDocComment
|
- include: modDocComment
|
||||||
- include: blockComment
|
- include: blockComment
|
||||||
dashComment:
|
dashComment:
|
||||||
- match: (--)
|
- match: '--'
|
||||||
captures:
|
|
||||||
0: punctuation.definition.comment.lean
|
|
||||||
push:
|
push:
|
||||||
- meta_scope: comment.line.double-dash.lean
|
- meta_scope: comment.line.double-dash.lean4
|
||||||
- match: $
|
- match: $
|
||||||
pop: true
|
pop: true
|
||||||
- include: scope:source.lean.markdown
|
- include: scope:source.lean4.markdown
|
||||||
definitionName:
|
definitionName:
|
||||||
- match: '\b[^:«»\(\)\{\}[:space:]=→λ∀?][^:«»\(\)\{\}[:space:]]*'
|
- match: '\b[^:«»\(\)\{\}[:space:]=→λ∀?][^:«»\(\)\{\}[:space:]]*'
|
||||||
scope: entity.name.function.lean
|
scope: entity.name.function.lean4
|
||||||
- match: «
|
- match: «
|
||||||
push:
|
push:
|
||||||
- meta_content_scope: entity.name.function.lean
|
- meta_content_scope: entity.name.function.lean4
|
||||||
- match: »
|
- match: »
|
||||||
pop: true
|
pop: true
|
||||||
docComment:
|
docComment:
|
||||||
- match: /--
|
- match: /--
|
||||||
push:
|
push:
|
||||||
- meta_scope: comment.block.documentation.lean
|
- meta_scope: comment.block.documentation.lean4
|
||||||
- match: "-/"
|
- match: '-/'
|
||||||
pop: true
|
pop: true
|
||||||
- include: scope:source.lean.markdown
|
- include: scope:source.lean4.markdown
|
||||||
- include: blockComment
|
- include: blockComment
|
||||||
modDocComment:
|
modDocComment:
|
||||||
- match: /-!
|
- match: /-!
|
||||||
push:
|
push:
|
||||||
- meta_scope: comment.block.documentation.lean
|
- meta_scope: comment.block.documentation.lean4
|
||||||
- match: "-/"
|
- match: '-/'
|
||||||
pop: true
|
pop: true
|
||||||
- include: scope:source.lean.markdown
|
- include: scope:source.lean4.markdown
|
||||||
- include: blockComment
|
|
||||||
stringBlock:
|
|
||||||
- match: /-"
|
|
||||||
push:
|
|
||||||
- meta_scope: comment.block.string.lean
|
|
||||||
- match: '"-/'
|
|
||||||
pop: true
|
|
||||||
- include: scope:source.lean.markdown
|
|
||||||
- include: blockComment
|
- include: blockComment
|
||||||
|
1
assets/syntaxes/02_Extra/LiveScript
vendored
1
assets/syntaxes/02_Extra/LiveScript
vendored
Submodule assets/syntaxes/02_Extra/LiveScript deleted from d82aeb737d
2
assets/syntaxes/02_Extra/Nix
vendored
2
assets/syntaxes/02_Extra/Nix
vendored
Submodule assets/syntaxes/02_Extra/Nix updated: 9032bd6137...48c497c709
1
assets/syntaxes/02_Extra/Org mode
vendored
1
assets/syntaxes/02_Extra/Org mode
vendored
Submodule assets/syntaxes/02_Extra/Org mode deleted from 4976d8f84e
1
assets/syntaxes/02_Extra/Org_mode
vendored
Submodule
1
assets/syntaxes/02_Extra/Org_mode
vendored
Submodule
Submodule assets/syntaxes/02_Extra/Org_mode added at bb6e5d8481
2
assets/syntaxes/02_Extra/PowerShell
vendored
2
assets/syntaxes/02_Extra/PowerShell
vendored
Submodule assets/syntaxes/02_Extra/PowerShell updated: c0372a1d2d...a08b55bf11
1
assets/syntaxes/02_Extra/SmartVHDL
vendored
Submodule
1
assets/syntaxes/02_Extra/SmartVHDL
vendored
Submodule
Submodule assets/syntaxes/02_Extra/SmartVHDL added at b45507ddc8
2
assets/syntaxes/02_Extra/Zig
vendored
2
assets/syntaxes/02_Extra/Zig
vendored
Submodule assets/syntaxes/02_Extra/Zig updated: 1a4a38445f...8a4a3fe4a0
42
assets/syntaxes/02_Extra/apt-source-list.sublime-syntax
vendored
Normal file
42
assets/syntaxes/02_Extra/apt-source-list.sublime-syntax
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# See http://www.sublimetext.com/docs/syntax.html
|
||||||
|
name: debsources
|
||||||
|
file_extensions:
|
||||||
|
- sources.list
|
||||||
|
scope: text.apt-source-list
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: comments
|
||||||
|
- match: ^[\w-]+
|
||||||
|
scope: constant.language.apt-source-list
|
||||||
|
- match: \w+://\S+
|
||||||
|
scope: markup.underline.link.apt-source-list
|
||||||
|
push: distribution
|
||||||
|
- match: \bmain\b
|
||||||
|
scope: support.class.apt-source-list
|
||||||
|
- match: \buniverse\b
|
||||||
|
scope: support.constant.apt-source-list
|
||||||
|
- match: \brestricted\b
|
||||||
|
scope: storage.modifier.apt-source-list
|
||||||
|
- match: \bmultiverse\b
|
||||||
|
scope: keyword.other.apt-source-list
|
||||||
|
- match: '[\w-]+'
|
||||||
|
scope: constant.other.apt-source-list
|
||||||
|
|
||||||
|
comments:
|
||||||
|
- match: '#'
|
||||||
|
scope: punctuation.definition.comment.apt-source-list
|
||||||
|
push: line_comment
|
||||||
|
|
||||||
|
line_comment:
|
||||||
|
- meta_scope: comment.line.apt-source-list
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
|
||||||
|
distribution:
|
||||||
|
- match: \S+
|
||||||
|
scope: support.type.apt-source-list
|
||||||
|
pop: 1
|
||||||
|
- match: $
|
||||||
|
pop: 1
|
2
assets/syntaxes/02_Extra/cmd-help
vendored
2
assets/syntaxes/02_Extra/cmd-help
vendored
Submodule assets/syntaxes/02_Extra/cmd-help updated: 209559b72f...c71ba410bd
2
assets/syntaxes/02_Extra/hosts
vendored
2
assets/syntaxes/02_Extra/hosts
vendored
Submodule assets/syntaxes/02_Extra/hosts updated: 21250a7117...60ed92c472
24
assets/syntaxes/02_Extra/log.sublime-syntax
vendored
24
assets/syntaxes/02_Extra/log.sublime-syntax
vendored
@@ -38,21 +38,21 @@ contexts:
|
|||||||
scope: markup.underline.link.scheme.log
|
scope: markup.underline.link.scheme.log
|
||||||
push: url-host
|
push: url-host
|
||||||
log_level_lines:
|
log_level_lines:
|
||||||
- match: ^(?=.*{{error}})
|
- match: (?=.*{{error}})
|
||||||
push:
|
push:
|
||||||
- error_line
|
- error_line_meta
|
||||||
- main_pop_at_eol
|
- main_pop_at_eol
|
||||||
- match: ^(?=.*{{warning}})
|
- match: (?=.*{{warning}})
|
||||||
push:
|
push:
|
||||||
- warning_line
|
- warning_line_meta
|
||||||
- main_pop_at_eol
|
- main_pop_at_eol
|
||||||
- match: ^(?=.*{{info}})
|
- match: (?=.*{{info}})
|
||||||
push:
|
push:
|
||||||
- info_line
|
- info_line_meta
|
||||||
- main_pop_at_eol
|
- main_pop_at_eol
|
||||||
- match: ^(?=.*{{debug}})
|
- match: (?=.*{{debug}})
|
||||||
push:
|
push:
|
||||||
- debug_line
|
- debug_line_meta
|
||||||
- main_pop_at_eol
|
- main_pop_at_eol
|
||||||
log_levels:
|
log_levels:
|
||||||
- match: '{{error}}'
|
- match: '{{error}}'
|
||||||
@@ -63,16 +63,16 @@ contexts:
|
|||||||
scope: markup.info.log
|
scope: markup.info.log
|
||||||
- match: '{{debug}}'
|
- match: '{{debug}}'
|
||||||
scope: markup.info.log
|
scope: markup.info.log
|
||||||
error_line:
|
error_line_meta:
|
||||||
- meta_scope: meta.annotation.error-line.log
|
- meta_scope: meta.annotation.error-line.log
|
||||||
- include: immediately_pop
|
- include: immediately_pop
|
||||||
warning_line:
|
warning_line_meta:
|
||||||
- meta_scope: meta.annotation.warning-line.log
|
- meta_scope: meta.annotation.warning-line.log
|
||||||
- include: immediately_pop
|
- include: immediately_pop
|
||||||
info_line:
|
info_line_meta:
|
||||||
- meta_scope: meta.annotation.info-line.log
|
- meta_scope: meta.annotation.info-line.log
|
||||||
- include: immediately_pop
|
- include: immediately_pop
|
||||||
debug_line:
|
debug_line_meta:
|
||||||
- meta_scope: meta.annotation.debug-line.log
|
- meta_scope: meta.annotation.debug-line.log
|
||||||
- include: immediately_pop
|
- include: immediately_pop
|
||||||
immediately_pop:
|
immediately_pop:
|
||||||
|
1
assets/syntaxes/02_Extra/sublime-odin
vendored
Submodule
1
assets/syntaxes/02_Extra/sublime-odin
vendored
Submodule
Submodule assets/syntaxes/02_Extra/sublime-odin added at 5d6a0ed41e
36
assets/syntaxes/02_Extra/syslog.sublime-syntax
vendored
36
assets/syntaxes/02_Extra/syslog.sublime-syntax
vendored
@@ -8,10 +8,10 @@ scope: text.log.syslog
|
|||||||
contexts:
|
contexts:
|
||||||
main:
|
main:
|
||||||
- match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2})
|
- match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2})
|
||||||
scope: meta.datetime.syslog constant.numeric.syslog
|
scope: meta.datetime.syslog
|
||||||
captures:
|
captures:
|
||||||
1: meta.date.syslog
|
1: meta.date.syslog constant.numeric.syslog
|
||||||
2: meta.time.syslog
|
2: meta.time.syslog constant.numeric.syslog
|
||||||
push: loghost
|
push: loghost
|
||||||
- match: ^
|
- match: ^
|
||||||
push: text
|
push: text
|
||||||
@@ -31,22 +31,24 @@ contexts:
|
|||||||
structured-data:
|
structured-data:
|
||||||
- match: '\['
|
- match: '\['
|
||||||
scope: punctuation.section.mapping.begin.syslog
|
scope: punctuation.section.mapping.begin.syslog
|
||||||
push:
|
push: structured-data-contents
|
||||||
- match: \]
|
|
||||||
scope: punctuation.section.mapping.end.syslog
|
|
||||||
pop: true
|
|
||||||
- match: \w+
|
|
||||||
scope: variable.parameter.syslog
|
|
||||||
- match: =
|
|
||||||
scope: keyword.operator.assignment.syslog
|
|
||||||
push:
|
|
||||||
- match: '[^\s\]]+'
|
|
||||||
scope: constant.other.syslog
|
|
||||||
pop: true
|
|
||||||
- match: (?=\])
|
|
||||||
pop: true
|
|
||||||
- match: (?=\S)
|
- match: (?=\S)
|
||||||
set: text
|
set: text
|
||||||
|
structured-data-contents:
|
||||||
|
- match: \]
|
||||||
|
scope: punctuation.section.mapping.end.syslog
|
||||||
|
pop: true
|
||||||
|
- match: \w+
|
||||||
|
scope: variable.parameter.syslog
|
||||||
|
- match: =
|
||||||
|
scope: keyword.operator.assignment.syslog
|
||||||
|
push: structured-data-assignment
|
||||||
|
structured-data-assignment:
|
||||||
|
- match: '[^\s\]]+'
|
||||||
|
scope: constant.other.syslog
|
||||||
|
pop: true
|
||||||
|
- match: (?=\])
|
||||||
|
pop: true
|
||||||
text:
|
text:
|
||||||
- match: $
|
- match: $
|
||||||
pop: true
|
pop: true
|
||||||
|
1
assets/syntaxes/02_Extra/typst-syntax-highlight
vendored
Submodule
1
assets/syntaxes/02_Extra/typst-syntax-highlight
vendored
Submodule
Submodule assets/syntaxes/02_Extra/typst-syntax-highlight added at 4e2e68b0a1
2
assets/theme_preview.rs
vendored
2
assets/theme_preview.rs
vendored
@@ -1,5 +1,5 @@
|
|||||||
// Output the square of a number.
|
// Output the square of a number.
|
||||||
fn print_square(num: f64) {
|
fn print_square(num: f64) {
|
||||||
let result = f64::powf(num, 2.0);
|
let result = f64::powf(num, 2.0);
|
||||||
println!("The square of {:.2} is {:.2}.", num, result);
|
println!("The square of {num:.2} is {result:.2}.");
|
||||||
}
|
}
|
||||||
|
BIN
assets/themes.bin
vendored
BIN
assets/themes.bin
vendored
Binary file not shown.
1
assets/themes/Catppuccin
vendored
Submodule
1
assets/themes/Catppuccin
vendored
Submodule
Submodule assets/themes/Catppuccin added at ccf194fdc9
2
assets/themes/github-sublime-theme
vendored
2
assets/themes/github-sublime-theme
vendored
Submodule assets/themes/github-sublime-theme updated: 508740b243...59e525f638
2
assets/themes/gruvbox
vendored
2
assets/themes/gruvbox
vendored
Submodule assets/themes/gruvbox updated: 64c47250e5...4050347282
2
assets/themes/zenburn
vendored
2
assets/themes/zenburn
vendored
Submodule assets/themes/zenburn updated: 86d4ee7a1f...4f21745723
@@ -9,6 +9,8 @@ use anyhow::{anyhow, bail};
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_with::DeserializeFromStr;
|
use serde_with::DeserializeFromStr;
|
||||||
@@ -34,13 +36,14 @@ impl FromStr for MappingTarget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MappingTarget {
|
impl ToTokens for MappingTarget {
|
||||||
fn codegen(&self) -> String {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
let t = match self {
|
||||||
Self::MapTo(syntax) => format!(r###"MappingTarget::MapTo(r#"{syntax}"#)"###),
|
Self::MapTo(syntax) => quote! { MappingTarget::MapTo(#syntax) },
|
||||||
Self::MapToUnknown => "MappingTarget::MapToUnknown".into(),
|
Self::MapToUnknown => quote! { MappingTarget::MapToUnknown },
|
||||||
Self::MapExtensionToUnknown => "MappingTarget::MapExtensionToUnknown".into(),
|
Self::MapExtensionToUnknown => quote! { MappingTarget::MapExtensionToUnknown },
|
||||||
}
|
};
|
||||||
|
tokens.append_all(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,22 +119,17 @@ impl FromStr for Matcher {
|
|||||||
Ok(Self(non_empty_segments))
|
Ok(Self(non_empty_segments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Matcher {
|
impl ToTokens for Matcher {
|
||||||
fn codegen(&self) -> String {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self.0.len() {
|
let t = match self.0.as_slice() {
|
||||||
0 => unreachable!("0-length matcher should never be created"),
|
[] => unreachable!("0-length matcher should never be created"),
|
||||||
// if-let guard would be ideal here
|
[MatcherSegment::Text(text)] => {
|
||||||
// see: https://github.com/rust-lang/rust/issues/51114
|
quote! { Lazy::new(|| Some(build_matcher_fixed(#text))) }
|
||||||
1 if self.0[0].is_text() => {
|
|
||||||
let s = self.0[0].text().unwrap();
|
|
||||||
format!(r###"Lazy::new(|| Some(build_matcher_fixed(r#"{s}"#)))"###)
|
|
||||||
}
|
}
|
||||||
// parser logic ensures that this case can only happen when there are dynamic segments
|
// parser logic ensures that this case can only happen when there are dynamic segments
|
||||||
_ => {
|
segs @ [_, ..] => quote! { Lazy::new(|| build_matcher_dynamic(&[ #(#segs),* ])) },
|
||||||
let segs = self.0.iter().map(MatcherSegment::codegen).join(", ");
|
};
|
||||||
format!(r###"Lazy::new(|| build_matcher_dynamic(&[{segs}]))"###)
|
tokens.append_all(t);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +141,15 @@ enum MatcherSegment {
|
|||||||
Text(String),
|
Text(String),
|
||||||
Env(String),
|
Env(String),
|
||||||
}
|
}
|
||||||
|
impl ToTokens for MatcherSegment {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let t = match self {
|
||||||
|
Self::Text(text) => quote! { MatcherSegment::Text(#text) },
|
||||||
|
Self::Env(env) => quote! { MatcherSegment::Env(#env) },
|
||||||
|
};
|
||||||
|
tokens.append_all(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl MatcherSegment {
|
impl MatcherSegment {
|
||||||
fn is_text(&self) -> bool {
|
fn is_text(&self) -> bool {
|
||||||
@@ -163,12 +170,6 @@ impl MatcherSegment {
|
|||||||
Self::Env(t) => Some(t),
|
Self::Env(t) => Some(t),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn codegen(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Text(s) => format!(r###"MatcherSegment::Text(r#"{s}"#)"###),
|
|
||||||
Self::Env(s) => format!(r###"MatcherSegment::Env(r#"{s}"#)"###),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that models a single .toml file in /src/syntax_mapping/builtins/.
|
/// A struct that models a single .toml file in /src/syntax_mapping/builtins/.
|
||||||
@@ -194,22 +195,19 @@ impl MappingDefModel {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct MappingList(Vec<(Matcher, MappingTarget)>);
|
struct MappingList(Vec<(Matcher, MappingTarget)>);
|
||||||
impl MappingList {
|
impl ToTokens for MappingList {
|
||||||
fn codegen(&self) -> String {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
let array_items: Vec<_> = self
|
let len = self.0.len();
|
||||||
|
let array_items = self
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(matcher, target)| {
|
.map(|(matcher, target)| quote! { (#matcher, #target) });
|
||||||
format!("({m}, {t})", m = matcher.codegen(), t = target.codegen())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let len = array_items.len();
|
|
||||||
|
|
||||||
format!(
|
let t = quote! {
|
||||||
"/// Generated by build script from /src/syntax_mapping/builtins/.\n\
|
/// Generated by build script from /src/syntax_mapping/builtins/.
|
||||||
pub(crate) static BUILTIN_MAPPINGS: [(Lazy<Option<GlobMatcher>>, MappingTarget); {len}] = [\n{items}\n];",
|
pub(crate) static BUILTIN_MAPPINGS: [(Lazy<Option<GlobMatcher>>, MappingTarget); #len] = [#(#array_items),*];
|
||||||
items = array_items.join(",\n")
|
};
|
||||||
)
|
tokens.append_all(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +234,14 @@ fn get_def_paths() -> anyhow::Result<Vec<PathBuf>> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let mut toml_paths = vec![];
|
let mut toml_paths = vec![];
|
||||||
for subdir in source_subdirs {
|
for subdir_name in source_subdirs {
|
||||||
let wd = WalkDir::new(Path::new("src/syntax_mapping/builtins").join(subdir));
|
let subdir = Path::new("src/syntax_mapping/builtins").join(subdir_name);
|
||||||
|
if !subdir.try_exists()? {
|
||||||
|
// Directory might not exist due to this `cargo vendor` bug:
|
||||||
|
// https://github.com/rust-lang/cargo/issues/15080
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let wd = WalkDir::new(subdir);
|
||||||
let paths = wd
|
let paths = wd
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map_ok(|entry| {
|
.filter_map_ok(|entry| {
|
||||||
@@ -285,10 +289,15 @@ pub fn build_static_mappings() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let mappings = read_all_mappings()?;
|
let mappings = read_all_mappings()?;
|
||||||
|
|
||||||
|
// IMPRV: parse + unparse is a bit cringe, but there seems to be no better
|
||||||
|
// option given the limited APIs of `prettyplease`
|
||||||
|
let rs_src = syn::parse_file(&mappings.to_token_stream().to_string())?;
|
||||||
|
let rs_src_pretty = prettyplease::unparse(&rs_src);
|
||||||
|
|
||||||
let codegen_path = Path::new(&env::var_os("OUT_DIR").ok_or(anyhow!("OUT_DIR is unset"))?)
|
let codegen_path = Path::new(&env::var_os("OUT_DIR").ok_or(anyhow!("OUT_DIR is unset"))?)
|
||||||
.join("codegen_static_syntax_mappings.rs");
|
.join("codegen_static_syntax_mappings.rs");
|
||||||
|
|
||||||
fs::write(codegen_path, mappings.codegen())?;
|
fs::write(codegen_path, rs_src_pretty)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -163,7 +163,7 @@ git show v0.6.0:src/main.rs | bat -l rs
|
|||||||
볼 수 있습니다:
|
볼 수 있습니다:
|
||||||
```bash
|
```bash
|
||||||
batdiff() {
|
batdiff() {
|
||||||
git diff --name-only --diff-filter=d | xargs bat --diff
|
git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
이것을 별도의 도구로 쓰고 싶다면
|
이것을 별도의 도구로 쓰고 싶다면
|
||||||
@@ -461,11 +461,11 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
|
|||||||
|
|
||||||
- `ansi`는 어떤 터미널에서도 무난하게 보입니다. 이는 3비트 색상을 사용합니다:
|
- `ansi`는 어떤 터미널에서도 무난하게 보입니다. 이는 3비트 색상을 사용합니다:
|
||||||
검정, 빨강, 녹색, 노랑, 파랑, 마젠타, 시안, 하양.
|
검정, 빨강, 녹색, 노랑, 파랑, 마젠타, 시안, 하양.
|
||||||
- `base16`은 [base16](https://github.com/chriskempson/base16) 터미널 테마를 위해
|
- `base16`은 [base16](https://github.com/tinted-theming/home) 터미널 테마를 위해
|
||||||
디자인되었습니다.
|
디자인되었습니다.
|
||||||
이는 [base16 스타일 가이드라인](https://github.com/chriskempson/base16/blob/master/styling.md)에
|
이는 [base16 스타일 가이드라인](https://github.com/tinted-theming/home/blob/main/styling.md)에
|
||||||
따라 4비트 색상(3비트 색상에 밝은 변형 추가)을 사용합니다.
|
따라 4비트 색상(3비트 색상에 밝은 변형 추가)을 사용합니다.
|
||||||
- `base16-256`는 [base16-shell](https://github.com/chriskempson/base16-shell)을
|
- `base16-256`는 [base16-shell](https://github.com/tinted-theming/base16-shell)을
|
||||||
위해 디자인되었습니다.
|
위해 디자인되었습니다.
|
||||||
이는 16부터 21의 일부 밝은 색상을 8비트 색상으로 대치합니다.
|
이는 16부터 21의 일부 밝은 색상을 8비트 색상으로 대치합니다.
|
||||||
단지 256-색상 터미널을 쓰지만 base16-shell을 쓰지 않는다고 해서 이것을
|
단지 256-색상 터미널을 쓰지만 base16-shell을 쓰지 않는다고 해서 이것을
|
||||||
|
179
doc/README-ru.md
179
doc/README-ru.md
@@ -3,11 +3,11 @@
|
|||||||
<a href="https://github.com/sharkdp/bat/actions?query=workflow%3ACICD"><img src="https://github.com/sharkdp/bat/workflows/CICD/badge.svg" alt="Build Status"></a>
|
<a href="https://github.com/sharkdp/bat/actions?query=workflow%3ACICD"><img src="https://github.com/sharkdp/bat/workflows/CICD/badge.svg" alt="Build Status"></a>
|
||||||
<img src="https://img.shields.io/crates/l/bat.svg" alt="license">
|
<img src="https://img.shields.io/crates/l/bat.svg" alt="license">
|
||||||
<a href="https://crates.io/crates/bat"><img src="https://img.shields.io/crates/v/bat.svg?colorB=319e8c" alt="Version info"></a><br>
|
<a href="https://crates.io/crates/bat"><img src="https://img.shields.io/crates/v/bat.svg?colorB=319e8c" alt="Version info"></a><br>
|
||||||
Клон утилиты <i>cat(1)</i> с поддержкой выделения синтаксиса и Git
|
Клон утилиты <i>cat(1)</i> с поддержкой подсветки синтаксиса и Git
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="#выделение-синтаксиса">Ключевые возможности</a> •
|
<a href="#подсветка-синтаксиса">Ключевые возможности</a> •
|
||||||
<a href="#как-использовать">Использование</a> •
|
<a href="#как-использовать">Использование</a> •
|
||||||
<a href="#установка">Установка</a> •
|
<a href="#установка">Установка</a> •
|
||||||
<a href="#кастомизация">Кастомизация</a> •
|
<a href="#кастомизация">Кастомизация</a> •
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
[Русский]
|
[Русский]
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
### Выделение синтаксиса
|
### Подсветка синтаксиса
|
||||||
|
|
||||||
`bat` поддерживает выделение синтаксиса для огромного количества языков программирования и разметки:
|
`bat` поддерживает подсветку синтаксиса для огромного количества языков программирования и разметки:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Интеграция с Git
|
### Интеграция с Git
|
||||||
`bat` использует `git`, чтобы показать изменения в коде
|
`bat` использует `git`, чтобы показать изменения в коде
|
||||||
@@ -31,15 +31,17 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Показать непечатаемые символы
|
### Показ непечатных символов
|
||||||
|
|
||||||
Вы можете использовать `-A` / `--show-all` флаг, чтобы показать символы, которые невозможно напечатать:
|
Вы можете использовать флаг `-A` / `--show-all`, чтобы показать непечатные символы:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Автоматическое разделение текста
|
### Автоматический пейджинг терминала
|
||||||
|
|
||||||
`bat` умеет перенаправлять вывод в `less`, если вывод не помещается на экране полностью.
|
`bat` умеет перенаправлять вывод в пейджер терминала (например, в `less`), если вывод не помещается на экране полностью.
|
||||||
|
Если вы хотите, чтобы `bat` работал как `cat` всё время, вы можете установить опцию `--paging=never` в командной строке или в конфигурационном файле.
|
||||||
|
Если вы намерены использовать `bat` в качестве алиаса для `cat`, вы можете установить `alias cat='bat --paging=never'`, чтобы сохранить изначальное поведение.
|
||||||
|
|
||||||
### Объединение файлов
|
### Объединение файлов
|
||||||
|
|
||||||
@@ -86,11 +88,23 @@ bat header.md content.md footer.md > document.md
|
|||||||
|
|
||||||
bat -n main.rs # показываем только количество строк
|
bat -n main.rs # показываем только количество строк
|
||||||
|
|
||||||
bat f - g # выводит 'f' в stdin, а потом 'g'.
|
bat f - g # выводит 'f', потом stdin, а потом 'g'.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Интеграция с другими утилитами
|
### Интеграция с другими утилитами
|
||||||
|
|
||||||
|
#### `fzf`
|
||||||
|
|
||||||
|
Вы можете использовать `bat` как просмотрщик для [`fzf`](https://github.com/junegunn/fzf).
|
||||||
|
Чтобы это заработало, используйте опцию `--color=always`, чтобы вывод был всегда цветным.
|
||||||
|
Вы можете также использовать опцию `--line-range`, чтобы уменьшить время загрузки для больших файлов:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fzf --preview "bat --color=always --style=numbers --line-range=:500 {}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Больше деталей смотрите в [`README` программы `fzf`](https://github.com/junegunn/fzf#preview-window).
|
||||||
|
|
||||||
#### `find` или `fd`
|
#### `find` или `fd`
|
||||||
|
|
||||||
Вы можете использовать флаг `-exec` в `find`, чтобы посмотреть превью всех файлов в `bat`
|
Вы можете использовать флаг `-exec` в `find`, чтобы посмотреть превью всех файлов в `bat`
|
||||||
@@ -121,12 +135,22 @@ tail -f /var/log/pacman.log | bat --paging=never -l log
|
|||||||
|
|
||||||
#### `git`
|
#### `git`
|
||||||
|
|
||||||
Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с выделением синтаксиса:
|
Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с подсветкой синтаксиса:
|
||||||
```bash
|
```bash
|
||||||
git show v0.6.0:src/main.rs | bat -l rs
|
git show v0.6.0:src/main.rs | bat -l rs
|
||||||
```
|
```
|
||||||
|
|
||||||
Обратите внимание, что выделение синтаксиса не работает в `git diff` на данный момент. Если вам это нужно, посмотрите [`delta`](https://github.com/dandavison/delta).
|
#### `git diff`
|
||||||
|
|
||||||
|
Вы можете использовать `bat` с `git diff` для просмотра строк кода вокруг изменений с подсветкой синтаксиса:
|
||||||
|
```bash
|
||||||
|
batdiff() {
|
||||||
|
git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Если вы хотите использовать это как отдельную программу, посмотрите `batdiff` из [`bat-extras`](https://github.com/eth-p/bat-extras).
|
||||||
|
|
||||||
|
Если вам это нужна более полная поддержка для операций с git и diff, посмотрите [`delta`](https://github.com/dandavison/delta).
|
||||||
|
|
||||||
#### `xclip`
|
#### `xclip`
|
||||||
|
|
||||||
@@ -135,17 +159,18 @@ git show v0.6.0:src/main.rs | bat -l rs
|
|||||||
```bash
|
```bash
|
||||||
bat main.cpp | xclip
|
bat main.cpp | xclip
|
||||||
```
|
```
|
||||||
`bat` обнаружит перенаправление вывода и выведет обычный текст без выделения синтаксиса.
|
`bat` обнаружит перенаправление вывода и выведет обычный текст без подсветки синтаксиса.
|
||||||
|
|
||||||
#### `man`
|
#### `man`
|
||||||
|
|
||||||
`bat` может быть использован в виде выделения цвета для `man`, для этого установите переменную окружения
|
`bat` может быть использован для раскрашивания вывода `man`, для этого установите переменную окружения
|
||||||
`MANPAGER`:
|
`MANPAGER`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
||||||
man 2 select
|
man 2 select
|
||||||
```
|
```
|
||||||
|
(замените `bat` на `batcat`, если у вас Debian или Ubuntu)
|
||||||
|
|
||||||
Возможно вам понадобится также установить `MANROFFOPT="-c"`, если у вас есть проблемы с форматированием.
|
Возможно вам понадобится также установить `MANROFFOPT="-c"`, если у вас есть проблемы с форматированием.
|
||||||
|
|
||||||
@@ -153,10 +178,40 @@ man 2 select
|
|||||||
|
|
||||||
Обратите внимание, что [синтаксис manpage](assets/syntaxes/02_Extra/Manpage.sublime-syntax) разрабатывается в этом репозитории и все еще находится в разработке.
|
Обратите внимание, что [синтаксис manpage](assets/syntaxes/02_Extra/Manpage.sublime-syntax) разрабатывается в этом репозитории и все еще находится в разработке.
|
||||||
|
|
||||||
|
Также заметьте, что это [не заработает](https://github.com/sharkdp/bat/issues/1145) с реализацией `man` через Mandocs.
|
||||||
|
|
||||||
#### `prettier` / `shfmt` / `rustfmt`
|
#### `prettier` / `shfmt` / `rustfmt`
|
||||||
|
|
||||||
[`Prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) — скрипт, который форматирует код и выводит его с помощью `bat`.
|
[`Prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) — скрипт, который форматирует код и выводит его с помощью `bat`.
|
||||||
|
|
||||||
|
#### Подсветка сообщений `--help`
|
||||||
|
|
||||||
|
Вы можете использовать `bat`, чтобы подсвечивать текст справки комманд: `$ cp --help | bat -plhelp`
|
||||||
|
|
||||||
|
Вы можете сделать такую вспомогательную команду для этого:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# in your .bashrc/.zshrc/*rc
|
||||||
|
alias bathelp='bat --plain --language=help'
|
||||||
|
help() {
|
||||||
|
"$@" --help 2>&1 | bathelp
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
В этом случае, вы можете просто писать `$ help cp` или `$ help git commit`.
|
||||||
|
|
||||||
|
Если вы используете `zsh`, вы можете объявить глобальные алиасы для `-h` и `--help`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
alias -g -- -h='-h 2>&1 | bat --language=help --style=plain'
|
||||||
|
alias -g -- --help='--help 2>&1 | bat --language=help --style=plain'
|
||||||
|
```
|
||||||
|
|
||||||
|
В этом случае, вы можете продолжать использовать `cp --help`, но при этом получать подцвеченный вывод.
|
||||||
|
|
||||||
|
Обратите внимание, что не всегда опция `-h` является краткой формы опции `--help` (например, у `ls`).
|
||||||
|
|
||||||
|
Пожалуйста, сообщайте о проблемах с подсветкой справки в [этот репозиторий](https://github.com/victor-gp/cmd-help-sublime-syntax).
|
||||||
|
|
||||||
## Установка
|
## Установка
|
||||||
|
|
||||||
@@ -165,8 +220,7 @@ man 2 select
|
|||||||
### Ubuntu (с помощью `apt`)
|
### Ubuntu (с помощью `apt`)
|
||||||
*... и другие дистрибутивы основанные на Debian.*
|
*... и другие дистрибутивы основанные на Debian.*
|
||||||
|
|
||||||
`bat` есть в репозиториях [Ubuntu](https://packages.ubuntu.com/eoan/bat) и
|
`bat` доступен на [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) и [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat).
|
||||||
[Debian](https://packages.debian.org/sid/bat) и доступен начиная с Ubuntu Eoan 19.10. На Debian `bat` пока что доступен только с нестабильной веткой "Sid".
|
|
||||||
|
|
||||||
Если ваша версия Ubuntu/Debian достаточно новая, вы можете установить `bat` так:
|
Если ваша версия Ubuntu/Debian достаточно новая, вы можете установить `bat` так:
|
||||||
|
|
||||||
@@ -245,6 +299,14 @@ cd /usr/ports/textproc/bat
|
|||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### On OpenBSD
|
||||||
|
|
||||||
|
Вы можете установить `bat` с помощью [`pkg_add(1)`](https://man.openbsd.org/pkg_add.1):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pkg_add bat
|
||||||
|
```
|
||||||
|
|
||||||
### С помощью nix
|
### С помощью nix
|
||||||
|
|
||||||
Вы можете установить `bat`, используя [nix package manager](https://nixos.org/nix):
|
Вы можете установить `bat`, используя [nix package manager](https://nixos.org/nix):
|
||||||
@@ -253,6 +315,14 @@ make install
|
|||||||
nix-env -i bat
|
nix-env -i bat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Через flox
|
||||||
|
|
||||||
|
Вы можете установить `bat` используя [Flox](https://flox.dev)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flox install bat
|
||||||
|
```
|
||||||
|
|
||||||
### openSUSE
|
### openSUSE
|
||||||
|
|
||||||
Вы можете установить `bat` с помощью `zypper`:
|
Вы можете установить `bat` с помощью `zypper`:
|
||||||
@@ -261,7 +331,7 @@ nix-env -i bat
|
|||||||
zypper install bat
|
zypper install bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### macOS
|
### На macOS (или Linux) через Homebrew
|
||||||
|
|
||||||
Вы можете установить `bat` с помощью [Homebrew](http://braumeister.org/formula/bat):
|
Вы можете установить `bat` с помощью [Homebrew](http://braumeister.org/formula/bat):
|
||||||
|
|
||||||
@@ -269,6 +339,8 @@ zypper install bat
|
|||||||
brew install bat
|
brew install bat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### На macOS через MacPorts
|
||||||
|
|
||||||
Или же установить его с помощью [MacPorts](https://ports.macports.org/port/bat/summary):
|
Или же установить его с помощью [MacPorts](https://ports.macports.org/port/bat/summary):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -277,7 +349,19 @@ port install bat
|
|||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#using-bat-on-windows).
|
Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#использование-bat-в-windows).
|
||||||
|
|
||||||
|
#### Пререквитизы
|
||||||
|
|
||||||
|
Вам нужно установить пакет [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads).
|
||||||
|
|
||||||
|
#### С помощью WinGet
|
||||||
|
|
||||||
|
Вы можете установить `bat` через [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
winget install sharkdp.bat
|
||||||
|
```
|
||||||
|
|
||||||
#### С помощью Chocolatey
|
#### С помощью Chocolatey
|
||||||
|
|
||||||
@@ -293,50 +377,10 @@ choco install bat
|
|||||||
scoop install bat
|
scoop install bat
|
||||||
```
|
```
|
||||||
|
|
||||||
Для этого у вас должен быть установлен [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads).
|
|
||||||
|
|
||||||
#### Из заранее скомпилированных файлов:
|
#### Из заранее скомпилированных файлов:
|
||||||
|
|
||||||
Их вы можете скачать на [странице релизов](https://github.com/sharkdp/bat/releases).
|
Их вы можете скачать на [странице релизов](https://github.com/sharkdp/bat/releases).
|
||||||
|
|
||||||
Для этого у вас должен быть установлен [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads).
|
|
||||||
|
|
||||||
### С помощью Docker
|
|
||||||
|
|
||||||
Вы можете использовать [Docker image](https://hub.docker.com/r/danlynn/bat/), чтобы запустить `bat` в контейнере:
|
|
||||||
```bash
|
|
||||||
docker pull danlynn/bat
|
|
||||||
alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat'
|
|
||||||
```
|
|
||||||
|
|
||||||
### С помощью Ansible
|
|
||||||
|
|
||||||
Вы можете установить `bat` с [Ansible](https://www.ansible.com/):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Устанавливаем роль на устройстве
|
|
||||||
ansible-galaxy install aeimer.install_bat
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
# Playbook для установки bat
|
|
||||||
- host: all
|
|
||||||
roles:
|
|
||||||
- aeimer.install_bat
|
|
||||||
```
|
|
||||||
|
|
||||||
- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat)
|
|
||||||
- [GitHub](https://github.com/aeimer/ansible-install-bat)
|
|
||||||
|
|
||||||
Этот способ должен сработать со следующими дистрибутивами:
|
|
||||||
- Debian/Ubuntu
|
|
||||||
- ARM (например Raspberry PI)
|
|
||||||
- Arch Linux
|
|
||||||
- Void Linux
|
|
||||||
- FreeBSD
|
|
||||||
- macOS
|
|
||||||
|
|
||||||
### Из скомпилированных файлов
|
### Из скомпилированных файлов
|
||||||
|
|
||||||
Перейдите на [страницу релизов](https://github.com/sharkdp/bat/releases) для
|
Перейдите на [страницу релизов](https://github.com/sharkdp/bat/releases) для
|
||||||
@@ -344,15 +388,24 @@ ansible-galaxy install aeimer.install_bat
|
|||||||
|
|
||||||
### Из исходников
|
### Из исходников
|
||||||
|
|
||||||
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.74.0 или выше. После этого используйте `cargo`, чтобы все скомпилировать:
|
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.74.0 или выше. После этого используйте `cargo`, чтобы всё скомпилировать:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo install --locked bat
|
cargo install --locked bat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Заметьте, что дополнительные файлы, такие как документация man и подсказки командной строки, не могут быть установлены таким способом.
|
||||||
|
Они будут сгенерированы командой `cargo` должны быть доступны в папке сборки (в `build`).
|
||||||
|
|
||||||
|
Подсказки командной строки также доступны при таком запуске:
|
||||||
|
```bash
|
||||||
|
bat --completion <shell>
|
||||||
|
# see --help for supported shells
|
||||||
|
```
|
||||||
|
|
||||||
## Кастомизация
|
## Кастомизация
|
||||||
|
|
||||||
### Темы для выделения текста
|
### Темы для подсветки синтаксиса
|
||||||
|
|
||||||
Используйте `bat --list-themes`, чтобы вывести список всех доступных тем. Для выбора темы `TwoDark` используйте `bat` с флагом
|
Используйте `bat --list-themes`, чтобы вывести список всех доступных тем. Для выбора темы `TwoDark` используйте `bat` с флагом
|
||||||
`--theme=TwoDark` или выставьте переменную окружения `BAT_THEME` в `TwoDark`. Используйте `export BAT_THEME="TwoDark"` в конфигурационном файле вашей оболочки, чтобы изменить ее навсегда. Или же используйте [конфигурационный файл](https://github.com/sharkdp/bat#configuration-file) `bat`.
|
`--theme=TwoDark` или выставьте переменную окружения `BAT_THEME` в `TwoDark`. Используйте `export BAT_THEME="TwoDark"` в конфигурационном файле вашей оболочки, чтобы изменить ее навсегда. Или же используйте [конфигурационный файл](https://github.com/sharkdp/bat#configuration-file) `bat`.
|
||||||
@@ -372,7 +425,7 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /путь/к/ф
|
|||||||
|
|
||||||
### Добавление новых синтаксисов
|
### Добавление новых синтаксисов
|
||||||
|
|
||||||
`bat` использует [`syntect`](https://github.com/trishume/syntect/) для выделения синтаксиса. `syntect` может читать
|
`bat` использует [`syntect`](https://github.com/trishume/syntect/) для подсветки синтаксиса. `syntect` может читать
|
||||||
[файл `.sublime-syntax`](https://www.sublimetext.com/docs/3/syntax.html)
|
[файл `.sublime-syntax`](https://www.sublimetext.com/docs/3/syntax.html)
|
||||||
и темы. Чтобы добавить новый синтаксис, сделайте следующее:
|
и темы. Чтобы добавить новый синтаксис, сделайте следующее:
|
||||||
|
|
||||||
@@ -403,7 +456,7 @@ bat cache --clear
|
|||||||
|
|
||||||
### Добавление новых тем
|
### Добавление новых тем
|
||||||
|
|
||||||
Это работает похожим образом, так же как и добавление новых тем выделения синтаксиса
|
Это работает похожим образом, так же как и добавление новых тем подсветки синтаксиса
|
||||||
|
|
||||||
Во-первых, создайте каталог с новыми темами для синтаксиса:
|
Во-первых, создайте каталог с новыми темами для синтаксиса:
|
||||||
```bash
|
```bash
|
||||||
@@ -590,7 +643,7 @@ cargo install --locked --force
|
|||||||
Есть очень много альтернатив `bat`. Смотрите [этот документ](doc/alternatives.md) для сравнения.
|
Есть очень много альтернатив `bat`. Смотрите [этот документ](doc/alternatives.md) для сравнения.
|
||||||
|
|
||||||
## Лицензия
|
## Лицензия
|
||||||
Copyright (c) 2018-2021 [Разработчики bat](https://github.com/sharkdp/bat).
|
Copyright (c) 2018-2024 [Разработчики bat](https://github.com/sharkdp/bat).
|
||||||
|
|
||||||
`bat` распространяется под лицензиями MIT License и Apache License 2.0 (на выбор пользователя).
|
`bat` распространяется под лицензиями MIT License и Apache License 2.0 (на выбор пользователя).
|
||||||
|
|
||||||
|
@@ -150,7 +150,7 @@ git show v0.6.0:src/main.rs | bat -l rs
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
batdiff() {
|
batdiff() {
|
||||||
git diff --name-only --diff-filter=d | xargs bat --diff
|
git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -170,20 +170,23 @@ bat main.cpp | xclip
|
|||||||
|
|
||||||
#### `man`
|
#### `man`
|
||||||
|
|
||||||
`bat`也能给`man`的输出上色。这需要设置`MANPAGER`环境变量:
|
`bat` 可以通过设置 `MANPAGER` 环境变量,用作 `man` 的彩色分页器:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
export MANPAGER="sh -c 'awk '\''{ gsub(/\x1B\[[0-9;]*m/, \"\", \$0); gsub(/.\x08/, \"\", \$0); print }'\'' | bat -p -lman'"
|
||||||
man 2 select
|
man 2 select
|
||||||
```
|
```
|
||||||
|
|
||||||
(如果你使用的是 Debian 或者 Ubuntu,使用`batcat`替换`bat`)
|
(如果你使用 Debian 或 Ubuntu,请将 `batcat` 替换为 `bat`)
|
||||||
|
|
||||||
如果你遇到格式化问题,设置`MANROFFOPT="-c"`也许会有帮助。
|
如果你希望将其打包为一个新的命令,也可以使用 [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md)。
|
||||||
|
|
||||||
`batman`能提供类似功能——作为一个独立的命令。
|
> [!WARNING]
|
||||||
|
> 在使用 Mandoc 的 `man` 实现时,这[无法](https://github.com/sharkdp/bat/issues/1145)直接工作。
|
||||||
|
>
|
||||||
|
> 请使用 `batman`,或将此 Shell 脚本包装为 [Shebang 可执行文件](https://en.wikipedia.org/wiki/Shebang_(Unix)),并将 `MANPAGER` 指向该文件。
|
||||||
|
|
||||||
注意:[man page 语法](assets/syntaxes/02_Extra/Manpage.sublime-syntax) 还需要完善。在使用特定的`man`实现时该功能[无法正常工作](https://github.com/sharkdp/bat/issues/1145)。
|
注意,[Manpage 语法](assets/syntaxes/02_Extra/Manpage.sublime-syntax)是在此仓库中开发的,仍需一些改进。
|
||||||
|
|
||||||
#### `prettier` / `shfmt` / `rustfmt`
|
#### `prettier` / `shfmt` / `rustfmt`
|
||||||
|
|
||||||
@@ -401,8 +404,8 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
|
|||||||
`bat` 自带三个 [8-bit 色彩](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 主题:
|
`bat` 自带三个 [8-bit 色彩](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 主题:
|
||||||
|
|
||||||
- `ansi` 适应于大部分终端。它使用 3-bit 色彩:黑红绿黄蓝洋红靛青白。
|
- `ansi` 适应于大部分终端。它使用 3-bit 色彩:黑红绿黄蓝洋红靛青白。
|
||||||
- `base16`专为 [base16](https://github.com/chriskempson/base16) 终端设计。它使用 4-bit 色彩(带有亮度的 3-bit 色彩)。根据 [base16 styling guidelines](https://github.com/chriskempson/base16/blob/master/styling.md) 制作。
|
- `base16`专为 [base16](https://github.com/tinted-theming/home) 终端设计。它使用 4-bit 色彩(带有亮度的 3-bit 色彩)。根据 [base16 styling guidelines](https://github.com/tinted-theming/home/blob/main/styling.md) 制作。
|
||||||
- `base16-25`专为 [base16-shell](https://github.com/chriskempson/base16-shell) 设计。它把部分亮色替换为 8-bit 色彩。请不要直接使用该主题,除非你清楚你的256色终端是否使用 base16-shell。
|
- `base16-25`专为 [base16-shell](https://github.com/tinted-theming/base16-shell) 设计。它把部分亮色替换为 8-bit 色彩。请不要直接使用该主题,除非你清楚你的256色终端是否使用 base16-shell。
|
||||||
|
|
||||||
尽管这些主题具有诸多限制,但具有一些 truecolor 主题不具有的三个优点:
|
尽管这些主题具有诸多限制,但具有一些 truecolor 主题不具有的三个优点:
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ in the `.sublime-syntax` format.
|
|||||||
4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the
|
4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the
|
||||||
`bat` binary.
|
`bat` binary.
|
||||||
|
|
||||||
5. Use `bat --list-languages` to check if the new languages are available.
|
5. Use `bat --list-languages` to check if the new languages are available. You may want to do something like ``export PATH="`pwd`/target/debug:$PATH"`` to ensure the locally compiled version is the one being used.
|
||||||
|
|
||||||
6. Add a syntax test for the new language. See [below](#Syntax-tests) for details.
|
6. Add a syntax test for the new language. See [below](#Syntax-tests) for details.
|
||||||
|
|
||||||
@@ -102,4 +102,4 @@ The following files have been manually modified after converting from a `.tmLang
|
|||||||
https://github.com/seanjames777/SML-Language-Definition/blob/master/sml.tmLanguage
|
https://github.com/seanjames777/SML-Language-Definition/blob/master/sml.tmLanguage
|
||||||
* `Cabal.sublime_syntax` has been added manually from
|
* `Cabal.sublime_syntax` has been added manually from
|
||||||
https://github.com/SublimeHaskell/SublimeHaskell/ - we don't want to include the whole submodule because it includes other syntaxes ("Haskell improved") as well.
|
https://github.com/SublimeHaskell/SublimeHaskell/ - we don't want to include the whole submodule because it includes other syntaxes ("Haskell improved") as well.
|
||||||
* `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean/blob/master/syntaxes/lean.json via conversion.
|
* `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean4/blob/master/vscode-lean4/syntaxes/lean4.json via conversion.
|
||||||
|
@@ -194,6 +194,8 @@ Options:
|
|||||||
'--line-range 40:' prints lines 40 to the end of the file
|
'--line-range 40:' prints lines 40 to the end of the file
|
||||||
'--line-range 40' only prints line 40
|
'--line-range 40' only prints line 40
|
||||||
'--line-range 30:+10' prints lines 30 to 40
|
'--line-range 30:+10' prints lines 30 to 40
|
||||||
|
'--line-range 35::5' prints lines 30 to 40 (line 35 with 5 lines of context)
|
||||||
|
'--line-range 30:40:2' prints lines 28 to 42 (range 30-40 with 2 lines of context)
|
||||||
|
|
||||||
-L, --list-languages
|
-L, --list-languages
|
||||||
Display a list of supported languages for syntax highlighting.
|
Display a list of supported languages for syntax highlighting.
|
||||||
|
BIN
doc/sponsors/graphite-logo.jpeg
Normal file
BIN
doc/sponsors/graphite-logo.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
doc/sponsors/warp-pack-header.png
Normal file
BIN
doc/sponsors/warp-pack-header.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
@@ -1,11 +0,0 @@
|
|||||||
<svg width="1354" height="420" viewBox="0 0 1354 420" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="1354" height="420" rx="20" fill="white"/>
|
|
||||||
<path d="M434.751 133.122H466.637L489.595 227.729C493.852 245.585 494.697 256.219 494.697 256.219H495.128C495.128 256.219 496.61 245.808 500.867 227.729L522.757 133.122H558.9L582.066 227.729C586.53 246.223 587.598 256.219 587.598 256.219H588.236C588.236 256.219 588.666 246.223 592.907 227.729L615.02 133.122H646.907L606.523 288.313H571.017L546.576 194.344C541.474 173.936 541.044 164.801 541.044 164.801H540.614C540.614 164.801 540.183 173.936 535.512 194.344L512.553 288.313H475.996L434.751 133.122Z" fill="black"/>
|
|
||||||
<path d="M641.583 231.934C641.583 196.428 664.541 173.47 699.202 173.47C733.639 173.47 756.597 196.428 756.597 231.934C756.597 267.647 733.639 290.828 699.202 290.828C664.557 290.812 641.583 267.647 641.583 231.934ZM726.832 231.934C726.832 208.976 715.783 195.998 699.202 195.998C681.346 195.998 671.349 210.458 671.349 231.934C671.349 255.323 682.398 268.284 699.202 268.284C717.058 268.284 726.832 253.824 726.832 231.934Z" fill="black"/>
|
|
||||||
<path d="M770.836 175.21H799.103V196.048H799.741C804.635 185.207 816.322 174.365 836.299 174.365C839.695 174.365 841.831 174.796 843.314 175.21V203.478H842.469C842.469 203.478 839.918 202.633 832.903 202.633C811.013 202.633 799.103 215.594 799.103 239.828V288.295H770.836V175.21Z" fill="black"/>
|
|
||||||
<path d="M856.5 133.122H884.767V182.865C884.767 212.2 884.336 217.509 884.336 217.509H884.767L926.857 175.212H962.139L912.843 224.11L970.031 288.313H936.646L895.401 241.536L884.767 251.946V288.297H856.5V133.122Z" fill="black"/>
|
|
||||||
<path d="M970.444 211.285C970.444 163.455 1000.21 131.569 1044.85 131.569C1089.49 131.569 1119.26 163.455 1119.26 211.285C1119.26 259.114 1089.49 291.001 1044.85 291.001C1000.21 291.001 970.444 259.114 970.444 211.285ZM1088.42 211.285C1088.42 178.761 1071 156.855 1044.84 156.855C1018.67 156.855 1001.26 178.761 1001.26 211.285C1001.26 243.809 1018.69 265.715 1044.84 265.715C1070.98 265.715 1088.42 243.809 1088.42 211.285Z" fill="black"/>
|
|
||||||
<path d="M1130.08 236.656H1162.4C1162.4 254.943 1174.95 265.146 1194.08 265.146C1210.23 265.146 1221.29 257.063 1221.29 245.584C1221.29 232.622 1212.79 229.21 1185.79 223.901C1161.12 219.007 1134.98 210.716 1134.98 178.399C1134.98 151.408 1157.93 131 1193.01 131C1229.57 131 1252.11 150.132 1252.11 179.037H1219.79C1219.79 165.007 1208.95 156.286 1193.01 156.286C1176.86 156.286 1166.86 164.146 1166.86 175.625C1166.86 187.742 1173.88 192.413 1195.56 196.878C1227.65 203.685 1254.02 207.288 1254.02 243.001C1254.02 271.3 1229.36 290.432 1193.01 290.432C1156.02 290.432 1130.08 268.957 1130.08 236.656Z" fill="black"/>
|
|
||||||
<path d="M100 210C100 214.824 101.269 219.647 103.723 223.793L148.231 300.878C152.8 308.747 159.739 315.178 168.369 318.055C185.377 323.724 202.977 316.447 211.354 301.893L222.1 283.278L179.708 210L224.47 132.408L235.216 113.792C238.431 108.208 242.747 103.638 247.824 100H243.17H178.777C166.677 100 155.508 106.431 149.5 116.923L103.723 196.208C101.269 200.354 100 205.177 100 210Z" fill="#6363F1"/>
|
|
||||||
<path d="M353.847 210C353.847 205.177 352.578 200.353 350.124 196.207L305.024 118.107C296.647 103.638 279.047 96.3608 262.039 101.945C253.409 104.822 246.47 111.253 241.901 119.122L231.747 136.638L274.139 210L229.378 287.592L218.632 306.208C215.416 311.708 211.101 316.362 206.024 320H210.678H275.07C287.17 320 298.34 313.569 304.347 303.077L350.124 223.792C352.578 219.646 353.847 214.823 353.847 210Z" fill="#6363F1"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1,4 +1,6 @@
|
|||||||
use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input};
|
use bat::{
|
||||||
|
assets::HighlightingAssets, config::Config, controller::Controller, output::OutputHandle, Input,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
@@ -10,7 +12,10 @@ fn main() {
|
|||||||
let controller = Controller::new(&config, &assets);
|
let controller = Controller::new(&config, &assets);
|
||||||
let input = Input::from_file(file!());
|
let input = Input::from_file(file!());
|
||||||
controller
|
controller
|
||||||
.run(vec![input.into()], Some(&mut buffer))
|
.run(
|
||||||
|
vec![input.into()],
|
||||||
|
Some(OutputHandle::FmtWrite(&mut buffer)),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
println!("{buffer}");
|
println!("{buffer}");
|
||||||
|
@@ -152,7 +152,7 @@ impl HighlightingAssets {
|
|||||||
&self,
|
&self,
|
||||||
path: impl AsRef<Path>,
|
path: impl AsRef<Path>,
|
||||||
mapping: &SyntaxMapping,
|
mapping: &SyntaxMapping,
|
||||||
) -> Result<SyntaxReferenceInSet> {
|
) -> Result<SyntaxReferenceInSet<'_>> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
|
||||||
let syntax_match = mapping.get_syntax_for(path);
|
let syntax_match = mapping.get_syntax_for(path);
|
||||||
@@ -163,7 +163,7 @@ impl HighlightingAssets {
|
|||||||
|
|
||||||
if let Some(MappingTarget::MapTo(syntax_name)) = syntax_match {
|
if let Some(MappingTarget::MapTo(syntax_name)) = syntax_match {
|
||||||
return self
|
return self
|
||||||
.find_syntax_by_name(syntax_name)?
|
.find_syntax_by_token(syntax_name)?
|
||||||
.ok_or_else(|| Error::UnknownSyntax(syntax_name.to_owned()));
|
.ok_or_else(|| Error::UnknownSyntax(syntax_name.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,11 +191,11 @@ impl HighlightingAssets {
|
|||||||
Some(theme) => theme,
|
Some(theme) => theme,
|
||||||
None => {
|
None => {
|
||||||
if theme == "ansi-light" || theme == "ansi-dark" {
|
if theme == "ansi-light" || theme == "ansi-dark" {
|
||||||
bat_warning!("Theme '{}' is deprecated, using 'ansi' instead.", theme);
|
bat_warning!("Theme '{theme}' is deprecated, using 'ansi' instead.");
|
||||||
return self.get_theme("ansi");
|
return self.get_theme("ansi");
|
||||||
}
|
}
|
||||||
if !theme.is_empty() {
|
if !theme.is_empty() {
|
||||||
bat_warning!("Unknown theme '{}', using default.", theme)
|
bat_warning!("Unknown theme '{theme}', using default.")
|
||||||
}
|
}
|
||||||
self.get_theme_set()
|
self.get_theme_set()
|
||||||
.get(
|
.get(
|
||||||
@@ -212,7 +212,7 @@ impl HighlightingAssets {
|
|||||||
language: Option<&str>,
|
language: Option<&str>,
|
||||||
input: &mut OpenedInput,
|
input: &mut OpenedInput,
|
||||||
mapping: &SyntaxMapping,
|
mapping: &SyntaxMapping,
|
||||||
) -> Result<SyntaxReferenceInSet> {
|
) -> Result<SyntaxReferenceInSet<'_>> {
|
||||||
if let Some(language) = language {
|
if let Some(language) = language {
|
||||||
let syntax_set = self.get_syntax_set()?;
|
let syntax_set = self.get_syntax_set()?;
|
||||||
return syntax_set
|
return syntax_set
|
||||||
@@ -244,14 +244,17 @@ impl HighlightingAssets {
|
|||||||
pub(crate) fn find_syntax_by_name(
|
pub(crate) fn find_syntax_by_name(
|
||||||
&self,
|
&self,
|
||||||
syntax_name: &str,
|
syntax_name: &str,
|
||||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
let syntax_set = self.get_syntax_set()?;
|
let syntax_set = self.get_syntax_set()?;
|
||||||
Ok(syntax_set
|
Ok(syntax_set
|
||||||
.find_syntax_by_name(syntax_name)
|
.find_syntax_by_name(syntax_name)
|
||||||
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_syntax_by_extension(&self, e: Option<&OsStr>) -> Result<Option<SyntaxReferenceInSet>> {
|
fn find_syntax_by_extension(
|
||||||
|
&self,
|
||||||
|
e: Option<&OsStr>,
|
||||||
|
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
let syntax_set = self.get_syntax_set()?;
|
let syntax_set = self.get_syntax_set()?;
|
||||||
let extension = e.and_then(|x| x.to_str()).unwrap_or_default();
|
let extension = e.and_then(|x| x.to_str()).unwrap_or_default();
|
||||||
Ok(syntax_set
|
Ok(syntax_set
|
||||||
@@ -259,11 +262,18 @@ impl HighlightingAssets {
|
|||||||
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_syntax_by_token(&self, token: &str) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
|
let syntax_set = self.get_syntax_set()?;
|
||||||
|
Ok(syntax_set
|
||||||
|
.find_syntax_by_token(token)
|
||||||
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_syntax_for_file_name(
|
fn get_syntax_for_file_name(
|
||||||
&self,
|
&self,
|
||||||
file_name: &OsStr,
|
file_name: &OsStr,
|
||||||
ignored_suffixes: &IgnoredSuffixes,
|
ignored_suffixes: &IgnoredSuffixes,
|
||||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
let mut syntax = self.find_syntax_by_extension(Some(file_name))?;
|
let mut syntax = self.find_syntax_by_extension(Some(file_name))?;
|
||||||
if syntax.is_none() {
|
if syntax.is_none() {
|
||||||
syntax =
|
syntax =
|
||||||
@@ -279,7 +289,7 @@ impl HighlightingAssets {
|
|||||||
&self,
|
&self,
|
||||||
file_name: &OsStr,
|
file_name: &OsStr,
|
||||||
ignored_suffixes: &IgnoredSuffixes,
|
ignored_suffixes: &IgnoredSuffixes,
|
||||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
let mut syntax = self.find_syntax_by_extension(Path::new(file_name).extension())?;
|
let mut syntax = self.find_syntax_by_extension(Path::new(file_name).extension())?;
|
||||||
if syntax.is_none() {
|
if syntax.is_none() {
|
||||||
syntax =
|
syntax =
|
||||||
@@ -294,11 +304,15 @@ impl HighlightingAssets {
|
|||||||
fn get_first_line_syntax(
|
fn get_first_line_syntax(
|
||||||
&self,
|
&self,
|
||||||
reader: &mut InputReader,
|
reader: &mut InputReader,
|
||||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||||
let syntax_set = self.get_syntax_set()?;
|
let syntax_set = self.get_syntax_set()?;
|
||||||
Ok(String::from_utf8(reader.first_line.clone())
|
Ok(String::from_utf8(reader.first_line.clone())
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|l| syntax_set.find_syntax_by_first_line(&l))
|
.and_then(|l| {
|
||||||
|
// Strip UTF-8 BOM if present
|
||||||
|
let line = l.strip_prefix('\u{feff}').unwrap_or(&l);
|
||||||
|
syntax_set.find_syntax_by_first_line(line)
|
||||||
|
})
|
||||||
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,8 +357,7 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
|
|||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
let contents = fs::read(path).map_err(|_| {
|
let contents = fs::read(path).map_err(|_| {
|
||||||
format!(
|
format!(
|
||||||
"Could not load cached {} '{}'",
|
"Could not load cached {description} '{}'",
|
||||||
description,
|
|
||||||
path.to_string_lossy()
|
path.to_string_lossy()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@@ -370,7 +383,7 @@ mod tests {
|
|||||||
pub temp_dir: TempDir,
|
pub temp_dir: TempDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SyntaxDetectionTest<'a> {
|
impl SyntaxDetectionTest<'_> {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
SyntaxDetectionTest {
|
SyntaxDetectionTest {
|
||||||
assets: HighlightingAssets::from_binary(),
|
assets: HighlightingAssets::from_binary(),
|
||||||
@@ -533,6 +546,41 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn syntax_detection_first_line_with_utf8_bom() {
|
||||||
|
let test = SyntaxDetectionTest::new();
|
||||||
|
|
||||||
|
// Test that XML files are detected correctly even with UTF-8 BOM
|
||||||
|
// The BOM should be stripped before first-line syntax detection
|
||||||
|
let xml_with_bom = "\u{feff}<?xml version=\"1.0\" encoding=\"utf-8\"?>";
|
||||||
|
assert_eq!(
|
||||||
|
test.syntax_for_file_with_content("unknown_file", xml_with_bom),
|
||||||
|
"XML"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test the specific .csproj case mentioned in the issue
|
||||||
|
// Even if .csproj has extension mapping, this tests first-line fallback
|
||||||
|
let csproj_content_with_bom = "\u{feff}<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">";
|
||||||
|
assert_eq!(
|
||||||
|
test.syntax_for_file_with_content("test.csproj", csproj_content_with_bom),
|
||||||
|
"XML"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test that shell scripts are detected correctly even with UTF-8 BOM
|
||||||
|
let script_with_bom = "\u{feff}#!/bin/bash";
|
||||||
|
assert_eq!(
|
||||||
|
test.syntax_for_file_with_content("unknown_script", script_with_bom),
|
||||||
|
"Bourne Again Shell (bash)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test that PHP files are detected correctly even with UTF-8 BOM
|
||||||
|
let php_with_bom = "\u{feff}<?php";
|
||||||
|
assert_eq!(
|
||||||
|
test.syntax_for_file_with_content("unknown_php", php_with_bom),
|
||||||
|
"PHP"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn syntax_detection_with_custom_mapping() {
|
fn syntax_detection_with_custom_mapping() {
|
||||||
let mut test = SyntaxDetectionTest::new();
|
let mut test = SyntaxDetectionTest::new();
|
||||||
|
@@ -40,15 +40,15 @@ impl AssetsMetadata {
|
|||||||
/// Load metadata about the stored cache file from the given folder.
|
/// Load metadata about the stored cache file from the given folder.
|
||||||
///
|
///
|
||||||
/// There are several possibilities:
|
/// There are several possibilities:
|
||||||
/// - We find a metadata.yaml file and are able to parse it
|
/// - We find a `metadata.yaml` file and are able to parse it
|
||||||
/// => return the contained information
|
/// - return the contained information
|
||||||
/// - We find a metadata.yaml file and but are not able to parse it
|
/// - We find a `metadata.yaml` file, but are not able to parse it
|
||||||
/// => return a SerdeYamlError
|
/// - return a [`Error::SerdeYamlError`]
|
||||||
/// - We do not find a metadata.yaml file but a syntaxes.bin or themes.bin file
|
/// - We do not find a `metadata.yaml` file but a `syntaxes.bin` or `themes.bin` file
|
||||||
/// => assume that these were created by an old version of bat and return
|
/// - assume that these were created by an old version of bat and return
|
||||||
/// AssetsMetadata::default() without version information
|
/// [`AssetsMetadata::default()`] without version information
|
||||||
/// - We do not find a metadata.yaml file and no cached assets
|
/// - We do not find a `metadata.yaml` file and no cached assets
|
||||||
/// => no user provided assets are available, return None
|
/// - no user provided assets are available, return `None`
|
||||||
pub fn load_from_folder(path: &Path) -> Result<Option<Self>> {
|
pub fn load_from_folder(path: &Path) -> Result<Option<Self>> {
|
||||||
match Self::try_load_from_folder(path) {
|
match Self::try_load_from_folder(path) {
|
||||||
Ok(metadata) => Ok(Some(metadata)),
|
Ok(metadata) => Ok(Some(metadata)),
|
||||||
|
@@ -47,9 +47,8 @@ fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> Result
|
|||||||
let res = theme_set.add_from_folder(&theme_dir);
|
let res = theme_set.add_from_folder(&theme_dir);
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
println!(
|
println!(
|
||||||
"Failed to load one or more themes from '{}' (reason: '{}')",
|
"Failed to load one or more themes from '{}' (reason: '{err}')",
|
||||||
theme_dir.to_string_lossy(),
|
theme_dir.to_string_lossy(),
|
||||||
err,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -162,15 +161,10 @@ fn asset_to_cache<T: serde::Serialize>(
|
|||||||
description: &str,
|
description: &str,
|
||||||
compressed: bool,
|
compressed: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
print!("Writing {} to {} ... ", description, path.to_string_lossy());
|
print!("Writing {description} to {} ... ", path.to_string_lossy());
|
||||||
let contents = asset_to_contents(asset, description, compressed)?;
|
let contents = asset_to_contents(asset, description, compressed)?;
|
||||||
std::fs::write(path, &contents[..]).map_err(|_| {
|
std::fs::write(path, &contents[..])
|
||||||
format!(
|
.map_err(|_| format!("Could not save {description} to {}", path.to_string_lossy()))?;
|
||||||
"Could not save {} to {}",
|
|
||||||
description,
|
|
||||||
path.to_string_lossy()
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
println!("okay");
|
println!("okay");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,7 @@ fn to_path_and_stem(source_dir: &Path, entry: DirEntry) -> Option<PathAndStem> {
|
|||||||
fn handle_file(path_and_stem: &PathAndStem) -> Result<Option<String>> {
|
fn handle_file(path_and_stem: &PathAndStem) -> Result<Option<String>> {
|
||||||
if path_and_stem.stem == "NOTICE" {
|
if path_and_stem.stem == "NOTICE" {
|
||||||
handle_notice(&path_and_stem.path)
|
handle_notice(&path_and_stem.path)
|
||||||
} else if path_and_stem.stem.to_ascii_uppercase() == "LICENSE" {
|
} else if path_and_stem.stem.eq_ignore_ascii_case("LICENSE") {
|
||||||
handle_license(&path_and_stem.path)
|
handle_license(&path_and_stem.path)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -95,6 +95,9 @@ fn include_license_in_acknowledgments(license_text: &str) -> bool {
|
|||||||
// Apache 2.0
|
// Apache 2.0
|
||||||
"Apache License Version 2.0, January 2004 http://www.apache.org/licenses/",
|
"Apache License Version 2.0, January 2004 http://www.apache.org/licenses/",
|
||||||
"Licensed under the Apache License, Version 2.0 (the \"License\");",
|
"Licensed under the Apache License, Version 2.0 (the \"License\");",
|
||||||
|
|
||||||
|
// CC BY 4.0
|
||||||
|
"Creative Commons Attribution 4.0 International Public License",
|
||||||
];
|
];
|
||||||
|
|
||||||
license_contains_marker(license_text, &markers)
|
license_contains_marker(license_text, &markers)
|
||||||
|
@@ -3,6 +3,7 @@ use std::env;
|
|||||||
use std::io::IsTerminal;
|
use std::io::IsTerminal;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::thread::available_parallelism;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clap_app,
|
clap_app,
|
||||||
@@ -95,7 +96,7 @@ impl App {
|
|||||||
Ok(clap_app::build_app(interactive_output).get_matches_from(args))
|
Ok(clap_app::build_app(interactive_output).get_matches_from(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(&self, inputs: &[Input]) -> Result<Config> {
|
pub fn config(&self, inputs: &[Input]) -> Result<Config<'_>> {
|
||||||
let style_components = self.style_components()?;
|
let style_components = self.style_components()?;
|
||||||
|
|
||||||
let extra_plain = self.matches.get_count("plain") > 1;
|
let extra_plain = self.matches.get_count("plain") > 1;
|
||||||
@@ -124,7 +125,10 @@ impl App {
|
|||||||
// If we have -pp as an option when in auto mode, the pager should be disabled.
|
// If we have -pp as an option when in auto mode, the pager should be disabled.
|
||||||
if extra_plain || self.matches.get_flag("no-paging") {
|
if extra_plain || self.matches.get_flag("no-paging") {
|
||||||
PagingMode::Never
|
PagingMode::Never
|
||||||
} else if inputs.iter().any(Input::is_stdin) {
|
} else if inputs.iter().any(Input::is_stdin)
|
||||||
|
// ignore stdin when --list-themes is used because in that case no input will be read anyways
|
||||||
|
&& !self.matches.get_flag("list-themes")
|
||||||
|
{
|
||||||
// If we are reading from stdin, only enable paging if we write to an
|
// If we are reading from stdin, only enable paging if we write to an
|
||||||
// interactive terminal and if we do not *read* from an interactive
|
// interactive terminal and if we do not *read* from an interactive
|
||||||
// terminal.
|
// terminal.
|
||||||
@@ -146,7 +150,9 @@ impl App {
|
|||||||
// start building glob matchers for builtin mappings immediately
|
// start building glob matchers for builtin mappings immediately
|
||||||
// this is an appropriate approach because it's statistically likely that
|
// this is an appropriate approach because it's statistically likely that
|
||||||
// all the custom mappings need to be checked
|
// all the custom mappings need to be checked
|
||||||
syntax_mapping.start_offload_build_all();
|
if available_parallelism()?.get() > 1 {
|
||||||
|
syntax_mapping.start_offload_build_all();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(values) = self.matches.get_many::<String>("ignored-suffix") {
|
if let Some(values) = self.matches.get_many::<String>("ignored-suffix") {
|
||||||
for suffix in values {
|
for suffix in values {
|
||||||
@@ -332,7 +338,7 @@ impl App {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inputs(&self) -> Result<Vec<Input>> {
|
pub fn inputs(&self) -> Result<Vec<Input<'_>>> {
|
||||||
let filenames: Option<Vec<&Path>> = self
|
let filenames: Option<Vec<&Path>> = self
|
||||||
.matches
|
.matches
|
||||||
.get_many::<PathBuf>("file-name")
|
.get_many::<PathBuf>("file-name")
|
||||||
@@ -425,7 +431,7 @@ impl App {
|
|||||||
None => StyleComponents(HashSet::from_iter(
|
None => StyleComponents(HashSet::from_iter(
|
||||||
StyleComponent::Default
|
StyleComponent::Default
|
||||||
.components(self.interactive_output)
|
.components(self.interactive_output)
|
||||||
.into_iter()
|
.iter()
|
||||||
.cloned(),
|
.cloned(),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
@@ -50,7 +50,7 @@ fn clear_asset(path: PathBuf, description: &str) {
|
|||||||
println!("skipped (not present)");
|
println!("skipped (not present)");
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("could not remove the cache file {:?}: {}", &path, err);
|
println!("could not remove the cache file {path:?}: {err}");
|
||||||
}
|
}
|
||||||
Ok(_) => println!("okay"),
|
Ok(_) => println!("okay"),
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ static VERSION: Lazy<String> = Lazy::new(|| {
|
|||||||
if git_version.is_empty() {
|
if git_version.is_empty() {
|
||||||
crate_version!().to_string()
|
crate_version!().to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{} ({})", crate_version!(), git_version)
|
format!("{} ({git_version})", crate_version!())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -525,7 +525,9 @@ pub fn build_app(interactive_output: bool) -> Command {
|
|||||||
'--line-range :40' prints lines 1 to 40\n \
|
'--line-range :40' prints lines 1 to 40\n \
|
||||||
'--line-range 40:' prints lines 40 to the end of the file\n \
|
'--line-range 40:' prints lines 40 to the end of the file\n \
|
||||||
'--line-range 40' only prints line 40\n \
|
'--line-range 40' only prints line 40\n \
|
||||||
'--line-range 30:+10' prints lines 30 to 40",
|
'--line-range 30:+10' prints lines 30 to 40\n \
|
||||||
|
'--line-range 35::5' prints lines 30 to 40 (line 35 with 5 lines of context)\n \
|
||||||
|
'--line-range 30:40:2' prints lines 28 to 42 (range 30-40 with 2 lines of context)",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@@ -88,9 +88,8 @@ pub fn generate_config_file() -> bat::error::Result<()> {
|
|||||||
|
|
||||||
fs::write(&config_file, default_config).map_err(|e| {
|
fs::write(&config_file, default_config).map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"Failed to create config file at '{}': {}",
|
"Failed to create config file at '{}': {e}",
|
||||||
config_file.to_string_lossy(),
|
config_file.to_string_lossy(),
|
||||||
e
|
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ pub fn new_file_input<'a>(file: &'a Path, name: Option<&'a Path>) -> Input<'a> {
|
|||||||
named(Input::ordinary_file(file), name.or(Some(file)))
|
named(Input::ordinary_file(file), name.or(Some(file)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_stdin_input(name: Option<&Path>) -> Input {
|
pub fn new_stdin_input(name: Option<&Path>) -> Input<'_> {
|
||||||
named(Input::stdin(), name)
|
named(Input::stdin(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@ use std::io::{BufReader, Write};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
use bat::output::{OutputHandle, OutputType};
|
||||||
use bat::theme::DetectColorScheme;
|
use bat::theme::DetectColorScheme;
|
||||||
use nu_ansi_term::Color::Green;
|
use nu_ansi_term::Color::Green;
|
||||||
use nu_ansi_term::Style;
|
use nu_ansi_term::Style;
|
||||||
@@ -161,7 +162,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for lang in languages {
|
for lang in languages {
|
||||||
write!(result, "{:width$}{}", lang.name, separator, width = longest).ok();
|
write!(result, "{:width$}{separator}", lang.name, width = longest).ok();
|
||||||
|
|
||||||
// Number of characters on this line so far, wrap before `desired_width`
|
// Number of characters on this line so far, wrap before `desired_width`
|
||||||
let mut num_chars = 0;
|
let mut num_chars = 0;
|
||||||
@@ -172,7 +173,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
|||||||
let new_chars = word.len() + comma_separator.len();
|
let new_chars = word.len() + comma_separator.len();
|
||||||
if num_chars + new_chars >= desired_width {
|
if num_chars + new_chars >= desired_width {
|
||||||
num_chars = 0;
|
num_chars = 0;
|
||||||
write!(result, "\n{:width$}{}", "", separator, width = longest).ok();
|
write!(result, "\n{:width$}{separator}", "", width = longest).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
num_chars += new_chars;
|
num_chars += new_chars;
|
||||||
@@ -205,12 +206,13 @@ pub fn list_themes(
|
|||||||
config.language = Some("Rust");
|
config.language = Some("Rust");
|
||||||
config.style_components = StyleComponents(style);
|
config.style_components = StyleComponents(style);
|
||||||
|
|
||||||
let stdout = io::stdout();
|
let mut output_type =
|
||||||
let mut stdout = stdout.lock();
|
OutputType::from_mode(config.paging_mode, config.wrapping_mode, config.pager)?;
|
||||||
|
let mut writer = output_type.handle()?;
|
||||||
|
|
||||||
let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
|
let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
|
||||||
for theme in assets.themes() {
|
for theme in assets.themes() {
|
||||||
let default_theme_info = if !config.loop_through && default_theme_name == theme {
|
let default_theme_info = if default_theme_name == theme {
|
||||||
" (default)"
|
" (default)"
|
||||||
} else if default_theme(ColorScheme::Dark) == theme {
|
} else if default_theme(ColorScheme::Dark) == theme {
|
||||||
" (default dark)"
|
" (default dark)"
|
||||||
@@ -221,24 +223,28 @@ pub fn list_themes(
|
|||||||
};
|
};
|
||||||
if config.colored_output {
|
if config.colored_output {
|
||||||
writeln!(
|
writeln!(
|
||||||
stdout,
|
writer,
|
||||||
"Theme: {}{}\n",
|
"Theme: {}{default_theme_info}\n",
|
||||||
Style::new().bold().paint(theme.to_string()),
|
Style::new().bold().paint(theme.to_string()),
|
||||||
default_theme_info
|
|
||||||
)?;
|
)?;
|
||||||
config.theme = theme.to_string();
|
config.theme = theme.to_string();
|
||||||
Controller::new(&config, &assets)
|
Controller::new(&config, &assets)
|
||||||
.run(vec![theme_preview_file()], None)
|
.run(
|
||||||
|
vec![theme_preview_file()],
|
||||||
|
Some(OutputHandle::IoWrite(&mut writer)),
|
||||||
|
)
|
||||||
.ok();
|
.ok();
|
||||||
writeln!(stdout)?;
|
writeln!(writer)?;
|
||||||
|
} else if config.loop_through {
|
||||||
|
writeln!(writer, "{theme}")?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(stdout, "{theme}{default_theme_info}")?;
|
writeln!(writer, "{theme}{default_theme_info}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.colored_output {
|
if config.colored_output {
|
||||||
writeln!(
|
writeln!(
|
||||||
stdout,
|
writer,
|
||||||
"Further themes can be installed to '{}', \
|
"Further themes can be installed to '{}', \
|
||||||
and are added to the cache with `bat cache --build`. \
|
and are added to the cache with `bat cache --build`. \
|
||||||
For more information, see:\n\n \
|
For more information, see:\n\n \
|
||||||
@@ -356,7 +362,7 @@ fn run() -> Result<bool> {
|
|||||||
"fish" => println!("{}", completions::FISH_COMPLETION),
|
"fish" => println!("{}", completions::FISH_COMPLETION),
|
||||||
"ps1" => println!("{}", completions::PS1_COMPLETION),
|
"ps1" => println!("{}", completions::PS1_COMPLETION),
|
||||||
"zsh" => println!("{}", completions::ZSH_COMPLETION),
|
"zsh" => println!("{}", completions::ZSH_COMPLETION),
|
||||||
_ => unreachable!("No completion for shell '{}' available.", shell),
|
_ => unreachable!("No completion for shell '{shell}' available."),
|
||||||
}
|
}
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
@@ -119,17 +119,25 @@ pub fn get_pager_executable(config_pager: Option<&str>) -> Option<String> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_config_should_include_all_lines() {
|
fn default_config_should_include_all_lines() {
|
||||||
|
use crate::line_range::MaxBufferedLineNumber;
|
||||||
use crate::line_range::RangeCheckResult;
|
use crate::line_range::RangeCheckResult;
|
||||||
|
|
||||||
assert_eq!(LineRanges::default().check(17), RangeCheckResult::InRange);
|
assert_eq!(
|
||||||
|
LineRanges::default().check(17, MaxBufferedLineNumber::Tentative(17)),
|
||||||
|
RangeCheckResult::InRange
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_config_should_highlight_no_lines() {
|
fn default_config_should_highlight_no_lines() {
|
||||||
|
use crate::line_range::MaxBufferedLineNumber;
|
||||||
use crate::line_range::RangeCheckResult;
|
use crate::line_range::RangeCheckResult;
|
||||||
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
Config::default().highlighted_lines.0.check(17),
|
Config::default()
|
||||||
|
.highlighted_lines
|
||||||
|
.0
|
||||||
|
.check(17, MaxBufferedLineNumber::Tentative(17)),
|
||||||
RangeCheckResult::InRange
|
RangeCheckResult::InRange
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
use std::io::{self, BufRead, Write};
|
|
||||||
|
|
||||||
use crate::assets::HighlightingAssets;
|
use crate::assets::HighlightingAssets;
|
||||||
use crate::config::{Config, VisibleLines};
|
use crate::config::{Config, VisibleLines};
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
@@ -10,11 +8,14 @@ use crate::input::{Input, InputReader, OpenedInput};
|
|||||||
use crate::lessopen::LessOpenPreprocessor;
|
use crate::lessopen::LessOpenPreprocessor;
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
use crate::line_range::LineRange;
|
use crate::line_range::LineRange;
|
||||||
use crate::line_range::{LineRanges, RangeCheckResult};
|
use crate::line_range::{LineRanges, MaxBufferedLineNumber, RangeCheckResult};
|
||||||
use crate::output::OutputType;
|
use crate::output::{OutputHandle, OutputType};
|
||||||
#[cfg(feature = "paging")]
|
#[cfg(feature = "paging")]
|
||||||
use crate::paging::PagingMode;
|
use crate::paging::PagingMode;
|
||||||
use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter};
|
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::io::{self, BufRead, Write};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use clircle::{Clircle, Identifier};
|
use clircle::{Clircle, Identifier};
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ pub struct Controller<'a> {
|
|||||||
preprocessor: Option<LessOpenPreprocessor>,
|
preprocessor: Option<LessOpenPreprocessor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> Controller<'b> {
|
impl Controller<'_> {
|
||||||
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
|
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
|
||||||
Controller {
|
Controller {
|
||||||
config,
|
config,
|
||||||
@@ -35,18 +36,14 @@ impl<'b> Controller<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(&self, inputs: Vec<Input>, output_handle: Option<OutputHandle<'_>>) -> Result<bool> {
|
||||||
&self,
|
self.run_with_error_handler(inputs, output_handle, default_error_handler)
|
||||||
inputs: Vec<Input>,
|
|
||||||
output_buffer: Option<&mut dyn std::fmt::Write>,
|
|
||||||
) -> Result<bool> {
|
|
||||||
self.run_with_error_handler(inputs, output_buffer, default_error_handler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_with_error_handler(
|
pub fn run_with_error_handler(
|
||||||
&self,
|
&self,
|
||||||
inputs: Vec<Input>,
|
inputs: Vec<Input>,
|
||||||
output_buffer: Option<&mut dyn std::fmt::Write>,
|
output_handle: Option<OutputHandle<'_>>,
|
||||||
mut handle_error: impl FnMut(&Error, &mut dyn Write),
|
mut handle_error: impl FnMut(&Error, &mut dyn Write),
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let mut output_type;
|
let mut output_type;
|
||||||
@@ -88,8 +85,9 @@ impl<'b> Controller<'b> {
|
|||||||
clircle::Identifier::stdout()
|
clircle::Identifier::stdout()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut writer = match output_buffer {
|
let mut writer = match output_handle {
|
||||||
Some(buf) => OutputHandle::FmtWrite(buf),
|
Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w),
|
||||||
|
Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w),
|
||||||
None => OutputHandle::IoWrite(output_type.handle()?),
|
None => OutputHandle::IoWrite(output_type.handle()?),
|
||||||
};
|
};
|
||||||
let mut no_errors: bool = true;
|
let mut no_errors: bool = true;
|
||||||
@@ -241,20 +239,63 @@ impl<'b> Controller<'b> {
|
|||||||
reader: &mut InputReader,
|
reader: &mut InputReader,
|
||||||
line_ranges: &LineRanges,
|
line_ranges: &LineRanges,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut line_buffer = Vec::new();
|
let mut current_line_buffer: Vec<u8> = Vec::new();
|
||||||
let mut line_number: usize = 1;
|
let mut current_line_number: usize = 1;
|
||||||
|
// Buffer needs to be 1 greater than the offset to have a look-ahead line for EOF
|
||||||
|
let buffer_size: usize = line_ranges.largest_offset_from_end() + 1;
|
||||||
|
// Buffers multiple line data and line number
|
||||||
|
let mut buffered_lines: VecDeque<(Vec<u8>, usize)> = VecDeque::with_capacity(buffer_size);
|
||||||
|
|
||||||
|
let mut reached_eof: bool = false;
|
||||||
let mut first_range: bool = true;
|
let mut first_range: bool = true;
|
||||||
let mut mid_range: bool = false;
|
let mut mid_range: bool = false;
|
||||||
|
|
||||||
let style_snip = self.config.style_components.snip();
|
let style_snip = self.config.style_components.snip();
|
||||||
|
|
||||||
while reader.read_line(&mut line_buffer)? {
|
loop {
|
||||||
match line_ranges.check(line_number) {
|
if reached_eof && buffered_lines.is_empty() {
|
||||||
|
// Done processing all lines
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if !reached_eof {
|
||||||
|
if reader.read_line(&mut current_line_buffer)? {
|
||||||
|
// Fill the buffer
|
||||||
|
buffered_lines
|
||||||
|
.push_back((mem::take(&mut current_line_buffer), current_line_number));
|
||||||
|
current_line_number += 1;
|
||||||
|
} else {
|
||||||
|
// No more data to read
|
||||||
|
reached_eof = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffered_lines.len() < buffer_size && !reached_eof {
|
||||||
|
// The buffer needs to be completely filled first
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some((line, line_nr)) = buffered_lines.pop_front() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if the last line number in the buffer is the last line of the file or
|
||||||
|
// just a line somewhere in the file
|
||||||
|
let max_buffered_line_number = buffered_lines
|
||||||
|
.back()
|
||||||
|
.map(|(_, max_line_number)| {
|
||||||
|
if reached_eof {
|
||||||
|
MaxBufferedLineNumber::Final(*max_line_number)
|
||||||
|
} else {
|
||||||
|
MaxBufferedLineNumber::Tentative(*max_line_number)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(MaxBufferedLineNumber::Final(line_nr));
|
||||||
|
|
||||||
|
match line_ranges.check(line_nr, max_buffered_line_number) {
|
||||||
RangeCheckResult::BeforeOrBetweenRanges => {
|
RangeCheckResult::BeforeOrBetweenRanges => {
|
||||||
// Call the printer in case we need to call the syntax highlighter
|
// Call the printer in case we need to call the syntax highlighter
|
||||||
// for this line. However, set `out_of_range` to `true`.
|
// for this line. However, set `out_of_range` to `true`.
|
||||||
printer.print_line(true, writer, line_number, &line_buffer)?;
|
printer.print_line(true, writer, line_nr, &line, max_buffered_line_number)?;
|
||||||
mid_range = false;
|
mid_range = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,15 +310,12 @@ impl<'b> Controller<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printer.print_line(false, writer, line_number, &line_buffer)?;
|
printer.print_line(false, writer, line_nr, &line, max_buffered_line_number)?;
|
||||||
}
|
}
|
||||||
RangeCheckResult::AfterLastRange => {
|
RangeCheckResult::AfterLastRange => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line_number += 1;
|
|
||||||
line_buffer.clear();
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
10
src/error.rs
10
src/error.rs
@@ -60,14 +60,18 @@ pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
|||||||
Error::SerdeYamlError(_) => {
|
Error::SerdeYamlError(_) => {
|
||||||
writeln!(
|
writeln!(
|
||||||
output,
|
output,
|
||||||
"{}: Error while parsing metadata.yaml file: {}",
|
"{}: Error while parsing metadata.yaml file: {error}",
|
||||||
Red.paint("[bat error]"),
|
Red.paint("[bat error]"),
|
||||||
error
|
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
writeln!(output, "{}: {}", Red.paint("[bat error]"), error).ok();
|
writeln!(
|
||||||
|
&mut std::io::stderr().lock(),
|
||||||
|
"{}: {error}",
|
||||||
|
Red.paint("[bat error]"),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
94
src/input.rs
94
src/input.rs
@@ -75,7 +75,7 @@ pub(crate) enum InputKind<'a> {
|
|||||||
CustomReader(Box<dyn Read + 'a>),
|
CustomReader(Box<dyn Read + 'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InputKind<'a> {
|
impl InputKind<'_> {
|
||||||
pub fn description(&self) -> InputDescription {
|
pub fn description(&self) -> InputDescription {
|
||||||
match self {
|
match self {
|
||||||
InputKind::OrdinaryFile(ref path) => InputDescription::new(path.to_string_lossy()),
|
InputKind::OrdinaryFile(ref path) => InputDescription::new(path.to_string_lossy()),
|
||||||
@@ -217,14 +217,14 @@ impl<'a> Input<'a> {
|
|||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
reader: {
|
reader: {
|
||||||
let mut file = File::open(&path)
|
let mut file = File::open(&path)
|
||||||
.map_err(|e| format!("'{}': {}", path.to_string_lossy(), e))?;
|
.map_err(|e| format!("'{}': {e}", path.to_string_lossy()))?;
|
||||||
if file.metadata()?.is_dir() {
|
if file.metadata()?.is_dir() {
|
||||||
return Err(format!("'{}' is a directory.", path.to_string_lossy()).into());
|
return Err(format!("'{}' is a directory.", path.to_string_lossy()).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(stdout) = stdout_identifier {
|
if let Some(stdout) = stdout_identifier {
|
||||||
let input_identifier = Identifier::try_from(file).map_err(|e| {
|
let input_identifier = Identifier::try_from(file).map_err(|e| {
|
||||||
format!("{}: Error identifying file: {}", path.to_string_lossy(), e)
|
format!("{}: Error identifying file: {e}", path.to_string_lossy())
|
||||||
})?;
|
})?;
|
||||||
if stdout.surely_conflicts_with(&input_identifier) {
|
if stdout.surely_conflicts_with(&input_identifier) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
@@ -267,7 +267,9 @@ impl<'a> InputReader<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if content_type == Some(ContentType::UTF_16LE) {
|
if content_type == Some(ContentType::UTF_16LE) {
|
||||||
reader.read_until(0x00, &mut first_line).ok();
|
read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A).ok();
|
||||||
|
} else if content_type == Some(ContentType::UTF_16BE) {
|
||||||
|
read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputReader {
|
InputReader {
|
||||||
@@ -283,16 +285,44 @@ impl<'a> InputReader<'a> {
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
|
|
||||||
|
|
||||||
if self.content_type == Some(ContentType::UTF_16LE) {
|
if self.content_type == Some(ContentType::UTF_16LE) {
|
||||||
let _ = self.inner.read_until(0x00, buf);
|
return read_utf16_line(&mut self.inner, buf, 0x00, 0x0A);
|
||||||
|
}
|
||||||
|
if self.content_type == Some(ContentType::UTF_16BE) {
|
||||||
|
return read_utf16_line(&mut self.inner, buf, 0x0A, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_utf16_line<R: BufRead>(
|
||||||
|
reader: &mut R,
|
||||||
|
buf: &mut Vec<u8>,
|
||||||
|
read_until_char: u8,
|
||||||
|
preceded_by_char: u8,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
loop {
|
||||||
|
let mut temp = Vec::new();
|
||||||
|
let n = reader.read_until(read_until_char, &mut temp)?;
|
||||||
|
if n == 0 {
|
||||||
|
// EOF reached
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf.extend_from_slice(&temp);
|
||||||
|
if buf.len() >= 2
|
||||||
|
&& buf[buf.len() - 2] == preceded_by_char
|
||||||
|
&& buf[buf.len() - 1] == read_until_char
|
||||||
|
{
|
||||||
|
// end of line found
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// end of line not found, keep going
|
||||||
|
}
|
||||||
|
Ok(!buf.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic() {
|
fn basic() {
|
||||||
let content = b"#!/bin/bash\necho hello";
|
let content = b"#!/bin/bash\necho hello";
|
||||||
@@ -350,3 +380,53 @@ fn utf16le() {
|
|||||||
assert!(!res.unwrap());
|
assert!(!res.unwrap());
|
||||||
assert!(buffer.is_empty());
|
assert!(buffer.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn utf16le_issue3367() {
|
||||||
|
let content = b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00\
|
||||||
|
\x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00\
|
||||||
|
\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00";
|
||||||
|
let mut reader = InputReader::new(&content[..]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00",
|
||||||
|
&reader.first_line[..]
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffer = vec![];
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(res.unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00",
|
||||||
|
&buffer[..]
|
||||||
|
);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(res.unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
b"\x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00",
|
||||||
|
&buffer[..]
|
||||||
|
);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(res.unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
b"\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00",
|
||||||
|
&buffer[..]
|
||||||
|
);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(!res.unwrap());
|
||||||
|
assert!(buffer.is_empty());
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
#![cfg(feature = "lessopen")]
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -41,7 +39,7 @@ impl LessOpenPreprocessor {
|
|||||||
// Note that $LESSCLOSE has no such requirement
|
// Note that $LESSCLOSE has no such requirement
|
||||||
if lessopen.match_indices("%s").count() != 1 {
|
if lessopen.match_indices("%s").count() != 1 {
|
||||||
let error_msg = "LESSOPEN ignored: must contain exactly one %s";
|
let error_msg = "LESSOPEN ignored: must contain exactly one %s";
|
||||||
bat_warning!("{}", error_msg);
|
bat_warning!("{error_msg}");
|
||||||
return Err(error_msg.into());
|
return Err(error_msg.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +110,7 @@ impl LessOpenPreprocessor {
|
|||||||
if self.preprocess_stdin {
|
if self.preprocess_stdin {
|
||||||
if let Some(stdout) = stdout_identifier {
|
if let Some(stdout) = stdout_identifier {
|
||||||
let input_identifier = Identifier::try_from(clircle::Stdio::Stdin)
|
let input_identifier = Identifier::try_from(clircle::Stdio::Stdin)
|
||||||
.map_err(|e| format!("Stdin: Error identifying file: {}", e))?;
|
.map_err(|e| format!("Stdin: Error identifying file: {e}"))?;
|
||||||
if stdout.surely_conflicts_with(&input_identifier) {
|
if stdout.surely_conflicts_with(&input_identifier) {
|
||||||
return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into());
|
return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into());
|
||||||
}
|
}
|
||||||
@@ -200,7 +198,7 @@ impl LessOpenPreprocessor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fall_back_to_original_file(&self, lessopen_stdout: &Vec<u8>, exit_code: ExitStatus) -> bool {
|
fn fall_back_to_original_file(&self, lessopen_stdout: &[u8], exit_code: ExitStatus) -> bool {
|
||||||
lessopen_stdout.is_empty()
|
lessopen_stdout.is_empty()
|
||||||
&& (!exit_code.success() || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
|
&& (!exit_code.success() || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@ mod less;
|
|||||||
mod lessopen;
|
mod lessopen;
|
||||||
pub mod line_range;
|
pub mod line_range;
|
||||||
pub(crate) mod nonprintable_notation;
|
pub(crate) mod nonprintable_notation;
|
||||||
mod output;
|
pub mod output;
|
||||||
#[cfg(feature = "paging")]
|
#[cfg(feature = "paging")]
|
||||||
mod pager;
|
mod pager;
|
||||||
#[cfg(feature = "paging")]
|
#[cfg(feature = "paging")]
|
||||||
|
@@ -1,16 +1,26 @@
|
|||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
|
use itertools::{Itertools, MinMaxResult};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct LineRange {
|
pub struct LineRange {
|
||||||
lower: usize,
|
lower: RangeBound,
|
||||||
upper: usize,
|
upper: RangeBound,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines a boundary for a range
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub(crate) enum RangeBound {
|
||||||
|
// An absolute line number marking the boundary of a range
|
||||||
|
Absolute(usize),
|
||||||
|
// A relative (implicitly negative) offset from the end of the file as a boundary
|
||||||
|
OffsetFromEnd(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LineRange {
|
impl Default for LineRange {
|
||||||
fn default() -> LineRange {
|
fn default() -> LineRange {
|
||||||
LineRange {
|
LineRange {
|
||||||
lower: usize::min_value(),
|
lower: RangeBound::Absolute(usize::MIN),
|
||||||
upper: usize::max_value(),
|
upper: RangeBound::Absolute(usize::MAX),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,8 +28,8 @@ impl Default for LineRange {
|
|||||||
impl LineRange {
|
impl LineRange {
|
||||||
pub fn new(from: usize, to: usize) -> Self {
|
pub fn new(from: usize, to: usize) -> Self {
|
||||||
LineRange {
|
LineRange {
|
||||||
lower: from,
|
lower: RangeBound::Absolute(from),
|
||||||
upper: to,
|
upper: RangeBound::Absolute(to),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,31 +39,47 @@ impl LineRange {
|
|||||||
|
|
||||||
fn parse_range(range_raw: &str) -> Result<LineRange> {
|
fn parse_range(range_raw: &str) -> Result<LineRange> {
|
||||||
let mut new_range = LineRange::default();
|
let mut new_range = LineRange::default();
|
||||||
|
let mut raw_range_iter = range_raw.bytes();
|
||||||
|
let first_byte = raw_range_iter.next().ok_or("Empty line range")?;
|
||||||
|
|
||||||
if range_raw.bytes().next().ok_or("Empty line range")? == b':' {
|
if first_byte == b':' {
|
||||||
new_range.upper = range_raw[1..].parse()?;
|
if raw_range_iter.next() == Some(b'-') {
|
||||||
|
// E.g. ':-3'
|
||||||
|
let value = range_raw[2..].parse()?;
|
||||||
|
new_range.upper = RangeBound::OffsetFromEnd(value);
|
||||||
|
} else {
|
||||||
|
let value = range_raw[1..].parse()?;
|
||||||
|
new_range.upper = RangeBound::Absolute(value);
|
||||||
|
}
|
||||||
return Ok(new_range);
|
return Ok(new_range);
|
||||||
} else if range_raw.bytes().last().ok_or("Empty line range")? == b':' {
|
} else if range_raw.bytes().last().ok_or("Empty line range")? == b':' {
|
||||||
new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
|
if first_byte == b'-' {
|
||||||
|
// E.g. '-3:'
|
||||||
|
let value = range_raw[1..range_raw.len() - 1].parse()?;
|
||||||
|
new_range.lower = RangeBound::OffsetFromEnd(value);
|
||||||
|
} else {
|
||||||
|
let value = range_raw[..range_raw.len() - 1].parse()?;
|
||||||
|
new_range.lower = RangeBound::Absolute(value);
|
||||||
|
}
|
||||||
return Ok(new_range);
|
return Ok(new_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_numbers: Vec<&str> = range_raw.split(':').collect();
|
let line_numbers: Vec<&str> = range_raw.split(':').collect();
|
||||||
match line_numbers.len() {
|
match line_numbers.len() {
|
||||||
1 => {
|
1 => {
|
||||||
new_range.lower = line_numbers[0].parse()?;
|
new_range.lower = RangeBound::Absolute(line_numbers[0].parse()?);
|
||||||
new_range.upper = new_range.lower;
|
new_range.upper = new_range.lower;
|
||||||
Ok(new_range)
|
Ok(new_range)
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
new_range.lower = line_numbers[0].parse()?;
|
let mut lower_absolute_bound: usize = line_numbers[0].parse()?;
|
||||||
let first_byte = line_numbers[1].bytes().next();
|
let first_byte = line_numbers[1].bytes().next();
|
||||||
|
|
||||||
new_range.upper = if first_byte == Some(b'+') {
|
let upper_absolute_bound = if first_byte == Some(b'+') {
|
||||||
let more_lines = &line_numbers[1][1..]
|
let more_lines = &line_numbers[1][1..]
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| "Invalid character after +")?;
|
.map_err(|_| "Invalid character after +")?;
|
||||||
new_range.lower.saturating_add(*more_lines)
|
lower_absolute_bound.saturating_add(*more_lines)
|
||||||
} else if first_byte == Some(b'-') {
|
} else if first_byte == Some(b'-') {
|
||||||
// this will prevent values like "-+5" even though "+5" is valid integer
|
// this will prevent values like "-+5" even though "+5" is valid integer
|
||||||
if line_numbers[1][1..].bytes().next() == Some(b'+') {
|
if line_numbers[1][1..].bytes().next() == Some(b'+') {
|
||||||
@@ -62,77 +88,178 @@ impl LineRange {
|
|||||||
let prior_lines = &line_numbers[1][1..]
|
let prior_lines = &line_numbers[1][1..]
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| "Invalid character after -")?;
|
.map_err(|_| "Invalid character after -")?;
|
||||||
let prev_lower = new_range.lower;
|
let prev_lower = lower_absolute_bound;
|
||||||
new_range.lower = new_range.lower.saturating_sub(*prior_lines);
|
lower_absolute_bound = lower_absolute_bound.saturating_sub(*prior_lines);
|
||||||
prev_lower
|
prev_lower
|
||||||
} else {
|
} else {
|
||||||
line_numbers[1].parse()?
|
line_numbers[1].parse()?
|
||||||
};
|
};
|
||||||
|
new_range.lower = RangeBound::Absolute(lower_absolute_bound);
|
||||||
|
new_range.upper = RangeBound::Absolute(upper_absolute_bound);
|
||||||
|
Ok(new_range)
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
// Handle context syntax: N::C or N:M:C
|
||||||
|
if line_numbers[1].is_empty() {
|
||||||
|
// Format: N::C - single line with context
|
||||||
|
let line_number: usize = line_numbers[0].parse()
|
||||||
|
.map_err(|_| "Invalid line number in N::C format")?;
|
||||||
|
let context: usize = line_numbers[2].parse()
|
||||||
|
.map_err(|_| "Invalid context number in N::C format")?;
|
||||||
|
|
||||||
|
new_range.lower = RangeBound::Absolute(line_number.saturating_sub(context));
|
||||||
|
new_range.upper = RangeBound::Absolute(line_number.saturating_add(context));
|
||||||
|
} else {
|
||||||
|
// Format: N:M:C - range with context
|
||||||
|
let start_line: usize = line_numbers[0].parse()
|
||||||
|
.map_err(|_| "Invalid start line number in N:M:C format")?;
|
||||||
|
let end_line: usize = line_numbers[1].parse()
|
||||||
|
.map_err(|_| "Invalid end line number in N:M:C format")?;
|
||||||
|
let context: usize = line_numbers[2].parse()
|
||||||
|
.map_err(|_| "Invalid context number in N:M:C format")?;
|
||||||
|
|
||||||
|
new_range.lower = RangeBound::Absolute(start_line.saturating_sub(context));
|
||||||
|
new_range.upper = RangeBound::Absolute(end_line.saturating_add(context));
|
||||||
|
}
|
||||||
Ok(new_range)
|
Ok(new_range)
|
||||||
}
|
}
|
||||||
_ => Err(
|
_ => Err(
|
||||||
"Line range contained more than one ':' character. Expected format: 'N' or 'N:M'"
|
"Line range contained too many ':' characters. Expected format: 'N', 'N:M', 'N::C', or 'N:M:C'"
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_inside(&self, line: usize) -> bool {
|
/// Checks if a line number is inside the range.
|
||||||
line >= self.lower && line <= self.upper
|
/// For ranges with relative offsets range bounds `max_buffered_line_number` is necessary
|
||||||
|
/// to convert the offset to an absolute value.
|
||||||
|
pub(crate) fn is_inside(
|
||||||
|
&self,
|
||||||
|
line: usize,
|
||||||
|
max_buffered_line_number: MaxBufferedLineNumber,
|
||||||
|
) -> bool {
|
||||||
|
match (self.lower, self.upper, max_buffered_line_number) {
|
||||||
|
(RangeBound::Absolute(lower), RangeBound::Absolute(upper), _) => {
|
||||||
|
lower <= line && line <= upper
|
||||||
|
}
|
||||||
|
(
|
||||||
|
RangeBound::Absolute(lower),
|
||||||
|
RangeBound::OffsetFromEnd(offset),
|
||||||
|
MaxBufferedLineNumber::Final(last_line_number),
|
||||||
|
) => lower <= line && line <= last_line_number.saturating_sub(offset),
|
||||||
|
(
|
||||||
|
RangeBound::Absolute(lower),
|
||||||
|
RangeBound::OffsetFromEnd(_),
|
||||||
|
MaxBufferedLineNumber::Tentative(_),
|
||||||
|
) => {
|
||||||
|
// We don't know the final line number yet, so the assumption is that the line is
|
||||||
|
// still far enough away from the upper end of the range
|
||||||
|
lower <= line
|
||||||
|
}
|
||||||
|
(
|
||||||
|
RangeBound::OffsetFromEnd(offset),
|
||||||
|
RangeBound::Absolute(upper),
|
||||||
|
MaxBufferedLineNumber::Final(last_line_number),
|
||||||
|
) => last_line_number.saturating_sub(offset) <= line && line <= upper,
|
||||||
|
(
|
||||||
|
RangeBound::OffsetFromEnd(_),
|
||||||
|
RangeBound::Absolute(_),
|
||||||
|
MaxBufferedLineNumber::Tentative(_),
|
||||||
|
) => {
|
||||||
|
// We don't know the final line number yet, so the assumption is that the line is
|
||||||
|
// still too far away from the having reached the lower end of the range
|
||||||
|
false
|
||||||
|
}
|
||||||
|
(
|
||||||
|
RangeBound::OffsetFromEnd(lower),
|
||||||
|
RangeBound::OffsetFromEnd(upper),
|
||||||
|
MaxBufferedLineNumber::Final(last_line_number),
|
||||||
|
) => {
|
||||||
|
last_line_number.saturating_sub(lower) <= line
|
||||||
|
&& line <= last_line_number.saturating_sub(upper)
|
||||||
|
}
|
||||||
|
(
|
||||||
|
RangeBound::OffsetFromEnd(_),
|
||||||
|
RangeBound::OffsetFromEnd(_),
|
||||||
|
MaxBufferedLineNumber::Tentative(_),
|
||||||
|
) => {
|
||||||
|
// We don't know the final line number yet, so the assumption is that we're still
|
||||||
|
// too far away from the having reached the lower end of the range
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_full() {
|
fn test_parse_full() {
|
||||||
let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
|
let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(40, range.lower);
|
assert_eq!(RangeBound::Absolute(40), range.lower);
|
||||||
assert_eq!(50, range.upper);
|
assert_eq!(RangeBound::Absolute(50), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_partial_min() {
|
fn test_parse_partial_min() {
|
||||||
let range = LineRange::from(":50").expect("Shouldn't fail on test!");
|
let range = LineRange::from(":50").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(usize::min_value(), range.lower);
|
assert_eq!(RangeBound::Absolute(usize::MIN), range.lower);
|
||||||
assert_eq!(50, range.upper);
|
assert_eq!(RangeBound::Absolute(50), range.upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_partial_relative_negative_from_back() {
|
||||||
|
let range = LineRange::from(":-5").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(usize::MIN), range.lower);
|
||||||
|
assert_eq!(RangeBound::OffsetFromEnd(5), range.upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_relative_negative_from_back_partial() {
|
||||||
|
let range = LineRange::from("-5:").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::OffsetFromEnd(5), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(usize::MAX), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_partial_max() {
|
fn test_parse_partial_max() {
|
||||||
let range = LineRange::from("40:").expect("Shouldn't fail on test!");
|
let range = LineRange::from("40:").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(40, range.lower);
|
assert_eq!(RangeBound::Absolute(40), range.lower);
|
||||||
assert_eq!(usize::max_value(), range.upper);
|
assert_eq!(RangeBound::Absolute(usize::MAX), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_single() {
|
fn test_parse_single() {
|
||||||
let range = LineRange::from("40").expect("Shouldn't fail on test!");
|
let range = LineRange::from("40").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(40, range.lower);
|
assert_eq!(RangeBound::Absolute(40), range.lower);
|
||||||
assert_eq!(40, range.upper);
|
assert_eq!(RangeBound::Absolute(40), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_fail() {
|
fn test_parse_fail() {
|
||||||
let range = LineRange::from("40:50:80");
|
// Test 4+ colon parts should still fail
|
||||||
|
let range = LineRange::from("40:50:80:90");
|
||||||
assert!(range.is_err());
|
assert!(range.is_err());
|
||||||
let range = LineRange::from("40::80");
|
// Test invalid formats that should still fail
|
||||||
|
let range = LineRange::from("-2:5");
|
||||||
assert!(range.is_err());
|
assert!(range.is_err());
|
||||||
let range = LineRange::from(":40:");
|
let range = LineRange::from(":40:");
|
||||||
assert!(range.is_err());
|
assert!(range.is_err());
|
||||||
|
// Test completely malformed input
|
||||||
|
let range = LineRange::from("abc:def");
|
||||||
|
assert!(range.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_plus() {
|
fn test_parse_plus() {
|
||||||
let range = LineRange::from("40:+10").expect("Shouldn't fail on test!");
|
let range = LineRange::from("40:+10").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(40, range.lower);
|
assert_eq!(RangeBound::Absolute(40), range.lower);
|
||||||
assert_eq!(50, range.upper);
|
assert_eq!(RangeBound::Absolute(50), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_plus_overflow() {
|
fn test_parse_plus_overflow() {
|
||||||
let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!");
|
let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!");
|
||||||
assert_eq!(usize::MAX, range.lower);
|
assert_eq!(RangeBound::Absolute(usize::MAX), range.lower);
|
||||||
assert_eq!(usize::MAX, range.upper);
|
assert_eq!(RangeBound::Absolute(usize::MAX), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -148,21 +275,21 @@ fn test_parse_plus_fail() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_minus_success() {
|
fn test_parse_minus_success() {
|
||||||
let range = LineRange::from("40:-10").expect("Shouldn't fail on test!");
|
let range = LineRange::from("40:-10").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(30, range.lower);
|
assert_eq!(RangeBound::Absolute(30), range.lower);
|
||||||
assert_eq!(40, range.upper);
|
assert_eq!(RangeBound::Absolute(40), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_minus_edge_cases_success() {
|
fn test_parse_minus_edge_cases_success() {
|
||||||
let range = LineRange::from("5:-4").expect("Shouldn't fail on test!");
|
let range = LineRange::from("5:-4").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(1, range.lower);
|
assert_eq!(RangeBound::Absolute(1), range.lower);
|
||||||
assert_eq!(5, range.upper);
|
assert_eq!(RangeBound::Absolute(5), range.upper);
|
||||||
let range = LineRange::from("5:-5").expect("Shouldn't fail on test!");
|
let range = LineRange::from("5:-5").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(0, range.lower);
|
assert_eq!(RangeBound::Absolute(0), range.lower);
|
||||||
assert_eq!(5, range.upper);
|
assert_eq!(RangeBound::Absolute(5), range.upper);
|
||||||
let range = LineRange::from("5:-100").expect("Shouldn't fail on test!");
|
let range = LineRange::from("5:-100").expect("Shouldn't fail on test!");
|
||||||
assert_eq!(0, range.lower);
|
assert_eq!(RangeBound::Absolute(0), range.lower);
|
||||||
assert_eq!(5, range.upper);
|
assert_eq!(RangeBound::Absolute(5), range.upper);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -175,6 +302,57 @@ fn test_parse_minus_fail() {
|
|||||||
assert!(range.is_err());
|
assert!(range.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_context_single_line() {
|
||||||
|
let range = LineRange::from("35::5").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(30), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(40), range.upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_context_range() {
|
||||||
|
let range = LineRange::from("30:40:2").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(28), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(42), range.upper);
|
||||||
|
|
||||||
|
// Test the case that used to fail but should now work
|
||||||
|
let range = LineRange::from("40:50:80").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(0), range.lower); // 40 - 80 = 0 (saturated)
|
||||||
|
assert_eq!(RangeBound::Absolute(130), range.upper); // 50 + 80 = 130
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_context_edge_cases() {
|
||||||
|
// Test with small line numbers that would underflow
|
||||||
|
let range = LineRange::from("5::10").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(0), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(15), range.upper);
|
||||||
|
|
||||||
|
// Test with zero context
|
||||||
|
let range = LineRange::from("50::0").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(50), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(50), range.upper);
|
||||||
|
|
||||||
|
// Test range with zero context
|
||||||
|
let range = LineRange::from("30:40:0").expect("Shouldn't fail on test!");
|
||||||
|
assert_eq!(RangeBound::Absolute(30), range.lower);
|
||||||
|
assert_eq!(RangeBound::Absolute(40), range.upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_context_fail() {
|
||||||
|
let range = LineRange::from("40::z");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("::5");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("40::");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("30:40:z");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("30::40:5");
|
||||||
|
assert!(range.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum RangeCheckResult {
|
pub enum RangeCheckResult {
|
||||||
// Within one of the given ranges
|
// Within one of the given ranges
|
||||||
@@ -187,10 +365,24 @@ pub enum RangeCheckResult {
|
|||||||
AfterLastRange,
|
AfterLastRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the maximum line number in the buffer when reading a file.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub(crate) enum MaxBufferedLineNumber {
|
||||||
|
// The currently known maximum line number, may not be the final line number
|
||||||
|
Tentative(usize),
|
||||||
|
// The final line number, when EOF has been reached
|
||||||
|
Final(usize),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LineRanges {
|
pub struct LineRanges {
|
||||||
ranges: Vec<LineRange>,
|
ranges: Vec<LineRange>,
|
||||||
largest_upper_bound: usize,
|
// The largest absolute upper line number of all ranges
|
||||||
|
largest_absolute_upper_bound: usize,
|
||||||
|
// The smallest relative offset from the end of all ranges
|
||||||
|
smallest_offset_from_end: usize,
|
||||||
|
// The largest relative offset from the end of all ranges
|
||||||
|
largest_offset_from_end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LineRanges {
|
impl LineRanges {
|
||||||
@@ -203,26 +395,62 @@ impl LineRanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(ranges: Vec<LineRange>) -> LineRanges {
|
pub fn from(ranges: Vec<LineRange>) -> LineRanges {
|
||||||
let largest_upper_bound = ranges
|
let largest_absolute_upper_bound = ranges
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r| r.upper)
|
.filter_map(|r| match r.upper {
|
||||||
|
RangeBound::Absolute(upper) => Some(upper),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(usize::max_value());
|
.unwrap_or(usize::MAX);
|
||||||
|
|
||||||
|
let offsets_min_max = ranges
|
||||||
|
.iter()
|
||||||
|
.flat_map(|r| [r.lower, r.upper])
|
||||||
|
.filter_map(|r| match r {
|
||||||
|
RangeBound::OffsetFromEnd(offset) => Some(offset),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.minmax();
|
||||||
|
|
||||||
|
let (smallest_offset_from_end, largest_offset_from_end) = match offsets_min_max {
|
||||||
|
MinMaxResult::NoElements => (usize::MIN, usize::MIN),
|
||||||
|
MinMaxResult::OneElement(offset) => (offset, offset),
|
||||||
|
MinMaxResult::MinMax(min, max) => (min, max),
|
||||||
|
};
|
||||||
|
|
||||||
LineRanges {
|
LineRanges {
|
||||||
ranges,
|
ranges,
|
||||||
largest_upper_bound,
|
largest_absolute_upper_bound,
|
||||||
|
smallest_offset_from_end,
|
||||||
|
largest_offset_from_end,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check(&self, line: usize) -> RangeCheckResult {
|
pub(crate) fn check(
|
||||||
if self.ranges.iter().any(|r| r.is_inside(line)) {
|
&self,
|
||||||
|
line: usize,
|
||||||
|
max_buffered_line_number: MaxBufferedLineNumber,
|
||||||
|
) -> RangeCheckResult {
|
||||||
|
if self
|
||||||
|
.ranges
|
||||||
|
.iter()
|
||||||
|
.any(|r| r.is_inside(line, max_buffered_line_number))
|
||||||
|
{
|
||||||
RangeCheckResult::InRange
|
RangeCheckResult::InRange
|
||||||
} else if line < self.largest_upper_bound {
|
} else if matches!(max_buffered_line_number, MaxBufferedLineNumber::Final(final_line_number) if line > final_line_number.saturating_sub(self.smallest_offset_from_end))
|
||||||
|
{
|
||||||
|
RangeCheckResult::AfterLastRange
|
||||||
|
} else if line < self.largest_absolute_upper_bound {
|
||||||
RangeCheckResult::BeforeOrBetweenRanges
|
RangeCheckResult::BeforeOrBetweenRanges
|
||||||
} else {
|
} else {
|
||||||
RangeCheckResult::AfterLastRange
|
RangeCheckResult::AfterLastRange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn largest_offset_from_end(&self) -> usize {
|
||||||
|
self.largest_offset_from_end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LineRanges {
|
impl Default for LineRanges {
|
||||||
@@ -249,54 +477,292 @@ fn ranges(rs: &[&str]) -> LineRanges {
|
|||||||
fn test_ranges_simple() {
|
fn test_ranges_simple() {
|
||||||
let ranges = ranges(&["3:8"]);
|
let ranges = ranges(&["3:8"]);
|
||||||
|
|
||||||
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2));
|
assert_eq!(
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
|
ranges.check(2, MaxBufferedLineNumber::Tentative(2))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Tentative(9))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranges_advanced() {
|
fn test_ranges_advanced() {
|
||||||
let ranges = ranges(&["3:8", "11:20", "25:30"]);
|
let ranges = ranges(&["3:8", "11:20", "25:30"]);
|
||||||
|
|
||||||
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2));
|
assert_eq!(
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(9));
|
ranges.check(2, MaxBufferedLineNumber::Tentative(2))
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(11));
|
);
|
||||||
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(22));
|
assert_eq!(
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(28));
|
RangeCheckResult::InRange,
|
||||||
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(31));
|
ranges.check(5, MaxBufferedLineNumber::Tentative(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Tentative(9))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(11, MaxBufferedLineNumber::Tentative(11))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(22, MaxBufferedLineNumber::Tentative(22))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(28, MaxBufferedLineNumber::Tentative(28))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(31, MaxBufferedLineNumber::Tentative(31))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranges_open_low() {
|
fn test_ranges_open_low() {
|
||||||
let ranges = ranges(&["3:8", ":5"]);
|
let ranges = ranges(&["3:8", ":5"]);
|
||||||
|
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
|
assert_eq!(
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
|
RangeCheckResult::InRange,
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(7));
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Tentative(3))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(7, MaxBufferedLineNumber::Tentative(7))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Tentative(9))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranges_open_high() {
|
fn test_ranges_open_high() {
|
||||||
let ranges = ranges(&["3:", "2:5"]);
|
let ranges = ranges(&["3:", "2:5"]);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1));
|
assert_eq!(
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
|
ranges.check(1, MaxBufferedLineNumber::Final(10))
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(9));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(2, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(10, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Tentative(3))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Tentative(9))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ranges_open_up_to_3_from_end() {
|
||||||
|
let ranges = ranges(&[":-3"]);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Tentative(3))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(8))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(2, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(4, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(6, MaxBufferedLineNumber::Final(6))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ranges_multiple_negative_from_back() {
|
||||||
|
let ranges = ranges(&[":-3", ":-9"]);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Tentative(3))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(14))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Final(16))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(7, MaxBufferedLineNumber::Final(16))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(13, MaxBufferedLineNumber::Final(16))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(14, MaxBufferedLineNumber::Final(16))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::AfterLastRange,
|
||||||
|
ranges.check(16, MaxBufferedLineNumber::Final(16))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ranges_3_from_back_up_to_end() {
|
||||||
|
let ranges = ranges(&["-3:"]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Tentative(3))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(8))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Final(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(2, MaxBufferedLineNumber::Final(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(3, MaxBufferedLineNumber::Final(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(4, MaxBufferedLineNumber::Final(5))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Final(5))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ranges_multiple_negative_offsets_to_end() {
|
||||||
|
let ranges = ranges(&["-3:", "-12:"]);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(8))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::BeforeOrBetweenRanges,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(17))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(8, MaxBufferedLineNumber::Final(20))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Final(20))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ranges_absolute_bound_and_offset() {
|
||||||
|
let ranges = ranges(&["5:", ":-2"]);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(4, MaxBufferedLineNumber::Tentative(6))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(5, MaxBufferedLineNumber::Tentative(7))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(8, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(9, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(10, MaxBufferedLineNumber::Final(10))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranges_all() {
|
fn test_ranges_all() {
|
||||||
let ranges = LineRanges::all();
|
let ranges = LineRanges::all();
|
||||||
|
|
||||||
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
|
assert_eq!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranges_none() {
|
fn test_ranges_none() {
|
||||||
let ranges = LineRanges::none();
|
let ranges = LineRanges::none();
|
||||||
|
|
||||||
assert_ne!(RangeCheckResult::InRange, ranges.check(1));
|
assert_ne!(
|
||||||
|
RangeCheckResult::InRange,
|
||||||
|
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
use std::fmt;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
#[cfg(feature = "paging")]
|
#[cfg(feature = "paging")]
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
@@ -92,6 +93,9 @@ impl OutputType {
|
|||||||
p.arg("-S"); // Short version of --chop-long-lines for compatibility
|
p.arg("-S"); // Short version of --chop-long-lines for compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensures that 'less' quits together with 'bat'
|
||||||
|
p.arg("-K"); // Short version of '--quit-on-intr'
|
||||||
|
|
||||||
// Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
|
// Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
|
||||||
// versions of 'less'. Unfortunately, it also breaks mouse-wheel support.
|
// versions of 'less'. Unfortunately, it also breaks mouse-wheel support.
|
||||||
//
|
//
|
||||||
@@ -162,3 +166,17 @@ impl Drop for OutputType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum OutputHandle<'a> {
|
||||||
|
IoWrite(&'a mut dyn io::Write),
|
||||||
|
FmtWrite(&'a mut dyn fmt::Write),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputHandle<'_> {
|
||||||
|
pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
|
||||||
|
match self {
|
||||||
|
Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
||||||
|
Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -10,6 +10,7 @@ use crate::{
|
|||||||
error::Result,
|
error::Result,
|
||||||
input,
|
input,
|
||||||
line_range::{HighlightedLineRanges, LineRange, LineRanges},
|
line_range::{HighlightedLineRanges, LineRange, LineRanges},
|
||||||
|
output::OutputHandle,
|
||||||
style::StyleComponent,
|
style::StyleComponent,
|
||||||
StripAnsiMode, SyntaxMapping, WrappingMode,
|
StripAnsiMode, SyntaxMapping, WrappingMode,
|
||||||
};
|
};
|
||||||
@@ -325,7 +326,10 @@ impl<'a> PrettyPrinter<'a> {
|
|||||||
|
|
||||||
// If writer is provided, pass it to the controller, otherwise pass None
|
// If writer is provided, pass it to the controller, otherwise pass None
|
||||||
if let Some(mut w) = writer {
|
if let Some(mut w) = writer {
|
||||||
controller.run(inputs.into_iter().map(|i| i.into()).collect(), Some(&mut w))
|
controller.run(
|
||||||
|
inputs.into_iter().map(|i| i.into()).collect(),
|
||||||
|
Some(OutputHandle::FmtWrite(&mut w)),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
|
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::io;
|
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
|
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
|
||||||
@@ -17,6 +15,7 @@ use content_inspector::ContentType;
|
|||||||
|
|
||||||
use encoding_rs::{UTF_16BE, UTF_16LE};
|
use encoding_rs::{UTF_16BE, UTF_16LE};
|
||||||
|
|
||||||
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
use unicode_width::UnicodeWidthChar;
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
|
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
|
||||||
@@ -28,7 +27,8 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}
|
|||||||
use crate::diff::LineChanges;
|
use crate::diff::LineChanges;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::input::OpenedInput;
|
use crate::input::OpenedInput;
|
||||||
use crate::line_range::RangeCheckResult;
|
use crate::line_range::{MaxBufferedLineNumber, RangeCheckResult};
|
||||||
|
use crate::output::OutputHandle;
|
||||||
use crate::preprocessor::strip_ansi;
|
use crate::preprocessor::strip_ansi;
|
||||||
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
||||||
use crate::style::StyleComponent;
|
use crate::style::StyleComponent;
|
||||||
@@ -68,20 +68,6 @@ const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting:
|
|||||||
font_style: FontStyle::empty(),
|
font_style: FontStyle::empty(),
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum OutputHandle<'a> {
|
|
||||||
IoWrite(&'a mut dyn io::Write),
|
|
||||||
FmtWrite(&'a mut dyn fmt::Write),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> OutputHandle<'a> {
|
|
||||||
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
|
||||||
Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait Printer {
|
pub(crate) trait Printer {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -99,6 +85,7 @@ pub(crate) trait Printer {
|
|||||||
handle: &mut OutputHandle,
|
handle: &mut OutputHandle,
|
||||||
line_number: usize,
|
line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
|
max_buffered_line_number: MaxBufferedLineNumber,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +103,7 @@ impl<'a> SimplePrinter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Printer for SimplePrinter<'a> {
|
impl Printer for SimplePrinter<'_> {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
_handle: &mut OutputHandle,
|
_handle: &mut OutputHandle,
|
||||||
@@ -140,11 +127,12 @@ impl<'a> Printer for SimplePrinter<'a> {
|
|||||||
handle: &mut OutputHandle,
|
handle: &mut OutputHandle,
|
||||||
_line_number: usize,
|
_line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
|
_max_buffered_line_number: MaxBufferedLineNumber,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Skip squeezed lines.
|
// Skip squeezed lines.
|
||||||
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
||||||
if String::from_utf8_lossy(line_buffer)
|
if String::from_utf8_lossy(line_buffer)
|
||||||
.trim_end_matches(|c| c == '\r' || c == '\n')
|
.trim_end_matches(['\r', '\n'])
|
||||||
.is_empty()
|
.is_empty()
|
||||||
{
|
{
|
||||||
self.consecutive_empty_lines += 1;
|
self.consecutive_empty_lines += 1;
|
||||||
@@ -267,7 +255,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
let is_printing_binary = input
|
let is_printing_binary = input
|
||||||
.reader
|
.reader
|
||||||
.content_type
|
.content_type
|
||||||
.map_or(false, |c| c.is_binary() && !config.show_nonprintable);
|
.is_some_and(|c| c.is_binary() && !config.show_nonprintable);
|
||||||
|
|
||||||
let needs_to_match_syntax = (!is_printing_binary
|
let needs_to_match_syntax = (!is_printing_binary
|
||||||
|| matches!(config.binary, BinaryBehavior::AsText))
|
|| matches!(config.binary, BinaryBehavior::AsText))
|
||||||
@@ -341,7 +329,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
||||||
} else {
|
} else {
|
||||||
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
||||||
let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
|
let hline = format!("{}{grid_char}{hline}", "─".repeat(self.panel_width));
|
||||||
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
|
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,8 +343,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
|
|
||||||
let text_truncated: String = text.chars().take(self.panel_width - 1).collect();
|
let text_truncated: String = text.chars().take(self.panel_width - 1).collect();
|
||||||
let text_filled: String = format!(
|
let text_filled: String = format!(
|
||||||
"{}{}",
|
"{text_truncated}{}",
|
||||||
text_truncated,
|
|
||||||
" ".repeat(self.panel_width - 1 - text_truncated.len())
|
" ".repeat(self.panel_width - 1 - text_truncated.len())
|
||||||
);
|
);
|
||||||
if self.config.style_components.grid() {
|
if self.config.style_components.grid() {
|
||||||
@@ -403,14 +390,18 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
handle: &mut OutputHandle,
|
handle: &mut OutputHandle,
|
||||||
content: &str,
|
content: &str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut content = content;
|
|
||||||
let content_width = self.config.term_width - self.get_header_component_indent_length();
|
let content_width = self.config.term_width - self.get_header_component_indent_length();
|
||||||
while content.len() > content_width {
|
if content.chars().count() <= content_width {
|
||||||
let (content_line, remaining) = content.split_at(content_width);
|
return self.print_header_component_with_indent(handle, content);
|
||||||
self.print_header_component_with_indent(handle, content_line)?;
|
|
||||||
content = remaining;
|
|
||||||
}
|
}
|
||||||
self.print_header_component_with_indent(handle, content)
|
|
||||||
|
let mut content_graphemes: Vec<&str> = content.graphemes(true).collect();
|
||||||
|
while content_graphemes.len() > content_width {
|
||||||
|
let (content_line, remaining) = content_graphemes.split_at(content_width);
|
||||||
|
self.print_header_component_with_indent(handle, content_line.join("").as_str())?;
|
||||||
|
content_graphemes = remaining.to_vec();
|
||||||
|
}
|
||||||
|
self.print_header_component_with_indent(handle, content_graphemes.join("").as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_regions_for_line<'b>(
|
fn highlight_regions_for_line<'b>(
|
||||||
@@ -432,7 +423,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
.highlight_line(for_highlighting, highlighter_from_set.syntax_set)?;
|
.highlight_line(for_highlighting, highlighter_from_set.syntax_set)?;
|
||||||
|
|
||||||
if too_long {
|
if too_long {
|
||||||
highlighted_line[0].1 = &line;
|
highlighted_line[0].1 = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(highlighted_line)
|
Ok(highlighted_line)
|
||||||
@@ -448,7 +439,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Printer for InteractivePrinter<'a> {
|
impl Printer for InteractivePrinter<'_> {
|
||||||
fn print_header(
|
fn print_header(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: &mut OutputHandle,
|
handle: &mut OutputHandle,
|
||||||
@@ -521,13 +512,12 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
.try_for_each(|component| match component {
|
.try_for_each(|component| match component {
|
||||||
StyleComponent::HeaderFilename => {
|
StyleComponent::HeaderFilename => {
|
||||||
let header_filename = format!(
|
let header_filename = format!(
|
||||||
"{}{}{}",
|
"{}{}{mode}",
|
||||||
description
|
description
|
||||||
.kind()
|
.kind()
|
||||||
.map(|kind| format!("{kind}: "))
|
.map(|kind| format!("{kind}: "))
|
||||||
.unwrap_or_else(|| "".into()),
|
.unwrap_or_else(|| "".into()),
|
||||||
self.colors.header_value.paint(description.title()),
|
self.colors.header_value.paint(description.title()),
|
||||||
mode
|
|
||||||
);
|
);
|
||||||
self.print_header_multiline_component(handle, &header_filename)
|
self.print_header_multiline_component(handle, &header_filename)
|
||||||
}
|
}
|
||||||
@@ -544,7 +534,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if self.config.style_components.grid() {
|
if self.config.style_components.grid() {
|
||||||
if self.content_type.map_or(false, |c| c.is_text())
|
if self.content_type.is_some_and(|c| c.is_text())
|
||||||
|| self.config.show_nonprintable
|
|| self.config.show_nonprintable
|
||||||
|| matches!(self.config.binary, BinaryBehavior::AsText)
|
|| matches!(self.config.binary, BinaryBehavior::AsText)
|
||||||
{
|
{
|
||||||
@@ -559,7 +549,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
|
|
||||||
fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
||||||
if self.config.style_components.grid()
|
if self.config.style_components.grid()
|
||||||
&& (self.content_type.map_or(false, |c| c.is_text())
|
&& (self.content_type.is_some_and(|c| c.is_text())
|
||||||
|| self.config.show_nonprintable
|
|| self.config.show_nonprintable
|
||||||
|| matches!(self.config.binary, BinaryBehavior::AsText))
|
|| matches!(self.config.binary, BinaryBehavior::AsText))
|
||||||
{
|
{
|
||||||
@@ -599,6 +589,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
handle: &mut OutputHandle,
|
handle: &mut OutputHandle,
|
||||||
line_number: usize,
|
line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
|
max_buffered_line_number: MaxBufferedLineNumber,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let line = if self.config.show_nonprintable {
|
let line = if self.config.show_nonprintable {
|
||||||
replace_nonprintable(
|
replace_nonprintable(
|
||||||
@@ -644,7 +635,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
|
|
||||||
// Skip squeezed lines.
|
// Skip squeezed lines.
|
||||||
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
||||||
if line.trim_end_matches(|c| c == '\r' || c == '\n').is_empty() {
|
if line.trim_end_matches(['\r', '\n']).is_empty() {
|
||||||
self.consecutive_empty_lines += 1;
|
self.consecutive_empty_lines += 1;
|
||||||
if self.consecutive_empty_lines > squeeze_limit {
|
if self.consecutive_empty_lines > squeeze_limit {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -660,8 +651,12 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
let mut panel_wrap: Option<String> = None;
|
let mut panel_wrap: Option<String> = None;
|
||||||
|
|
||||||
// Line highlighting
|
// Line highlighting
|
||||||
let highlight_this_line =
|
let highlight_this_line = self
|
||||||
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
|
.config
|
||||||
|
.highlighted_lines
|
||||||
|
.0
|
||||||
|
.check(line_number, max_buffered_line_number)
|
||||||
|
== RangeCheckResult::InRange;
|
||||||
|
|
||||||
if highlight_this_line && self.config.theme == "ansi" {
|
if highlight_this_line && self.config.theme == "ansi" {
|
||||||
self.ansi_style.update(ANSI_UNDERLINE_ENABLE);
|
self.ansi_style.update(ANSI_UNDERLINE_ENABLE);
|
||||||
@@ -697,14 +692,14 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
// Regular text.
|
// Regular text.
|
||||||
EscapeSequence::Text(text) => {
|
EscapeSequence::Text(text) => {
|
||||||
let text = self.preprocess(text, &mut cursor_total);
|
let text = self.preprocess(text, &mut cursor_total);
|
||||||
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
|
let text_trimmed = text.trim_end_matches(['\r', '\n']);
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
handle,
|
handle,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
style,
|
style,
|
||||||
&format!("{}{}", self.ansi_style, text_trimmed),
|
&format!("{}{text_trimmed}", self.ansi_style),
|
||||||
true_color,
|
true_color,
|
||||||
colored_output,
|
colored_output,
|
||||||
italics,
|
italics,
|
||||||
@@ -751,10 +746,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
match chunk {
|
match chunk {
|
||||||
// Regular text.
|
// Regular text.
|
||||||
EscapeSequence::Text(text) => {
|
EscapeSequence::Text(text) => {
|
||||||
let text = self.preprocess(
|
let text = self
|
||||||
text.trim_end_matches(|c| c == '\r' || c == '\n'),
|
.preprocess(text.trim_end_matches(['\r', '\n']), &mut cursor_total);
|
||||||
&mut cursor_total,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut max_width = cursor_max - cursor;
|
let mut max_width = cursor_max - cursor;
|
||||||
|
|
||||||
@@ -796,7 +789,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
"{}{}\n{}",
|
"{}{}\n{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
style,
|
style,
|
||||||
&format!("{}{}", self.ansi_style, line_buf),
|
&format!("{}{line_buf}", self.ansi_style),
|
||||||
self.config.true_color,
|
self.config.true_color,
|
||||||
self.config.colored_output,
|
self.config.colored_output,
|
||||||
self.config.use_italic_text,
|
self.config.use_italic_text,
|
||||||
@@ -823,7 +816,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
"{}",
|
"{}",
|
||||||
as_terminal_escaped(
|
as_terminal_escaped(
|
||||||
style,
|
style,
|
||||||
&format!("{}{}", self.ansi_style, line_buf),
|
&format!("{}{line_buf}", self.ansi_style),
|
||||||
self.config.true_color,
|
self.config.true_color,
|
||||||
self.config.colored_output,
|
self.config.colored_output,
|
||||||
self.config.use_italic_text,
|
self.config.use_italic_text,
|
||||||
|
@@ -225,7 +225,7 @@ impl FromStr for StyleComponentList {
|
|||||||
fn from_str(s: &str) -> Result<Self> {
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
Ok(StyleComponentList(
|
Ok(StyleComponentList(
|
||||||
s.split(",")
|
s.split(",")
|
||||||
.map(|s| ComponentAction::extract_from_str(s)) // If the component starts with "-", it's meant to be removed
|
.map(ComponentAction::extract_from_str) // If the component starts with "-", it's meant to be removed
|
||||||
.map(|(a, s)| Ok((a, StyleComponent::from_str(s)?)))
|
.map(|(a, s)| Ok((a, StyleComponent::from_str(s)?)))
|
||||||
.collect::<Result<Vec<(ComponentAction, StyleComponent)>>>()?,
|
.collect::<Result<Vec<(ComponentAction, StyleComponent)>>>()?,
|
||||||
))
|
))
|
||||||
|
@@ -61,7 +61,7 @@ pub struct SyntaxMapping<'a> {
|
|||||||
halt_glob_build: Arc<AtomicBool>,
|
halt_glob_build: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for SyntaxMapping<'a> {
|
impl Drop for SyntaxMapping<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// signal the offload thread to halt early
|
// signal the offload thread to halt early
|
||||||
self.halt_glob_build.store(true, Ordering::Relaxed);
|
self.halt_glob_build.store(true, Ordering::Relaxed);
|
||||||
@@ -153,7 +153,7 @@ impl<'a> SyntaxMapping<'a> {
|
|||||||
if glob.is_match_candidate(&candidate)
|
if glob.is_match_candidate(&candidate)
|
||||||
|| candidate_filename
|
|| candidate_filename
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |filename| glob.is_match_candidate(filename))
|
.is_some_and(|filename| glob.is_match_candidate(filename))
|
||||||
{
|
{
|
||||||
return Some(*syntax);
|
return Some(*syntax);
|
||||||
}
|
}
|
||||||
|
2
src/syntax_mapping/builtins/common/50-dotnet-xml.toml
Normal file
2
src/syntax_mapping/builtins/common/50-dotnet-xml.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[mappings]
|
||||||
|
"XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets"]
|
@@ -1,3 +1,3 @@
|
|||||||
# JSON Lines is a simple variation of JSON #2535
|
# JSON Lines is a simple variation of JSON #2535
|
||||||
[mappings]
|
[mappings]
|
||||||
"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson"]
|
"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson", "*.ndjson"]
|
||||||
|
2
src/syntax_mapping/builtins/common/50-mill.toml
Normal file
2
src/syntax_mapping/builtins/common/50-mill.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[mappings]
|
||||||
|
"Scala" = ["*.mill"]
|
2
src/syntax_mapping/builtins/common/50-nix.toml
Normal file
2
src/syntax_mapping/builtins/common/50-nix.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[mappings]
|
||||||
|
"JSON" = ["flake.lock"]
|
5
src/syntax_mapping/builtins/linux/50-flatpak.toml
Normal file
5
src/syntax_mapping/builtins/linux/50-flatpak.toml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[mappings]
|
||||||
|
"INI" = [
|
||||||
|
"*.flatpakref",
|
||||||
|
"*.flatpakrepo"
|
||||||
|
]
|
6
src/syntax_mapping/builtins/linux/50-paru.toml
Normal file
6
src/syntax_mapping/builtins/linux/50-paru.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# See https://github.com/Morganamilo/paru/blob/master/man/paru.conf.5
|
||||||
|
[mappings]
|
||||||
|
"INI" = [
|
||||||
|
"${PARU_CONF}",
|
||||||
|
"paru.conf",
|
||||||
|
]
|
@@ -1,7 +1,5 @@
|
|||||||
# see `man quadlet`
|
# see `man quadlet`
|
||||||
[mappings]
|
[mappings]
|
||||||
"INI" = [
|
"INI" = [
|
||||||
"**/containers/systemd/*.{container,volume,network,kube,image}",
|
"**/containers/systemd/**/*.{container,volume,network,kube,image}",
|
||||||
"**/containers/systemd/users/*.{container,volume,network,kube,image}",
|
|
||||||
"**/containers/systemd/users/*/*.{container,volume,network,kube,image}",
|
|
||||||
]
|
]
|
||||||
|
3
src/syntax_mapping/builtins/unix-family/50-certbot.toml
Normal file
3
src/syntax_mapping/builtins/unix-family/50-certbot.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# See https://eff-certbot.readthedocs.io/en/stable/using.html#configuration-file
|
||||||
|
[mappings]
|
||||||
|
"INI" = ["/etc/letsencrypt/renewal/*.conf"]
|
@@ -2,4 +2,24 @@
|
|||||||
"Bourne Again Shell (bash)" = [
|
"Bourne Again Shell (bash)" = [
|
||||||
# used by lots of shells
|
# used by lots of shells
|
||||||
"/etc/profile",
|
"/etc/profile",
|
||||||
|
|
||||||
|
"bashrc",
|
||||||
|
"*.bashrc",
|
||||||
|
"bash_profile",
|
||||||
|
"*.bash_profile",
|
||||||
|
"bash_login",
|
||||||
|
"*.bash_login",
|
||||||
|
"bash_logout",
|
||||||
|
"*.bash_logout",
|
||||||
|
|
||||||
|
"zshrc",
|
||||||
|
"*.zshrc",
|
||||||
|
"zprofile",
|
||||||
|
"*.zprofile",
|
||||||
|
"zlogin",
|
||||||
|
"*.zlogin",
|
||||||
|
"zlogout",
|
||||||
|
"*.zlogout",
|
||||||
|
"zshenv",
|
||||||
|
"*.zshenv"
|
||||||
]
|
]
|
||||||
|
15
src/theme.rs
15
src/theme.rs
@@ -10,9 +10,9 @@ pub mod env {
|
|||||||
/// See [`crate::theme::ThemeOptions::theme`].
|
/// See [`crate::theme::ThemeOptions::theme`].
|
||||||
pub const BAT_THEME: &str = "BAT_THEME";
|
pub const BAT_THEME: &str = "BAT_THEME";
|
||||||
/// See [`crate::theme::ThemeOptions::theme_dark`].
|
/// See [`crate::theme::ThemeOptions::theme_dark`].
|
||||||
pub const BAT_THEME_DARK: &str = "BAT_THEME";
|
pub const BAT_THEME_DARK: &str = "BAT_THEME_DARK";
|
||||||
/// See [`crate::theme::ThemeOptions::theme_light`].
|
/// See [`crate::theme::ThemeOptions::theme_light`].
|
||||||
pub const BAT_THEME_LIGHT: &str = "BAT_THEME";
|
pub const BAT_THEME_LIGHT: &str = "BAT_THEME_LIGHT";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Chooses an appropriate theme or falls back to a default theme
|
/// Chooses an appropriate theme or falls back to a default theme
|
||||||
@@ -266,10 +266,10 @@ impl ColorSchemeDetector for TerminalColorSchemeDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn detect(&self) -> Option<ColorScheme> {
|
fn detect(&self) -> Option<ColorScheme> {
|
||||||
use terminal_colorsaurus::{color_scheme, ColorScheme as ColorsaurusScheme, QueryOptions};
|
use terminal_colorsaurus::{theme_mode, QueryOptions, ThemeMode};
|
||||||
match color_scheme(QueryOptions::default()).ok()? {
|
match theme_mode(QueryOptions::default()).ok()? {
|
||||||
ColorsaurusScheme::Dark => Some(ColorScheme::Dark),
|
ThemeMode::Dark => Some(ColorScheme::Dark),
|
||||||
ColorsaurusScheme::Light => Some(ColorScheme::Light),
|
ThemeMode::Light => Some(ColorScheme::Light),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +383,6 @@ mod tests {
|
|||||||
theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
|
theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
|
||||||
theme_dark: Some(ThemeName::Named("Dark Theme".to_string())),
|
theme_dark: Some(ThemeName::Named("Dark Theme".to_string())),
|
||||||
theme_light: Some(ThemeName::Named("Light Theme".to_string())),
|
theme_light: Some(ThemeName::Named("Light Theme".to_string())),
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
] {
|
] {
|
||||||
let detector = ConstantDetector(color_scheme);
|
let detector = ConstantDetector(color_scheme);
|
||||||
@@ -509,7 +508,7 @@ mod tests {
|
|||||||
ThemePreference::Light,
|
ThemePreference::Light,
|
||||||
];
|
];
|
||||||
for pref in prefs {
|
for pref in prefs {
|
||||||
assert_eq!(pref, ThemePreference::new(&pref.to_string()));
|
assert_eq!(pref, ThemePreference::new(pref.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -212,15 +212,15 @@ impl Attributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_with_charset(&mut self, kind: char, set: impl Iterator<Item = char>) -> bool {
|
fn update_with_charset(&mut self, kind: char, set: impl Iterator<Item = char>) -> bool {
|
||||||
self.charset = format!("\x1B{}{}", kind, set.take(1).collect::<String>());
|
self.charset = format!("\x1B{kind}{}", set.take(1).collect::<String>());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_color(color: u16, parameters: &mut dyn Iterator<Item = u16>) -> String {
|
fn parse_color(color: u16, parameters: &mut dyn Iterator<Item = u16>) -> String {
|
||||||
match color % 10 {
|
match color % 10 {
|
||||||
8 => match parameters.next() {
|
8 => match parameters.next() {
|
||||||
Some(5) /* 256-color */ => format!("\x1B[{};5;{}m", color, join(";", 1, parameters)),
|
Some(5) /* 256-color */ => format!("\x1B[{color};5;{}m", join(";", 1, parameters)),
|
||||||
Some(2) /* 24-bit color */ => format!("\x1B[{};2;{}m", color, join(";", 3, parameters)),
|
Some(2) /* 24-bit color */ => format!("\x1B[{color};2;{}m", join(";", 3, parameters)),
|
||||||
Some(c) => format!("\x1B[{color};{c}m"),
|
Some(c) => format!("\x1B[{color};{c}m"),
|
||||||
_ => "".to_owned(),
|
_ => "".to_owned(),
|
||||||
},
|
},
|
||||||
@@ -360,10 +360,10 @@ pub struct EscapeSequenceOffsetsIterator<'a> {
|
|||||||
|
|
||||||
impl<'a> EscapeSequenceOffsetsIterator<'a> {
|
impl<'a> EscapeSequenceOffsetsIterator<'a> {
|
||||||
pub fn new(text: &'a str) -> EscapeSequenceOffsetsIterator<'a> {
|
pub fn new(text: &'a str) -> EscapeSequenceOffsetsIterator<'a> {
|
||||||
return EscapeSequenceOffsetsIterator {
|
EscapeSequenceOffsetsIterator {
|
||||||
text,
|
text,
|
||||||
chars: text.char_indices().peekable(),
|
chars: text.char_indices().peekable(),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes values from the iterator while the predicate returns true.
|
/// Takes values from the iterator while the predicate returns true.
|
||||||
@@ -539,7 +539,7 @@ impl<'a> EscapeSequenceOffsetsIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for EscapeSequenceOffsetsIterator<'a> {
|
impl Iterator for EscapeSequenceOffsetsIterator<'_> {
|
||||||
type Item = EscapeSequenceOffsets;
|
type Item = EscapeSequenceOffsets;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.chars.peek() {
|
match self.chars.peek() {
|
||||||
@@ -564,10 +564,10 @@ pub struct EscapeSequenceIterator<'a> {
|
|||||||
|
|
||||||
impl<'a> EscapeSequenceIterator<'a> {
|
impl<'a> EscapeSequenceIterator<'a> {
|
||||||
pub fn new(text: &'a str) -> EscapeSequenceIterator<'a> {
|
pub fn new(text: &'a str) -> EscapeSequenceIterator<'a> {
|
||||||
return EscapeSequenceIterator {
|
EscapeSequenceIterator {
|
||||||
text,
|
text,
|
||||||
offset_iter: EscapeSequenceOffsetsIterator::new(text),
|
offset_iter: EscapeSequenceOffsetsIterator::new(text),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,10 @@ fn all_themes_are_present() {
|
|||||||
themes,
|
themes,
|
||||||
vec を使用して設定も可能です(`--pager` オプション)
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K472[m[K[36m[K:[m[K環境変数を利用する代わりに、 `[1;33m[Kbat[m[K` の [設定ファイル](#設定ファイル) を使用して設定も可能です(`--pager` オプション)
|
||||||
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K475[m[K[36m[K:[m[K`[1;33m[Kbat[m[K` はページャーの以下のコマンドラインオプション を受け付けるでしょう:
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K475[m[K[36m[K:[m[K`[1;33m[Kbat[m[K` はページャーの以下のコマンドラインオプション を受け付けるでしょう:
|
||||||
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K491[m[K[36m[K:[m[KmacOSでダークモード機能を使用する場合、OSテーマに基づいて異なるテーマを使用するように `[1;33m[Kbat[m[K` を構成することができます。
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K491[m[K[36m[K:[m[KmacOSでダークモード機能を使用する場合、OSテーマに基づいて異なるテーマを使用するように `[1;33m[Kbat[m[K` を構成することができます。
|
||||||
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K496[m[K[36m[K:[m[Kalias cat="[1;33m[Kbat[m[K --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)"
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K496[m[K[36m[K:[m[Kalias cat="[1;33m[Kbat[m[K --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)"
|
||||||
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K501[m[K[36m[K:[m[K`[1;33m[Kbat[m[K` は設定ファイルでカスタマイズすることが可能です。ファイルの場所はOSに依存します。
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K501[m[K[36m[K:[m[K`[1;33m[Kbat[m[K` は設定ファイルでカスタマイズすることが可能です。ファイルの場所はOSに依存します。
|
||||||
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K504[m[K[36m[K:[m[K[1;33m[Kbat[m[K --config-file
|
[35m[Kdoc/README-ja.md[m[K[36m[K:[m[K[32m[K504[m[K[36m[K:[m[K[1;33m[Kbat[m[K --config-file
|
||||||
@@ -721,7 +721,7 @@
|
|||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K108[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`을 [`fzf`](https://github.com/junegunn/fzf)의 프리뷰로 쓸 수 있습니다.
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K108[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`을 [`fzf`](https://github.com/junegunn/fzf)의 프리뷰로 쓸 수 있습니다.
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K109[m[K[36m[K:[m[K이를 위해서는 `[1;33m[Kbat[m[K`의 `--color=always` 옵션으로 항상 컬러 출력이 나오게 해야
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K109[m[K[36m[K:[m[K이를 위해서는 `[1;33m[Kbat[m[K`의 `--color=always` 옵션으로 항상 컬러 출력이 나오게 해야
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K113[m[K[36m[K:[m[Kfzf --preview '[1;33m[Kbat[m[K --color=always --style=numbers --line-range=:500 {}'
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K113[m[K[36m[K:[m[Kfzf --preview '[1;33m[Kbat[m[K --color=always --style=numbers --line-range=:500 {}'
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K120[m[K[36m[K:[m[K`find`의 `-exec` 옵션을 사용하여 모든 검색 결과를 `[1;33m[Kbat[m[K`로 미리 볼 수 있습니다:
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K120[m[K[36m[K:[m[K`find`의 `-exec` 옵션을 사용하여 모든 검색 결과를 `[1;33m[Kbat[m[K`로 미리 볼 수 있습니다:
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K122[m[K[36m[K:[m[Kfind … -exec [1;33m[Kbat[m[K {} +
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K122[m[K[36m[K:[m[Kfind … -exec [1;33m[Kbat[m[K {} +
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K125[m[K[36m[K:[m[K[`fd`](https://github.com/sharkdp/fd)를 사용하는 경우, `-X`/`--exec-[1;33m[Kbat[m[Kch`
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K125[m[K[36m[K:[m[K[`fd`](https://github.com/sharkdp/fd)를 사용하는 경우, `-X`/`--exec-[1;33m[Kbat[m[Kch`
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K128[m[K[36m[K:[m[Kfd … -X [1;33m[Kbat[m[K
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K128[m[K[36m[K:[m[Kfd … -X [1;33m[Kbat[m[K
|
||||||
@@ -765,7 +765,7 @@
|
|||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K271[m[K[36m[K:[m[Kpacman -S [1;33m[Kbat[m[K
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K271[m[K[36m[K:[m[Kpacman -S [1;33m[Kbat[m[K
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K279[m[K[36m[K:[m[K[`[1;33m[Kbat[m[K` 패키지](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506)를
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K279[m[K[36m[K:[m[K[`[1;33m[Kbat[m[K` 패키지](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506)를
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K283[m[K[36m[K:[m[Kdnf install [1;33m[Kbat[m[K
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K283[m[K[36m[K:[m[Kdnf install [1;33m[Kbat[m[K
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K288[m[K[36m[K:[m[Kdev-kit을 통해 [`[1;33m[Kbat[m[K` 패키지](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/[1;33m[Kbat[m[K)를 설치할 수 있습니다:
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K288[m[K[36m[K:[m[Kdev-kit을 통해 [`[1;33m[Kbat[m[K` 패키지](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/[1;33m[Kbat[m[K)를 설치할 수 있습니다:
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K291[m[K[36m[K:[m[Kemerge sys-apps/[1;33m[Kbat[m[K
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K291[m[K[36m[K:[m[Kemerge sys-apps/[1;33m[Kbat[m[K
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K297[m[K[36m[K:[m[K[`[1;33m[Kbat[m[K` 패키지](https://packages.gentoo.org/packages/sys-apps/[1;33m[Kbat[m[K)를 설치할 수
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K297[m[K[36m[K:[m[K[`[1;33m[Kbat[m[K` 패키지](https://packages.gentoo.org/packages/sys-apps/[1;33m[Kbat[m[K)를 설치할 수
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K301[m[K[36m[K:[m[Kemerge sys-apps/[1;33m[Kbat[m[K
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K301[m[K[36m[K:[m[Kemerge sys-apps/[1;33m[Kbat[m[K
|
||||||
@@ -860,7 +860,7 @@
|
|||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K796[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`의 pretty-printing 기능을 라이브러리로 사용하는 애플리케이션을 만들고
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K796[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`의 pretty-printing 기능을 라이브러리로 사용하는 애플리케이션을 만들고
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K797[m[K[36m[K:[m[K싶다면, [API 문서](https://docs.rs/[1;33m[Kbat[m[K/)를 살펴보세요.
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K797[m[K[36m[K:[m[K싶다면, [API 문서](https://docs.rs/[1;33m[Kbat[m[K/)를 살펴보세요.
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K798[m[K[36m[K:[m[K참고로 `[1;33m[Kbat[m[K`에 라이브러리로써 의존한다면, `regex-onig`나 `regex-fancy`를
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K798[m[K[36m[K:[m[K참고로 `[1;33m[Kbat[m[K`에 라이브러리로써 의존한다면, `regex-onig`나 `regex-fancy`를
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K814[m[K[36m[K:[m[K만약 `[1;33m[Kbat[m[K`의 취약점을 발견하였다면, [David Peter](https://david-peter.de/)에게 메일로 연락주시기 바랍니다.
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K814[m[K[36m[K:[m[K만약 `[1;33m[Kbat[m[K`의 취약점을 발견하였다면, [David Peter](https://david-peter.de/)에게 메일로 연락주시기 바랍니다.
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K818[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`은 다음과 같은 목표를 달성하려고 합니다:
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K818[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`은 다음과 같은 목표를 달성하려고 합니다:
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K829[m[K[36m[K:[m[KCopyright (c) 2018-2021 [[1;33m[Kbat[m[K-developers](https://github.com/sharkdp/[1;33m[Kbat[m[K).
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K829[m[K[36m[K:[m[KCopyright (c) 2018-2021 [[1;33m[Kbat[m[K-developers](https://github.com/sharkdp/[1;33m[Kbat[m[K).
|
||||||
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K831[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`는 여러분의 선택에 따라 MIT 라이센스 또는 Apache 라이센스 2.0의 조건에 따라
|
[35m[Kdoc/README-ko.md[m[K[36m[K:[m[K[32m[K831[m[K[36m[K:[m[K`[1;33m[Kbat[m[K`는 여러분의 선택에 따라 MIT 라이센스 또는 Apache 라이센스 2.0의 조건에 따라
|
||||||
@@ -2021,7 +2021,7 @@
|
|||||||
[35m[Ktests/syntax-tests/highlighted/Manpage/bat-0.16.man[m[K[36m[K:[m[K[32m[K243[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;166;226;46m[1;33m[KBAT[m[K[0m[38;2;249;38;114m([0m[38;2;190;132;255m1[0m[38;2;249;38;114m)[0m
|
[35m[Ktests/syntax-tests/highlighted/Manpage/bat-0.16.man[m[K[36m[K:[m[K[32m[K243[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;166;226;46m[1;33m[KBAT[m[K[0m[38;2;249;38;114m([0m[38;2;190;132;255m1[0m[38;2;249;38;114m)[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/Svelte/App.svelte[m[K[36m[K:[m[K[32m[K30[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;246;170;17m// This block is a regression test for a [1;33m[Kbat[m[K panic when a LiveScript syntax definition is missing[0m
|
[35m[Ktests/syntax-tests/highlighted/Svelte/App.svelte[m[K[36m[K:[m[K[32m[K30[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;246;170;17m// This block is a regression test for a [1;33m[Kbat[m[K panic when a LiveScript syntax definition is missing[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/VimL/source.vim[m[K[36m[K:[m[K[32m[K77[m[K[36m[K:[m[K[38;2;117;113;94m" Error case from issue #1604 (https://github.com/sharkdp/[1;33m[Kbat[m[K/issues/1064)[0m
|
[35m[Ktests/syntax-tests/highlighted/VimL/source.vim[m[K[36m[K:[m[K[32m[K77[m[K[36m[K:[m[K[38;2;117;113;94m" Error case from issue #1604 (https://github.com/sharkdp/[1;33m[Kbat[m[K/issues/1064)[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/Java/test.java[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K[38;2;117;113;94m/*[0m[38;2;117;113;94m This Java program was submiited to help [1;33m[Kbat[m[K[0m
|
[35m[Ktests/syntax-tests/highlighted/Java/test.java[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K[38;2;117;113;94m/*[0m[38;2;117;113;94m This Java program was submitted to help [1;33m[Kbat[m[K[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/Sass/example.sass[m[K[36m[K:[m[K[32m[K46[m[K[36m[K:[m[K[38;2;248;248;242m [0m[3;38;2;102;217;239mbackground-image[0m[38;2;255;255;255m:[0m[38;2;248;248;242m [0m[38;2;102;217;239murl[0m[38;2;255;255;255m([0m[38;2;230;219;116m"[0m[38;2;230;219;116mhttps://github.com/sharkdp/[1;33m[Kbat[m[K/raw/master/doc/logo-header.svg[0m[38;2;230;219;116m"[0m[38;2;255;255;255m)[0m
|
[35m[Ktests/syntax-tests/highlighted/Sass/example.sass[m[K[36m[K:[m[K[32m[K46[m[K[36m[K:[m[K[38;2;248;248;242m [0m[3;38;2;102;217;239mbackground-image[0m[38;2;255;255;255m:[0m[38;2;248;248;242m [0m[38;2;102;217;239murl[0m[38;2;255;255;255m([0m[38;2;230;219;116m"[0m[38;2;230;219;116mhttps://github.com/sharkdp/[1;33m[Kbat[m[K/raw/master/doc/logo-header.svg[0m[38;2;230;219;116m"[0m[38;2;255;255;255m)[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/HTML/test.html[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;255;255;255m<[0m[38;2;249;38;114mtitle[0m[38;2;255;255;255m>[0m[38;2;248;248;242m[1;33m[KBat[m[K Syntax Test[0m[38;2;255;255;255m</[0m[38;2;249;38;114mtitle[0m[38;2;255;255;255m>[0m
|
[35m[Ktests/syntax-tests/highlighted/HTML/test.html[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K[38;2;248;248;242m [0m[38;2;255;255;255m<[0m[38;2;249;38;114mtitle[0m[38;2;255;255;255m>[0m[38;2;248;248;242m[1;33m[KBat[m[K Syntax Test[0m[38;2;255;255;255m</[0m[38;2;249;38;114mtitle[0m[38;2;255;255;255m>[0m
|
||||||
[35m[Ktests/syntax-tests/highlighted/Cpp/test.cpp[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K[38;2;117;113;94m/*[0m[38;2;117;113;94m This C program was submitted to help [1;33m[Kbat[m[K[0m
|
[35m[Ktests/syntax-tests/highlighted/Cpp/test.cpp[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K[38;2;117;113;94m/*[0m[38;2;117;113;94m This C program was submitted to help [1;33m[Kbat[m[K[0m
|
||||||
@@ -2119,7 +2119,7 @@
|
|||||||
[35m[Ktests/syntax-tests/source/Svelte/App.svelte[m[K[36m[K:[m[K[32m[K30[m[K[36m[K:[m[K // This block is a regression test for a [1;33m[Kbat[m[K panic when a LiveScript syntax definition is missing
|
[35m[Ktests/syntax-tests/source/Svelte/App.svelte[m[K[36m[K:[m[K[32m[K30[m[K[36m[K:[m[K // This block is a regression test for a [1;33m[Kbat[m[K panic when a LiveScript syntax definition is missing
|
||||||
[35m[Ktests/syntax-tests/source/VimL/source.vim[m[K[36m[K:[m[K[32m[K77[m[K[36m[K:[m[K" Error case from issue #1604 (https://github.com/sharkdp/[1;33m[Kbat[m[K/issues/1064)
|
[35m[Ktests/syntax-tests/source/VimL/source.vim[m[K[36m[K:[m[K[32m[K77[m[K[36m[K:[m[K" Error case from issue #1604 (https://github.com/sharkdp/[1;33m[Kbat[m[K/issues/1064)
|
||||||
[35m[Ktests/syntax-tests/source/Git Config/LICENSE.md[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[KThe `test.gitconfig` file has been added from https://github.com/sharkdp/[1;33m[Kbat[m[K/pull/1336#issuecomment-715905807. Its "free to use".
|
[35m[Ktests/syntax-tests/source/Git Config/LICENSE.md[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[KThe `test.gitconfig` file has been added from https://github.com/sharkdp/[1;33m[Kbat[m[K/pull/1336#issuecomment-715905807. Its "free to use".
|
||||||
[35m[Ktests/syntax-tests/source/Java/test.java[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K/* This Java program was submiited to help [1;33m[Kbat[m[K
|
[35m[Ktests/syntax-tests/source/Java/test.java[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K/* This Java program was submitted to help [1;33m[Kbat[m[K
|
||||||
[35m[Ktests/syntax-tests/source/Sass/example.sass[m[K[36m[K:[m[K[32m[K46[m[K[36m[K:[m[K background-image: url("https://github.com/sharkdp/[1;33m[Kbat[m[K/raw/master/doc/logo-header.svg")
|
[35m[Ktests/syntax-tests/source/Sass/example.sass[m[K[36m[K:[m[K[32m[K46[m[K[36m[K:[m[K background-image: url("https://github.com/sharkdp/[1;33m[Kbat[m[K/raw/master/doc/logo-header.svg")
|
||||||
[35m[Ktests/syntax-tests/source/HTML/test.html[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K <title>[1;33m[KBat[m[K Syntax Test</title>
|
[35m[Ktests/syntax-tests/source/HTML/test.html[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K <title>[1;33m[KBat[m[K Syntax Test</title>
|
||||||
[35m[Ktests/syntax-tests/source/Cpp/test.cpp[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K/* This C program was submitted to help [1;33m[Kbat[m[K
|
[35m[Ktests/syntax-tests/source/Cpp/test.cpp[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K/* This C program was submitted to help [1;33m[Kbat[m[K
|
||||||
@@ -2138,7 +2138,7 @@
|
|||||||
[35m[Ktests/syntax-tests/source/TOML/Cargo.toml[m[K[36m[K:[m[K[32m[K20[m[K[36m[K:[m[K# Feature required for [1;33m[Kbat[m[K the application. Should be disabled when depending on
|
[35m[Ktests/syntax-tests/source/TOML/Cargo.toml[m[K[36m[K:[m[K[32m[K20[m[K[36m[K:[m[K# Feature required for [1;33m[Kbat[m[K the application. Should be disabled when depending on
|
||||||
[35m[Ktests/syntax-tests/source/TOML/Cargo.toml[m[K[36m[K:[m[K[32m[K21[m[K[36m[K:[m[K# [1;33m[Kbat[m[K as a library.
|
[35m[Ktests/syntax-tests/source/TOML/Cargo.toml[m[K[36m[K:[m[K[32m[K21[m[K[36m[K:[m[K# [1;33m[Kbat[m[K as a library.
|
||||||
[35m[Ktests/syntax-tests/source/Erlang/bat_erlang.erl[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[K-module([1;33m[Kbat[m[K_erlang).
|
[35m[Ktests/syntax-tests/source/Erlang/bat_erlang.erl[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[K-module([1;33m[Kbat[m[K_erlang).
|
||||||
[35m[Ktests/syntax-tests/source/Batch/LICENSE.md[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[KThe `build.[1;33m[Kbat[m[K` file has been added from https://github.com/Leandros/ClangOnWindows/blob/master/build.[1;33m[Kbat[m[K under the following license:
|
[35m[Ktests/syntax-tests/source/Batch/LICENSE.md[m[K[36m[K:[m[K[32m[K1[m[K[36m[K:[m[KThe `build.[1;33m[Kbat[m[K` file has been added from https://github.com/Leandros/ClangOnWindows/blob/master/build.[1;33m[Kbat[m[K under the following license:
|
||||||
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K# [1;33m[Kbat[m[K-extras | Copyright (C) 2020 eth-p and contributors | MIT License
|
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K3[m[K[36m[K:[m[K# [1;33m[Kbat[m[K-extras | Copyright (C) 2020 eth-p and contributors | MIT License
|
||||||
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K# Repository: https://github.com/eth-p/[1;33m[Kbat[m[K-extras
|
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K5[m[K[36m[K:[m[K# Repository: https://github.com/eth-p/[1;33m[Kbat[m[K-extras
|
||||||
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K# Issues: https://github.com/eth-p/[1;33m[Kbat[m[K-extras/issues
|
[35m[Ktests/syntax-tests/source/Bash/batgrep.sh[m[K[36m[K:[m[K[32m[K6[m[K[36m[K:[m[K# Issues: https://github.com/eth-p/[1;33m[Kbat[m[K-extras/issues
|
||||||
|
6
tests/examples/multiline.txt
vendored
6
tests/examples/multiline.txt
vendored
@@ -2,3 +2,9 @@ line 1
|
|||||||
line 2
|
line 2
|
||||||
line 3
|
line 3
|
||||||
line 4
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6
|
||||||
|
line 7
|
||||||
|
line 8
|
||||||
|
line 9
|
||||||
|
line 10
|
||||||
|
0
tests/examples/test.A—B가
vendored
Normal file
0
tests/examples/test.A—B가
vendored
Normal file
BIN
tests/examples/test_UTF-16BE-complicated.txt
vendored
Normal file
BIN
tests/examples/test_UTF-16BE-complicated.txt
vendored
Normal file
Binary file not shown.
BIN
tests/examples/test_UTF-16BE.txt
vendored
Normal file
BIN
tests/examples/test_UTF-16BE.txt
vendored
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user