1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-07-13 02:23:26 +01:00

Compare commits

..

2 Commits

Author SHA1 Message Date
2181f72d3d Update changelog 2025-02-09 21:02:50 +02:00
c3e4cf6f45 Make map-syntax target case insensitive 2025-02-09 21:01:25 +02:00
98 changed files with 667 additions and 2478 deletions
.github/workflows
.gitmodulesCHANGELOG.mdCargo.lockCargo.tomlREADME.md
assets
build
doc
examples
src
tests

@ -53,7 +53,7 @@ jobs:
ensure_cargo_fmt:
name: Ensure 'cargo fmt' has been run
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: dtolnay/rust-toolchain@stable
with:
@ -63,7 +63,7 @@ jobs:
min_version:
name: Minimum supported rust version
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
needs: crate_metadata
steps:
- name: Checkout source code
@ -81,7 +81,7 @@ jobs:
license_checks:
name: License checks
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
with:
@ -90,7 +90,7 @@ jobs:
test_with_new_syntaxes_and_themes:
name: Run tests with updated syntaxes and themes
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Git checkout
uses: actions/checkout@v4
@ -119,7 +119,7 @@ jobs:
test_with_system_config:
name: Run tests with system wide configuration
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Git checkout
uses: actions/checkout@v4
@ -135,7 +135,7 @@ jobs:
documentation:
name: Documentation
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Git checkout
uses: actions/checkout@v4
@ -164,18 +164,19 @@ jobs:
fail-fast: false
matrix:
job:
- { target: aarch64-unknown-linux-musl , os: ubuntu-latest, 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-latest, dpkg_arch: 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-2025, }
- { target: i686-unknown-linux-gnu , os: ubuntu-latest, dpkg_arch: i686, use-cross: true }
- { target: i686-unknown-linux-musl , os: ubuntu-latest, dpkg_arch: musl-linux-i686, use-cross: true }
- { target: aarch64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
- { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: arm64, use-cross: true }
- { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, dpkg_arch: armhf, use-cross: true }
- { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, dpkg_arch: musl-linux-armhf, use-cross: true }
- { target: i686-pc-windows-msvc , os: windows-2019, }
- { target: i686-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: i686, use-cross: true }
- { target: i686-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-i686, use-cross: true }
- { target: x86_64-apple-darwin , os: macos-13, }
- { target: aarch64-apple-darwin , os: macos-14, }
- { target: x86_64-pc-windows-msvc , os: windows-2025, }
- { target: x86_64-unknown-linux-gnu , os: ubuntu-latest, dpkg_arch: amd64, use-cross: true }
- { target: x86_64-unknown-linux-musl , os: ubuntu-latest, dpkg_arch: musl-linux-amd64, use-cross: true }
- { target: x86_64-pc-windows-gnu , os: windows-2019, }
- { target: x86_64-pc-windows-msvc , os: windows-2019, }
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: amd64, use-cross: true }
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-amd64, use-cross: true }
env:
BUILD_CMD: cargo
steps:

@ -30,4 +30,4 @@ jobs:
echo "Added lines in CHANGELOG.md:"
echo "$ADDED"
echo "Grepping for PR info (see CONTRIBUTING.md):"
grep "#${PR_NUMBER}\\b.*${PR_SUBMITTER}\\b" <<< "$ADDED"
grep "#${PR_NUMBER}\\b.*@${PR_SUBMITTER}\\b" <<< "$ADDED"

20
.gitmodules vendored

@ -196,7 +196,10 @@
branch = bat-source
[submodule "assets/syntaxes/02_Extra/Lean"]
path = assets/syntaxes/02_Extra/Lean
url = https://github.com/leanprover/vscode-lean4.git
url = https://github.com/leanprover/vscode-lean.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"]
path = assets/syntaxes/02_Extra/Zig
url = https://github.com/ziglang/sublime-zig-language.git
@ -263,18 +266,3 @@
[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

@ -2,52 +2,25 @@
## Features
- 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)
## 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)
## 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)
## 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)
## Themes
- Add Catppuccin, see #3317 (@SchweGELBin)
- Updated Catppuccin, see #3333 (@SchweGELBin)
## `bat` as a library
# v0.25.0

204
Cargo.lock generated

@ -77,9 +77,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.97"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "assert_cmd"
@ -133,17 +133,13 @@ dependencies = [
"grep-cli",
"home",
"indexmap",
"itertools 0.13.0",
"itertools 0.14.0",
"itertools",
"nix",
"nu-ansi-term",
"once_cell",
"path_abs",
"plist",
"predicates",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"semver",
"serde",
@ -152,13 +148,11 @@ dependencies = [
"serde_yaml",
"serial_test",
"shell-words",
"syn",
"syntect",
"tempfile",
"terminal-colorsaurus",
"thiserror 2.0.11",
"toml",
"unicode-segmentation",
"unicode-width 0.1.14",
"wait-timeout",
"walkdir",
@ -489,13 +483,13 @@ dependencies = [
[[package]]
name = "etcetera"
version = "0.10.0"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6"
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
dependencies = [
"cfg-if",
"home",
"windows-sys 0.59.0",
"windows-sys 0.48.0",
]
[[package]]
@ -563,9 +557,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "flate2"
version = "1.1.2"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
dependencies = [
"crc32fast",
"miniz_oxide",
@ -613,7 +607,7 @@ dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -850,9 +844,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.8.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
@ -865,15 +859,6 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.14.0"
@ -976,9 +961,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
dependencies = [
"adler2",
]
@ -1093,7 +1078,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1166,21 +1151,11 @@ dependencies = [
"termtree",
]
[[package]]
name = "prettyplease"
version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
@ -1196,9 +1171,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@ -1344,9 +1319,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "1.0.0"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
@ -1454,9 +1429,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.104"
version = "2.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
dependencies = [
"proc-macro2",
"quote",
@ -1658,43 +1633,39 @@ dependencies = [
[[package]]
name = "toml"
version = "0.9.1"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0207d6ed1852c2a124c1fbec61621acb8330d2bf969a5d0643131e9affd985a5"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.7.0"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_parser"
version = "1.0.0"
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5c1c469eda89749d2230d8156a5969a69ffe0d6d01200581cdc6110674d293e"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b679217f2848de74cabd3e8fc5e6d66f40b7da40f8e1954d92054d9010690fd5"
[[package]]
name = "typenum"
version = "1.17.0"
@ -1707,12 +1678,6 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
version = "0.1.14"
@ -1847,7 +1812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
dependencies = [
"windows-core 0.56.0",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1857,7 +1822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
"windows-core 0.57.0",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1869,7 +1834,7 @@ dependencies = [
"windows-implement 0.56.0",
"windows-interface 0.56.0",
"windows-result",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1881,7 +1846,7 @@ dependencies = [
"windows-implement 0.57.0",
"windows-interface 0.57.0",
"windows-result",
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1934,7 +1899,16 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
@ -1943,7 +1917,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
@ -1952,7 +1926,22 @@ version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
@ -1961,28 +1950,46 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@ -1995,24 +2002,48 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
@ -2021,9 +2052,12 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.7.11"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"

@ -10,7 +10,6 @@ version = "0.25.0"
exclude = ["assets/syntaxes/*", "assets/themes/*"]
build = "build/main.rs"
edition = '2021'
# You are free to bump MSRV as soon as a reason for bumping emerges.
rust-version = "1.74"
[features]
@ -46,7 +45,7 @@ nu-ansi-term = "0.50.0"
ansi_colours = "^1.2"
bincode = "1.0"
console = "0.15.10"
flate2 = "1.1"
flate2 = "1.0"
once_cell = "1.20"
thiserror = "2.0"
wild = { version = "2.2", optional = true }
@ -61,7 +60,7 @@ semver = "1.0"
path_abs = { version = "0.5", default-features = false }
clircle = { version = "0.6.1", default-features = false }
bugreport = { version = "0.5.0", optional = true }
etcetera = { version = "0.10.0", optional = true }
etcetera = { version = "0.8.0", optional = true }
grep-cli = { version = "0.1.11", optional = true }
regex = { version = "1.10.6", optional = true }
walkdir = { version = "2.5", optional = true }
@ -69,8 +68,6 @@ bytesize = { version = "1.3.0" }
encoding_rs = "0.8.35"
execute = { version = "0.2.13", optional = true }
terminal-colorsaurus = "0.4"
unicode-segmentation = "1.12.0"
itertools = "0.13.0"
[dependencies.git2]
version = "0.20"
@ -104,19 +101,15 @@ serde = { version = "1.0", features = ["derive"] }
nix = { version = "0.29", default-features = false, features = ["term"] }
[build-dependencies]
anyhow = "1.0.97"
indexmap = { version = "2.8.0", features = ["serde"] }
anyhow = "1.0.86"
indexmap = { version = "2.3.0", features = ["serde"] }
itertools = "0.14.0"
once_cell = "1.20"
prettyplease = "0.2.35"
proc-macro2 = "1.0.95"
quote = "1.0.40"
regex = "1.10.6"
serde = "1.0"
serde_derive = "1.0"
serde_with = { version = "3.12.0", default-features = false, features = ["macros"] }
syn = { version = "2.0.104", features = ["full"] }
toml = { version = "0.9.1", features = ["preserve_order"] }
toml = { version = "0.8.19", features = ["preserve_order"] }
walkdir = "2.5"
[build-dependencies.clap]

@ -22,22 +22,25 @@
### Sponsors
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>
<p>
<a href="https://www.warp.dev/bat">
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=bat_20231001">
<img src="doc/sponsors/warp-logo.png" width="200" alt="Warp">
<br>
<strong>Warp, the intelligent terminal</strong>
<br>
<sub>Available on MacOS, Linux, Windows</sub>
</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">
<sub>Run commands like a power user with AI and your dev teams</sub>
<br>
<strong>Graphite is the AI developer productivity platform helping<br>teams on GitHub ship higher quality software, faster</strong>
<sup>knowledge in one fast, intuitive terminal. For MacOS or Linux.</sup>
</a>
</p>
### Syntax highlighting
@ -248,13 +251,6 @@ alias -g -- -h='-h 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.
Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`).
@ -427,7 +423,7 @@ take a look at the ["Using `bat` on Windows"](#using-bat-on-windows) section.
#### Prerequisites
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)
You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package.
#### With WinGet
@ -468,25 +464,14 @@ 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
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
cargo install --locked bat
```
Note that additional files like the man page or shell completion
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`.
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`).
Furthermore, shell completions are also available by running:
Shell completions are also available by running:
```bash
bat --completion <shell>
# see --help for supported shells
@ -523,12 +508,12 @@ even when truecolor support is available:
- `ansi` looks decent on any terminal. It uses 3-bit colors: black, red, green,
yellow, blue, magenta, cyan, and white.
- `base16` is designed for [base16](https://github.com/tinted-theming/home) terminal themes. It uses
- `base16` is designed for [base16](https://github.com/chriskempson/base16) terminal themes. It uses
4-bit colors (3-bit colors plus bright variants) in accordance with the
[base16 styling guidelines](https://github.com/tinted-theming/home/blob/main/styling.md).
- `base16-256` is designed for [tinted-shell](https://github.com/tinted-theming/tinted-shell).
[base16 styling guidelines](https://github.com/chriskempson/base16/blob/master/styling.md).
- `base16-256` is designed for [base16-shell](https://github.com/chriskempson/base16-shell).
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 tinted-shell.
because you have a 256-color terminal but are not using base16-shell.
Although these themes are more restricted, they have three advantages over truecolor themes. They:
@ -710,7 +695,7 @@ theme based on the OS theme. The following snippet uses the `default` theme when
and the `GitHub` theme when in the _light mode_.
```bash
alias cat="bat --theme auto:system --theme-dark default --theme-light GitHub"
alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)"
```

Binary file not shown.

@ -180,8 +180,8 @@ This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR
.HP
\fB\-\-theme\-light\fR <theme>
.IP
Sets the theme name for syntax highlighting used when the terminal uses a light background.
To set a default theme, add the \fB\-\-theme-light="..."\fP option to the configuration file or
Sets the theme name for syntax highlighting used when the terminal uses a dark background.
To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP).
This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR.
.HP
@ -203,18 +203,8 @@ Configure which elements (line numbers, file headers, grid borders, Git modifica
\&..) 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').
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="..").
.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,
export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible
values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid,
rule, numbers, snip.
.HP
\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...

@ -21,26 +21,11 @@ index 9c2aa3e..180cbbf 100644
<string>Invalid</string>
<key>scope</key>
- <string>invalid</string>
+ <string>invalid, meta.annotation.error-line</string>
+ <string>invalid, markup.error</string>
<key>settings</key>
<dict>
<key>background</key>
@@ -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>
@@ -1042,7 +1042,7 @@
<key>name</key>
<string>Invalid deprecated</string>
<key>scope</key>

BIN
assets/syntaxes.bin vendored

Binary file not shown.

@ -2,21 +2,20 @@
---
# See http://www.sublimetext.com/docs/3/syntax.html
name: Comma Separated Values
scope: text.csv.comma
file_extensions:
- csv
- tsv
scope: text.csv
variables:
field_separator: (?:,)
field_separator: (?:[,;|\t])
record_separator: (?:$\n?)
contexts:
main:
- match: '^'
push: fields
prototype:
- match: (?={{record_separator}})
pop: true
fields:
- include: record_separator
- match: ''
- match: ""
push:
- field_or_record_separator
- field5
- field_or_record_separator
- field4
- field_or_record_separator
@ -25,55 +24,54 @@ contexts:
- field2
- field_or_record_separator
- field1
record_separator_pop:
- match: (?={{record_separator}})
pop: true
record_separator:
main:
- meta_include_prototype: false
- match: '{{record_separator}}'
scope: punctuation.terminator.record.csv
pop: true
- match: "^"
set: fields
field_or_record_separator:
- meta_include_prototype: false
- include: record_separator_pop
- match: '{{field_separator}}'
- match: "{{record_separator}}"
scope: punctuation.terminator.record.csv
pop: true
- 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
push: double_quoted_string
- include: record_separator_pop
- match: (?={{field_separator}})
- match: (?={{field_separator}}|{{record_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: ''
- match: ""
set:
- meta_content_scope: meta.field-1.csv variable.parameter
- meta_content_scope: meta.field-1.csv support.type
- include: field_contents
field2:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-2.csv support.function
- include: field_contents
field3:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-3.csv constant.numeric
- include: field_contents
field4:
- match: ''
- match: ""
set:
- meta_content_scope: meta.field-4.csv keyword.operator
- include: field_contents
field5:
- match: ''
set:
- meta_content_scope: meta.field-5.csv string.unquoted
- include: field_contents

@ -1,80 +0,0 @@
%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

@ -1,79 +0,0 @@
%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

@ -1,113 +0,0 @@
%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

@ -1,83 +0,0 @@
%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

@ -1,130 +1,125 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/syntax.html
name: Lean 4
# http://www.sublimetext.com/docs/3/syntax.html
name: Lean
file_extensions:
- lean
scope: source.lean4
scope: source.lean
contexts:
main:
- include: comments
- 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+(\{[^}]*\})?'
- match: '\b(?<!\.)(inductive|coinductive|structure|theorem|axiom|axioms|abbreviation|lemma|definition|def|instance|class|constant)\b\s+(\{[^}]*\})?'
captures:
1: keyword.other.definitioncommand.lean4
1: keyword.other.definitioncommand.lean
push:
- meta_scope: meta.definitioncommand.lean4
- match: '(?=\bwith\b|\bextends\b|\bwhere\b|[:\|\(\[\{⦃<>])'
- meta_scope: meta.definitioncommand.lean
- match: '(?=\bwith\b|\bextends\b|[:\|\(\[\{⦃<>])'
pop: true
- include: comments
- include: definitionName
- match: ','
- 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: keyword.other.lean4
- match: ","
- match: \b(Prop|Type|Sort)\b
scope: storage.type.lean
- 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: «
push:
- meta_content_scope: entity.name.lean4
- meta_content_scope: entity.name.lean
- match: »
pop: true
- match: (s!)"
captures:
1: keyword.other.lean4
push:
- meta_scope: string.interpolated.lean4
- match: '"'
pop: true
- match: '(\{)'
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]'
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(?<!\.)(if|then|else)\b
scope: keyword.control.lean
- 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: '''[^\\'']'''
scope: string.quoted.single.lean4
- 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.lean4
captures:
1: constant.character.escape.lean4
0: punctuation.definition.string.begin.lean
push:
- meta_scope: string.quoted.double.lean
- match: '"'
captures:
0: punctuation.definition.string.end.lean
pop: true
- match: '\\[\\"nt'']'
scope: constant.character.escape.lean
- match: '\\x[0-9A-Fa-f][0-9A-Fa-f]'
scope: constant.character.escape.lean
- match: '\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]'
scope: constant.character.escape.lean
- match: '''[^\\'']'''
scope: string.quoted.single.lean
- match: '''(\\(x..|u....|.))'''
scope: string.quoted.single.lean
captures:
1: constant.character.escape.lean
- match: '`+[^\[(]\S+'
scope: entity.name.lean4
- match: '\b([0-9]+|0([xX][0-9a-fA-F]+)|[-]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?)\b'
scope: constant.numeric.lean4
scope: entity.name.lean
- match: '\b([0-9]+|0([xX][0-9a-fA-F]+))\b'
scope: constant.numeric.lean
blockComment:
- match: /-
push:
- meta_scope: comment.block.lean4
- match: '-/'
- meta_scope: comment.block.lean
- match: "-/"
pop: true
- include: scope:source.lean4.markdown
- include: scope:source.lean.markdown
- include: blockComment
comments:
- include: dashComment
- include: docComment
- include: stringBlock
- include: modDocComment
- include: blockComment
dashComment:
- match: '--'
- match: (--)
captures:
0: punctuation.definition.comment.lean
push:
- meta_scope: comment.line.double-dash.lean4
- meta_scope: comment.line.double-dash.lean
- match: $
pop: true
- include: scope:source.lean4.markdown
- include: scope:source.lean.markdown
definitionName:
- match: '\b[^:«»\(\)\{\}[:space:]=→λ∀?][^:«»\(\)\{\}[:space:]]*'
scope: entity.name.function.lean4
scope: entity.name.function.lean
- match: «
push:
- meta_content_scope: entity.name.function.lean4
- meta_content_scope: entity.name.function.lean
- match: »
pop: true
docComment:
- match: /--
push:
- meta_scope: comment.block.documentation.lean4
- match: '-/'
- meta_scope: comment.block.documentation.lean
- match: "-/"
pop: true
- include: scope:source.lean4.markdown
- include: scope:source.lean.markdown
- include: blockComment
modDocComment:
- match: /-!
push:
- meta_scope: comment.block.documentation.lean4
- match: '-/'
- meta_scope: comment.block.documentation.lean
- match: "-/"
pop: true
- include: scope:source.lean4.markdown
- include: scope:source.lean.markdown
- include: blockComment
stringBlock:
- match: /-"
push:
- meta_scope: comment.block.string.lean
- match: '"-/'
pop: true
- include: scope:source.lean.markdown
- include: blockComment

@ -1,42 +0,0 @@
%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

@ -38,21 +38,21 @@ contexts:
scope: markup.underline.link.scheme.log
push: url-host
log_level_lines:
- match: (?=.*{{error}})
- match: ^(?=.*{{error}})
push:
- error_line_meta
- error_line
- main_pop_at_eol
- match: (?=.*{{warning}})
- match: ^(?=.*{{warning}})
push:
- warning_line_meta
- warning_line
- main_pop_at_eol
- match: (?=.*{{info}})
- match: ^(?=.*{{info}})
push:
- info_line_meta
- info_line
- main_pop_at_eol
- match: (?=.*{{debug}})
- match: ^(?=.*{{debug}})
push:
- debug_line_meta
- debug_line
- main_pop_at_eol
log_levels:
- match: '{{error}}'
@ -63,16 +63,16 @@ contexts:
scope: markup.info.log
- match: '{{debug}}'
scope: markup.info.log
error_line_meta:
error_line:
- meta_scope: meta.annotation.error-line.log
- include: immediately_pop
warning_line_meta:
warning_line:
- meta_scope: meta.annotation.warning-line.log
- include: immediately_pop
info_line_meta:
info_line:
- meta_scope: meta.annotation.info-line.log
- include: immediately_pop
debug_line_meta:
debug_line:
- meta_scope: meta.annotation.debug-line.log
- include: immediately_pop
immediately_pop:

@ -8,10 +8,10 @@ scope: text.log.syslog
contexts:
main:
- match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2})
scope: meta.datetime.syslog
scope: meta.datetime.syslog constant.numeric.syslog
captures:
1: meta.date.syslog constant.numeric.syslog
2: meta.time.syslog constant.numeric.syslog
1: meta.date.syslog
2: meta.time.syslog
push: loghost
- match: ^
push: text
@ -31,24 +31,22 @@ contexts:
structured-data:
- match: '\['
scope: punctuation.section.mapping.begin.syslog
push: structured-data-contents
push:
- 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)
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:
- match: $
pop: true

BIN
assets/themes.bin vendored

Binary file not shown.

@ -9,8 +9,6 @@ use anyhow::{anyhow, bail};
use indexmap::IndexMap;
use itertools::Itertools;
use once_cell::sync::Lazy;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens, TokenStreamExt};
use regex::Regex;
use serde_derive::Deserialize;
use serde_with::DeserializeFromStr;
@ -36,14 +34,13 @@ impl FromStr for MappingTarget {
}
}
}
impl ToTokens for MappingTarget {
fn to_tokens(&self, tokens: &mut TokenStream) {
let t = match self {
Self::MapTo(syntax) => quote! { MappingTarget::MapTo(#syntax) },
Self::MapToUnknown => quote! { MappingTarget::MapToUnknown },
Self::MapExtensionToUnknown => quote! { MappingTarget::MapExtensionToUnknown },
};
tokens.append_all(t);
impl MappingTarget {
fn codegen(&self) -> String {
match self {
Self::MapTo(syntax) => format!(r###"MappingTarget::MapTo(r#"{syntax}"#)"###),
Self::MapToUnknown => "MappingTarget::MapToUnknown".into(),
Self::MapExtensionToUnknown => "MappingTarget::MapExtensionToUnknown".into(),
}
}
}
@ -119,17 +116,22 @@ impl FromStr for Matcher {
Ok(Self(non_empty_segments))
}
}
impl ToTokens for Matcher {
fn to_tokens(&self, tokens: &mut TokenStream) {
let t = match self.0.as_slice() {
[] => unreachable!("0-length matcher should never be created"),
[MatcherSegment::Text(text)] => {
quote! { Lazy::new(|| Some(build_matcher_fixed(#text))) }
impl Matcher {
fn codegen(&self) -> String {
match self.0.len() {
0 => unreachable!("0-length matcher should never be created"),
// if-let guard would be ideal here
// see: https://github.com/rust-lang/rust/issues/51114
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
segs @ [_, ..] => quote! { Lazy::new(|| build_matcher_dynamic(&[ #(#segs),* ])) },
};
tokens.append_all(t);
_ => {
let segs = self.0.iter().map(MatcherSegment::codegen).join(", ");
format!(r###"Lazy::new(|| build_matcher_dynamic(&[{segs}]))"###)
}
}
}
}
@ -141,15 +143,6 @@ enum MatcherSegment {
Text(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)]
impl MatcherSegment {
fn is_text(&self) -> bool {
@ -170,6 +163,12 @@ impl MatcherSegment {
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/.
@ -195,19 +194,22 @@ impl MappingDefModel {
#[derive(Clone, Debug)]
struct MappingList(Vec<(Matcher, MappingTarget)>);
impl ToTokens for MappingList {
fn to_tokens(&self, tokens: &mut TokenStream) {
let len = self.0.len();
let array_items = self
impl MappingList {
fn codegen(&self) -> String {
let array_items: Vec<_> = self
.0
.iter()
.map(|(matcher, target)| quote! { (#matcher, #target) });
.map(|(matcher, target)| {
format!("({m}, {t})", m = matcher.codegen(), t = target.codegen())
})
.collect();
let len = array_items.len();
let t = quote! {
/// Generated by build script from /src/syntax_mapping/builtins/.
pub(crate) static BUILTIN_MAPPINGS: [(Lazy<Option<GlobMatcher>>, MappingTarget); #len] = [#(#array_items),*];
};
tokens.append_all(t);
format!(
"/// Generated by build script from /src/syntax_mapping/builtins/.\n\
pub(crate) static BUILTIN_MAPPINGS: [(Lazy<Option<GlobMatcher>>, MappingTarget); {len}] = [\n{items}\n];",
items = array_items.join(",\n")
)
}
}
@ -289,15 +291,10 @@ pub fn build_static_mappings() -> anyhow::Result<()> {
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"))?)
.join("codegen_static_syntax_mappings.rs");
fs::write(codegen_path, rs_src_pretty)?;
fs::write(codegen_path, mappings.codegen())?;
Ok(())
}

@ -461,11 +461,11 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
- `ansi`는 어떤 터미널에서도 무난하게 보입니다. 이는 3비트 색상을 사용합니다:
검정, 빨강, 녹색, 노랑, 파랑, 마젠타, 시안, 하양.
- `base16`은 [base16](https://github.com/tinted-theming/home) 터미널 테마를 위해
- `base16`은 [base16](https://github.com/chriskempson/base16) 터미널 테마를 위해
디자인되었습니다.
이는 [base16 스타일 가이드라인](https://github.com/tinted-theming/home/blob/main/styling.md)에
이는 [base16 스타일 가이드라인](https://github.com/chriskempson/base16/blob/master/styling.md)에
따라 4비트 색상(3비트 색상에 밝은 변형 추가)을 사용합니다.
- `base16-256`는 [base16-shell](https://github.com/tinted-theming/base16-shell)을
- `base16-256`는 [base16-shell](https://github.com/chriskempson/base16-shell)을
위해 디자인되었습니다.
이는 16부터 21의 일부 밝은 색상을 8비트 색상으로 대치합니다.
단지 256-색상 터미널을 쓰지만 base16-shell을 쓰지 않는다고 해서 이것을

@ -401,8 +401,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) 主题:
- `ansi` 适应于大部分终端。它使用 3-bit 色彩:黑红绿黄蓝洋红靛青白。
- `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/tinted-theming/base16-shell) 设计。它把部分亮色替换为 8-bit 色彩。请不要直接使用该主题除非你清楚你的256色终端是否使用 base16-shell。
- `base16`专为 [base16](https://github.com/chriskempson/base16) 终端设计。它使用 4-bit 色彩(带有亮度的 3-bit 色彩)。根据 [base16 styling guidelines](https://github.com/chriskempson/base16/blob/master/styling.md) 制作。
- `base16-25`专为 [base16-shell](https://github.com/chriskempson/base16-shell) 设计。它把部分亮色替换为 8-bit 色彩。请不要直接使用该主题除非你清楚你的256色终端是否使用 base16-shell。
尽管这些主题具有诸多限制,但具有一些 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
`bat` binary.
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.
5. Use `bat --list-languages` to check if the new languages are available.
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
* `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.
* `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean4/blob/master/vscode-lean4/syntaxes/lean4.json via conversion.
* `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean/blob/master/syntaxes/lean.json via conversion.

Binary file not shown.

Before

(image error) Size: 28 KiB

@ -0,0 +1,11 @@
<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>

After

(image error) Size: 3.4 KiB

@ -1,6 +1,4 @@
use bat::{
assets::HighlightingAssets, config::Config, controller::Controller, output::OutputHandle, Input,
};
use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input};
fn main() {
let mut buffer = String::new();
@ -12,10 +10,7 @@ fn main() {
let controller = Controller::new(&config, &assets);
let input = Input::from_file(file!());
controller
.run(
vec![input.into()],
Some(OutputHandle::FmtWrite(&mut buffer)),
)
.run(vec![input.into()], Some(&mut buffer))
.unwrap();
println!("{buffer}");

@ -163,7 +163,7 @@ impl HighlightingAssets {
if let Some(MappingTarget::MapTo(syntax_name)) = syntax_match {
return self
.find_syntax_by_name(syntax_name)?
.find_syntax_by_token(syntax_name)?
.ok_or_else(|| Error::UnknownSyntax(syntax_name.to_owned()));
}
@ -259,6 +259,13 @@ impl HighlightingAssets {
.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(
&self,
file_name: &OsStr,
@ -298,11 +305,7 @@ impl HighlightingAssets {
let syntax_set = self.get_syntax_set()?;
Ok(String::from_utf8(reader.first_line.clone())
.ok()
.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)
})
.and_then(|l| syntax_set.find_syntax_by_first_line(&l))
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
}
}
@ -537,41 +540,6 @@ 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]
fn syntax_detection_with_custom_mapping() {
let mut test = SyntaxDetectionTest::new();

@ -95,9 +95,6 @@ fn include_license_in_acknowledgments(license_text: &str) -> bool {
// Apache 2.0
"Apache License Version 2.0, January 2004 http://www.apache.org/licenses/",
"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)

@ -124,10 +124,7 @@ impl App {
// 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") {
PagingMode::Never
} 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")
{
} else if inputs.iter().any(Input::is_stdin) {
// 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
// terminal.

@ -16,7 +16,6 @@ use std::io::{BufReader, Write};
use std::path::Path;
use std::process;
use bat::output::{OutputHandle, OutputType};
use bat::theme::DetectColorScheme;
use nu_ansi_term::Color::Green;
use nu_ansi_term::Style;
@ -206,9 +205,8 @@ pub fn list_themes(
config.language = Some("Rust");
config.style_components = StyleComponents(style);
let mut output_type =
OutputType::from_mode(config.paging_mode, config.wrapping_mode, config.pager)?;
let mut writer = output_type.handle()?;
let stdout = io::stdout();
let mut stdout = stdout.lock();
let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
for theme in assets.themes() {
@ -223,29 +221,26 @@ pub fn list_themes(
};
if config.colored_output {
writeln!(
writer,
stdout,
"Theme: {}{}\n",
Style::new().bold().paint(theme.to_string()),
default_theme_info
)?;
config.theme = theme.to_string();
Controller::new(&config, &assets)
.run(
vec![theme_preview_file()],
Some(OutputHandle::IoWrite(&mut writer)),
)
.run(vec![theme_preview_file()], None)
.ok();
writeln!(writer)?;
writeln!(stdout)?;
} else if config.loop_through {
writeln!(writer, "{theme}")?;
writeln!(stdout, "{theme}")?;
} else {
writeln!(writer, "{theme}{default_theme_info}")?;
writeln!(stdout, "{theme}{default_theme_info}")?;
}
}
if config.colored_output {
writeln!(
writer,
stdout,
"Further themes can be installed to '{}', \
and are added to the cache with `bat cache --build`. \
For more information, see:\n\n \

@ -119,25 +119,17 @@ pub fn get_pager_executable(config_pager: Option<&str>) -> Option<String> {
#[test]
fn default_config_should_include_all_lines() {
use crate::line_range::MaxBufferedLineNumber;
use crate::line_range::RangeCheckResult;
assert_eq!(
LineRanges::default().check(17, MaxBufferedLineNumber::Tentative(17)),
RangeCheckResult::InRange
);
assert_eq!(LineRanges::default().check(17), RangeCheckResult::InRange);
}
#[test]
fn default_config_should_highlight_no_lines() {
use crate::line_range::MaxBufferedLineNumber;
use crate::line_range::RangeCheckResult;
assert_ne!(
Config::default()
.highlighted_lines
.0
.check(17, MaxBufferedLineNumber::Tentative(17)),
Config::default().highlighted_lines.0.check(17),
RangeCheckResult::InRange
);
}

@ -1,3 +1,5 @@
use std::io::{self, BufRead, Write};
use crate::assets::HighlightingAssets;
use crate::config::{Config, VisibleLines};
#[cfg(feature = "git")]
@ -8,14 +10,11 @@ use crate::input::{Input, InputReader, OpenedInput};
use crate::lessopen::LessOpenPreprocessor;
#[cfg(feature = "git")]
use crate::line_range::LineRange;
use crate::line_range::{LineRanges, MaxBufferedLineNumber, RangeCheckResult};
use crate::output::{OutputHandle, OutputType};
use crate::line_range::{LineRanges, RangeCheckResult};
use crate::output::OutputType;
#[cfg(feature = "paging")]
use crate::paging::PagingMode;
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
use std::collections::VecDeque;
use std::io::{self, BufRead, Write};
use std::mem;
use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter};
use clircle::{Clircle, Identifier};
@ -36,14 +35,18 @@ impl Controller<'_> {
}
}
pub fn run(&self, inputs: Vec<Input>, output_handle: Option<OutputHandle<'_>>) -> Result<bool> {
self.run_with_error_handler(inputs, output_handle, default_error_handler)
pub fn run(
&self,
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(
&self,
inputs: Vec<Input>,
output_handle: Option<OutputHandle<'_>>,
output_buffer: Option<&mut dyn std::fmt::Write>,
mut handle_error: impl FnMut(&Error, &mut dyn Write),
) -> Result<bool> {
let mut output_type;
@ -85,9 +88,8 @@ impl Controller<'_> {
clircle::Identifier::stdout()
};
let mut writer = match output_handle {
Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w),
Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w),
let mut writer = match output_buffer {
Some(buf) => OutputHandle::FmtWrite(buf),
None => OutputHandle::IoWrite(output_type.handle()?),
};
let mut no_errors: bool = true;
@ -239,63 +241,20 @@ impl Controller<'_> {
reader: &mut InputReader,
line_ranges: &LineRanges,
) -> Result<()> {
let mut current_line_buffer: Vec<u8> = Vec::new();
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 line_buffer = Vec::new();
let mut line_number: usize = 1;
let mut reached_eof: bool = false;
let mut first_range: bool = true;
let mut mid_range: bool = false;
let style_snip = self.config.style_components.snip();
loop {
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) {
while reader.read_line(&mut line_buffer)? {
match line_ranges.check(line_number) {
RangeCheckResult::BeforeOrBetweenRanges => {
// Call the printer in case we need to call the syntax highlighter
// for this line. However, set `out_of_range` to `true`.
printer.print_line(true, writer, line_nr, &line, max_buffered_line_number)?;
printer.print_line(true, writer, line_number, &line_buffer)?;
mid_range = false;
}
@ -310,12 +269,15 @@ impl Controller<'_> {
}
}
printer.print_line(false, writer, line_nr, &line, max_buffered_line_number)?;
printer.print_line(false, writer, line_number, &line_buffer)?;
}
RangeCheckResult::AfterLastRange => {
break;
}
}
line_number += 1;
line_buffer.clear();
}
Ok(())
}

@ -67,13 +67,7 @@ pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
.ok();
}
_ => {
writeln!(
&mut std::io::stderr().lock(),
"{}: {}",
Red.paint("[bat error]"),
error
)
.ok();
writeln!(output, "{}: {}", Red.paint("[bat error]"), error).ok();
}
};
}

@ -38,7 +38,7 @@ mod less;
mod lessopen;
pub mod line_range;
pub(crate) mod nonprintable_notation;
pub mod output;
mod output;
#[cfg(feature = "paging")]
mod pager;
#[cfg(feature = "paging")]

@ -1,26 +1,16 @@
use crate::error::*;
use itertools::{Itertools, MinMaxResult};
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone)]
pub struct LineRange {
lower: RangeBound,
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),
lower: usize,
upper: usize,
}
impl Default for LineRange {
fn default() -> LineRange {
LineRange {
lower: RangeBound::Absolute(usize::MIN),
upper: RangeBound::Absolute(usize::MAX),
lower: usize::MIN,
upper: usize::MAX,
}
}
}
@ -28,8 +18,8 @@ impl Default for LineRange {
impl LineRange {
pub fn new(from: usize, to: usize) -> Self {
LineRange {
lower: RangeBound::Absolute(from),
upper: RangeBound::Absolute(to),
lower: from,
upper: to,
}
}
@ -39,47 +29,31 @@ impl LineRange {
fn parse_range(range_raw: &str) -> Result<LineRange> {
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 first_byte == b':' {
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);
}
if range_raw.bytes().next().ok_or("Empty line range")? == b':' {
new_range.upper = range_raw[1..].parse()?;
return Ok(new_range);
} else if range_raw.bytes().last().ok_or("Empty line range")? == b':' {
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);
}
new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
return Ok(new_range);
}
let line_numbers: Vec<&str> = range_raw.split(':').collect();
match line_numbers.len() {
1 => {
new_range.lower = RangeBound::Absolute(line_numbers[0].parse()?);
new_range.lower = line_numbers[0].parse()?;
new_range.upper = new_range.lower;
Ok(new_range)
}
2 => {
let mut lower_absolute_bound: usize = line_numbers[0].parse()?;
new_range.lower = line_numbers[0].parse()?;
let first_byte = line_numbers[1].bytes().next();
let upper_absolute_bound = if first_byte == Some(b'+') {
new_range.upper = if first_byte == Some(b'+') {
let more_lines = &line_numbers[1][1..]
.parse()
.map_err(|_| "Invalid character after +")?;
lower_absolute_bound.saturating_add(*more_lines)
new_range.lower.saturating_add(*more_lines)
} else if first_byte == Some(b'-') {
// this will prevent values like "-+5" even though "+5" is valid integer
if line_numbers[1][1..].bytes().next() == Some(b'+') {
@ -88,14 +62,13 @@ impl LineRange {
let prior_lines = &line_numbers[1][1..]
.parse()
.map_err(|_| "Invalid character after -")?;
let prev_lower = lower_absolute_bound;
lower_absolute_bound = lower_absolute_bound.saturating_sub(*prior_lines);
let prev_lower = new_range.lower;
new_range.lower = new_range.lower.saturating_sub(*prior_lines);
prev_lower
} else {
line_numbers[1].parse()?
};
new_range.lower = RangeBound::Absolute(lower_absolute_bound);
new_range.upper = RangeBound::Absolute(upper_absolute_bound);
Ok(new_range)
}
_ => Err(
@ -105,107 +78,37 @@ impl LineRange {
}
}
/// Checks if a line number is inside the range.
/// 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
}
}
pub(crate) fn is_inside(&self, line: usize) -> bool {
line >= self.lower && line <= self.upper
}
}
#[test]
fn test_parse_full() {
let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(40), range.lower);
assert_eq!(RangeBound::Absolute(50), range.upper);
assert_eq!(40, range.lower);
assert_eq!(50, range.upper);
}
#[test]
fn test_parse_partial_min() {
let range = LineRange::from(":50").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(usize::MIN), range.lower);
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);
assert_eq!(usize::MIN, range.lower);
assert_eq!(50, range.upper);
}
#[test]
fn test_parse_partial_max() {
let range = LineRange::from("40:").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(40), range.lower);
assert_eq!(RangeBound::Absolute(usize::MAX), range.upper);
assert_eq!(40, range.lower);
assert_eq!(usize::MAX, range.upper);
}
#[test]
fn test_parse_single() {
let range = LineRange::from("40").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(40), range.lower);
assert_eq!(RangeBound::Absolute(40), range.upper);
assert_eq!(40, range.lower);
assert_eq!(40, range.upper);
}
#[test]
@ -214,8 +117,6 @@ fn test_parse_fail() {
assert!(range.is_err());
let range = LineRange::from("40::80");
assert!(range.is_err());
let range = LineRange::from("-2:5");
assert!(range.is_err());
let range = LineRange::from(":40:");
assert!(range.is_err());
}
@ -223,15 +124,15 @@ fn test_parse_fail() {
#[test]
fn test_parse_plus() {
let range = LineRange::from("40:+10").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(40), range.lower);
assert_eq!(RangeBound::Absolute(50), range.upper);
assert_eq!(40, range.lower);
assert_eq!(50, range.upper);
}
#[test]
fn test_parse_plus_overflow() {
let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(usize::MAX), range.lower);
assert_eq!(RangeBound::Absolute(usize::MAX), range.upper);
assert_eq!(usize::MAX, range.lower);
assert_eq!(usize::MAX, range.upper);
}
#[test]
@ -247,21 +148,21 @@ fn test_parse_plus_fail() {
#[test]
fn test_parse_minus_success() {
let range = LineRange::from("40:-10").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(30), range.lower);
assert_eq!(RangeBound::Absolute(40), range.upper);
assert_eq!(30, range.lower);
assert_eq!(40, range.upper);
}
#[test]
fn test_parse_minus_edge_cases_success() {
let range = LineRange::from("5:-4").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(1), range.lower);
assert_eq!(RangeBound::Absolute(5), range.upper);
assert_eq!(1, range.lower);
assert_eq!(5, range.upper);
let range = LineRange::from("5:-5").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(0), range.lower);
assert_eq!(RangeBound::Absolute(5), range.upper);
assert_eq!(0, range.lower);
assert_eq!(5, range.upper);
let range = LineRange::from("5:-100").expect("Shouldn't fail on test!");
assert_eq!(RangeBound::Absolute(0), range.lower);
assert_eq!(RangeBound::Absolute(5), range.upper);
assert_eq!(0, range.lower);
assert_eq!(5, range.upper);
}
#[test]
@ -286,24 +187,10 @@ pub enum RangeCheckResult {
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)]
pub struct LineRanges {
ranges: Vec<LineRange>,
// 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,
largest_upper_bound: usize,
}
impl LineRanges {
@ -316,62 +203,22 @@ impl LineRanges {
}
pub fn from(ranges: Vec<LineRange>) -> LineRanges {
let largest_absolute_upper_bound = ranges
.iter()
.filter_map(|r| match r.upper {
RangeBound::Absolute(upper) => Some(upper),
_ => None,
})
.max()
.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),
};
let largest_upper_bound = ranges.iter().map(|r| r.upper).max().unwrap_or(usize::MAX);
LineRanges {
ranges,
largest_absolute_upper_bound,
smallest_offset_from_end,
largest_offset_from_end,
largest_upper_bound,
}
}
pub(crate) fn check(
&self,
line: usize,
max_buffered_line_number: MaxBufferedLineNumber,
) -> RangeCheckResult {
if self
.ranges
.iter()
.any(|r| r.is_inside(line, max_buffered_line_number))
{
pub(crate) fn check(&self, line: usize) -> RangeCheckResult {
if self.ranges.iter().any(|r| r.is_inside(line)) {
RangeCheckResult::InRange
} 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 {
} else if line < self.largest_upper_bound {
RangeCheckResult::BeforeOrBetweenRanges
} else {
RangeCheckResult::AfterLastRange
}
}
pub(crate) fn largest_offset_from_end(&self) -> usize {
self.largest_offset_from_end
}
}
impl Default for LineRanges {
@ -398,292 +245,54 @@ fn ranges(rs: &[&str]) -> LineRanges {
fn test_ranges_simple() {
let ranges = ranges(&["3:8"]);
assert_eq!(
RangeCheckResult::BeforeOrBetweenRanges,
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))
);
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
}
#[test]
fn test_ranges_advanced() {
let ranges = ranges(&["3:8", "11:20", "25:30"]);
assert_eq!(
RangeCheckResult::BeforeOrBetweenRanges,
ranges.check(2, MaxBufferedLineNumber::Tentative(2))
);
assert_eq!(
RangeCheckResult::InRange,
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))
);
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(9));
assert_eq!(RangeCheckResult::InRange, ranges.check(11));
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(22));
assert_eq!(RangeCheckResult::InRange, ranges.check(28));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(31));
}
#[test]
fn test_ranges_open_low() {
let ranges = ranges(&["3:8", ":5"]);
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(7, MaxBufferedLineNumber::Tentative(7))
);
assert_eq!(
RangeCheckResult::AfterLastRange,
ranges.check(9, MaxBufferedLineNumber::Tentative(9))
);
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
assert_eq!(RangeCheckResult::InRange, ranges.check(7));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
}
#[test]
fn test_ranges_open_high() {
let ranges = ranges(&["3:", "2:5"]);
assert_eq!(
RangeCheckResult::BeforeOrBetweenRanges,
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
);
assert_eq!(
RangeCheckResult::BeforeOrBetweenRanges,
ranges.check(1, MaxBufferedLineNumber::Final(10))
);
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))
);
assert_eq!(RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1));
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::InRange, ranges.check(9));
}
#[test]
fn test_ranges_all() {
let ranges = LineRanges::all();
assert_eq!(
RangeCheckResult::InRange,
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
);
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
}
#[test]
fn test_ranges_none() {
let ranges = LineRanges::none();
assert_ne!(
RangeCheckResult::InRange,
ranges.check(1, MaxBufferedLineNumber::Tentative(1))
);
assert_ne!(RangeCheckResult::InRange, ranges.check(1));
}

@ -1,4 +1,3 @@
use std::fmt;
use std::io::{self, Write};
#[cfg(feature = "paging")]
use std::process::Child;
@ -163,17 +162,3 @@ 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,7 +10,6 @@ use crate::{
error::Result,
input,
line_range::{HighlightedLineRanges, LineRange, LineRanges},
output::OutputHandle,
style::StyleComponent,
StripAnsiMode, SyntaxMapping, WrappingMode,
};
@ -326,10 +325,7 @@ impl<'a> PrettyPrinter<'a> {
// If writer is provided, pass it to the controller, otherwise pass None
if let Some(mut w) = writer {
controller.run(
inputs.into_iter().map(|i| i.into()).collect(),
Some(OutputHandle::FmtWrite(&mut w)),
)
controller.run(inputs.into_iter().map(|i| i.into()).collect(), Some(&mut w))
} else {
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
}

@ -1,3 +1,5 @@
use std::fmt;
use std::io;
use std::vec::Vec;
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
@ -15,7 +17,6 @@ use content_inspector::ContentType;
use encoding_rs::{UTF_16BE, UTF_16LE};
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthChar;
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
@ -27,8 +28,7 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}
use crate::diff::LineChanges;
use crate::error::*;
use crate::input::OpenedInput;
use crate::line_range::{MaxBufferedLineNumber, RangeCheckResult};
use crate::output::OutputHandle;
use crate::line_range::RangeCheckResult;
use crate::preprocessor::strip_ansi;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
@ -68,6 +68,20 @@ const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting:
font_style: FontStyle::empty(),
};
pub enum OutputHandle<'a> {
IoWrite(&'a mut dyn io::Write),
FmtWrite(&'a mut dyn fmt::Write),
}
impl OutputHandle<'_> {
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 {
fn print_header(
&mut self,
@ -85,7 +99,6 @@ pub(crate) trait Printer {
handle: &mut OutputHandle,
line_number: usize,
line_buffer: &[u8],
max_buffered_line_number: MaxBufferedLineNumber,
) -> Result<()>;
}
@ -127,7 +140,6 @@ impl Printer for SimplePrinter<'_> {
handle: &mut OutputHandle,
_line_number: usize,
line_buffer: &[u8],
_max_buffered_line_number: MaxBufferedLineNumber,
) -> Result<()> {
// Skip squeezed lines.
if let Some(squeeze_limit) = self.config.squeeze_lines {
@ -391,18 +403,14 @@ impl<'a> InteractivePrinter<'a> {
handle: &mut OutputHandle,
content: &str,
) -> Result<()> {
let mut content = content;
let content_width = self.config.term_width - self.get_header_component_indent_length();
if content.chars().count() <= content_width {
return self.print_header_component_with_indent(handle, content);
while content.len() > content_width {
let (content_line, remaining) = content.split_at(content_width);
self.print_header_component_with_indent(handle, content_line)?;
content = remaining;
}
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.iter().cloned().collect();
}
self.print_header_component_with_indent(handle, content_graphemes.join("").as_str())
self.print_header_component_with_indent(handle, content)
}
fn highlight_regions_for_line<'b>(
@ -591,7 +599,6 @@ impl Printer for InteractivePrinter<'_> {
handle: &mut OutputHandle,
line_number: usize,
line_buffer: &[u8],
max_buffered_line_number: MaxBufferedLineNumber,
) -> Result<()> {
let line = if self.config.show_nonprintable {
replace_nonprintable(
@ -653,12 +660,8 @@ impl Printer for InteractivePrinter<'_> {
let mut panel_wrap: Option<String> = None;
// Line highlighting
let highlight_this_line = self
.config
.highlighted_lines
.0
.check(line_number, max_buffered_line_number)
== RangeCheckResult::InRange;
let highlight_this_line =
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
if highlight_this_line && self.config.theme == "ansi" {
self.ansi_style.update(ANSI_UNDERLINE_ENABLE);

@ -1,2 +0,0 @@
[mappings]
"XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets"]

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

@ -1,2 +0,0 @@
[mappings]
"Scala" = ["*.mill"]

@ -1,5 +1,7 @@
# see `man quadlet`
[mappings]
"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}",
]

@ -1,3 +0,0 @@
# See https://eff-certbot.readthedocs.io/en/stable/using.html#configuration-file
[mappings]
"INI" = ["/etc/letsencrypt/renewal/*.conf"]

@ -2,24 +2,4 @@
"Bourne Again Shell (bash)" = [
# used by lots of shells
"/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"
]

@ -14,10 +14,6 @@ fn all_themes_are_present() {
themes,
vec![
"1337",
"Catppuccin Frappe",
"Catppuccin Latte",
"Catppuccin Macchiato",
"Catppuccin Mocha",
"Coldark-Cold",
"Coldark-Dark",
"DarkNeon",

@ -176,46 +176,6 @@ fn line_range_2_3() {
.stdout("line 2\nline 3\n");
}
#[test]
fn line_range_up_to_2_from_back() {
bat()
.arg("multiline.txt")
.arg("--line-range=:-2")
.assert()
.success()
.stdout("line 1\nline 2\n");
}
#[test]
fn line_range_up_to_2_from_back_single_line_is_empty() {
bat()
.arg("single-line.txt")
.arg("--line-range=:-2")
.assert()
.success()
.stdout("");
}
#[test]
fn line_range_from_back_last_two() {
bat()
.arg("multiline.txt")
.arg("--line-range=-2:")
.assert()
.success()
.stdout("line 3\nline 4\n");
}
#[test]
fn line_range_from_back_last_two_single_line() {
bat()
.arg("single-line.txt")
.arg("--line-range=-2:")
.assert()
.success()
.stdout("Single Line");
}
#[test]
fn line_range_first_two() {
bat()
@ -450,16 +410,6 @@ fn stdin_to_stdout_cycle() -> io::Result<()> {
Ok(())
}
#[cfg(unix)]
#[test]
fn bat_error_to_stderr() {
bat()
.arg("/tmp")
.assert()
.failure()
.stderr(predicate::str::contains("[bat error]"));
}
#[cfg(unix)]
#[test]
fn no_args_doesnt_break() {
@ -1650,17 +1600,6 @@ oken
.stderr("");
}
#[test]
fn header_narrow_terminal_with_multibyte_chars() {
bat()
.arg("--terminal-width=30")
.arg("--decorations=always")
.arg("test.A—B가")
.assert()
.success()
.stderr("");
}
#[test]
#[cfg(feature = "git")] // Expected output assumes git is enabled
fn header_default() {
@ -2812,6 +2751,27 @@ fn highlighting_independant_from_map_syntax_case() {
.stderr("");
}
#[test]
fn map_syntax_target_syntax_case_insensitive() {
let expected = bat()
.arg("-f")
.arg("--map-syntax=*.config:json")
.arg("map-syntax_case.Config")
.assert()
.get_output()
.stdout
.clone();
bat()
.arg("-f")
.arg("--map-syntax=*.config:json")
.arg("map-syntax_case.Config")
.assert()
.success()
.stdout(expected)
.stderr("");
}
#[test]
fn strip_ansi_always_strips_ansi() {
bat()

@ -12,15 +12,13 @@ def compare_highlighted_versions(root_old, root_new):
print(" -", root_old)
print(" -", root_new)
has_changes = False
# Used to check for newly added files that don't have a test
unknown_files = {strip_root(p) for p in glob.glob(path.join(root_new, "*", "*"))}
for path_old in glob.glob(path.join(root_old, "*", "*")):
rel_path = strip_root(path_old)
unknown_files.discard(rel_path)
path_new = path.join(root_new, rel_path)
filename = path.basename(path_old)
dirname = path.basename(path.dirname(path_old))
print("\n========== {}".format(rel_path))
path_new = path.join(root_new, dirname, filename)
print("\n========== {}/{}".format(dirname, filename))
with open(path_old) as file_old:
lines_old = file_old.readlines()
@ -41,21 +39,11 @@ def compare_highlighted_versions(root_old, root_new):
has_changes = True
else:
print("No changes")
for f in unknown_files:
print("\n========== {}: No fixture for this language, run update.sh".format(f))
has_changes = True
print()
return has_changes
def strip_root(p: str) -> str:
filename = path.basename(p)
dirname = path.basename(path.dirname(p))
return path.join(dirname, filename)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="This script compares two directories that were created "

@ -1,3 +0,0 @@
foo,bar,baz,this|that,test,colors,cycle
1.2,1.7,2.5,blah;cool,test,colors,cycle
1 foo bar baz this|that test colors cycle
2 1.2 1.7 2.5 blah;cool test colors cycle

@ -1,7 +1,7 @@
first,last,address,city,zip
John,Doe,120 any st.,"Anytown, WW",08123
a,b
1,"ha 
first,last,address,city,zip
John,Doe,120 any st.,"Anytown, WW",08123
a,b
1,"ha 
""ha"" 
ha",120 any st.,"Anytown, WW",08123
3,4,120 any st.,"Anytown, WW",08123
ha",120 any st.,"Anytown, WW",08123
3,4,120 any st.,"Anytown, WW",08123

Can't render this file because it contains an unexpected character in line 2 and column 177.

@ -1,3 +0,0 @@
foo|bar|baz
1,2|1,7|2,7
1,5|8,5|-5,5
1 [3 38 2 253 151 31mfoo[38 2 253 151 31m|[38 2 102 217 239mbar[38 2 253 151 31m|[38 2 190 132 255mbaz
2 [3 38 2 253 151 31m1,2[38 2 253 151 31m|[38 2 102 217 239m1,7[38 2 253 151 31m|[38 2 190 132 255m2,7
3 [3 38 2 253 151 31m1,5[38 2 253 151 31m|[38 2 102 217 239m8,5[38 2 253 151 31m|[38 2 190 132 255m-5,5

@ -1,3 +0,0 @@
foo;bar;baz
1,2;1,7;2,7
1,5;8,5;-5,5
1 [3 38 2 253 151 31mfoo[38 2 253 151 31m [38 2 102 217 239mbar[38 2 253 151 31m [38 2 190 132 255mbaz
2 [3 38 2 253 151 31m1,2[38 2 253 151 31m [38 2 102 217 239m1,7[38 2 253 151 31m [38 2 190 132 255m2,7
3 [3 38 2 253 151 31m1,5[38 2 253 151 31m [38 2 102 217 239m8,5[38 2 253 151 31m [38 2 190 132 255m-5,5

@ -1,3 +0,0 @@
foo bar baz|;, test hello world tsv
1,2 1,7 2,7 a b c "hello again" tsv
";|," ;|, baz test "hello world" tsv
Can't render this file because it contains an unexpected character in line 2 and column 218.

@ -1,71 +0,0 @@
extends Node
signal custom_signal(param)
const PI = 3.14159
var untyped_var = "Hello, World!"
var typed_int: int = 42
var typed_float: float = 3.14
var typed_string: String = "GDScript Test"
var typed_array: Array = [1, 2, 3, 4]
var typed_dict: Dictionary = {"key": "value", "number": 100}
onready var label = $Label
func say_hello() -> void:
 print("Hello from GDScript!")
func add_numbers(a: int, b: int = 10) -> int:
 return a + b
func process_value(value: int) -> String:
 if value < 0:
 return "Negative"
 elif value == 0:
 return "Zero"
 else:
 return "Positive"
func sum_array(arr: Array) -> int:
 var total: int = 0
 for num in arr:
 total += num
 return total
func describe_number(num: int) -> String:
 match num:
 0:
 return "Zero"
 1, 2, 3:
 return "Small number"
 _:
 return "Large number"
func long_description() -> String:
 return """This is a test file for GDScript.
It covers variables, functions, control structures, loops, signals, inner classes,
multiline strings, arrays, and dictionaries."""
class InnerExample:
 var inner_value: int = 99
 func show_value() -> void:
 print("Inner value is:", inner_value)
func test_inner_class() -> void:
 var inner = InnerExample.new()
 inner.show_value()
func trigger_signal() -> void:
 emit_signal("custom_signal", "TestParam")
func _ready() -> void:
 say_hello()
 var result_add = add_numbers(5)
 print("Add result:", result_add)
 print("Process value for -5:", process_value(-5))
 print("Sum of array [10, 20, 30]:", sum_array([10, 20, 30]))
 print("Description for 2:", describe_number(2))
 print("Long description:\n", long_description())
 test_inner_class()
 trigger_signal()

@ -1,3 +0,0 @@
{"some":"thing"}
{"foo":17,"bar":false,"quux":true}
{"may":{"include":"nested","objects":["and","arrays"]}}

@ -1,82 +1,67 @@
import MIL.Common
import Mathlib.Topology.Instances.Real.Defs
import data.matrix.notation
import data.vector2
open Set Filter Topology
/-!
variable {α : Type*}
variable (s t : Set )
variable (ssubt : s t)
variable {α : Type*} (s : Set (Set α))
-- Apostrophes are allowed in variable names
variable (f'_x x' : )
variable (bangwI' jablu'DI' QaQqu' nay' Ghay'cha' he' : )
Helpers that don't currently fit elsewhere...
-- In the next example we could use `tauto` in each proof instead of knowing the lemmas
example {α : Type*} (s : Set α) : Filter α :=
 { sets := { t | s t }
 univ_sets := subset_univ s
 sets_of_superset := fun hU hUV Subset.trans hU hUV
 inter_sets := fun hU hV subset_inter hU hV }
-/
lemma split_eq {m n : Type*} (x : m × n) (p p' : m × n) :
 p = x p' = x (x p x p') := by tauto
-- For `playfield`s, the piece type and/or piece index type.
variables (X : Type*)
variables [has_repr X]
namespace chess.utils
section repr
@[class] structure One₂ (α : Type) where
 /-- The element one -/
 one : α
/--
An auxiliary wrapper for `option X` that allows for overriding the `has_repr` instance
for `option`, and rather, output just the value in the `some` and a custom provided
`string` for `none`.
-/
structure option_wrapper :=
(val : option X)
(none_s : string)
structure StandardTwoSimplex where
 x : 
 y : 
 z : 
 x_nonneg : 0 x
 y_nonneg : 0 y
 z_nonneg : 0 z
 sum_eq : x + y + z = 1
instance wrapped_option_repr : has_repr (option_wrapper X) :=
λ val, s, (option.map has_repr.repr val).get_or_else s
#check Pi.ringHom
#check ker_Pi_Quotient_mk
#eval 1 + 1
variables {X}
/--
Construct an `option_wrapper` term from a provided `option X` and the `string`
that will override the `has_repr.repr` for `none`.
-/
def option_wrap (val : option X) (none_s : string) : option_wrapper X := val, none_s
/-- The homomorphism from ``R ⨅ i, I i`` to ``Π i, R I i`` featured in the Chinese
 Remainder Theorem. -/
def chineseMap (I : ι Ideal R) : (R i, I i) +* Π i, R I i :=
 Ideal.Quotient.lift ( i, I i) (Pi.ringHom fun i : ι Ideal.Quotient.mk (I i))
 (by simp [ RingHom.mem_ker, ker_Pi_Quotient_mk])
-- The size of the "vectors" for a `fin n' → X`, for `has_repr` definitions
variables {m' n' : }
lemma chineseMap_mk (I : ι Ideal R) (x : R) :
 chineseMap I (Quotient.mk _ x) = fun i : ι Ideal.Quotient.mk (I i) x :=
 rfl
/--
For a "vector" `X^n'` represented by the type `Π n' : , fin n' → X`, where
the `X` has a `has_repr` instance itself, we can provide a `has_repr` for the "vector".
This definition is used for displaying rows of the playfield, when it is defined
via a `matrix`, likely through notation.
-/
def vec_repr : Π {n' : }, (fin n' X) string :=
λ _ v, string.intercalate ", " ((vector.of_fn v).to_list.map repr)
theorem isCoprime_Inf {I : Ideal R} {J : ι Ideal R} {s : Finset ι}
 (hf : j s, IsCoprime I (J j)) : IsCoprime I ( j s, J j) := by
 classical
 simp_rw [isCoprime_iff_add] at *
 induction s using Finset.induction with
 | empty =>
 simp
 | @insert i s _ hs =>
 rw [Finset.iInf_insert, inf_comm, one_eq_top, eq_top_iff, one_eq_top]
 set K := j s, J j
 calc
 1 = I + K := (hs fun j hj hf j (Finset.mem_insert_of_mem hj)).symm
 _ = I + K * (I + J i) := by rw [hf i (Finset.mem_insert_self i s), mul_one]
 _ = (1 + K) * I + K * J i := by ring
 _ I + K J i := by gcongr ; apply mul_le_left ; apply mul_le_inf
instance vec_repr_instance : has_repr (fin n' X) := vec_repr
/--
For a `matrix` `X^(m' × n')` where the `X` has a `has_repr` instance itself,
we can provide a `has_repr` for the matrix, using `vec_repr` for each of the rows of the matrix.
This definition is used for displaying the playfield, when it is defined
via a `matrix`, likely through notation.
-/
def matrix_repr : Π {m' n'}, matrix (fin m') (fin n') X string :=
λ _ _ M, string.intercalate ";\n" ((vector.of_fn M).to_list.map repr)
class Ring₃ (R : Type) extends AddGroup₃ R, Monoid₃ R, MulZeroClass R where
 /-- Multiplication is left distributive over addition -/
 left_distrib : a b c : R, a * (b + c) = a * b + a * c
 /-- Multiplication is right distributive over addition -/
 right_distrib : a b c : R, (a + b) * c = a * c + b * c
instance {R : Type} [Ring₃ R] : AddCommGroup₃ R :=
{ Ring₃.toAddGroup₃ with
 add_comm := by
 sorry }
instance matrix_repr_instance :
 has_repr (matrix (fin n') (fin m') X) := matrix_repr
end repr

@ -1,3 +1,3 @@
2021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
2021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html
2022-03-16T17:41:02.519 helix_term::application [WARN] unhandled window/showMessage: ShowMessageParams { typ: Error, message: "rust-analyzer failed to load workspace: Failed to read Cargo metadata from Cargo.toml file /home/zeta/dev/raytracer/Cargo.toml, cargo 1.61.0-nightly (65c8266 2022-03-09): Failed to run `\"cargo\" \"metadata\" \"--format-version\" \"1\" \"--manifest-path\" \"/home/zeta/dev/raytracer/Cargo.toml\" \"--filter-platform\" \"wasm32-unknown-unknown\"`: `cargo metadata` exited with an error: Updating crates.io index\nerror: failed to select a version for `parking_lot`.\n ... required by package `raytracer v0.1.0 (/home/zeta/dev/raytracer)`\nversions that meet the requirements `^0.12.0` are: 0.12.0\n\nthe package `raytracer` depends on `parking_lot`, with features: `wasm-bindgen` but `parking_lot` does not have these features.\n\n\nfailed to select a version for `parking_lot` which could resolve this conflict\n" }
2022-03-16T17:41:02.519 helix_term::application [WARN] unhandled window/showMessage: ShowMessageParams { typ: Error, message: "rust-analyzer failed to load workspace: Failed to read Cargo metadata from Cargo.toml file /home/zeta/dev/raytracer/Cargo.toml, cargo 1.61.0-nightly (65c8266 2022-03-09): Failed to run `\"cargo\" \"metadata\" \"--format-version\" \"1\" \"--manifest-path\" \"/home/zeta/dev/raytracer/Cargo.toml\" \"--filter-platform\" \"wasm32-unknown-unknown\"`: `cargo metadata` exited with an error: Updating crates.io index\nerror: failed to select a version for `parking_lot`.\n ... required by package `raytracer v0.1.0 (/home/zeta/dev/raytracer)`\nversions that meet the requirements `^0.12.0` are: 0.12.0\n\nthe package `raytracer` depends on `parking_lot`, with features: `wasm-bindgen` but `parking_lot` does not have these features.\n\n\nfailed to select a version for `parking_lot` which could resolve this conflict\n" }

@ -1,27 +0,0 @@
package main
import "core:fmt"
import "core:math"
Vector :: struct {
 components: []f64,
}
euclidean_distance :: proc(v1: Vector, v2: Vector) -> f64 {
 if len(v1.components) != len(v2.components) {
 panic("Vectors must be same dimension")
 }
 sum: f64 = 0.0;
 for i, comp in v1.components {
 diff := comp - v2.components[i];
 sum += diff * diff;
 }
 return math.sqrt(sum);
}
main :: proc() {
 v1: Vector = Vector{components = []f64{1.0, 2.0, 3.0}};
 v2: Vector = Vector{components = []f64{4.0, 6.0, 8.0}};
 dist: f64 = euclidean_distance(v1, v2);
 fmt.println("Distance:", dist);
}

@ -1,17 +1,16 @@
Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded.
Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files.
Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available
Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice"
Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP.
Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37
Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> <null>
Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4
Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi)
Apr 4 16:32:07 hostname-here NetworkManager[740]: <info> [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL
Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid'
Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 [updater] Updater not running platform=linux dev=false
Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epoll add event: fd:6 op:1 ev:00002001
Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001
Aug 11 21:40:31 hostname-here scop hello
Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories.
2025-02-08 20:52:11.039 - setfont: ERROR kdfontop.c:183 put_font_kdfontop: Unable to load such font with such kernel version
Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded.
Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files.
Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available
Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice"
Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP.
Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37
Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> <null>
Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4
Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi)
Apr 4 16:32:07 hostname-here NetworkManager[740]: <info> [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL
Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid'
Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 [updater] Updater not running platform=linux dev=false
Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epoll add event: fd:6 op:1 ev:00002001
Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001
Aug 11 21:40:31 hostname-here scop hello
Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories.

@ -1,28 +0,0 @@
#set text(9.5pt)
= Heading
- Bullet 1
- Bullet 2
- Bullet 3
+ List 1
+ List 2
+ List 3
#figure(
 table(
 columns: (auto, auto),
 table.header(
 [Name], [Age],
 ),
 [John], [50],
 [Jane], [48],
 ),
 caption: [People],
)
```python
def foo():
 print("hi")
```

@ -1,74 +0,0 @@
-- This is a single-line comment
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SyntaxTest is
 generic (
 DATA_WIDTH : integer := 8
 );
 port (
 clk : in std_logic;
 rst : in std_logic;
 a, b : in std_logic_vector(DATA_WIDTH - 1 downto 0);
 sel : in std_logic;
 result : out std_logic_vector(DATA_WIDTH - 1 downto 0);
 flag : out std_logic
 );
end SyntaxTest;
architecture Behavioral of SyntaxTest is
 signal tmp : std_logic_vector(DATA_WIDTH - 1 downto 0);
 signal done : std_logic := '0';
 type state_type is (IDLE, LOAD, EXECUTE, DONE);
 signal state : state_type := IDLE;
begin
 process(clk, rst)
 variable i : integer := 0;
 begin
 if rst = '1' then
 tmp <= (others => '0');
 flag <= '0';
 state <= IDLE;
 elsif rising_edge(clk) then
 case state is
 when IDLE =>
 if sel = '1' then
 tmp <= a and b;
 state <= EXECUTE;
 else
 tmp <= a or b;
 state <= LOAD;
 end if;
 when LOAD =>
 tmp <= a xor b;
 state <= EXECUTE;
 when EXECUTE =>
 if i < DATA_WIDTH then
 tmp(i) <= not tmp(i);
 i := i + 1;
 else
 state <= DONE;
 end if;
 when DONE =>
 flag <= '1';
 state <= IDLE;
 when others =>
 state <= IDLE;
 end case;
 end if;
 end process;
 result <= tmp;
end Behavioral;

@ -1,5 +0,0 @@
<Project>
 <PropertyGroup>
 <OutDir>C:\output\$(MSBuildProjectName)</OutDir>
 </PropertyGroup>
</Project>

@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>net9.0</TargetFramework>
 <RootNamespace>SomeNamespace</RootNamespace>
 <ImplicitUsings>enable</ImplicitUsings>
 <Nullable>enable</Nullable>
 </PropertyGroup>
</Project>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Target Name="TestTarget" AfterTargets="Build">
 <Message Importance="High" Text="-------------MHM----------------" />
 </Target>
</Project>

@ -1,15 +0,0 @@
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb https://deb.debian.org/debian bookworm main non-free-firmware
#deb-src https://deb.debian.org/debian bookworm main non-free-firmware
## Major bug fix updates produced after the final release of the
## distribution.
# deb-src http://lt.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
deb https://security.debian.org/debian-security bookworm-security main non-free-firmware
deb-src https://security.debian.org/debian-security bookworm-security main non-free-firmware
deb https://deb.debian.org/debian bookworm-updates main non-free-firmware
deb-src https://deb.debian.org/debian bookworm-updates main non-free-firmware

@ -1,3 +0,0 @@
foo,bar,baz,this|that,test,colors,cycle
1.2,1.7,2.5,blah;cool,test,colors,cycle
1 foo bar baz this|that test colors cycle
2 1.2 1.7 2.5 blah;cool test colors cycle

@ -1,3 +0,0 @@
foo|bar|baz
1,2|1,7|2,7
1,5|8,5|-5,5
1 foo bar baz
2 1,2 1,7 2,7
3 1,5 8,5 -5,5

@ -1,3 +0,0 @@
foo;bar;baz
1,2;1,7;2,7
1,5;8,5;-5,5
1 foo bar baz
2 1,2 1,7 2,7
3 1,5 8,5 -5,5

@ -1,3 +0,0 @@
foo bar baz|;, test hello world tsv
1,2 1,7 2,7 a b c "hello again" tsv
";|," ;|, baz test "hello world" tsv
1 foo bar baz|;, test hello world tsv
2 1,2 1,7 2,7 a b c hello again tsv
3 ;|, ;|, baz test hello world tsv

@ -1,71 +0,0 @@
extends Node
signal custom_signal(param)
const PI = 3.14159
var untyped_var = "Hello, World!"
var typed_int: int = 42
var typed_float: float = 3.14
var typed_string: String = "GDScript Test"
var typed_array: Array = [1, 2, 3, 4]
var typed_dict: Dictionary = {"key": "value", "number": 100}
onready var label = $Label
func say_hello() -> void:
print("Hello from GDScript!")
func add_numbers(a: int, b: int = 10) -> int:
return a + b
func process_value(value: int) -> String:
if value < 0:
return "Negative"
elif value == 0:
return "Zero"
else:
return "Positive"
func sum_array(arr: Array) -> int:
var total: int = 0
for num in arr:
total += num
return total
func describe_number(num: int) -> String:
match num:
0:
return "Zero"
1, 2, 3:
return "Small number"
_:
return "Large number"
func long_description() -> String:
return """This is a test file for GDScript.
It covers variables, functions, control structures, loops, signals, inner classes,
multiline strings, arrays, and dictionaries."""
class InnerExample:
var inner_value: int = 99
func show_value() -> void:
print("Inner value is:", inner_value)
func test_inner_class() -> void:
var inner = InnerExample.new()
inner.show_value()
func trigger_signal() -> void:
emit_signal("custom_signal", "TestParam")
func _ready() -> void:
say_hello()
var result_add = add_numbers(5)
print("Add result:", result_add)
print("Process value for -5:", process_value(-5))
print("Sum of array [10, 20, 30]:", sum_array([10, 20, 30]))
print("Description for 2:", describe_number(2))
print("Long description:\n", long_description())
test_inner_class()
trigger_signal()

@ -1,3 +0,0 @@
{"some":"thing"}
{"foo":17,"bar":false,"quux":true}
{"may":{"include":"nested","objects":["and","arrays"]}}

@ -1,230 +0,0 @@
The `test.lean` file has been adpated from
- multiple files of [Mathematics in Lean](https://leanprover-community.github.io/mathematics_in_lean/) under the Apache 2.0 license,
- and https://github.com/Julian/lean-across-the-board under the MIT license.
## Mathematics in Lean (Apache 2.0)
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 Jeremy Avigad, Patrick Massot.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## Julian/lean-across-the-board (MIT)
Copyright (c) 2020 Julian Berman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -1,82 +1,67 @@
import MIL.Common
import Mathlib.Topology.Instances.Real.Defs
import data.matrix.notation
import data.vector2
open Set Filter Topology
/-!
variable {α : Type*}
variable (s t : Set )
variable (ssubt : s t)
variable {α : Type*} (s : Set (Set α))
-- Apostrophes are allowed in variable names
variable (f'_x x' : )
variable (bangwI' jablu'DI' QaQqu' nay' Ghay'cha' he' : )
Helpers that don't currently fit elsewhere...
-- In the next example we could use `tauto` in each proof instead of knowing the lemmas
example {α : Type*} (s : Set α) : Filter α :=
{ sets := { t | s t }
univ_sets := subset_univ s
sets_of_superset := fun hU hUV Subset.trans hU hUV
inter_sets := fun hU hV subset_inter hU hV }
-/
lemma split_eq {m n : Type*} (x : m × n) (p p' : m × n) :
p = x p' = x (x p x p') := by tauto
-- For `playfield`s, the piece type and/or piece index type.
variables (X : Type*)
variables [has_repr X]
namespace chess.utils
section repr
@[class] structure One₂ (α : Type) where
/-- The element one -/
one : α
/--
An auxiliary wrapper for `option X` that allows for overriding the `has_repr` instance
for `option`, and rather, output just the value in the `some` and a custom provided
`string` for `none`.
-/
structure option_wrapper :=
(val : option X)
(none_s : string)
structure StandardTwoSimplex where
x :
y :
z :
x_nonneg : 0 x
y_nonneg : 0 y
z_nonneg : 0 z
sum_eq : x + y + z = 1
instance wrapped_option_repr : has_repr (option_wrapper X) :=
λ val, s, (option.map has_repr.repr val).get_or_else s
#check Pi.ringHom
#check ker_Pi_Quotient_mk
#eval 1 + 1
variables {X}
/--
Construct an `option_wrapper` term from a provided `option X` and the `string`
that will override the `has_repr.repr` for `none`.
-/
def option_wrap (val : option X) (none_s : string) : option_wrapper X := val, none_s
/-- The homomorphism from ``R ⨅ i, I i`` to ``Π i, R I i`` featured in the Chinese
Remainder Theorem. -/
def chineseMap (I : ι Ideal R) : (R i, I i) +* Π i, R I i :=
Ideal.Quotient.lift ( i, I i) (Pi.ringHom fun i : ι Ideal.Quotient.mk (I i))
(by simp [ RingHom.mem_ker, ker_Pi_Quotient_mk])
-- The size of the "vectors" for a `fin n' → X`, for `has_repr` definitions
variables {m' n' : }
lemma chineseMap_mk (I : ι Ideal R) (x : R) :
chineseMap I (Quotient.mk _ x) = fun i : ι Ideal.Quotient.mk (I i) x :=
rfl
/--
For a "vector" `X^n'` represented by the type `Π n' : , fin n' → X`, where
the `X` has a `has_repr` instance itself, we can provide a `has_repr` for the "vector".
This definition is used for displaying rows of the playfield, when it is defined
via a `matrix`, likely through notation.
-/
def vec_repr : Π {n' : }, (fin n' X) string :=
λ _ v, string.intercalate ", " ((vector.of_fn v).to_list.map repr)
theorem isCoprime_Inf {I : Ideal R} {J : ι Ideal R} {s : Finset ι}
(hf : j s, IsCoprime I (J j)) : IsCoprime I ( j s, J j) := by
classical
simp_rw [isCoprime_iff_add] at *
induction s using Finset.induction with
| empty =>
simp
| @insert i s _ hs =>
rw [Finset.iInf_insert, inf_comm, one_eq_top, eq_top_iff, one_eq_top]
set K := j s, J j
calc
1 = I + K := (hs fun j hj hf j (Finset.mem_insert_of_mem hj)).symm
_ = I + K * (I + J i) := by rw [hf i (Finset.mem_insert_self i s), mul_one]
_ = (1 + K) * I + K * J i := by ring
_ I + K J i := by gcongr ; apply mul_le_left ; apply mul_le_inf
instance vec_repr_instance : has_repr (fin n' X) := vec_repr
/--
For a `matrix` `X^(m' × n')` where the `X` has a `has_repr` instance itself,
we can provide a `has_repr` for the matrix, using `vec_repr` for each of the rows of the matrix.
This definition is used for displaying the playfield, when it is defined
via a `matrix`, likely through notation.
-/
def matrix_repr : Π {m' n'}, matrix (fin m') (fin n') X string :=
λ _ _ M, string.intercalate ";\n" ((vector.of_fn M).to_list.map repr)
class Ring₃ (R : Type) extends AddGroup₃ R, Monoid₃ R, MulZeroClass R where
/-- Multiplication is left distributive over addition -/
left_distrib : a b c : R, a * (b + c) = a * b + a * c
/-- Multiplication is right distributive over addition -/
right_distrib : a b c : R, (a + b) * c = a * c + b * c
instance {R : Type} [Ring₃ R] : AddCommGroup₃ R :=
{ Ring₃.toAddGroup₃ with
add_comm := by
sorry }
instance matrix_repr_instance :
has_repr (matrix (fin n') (fin m') X) := matrix_repr
end repr

@ -1,27 +0,0 @@
package main
import "core:fmt"
import "core:math"
Vector :: struct {
components: []f64,
}
euclidean_distance :: proc(v1: Vector, v2: Vector) -> f64 {
if len(v1.components) != len(v2.components) {
panic("Vectors must be same dimension")
}
sum: f64 = 0.0;
for i, comp in v1.components {
diff := comp - v2.components[i];
sum += diff * diff;
}
return math.sqrt(sum);
}
main :: proc() {
v1: Vector = Vector{components = []f64{1.0, 2.0, 3.0}};
v2: Vector = Vector{components = []f64{4.0, 6.0, 8.0}};
dist: f64 = euclidean_distance(v1, v2);
fmt.println("Distance:", dist);
}

@ -14,4 +14,3 @@ Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epol
Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001
Aug 11 21:40:31 hostname-here scop hello
Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories.
2025-02-08 20:52:11.039 - setfont: ERROR kdfontop.c:183 put_font_kdfontop: Unable to load such font with such kernel version

@ -1,28 +0,0 @@
#set text(9.5pt)
= Heading
- Bullet 1
- Bullet 2
- Bullet 3
+ List 1
+ List 2
+ List 3
#figure(
table(
columns: (auto, auto),
table.header(
[Name], [Age],
),
[John], [50],
[Jane], [48],
),
caption: [People],
)
```python
def foo():
print("hi")
```

@ -1,74 +0,0 @@
-- This is a single-line comment
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SyntaxTest is
generic (
DATA_WIDTH : integer := 8
);
port (
clk : in std_logic;
rst : in std_logic;
a, b : in std_logic_vector(DATA_WIDTH - 1 downto 0);
sel : in std_logic;
result : out std_logic_vector(DATA_WIDTH - 1 downto 0);
flag : out std_logic
);
end SyntaxTest;
architecture Behavioral of SyntaxTest is
signal tmp : std_logic_vector(DATA_WIDTH - 1 downto 0);
signal done : std_logic := '0';
type state_type is (IDLE, LOAD, EXECUTE, DONE);
signal state : state_type := IDLE;
begin
process(clk, rst)
variable i : integer := 0;
begin
if rst = '1' then
tmp <= (others => '0');
flag <= '0';
state <= IDLE;
elsif rising_edge(clk) then
case state is
when IDLE =>
if sel = '1' then
tmp <= a and b;
state <= EXECUTE;
else
tmp <= a or b;
state <= LOAD;
end if;
when LOAD =>
tmp <= a xor b;
state <= EXECUTE;
when EXECUTE =>
if i < DATA_WIDTH then
tmp(i) <= not tmp(i);
i := i + 1;
else
state <= DONE;
end if;
when DONE =>
flag <= '1';
state <= IDLE;
when others =>
state <= IDLE;
end case;
end if;
end process;
result <= tmp;
end Behavioral;

@ -1,5 +0,0 @@
<Project>
<PropertyGroup>
<OutDir>C:\output\$(MSBuildProjectName)</OutDir>
</PropertyGroup>
</Project>

@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>SomeNamespace</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="TestTarget" AfterTargets="Build">
<Message Importance="High" Text="-------------MHM----------------" />
</Target>
</Project>

@ -1,15 +0,0 @@
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb https://deb.debian.org/debian bookworm main non-free-firmware
#deb-src https://deb.debian.org/debian bookworm main non-free-firmware
## Major bug fix updates produced after the final release of the
## distribution.
# deb-src http://lt.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
deb https://security.debian.org/debian-security bookworm-security main non-free-firmware
deb-src https://security.debian.org/debian-security bookworm-security main non-free-firmware
deb https://deb.debian.org/debian bookworm-updates main non-free-firmware
deb-src https://deb.debian.org/debian bookworm-updates main non-free-firmware