mirror of
https://github.com/sharkdp/bat
synced 2026-08-04 19:01:44 +00:00
Compare commits
396 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30b742e984 | |||
| 671deeef8c | |||
| a892caeb33 | |||
| a770cbf25e | |||
| 931c6e9414 | |||
| 8dc7e2efa3 | |||
| 10965a6122 | |||
| e43d97dc15 | |||
| 2c7087b8de | |||
| bb1f5aa841 | |||
| 2109a7830b | |||
| ec27c78a8a | |||
| 67fe833bc8 | |||
| e956225b4d | |||
| 314ec881ef | |||
| 25a6a55437 | |||
| 5bff4548be | |||
| 866b9e16a8 | |||
| 5af176c94f | |||
| 9e7da05459 | |||
| 1ae02c65fb | |||
| 495e7fd3b1 | |||
| b48f0fe389 | |||
| c19c704a43 | |||
| 693bd5929d | |||
| 8275b0436d | |||
| 278bde5cee | |||
| eee7e5a575 | |||
| ad7b634ee6 | |||
| 1310f83c8d | |||
| 897b9e7030 | |||
| 1891e194b5 | |||
| d2d01b9fe8 | |||
| 5842d58c01 | |||
| e3c71adba7 | |||
| 504f28b3a1 | |||
| d977ba9194 | |||
| 9c09799e1f | |||
| d83c93c805 | |||
| fc8fd1e63f | |||
| 404d6a4a81 | |||
| 25d96da4a2 | |||
| e97095b724 | |||
| ce96df00b6 | |||
| f98fc5f06a | |||
| 1dbb4ef683 | |||
| 0502a3bd4a | |||
| 869cf6368c | |||
| 078228deac | |||
| e09d7dabb8 | |||
| 6d1cc8c2c8 | |||
| 87f021078e | |||
| d5b0502419 | |||
| 860f3e9006 | |||
| 1be346a038 | |||
| f9fd5e4851 | |||
| da09f3877b | |||
| e30e1bab2e | |||
| f140f6da46 | |||
| 3446fdf5f2 | |||
| e1345cdc2a | |||
| a2676ccc55 | |||
| b39e28d2c8 | |||
| 0d71968615 | |||
| 80da0dc619 | |||
| 64903bb858 | |||
| 3456ce1187 | |||
| 886a5b3d24 | |||
| 238482e5f3 | |||
| 79b960e17e | |||
| 6aa626f1c4 | |||
| 1b30539493 | |||
| 96b24d8a7e | |||
| 20b02e72b3 | |||
| 254efac9c2 | |||
| dcec322117 | |||
| d781156327 | |||
| 732750c274 | |||
| 6b6baa3118 | |||
| 54c434934e | |||
| ad6e0a2581 | |||
| bd619db3ca | |||
| e098eb43a2 | |||
| ea369ee17f | |||
| 63d32bc818 | |||
| dccf8d8221 | |||
| 97129ab9d8 | |||
| 52d0d6ca30 | |||
| a05494e9d9 | |||
| 84ac92efbb | |||
| b4c6e412dc | |||
| 3e21d69a92 | |||
| b7690d4bb1 | |||
| d404139ff7 | |||
| 9ef1e9f792 | |||
| 503fe0b641 | |||
| 1807f9653c | |||
| 1e74f0e2a9 | |||
| c1e1f753cf | |||
| d90797f8e9 | |||
| b4096e5627 | |||
| 4e3ab4d399 | |||
| f0d936763c | |||
| 7897260bf0 | |||
| eb6e43b9a9 | |||
| 7cdcdbb31d | |||
| 9159341714 | |||
| b23ff24ebc | |||
| e1ecc17f69 | |||
| 0fe3badf19 | |||
| 89d4cb951a | |||
| e9681bf22d | |||
| 1b6df8a480 | |||
| cf24986edb | |||
| b9c556a0b6 | |||
| 9d6bde48fa | |||
| d6c8fee044 | |||
| 8b4abb03db | |||
| 375cf76e15 | |||
| 1a4acc435e | |||
| d8030626f8 | |||
| fb61aa4f60 | |||
| 76df41fa97 | |||
| 97efd75cee | |||
| 53d0c1deca | |||
| 155179a07a | |||
| ba00caf9c3 | |||
| ac418ba21c | |||
| acde83af31 | |||
| 021a68eb21 | |||
| 566aab3b05 | |||
| f88eba6476 | |||
| 1d9e7ac4c2 | |||
| 80ae2ecbf8 | |||
| 96d4492d27 | |||
| c90f0b8e21 | |||
| 4b866ab6af | |||
| 2dbd91e543 | |||
| 785da3d9df | |||
| d455cb7c32 | |||
| d2b4766f92 | |||
| 5cf92b4f94 | |||
| 7b803a50af | |||
| 67ec5fe2b7 | |||
| 3447ed4def | |||
| 532fb921a6 | |||
| ba4d5a2e7d | |||
| 026273a05c | |||
| 8903b64830 | |||
| 194155f062 | |||
| a6ff3b900d | |||
| 8a52bcf92d | |||
| 0b1535f63b | |||
| 0a5b3eaf3e | |||
| 11294249f8 | |||
| 35a1236ad0 | |||
| af8da50c2c | |||
| 649d1e3df2 | |||
| 199cfd4519 | |||
| c7cce0752b | |||
| 3a89486189 | |||
| 720a2fb7a5 | |||
| e3c990f11e | |||
| 90c7d0c365 | |||
| 56002267d2 | |||
| 84734eac9d | |||
| acdea97e71 | |||
| 839e4ee611 | |||
| c7afcdebf8 | |||
| 08e6db1581 | |||
| 4d08ecd828 | |||
| 28e1d0e613 | |||
| d11839ad03 | |||
| 8cacd9b432 | |||
| 6f67444c99 | |||
| fd2b376ea0 | |||
| cda54e4f61 | |||
| 3b90ada735 | |||
| 1837d364fe | |||
| 4ea3e6bbb7 | |||
| 38544ed735 | |||
| 5444b0dfed | |||
| f3dde0185d | |||
| 2e3784aa30 | |||
| 1088455702 | |||
| 4f812c32ab | |||
| b6c59a5bd4 | |||
| b682679776 | |||
| 81771432fb | |||
| 627181bcb6 | |||
| 226d9a573a | |||
| 246cf79dbd | |||
| ea955c734d | |||
| 6223ad6d52 | |||
| 31a9335bd5 | |||
| 9316f2a758 | |||
| c884c3cc12 | |||
| 08850f0474 | |||
| 8e6c5bc562 | |||
| 052425b12f | |||
| 2df3305b94 | |||
| 6882fc1512 | |||
| 2508323264 | |||
| 297afad337 | |||
| 1dddce3aa1 | |||
| 76be0d3933 | |||
| e5b8c4471a | |||
| b191691767 | |||
| 5c95b8803b | |||
| 5b421b455d | |||
| a6d6c28723 | |||
| 2966939e38 | |||
| d179693d1d | |||
| 268577c6f9 | |||
| 037861e588 | |||
| 94ccc646e8 | |||
| 0cc5d1dab6 | |||
| 28397b8f78 | |||
| c899849101 | |||
| bf53b64125 | |||
| c68aa0f424 | |||
| 6b57f4eebc | |||
| 0ddd388a29 | |||
| 34811b8161 | |||
| 8b92aae23f | |||
| 3a0941cabe | |||
| 52877c6d67 | |||
| 455de98a89 | |||
| 8c6a74a6c5 | |||
| 3f8b340ed8 | |||
| 65e6970907 | |||
| 90cc019482 | |||
| eaf0b99d25 | |||
| 3b1dcca5d0 | |||
| 26dbdf4fa0 | |||
| 6691786d82 | |||
| 50209bfe21 | |||
| c91511cca1 | |||
| c9f7a0c126 | |||
| 69c798eafd | |||
| 195d5e0e16 | |||
| 86c1777205 | |||
| 16874ab016 | |||
| bf5883f06f | |||
| e27bdfc7d6 | |||
| a7f4f202cb | |||
| 397223374a | |||
| 0c2da90fa4 | |||
| fe29da6e76 | |||
| 0eccfb50d9 | |||
| f74263e71d | |||
| 54f4896ced | |||
| 9d92350cbb | |||
| 26d409db65 | |||
| 06cd4b2ce8 | |||
| a348a9f68e | |||
| 39e2971e96 | |||
| a13eb60df3 | |||
| 9342d0bb24 | |||
| 36d7250af2 | |||
| 2ce8655167 | |||
| a452467e06 | |||
| 2ea3758c4b | |||
| 65bb4c7ee6 | |||
| 556149ad3a | |||
| 33bbf25468 | |||
| 5ee8913538 | |||
| 9b1c1c0271 | |||
| 2712d63a4b | |||
| b21fb6bca8 | |||
| ee43377a9c | |||
| 120b33a9db | |||
| 17b37fedcb | |||
| 1013cdd80a | |||
| be0a2d6048 | |||
| d1a1943998 | |||
| 2a9f5a24ed | |||
| a0ae089c4a | |||
| 96cc391f2d | |||
| a1e1170319 | |||
| 54a331d162 | |||
| 5e3b17e6f7 | |||
| 486e6a19cd | |||
| 247dfbee83 | |||
| 882931a77b | |||
| 12cb438aa4 | |||
| d0782ef954 | |||
| c826c2a438 | |||
| 9aa97b6c22 | |||
| f7890870ea | |||
| 145b99f01c | |||
| 9af1d2b891 | |||
| 2eee68599d | |||
| d569693dab | |||
| 900f61032d | |||
| d0ca566979 | |||
| a5a7dc14e4 | |||
| 54b33c8c21 | |||
| a5de77af4d | |||
| 870ff7b538 | |||
| 15b9acd12f | |||
| b327127f37 | |||
| 9214a4a4f0 | |||
| fcecd97224 | |||
| 870b3c0daf | |||
| b9c780c8c8 | |||
| ca865f9d26 | |||
| 3ee0e56315 | |||
| 091b0b6437 | |||
| 9f005d115d | |||
| b4cfc9633c | |||
| f7e055b6b7 | |||
| d4b438b9d3 | |||
| cd26d403a3 | |||
| f95a23f948 | |||
| 0886a24685 | |||
| 53eb9c57d6 | |||
| 026a9ebae3 | |||
| bdd10b8bec | |||
| fc160b0dcd | |||
| cb7b158172 | |||
| fcc36b1f79 | |||
| 4e4110bf50 | |||
| 22c8978fca | |||
| f711fb5006 | |||
| 64a9341b73 | |||
| ccf88fd5d8 | |||
| 6343535eb2 | |||
| e2ac6de783 | |||
| 25cee002f9 | |||
| 13a53d230b | |||
| ea27053a63 | |||
| b2b932f3ed | |||
| 747d074be1 | |||
| 61109ece15 | |||
| 389edd7239 | |||
| 23813cc08b | |||
| fdeb98e859 | |||
| 6a417886aa | |||
| 8b9991d780 | |||
| f59ddd1e36 | |||
| f90b9d1acc | |||
| f7af537018 | |||
| fd68af8031 | |||
| ebdef04c8f | |||
| a4150600af | |||
| 49223eed06 | |||
| 7dc7133b3c | |||
| e5e47716b0 | |||
| b4f8cd3bae | |||
| ee3a37f3fc | |||
| 4c60ab12cc | |||
| ac32dd17c9 | |||
| 4e3c57cc7c | |||
| 438a9a99ed | |||
| 9b0877102c | |||
| 67bed73e15 | |||
| ef7c39b159 | |||
| 8a399c8d7d | |||
| 9a0e444e09 | |||
| 438f3df345 | |||
| 7e2e0c82ac | |||
| da92154163 | |||
| 179bd4f525 | |||
| 53d67e2b6e | |||
| b625d07c34 | |||
| ec606e5dcc | |||
| c253821a5e | |||
| ccb1d78b22 | |||
| 9eb64b97fe | |||
| 15f0268bdc | |||
| 3fa70deaa7 | |||
| d4553c6b38 | |||
| 23d92d7641 | |||
| 92729430fc | |||
| 3eb79d63ce | |||
| 0483407775 | |||
| cbdf5c50c4 | |||
| 418b3c5ea1 | |||
| 9dca3126b3 | |||
| 7df9a5fe82 | |||
| 4bba08062c | |||
| 4e8ea815af | |||
| b7bc2d54ba | |||
| 21f9e2b0f7 | |||
| 92aa2b547e | |||
| 65f66d0bee | |||
| f5a9236a47 | |||
| edbe8f3e1a | |||
| ed09a80a73 | |||
| 802540ea08 | |||
| dbf84e77e0 | |||
| 8f18567f2d | |||
| e4d7e004ee | |||
| 51b57ccdb7 | |||
| 25f83610f9 |
+96
@@ -0,0 +1,96 @@
|
|||||||
|
[submodule "assets/syntaxes/Elixir"]
|
||||||
|
path = assets/syntaxes/Elixir
|
||||||
|
url = https://github.com/princemaple/elixir-sublime-syntax/
|
||||||
|
[submodule "assets/syntaxes/Packages"]
|
||||||
|
path = assets/syntaxes/Packages
|
||||||
|
url = https://github.com/sublimehq/Packages/
|
||||||
|
[submodule "assets/syntaxes/TOML"]
|
||||||
|
path = assets/syntaxes/TOML
|
||||||
|
url = https://github.com/sharkdp/sublime_toml_highlighting
|
||||||
|
[submodule "assets/syntaxes/Julia"]
|
||||||
|
path = assets/syntaxes/Julia
|
||||||
|
url = https://github.com/JuliaEditorSupport/Julia-sublime
|
||||||
|
[submodule "assets/themes/sublime-monokai-extended"]
|
||||||
|
path = assets/themes/sublime-monokai-extended
|
||||||
|
url = https://github.com/jonschlinkert/sublime-monokai-extended
|
||||||
|
[submodule "assets/syntaxes/Docker"]
|
||||||
|
path = assets/syntaxes/Docker
|
||||||
|
url = https://github.com/asbjornenge/Docker.tmbundle
|
||||||
|
[submodule "assets/syntaxes/VimL"]
|
||||||
|
path = assets/syntaxes/VimL
|
||||||
|
url = https://github.com/SalGnt/Sublime-VimL
|
||||||
|
[submodule "assets/syntaxes/INI"]
|
||||||
|
path = assets/syntaxes/INI
|
||||||
|
url = https://github.com/clintberry/sublime-text-2-ini
|
||||||
|
[submodule "assets/syntaxes/CMake"]
|
||||||
|
path = assets/syntaxes/CMake
|
||||||
|
url = https://github.com/zyxar/Sublime-CMakeLists
|
||||||
|
[submodule "assets/syntaxes/LESS"]
|
||||||
|
path = assets/syntaxes/LESS
|
||||||
|
url = https://github.com/danro/LESS-sublime
|
||||||
|
[submodule "assets/themes/DarkNeon"]
|
||||||
|
path = assets/themes/DarkNeon
|
||||||
|
url = https://github.com/RainyDayMedia/DarkNeon
|
||||||
|
[submodule "assets/themes/github-sublime-theme"]
|
||||||
|
path = assets/themes/github-sublime-theme
|
||||||
|
url = https://github.com/AlexanderEkdahl/github-sublime-theme
|
||||||
|
[submodule "assets/themes/1337-Scheme"]
|
||||||
|
path = assets/themes/1337-Scheme
|
||||||
|
url = https://github.com/MarkMichos/1337-Scheme
|
||||||
|
[submodule "assets/themes/TwoDark"]
|
||||||
|
path = assets/themes/TwoDark
|
||||||
|
url = https://github.com/erremauro/TwoDark
|
||||||
|
[submodule "assets/syntaxes/AWK"]
|
||||||
|
path = assets/syntaxes/AWK
|
||||||
|
url = https://github.com/JohnNilsson/awk-sublime
|
||||||
|
[submodule "assets/syntaxes/Nix"]
|
||||||
|
path = assets/syntaxes/Nix
|
||||||
|
url = https://github.com/wmertens/sublime-nix
|
||||||
|
[submodule "assets/themes/zenburn"]
|
||||||
|
path = assets/themes/zenburn
|
||||||
|
url = https://github.com/colinta/zenburn.git
|
||||||
|
[submodule "assets/syntaxes/Kotlin"]
|
||||||
|
path = assets/syntaxes/Kotlin
|
||||||
|
url = https://github.com/vkostyukov/kotlin-sublime-package
|
||||||
|
[submodule "assets/syntaxes/Elm"]
|
||||||
|
path = assets/syntaxes/Elm
|
||||||
|
url = https://github.com/elm-community/SublimeElmLanguageSupport
|
||||||
|
[submodule "assets/syntaxes/TypeScript"]
|
||||||
|
path = assets/syntaxes/TypeScript
|
||||||
|
url = https://github.com/Microsoft/TypeScript-Sublime-Plugin
|
||||||
|
[submodule "assets/syntaxes/Puppet"]
|
||||||
|
path = assets/syntaxes/Puppet
|
||||||
|
url = https://github.com/russCloak/SublimePuppet
|
||||||
|
[submodule "assets/syntaxes/CSV"]
|
||||||
|
path = assets/syntaxes/CSV
|
||||||
|
url = https://github.com/wadetb/Sublime-Text-Advanced-CSV
|
||||||
|
[submodule "assets/themes/onehalf"]
|
||||||
|
path = assets/themes/onehalf
|
||||||
|
url = https://github.com/sonph/onehalf
|
||||||
|
[submodule "assets/syntaxes/JavaScript (Babel)"]
|
||||||
|
path = assets/syntaxes/JavaScript (Babel)
|
||||||
|
url = https://github.com/babel/babel-sublime
|
||||||
|
[submodule "assets/syntaxes/Cabal"]
|
||||||
|
path = assets/syntaxes/Cabal
|
||||||
|
url = https://github.com/SublimeHaskell/SublimeHaskell
|
||||||
|
[submodule "assets/syntaxes/Dart"]
|
||||||
|
path = assets/syntaxes/Dart
|
||||||
|
url = https://github.com/guillermooo/dart-sublime-bundle
|
||||||
|
[submodule "assets/syntaxes/FSharp"]
|
||||||
|
path = assets/syntaxes/FSharp
|
||||||
|
url = https://github.com/hoest/sublimetext-fsharp
|
||||||
|
[submodule "assets/syntaxes/PureScript"]
|
||||||
|
path = assets/syntaxes/PureScript
|
||||||
|
url = https://github.com/tellnobody1/sublime-purescript-syntax
|
||||||
|
[submodule "assets/syntaxes/Swift"]
|
||||||
|
path = assets/syntaxes/Swift
|
||||||
|
url = https://github.com/quiqueg/Swift-Sublime-Package
|
||||||
|
[submodule "assets/syntaxes/Crystal"]
|
||||||
|
path = assets/syntaxes/Crystal
|
||||||
|
url = https://github.com/crystal-lang-tools/sublime-crystal.git
|
||||||
|
[submodule "assets/syntaxes/PowerShell"]
|
||||||
|
path = assets/syntaxes/PowerShell
|
||||||
|
url = https://github.com/PowerShell/EditorSyntax
|
||||||
|
[submodule "assets/syntaxes/Robot"]
|
||||||
|
path = assets/syntaxes/Robot
|
||||||
|
url = https://github.com/andriyko/sublime-robot-framework-assistant.git
|
||||||
+40
-12
@@ -6,25 +6,55 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
rust: stable
|
rust: stable
|
||||||
env: TARGET=x86_64-unknown-linux-gnu
|
env: TARGET=x86_64-unknown-linux-gnu
|
||||||
|
- os: linux
|
||||||
|
rust: stable
|
||||||
|
env:
|
||||||
|
- TARGET=x86_64-unknown-linux-musl
|
||||||
|
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
|
||||||
|
- os: linux
|
||||||
|
rust: stable
|
||||||
|
env: TARGET=i686-unknown-linux-gnu
|
||||||
- os: osx
|
- os: osx
|
||||||
rust: stable
|
rust: stable
|
||||||
env: TARGET=x86_64-apple-darwin
|
env: TARGET=x86_64-apple-darwin
|
||||||
|
- os: linux
|
||||||
|
rust: stable
|
||||||
|
env:
|
||||||
|
- TARGET=arm-unknown-linux-gnueabihf
|
||||||
|
- CC_arm_unknown_linux_gnueabihf=/usr/bin/arm-linux-gnueabihf-gcc-4.8
|
||||||
|
- CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc-4.8
|
||||||
|
- os: linux
|
||||||
|
rust: stable
|
||||||
|
env:
|
||||||
|
- TARGET=aarch64-unknown-linux-gnu
|
||||||
|
- CC_aarch64-unknown-linux-gnu=/usr/bin/aarch64-linux-gnu-gcc-4.8
|
||||||
|
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc-4.8
|
||||||
|
|
||||||
# Minimum Rust supported channel.
|
# Minimum Rust supported channel.
|
||||||
- os: linux
|
- os: linux
|
||||||
rust: 1.22.1
|
rust: 1.29.0
|
||||||
env: TARGET=x86_64-unknown-linux-gnu
|
env: TARGET=x86_64-unknown-linux-gnu
|
||||||
|
- os: linux
|
||||||
|
rust: 1.29.0
|
||||||
|
env:
|
||||||
|
- TARGET=x86_64-unknown-linux-musl
|
||||||
|
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
|
||||||
- os: osx
|
- os: osx
|
||||||
rust: 1.22.1
|
rust: 1.29.0
|
||||||
env: TARGET=x86_64-apple-darwin
|
env: TARGET=x86_64-apple-darwin
|
||||||
|
|
||||||
addons:
|
# Code formatting check
|
||||||
apt:
|
- os: linux
|
||||||
packages:
|
rust: nightly
|
||||||
# needed for i686-unknown-linux-gnu target
|
# skip the global install step
|
||||||
- gcc-multilib
|
install:
|
||||||
# needed to build deb packages
|
- cargo install --debug --force rustfmt-nightly
|
||||||
- fakeroot
|
script: cargo fmt -- --check
|
||||||
|
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- ci/before_install.bash
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
@@ -39,9 +69,7 @@ install:
|
|||||||
- if [[ $TRAVIS_OS_NAME = linux && $HOST != $TARGET ]]; then rustup target add $TARGET; fi
|
- if [[ $TRAVIS_OS_NAME = linux && $HOST != $TARGET ]]; then rustup target add $TARGET; fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# Incorporate TARGET env var to the build and test process
|
- ci/script.bash
|
||||||
- cargo build --target $TARGET --verbose
|
|
||||||
- cargo test --target $TARGET --verbose
|
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- bash ci/before_deploy.bash
|
- bash ci/before_deploy.bash
|
||||||
|
|||||||
Generated
+526
-406
File diff suppressed because it is too large
Load Diff
+32
-8
@@ -7,24 +7,48 @@ license = "MIT/Apache-2.0"
|
|||||||
name = "bat"
|
name = "bat"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/sharkdp/bat"
|
repository = "https://github.com/sharkdp/bat"
|
||||||
version = "0.2.0"
|
version = "0.8.0"
|
||||||
|
exclude = [
|
||||||
|
"assets/syntaxes/*",
|
||||||
|
"assets/themes/*",
|
||||||
|
]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
atty = "0.2.2"
|
atty = "0.2.2"
|
||||||
ansi_term = "0.9"
|
ansi_term = "0.11"
|
||||||
bincode = "1.0"
|
ansi_colours = "^1.0"
|
||||||
console = "0.6"
|
console = "0.6"
|
||||||
git2 = "0.6"
|
directories = "1.0"
|
||||||
error-chain = "0.11"
|
|
||||||
directories = "0.9"
|
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
|
wild = "2.0"
|
||||||
|
content_inspector = "0.2.3"
|
||||||
|
encoding = "0.2"
|
||||||
|
shell-words = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies.git2]
|
||||||
|
version = "0.7"
|
||||||
|
default-features = false
|
||||||
|
features = []
|
||||||
|
|
||||||
[dependencies.syntect]
|
[dependencies.syntect]
|
||||||
version = "2"
|
version = "3.0.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["parsing", "yaml-load", "dump-load", "dump-create"]
|
features = ["parsing", "yaml-load", "dump-load", "dump-create"]
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
version = "2"
|
version = "2.32"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["suggestions", "color", "wrap_help"]
|
features = ["suggestions", "color", "wrap_help"]
|
||||||
|
|
||||||
|
[dependencies.error-chain]
|
||||||
|
version = "0.12"
|
||||||
|
default-features = false
|
||||||
|
features = []
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempdir = "0.3"
|
||||||
|
assert_cmd = "0.10.1"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
clap = "2.32"
|
||||||
|
|||||||
@@ -1,69 +1,410 @@
|
|||||||
# bat
|
<p align="center">
|
||||||
|
<img src="doc/logo-header.svg" alt="bat - a cat clone with wings"><br>
|
||||||
|
<a href="https://travis-ci.org/sharkdp/bat"><img src="https://travis-ci.org/sharkdp/bat.svg?branch=master" alt="Build Status"></a>
|
||||||
|
<a href="https://ci.appveyor.com/project/sharkdp/bat"><img src="https://ci.appveyor.com/api/projects/status/cptsmtbiwbnr2vhf?svg=true"></a>
|
||||||
|
<img src="https://img.shields.io/crates/l/bat.svg" alt="license">
|
||||||
|
<a href="https://crates.io/crates/bat"><img src="https://img.shields.io/crates/v/bat.svg?colorB=319e8c" alt="Version info"></a><br>
|
||||||
|
A <i>cat(1)</i> clone with syntax highlighting and Git integration.
|
||||||
|
</p>
|
||||||
|
|
||||||
[](https://travis-ci.org/sharkdp/bat)
|
<p align="center">
|
||||||
[](https://crates.io/crates/bat)
|
<a href="#syntax-highlighting">Key Features</a> •
|
||||||
|
<a href="#how-to-use">How To Use</a> •
|
||||||
A *cat(1)* clone with syntax highlighting and Git integration.
|
<a href="#installation">Installation</a> •
|
||||||
|
<a href="#customization">Customization</a> •
|
||||||
## Features
|
<a href="#project-goals-and-alternatives">Project goals, alternatives</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
### Syntax highlighting
|
### Syntax highlighting
|
||||||
|
|
||||||
`bat` supports syntax highlighting for a large number of programming and markup languages:
|
`bat` supports syntax highlighting for a large number of programming and markup
|
||||||
|
languages:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Git integration
|
### Git integration
|
||||||
|
|
||||||
`bat` communicates with `git` to show modifications with respect to the index (see left side bar):
|
`bat` communicates with `git` to show modifications with respect to the index
|
||||||
|
(see left side bar):
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### Automatic paging
|
||||||
|
|
||||||
|
`bat` can pipe its own output to `less` if the output is too large for one screen.
|
||||||
|
|
||||||
|
### File concatenation
|
||||||
|
|
||||||
|
Oh.. you can also use it to concatenate files :wink:. Whenever
|
||||||
|
`bat` detects a non-interactive terminal, it will fall back to printing
|
||||||
|
the plain file contents.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
Display a single file on the terminal
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> bat README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Display multiple files at once
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> bat src/*.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
Read from stdin, determine the syntax automatically
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> curl -s https://sh.rustup.rs | bat
|
||||||
|
```
|
||||||
|
|
||||||
|
Read from stdin, specify the language explicitly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> yaml2json .travis.yml | json_pp | bat -l json
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
As a replacement for `cat`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bat > note.md # quickly create a new file
|
||||||
|
|
||||||
|
bat header.md content.md footer.md > document.md
|
||||||
|
|
||||||
|
bat -n main.rs # show line numbers (only)
|
||||||
|
|
||||||
|
bat f - g # output 'f', then stdin, then 'g'.
|
||||||
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Check out the [Release page](https://github.com/sharkdp/bat/releases) for binary builds and Debian packages.
|
### On Ubuntu
|
||||||
|
*... and other Debian-based Linux distributions.*
|
||||||
|
|
||||||
|
Download the latest `.deb` package from the [release page](https://github.com/sharkdp/bat/releases)
|
||||||
|
and install it via:
|
||||||
|
``` bash
|
||||||
|
sudo dpkg -i bat_0.8.0_amd64.deb # adapt version number and architecture
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Arch Linux
|
||||||
|
|
||||||
|
You can install [the `bat` package](https://www.archlinux.org/packages/community/x86_64/bat/)
|
||||||
|
from the official sources:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pacman -S bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Void Linux
|
||||||
|
|
||||||
|
You can install `bat` via xbps-install:
|
||||||
|
```
|
||||||
|
xbps-install -S bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### On FreeBSD
|
||||||
|
|
||||||
|
You can install a precompiled [`bat` package](https://www.freshports.org/textproc/bat) with pkg:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pkg install bat
|
||||||
|
```
|
||||||
|
|
||||||
|
or build it on your own from the FreeBSD ports:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /usr/ports/textproc/bat
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via nix
|
||||||
|
|
||||||
|
You can install `bat` using the [nix package manager](https://nixos.org/nix):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix-env -i bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### On macOS
|
||||||
|
|
||||||
|
You can install `bat` with [Homebrew](http://braumeister.org/formula/bat):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Windows
|
||||||
|
|
||||||
|
You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases),
|
||||||
|
or install it with [scoop](https://scoop.sh/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scoop install bat
|
||||||
|
```
|
||||||
|
|
||||||
|
[See below](#using-bat-on-windows) for notes.
|
||||||
|
|
||||||
|
### Via Docker
|
||||||
|
|
||||||
|
There is a [Docker image](https://hub.docker.com/r/danlynn/bat/) that you can use to run `bat` in a container:
|
||||||
|
```bash
|
||||||
|
docker pull danlynn/bat
|
||||||
|
alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via Ansible
|
||||||
|
|
||||||
|
You can install `bat` with [Ansible](https://www.ansible.com/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install role on local machine
|
||||||
|
ansible-galaxy install aeimer.install_bat
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# Playbook to install bat
|
||||||
|
- host: all
|
||||||
|
roles:
|
||||||
|
- aeimer.install_bat
|
||||||
|
```
|
||||||
|
|
||||||
|
- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat)
|
||||||
|
- [GitHub](https://github.com/aeimer/ansible-install-bat)
|
||||||
|
|
||||||
|
This should work with the following distributions:
|
||||||
|
- Debian/Ubuntu
|
||||||
|
- ARM (eg. Raspberry PI)
|
||||||
|
- Arch Linux
|
||||||
|
- Void Linux
|
||||||
|
- FreeBSD
|
||||||
|
- MacOS
|
||||||
|
|
||||||
|
### From binaries
|
||||||
|
|
||||||
|
Check out the [Release page](https://github.com/sharkdp/bat/releases) for
|
||||||
|
prebuilt versions of `bat` for many different architectures. Statically-linked
|
||||||
|
binaries are available, just look for releases with `musl` in the name on the
|
||||||
|
releases page.
|
||||||
|
|
||||||
### From source
|
### From source
|
||||||
|
|
||||||
If you want to build to compile `bat` from source, you need Rust 1.22 or higher.
|
If you want to build `bat` from source, you need Rust 1.29 or
|
||||||
Make sure that you have the devel-version of libopenssl installed (see instructions
|
higher. You can then use `cargo` to build everything:
|
||||||
[here](https://github.com/sfackler/rust-openssl)). You can then use `cargo` to build everything:
|
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
cargo install bat
|
cargo install bat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You may have to install `cmake` and the `libz` development package
|
||||||
|
(`libz-dev` or `libz-devel`) in order for the build to succeed.
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
`bat` uses the excellent [`syntect`](https://github.com/trishume/syntect/) library for syntax highlighting. `syntect` can read any Sublime Text language definition and theme.
|
### Highlighting theme
|
||||||
|
|
||||||
To build your own language-set and theme, follow these steps:
|
Use `bat --list-themes` to get a list of all available themes for syntax
|
||||||
|
highlighting. To select the `TwoDark` theme, call `bat` with the
|
||||||
|
`--theme=TwoDark` option or set the `BAT_THEME` environment variable to
|
||||||
|
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to
|
||||||
|
make the change permanent.
|
||||||
|
|
||||||
Create a folder with a syntax highlighting theme:
|
If you want to preview the different themes on a custom file, you can use
|
||||||
|
the following command (you need [`fzf`](https://github.com/junegunn/fzf) for this):
|
||||||
``` bash
|
``` bash
|
||||||
mkdir -p ~/.config/bat/themes
|
bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
|
||||||
cd ~/.config/bat/themes
|
|
||||||
|
|
||||||
# Download a theme, for example:
|
|
||||||
git clone https://github.com/jonschlinkert/sublime-monokai-extended
|
|
||||||
|
|
||||||
# Create a 'Default.tmTheme' link
|
|
||||||
ln -s "sublime-monokai-extended/Monokai Extended.tmTheme" Default.tmTheme
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a folder with language definition files:
|
`bat` looks good on a dark background by default. However, if your terminal uses a
|
||||||
``` bash
|
light background, some themes will work better for you. For example, the `GitHub`
|
||||||
mkdir -p ~/.config/bat/syntax
|
theme is made for light backgrounds. You can also make your own theme by following the
|
||||||
cd ~/.config/bat/syntax
|
['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes).
|
||||||
|
|
||||||
# Download some language definition files, for example:
|
### Output style
|
||||||
git clone https://github.com/sublimehq/Packages/
|
|
||||||
rm -rf Packages/Markdown
|
You can use the `--style` option to control the appearance of `bat`s output.
|
||||||
git clone https://github.com/jonschlinkert/sublime-markdown-extended
|
You can use `--style=numbers,changes`, for example, to show only Git changes
|
||||||
|
and line numbers but no grid and no file header. Use the `BAT_STYLE` environment
|
||||||
|
variable to make these changes permanent.
|
||||||
|
|
||||||
|
### Adding new syntaxes / language definitions
|
||||||
|
|
||||||
|
`bat` uses the excellent [`syntect`](https://github.com/trishume/syntect/)
|
||||||
|
library for syntax highlighting. `syntect` can read any
|
||||||
|
[Sublime Text `.sublime-syntax` file](https://www.sublimetext.com/docs/3/syntax.html)
|
||||||
|
and theme. To add new syntax definitions, do the following.
|
||||||
|
|
||||||
|
Create a folder with syntax definition files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BAT_CONFIG_DIR="$(bat cache --config-dir)"
|
||||||
|
|
||||||
|
mkdir -p "$BAT_CONFIG_DIR/syntaxes"
|
||||||
|
cd "$BAT_CONFIG_DIR/syntaxes"
|
||||||
|
|
||||||
|
# Put new '.sublime-syntax' language definition files
|
||||||
|
# in this folder (or its subdirectories), for example:
|
||||||
|
git clone https://github.com/tellnobody1/sublime-purescript-syntax
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, use the following command to parse all these files into a binary
|
Now use the following command to parse these files into a binary cache:
|
||||||
cache:
|
|
||||||
``` bash
|
```bash
|
||||||
bat init-cache
|
bat cache --init
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Finally, use `bat --list-languages` to check if the new languages are available.
|
||||||
|
|
||||||
|
If you ever want to go back to the default settings, call:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bat cache --clear
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding new themes
|
||||||
|
|
||||||
|
This works very similar to how we add new syntax definitions.
|
||||||
|
|
||||||
|
First, create a folder with the new syntax highlighting themes:
|
||||||
|
```bash
|
||||||
|
BAT_CONFIG_DIR="$(bat cache --config-dir)"
|
||||||
|
|
||||||
|
mkdir -p "$BAT_CONFIG_DIR/themes"
|
||||||
|
cd "$BAT_CONFIG_DIR/themes"
|
||||||
|
|
||||||
|
# Download a theme in '.tmTheme' format, for example:
|
||||||
|
git clone https://github.com/greggb/sublime-snazzy
|
||||||
|
|
||||||
|
# Update the binary cache
|
||||||
|
bat cache --init
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, use `bat --list-themes` to check if the new themes are available.
|
||||||
|
|
||||||
|
### Using a different pager
|
||||||
|
|
||||||
|
`bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not
|
||||||
|
set, `less` is used by default. If you want to use a different pager, you can either modify the
|
||||||
|
`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in
|
||||||
|
`PAGER`.
|
||||||
|
|
||||||
|
If you want to pass command-line arguments to the pager, you need to create a small shell
|
||||||
|
script as a wrapper, for example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
less --tabs 4 -R "$@"
|
||||||
|
```
|
||||||
|
(put this in a file `~/.bat-pager.sh`, make it executable `chmod +x ~/.bat-pager.sh` and use
|
||||||
|
`export BAT_PAGER="$HOME/.bat-pager.sh"` in your shells `rc` file)
|
||||||
|
|
||||||
|
**Note**: By default, if the pager is set to `less`, `bat` will pass the following command line
|
||||||
|
options to the pager: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` and `-X`/`--no-init`.
|
||||||
|
The first (`-R`) is needed to interpret ANSI colors correctly. The second option (`-F`) instructs
|
||||||
|
less to exit immediately if the output size is smaller than the vertical size of the terminal.
|
||||||
|
This is convenient for small files because you do not have to press `q` to quit the pager. The
|
||||||
|
third option (`-X`) is needed to fix a bug with the `--quit-if-one-screen` feature in old versions
|
||||||
|
of `less`. Unfortunately, it also breaks mouse-wheel support in `less`. If you want to enable
|
||||||
|
mouse-wheel scrolling, you can either pass just `-R` (as in the example above, this will disable
|
||||||
|
the quit-if-one-screen feature), or you can use a recent version of `less` and pass `-RF` which
|
||||||
|
will hopefully enable both quit-if-one-screen and mouse-wheel scrolling.
|
||||||
|
|
||||||
|
If scrolling still doesn't work for you, you can try to pass the `-S` option in addition.
|
||||||
|
|
||||||
|
## Using `bat` on Windows
|
||||||
|
|
||||||
|
`bat` mostly works out-of-the-box on Windows, but a few features may need extra configuration.
|
||||||
|
|
||||||
|
### Paging
|
||||||
|
|
||||||
|
Windows only includes a very limited pager in the form of `more`. You can download a Windows binary
|
||||||
|
for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through
|
||||||
|
Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in
|
||||||
|
your `PATH` or [define an environment variable](#using-a-different-pager).
|
||||||
|
|
||||||
|
### Colours
|
||||||
|
|
||||||
|
Windows 10 natively supports colours in both `conhost.exe` (Command Prompt) and PowerShell since
|
||||||
|
[v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)), as
|
||||||
|
well as in newer versions of bash. On earlier versions of Windows, you can use
|
||||||
|
[Cmder](http://cmder.net/), which includes [ConEmu](https://conemu.github.io/).
|
||||||
|
|
||||||
|
**Note:** The Git and MSYS versions of `less` do not correctly interpret colours on Windows. If you
|
||||||
|
don’t have any other pagers installed, you can disable paging entirely by passing `--paging=never`
|
||||||
|
or by setting `BAT_PAGER` to an empty string.
|
||||||
|
|
||||||
|
### Cygwin
|
||||||
|
|
||||||
|
`bat` on Windows does not natively support Cygwin's unix-style paths (`/cygdrive/*`). When passed an absolute cygwin path as an argument, `bat` will encounter the following error: `The system cannot find the path specified. (os error 3)`
|
||||||
|
|
||||||
|
This can be solved by creating a wrapper or adding the following function to your `.bash_profile` file:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
bat() {
|
||||||
|
local index
|
||||||
|
local args=("$@")
|
||||||
|
for index in $(seq 0 ${#args[@]}) ; do
|
||||||
|
case "${args[index]}" in
|
||||||
|
-*) continue;;
|
||||||
|
*) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
command bat "${args[@]}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Terminals & colors
|
||||||
|
|
||||||
|
`bat` handles terminals *with* and *without* truecolor support. However, the colors in the syntax
|
||||||
|
highlighting themes are not optimized for 8-bit colors and it is therefore strongly recommended
|
||||||
|
that you use a terminal with 24-bit truecolor support (`terminator`, `konsole`, `iTerm2`, ...).
|
||||||
|
See [this article](https://gist.github.com/XVilka/8346728) for more details and a full list of
|
||||||
|
terminals with truecolor support.
|
||||||
|
|
||||||
|
Make sure that your truecolor terminal sets the `COLORTERM` variable to either `truecolor` or
|
||||||
|
`24bit`. Otherwise, `bat` will not be able to determine whether or not 24-bit escape sequences
|
||||||
|
are supported (and fall back to 8-bit colors).
|
||||||
|
|
||||||
|
### Line numbers and grid are hardly visible
|
||||||
|
|
||||||
|
Please try a different theme (see `bat --list-themes` for a list). The `OneHalfDark` and
|
||||||
|
`OneHalfLight` themes provide grid and line colors that are brighter.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recursive clone to retrieve all submodules
|
||||||
|
git clone --recursive https://github.com/sharkdp/bat
|
||||||
|
|
||||||
|
# Build (debug version)
|
||||||
|
cd bat
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
# Run unit tests and integration tests
|
||||||
|
cargo test
|
||||||
|
|
||||||
|
# Install (release version)
|
||||||
|
cargo install
|
||||||
|
|
||||||
|
# Build a bat binary with modified syntaxes and themes
|
||||||
|
bash assets/create.sh
|
||||||
|
cargo install -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project goals and alternatives
|
||||||
|
|
||||||
|
`bat` tries to achieve the following goals:
|
||||||
|
|
||||||
|
- Provide beautiful, advanced syntax highlighting
|
||||||
|
- Integrate with Git to show file modifications
|
||||||
|
- Be a drop-in replacement for (POSIX) `cat`
|
||||||
|
- Offer a user-friendly command-line interface
|
||||||
|
|
||||||
|
There are a lot of alternatives, if you are looking for similar programs. See
|
||||||
|
[this document](doc/alternatives.md) for a comparison.
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
environment:
|
||||||
|
global:
|
||||||
|
TARGET: x86_64-pc-windows-msvc
|
||||||
|
RUST_VERSION: stable
|
||||||
|
CRATE_NAME: bat
|
||||||
|
CARGO_HOME: "c:\\cargo"
|
||||||
|
RUSTUP_HOME: "c:\\rustup"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||||
|
- rustup-init.exe -y --default-host %TARGET%
|
||||||
|
- set PATH=%PATH%;C:\cargo\bin
|
||||||
|
- rustc -Vv
|
||||||
|
- cargo -V
|
||||||
|
|
||||||
|
build: false
|
||||||
|
test_script:
|
||||||
|
- cargo test --target %TARGET% --verbose
|
||||||
|
- cargo run --target %TARGET% -- src/main.rs README.md --paging=never
|
||||||
|
|
||||||
|
before_deploy:
|
||||||
|
# Generate artifacts for release
|
||||||
|
- cargo build --release --verbose
|
||||||
|
- ps: ci\before_deploy.ps1
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
description: 'Automatically deployed release'
|
||||||
|
artifact: /.*\.zip/
|
||||||
|
# Here's how:
|
||||||
|
# - Go to 'https://github.com/settings/tokens/new' and generate a Token with only the
|
||||||
|
# `public_repo` scope enabled
|
||||||
|
# - Then go to 'https://ci.appveyor.com/tools/encrypt' and enter the newly generated token.
|
||||||
|
# - Enter the "encrypted value" below
|
||||||
|
auth_token:
|
||||||
|
secure: oO4/J+hcFXgXcEqEc8gzlQNqLG0IxU78s4EyH+uczGdsyWajb3yipxPR6nXUvmoj
|
||||||
|
provider: GitHub
|
||||||
|
on:
|
||||||
|
RUST_VERSION: stable
|
||||||
|
appveyor_repo_tag: true
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- C:\Users\appveyor\.cargo\registry
|
||||||
|
- target
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
- provider: Email
|
||||||
|
on_build_success: false
|
||||||
|
on_build_failure: false
|
||||||
|
on_build_status_changed: false
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
syntaxes/*
|
||||||
|
themes/*
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
diff --git syntaxes/Packages/Java/JavaDoc.sublime-syntax syntaxes/Packages/Java/JavaDoc.sublime-syntax
|
||||||
|
index 422a6a9..40a741e 100644
|
||||||
|
--- syntaxes/Packages/Java/JavaDoc.sublime-syntax
|
||||||
|
+++ syntaxes/Packages/Java/JavaDoc.sublime-syntax
|
||||||
|
@@ -13,7 +13,7 @@ variables:
|
||||||
|
contexts:
|
||||||
|
prototype:
|
||||||
|
# https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#leadingasterisks
|
||||||
|
- - match: ^\s*(\*)\s*(?!\s*@)
|
||||||
|
+ - match: ^\s*(\*)(?!/)\s*(?!\s*@)
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.javadoc
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
## Syntax Highlighting in bat
|
||||||
|
|
||||||
|
`bat` uses the [syntect](https://github.com/trishume/syntect) library to highlight source
|
||||||
|
code. As a basis, syntect uses [Sublime Text](https://www.sublimetext.com/) syntax definitions
|
||||||
|
in the `.sublime-syntax` format.
|
||||||
|
|
||||||
|
In order to add new syntaxes to `bat`, follow these steps:
|
||||||
|
|
||||||
|
1. Find a Sublime Text syntax for the given language, preferably in a separate Git repository
|
||||||
|
which can be included as a submodule (under `assets/syntaxes`).
|
||||||
|
|
||||||
|
2. If the Sublime Text syntax is only available as a `.tmLanguage` file, open the file in
|
||||||
|
Sublime Text and convert it to a `.sublime-syntax` file via *Tools* -> *Developer* ->
|
||||||
|
*New Syntax from XXX.tmLanguage...*. Save the new file in the `assets/syntaxes` folder.
|
||||||
|
|
||||||
|
3. Run the `create.sh` script. It calls `bat cache --init` to parse all available
|
||||||
|
`.sublime-syntax` files and serialize them to a `syntaxes.bin` file (in this folder).
|
||||||
|
|
||||||
|
4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the
|
||||||
|
`bat` binary.
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
Make sure that the local cache does not interfere with the internally stored syntaxes and
|
||||||
|
themes (`bat cache --clear`).
|
||||||
|
|
||||||
|
### Manual modifications
|
||||||
|
|
||||||
|
The following files have been manually modified after converting from a `.tmLanguage` file:
|
||||||
|
|
||||||
|
* `Dart.sublime-syntax` => removed `#regex.dart` include.
|
||||||
|
* `INI.sublime-syntax` => added `.hgrc` and `hgrc` file types.
|
||||||
Regular → Executable
+11
-22
@@ -1,27 +1,16 @@
|
|||||||
set -e
|
#!/bin/bash
|
||||||
|
|
||||||
THEME_FOLDER="$HOME/.config/bat/themes"
|
ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
SYNTAX_FOLDER="$HOME/.config/bat/syntax"
|
|
||||||
|
|
||||||
if [ ! -e "$THEME_FOLDER" ]; then
|
# Always remove the local cache to avoid any confusion
|
||||||
mkdir -p "$THEME_FOLDER"
|
bat cache --clear
|
||||||
(
|
|
||||||
cd "$THEME_FOLDER"
|
|
||||||
git clone https://github.com/jonschlinkert/sublime-monokai-extended
|
|
||||||
ln -s "sublime-monokai-extended/Monokai Extended.tmTheme" Default.tmTheme
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -e "$SYNTAX_FOLDER" ]; then
|
# TODO: Remove this (and the reverse part below) when
|
||||||
mkdir -p "$SYNTAX_FOLDER"
|
# https://github.com/trishume/syntect/issues/160 has been fixed
|
||||||
(
|
JAVADOC_FILE="${ASSET_DIR}/syntaxes/Packages/Java/JavaDoc.sublime-syntax"
|
||||||
cd "$SYNTAX_FOLDER"
|
JAVADOC_PATCH="${ASSET_DIR}/JavaDoc.sublime-syntax.patch"
|
||||||
git clone https://github.com/sublimehq/Packages/
|
patch "$JAVADOC_FILE" "$JAVADOC_PATCH"
|
||||||
rm -rf Packages/Markdown
|
|
||||||
git clone https://github.com/jonschlinkert/sublime-markdown-extended
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
bat init-cache
|
bat cache --init --blank --source="$ASSET_DIR" --target="$ASSET_DIR"
|
||||||
|
|
||||||
cp "$HOME/.cache/bat"/* .
|
patch -R "$JAVADOC_FILE" "$JAVADOC_PATCH"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Submodule
+1
Submodule assets/syntaxes/AWK added at 1ce5f90d44
Submodule
+1
Submodule assets/syntaxes/CMake added at aba96a0862
Submodule
+1
Submodule assets/syntaxes/CSV added at 4786d037a7
@@ -0,0 +1,46 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Advanced CSV
|
||||||
|
file_extensions:
|
||||||
|
- csv
|
||||||
|
- tsv
|
||||||
|
scope: text.advanced_csv
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: (\")
|
||||||
|
captures:
|
||||||
|
1: string.quoted.double.advanced_csv
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.quoted.advanced_csv
|
||||||
|
- match: (\")
|
||||||
|
captures:
|
||||||
|
1: string.quoted.double.advanced_csv
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: '(\[([+-]?\d*)(\:)?([+-]?\d*)(\,)?([+-]?\d*)(\:)?([+-]?\d*)\])?\s*([<>v^])?\s*(=)'
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.advanced_csv
|
||||||
|
2: constant.numeric.formula.advanced_csv
|
||||||
|
4: constant.numeric.formula.advanced_csv
|
||||||
|
6: constant.numeric.formula.advanced_csv
|
||||||
|
8: constant.numeric.formula.advanced_csv
|
||||||
|
9: keyword.operator.advanced_csv
|
||||||
|
10: keyword.operator.advanced_csv
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.range.advanced_csv
|
||||||
|
- match: (?=(\")|$)
|
||||||
|
pop: true
|
||||||
|
- include: scope:source.python
|
||||||
|
- match: '(?<=^|,|\s|\")([0-9.eE+-]+)(?=$|,|\s|\")'
|
||||||
|
scope: meta.number.advanced_csv
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.advanced_csv
|
||||||
|
- match: '(?<=^|,|\s|\")([^, \t\"]+)(?=$|,|\s|\")'
|
||||||
|
scope: meta.nonnumber.advanced_csv
|
||||||
|
captures:
|
||||||
|
1: storage.type.advanced_csv
|
||||||
|
- match: (\,)
|
||||||
|
scope: meta.delimiter.advanced_csv
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.advanced_csv
|
||||||
Submodule
+1
Submodule assets/syntaxes/Cabal added at 1c054d9b36
@@ -0,0 +1,47 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Cabal
|
||||||
|
file_extensions:
|
||||||
|
- cabal
|
||||||
|
scope: source.cabal
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: ^(\s*)(exposed-modules):$
|
||||||
|
captures:
|
||||||
|
2: constant.other.cabal
|
||||||
|
push:
|
||||||
|
- meta_scope: exposed.modules.cabal
|
||||||
|
- match: ^(?!\1\s)
|
||||||
|
pop: true
|
||||||
|
- include: module_name
|
||||||
|
- match: ^(\s*)(build-depends):$
|
||||||
|
captures:
|
||||||
|
2: constant.other.cabal
|
||||||
|
push:
|
||||||
|
- meta_scope: exposed.modules.cabal
|
||||||
|
- match: ^(?!\1\s)
|
||||||
|
pop: true
|
||||||
|
- match: "([<>=]+)|([&|]+)"
|
||||||
|
scope: keyword.operator.haskell
|
||||||
|
- match: ((\d+|\*)\.)*(\d+|\*)
|
||||||
|
scope: constant.numeric.haskell
|
||||||
|
- match: '([\w\-]+)'
|
||||||
|
scope: support.function.haskell
|
||||||
|
- match: '^\s*([a-zA-Z_-]+)(:)\s+'
|
||||||
|
scope: entity.cabal
|
||||||
|
captures:
|
||||||
|
1: constant.other.cabal
|
||||||
|
2: punctuation.entity.cabal
|
||||||
|
- match: '^(?i)(executable|library|test-suite|benchmark|flag|source-repository)\s+([^\s,]+)\s*$'
|
||||||
|
scope: entity.cabal
|
||||||
|
captures:
|
||||||
|
1: keyword.entity.cabal
|
||||||
|
2: string.cabal
|
||||||
|
- match: ^(?i)library\s*$
|
||||||
|
scope: keyword.entity.cabal
|
||||||
|
- match: "--.*$"
|
||||||
|
scope: comment.cabal
|
||||||
|
module_name:
|
||||||
|
- match: '([A-Z][A-Za-z_''0-9]*)(\.[A-Z][A-Za-z_''0-9]*)*'
|
||||||
|
scope: storage.module.haskell
|
||||||
Submodule
+1
Submodule assets/syntaxes/Crystal added at 2f96cec2ca
File diff suppressed because it is too large
Load Diff
Submodule
+1
Submodule assets/syntaxes/Dart added at d891fb36c9
@@ -0,0 +1,369 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Dart
|
||||||
|
file_extensions:
|
||||||
|
- dart
|
||||||
|
scope: source.dart
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: ^(#!.*)$
|
||||||
|
scope: meta.preprocessor.script.dart
|
||||||
|
- match: ^\s*\b(library|import|export|part of|part)\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.import.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.dart
|
||||||
|
- match: ;
|
||||||
|
captures:
|
||||||
|
0: punctuation.terminator.dart
|
||||||
|
pop: true
|
||||||
|
- include: strings
|
||||||
|
- match: \b(as|show|hide|deferred)\b
|
||||||
|
scope: keyword.other.import.dart
|
||||||
|
- include: comments
|
||||||
|
- include: constants-and-special-vars
|
||||||
|
- include: annotations
|
||||||
|
- include: decl-typedef
|
||||||
|
- include: decl-class
|
||||||
|
- include: decl-enum
|
||||||
|
- include: decl-function
|
||||||
|
- include: keywords
|
||||||
|
- include: strings
|
||||||
|
annotations:
|
||||||
|
- match: '^(?:\s*)((@)([a-zA-Z0-9_]+))'
|
||||||
|
captures:
|
||||||
|
1: annotation.dart
|
||||||
|
2: entity.name.function.annotation.dart
|
||||||
|
3: support.type.dart
|
||||||
|
comments:
|
||||||
|
- match: /\*\*/
|
||||||
|
scope: comment.block.empty.dart
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.dart
|
||||||
|
- include: comments-inline
|
||||||
|
comments-inline:
|
||||||
|
- match: /\*
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.dart
|
||||||
|
- match: \*/
|
||||||
|
pop: true
|
||||||
|
- include: scope:text.dart-doccomments
|
||||||
|
- match: (///)
|
||||||
|
captures:
|
||||||
|
1: marker.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.line.triple-slash.dart
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- include: scope:text.dart-doccomments
|
||||||
|
- match: (//)
|
||||||
|
captures:
|
||||||
|
1: marker.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.line.double-slash.dart
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- include: scope:text.dart-doccomments
|
||||||
|
constants-and-special-vars:
|
||||||
|
- match: \b(true|false|null)\b
|
||||||
|
scope: constant.language.dart
|
||||||
|
- match: \b(this|super)\b
|
||||||
|
scope: variable.language.dart
|
||||||
|
- match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)\b'
|
||||||
|
scope: constant.numeric.dart
|
||||||
|
decl-class:
|
||||||
|
- match: \bclass\b
|
||||||
|
captures:
|
||||||
|
0: keyword.control.new.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.class.dart
|
||||||
|
- match: "(?={)"
|
||||||
|
pop: true
|
||||||
|
- include: keywords
|
||||||
|
- match: "[A-Za-z_][A-Za-z0-9_]*"
|
||||||
|
scope: class.name.dart
|
||||||
|
decl-enum:
|
||||||
|
- match: \benum\b
|
||||||
|
captures:
|
||||||
|
0: keyword.declaration.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.enum.dart
|
||||||
|
- match: "(?={)"
|
||||||
|
pop: true
|
||||||
|
- include: keywords
|
||||||
|
- match: "[A-Za-z_][A-Za-z0-9_]*"
|
||||||
|
scope: enum.name.dart
|
||||||
|
decl-function:
|
||||||
|
- match: ^\s*(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(get)\s+(\w+)\s+(?==>)
|
||||||
|
comment: A getter with a primitive return type.
|
||||||
|
scope: meta.declaration.function.dart
|
||||||
|
captures:
|
||||||
|
1: storage.type.primitive.dart
|
||||||
|
2: keyword.declaration.dart
|
||||||
|
3: function.name.dart
|
||||||
|
- match: ^\s*(?:\b(\w+)\b\s+)?(get)\s+(\w+)\s+(?==>)
|
||||||
|
comment: A getter with a user-defined return type or no return type.
|
||||||
|
scope: meta.declaration.function.dart
|
||||||
|
captures:
|
||||||
|
1: type.user-defined.dart
|
||||||
|
2: keyword.declaration.dart
|
||||||
|
3: function.name.dart
|
||||||
|
- match: ^\s*(set)\s+(\w+)(?=\()
|
||||||
|
comment: A setter.
|
||||||
|
captures:
|
||||||
|
1: keyword.declaration.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: comments-inline
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: ^\s*(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(\w+)(?=\()
|
||||||
|
comment: A function with a primitive return type.
|
||||||
|
captures:
|
||||||
|
1: storage.type.primitive.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: comments-inline
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: ^\s*(?:\b(return)\b)\s+(\w+)(?=\()
|
||||||
|
comment: A function invocation after 'return'
|
||||||
|
captures:
|
||||||
|
1: keyword.control.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.invocation.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: comments-inline
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: ^\s*\b(new)\b\s+(\w+)(?=\()
|
||||||
|
comment: A class instantiation after 'new'
|
||||||
|
captures:
|
||||||
|
1: keyword.declaration.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.invocation.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: comments-inline
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
decl-function-parameter:
|
||||||
|
- include: constants-and-special-vars
|
||||||
|
- match: (?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(\w+)(?=\()
|
||||||
|
comment: A function with a primitive return type.
|
||||||
|
captures:
|
||||||
|
1: storage.type.primitive.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.parameter.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: \b(new)\b\s+(\w+)(?=\()
|
||||||
|
comment: A class instantiation after 'new'
|
||||||
|
captures:
|
||||||
|
1: keyword.declaration.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.invocation.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: (?:\b(\w+)\b)\s+(\w+)(?=\()
|
||||||
|
comment: A function with a user-defined return type.
|
||||||
|
captures:
|
||||||
|
1: type.user-defined.dart
|
||||||
|
2: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.parameter.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
- match: (\w+)(?=\()
|
||||||
|
comment: A function with no return type.
|
||||||
|
captures:
|
||||||
|
1: function.name.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.parameter.function.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: decl-function-parameter
|
||||||
|
- include: strings
|
||||||
|
- include: keywords
|
||||||
|
decl-typedef:
|
||||||
|
- match: typedef
|
||||||
|
captures:
|
||||||
|
0: keyword.control.new.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.declaration.typedef.dart
|
||||||
|
- match: ;
|
||||||
|
captures:
|
||||||
|
0: punctuation.terminator.dart
|
||||||
|
pop: true
|
||||||
|
- match: '(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b|([a-zA-Z_][a-zA-Z0-9_]*))\s+([a-zA-Z_][a-zA-Z0-9_]+)'
|
||||||
|
captures:
|
||||||
|
1: storage.type.primitive.dart
|
||||||
|
2: typedef.return.dart
|
||||||
|
3: typedef.name.dart
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- meta_scope: typedef.params.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: keywords
|
||||||
|
keywords:
|
||||||
|
- match: \bassert\b
|
||||||
|
scope: keyword.control.assert.dart
|
||||||
|
- match: \bas\b
|
||||||
|
scope: keyword.cast.dart
|
||||||
|
- match: \b(try|catch|finally|throw|on|rethrow)\b
|
||||||
|
scope: keyword.control.catch-exception.dart
|
||||||
|
- match: \s+\?\s+|\s+:\s+
|
||||||
|
scope: keyword.control.ternary.dart
|
||||||
|
- match: \b(break|case|continue|default|do|else|for|if|in|return|switch|while)\b
|
||||||
|
scope: keyword.control.dart
|
||||||
|
- match: \b(async\*|async|await\*|await|yield)\b
|
||||||
|
scope: keyword.control.async.dart
|
||||||
|
- match: \b(new)\b
|
||||||
|
scope: keyword.control.new.dart
|
||||||
|
- match: \b(abstract|extends|external|factory|implements|with|interface|get|native|operator|set|typedef)\b
|
||||||
|
scope: keyword.declaration.dart
|
||||||
|
- match: \b(is\!?)\b
|
||||||
|
scope: keyword.operator.dart
|
||||||
|
- match: (<<|>>>?|~|\^|\||&)
|
||||||
|
scope: keyword.operator.bitwise.dart
|
||||||
|
- match: ((&|\^|\||<<|>>>?)=)
|
||||||
|
scope: keyword.operator.assignment.bitwise.dart
|
||||||
|
- match: (===?|!==?|<=?|>=?)
|
||||||
|
scope: keyword.operator.comparison.dart
|
||||||
|
- match: '(([+*/%-]|\~)=)'
|
||||||
|
scope: keyword.operator.assignment.arithmetic.dart
|
||||||
|
- match: (=)
|
||||||
|
scope: keyword.operator.assignment.dart
|
||||||
|
- match: (\-\-|\+\+)
|
||||||
|
scope: keyword.operator.increment-decrement.dart
|
||||||
|
- match: (\-|\+|\*|\/|\~\/|%)
|
||||||
|
scope: keyword.operator.arithmetic.dart
|
||||||
|
- match: (!|&&|\|\|)
|
||||||
|
scope: keyword.operator.logical.dart
|
||||||
|
- match: ;
|
||||||
|
scope: punctuation.terminator.dart
|
||||||
|
- match: \b(static|final|const)\b
|
||||||
|
scope: storage.modifier.dart
|
||||||
|
- match: \b(?:void|bool|num|int|double|dynamic|var|String|List|Map)\b
|
||||||
|
scope: storage.type.primitive.dart
|
||||||
|
regexp:
|
||||||
|
- match: '\\[^''"]'
|
||||||
|
scope: constant.character.escaped.regex.dart
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- meta_content_scope: meta.capture.regex.dart
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- match: \?(:|=|!)
|
||||||
|
scope: ignore.capture.regex.dart
|
||||||
|
- match: \*|\+|\?|\.|\|
|
||||||
|
scope: keyword.other.regex.dart
|
||||||
|
- match: \^|\$
|
||||||
|
scope: keyword.other.regex.dart
|
||||||
|
- match: \.
|
||||||
|
scope: constant.other.regex.dart
|
||||||
|
- match: '\[(\^)?'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.negation.regex.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: constant.character.range.regex.dart
|
||||||
|
- match: '\]'
|
||||||
|
pop: true
|
||||||
|
- match: '\\[^"'']'
|
||||||
|
scope: constant.character.escaped.regex.dart
|
||||||
|
- match: '\{(?:\d+)?,(?:\d+)?\}'
|
||||||
|
scope: keyword.other.regex.dart
|
||||||
|
string-interp:
|
||||||
|
- match: '(\$)(\{)'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.dart
|
||||||
|
2: keyword.other.dart
|
||||||
|
push:
|
||||||
|
- meta_scope: interpolation.dart
|
||||||
|
- meta_content_scope: source.dart
|
||||||
|
- match: '(\})'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.dart
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: (\$)(\w+)
|
||||||
|
captures:
|
||||||
|
1: keyword.other.dart
|
||||||
|
2: variable.parameter.dart
|
||||||
|
- match: \\.
|
||||||
|
scope: constant.character.escape.dart
|
||||||
|
strings:
|
||||||
|
- match: (?<!r)"""
|
||||||
|
push:
|
||||||
|
- meta_scope: string.interpolated.triple.double.dart
|
||||||
|
- match: '"""(?!")'
|
||||||
|
pop: true
|
||||||
|
- include: string-interp
|
||||||
|
- match: (?<!r)'''
|
||||||
|
push:
|
||||||
|
- meta_scope: string.interpolated.triple.single.dart
|
||||||
|
- match: "'''(?!')"
|
||||||
|
pop: true
|
||||||
|
- include: string-interp
|
||||||
|
- match: r"""
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.triple.double.dart
|
||||||
|
- match: '"""(?!")'
|
||||||
|
pop: true
|
||||||
|
- match: r'''
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.triple.single.dart
|
||||||
|
- match: "'''(?!')"
|
||||||
|
pop: true
|
||||||
|
- match: (?<!\\|r)"
|
||||||
|
push:
|
||||||
|
- meta_scope: string.interpolated.double.dart
|
||||||
|
- match: '"'
|
||||||
|
pop: true
|
||||||
|
- match: \n
|
||||||
|
scope: invalid.string.newline
|
||||||
|
- include: string-interp
|
||||||
|
- match: r"
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.dart
|
||||||
|
- match: '"'
|
||||||
|
pop: true
|
||||||
|
- include: regexp
|
||||||
|
- match: (?<!\|r)'
|
||||||
|
push:
|
||||||
|
- meta_scope: string.interpolated.single.dart
|
||||||
|
- match: "'"
|
||||||
|
pop: true
|
||||||
|
- include: string-interp
|
||||||
|
- match: r'
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.dart
|
||||||
|
- match: "'"
|
||||||
|
pop: true
|
||||||
|
- include: regexp
|
||||||
Submodule
+1
Submodule assets/syntaxes/Docker added at 6e521ead6c
Submodule
+1
Submodule assets/syntaxes/Elixir added at 044d9af8a1
Submodule
+1
Submodule assets/syntaxes/Elm added at dfbb8bdc9a
Submodule
+1
Submodule assets/syntaxes/FSharp added at da846f4227
@@ -0,0 +1,234 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: "F#"
|
||||||
|
file_extensions:
|
||||||
|
- fs
|
||||||
|
- fsi
|
||||||
|
- fsx
|
||||||
|
scope: source.fsharp
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: comments
|
||||||
|
- include: constants
|
||||||
|
- include: structure
|
||||||
|
- include: attributes
|
||||||
|
- include: strings
|
||||||
|
- include: definition
|
||||||
|
- include: method_calls
|
||||||
|
- include: modules
|
||||||
|
- include: anonymous_functions
|
||||||
|
- include: keywords
|
||||||
|
anonymous_functions:
|
||||||
|
- match: \b(fun)\b
|
||||||
|
captures:
|
||||||
|
1: keyword.other.function-definition.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.function.anonymous
|
||||||
|
- match: (->)
|
||||||
|
captures:
|
||||||
|
1: keyword.other.fsharp
|
||||||
|
pop: true
|
||||||
|
- include: variables
|
||||||
|
attributes:
|
||||||
|
- match: '\[\<'
|
||||||
|
push:
|
||||||
|
- meta_scope: support.function.attribute.fsharp
|
||||||
|
- match: '\>\]'
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
characters:
|
||||||
|
- match: (')
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.fsharp
|
||||||
|
- match: (')
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.end.fsharp
|
||||||
|
pop: true
|
||||||
|
- match: '\\$[ \t]*'
|
||||||
|
scope: punctuation.separator.string.ignore-eol.fsharp
|
||||||
|
- match: '\\([\\""ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
|
||||||
|
scope: constant.character.string.escape.fsharp
|
||||||
|
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
|
||||||
|
scope: invalid.illeagal.character.string.fsharp
|
||||||
|
comments:
|
||||||
|
- match: \(\*\*?(\*)\)
|
||||||
|
scope: comment.block.fsharp
|
||||||
|
captures:
|
||||||
|
1: comment.block.empty.fsharp
|
||||||
|
- match: '\(\*[^\)]'
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.fsharp
|
||||||
|
- match: \*\)
|
||||||
|
pop: true
|
||||||
|
- include: comments
|
||||||
|
- match: //.*$
|
||||||
|
scope: comment.line.double-slash.fsharp
|
||||||
|
constants:
|
||||||
|
- match: \(\)
|
||||||
|
scope: constant.language.unit.fsharp
|
||||||
|
- match: '\b-?[0-9][0-9_]*((\.([0-9][0-9_]*([eE][+-]??[0-9][0-9_]*)?)?)|([eE][+-]??[0-9][0-9_]*))'
|
||||||
|
scope: constant.numeric.floating-point.fsharp
|
||||||
|
- match: '\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))'
|
||||||
|
scope: constant.numeric.integer.nativeint.fsharp
|
||||||
|
definition:
|
||||||
|
- match: '\b(val|val|let|and|member|override|use)\s?(rec|inline|mutable)?(\s+\(?([a-zA-Z.\|_][a-zA-Z0-9.|_]*)\)?\w*)\b'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.binding.fsharp
|
||||||
|
2: keyword.other.function-recursive.fsharp
|
||||||
|
3: variable.other.binding.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.binding.fsharp
|
||||||
|
- match: "=|$"
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.function.type-constraint.fsharp
|
||||||
|
pop: true
|
||||||
|
- include: variables
|
||||||
|
- match: \b(let)\s+((\(\))|(_))\s+=
|
||||||
|
scope: meta.expression.fsharp
|
||||||
|
captures:
|
||||||
|
1: keyword.other.binding.fsharp
|
||||||
|
2: keyword.other.function-recursive.fsharp
|
||||||
|
4: constant.language.unit.fsharp
|
||||||
|
5: constant.language.ignored.fsharp
|
||||||
|
keywords:
|
||||||
|
- match: ^\s*#\s*(light|if|else|endif|r|I|load|time|help|quit)\b
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.preprocessor.fsharp
|
||||||
|
- match: (\s|$)
|
||||||
|
pop: true
|
||||||
|
- match: \b(new|in|as|if|then|else|elif|for|begin|end|match|with|type|inherit|true|false|null|do)\b
|
||||||
|
scope: keyword.other.fsharp
|
||||||
|
- match: '(\|>|\|?>|\->|\<\-|:>|:|\[|\]|\;|\||_)'
|
||||||
|
scope: entity.name
|
||||||
|
method_calls:
|
||||||
|
- match: '(?<!\w)([a-z]\w*)(\.)'
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.method-call.fsharp
|
||||||
|
- match: '[A-Z]\w*(\.)'
|
||||||
|
scope: meta.method.fsharp
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.method-call.fsharp
|
||||||
|
- match: (?=.)
|
||||||
|
pop: true
|
||||||
|
modules:
|
||||||
|
- match: '\b(namespace|module)\s+([a-zA-Z][a-zA-Z0-9''_.]*)'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.fsharp
|
||||||
|
2: entity.name.section.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.module.namespace.fsharp
|
||||||
|
- match: (\s|$)
|
||||||
|
pop: true
|
||||||
|
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
|
||||||
|
scope: support.other.module.fsharp
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.module-reference.fsharp
|
||||||
|
2: support.other.module.fsharp
|
||||||
|
- match: '\b(open)\s+([A-Z][a-zA-Z0-9''_]*)(?=(\.[A-Z][a-zA-Z0-9_]*)*)'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.fsharp
|
||||||
|
2: support.other.module.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.module.open.fsharp
|
||||||
|
- match: (\s|$)
|
||||||
|
pop: true
|
||||||
|
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
|
||||||
|
scope: support.other.module.fsharp
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.module-reference.fsharp
|
||||||
|
2: support.other.module.fsharp
|
||||||
|
- match: '^\s*(module)\s+([A-Z][a-zA-Z0-9''_]*)\s*(=)\s*([A-Z][a-zA-Z0-9''_]*)'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.module-definition.fsharp
|
||||||
|
2: entity.name.type.module.fsharp
|
||||||
|
3: punctuation.separator.module-definition.fsharp
|
||||||
|
4: support.other.module.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.module.alias.fsharp
|
||||||
|
- match: (\s|$)
|
||||||
|
pop: true
|
||||||
|
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
|
||||||
|
scope: support.other.module.fsharp
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.module-reference.fsharp
|
||||||
|
2: support.other.module.fsharp
|
||||||
|
- match: '(?<!\w)([A-Z][a-zA-Z0-9_]*)(\.)'
|
||||||
|
captures:
|
||||||
|
1: support.other.module.fsharp
|
||||||
|
2: punctuation.separator.module-reference.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.module.reference.fsharp
|
||||||
|
- match: '[A-Z][a-zA-Z0-9_]+(\.)'
|
||||||
|
scope: support.other.module.fsharp
|
||||||
|
captures:
|
||||||
|
1: punctuation.separator.module-reference.fsharp
|
||||||
|
- match: (?=.)
|
||||||
|
pop: true
|
||||||
|
strings:
|
||||||
|
- match: '(?=[^\\])(""")'
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.fsharp
|
||||||
|
- match: (""")
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.end.fsharp
|
||||||
|
pop: true
|
||||||
|
- match: '\\$[ \t]*'
|
||||||
|
scope: punctuation.separator.string.ignore-eol.fsharp
|
||||||
|
- match: '(?=[^\\])(@")'
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.fsharp
|
||||||
|
- match: (")
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.end.fsharp
|
||||||
|
pop: true
|
||||||
|
- match: '\\$[ \t]*'
|
||||||
|
scope: punctuation.separator.string.ignore-eol.fsharp
|
||||||
|
- match: '(?=[^\\])(")'
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.fsharp
|
||||||
|
- match: (")
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.end.fsharp
|
||||||
|
pop: true
|
||||||
|
- match: '\\$[ \t]*'
|
||||||
|
scope: punctuation.separator.string.ignore-eol.fsharp
|
||||||
|
- match: '\\([\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
|
||||||
|
scope: constant.character.string.escape.fsharp
|
||||||
|
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
|
||||||
|
scope: invalid.illeagal.character.string.fsharp
|
||||||
|
- match: '(?=[^\\])('')'
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.fsharp
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.fsharp
|
||||||
|
- match: (')
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.end.fsharp
|
||||||
|
pop: true
|
||||||
|
- match: '\\$[ \t]*'
|
||||||
|
scope: punctuation.separator.string.ignore-eol.fsharp
|
||||||
|
- match: '\\([\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
|
||||||
|
scope: constant.character.string.escape.fsharp
|
||||||
|
- match: '\\(?![\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
|
||||||
|
scope: invalid.illeagal.character.string.fsharp
|
||||||
|
structure:
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.paren-group.fsharp
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
variables:
|
||||||
|
- match: \(\)
|
||||||
|
scope: variable.parameter.unit.fsharp
|
||||||
|
- match: '[a-zA-Z]\w*'
|
||||||
|
scope: variable.parameter.fsharp
|
||||||
Submodule
+1
Submodule assets/syntaxes/INI added at 8dd3e316ad
@@ -0,0 +1,45 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: INI
|
||||||
|
file_extensions:
|
||||||
|
- ini
|
||||||
|
- INI
|
||||||
|
- inf
|
||||||
|
- INF
|
||||||
|
- reg
|
||||||
|
- REG
|
||||||
|
- lng
|
||||||
|
- cfg
|
||||||
|
- CFG
|
||||||
|
- url
|
||||||
|
- URL
|
||||||
|
- .editorconfig
|
||||||
|
- .hgrc
|
||||||
|
- hgrc
|
||||||
|
scope: source.ini
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: ^\s*(;|#).*$\n?
|
||||||
|
scope: comment.line.semicolon.ini
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.ini
|
||||||
|
- match: '^\s*(\[)(.*?)(\])'
|
||||||
|
scope: meta.tag.section.ini
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.section.ini
|
||||||
|
2: entity.section.ini
|
||||||
|
3: punctuation.definition.section.ini
|
||||||
|
- match: '^(\s*(["'']?)(.+?)(\2)\s*(=))?\s*((["'']?)(.*?)(\7))\s*(;.*)?$\n?'
|
||||||
|
scope: meta.declaration.ini
|
||||||
|
captures:
|
||||||
|
1: meta.property.ini
|
||||||
|
2: punctuation.definition.quote.ini
|
||||||
|
3: keyword.name.ini
|
||||||
|
4: punctuation.definition.quote.ini
|
||||||
|
5: punctuation.definition.equals.ini
|
||||||
|
6: meta.value.ini
|
||||||
|
7: punctuation.definition.quote.ini
|
||||||
|
8: string.name.value.ini
|
||||||
|
9: punctuation.definition.quote.ini
|
||||||
|
10: comment.declarationline.semicolon.ini
|
||||||
Submodule
+1
Submodule assets/syntaxes/JavaScript (Babel) added at a9a908fe1d
File diff suppressed because it is too large
Load Diff
Submodule
+1
Submodule assets/syntaxes/Julia added at 581805e47c
Submodule
+1
Submodule assets/syntaxes/Kotlin added at aeeed2780b
@@ -0,0 +1,398 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Kotlin
|
||||||
|
file_extensions:
|
||||||
|
- kt
|
||||||
|
- kts
|
||||||
|
scope: source.Kotlin
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: comments
|
||||||
|
- match: '^\s*(package)\b(?:\s*([^ ;$]+)\s*)?'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.kotlin
|
||||||
|
2: entity.name.package.kotlin
|
||||||
|
- include: imports
|
||||||
|
- include: statements
|
||||||
|
classes:
|
||||||
|
- match: (?<!::)(?=\b(?:companion|class|object|interface)\b)
|
||||||
|
push:
|
||||||
|
- match: '(?=$|\})'
|
||||||
|
pop: true
|
||||||
|
- include: comments
|
||||||
|
- match: \b(companion\s*)?(class|object|interface)\b
|
||||||
|
captures:
|
||||||
|
1: storage.modifier.kotlin
|
||||||
|
2: storage.modifier.kotlin
|
||||||
|
push:
|
||||||
|
- match: '(?=<|\{|\(|:|$)'
|
||||||
|
pop: true
|
||||||
|
- include: comments
|
||||||
|
- match: \w+
|
||||||
|
scope: entity.name.type.class.kotlin
|
||||||
|
- match: <
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: generics
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: parameters
|
||||||
|
- match: (:)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: "(?={|$)"
|
||||||
|
pop: true
|
||||||
|
- match: \w+
|
||||||
|
scope: entity.other.inherited-class.kotlin
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: statements
|
||||||
|
comments:
|
||||||
|
- match: /\*
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.kotlin
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.kotlin
|
||||||
|
- match: \*/
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.kotlin
|
||||||
|
pop: true
|
||||||
|
- match: \s*((//).*$\n?)
|
||||||
|
captures:
|
||||||
|
1: comment.line.double-slash.kotlin
|
||||||
|
2: punctuation.definition.comment.kotlin
|
||||||
|
constants:
|
||||||
|
- match: \b(true|false|null|this|super)\b
|
||||||
|
scope: constant.language.kotlin
|
||||||
|
- match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)([LlFf])?\b'
|
||||||
|
scope: constant.numeric.kotlin
|
||||||
|
- match: '\b([A-Z][A-Z0-9_]+)\b'
|
||||||
|
scope: constant.other.kotlin
|
||||||
|
expressions:
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- include: types
|
||||||
|
- include: strings
|
||||||
|
- include: constants
|
||||||
|
- include: comments
|
||||||
|
- include: keywords
|
||||||
|
functions:
|
||||||
|
- match: (?=\s*\b(?:fun)\b)
|
||||||
|
push:
|
||||||
|
- match: '(?=$|\})'
|
||||||
|
pop: true
|
||||||
|
- match: \b(fun)\b
|
||||||
|
captures:
|
||||||
|
1: keyword.other.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=\()
|
||||||
|
pop: true
|
||||||
|
- match: <
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: generics
|
||||||
|
- match: '([\.<\?>\w]+\.)?(\w+)'
|
||||||
|
captures:
|
||||||
|
2: entity.name.function.kotlin
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: parameters
|
||||||
|
- match: (:)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: "(?={|=|$)"
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '(?=\})'
|
||||||
|
pop: true
|
||||||
|
- include: statements
|
||||||
|
- match: (=)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.assignment.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=$)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
generics:
|
||||||
|
- match: (:)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=,|>)
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- include: keywords
|
||||||
|
- match: \w+
|
||||||
|
scope: storage.type.generic.kotlin
|
||||||
|
getters-and-setters:
|
||||||
|
- match: \b(get)\b\s*\(\s*\)
|
||||||
|
captures:
|
||||||
|
1: entity.name.function.kotlin
|
||||||
|
push:
|
||||||
|
- match: '\}|(?=\bset\b)|$'
|
||||||
|
pop: true
|
||||||
|
- match: (=)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.assignment.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=$|\bset\b)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- match: \b(set)\b\s*(?=\()
|
||||||
|
captures:
|
||||||
|
1: entity.name.function.kotlin
|
||||||
|
push:
|
||||||
|
- match: '\}|(?=\bget\b)|$'
|
||||||
|
pop: true
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: parameters
|
||||||
|
- match: (=)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.assignment.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=$|\bset\b)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
imports:
|
||||||
|
- match: '^\s*(import)\s+[^ $]+\s+(as)?'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.kotlin
|
||||||
|
2: keyword.other.kotlin
|
||||||
|
keywords:
|
||||||
|
- match: \b(var|val|public|private|protected|abstract|final|sealed|enum|open|attribute|annotation|override|inline|vararg|in|out|internal|data|tailrec|operator|infix|const|yield|typealias|typeof|reified|suspend)\b
|
||||||
|
scope: storage.modifier.kotlin
|
||||||
|
- match: \b(try|catch|finally|throw)\b
|
||||||
|
scope: keyword.control.catch-exception.kotlin
|
||||||
|
- match: \b(if|else|while|for|do|return|when|where|break|continue)\b
|
||||||
|
scope: keyword.control.kotlin
|
||||||
|
- match: \b(in|is|!in|!is|as|as\?|assert)\b
|
||||||
|
scope: keyword.operator.kotlin
|
||||||
|
- match: (==|!=|===|!==|<=|>=|<|>)
|
||||||
|
scope: keyword.operator.comparison.kotlin
|
||||||
|
- match: (=)
|
||||||
|
scope: keyword.operator.assignment.kotlin
|
||||||
|
- match: (::)
|
||||||
|
scope: keyword.operator.kotlin
|
||||||
|
- match: (:)
|
||||||
|
scope: keyword.operator.declaration.kotlin
|
||||||
|
- match: \b(by)\b
|
||||||
|
scope: keyword.other.by.kotlin
|
||||||
|
- match: (\?\.)
|
||||||
|
scope: keyword.operator.safenav.kotlin
|
||||||
|
- match: (\.)
|
||||||
|
scope: keyword.operator.dot.kotlin
|
||||||
|
- match: (\?:)
|
||||||
|
scope: keyword.operator.elvis.kotlin
|
||||||
|
- match: (\-\-|\+\+)
|
||||||
|
scope: keyword.operator.increment-decrement.kotlin
|
||||||
|
- match: (\+=|\-=|\*=|\/=)
|
||||||
|
scope: keyword.operator.arithmetic.assign.kotlin
|
||||||
|
- match: (\.\.)
|
||||||
|
scope: keyword.operator.range.kotlin
|
||||||
|
- match: (\-|\+|\*|\/|%)
|
||||||
|
scope: keyword.operator.arithmetic.kotlin
|
||||||
|
- match: (!|&&|\|\|)
|
||||||
|
scope: keyword.operator.logical.kotlin
|
||||||
|
- match: (;)
|
||||||
|
scope: punctuation.terminator.kotlin
|
||||||
|
namespaces:
|
||||||
|
- match: \b(namespace)\b
|
||||||
|
scope: keyword.other.kotlin
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: statements
|
||||||
|
parameters:
|
||||||
|
- match: (:)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=,|\)|=)
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- match: (=)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=,|\))
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- include: keywords
|
||||||
|
- match: \w+
|
||||||
|
scope: variable.parameter.function.kotlin
|
||||||
|
statements:
|
||||||
|
- include: namespaces
|
||||||
|
- include: typedefs
|
||||||
|
- include: classes
|
||||||
|
- include: functions
|
||||||
|
- include: variables
|
||||||
|
- include: getters-and-setters
|
||||||
|
- include: expressions
|
||||||
|
strings:
|
||||||
|
- match: '"""'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.kotlin
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.third.kotlin
|
||||||
|
- match: '"""'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.kotlin
|
||||||
|
pop: true
|
||||||
|
- match: '(\$\w+|\$\{[^\}]+\})'
|
||||||
|
scope: variable.parameter.template.kotlin
|
||||||
|
- match: \\.
|
||||||
|
scope: constant.character.escape.kotlin
|
||||||
|
- match: '"'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.kotlin
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.kotlin
|
||||||
|
- match: '"'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.kotlin
|
||||||
|
pop: true
|
||||||
|
- match: '(\$\w+|\$\{[^\}]+\})'
|
||||||
|
scope: variable.parameter.template.kotlin
|
||||||
|
- match: \\.
|
||||||
|
scope: constant.character.escape.kotlin
|
||||||
|
- match: "'"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.kotlin
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.kotlin
|
||||||
|
- match: "'"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.kotlin
|
||||||
|
pop: true
|
||||||
|
- match: \\.
|
||||||
|
scope: constant.character.escape.kotlin
|
||||||
|
- match: "`"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.kotlin
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.kotlin
|
||||||
|
- match: "`"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.kotlin
|
||||||
|
pop: true
|
||||||
|
typedefs:
|
||||||
|
- match: (?=\s*(?:type))
|
||||||
|
push:
|
||||||
|
- match: (?=$)
|
||||||
|
pop: true
|
||||||
|
- match: \b(type)\b
|
||||||
|
scope: keyword.other.kotlin
|
||||||
|
- match: <
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: generics
|
||||||
|
- include: expressions
|
||||||
|
types:
|
||||||
|
- match: \b(Nothing|Any|Unit|String|CharSequence|Int|Boolean|Char|Long|Double|Float|Short|Byte|dynamic)\b
|
||||||
|
scope: storage.type.buildin.kotlin
|
||||||
|
- match: \b(IntArray|BooleanArray|CharArray|LongArray|DoubleArray|FloatArray|ShortArray|ByteArray)\b
|
||||||
|
scope: storage.type.buildin.array.kotlin
|
||||||
|
- match: \b(Array|Collection|List|Map|Set|MutableList|MutableMap|MutableSet|Sequence)<\b
|
||||||
|
captures:
|
||||||
|
1: storage.type.buildin.collection.kotlin
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- include: keywords
|
||||||
|
- match: \w+<
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- include: keywords
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: statements
|
||||||
|
- match: \(
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- match: (->)
|
||||||
|
scope: keyword.operator.declaration.kotlin
|
||||||
|
variables:
|
||||||
|
- match: (?=\s*\b(?:var|val)\b)
|
||||||
|
push:
|
||||||
|
- match: (?=:|=|(\b(by)\b)|$)
|
||||||
|
pop: true
|
||||||
|
- match: \b(var|val)\b
|
||||||
|
captures:
|
||||||
|
1: keyword.other.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=:|=|(\b(by)\b)|$)
|
||||||
|
pop: true
|
||||||
|
- match: <
|
||||||
|
push:
|
||||||
|
- match: ">"
|
||||||
|
pop: true
|
||||||
|
- include: generics
|
||||||
|
- match: '([\.<\?>\w]+\.)?(\w+)'
|
||||||
|
captures:
|
||||||
|
2: entity.name.variable.kotlin
|
||||||
|
- match: (:)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.declaration.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?==|$)
|
||||||
|
pop: true
|
||||||
|
- include: types
|
||||||
|
- include: getters-and-setters
|
||||||
|
- match: \b(by)\b
|
||||||
|
captures:
|
||||||
|
1: keyword.other.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=$)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- match: (=)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.assignment.kotlin
|
||||||
|
push:
|
||||||
|
- match: (?=$)
|
||||||
|
pop: true
|
||||||
|
- include: expressions
|
||||||
|
- include: getters-and-setters
|
||||||
Submodule
+1
Submodule assets/syntaxes/LESS added at d3ddfe7b51
Submodule
+1
Submodule assets/syntaxes/Nix added at ebf06571f3
@@ -0,0 +1,609 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Nix
|
||||||
|
file_extensions:
|
||||||
|
- nix
|
||||||
|
scope: source.nix
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: expression
|
||||||
|
comment:
|
||||||
|
- match: '/\*([^*]|\*[^\/])*'
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.nix
|
||||||
|
- match: \*\/
|
||||||
|
pop: true
|
||||||
|
- include: comment-remark
|
||||||
|
- match: '\#'
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.line.number-sign.nix
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- include: comment-remark
|
||||||
|
attribute-bind:
|
||||||
|
- include: attribute-name
|
||||||
|
- include: attribute-bind-from-equals
|
||||||
|
attribute-bind-from-equals:
|
||||||
|
- match: \=
|
||||||
|
captures:
|
||||||
|
0: keyword.operator.bind.nix
|
||||||
|
push:
|
||||||
|
- match: \;
|
||||||
|
captures:
|
||||||
|
0: punctuation.terminator.bind.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
attribute-inherit:
|
||||||
|
- match: \binherit\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.inherit.nix
|
||||||
|
push:
|
||||||
|
- match: \;
|
||||||
|
captures:
|
||||||
|
0: punctuation.terminator.inherit.nix
|
||||||
|
pop: true
|
||||||
|
- match: \(
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.function.arguments.nix
|
||||||
|
push:
|
||||||
|
- match: (?=\;)
|
||||||
|
pop: true
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.function.arguments.nix
|
||||||
|
push:
|
||||||
|
- match: (?=\;)
|
||||||
|
pop: true
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: attribute-name-single
|
||||||
|
- include: others
|
||||||
|
- include: expression
|
||||||
|
- match: '(?=[a-zA-Z\_])'
|
||||||
|
push:
|
||||||
|
- match: (?=\;)
|
||||||
|
pop: true
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: attribute-name-single
|
||||||
|
- include: others
|
||||||
|
- include: others
|
||||||
|
attribute-name:
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
scope: entity.other.attribute-name.multipart.nix
|
||||||
|
- match: \.
|
||||||
|
- include: string-quoted
|
||||||
|
- include: interpolation
|
||||||
|
attribute-name-single:
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
scope: entity.other.attribute-name.single.nix
|
||||||
|
attrset-contents:
|
||||||
|
- include: attribute-inherit
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: attribute-bind
|
||||||
|
- include: others
|
||||||
|
attrset-definition:
|
||||||
|
- match: '(?=\{)'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: '(\{)'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.attrset.nix
|
||||||
|
push:
|
||||||
|
- match: '(\})'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.attrset.nix
|
||||||
|
pop: true
|
||||||
|
- include: attrset-contents
|
||||||
|
- match: '(?<=\})'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
attrset-definition-brace-opened:
|
||||||
|
- match: '(?<=\})'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.attrset.nix
|
||||||
|
pop: true
|
||||||
|
- include: attrset-contents
|
||||||
|
attrset-for-sure:
|
||||||
|
- match: (?=\brec\b)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: \brec\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=\{)'
|
||||||
|
pop: true
|
||||||
|
- include: others
|
||||||
|
- include: attrset-definition
|
||||||
|
- include: others
|
||||||
|
- match: '(?=\{\s*(\}|[^,?]*(=|;)))'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: attrset-definition
|
||||||
|
- include: others
|
||||||
|
attrset-or-function:
|
||||||
|
- match: '\{'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.attrset-or-function.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: '(?=(\s*\}|\"|\binherit\b|\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*(\s*\.|\s*=[^=])))'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: attrset-definition-brace-opened
|
||||||
|
- match: '(?=(\.\.\.|\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*\s*[,?]))'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-definition-brace-opened
|
||||||
|
- include: bad-reserved
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
captures:
|
||||||
|
0: variable.parameter.function.maybe.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: (?=\.)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: attrset-definition-brace-opened
|
||||||
|
- match: \s*(\,)
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-definition-brace-opened
|
||||||
|
- match: (?=\=)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: attribute-bind-from-equals
|
||||||
|
- include: attrset-definition-brace-opened
|
||||||
|
- match: (?=\?)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-parameter-default
|
||||||
|
- match: \,
|
||||||
|
captures:
|
||||||
|
0: keyword.operator.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-definition-brace-opened
|
||||||
|
- include: others
|
||||||
|
- include: others
|
||||||
|
bad-reserved:
|
||||||
|
- match: '(?<![\w''-])(if|then|else|assert|with|let|in|rec|inherit)(?![\w''-])'
|
||||||
|
scope: invalid.illegal.reserved.nix
|
||||||
|
comment-remark:
|
||||||
|
- match: (TODO|FIXME|BUG|\!\!\!):?
|
||||||
|
captures:
|
||||||
|
1: markup.bold.comment.nix
|
||||||
|
constants:
|
||||||
|
- match: \b(builtins|true|false|null)\b
|
||||||
|
captures:
|
||||||
|
0: constant.language.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- match: \b(scopedImport|import|isNull|abort|throw|baseNameOf|dirOf|removeAttrs|map|toString|derivationStrict|derivation)\b
|
||||||
|
captures:
|
||||||
|
0: support.function.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- match: '\b[0-9]+\b'
|
||||||
|
captures:
|
||||||
|
0: constant.numeric.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
expression:
|
||||||
|
- include: parens-and-cont
|
||||||
|
- include: list-and-cont
|
||||||
|
- include: string
|
||||||
|
- include: interpolation
|
||||||
|
- include: with-assert
|
||||||
|
- include: function-for-sure
|
||||||
|
- include: attrset-for-sure
|
||||||
|
- include: attrset-or-function
|
||||||
|
- include: let
|
||||||
|
- include: if
|
||||||
|
- include: operator-unary
|
||||||
|
- include: constants
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: parameter-name-and-cont
|
||||||
|
- include: others
|
||||||
|
expression-cont:
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: parens
|
||||||
|
- include: list
|
||||||
|
- include: string
|
||||||
|
- include: interpolation
|
||||||
|
- include: function-for-sure
|
||||||
|
- include: attrset-for-sure
|
||||||
|
- include: attrset-or-function
|
||||||
|
- match: '(\bor\b|\.|==|!=|!|\<\=|\<|\>\=|\>|&&|\|\||-\>|//|\?|\+\+|-|\*|/(?=([^*]|$))|\+)'
|
||||||
|
scope: keyword.operator.nix
|
||||||
|
- include: constants
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: parameter-name
|
||||||
|
- include: others
|
||||||
|
function-body:
|
||||||
|
- match: '(@\s*([a-zA-Z\_][a-zA-Z0-9\_\''\-]*)\s*)?(\:)'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
function-body-from-colon:
|
||||||
|
- match: (\:)
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.function.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
function-contents:
|
||||||
|
- include: bad-reserved
|
||||||
|
- include: function-parameter
|
||||||
|
- include: others
|
||||||
|
function-definition:
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-body-from-colon
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- match: '(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*)'
|
||||||
|
captures:
|
||||||
|
0: variable.parameter.function.4.nix
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- match: \@
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-until-colon-no-arg
|
||||||
|
- include: others
|
||||||
|
- include: others
|
||||||
|
- match: '(?=\{)'
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-until-colon-with-arg
|
||||||
|
- include: others
|
||||||
|
function-definition-brace-opened:
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-body-from-colon
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-close-brace-with-arg
|
||||||
|
- match: (?=.?)
|
||||||
|
push:
|
||||||
|
- match: '(?=\})'
|
||||||
|
pop: true
|
||||||
|
- include: function-contents
|
||||||
|
- include: others
|
||||||
|
function-for-sure:
|
||||||
|
- match: '(?=(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*\s*[:@]|\{[^}]*\}\s*:|\{[^#}"''/=]*[,\?]))'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: function-definition
|
||||||
|
function-header-close-brace-no-arg:
|
||||||
|
- match: '\}'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.entity.function.nix
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: others
|
||||||
|
function-header-close-brace-with-arg:
|
||||||
|
- match: '\}'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.entity.function.nix
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-terminal-arg
|
||||||
|
- include: others
|
||||||
|
function-header-open-brace:
|
||||||
|
- match: '\{'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.entity.function.2.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=\})'
|
||||||
|
pop: true
|
||||||
|
- include: function-contents
|
||||||
|
function-header-terminal-arg:
|
||||||
|
- match: (?=@)
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- match: \@
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- match: '(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*)'
|
||||||
|
push:
|
||||||
|
- meta_scope: variable.parameter.function.3.nix
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: others
|
||||||
|
- include: others
|
||||||
|
function-header-until-colon-no-arg:
|
||||||
|
- match: '(?=\{)'
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-open-brace
|
||||||
|
- include: function-header-close-brace-no-arg
|
||||||
|
function-header-until-colon-with-arg:
|
||||||
|
- match: '(?=\{)'
|
||||||
|
push:
|
||||||
|
- match: (?=\:)
|
||||||
|
pop: true
|
||||||
|
- include: function-header-open-brace
|
||||||
|
- include: function-header-close-brace-with-arg
|
||||||
|
function-parameter:
|
||||||
|
- match: (\.\.\.)
|
||||||
|
push:
|
||||||
|
- meta_scope: keyword.operator.nix
|
||||||
|
- match: '(,|(?=\}))'
|
||||||
|
pop: true
|
||||||
|
- include: others
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
captures:
|
||||||
|
0: variable.parameter.function.1.nix
|
||||||
|
push:
|
||||||
|
- match: '(,|(?=\}))'
|
||||||
|
captures:
|
||||||
|
0: keyword.operator.nix
|
||||||
|
pop: true
|
||||||
|
- include: whitespace
|
||||||
|
- include: comment
|
||||||
|
- include: function-parameter-default
|
||||||
|
- include: expression
|
||||||
|
- include: others
|
||||||
|
function-parameter-default:
|
||||||
|
- match: \?
|
||||||
|
captures:
|
||||||
|
0: keyword.operator.nix
|
||||||
|
push:
|
||||||
|
- match: "(?=[,}])"
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
if:
|
||||||
|
- match: (?=\bif\b)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: \bif\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: \bth(?=en\b)
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
- match: (?<=th)en\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: \bel(?=se\b)
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
- match: (?<=el)se\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
illegal:
|
||||||
|
- match: .
|
||||||
|
scope: invalid.illegal
|
||||||
|
interpolation:
|
||||||
|
- match: '\$\{'
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.embedded.begin.nix
|
||||||
|
push:
|
||||||
|
- meta_scope: markup.italic
|
||||||
|
- match: '\}'
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.embedded.end.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
let:
|
||||||
|
- match: (?=\blet\b)
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: \blet\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(in|else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: '(?=\{)'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: '\{'
|
||||||
|
push:
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- include: attrset-contents
|
||||||
|
- match: '(^|(?<=\}))'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- include: others
|
||||||
|
- include: attrset-contents
|
||||||
|
- include: others
|
||||||
|
- match: \bin\b
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
list:
|
||||||
|
- match: '\['
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.list.nix
|
||||||
|
push:
|
||||||
|
- match: '\]'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.list.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
list-and-cont:
|
||||||
|
- match: '(?=\[)'
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: list
|
||||||
|
- include: expression-cont
|
||||||
|
operator-unary:
|
||||||
|
- match: (!|-)
|
||||||
|
scope: keyword.operator.unary.nix
|
||||||
|
others:
|
||||||
|
- include: whitespace
|
||||||
|
- include: comment
|
||||||
|
- include: illegal
|
||||||
|
parameter-name:
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
captures:
|
||||||
|
0: variable.parameter.name.nix
|
||||||
|
parameter-name-and-cont:
|
||||||
|
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
|
||||||
|
captures:
|
||||||
|
0: variable.parameter.name.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
parens:
|
||||||
|
- match: \(
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.expression.nix
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.expression.nix
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
|
parens-and-cont:
|
||||||
|
- match: (?=\()
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: parens
|
||||||
|
- include: expression-cont
|
||||||
|
string:
|
||||||
|
- match: (?=\'\')
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- match: \'\'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.other.start.nix
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.other.nix
|
||||||
|
- match: \'\'(?!\$|\'|\\.)
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.other.end.nix
|
||||||
|
pop: true
|
||||||
|
- match: \'\'(\$|\'|\\.)
|
||||||
|
scope: constant.character.escape.nix
|
||||||
|
- include: interpolation
|
||||||
|
- include: expression-cont
|
||||||
|
- match: (?=\")
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: string-quoted
|
||||||
|
- include: expression-cont
|
||||||
|
- match: '([a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+)'
|
||||||
|
captures:
|
||||||
|
0: string.unquoted.path.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- match: '(\<[a-zA-Z0-9\.\_\-\+]+(\/[a-zA-Z0-9\.\_\-\+]+)*\>)'
|
||||||
|
captures:
|
||||||
|
0: string.unquoted.spath.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
- match: '([a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\'']+)'
|
||||||
|
captures:
|
||||||
|
0: string.unquoted.url.nix
|
||||||
|
push:
|
||||||
|
- match: '(?=([\])};,]|\b(else|then)\b))'
|
||||||
|
pop: true
|
||||||
|
- include: expression-cont
|
||||||
|
string-quoted:
|
||||||
|
- match: \"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.double.start.nix
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.nix
|
||||||
|
- match: \"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.double.end.nix
|
||||||
|
pop: true
|
||||||
|
- match: \\.
|
||||||
|
scope: constant.character.escape.nix
|
||||||
|
- include: interpolation
|
||||||
|
whitespace:
|
||||||
|
- match: \s+
|
||||||
|
with-assert:
|
||||||
|
- match: '(?<![\w''-])(with|assert)(?![\w''-])'
|
||||||
|
captures:
|
||||||
|
0: keyword.other.nix
|
||||||
|
push:
|
||||||
|
- match: \;
|
||||||
|
pop: true
|
||||||
|
- include: expression
|
||||||
Submodule
+1
Submodule assets/syntaxes/Packages added at 289782ff2e
Submodule
+1
Submodule assets/syntaxes/PowerShell added at 12b7d7257e
@@ -0,0 +1,466 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: PowerShell
|
||||||
|
file_extensions:
|
||||||
|
- ps1
|
||||||
|
- psm1
|
||||||
|
- psd1
|
||||||
|
scope: source.powershell
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: "<#"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.powershell
|
||||||
|
- match: "#>"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: commentEmbeddedDocs
|
||||||
|
- match: '[2-6]>&1|>>|>|<<|<|>|>\||[1-6]>|[1-6]>>'
|
||||||
|
scope: keyword.operator.redirection.powershell
|
||||||
|
- include: commands
|
||||||
|
- include: commentLine
|
||||||
|
- include: variable
|
||||||
|
- include: interpolatedStringContent
|
||||||
|
- include: function
|
||||||
|
- include: attribute
|
||||||
|
- include: UsingDirective
|
||||||
|
- include: type
|
||||||
|
- include: hashtable
|
||||||
|
- include: doubleQuotedString
|
||||||
|
- include: scriptblock
|
||||||
|
- include: doubleQuotedStringEscapes
|
||||||
|
- match: (?<!')'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.powershell
|
||||||
|
- match: "'(?!')"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: "''"
|
||||||
|
scope: constant.character.escape.powershell
|
||||||
|
- match: \@"(?=$)
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.heredoc.powershell
|
||||||
|
- match: ^"@
|
||||||
|
pop: true
|
||||||
|
- include: variableNoProperty
|
||||||
|
- include: doubleQuotedStringEscapes
|
||||||
|
- include: interpolation
|
||||||
|
- match: \@'(?=$)
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.heredoc.powershell
|
||||||
|
- match: ^'@
|
||||||
|
pop: true
|
||||||
|
- match: "''"
|
||||||
|
scope: constant.character.escape.powershell
|
||||||
|
- include: numericConstant
|
||||||
|
- match: (@)(\()
|
||||||
|
captures:
|
||||||
|
1: keyword.other.array.begin.powershell
|
||||||
|
2: punctuation.section.group.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.group.array-expression.powershell
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: (\$)(\()
|
||||||
|
comment: "TODO: move to repo; make recursive."
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: punctuation.section.group.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.group.complex.subexpression.powershell
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: '(\b(([A-Za-z0-9\-_\.]+)\.(?i:exe|com|cmd|bat))\b)'
|
||||||
|
scope: support.function.powershell
|
||||||
|
- match: (?<!\w|-|\.)((?i:begin|break|catch|continue|data|default|define|do|dynamicparam|else|elseif|end|exit|finally|for|from|if|in|inlinescript|parallel|param|process|return|sequence|switch|throw|trap|try|until|var|while)|%|\?)(?!\w)
|
||||||
|
scope: keyword.control.powershell
|
||||||
|
- match: '(?<!\w|-|[^\)]\.)((?i:(foreach|where)(?!-object))|%|\?)(?!\w)'
|
||||||
|
scope: keyword.control.powershell
|
||||||
|
- match: (?<!\w)(--%)(?!\w)
|
||||||
|
comment: This should be moved to the repository at some point.
|
||||||
|
captures:
|
||||||
|
1: keyword.control.powershell
|
||||||
|
push:
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- match: .+
|
||||||
|
scope: string.unquoted.powershell
|
||||||
|
- match: (?<!\w)((?i:hidden|static))(?!\w)
|
||||||
|
comment: This should only be relevant inside a class but will require a rework of how classes are matched. This is a temp fix.
|
||||||
|
scope: storage.modifier.powershell
|
||||||
|
- match: '(?<!\w|-)((?i:class)|%|\?)(?:\s)+((?:\p{L}|\d|_|-|)+)\b'
|
||||||
|
comment: capture should be entity.name.type, but it doesn't provide a good color in the default schema.
|
||||||
|
captures:
|
||||||
|
1: storage.type.powershell
|
||||||
|
2: entity.name.function
|
||||||
|
- match: (?<!\w)-(?i:is(?:not)?|as)\b
|
||||||
|
scope: keyword.operator.comparison.powershell
|
||||||
|
- match: '(?<!\w)-(?i:[ic]?(?:eq|ne|[gl][te]|(?:not)?(?:like|match|contains|in)|replace))(?!\p{L})'
|
||||||
|
scope: keyword.operator.comparison.powershell
|
||||||
|
- match: '(?<!\w)-(?i:join|split)(?!\p{L})|!'
|
||||||
|
scope: keyword.operator.unary.powershell
|
||||||
|
- match: '(?<!\w)-(?i:and|or|not|xor)(?!\p{L})|!'
|
||||||
|
scope: keyword.operator.logical.powershell
|
||||||
|
- match: '(?<!\w)-(?i:band|bor|bnot|bxor|shl|shr)(?!\p{L})'
|
||||||
|
scope: keyword.operator.bitwise.powershell
|
||||||
|
- match: '(?<!\w)-(?i:f)(?!\p{L})'
|
||||||
|
scope: keyword.operator.string-format.powershell
|
||||||
|
- match: "[+%*/-]?=|[+/*%-]"
|
||||||
|
scope: keyword.operator.assignment.powershell
|
||||||
|
- match: '\|{2}|&{2}|;'
|
||||||
|
scope: punctuation.terminator.statement.powershell
|
||||||
|
- match: '&|(?<!\w)\.(?= )|`|,|\|'
|
||||||
|
scope: keyword.operator.other.powershell
|
||||||
|
- match: (?<!\s|^)\.\.(?=\-?\d|\(|\$)
|
||||||
|
comment: This is very imprecise, is there a syntax for 'must come after...'
|
||||||
|
scope: keyword.operator.range.powershell
|
||||||
|
RequiresDirective:
|
||||||
|
- match: (?<=#)(?i:(requires))\s
|
||||||
|
captures:
|
||||||
|
0: keyword.control.requires.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.requires.powershell
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- match: \-(?i:Modules|PSSnapin|RunAsAdministrator|ShellId|Version)
|
||||||
|
scope: keyword.other.powershell
|
||||||
|
- match: '(?<!-)\b\p{L}+|\d+(?:\.\d+)*'
|
||||||
|
scope: variable.parameter.powershell
|
||||||
|
- include: hashtable
|
||||||
|
UsingDirective:
|
||||||
|
- match: (?<!\w)(?i:(using))\s+(?i:(namespace|module))\s+(?i:((?:\w+(?:\.)?)+))
|
||||||
|
captures:
|
||||||
|
1: keyword.control.using.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
3: variable.parameter.powershell
|
||||||
|
attribute:
|
||||||
|
- match: '(\[)\s*\b(?i)(cmdletbinding|alias|outputtype|parameter|validatenotnull|validatenotnullorempty|validatecount|validateset|allownull|allowemptycollection|allowemptystring|validatescript|validaterange|validatepattern|validatelength)\b'
|
||||||
|
captures:
|
||||||
|
1: punctuation.section.bracket.begin.powershell
|
||||||
|
2: support.function.attribute.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.attribute.powershell
|
||||||
|
- match: '(\])'
|
||||||
|
captures:
|
||||||
|
1: punctuation.section.bracket.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: \(
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.begin.powershell
|
||||||
|
push:
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: variable
|
||||||
|
- include: variableNoProperty
|
||||||
|
- include: hashtable
|
||||||
|
- include: scriptblock
|
||||||
|
- include: doubleQuotedStringEscapes
|
||||||
|
- include: doubleQuotedString
|
||||||
|
- include: type
|
||||||
|
- include: numericConstant
|
||||||
|
- include: doubleQuotedString
|
||||||
|
- include: main
|
||||||
|
- match: (?i)\b(mandatory|valuefrompipeline|valuefrompipelinebypropertyname|valuefromremainingarguments|position|parametersetname|defaultparametersetname|supportsshouldprocess|supportspaging|positionalbinding|helpuri|confirmimpact|helpmessage)\b(?:\s+)?(=)?
|
||||||
|
captures:
|
||||||
|
1: variable.parameter.attribute.powershell
|
||||||
|
2: keyword.operator.assignment.powershell
|
||||||
|
- match: (?<!')'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.single.powershell
|
||||||
|
- match: "'(?!')"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: "''"
|
||||||
|
scope: constant.character.escape.powershell
|
||||||
|
commands:
|
||||||
|
- match: '(?:(\p{L}|\d|_|-|\\|\:)*\\)?\b(?i:Add|Approve|Assert|Backup|Block|Build|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Deploy|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Write)\-.+?(?:\.(?i:exe|cmd|bat|ps1))?\b'
|
||||||
|
comment: "Verb-Noun pattern:"
|
||||||
|
scope: support.function.powershell
|
||||||
|
- match: (?<!\w)(?i:foreach-object)(?!\w)
|
||||||
|
comment: Builtin cmdlets with reserved verbs
|
||||||
|
scope: support.function.powershell
|
||||||
|
- match: (?<!\w)(?i:where-object)(?!\w)
|
||||||
|
comment: Builtin cmdlets with reserved verbs
|
||||||
|
scope: support.function.powershell
|
||||||
|
- match: (?<!\w)(?i:sort-object)(?!\w)
|
||||||
|
comment: Builtin cmdlets with reserved verbs
|
||||||
|
scope: support.function.powershell
|
||||||
|
- match: (?<!\w)(?i:tee-object)(?!\w)
|
||||||
|
comment: Builtin cmdlets with reserved verbs
|
||||||
|
scope: support.function.powershell
|
||||||
|
commentEmbeddedDocs:
|
||||||
|
- match: ^(?i:(?:\s?|#)+(\.)(COMPONENT|DESCRIPTION|EXAMPLE|EXTERNALHELP|FORWARDHELPCATEGORY|FORWARDHELPTARGETNAME|FUNCTIONALITY|INPUTS|LINK|NOTES|OUTPUTS|REMOTEHELPRUNSPACE|ROLE|SYNOPSIS))
|
||||||
|
scope: comment.documentation.embedded.powershell
|
||||||
|
captures:
|
||||||
|
1: constant.string.documentation.powershell
|
||||||
|
2: keyword.operator.documentation.powershell
|
||||||
|
- match: '(?i:\s?(\.)(PARAMETER|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP)\s+([a-z0-9-_]+))'
|
||||||
|
scope: comment.documentation.embedded.powershell
|
||||||
|
captures:
|
||||||
|
1: constant.string.documentation.powershell
|
||||||
|
2: keyword.operator.documentation.powershell
|
||||||
|
3: keyword.operator.documentation.powershell
|
||||||
|
commentLine:
|
||||||
|
- match: '(?<![`\\-])#'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.line.powershell
|
||||||
|
- match: $\n?
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.powershell
|
||||||
|
pop: true
|
||||||
|
- include: commentEmbeddedDocs
|
||||||
|
- include: RequiresDirective
|
||||||
|
doubleQuotedString:
|
||||||
|
- match: (?<!(?<!`)")"
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: string.quoted.double.powershell
|
||||||
|
- match: '"(?!")'
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.string.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: '(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,64}\b'
|
||||||
|
- include: variableNoProperty
|
||||||
|
- include: variable
|
||||||
|
- include: doubleQuotedStringEscapes
|
||||||
|
- include: interpolation
|
||||||
|
- match: '`\s*$'
|
||||||
|
scope: keyword.other.powershell
|
||||||
|
doubleQuotedStringEscapes:
|
||||||
|
- match: '`[0abnfrvt"''$`]'
|
||||||
|
scope: constant.character.escape.powershell
|
||||||
|
- match: '""'
|
||||||
|
scope: constant.character.escape.powershell
|
||||||
|
function:
|
||||||
|
- match: '^(?:\s*+)(?i)(function|filter|configuration|workflow)\s+(?:(global|local|script|private):)?((?:\p{L}|\d|_|-|\.)+)'
|
||||||
|
captures:
|
||||||
|
0: meta.function.powershell
|
||||||
|
1: storage.type.powershell
|
||||||
|
2: storage.modifier.scope.powershell
|
||||||
|
3: entity.name.function.powershell
|
||||||
|
push:
|
||||||
|
- match: '(?=\{|\()'
|
||||||
|
pop: true
|
||||||
|
- include: commentLine
|
||||||
|
hashtable:
|
||||||
|
- match: '(@)(\{)'
|
||||||
|
captures:
|
||||||
|
1: keyword.other.hashtable.begin.powershell
|
||||||
|
2: punctuation.section.braces.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.hashtable.powershell
|
||||||
|
- match: '(\})'
|
||||||
|
captures:
|
||||||
|
1: punctuation.section.braces.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: \b((?:\'|\")?)(\w+)((?:\'|\")?)(?:\s+)?(=)(?:\s+)?
|
||||||
|
scope: meta.hashtable.assignment.powershell
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.string.begin.powershell
|
||||||
|
2: variable.other.readwrite.powershell
|
||||||
|
3: punctuation.definition.string.end.powershell
|
||||||
|
4: keyword.operator.assignment.powershell
|
||||||
|
- include: scriptblock
|
||||||
|
- include: main
|
||||||
|
interpolatedStringContent:
|
||||||
|
- match: \(
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_content_scope: interpolated.simple.source.powershell
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- include: interpolation
|
||||||
|
- include: interpolatedStringContent
|
||||||
|
interpolation:
|
||||||
|
- match: (\$)(\()
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: punctuation.section.group.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_content_scope: interpolated.complex.source.powershell
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.group.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- include: interpolation
|
||||||
|
- include: interpolatedStringContent
|
||||||
|
numericConstant:
|
||||||
|
- match: '(?<!\w)([-+]?0(?:x|X)[0-9a-fA-F_]+(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.hex.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?(?:[0-9_]+)?\.[0-9_]+(?:(?:e|E)[0-9]+)?(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.integer.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?0(?:b|B)[01_]+(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.octal.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?[0-9_]+(?:e|E)(?:[0-9_])?+(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.integer.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?[0-9_]+\.(?:e|E)(?:[0-9_])?+(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.integer.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?[0-9_]+[\.]?(?:F|f|D|d|M|m))((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.integer.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
- match: '(?<!\w)([-+]?[0-9_]+[\.]?(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
|
||||||
|
captures:
|
||||||
|
1: constant.numeric.integer.powershell
|
||||||
|
2: keyword.other.powershell
|
||||||
|
scriptblock:
|
||||||
|
- match: '\{'
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.braces.begin.powershell
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.scriptblock.powershell
|
||||||
|
- match: '\}'
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.braces.end.powershell
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
type:
|
||||||
|
- match: '\['
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.bracket.begin.powershell
|
||||||
|
push:
|
||||||
|
- match: '\]'
|
||||||
|
captures:
|
||||||
|
0: punctuation.section.bracket.end.powershell
|
||||||
|
pop: true
|
||||||
|
- match: '(?!\d+|\.)(?:\p{L}|\p{N}|\.)+'
|
||||||
|
scope: storage.type.powershell
|
||||||
|
- include: main
|
||||||
|
variable:
|
||||||
|
- match: (\$)(?i:(False|Null|True))\b
|
||||||
|
comment: These are special constants.
|
||||||
|
captures:
|
||||||
|
0: constant.language.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
- match: '(\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
|
||||||
|
comment: These are the other built-in constants.
|
||||||
|
captures:
|
||||||
|
0: support.constant.variable.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: '(\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
|
||||||
|
comment: Automatic variables are not constants, but they are read-only. In monokai (default) color schema support.variable doesn't have color, so we use constant.
|
||||||
|
captures:
|
||||||
|
0: support.constant.automatic.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: '(\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
|
||||||
|
comment: Style preference variables as language variables so that they stand out.
|
||||||
|
captures:
|
||||||
|
0: variable.language.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$|@)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)?'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: storage.modifier.scope.powershell
|
||||||
|
4: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$)(\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)?'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: punctuation.section.braces.begin.powershell
|
||||||
|
3: storage.modifier.scope.powershell
|
||||||
|
5: punctuation.section.braces.end.powershell
|
||||||
|
6: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$|@)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)?'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: support.variable.drive.powershell
|
||||||
|
4: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$)(\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)?'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: punctuation.section.braces.begin.powershell
|
||||||
|
3: support.variable.drive.powershell
|
||||||
|
5: punctuation.section.braces.end.powershell
|
||||||
|
6: variable.other.member.powershell
|
||||||
|
variableNoProperty:
|
||||||
|
- match: (\$)(?i:(False|Null|True))\b
|
||||||
|
comment: These are special constants.
|
||||||
|
captures:
|
||||||
|
0: constant.language.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
- match: (\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))\b
|
||||||
|
comment: These are the other built-in constants.
|
||||||
|
captures:
|
||||||
|
0: support.constant.variable.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: (\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))\b
|
||||||
|
comment: Automatic variables are not constants, but they are read-only...
|
||||||
|
captures:
|
||||||
|
0: support.variable.automatic.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: (\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))\b
|
||||||
|
comment: Style preference variables as language variables so that they stand out.
|
||||||
|
captures:
|
||||||
|
0: variable.language.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
3: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$|@)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+))'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: storage.modifier.scope.powershell
|
||||||
|
4: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$)(\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: storage.modifier.scope.powershell
|
||||||
|
4: keyword.other.powershell
|
||||||
|
5: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+))'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: support.variable.drive.powershell
|
||||||
|
4: variable.other.member.powershell
|
||||||
|
- match: '(?i:(\$)(\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\}))'
|
||||||
|
captures:
|
||||||
|
0: variable.other.readwrite.powershell
|
||||||
|
1: punctuation.definition.variable.powershell
|
||||||
|
2: punctuation.section.braces.begin
|
||||||
|
3: support.variable.drive.powershell
|
||||||
|
5: punctuation.section.braces.end
|
||||||
Submodule
+1
Submodule assets/syntaxes/Puppet added at 2a224343d2
Submodule
+1
Submodule assets/syntaxes/PureScript added at 42a61e39ad
Submodule
+1
Submodule assets/syntaxes/Robot added at 8e5a349a3e
@@ -0,0 +1,54 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Robot Framework syntax highlighting.
|
||||||
|
file_extensions:
|
||||||
|
- robot
|
||||||
|
scope: source.robot
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- match: '\$\{(\d+|\d+\.\d*|0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+)\}'
|
||||||
|
comment: "Robot Framework numbers, like ${1} or ${12.3}"
|
||||||
|
scope: constant.numeric.robot
|
||||||
|
- match: '(?i)(%\{[\w|\s]+\})'
|
||||||
|
comment: "Robot Framework environment variable, like %{USER}"
|
||||||
|
scope: variable.parameter.robot
|
||||||
|
- match: '((?<!\\)|(?<=\\\\))[$&]{'
|
||||||
|
comment: Robot Framework scalar and dictionary variables
|
||||||
|
push:
|
||||||
|
- meta_scope: entity.name.class
|
||||||
|
- match: '\}'
|
||||||
|
pop: true
|
||||||
|
- match: '((?<!\\)(@{)|(?<=\\\\)(@{))'
|
||||||
|
comment: Robot Framework list variables
|
||||||
|
push:
|
||||||
|
- meta_scope: entity.name.class
|
||||||
|
- match: '(}\[.+])|(})'
|
||||||
|
pop: true
|
||||||
|
- match: '(?i)^(\|\s*)?(\*{1,3} ?)(settings?|variables?|keywords?|test cases?)( ?\*{1,3})?(\s*\|)?'
|
||||||
|
comment: Robot Framework data tables
|
||||||
|
scope: string.robot.header
|
||||||
|
- match: '(?i)(^\|\s*)?\[?Documentation\]?\s+'
|
||||||
|
comment: Test case, keyword and settings table documentation
|
||||||
|
push:
|
||||||
|
- meta_scope: comment
|
||||||
|
- match: ^(?!\s*+\.\.\.)
|
||||||
|
pop: true
|
||||||
|
- match: '(^| {2,}|\t|\\| {1,})(?<!\\\\)#'
|
||||||
|
comment: Comment character
|
||||||
|
push:
|
||||||
|
- meta_scope: comment
|
||||||
|
- match: $
|
||||||
|
pop: true
|
||||||
|
- match: '(?i)\s+\[(Tags|Setup|Teardown|Template|Timeout|Arguments|Return)\]'
|
||||||
|
comment: Tests case and keyword settings
|
||||||
|
scope: storage.type
|
||||||
|
- match: (?i)^(\|\s*)?(Library|Resource|Test Timeout|Test Template|Test Teardown|Test Setup|Default Tags|Force Tags|Metadata|Variables|Suite Setup|Suite Teardown)(?:( )|( \| ))
|
||||||
|
comment: Settings table settings, like Library
|
||||||
|
scope: constant.language
|
||||||
|
- match: '^(\|\s+)?(?!^\.{3})(?![\|$&])\S+'
|
||||||
|
comment: Keywords and test cases
|
||||||
|
push:
|
||||||
|
- meta_scope: keyword.control.robot
|
||||||
|
- match: '($|\||\s{2,})'
|
||||||
|
pop: true
|
||||||
Submodule
+1
Submodule assets/syntaxes/Swift added at fef17119ce
@@ -0,0 +1,371 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: Swift
|
||||||
|
file_extensions:
|
||||||
|
- swift
|
||||||
|
first_line_match: ^#!/.*\bswift
|
||||||
|
scope: source.swift
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: shebang-line
|
||||||
|
- include: comment
|
||||||
|
- include: attribute
|
||||||
|
- include: literal
|
||||||
|
- include: operator
|
||||||
|
- include: declaration
|
||||||
|
- include: storage-type
|
||||||
|
- include: keyword
|
||||||
|
- include: type
|
||||||
|
- include: boolean
|
||||||
|
comment:
|
||||||
|
- include: documentation-comment
|
||||||
|
- include: block-comment
|
||||||
|
- include: in-line-comment
|
||||||
|
access-level-modifier:
|
||||||
|
- match: \b(open|public|internal|fileprivate|private)\b(?:\(set\))?
|
||||||
|
comment: access-level-modifier
|
||||||
|
scope: keyword.other.access-level-modifier.swift
|
||||||
|
arithmetic-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.arithmetic.swift
|
||||||
|
array-type:
|
||||||
|
- match: \b(Array)(<)
|
||||||
|
captures:
|
||||||
|
1: support.type.array.swift
|
||||||
|
2: punctuation.array.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.array.swift
|
||||||
|
- match: (>)
|
||||||
|
captures:
|
||||||
|
1: punctuation.array.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
assignment-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/|%|<<|>>|&|\^|\||&&|\|\|)?=(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.assignment.swift
|
||||||
|
attribute:
|
||||||
|
- match: '((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))(\()'
|
||||||
|
captures:
|
||||||
|
1: storage.modifier.attribute.swift
|
||||||
|
2: punctuation.definition.attribute.swift
|
||||||
|
3: punctuation.definition.attribute-arguments.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_content_scope: meta.attribute.arguments.swift
|
||||||
|
- match: \)
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.attribute-arguments.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
- match: '((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))'
|
||||||
|
captures:
|
||||||
|
1: storage.modifier.attribute.swift
|
||||||
|
2: punctuation.definition.attribute.swift
|
||||||
|
bitwise-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(&|\||\^|<<|>>)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.bitwise.swift
|
||||||
|
block-comment:
|
||||||
|
- match: /\*
|
||||||
|
comment: Block comment
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.swift
|
||||||
|
- match: \*/
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.end.swift
|
||||||
|
pop: true
|
||||||
|
boolean:
|
||||||
|
- match: \b(true|false)\b
|
||||||
|
scope: keyword.constant.boolean.swift
|
||||||
|
branch-statement-keyword:
|
||||||
|
- include: if-statement-keyword
|
||||||
|
- include: switch-statement-keyword
|
||||||
|
catch-statement-keyword:
|
||||||
|
- match: \b(catch|do)\b
|
||||||
|
comment: catch-statement
|
||||||
|
scope: kewyord.control.catch.swift
|
||||||
|
code-block:
|
||||||
|
- match: '(\{)'
|
||||||
|
comment: code-block
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.code-block.begin.swift
|
||||||
|
push:
|
||||||
|
- match: '(\})'
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.code-block.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
collection-type:
|
||||||
|
- include: array-type
|
||||||
|
- include: dictionary-type
|
||||||
|
- match: \b(Array|Dictionary)\b
|
||||||
|
scope: support.type.swift
|
||||||
|
comparative-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])((=|!)==?|(<|>)=?|~=)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.comparative.swift
|
||||||
|
control-transfer-statement-keyword:
|
||||||
|
- match: \b(continue|break|fallthrough|return)\b
|
||||||
|
comment: control-transfer-statement
|
||||||
|
scope: keyword.control.transfer.swift
|
||||||
|
custom-operator:
|
||||||
|
- match: '(?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:])'
|
||||||
|
scope: keyword.operator.custom.prefix.unary.swift
|
||||||
|
- match: '(?<![\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:\.])'
|
||||||
|
scope: keyword.operator.custom.postfix.unary.swift
|
||||||
|
- match: '(?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?=[\s)\]},;:])'
|
||||||
|
scope: keyword.operator.custom.binary.swift
|
||||||
|
declaration:
|
||||||
|
- include: import-declaration
|
||||||
|
- include: function-declaration
|
||||||
|
declaration-modifier:
|
||||||
|
- match: \b(class|convenience|dynamic|final|lazy|(non)?mutating|optional|override|required|static|unowned((un)?safe)?|weak)\b
|
||||||
|
comment: declaration-modifier
|
||||||
|
scope: keyword.other.declaration-modifier.swift
|
||||||
|
dictionary-type:
|
||||||
|
- match: \b(Dictionary)(<)
|
||||||
|
captures:
|
||||||
|
1: support.type.dictionary.swift
|
||||||
|
2: punctuation.dictionary.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.dictionary.swift
|
||||||
|
- match: (>)
|
||||||
|
captures:
|
||||||
|
1: punctuation.dictionary.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
documentation-comment:
|
||||||
|
- match: /\*\*
|
||||||
|
comment: Documentation comment
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.documentation.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: comment.block.documentation.swift
|
||||||
|
- match: \*/
|
||||||
|
captures:
|
||||||
|
0: punctuation.definition.comment.block.documentation.end.swift
|
||||||
|
pop: true
|
||||||
|
floating-point-literal:
|
||||||
|
- match: '\b([0-9][0-9_]*)(\.([0-9][0-9_]*))?([eE][+\-]?([0-9][0-9_]*))?\b'
|
||||||
|
comment: floating-point-literal -> (decimal-literal)(decimal-fraction)?(decimal-exponent)?
|
||||||
|
- match: '\b(0x\h[\h_]*)(\.(0x\h[\h_]*))?([pP][+\-]?(0x\h[\h_]*))\b'
|
||||||
|
comment: floating-point-literal -> (hexadecimal-literal)(hexadecimal-fraction)?(hexadecimal-exponent)
|
||||||
|
function-body:
|
||||||
|
- include: code-block
|
||||||
|
function-declaration:
|
||||||
|
- match: '\b(func)\s+(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)\s*(?=\(|<)'
|
||||||
|
comment: function-declaration
|
||||||
|
captures:
|
||||||
|
1: storage.type.function.swift
|
||||||
|
2: entity.type.function.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.function-declaration.swift
|
||||||
|
- match: '(?<=\})'
|
||||||
|
pop: true
|
||||||
|
- include: generic-parameter-clause
|
||||||
|
- include: parameter-clause
|
||||||
|
- include: function-result
|
||||||
|
- include: function-body
|
||||||
|
function-result:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(\->)(?![/=\-+!*%<>&|\^~.])\s*'
|
||||||
|
comment: function-result
|
||||||
|
captures:
|
||||||
|
1: keyword.operator.function-result.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.function-result.swift
|
||||||
|
- match: '\s*(?=\{)'
|
||||||
|
pop: true
|
||||||
|
- include: type
|
||||||
|
generic-parameter-clause:
|
||||||
|
- match: (<)
|
||||||
|
comment: generic-parameter-clause
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.generic-parameter-clause.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.generic-parameter-clause.swift
|
||||||
|
- match: (>)
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.generic-parameter-clause.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
identifier:
|
||||||
|
- match: '(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B)'
|
||||||
|
comment: identifier
|
||||||
|
scope: meta.identifier.swift
|
||||||
|
if-statement-keyword:
|
||||||
|
- match: \b(if|else)\b
|
||||||
|
comment: if-statement
|
||||||
|
scope: keyword.control.if.swift
|
||||||
|
import-declaration:
|
||||||
|
- match: '\b(import)\s+(?:(typealias|struct|class|enum|protocol|var|func)\s+)?((?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)(?:\.(?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+))*)'
|
||||||
|
comment: import-declaration
|
||||||
|
scope: meta.import.swift
|
||||||
|
captures:
|
||||||
|
1: keyword.other.import.swift
|
||||||
|
2: storage.modifier.swift
|
||||||
|
3: support.type.module.import.swift
|
||||||
|
in-line-comment:
|
||||||
|
- match: (//).*
|
||||||
|
comment: In-line comment
|
||||||
|
scope: comment.line.double-slash.swift
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.line.double-slash.swift
|
||||||
|
increment-decrement-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(\+\+|\-\-)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.increment-or-decrement.swift
|
||||||
|
integer-literal:
|
||||||
|
- match: '(\B\-|\b)(0b[01][01_]*)\b'
|
||||||
|
comment: binary-literal
|
||||||
|
scope: constant.numeric.integer.binary.swift
|
||||||
|
- match: '(\B\-|\b)(0o[0-7][0-7_]*)\b'
|
||||||
|
comment: octal-literal
|
||||||
|
scope: constant.numeric.integer.octal.swift
|
||||||
|
- match: '(\B\-|\b)([0-9][0-9_]*)\b'
|
||||||
|
comment: decimal-literal
|
||||||
|
scope: constant.numeric.integer.decimal.swift
|
||||||
|
- match: '(\B\-|\b)(0x\h[\h_]*)\b'
|
||||||
|
comment: hexadecimal-literal
|
||||||
|
scope: constant.numeric.integer.hexadecimal.swift
|
||||||
|
integer-type:
|
||||||
|
- match: \bU?Int(8|16|32|64)?\b
|
||||||
|
comment: Int types
|
||||||
|
scope: support.type.swift
|
||||||
|
keyword:
|
||||||
|
- include: branch-statement-keyword
|
||||||
|
- include: control-transfer-statement-keyword
|
||||||
|
- include: loop-statement-keyword
|
||||||
|
- include: catch-statement-keyword
|
||||||
|
- include: operator-declaration-modifier
|
||||||
|
- include: declaration-modifier
|
||||||
|
- include: access-level-modifier
|
||||||
|
- match: \b(class|deinit|enum|extension|func|import|init|let|protocol|static|struct|subscript|typealias|var|throws|rethrows)\b
|
||||||
|
comment: declaration keyword
|
||||||
|
scope: keyword.declaration.swift
|
||||||
|
- match: \b(break|case|continue|default|do|else|fallthrough|if|in|for|return|switch|where|while|repeat|catch|guard|defer|try|throw)\b
|
||||||
|
comment: statement keyword
|
||||||
|
scope: keyword.statement.swift
|
||||||
|
- match: \b(as|dynamicType|is|new|super|self|Self|Type)\b
|
||||||
|
comment: expression and type keyword
|
||||||
|
scope: keyword.other.statement.swift
|
||||||
|
- match: \b(associativity|didSet|get|infix|inout|left|mutating|none|nonmutating|operator|override|postfix|precedence|prefix|right|set|unowned((un)?safe)?|weak|willSet)\b
|
||||||
|
comment: other keyword
|
||||||
|
scope: keyword.other.swift
|
||||||
|
literal:
|
||||||
|
- include: integer-literal
|
||||||
|
- include: floating-point-literal
|
||||||
|
- include: nil-literal
|
||||||
|
- include: string-literal
|
||||||
|
- include: special-literal
|
||||||
|
logical-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])(!|&&|\|\|)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.logical.swift
|
||||||
|
loop-statement-keyword:
|
||||||
|
- match: \b(while|repeat|for|in)\b
|
||||||
|
comment: loop-statement
|
||||||
|
scope: keyword.control.loop.swift
|
||||||
|
nil-literal:
|
||||||
|
- match: \bnil\b
|
||||||
|
comment: nil-literal
|
||||||
|
scope: constant.nil.swift
|
||||||
|
operator:
|
||||||
|
- include: comparative-operator
|
||||||
|
- include: assignment-operator
|
||||||
|
- include: logical-operator
|
||||||
|
- include: remainder-operator
|
||||||
|
- include: increment-decrement-operator
|
||||||
|
- include: overflow-operator
|
||||||
|
- include: range-operator
|
||||||
|
- include: bitwise-operator
|
||||||
|
- include: arithmetic-operator
|
||||||
|
- include: ternary-operator
|
||||||
|
- include: type-casting-operator
|
||||||
|
- include: custom-operator
|
||||||
|
operator-declaration-modifier:
|
||||||
|
- match: \b(operator|prefix|infix|postfix)\b
|
||||||
|
comment: operator-declaration
|
||||||
|
scope: keyword.other.operator.swift
|
||||||
|
optional-type:
|
||||||
|
- match: \b(Optional)(<)
|
||||||
|
scope: meta.optional.swift
|
||||||
|
overflow-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])\&(\+|\-|\*|\/|%)(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.overflow.swift
|
||||||
|
parameter-clause:
|
||||||
|
- match: (\()
|
||||||
|
comment: parameter-clause
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.function-arguments.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.parameter-clause.swift
|
||||||
|
- match: (\))
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.function-arguments.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: main
|
||||||
|
primitive-type:
|
||||||
|
- match: \b(Int|Float|Double|String|Bool|Character|Void)\b
|
||||||
|
comment: Primitive types
|
||||||
|
scope: support.type.swift
|
||||||
|
protocol-composition-type:
|
||||||
|
- match: \b(protocol)(<)
|
||||||
|
scope: meta.protocol.swift
|
||||||
|
range-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])\.\.(?:\.)?(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.range.swift
|
||||||
|
remainder-operator:
|
||||||
|
- match: '(?<![/=\-+!*%<>&|\^~.])\%(?![/=\-+!*%<>&|\^~.])'
|
||||||
|
scope: keyword.operator.remainder.swift
|
||||||
|
shebang-line:
|
||||||
|
- match: ^(#!).*$
|
||||||
|
comment: Shebang line
|
||||||
|
scope: comment.line.shebang.swift
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.line.shebang.swift
|
||||||
|
special-literal:
|
||||||
|
- match: \b__(FILE|LINE|COLUMN|FUNCTION)__\b
|
||||||
|
scope: keyword.other.literal.swift
|
||||||
|
storage-type:
|
||||||
|
- match: \b(var|func|let|class|enum|struct|protocol|extension|typealias)\b
|
||||||
|
scope: storage.type.swift
|
||||||
|
string-literal:
|
||||||
|
- match: \"
|
||||||
|
captures:
|
||||||
|
0: string.quoted.double.swift
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.literal.string.swift
|
||||||
|
- match: \"
|
||||||
|
captures:
|
||||||
|
0: string.quoted.double.swift
|
||||||
|
pop: true
|
||||||
|
- match: '\\([0tnr\"\''\\]|x\h{2}|u\h{4}|U\h{8})'
|
||||||
|
scope: constant.character.escape.swift
|
||||||
|
- match: (\\\()
|
||||||
|
captures:
|
||||||
|
1: support.punctuation.expression.begin.swift
|
||||||
|
push:
|
||||||
|
- meta_content_scope: meta.expression.swift
|
||||||
|
- match: (\))
|
||||||
|
captures:
|
||||||
|
1: support.punctuation.expression.end.swift
|
||||||
|
pop: true
|
||||||
|
- include: scope:source.swift
|
||||||
|
- match: (\"|\\)
|
||||||
|
scope: invalid.illegal.swift
|
||||||
|
- match: (.)
|
||||||
|
scope: string.quoted.double.swift
|
||||||
|
switch-statement-keyword:
|
||||||
|
- match: \b(switch|case|default|where)\b
|
||||||
|
comment: switch-statement
|
||||||
|
scope: keyword.control.switch.swift
|
||||||
|
ternary-operator:
|
||||||
|
- match: '(?<=[\s(\[{,;:])(\?|:)(?=[\s)\]},;:])'
|
||||||
|
scope: keyword.operator.ternary.swift
|
||||||
|
type:
|
||||||
|
- include: primitive-type
|
||||||
|
- include: integer-type
|
||||||
|
- include: collection-type
|
||||||
|
- include: optional-type
|
||||||
|
- include: protocol-composition-type
|
||||||
|
type-casting-operator:
|
||||||
|
- match: \b(is\b|as(\?\B|\b))
|
||||||
|
scope: keyword.operator.type-casting.swift
|
||||||
Submodule
+1
Submodule assets/syntaxes/TOML added at b5e3064e99
Submodule
+1
Submodule assets/syntaxes/TypeScript added at 19a599ad0e
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Submodule
+1
Submodule assets/syntaxes/VimL added at ed40c3bc81
@@ -0,0 +1,91 @@
|
|||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
# http://www.sublimetext.com/docs/3/syntax.html
|
||||||
|
name: VimL
|
||||||
|
file_extensions:
|
||||||
|
- vim
|
||||||
|
- .vimrc
|
||||||
|
scope: source.viml
|
||||||
|
contexts:
|
||||||
|
main:
|
||||||
|
- include: comment
|
||||||
|
- include: string_quoted_double
|
||||||
|
- include: string_quoted_single
|
||||||
|
- include: string_regex
|
||||||
|
- include: inline_comment
|
||||||
|
- include: number_int
|
||||||
|
- include: number_hex
|
||||||
|
- include: keyword
|
||||||
|
- include: support_function
|
||||||
|
- include: support_variable
|
||||||
|
- include: support_type
|
||||||
|
- include: function_params
|
||||||
|
- include: function_definition
|
||||||
|
- include: function_call
|
||||||
|
- include: function
|
||||||
|
- include: variable
|
||||||
|
- include: expr
|
||||||
|
comment:
|
||||||
|
- match: ^\s*".*$
|
||||||
|
scope: comment.line.quotes.viml
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.vim
|
||||||
|
expr:
|
||||||
|
- match: (\|\||&&|==(\?|#)?|(!|>|<)=(#|\?)?|(=|!)~(#|\?)?|(>|<)(#|\?)is|isnot|\.|\*|\\|%)
|
||||||
|
scope: storage.function.viml
|
||||||
|
function:
|
||||||
|
- match: \b(fu(n|nction)?|end(f|fu|fun|function)?)\b
|
||||||
|
scope: storage.function.viml
|
||||||
|
function_call:
|
||||||
|
- match: '(([sgbwtl]|)?:?[0-9a-zA-Z_#]+)(?=\()'
|
||||||
|
scope: support.function.any-method
|
||||||
|
function_definition:
|
||||||
|
- match: '^\s*(function)\s*!?\s+(?=(s:)?[0-9a-zA-Z_#]+\s*\()'
|
||||||
|
captures:
|
||||||
|
1: storage.function.viml
|
||||||
|
push:
|
||||||
|
- meta_scope: meta.function.viml
|
||||||
|
- match: (\()
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.parameters.begin.viml
|
||||||
|
pop: true
|
||||||
|
- match: "(s:)?[0-9a-zA-Z_#]+"
|
||||||
|
scope: entity.name.function.viml
|
||||||
|
function_params:
|
||||||
|
- match: '-\w+='
|
||||||
|
scope: support.type.viml
|
||||||
|
inline_comment:
|
||||||
|
- match: '(?!\$)(")(?!\{).*$\n?'
|
||||||
|
scope: comment.line.quotes.viml
|
||||||
|
captures:
|
||||||
|
1: punctuation.definition.comment.vim
|
||||||
|
keyword:
|
||||||
|
- match: \b(if|while|for|try|return|throw|end(if|for|while|try)?|au(g|group)|else(if|)?|do|in|catch|finally|:)\b
|
||||||
|
scope: keyword.control.viml
|
||||||
|
number_hex:
|
||||||
|
- match: "0x[0-9a-f]+"
|
||||||
|
scope: constant.numeric.hex
|
||||||
|
number_int:
|
||||||
|
- match: '-?\d+'
|
||||||
|
scope: constant.numeric.integer
|
||||||
|
string_quoted_double:
|
||||||
|
- match: '"(\\\\|\\"|\n[^\S\n]*\\|[^\n"])*"'
|
||||||
|
scope: string.quoted.double.viml
|
||||||
|
string_quoted_single:
|
||||||
|
- match: '''(''''|\n[^\S\n]*\\|[^\n''])*'''
|
||||||
|
scope: string.quoted.single.viml
|
||||||
|
string_regex:
|
||||||
|
- match: '/(\\\\|\\/|\n[^\S\n]*\\|[^\n/])*/'
|
||||||
|
scope: string.regexp.viml
|
||||||
|
support_function:
|
||||||
|
- match: \b(set(local|global)?|let|command|filetype|colorscheme|\w*map|\w*a(b|brev)?|syn|exe(c|cute)?|ec(ho|)?|au(tocmd|)?)\b
|
||||||
|
scope: support.function.viml
|
||||||
|
support_type:
|
||||||
|
- match: <.*?>
|
||||||
|
scope: support.type.viml
|
||||||
|
support_variable:
|
||||||
|
- match: '\b(am(enu|)?|(hl|inc)?search|[Bb]uf([Nn]ew[Ff]ile|[Rr]ead)?|[Ff]ile[Tt]ype)\b'
|
||||||
|
scope: support.variable.viml
|
||||||
|
variable:
|
||||||
|
- match: '([sSgGbBwWlLaAvV]:|@|$|&(?!&))\w*'
|
||||||
|
scope: variable.other.viml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// Output the square of a number.
|
||||||
|
fn print_square(num: f64) {
|
||||||
|
let result = f64::powf(num, 2.0);
|
||||||
|
println!("The square of {:.2} is {:.2}.", num, result);
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Submodule
+1
Submodule assets/themes/1337-Scheme added at ca6a329cfd
Submodule
+1
Submodule assets/themes/DarkNeon added at 174bd535da
Submodule
+1
Submodule assets/themes/TwoDark added at 8e0f6fa5b5
Submodule
+1
Submodule assets/themes/github-sublime-theme added at 508740b243
Submodule
+1
Submodule assets/themes/onehalf added at 2516b37c3f
Submodule
+1
Submodule assets/themes/sublime-monokai-extended added at 1658f51c15
Submodule
+1
Submodule assets/themes/zenburn added at b7f27e2f65
@@ -0,0 +1,26 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate clap;
|
||||||
|
|
||||||
|
use clap::Shell;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
include!("src/clap_app.rs");
|
||||||
|
|
||||||
|
const BIN_NAME: &str = "bat";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let outdir = std::env::var_os("SHELL_COMPLETIONS_DIR").or(std::env::var_os("OUT_DIR"));
|
||||||
|
|
||||||
|
let outdir = match outdir {
|
||||||
|
None => return,
|
||||||
|
Some(outdir) => outdir,
|
||||||
|
};
|
||||||
|
|
||||||
|
fs::create_dir_all(&outdir).unwrap();
|
||||||
|
|
||||||
|
let mut app = build_app(true);
|
||||||
|
app.gen_completions(BIN_NAME, Shell::Bash, &outdir);
|
||||||
|
app.gen_completions(BIN_NAME, Shell::Fish, &outdir);
|
||||||
|
app.gen_completions(BIN_NAME, Shell::Zsh, &outdir);
|
||||||
|
app.gen_completions(BIN_NAME, Shell::PowerShell, &outdir);
|
||||||
|
}
|
||||||
+37
-5
@@ -11,23 +11,39 @@ pack() {
|
|||||||
local tempdir
|
local tempdir
|
||||||
local out_dir
|
local out_dir
|
||||||
local package_name
|
local package_name
|
||||||
|
local gcc_prefix
|
||||||
|
|
||||||
tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp)
|
tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp)
|
||||||
out_dir=$(pwd)
|
out_dir=$(pwd)
|
||||||
package_name="$PROJECT_NAME-$TRAVIS_TAG-$TARGET"
|
package_name="$PROJECT_NAME-$TRAVIS_TAG-$TARGET"
|
||||||
|
|
||||||
|
if [[ $TARGET == "arm-unknown-linux-gnueabihf" ]]; then
|
||||||
|
gcc_prefix="arm-linux-gnueabihf-"
|
||||||
|
elif [[ $TARGET == "aarch64-unknown-linux-gnu" ]]; then
|
||||||
|
gcc_prefix="aarch64-linux-gnu-"
|
||||||
|
else
|
||||||
|
gcc_prefix=""
|
||||||
|
fi
|
||||||
|
|
||||||
# create a "staging" directory
|
# create a "staging" directory
|
||||||
mkdir "$tempdir/$package_name"
|
mkdir "$tempdir/$package_name"
|
||||||
|
mkdir "$tempdir/$package_name/autocomplete"
|
||||||
|
|
||||||
# copying the main binary
|
# copying the main binary
|
||||||
cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/"
|
cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/"
|
||||||
strip "$tempdir/$package_name/$PROJECT_NAME"
|
"${gcc_prefix}"strip "$tempdir/$package_name/$PROJECT_NAME"
|
||||||
|
|
||||||
# readme and license
|
# manpage, readme and license
|
||||||
|
cp "doc/$PROJECT_NAME.1" "$tempdir/$package_name"
|
||||||
cp README.md "$tempdir/$package_name"
|
cp README.md "$tempdir/$package_name"
|
||||||
cp LICENSE-MIT "$tempdir/$package_name"
|
cp LICENSE-MIT "$tempdir/$package_name"
|
||||||
cp LICENSE-APACHE "$tempdir/$package_name"
|
cp LICENSE-APACHE "$tempdir/$package_name"
|
||||||
|
|
||||||
|
# various autocomplete
|
||||||
|
cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".bash "$tempdir/$package_name/autocomplete/${PROJECT_NAME}.bash-completion"
|
||||||
|
cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".fish "$tempdir/$package_name/autocomplete"
|
||||||
|
cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/_"$PROJECT_NAME" "$tempdir/$package_name/autocomplete"
|
||||||
|
|
||||||
# archiving
|
# archiving
|
||||||
pushd "$tempdir"
|
pushd "$tempdir"
|
||||||
tar czf "$out_dir/$package_name.tar.gz" "$package_name"/*
|
tar czf "$out_dir/$package_name.tar.gz" "$package_name"/*
|
||||||
@@ -41,17 +57,28 @@ make_deb() {
|
|||||||
local version
|
local version
|
||||||
local dpkgname
|
local dpkgname
|
||||||
local conflictname
|
local conflictname
|
||||||
|
local gcc_prefix
|
||||||
|
|
||||||
case $TARGET in
|
case $TARGET in
|
||||||
x86_64*)
|
x86_64*)
|
||||||
architecture=amd64
|
architecture=amd64
|
||||||
|
gcc_prefix=""
|
||||||
;;
|
;;
|
||||||
i686*)
|
i686*)
|
||||||
architecture=i386
|
architecture=i386
|
||||||
|
gcc_prefix=""
|
||||||
|
;;
|
||||||
|
aarch64*)
|
||||||
|
architecture=arm64
|
||||||
|
gcc_prefix="aarch64-linux-gnu-"
|
||||||
|
;;
|
||||||
|
arm*hf)
|
||||||
|
architecture=armhf
|
||||||
|
gcc_prefix="arm-linux-gnueabihf-"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: unknown target" >&2
|
echo "make_deb: skipping target '${TARGET}'" >&2
|
||||||
return 1
|
return 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
version=${TRAVIS_TAG#v}
|
version=${TRAVIS_TAG#v}
|
||||||
@@ -67,7 +94,11 @@ make_deb() {
|
|||||||
|
|
||||||
# copy the main binary
|
# copy the main binary
|
||||||
install -Dm755 "target/$TARGET/release/$PROJECT_NAME" "$tempdir/usr/bin/$PROJECT_NAME"
|
install -Dm755 "target/$TARGET/release/$PROJECT_NAME" "$tempdir/usr/bin/$PROJECT_NAME"
|
||||||
strip "$tempdir/usr/bin/$PROJECT_NAME"
|
"${gcc_prefix}"strip "$tempdir/usr/bin/$PROJECT_NAME"
|
||||||
|
|
||||||
|
# manpage
|
||||||
|
install -Dm644 "doc/$PROJECT_NAME.1" "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
|
||||||
|
gzip --best "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
|
||||||
|
|
||||||
# readme and license
|
# readme and license
|
||||||
install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md"
|
install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md"
|
||||||
@@ -86,6 +117,7 @@ Architecture: $architecture
|
|||||||
Provides: $PROJECT_NAME
|
Provides: $PROJECT_NAME
|
||||||
Conflicts: $conflictname
|
Conflicts: $conflictname
|
||||||
Description: A cat(1) clone with wings.
|
Description: A cat(1) clone with wings.
|
||||||
|
A cat(1) clone with syntax highlighting and Git integration.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
fakeroot dpkg-deb --build "$tempdir" "${dpkgname}_${version}_${architecture}.deb"
|
fakeroot dpkg-deb --build "$tempdir" "${dpkgname}_${version}_${architecture}.deb"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# This script takes care of packaging the build artifacts that will go in the
|
||||||
|
# release zipfile
|
||||||
|
|
||||||
|
$SRC_DIR = $PWD.Path
|
||||||
|
$STAGE = [System.Guid]::NewGuid().ToString()
|
||||||
|
|
||||||
|
Set-Location $ENV:Temp
|
||||||
|
New-Item -Type Directory -Name $STAGE
|
||||||
|
Set-Location $STAGE
|
||||||
|
|
||||||
|
$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"
|
||||||
|
|
||||||
|
Copy-Item "$SRC_DIR\target\release\bat.exe" '.\'
|
||||||
|
Copy-Item $SRC_DIR\target\release\build\bat-*\out\_bat.ps1 '.\'
|
||||||
|
|
||||||
|
# readme and license
|
||||||
|
Copy-Item $SRC_DIR\README.md '.\'
|
||||||
|
Copy-Item $SRC_DIR\LICENSE-MIT '.\'
|
||||||
|
Copy-Item $SRC_DIR\LICENSE-APACHE '.\'
|
||||||
|
|
||||||
|
7z a "$ZIP" *
|
||||||
|
|
||||||
|
Push-AppveyorArtifact "$ZIP"
|
||||||
|
|
||||||
|
Set-Location ..
|
||||||
|
Remove-Item $STAGE -Force -Recurse
|
||||||
|
Set-Location $SRC_DIR
|
||||||
Executable
+37
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
if [ "$TRAVIS_OS_NAME" != linux ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
|
# needed for musl targets
|
||||||
|
sudo apt-get install -y musl-tools
|
||||||
|
|
||||||
|
# needed to build deb packages
|
||||||
|
sudo apt-get install -y fakeroot
|
||||||
|
|
||||||
|
# needed for i686 linux gnu target
|
||||||
|
if [[ $TARGET == i686-unknown-linux-gnu ]]; then
|
||||||
|
sudo apt-get install -y gcc-multilib
|
||||||
|
fi
|
||||||
|
|
||||||
|
# needed for cross-compiling for arm
|
||||||
|
if [[ $TARGET == arm-unknown-linux-gnueabihf ]]; then
|
||||||
|
sudo apt-get install -y \
|
||||||
|
gcc-4.8-arm-linux-gnueabihf \
|
||||||
|
binutils-arm-linux-gnueabihf \
|
||||||
|
libc6-armhf-cross \
|
||||||
|
libc6-dev-armhf-cross
|
||||||
|
fi
|
||||||
|
|
||||||
|
# needed for cross-compiling for arm64
|
||||||
|
if [[ $TARGET == aarch64-unknown-linux-gnu ]]; then
|
||||||
|
sudo apt-get install -y \
|
||||||
|
gcc-4.8-aarch64-linux-gnu \
|
||||||
|
binutils-aarch64-linux-gnu \
|
||||||
|
gcc-aarch64-linux-gnu
|
||||||
|
fi
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# Incorporate TARGET env var to the build and test process
|
||||||
|
cargo build --target "$TARGET" --verbose
|
||||||
|
|
||||||
|
# We cannot run arm executables on linux
|
||||||
|
if [[ $TARGET != arm-unknown-linux-gnueabihf ]] && [[ $TARGET != aarch64-unknown-linux-gnu ]]; then
|
||||||
|
cargo test --target "$TARGET" --verbose
|
||||||
|
|
||||||
|
# Run 'bat' on its own source code and the README
|
||||||
|
cargo run --target "$TARGET" -- src/main.rs README.md --paging=never
|
||||||
|
fi
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Alternatives
|
||||||
|
|
||||||
|
The following table tries to give an overview *from `bat`s perspective*, i.e. we only compare
|
||||||
|
categories which are relevant for `bat`. Some of these projects have completely different goals and
|
||||||
|
if you are not looking for a program like `bat`, this comparison might not be for you.
|
||||||
|
|
||||||
|
| | bat | [pygments](http://pygments.org/) | [highlight](http://www.andre-simon.de/doku/highlight/highlight.php) | [ccat](https://github.com/jingweno/ccat) | [source-highlight](https://www.gnu.org/software/src-highlite/) | [hicat](https://github.com/rstacruz/hicat) | [coderay](https://github.com/rubychan/coderay) | [rouge](https://github.com/jneen/rouge) |
|
||||||
|
|----------------------------------------------|---------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------|------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|
|
||||||
|
| Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: |
|
||||||
|
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
|
||||||
|
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: |
|
||||||
|
| Languages (circa) | 100 | 300 | 200 | 7 | 80 | 130 | 30 | 130 |
|
||||||
|
| Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: |
|
||||||
|
| Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
|
| Execution time [ms] (`jquery-3.3.1.js`) | 624 | 789 | 400 | 80 | 300 | 316 | 157 | 695 |
|
||||||
|
| Execution time [ms] (`miniz.c`) | 66 | 656 | 26 | 8 | 53 | 141 | 75 | 254 |
|
||||||
|
| Execution time [ms] (370 kB XML file) | 238 | 487 | 129 | 111 | 110 | 339 | 147 | 359 |
|
||||||
|
|
||||||
|
If you think that some entries in this table are outdated or wrong, please open a ticket or pull
|
||||||
|
request.
|
||||||
|
|
||||||
|
Some other alternatives that are also related, but not yet included in the table:
|
||||||
|
- [lesspipe](https://github.com/wofr06/lesspipe)
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
.TH BAT "1"
|
||||||
|
.SH NAME
|
||||||
|
bat \- manual page for bat
|
||||||
|
.SH DESCRIPTION
|
||||||
|
bat - a cat(1) clone with syntax highlighting and Git integration.
|
||||||
|
.SH "USAGE"
|
||||||
|
.IP
|
||||||
|
bat [OPTIONS] [FILE]...
|
||||||
|
.IP
|
||||||
|
bat <SUBCOMMAND>
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.HP
|
||||||
|
\fB\-l\fR, \fB\-\-language\fR <language>
|
||||||
|
.IP
|
||||||
|
Explicitly set the language for syntax highlighting. The language can be
|
||||||
|
specified as a name (like 'C++' or 'LaTeX') or possible file extension (like
|
||||||
|
\&'cpp', 'hpp' or 'md'). Use '\-\-list\-languages' to show all supported language
|
||||||
|
names and file extensions.
|
||||||
|
.HP
|
||||||
|
\fB\-\-list\-languages\fR
|
||||||
|
.IP
|
||||||
|
Display a list of supported languages for syntax highlighting.
|
||||||
|
.HP
|
||||||
|
\fB\-m\fR, \fB\-\-map\-syntax\fR <from:to>...
|
||||||
|
.IP
|
||||||
|
Map a file extension or file name to an existing syntax. For example, to highlight
|
||||||
|
*.conf files with the INI syntax, use '\-m conf:ini'. To highlight files named
|
||||||
|
\&'.myignore' with the Git Ignore syntax, use '\-m .myignore:gitignore'.
|
||||||
|
.HP
|
||||||
|
\fB\-\-theme\fR <theme>
|
||||||
|
.IP
|
||||||
|
Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all
|
||||||
|
available themes. To set a default theme, export the BAT_THEME environment
|
||||||
|
variable (e.g.: export BAT_THEME="TwoDark").
|
||||||
|
.HP
|
||||||
|
\fB\-\-list\-themes\fR
|
||||||
|
.IP
|
||||||
|
Display a list of supported themes for syntax highlighting.
|
||||||
|
.HP
|
||||||
|
\fB\-\-style\fR <style\-components>
|
||||||
|
.IP
|
||||||
|
Configure which elements (line numbers, file headers, grid borders, Git
|
||||||
|
modifications, ..) to display in addition to the file contents. The argument
|
||||||
|
is a comma\-separated list of components to display (e.g.
|
||||||
|
\&'numbers,changes,grid') or a pre\-defined style ('full'). To set a default
|
||||||
|
theme, export the BAT_STYLE environment variable (e.g.: export
|
||||||
|
BAT_STYLE="numbers"). [possible values: auto, full, plain, changes, header,
|
||||||
|
grid, numbers]
|
||||||
|
.HP
|
||||||
|
\fB\-p\fR, \fB\-\-plain\fR
|
||||||
|
.IP
|
||||||
|
Only show plain style, no decorations. This is an alias for '\-\-style=plain'
|
||||||
|
.HP
|
||||||
|
\fB\-n\fR, \fB\-\-number\fR
|
||||||
|
.IP
|
||||||
|
Only show line numbers, no other decorations. This is an alias for
|
||||||
|
\&'\-\-style=numbers'
|
||||||
|
.HP
|
||||||
|
\fB\-\-line\-range\fR <N:M>
|
||||||
|
.IP
|
||||||
|
Only print the specified range of lines for each file. For example:
|
||||||
|
.RS
|
||||||
|
.IP "\-\-line\-range 30:40"
|
||||||
|
prints lines 30 to 40
|
||||||
|
.IP "\-\-line\-range :40"
|
||||||
|
prints lines 1 to 40
|
||||||
|
.IP "\-\-line\-range 40:"
|
||||||
|
prints lines 40 to the end of the file
|
||||||
|
.RE
|
||||||
|
.HP
|
||||||
|
\fB\-\-color\fR <when>
|
||||||
|
.IP
|
||||||
|
Specify when to use colored output. The automatic mode only enables colors if an
|
||||||
|
interactive terminal is detected. Possible values: *auto*, never, always.
|
||||||
|
.HP
|
||||||
|
\fB\-\-decorations\fR <when>
|
||||||
|
.IP
|
||||||
|
Specify when to use the decorations that have been specified via '\-\-style'. The
|
||||||
|
automatic mode only enables decorations if an interactive terminal is detected. Possible
|
||||||
|
values: *auto*, never, always.
|
||||||
|
.HP
|
||||||
|
\fB\-\-paging\fR <when>
|
||||||
|
.IP
|
||||||
|
Specify when to use the pager. To control which pager is used, set the PAGER or
|
||||||
|
BAT_PAGER environment variables (the latter takes precedence). The default pager is
|
||||||
|
\&'less'. To disable the pager permanently, set BAT_PAGER to an empty string. Possible
|
||||||
|
values: *auto*, never, always.
|
||||||
|
.HP
|
||||||
|
\fB\-\-wrap\fR <mode>
|
||||||
|
.IP
|
||||||
|
Specify the text\-wrapping mode (*auto*, never, character).
|
||||||
|
.HP
|
||||||
|
\fB\-\-tabs\fR <T>
|
||||||
|
.IP
|
||||||
|
Set the tab width to T spaces. Use a width of 0 to pass tabs through directly
|
||||||
|
.HP
|
||||||
|
\fB\-u\fR, \fB\-\-unbuffered\fR
|
||||||
|
.IP
|
||||||
|
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered'). The output is
|
||||||
|
always unbuffered \- this option is simply ignored.
|
||||||
|
.HP
|
||||||
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
.IP
|
||||||
|
Print this help message.
|
||||||
|
.HP
|
||||||
|
\fB\-V\fR, \fB\-\-version\fR
|
||||||
|
.IP
|
||||||
|
Show version information.
|
||||||
|
.SH "ARGS"
|
||||||
|
.IP
|
||||||
|
<FILE>...
|
||||||
|
.IP
|
||||||
|
File(s) to print / concatenate. Use a dash ('\-') or no argument at all to read
|
||||||
|
from standard input.
|
||||||
|
.SH "SUBCOMMANDS"
|
||||||
|
.IP
|
||||||
|
cache
|
||||||
|
.IP
|
||||||
|
Modify the syntax\-definition and theme cache. See "bat cache --help" for more information
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000"
|
||||||
|
height="286.64285"
|
||||||
|
viewBox="0 0 1000 286.64285"
|
||||||
|
version="1.1"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996"
|
||||||
|
id="svg1285"
|
||||||
|
sodipodi:docname="logo-header.svg"
|
||||||
|
inkscape:version="0.92.2 2405546, 2018-03-11"><metadata
|
||||||
|
id="metadata1289"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1175"
|
||||||
|
id="namedview1287"
|
||||||
|
showgrid="false"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:zoom="0.82573726"
|
||||||
|
inkscape:cx="438.92362"
|
||||||
|
inkscape:cy="320.87266"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg1285"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.14294769px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||||
|
id="rect1929"
|
||||||
|
width="1000"
|
||||||
|
height="286.64285"
|
||||||
|
x="0"
|
||||||
|
y="0" /><g
|
||||||
|
id="g929"
|
||||||
|
transform="translate(0,13.321425)"><g
|
||||||
|
transform="matrix(5.1207879,0,0,4.741146,45.483811,-7057.152)"
|
||||||
|
id="g1168">
|
||||||
|
<path
|
||||||
|
d="m 77.792,1533.05 c 0,0.32 -0.064,0.61 -0.192,0.88 -0.128,0.27 -0.3,0.5 -0.516,0.7 -0.216,0.19 -0.468,0.34 -0.756,0.45 -0.288,0.11 -0.596,0.16 -0.924,0.16 h -4.02 v -8.52 h 4.104 c 0.296,0 0.564,0.07 0.804,0.19 0.24,0.13 0.444,0.3 0.612,0.5 0.168,0.21 0.298,0.44 0.39,0.7 0.092,0.26 0.138,0.52 0.138,0.78 0,0.44 -0.108,0.83 -0.324,1.19 -0.216,0.35 -0.516,0.62 -0.9,0.8 0.488,0.14 0.874,0.41 1.158,0.8 0.284,0.39 0.426,0.85 0.426,1.37 z m -0.84,-0.15 c 0,-0.21 -0.036,-0.41 -0.108,-0.6 -0.072,-0.2 -0.174,-0.37 -0.306,-0.52 -0.132,-0.15 -0.288,-0.27 -0.468,-0.36 -0.18,-0.09 -0.374,-0.14 -0.582,-0.14 h -3.264 v 3.23 h 3.18 c 0.216,0 0.418,-0.04 0.606,-0.13 0.188,-0.09 0.352,-0.21 0.492,-0.35 0.14,-0.15 0.25,-0.33 0.33,-0.52 0.08,-0.2 0.12,-0.4 0.12,-0.61 z m -4.728,-5.45 v 3.15 h 2.928 c 0.208,0 0.402,-0.04 0.582,-0.13 0.18,-0.09 0.334,-0.21 0.462,-0.35 0.128,-0.14 0.228,-0.31 0.3,-0.5 0.072,-0.19 0.108,-0.38 0.108,-0.59 0,-0.22 -0.034,-0.42 -0.102,-0.62 -0.068,-0.19 -0.164,-0.35 -0.288,-0.49 -0.124,-0.14 -0.27,-0.26 -0.438,-0.34 -0.168,-0.08 -0.352,-0.13 -0.552,-0.13 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1162"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m 88.436,1526.72 h 0.708 l 3.54,8.52 h -0.888 l -1.104,-2.66 h -3.828 l -1.092,2.66 h -0.9 z m 2.064,5.2 -1.716,-4.21 -1.74,4.21 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1164"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m 105.716,1527.47 h -3.036 v 7.77 h -0.84 v -7.77 h -3.036 v -0.75 h 6.912 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1166"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g><g
|
||||||
|
transform="translate(1.9578e-5)"
|
||||||
|
id="g6103"><g
|
||||||
|
id="g1172"
|
||||||
|
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path1170"
|
||||||
|
style="fill:url(#_Linear1)"
|
||||||
|
d="m 4399.57,773.907 c 0,0 35.33,20.718 42.25,24.779 13.1,7.683 47.96,27.832 64.24,37.232 1.77,1.027 2.87,2.923 2.87,4.975 0.01,2.053 -1.08,3.952 -2.85,4.986 -27.1,15.803 -110.2,64.254 -128.26,74.788 -2.16,1.254 -4.82,1.237 -6.95,-0.046 -13.57,-8.147 -62.93,-37.791 -75.02,-44.875 -16.93,-9.911 -37.27,-21.84 -37.27,-21.84 z" />
|
||||||
|
</g><g
|
||||||
|
id="g1176"
|
||||||
|
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path1174"
|
||||||
|
style="fill:#31369e"
|
||||||
|
d="m 4269.48,860.305 c -54.5,-31.918 -88.34,-51.732 -117.18,-68.621 -3.98,-2.335 -6.43,-6.608 -6.44,-11.228 0,-4.619 2.45,-8.893 6.44,-11.229 l 319.41,-187.171 c 2.02,-1.186 4.52,-1.198 6.56,-0.032 2.03,1.166 3.29,3.333 3.29,5.678 0,29.472 0,107.932 0,138.732 0,7.842 -4.16,15.094 -10.94,19.049 -13.32,7.783 -54.43,31.465 -67.73,39.233 0,0 -133.3,75.654 -133.41,75.589 z" />
|
||||||
|
</g><g
|
||||||
|
id="g1180"
|
||||||
|
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path1178"
|
||||||
|
style="fill:#1d2167"
|
||||||
|
d="m 4604.42,705.593 85.54,34.367 v -63.802 c 0,-2.628 -1.37,-5.066 -3.62,-6.431 -2.24,-1.365 -5.04,-1.459 -7.37,-0.247 -5.93,3.078 -74.55,36.113 -74.55,36.113 z" />
|
||||||
|
</g><g
|
||||||
|
id="g1184"
|
||||||
|
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path1182"
|
||||||
|
style="fill:url(#_Linear2)"
|
||||||
|
d="m 4976.91,704.019 c 0,0 -8.53,-4.983 -8.56,-5 -79.92,-46.83 -170.16,-99.71 -199.6,-116.963 -2.02,-1.186 -4.52,-1.198 -6.56,-0.032 -2.04,1.166 -3.29,3.333 -3.29,5.678 0,29.472 0,107.932 0,138.732 0,7.842 4.16,15.094 10.93,19.049 13.33,7.783 68.33,39.913 68.33,39.913 z" />
|
||||||
|
</g><g
|
||||||
|
id="g1188"
|
||||||
|
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path1186"
|
||||||
|
style="fill:url(#_Linear3)"
|
||||||
|
d="m 4968.44,699.073 c 0,0 -235.66,138.235 -263.83,154.762 -3.01,1.764 -6.73,1.783 -9.76,0.05 -3.02,-1.733 -4.89,-4.953 -4.89,-8.44 V 731.796 c 0,0 -111.16,-50.383 -128.47,-59.371 -2.33,-1.212 -4.9781,-0.84921 -7.37,0.247 -1.9592,0.89788 -3.62,3.803 -3.62,6.431 v 166.342 c 0,3.487 0.43,15.045 -12.02,22.226 -2.41,1.392 -130.21,75.278 -130.21,75.278 l 211.99,122.751 c 0,0 377.71,-221.201 467.9,-274.016 3.98,-2.335 6.43,-6.608 6.43,-11.228 0,-4.619 -2.45,-8.893 -6.43,-11.229 -24.64,-14.438 -119.72,-70.154 -119.72,-70.154"
|
||||||
|
sodipodi:nodetypes="cccsccsssccccscc" />
|
||||||
|
</g></g><g
|
||||||
|
transform="matrix(0.18627124,0,0,0.22786575,340.43532,-286.36087)"
|
||||||
|
id="g1262">
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1192">
|
||||||
|
<path
|
||||||
|
d="m 374.487,2270.67 h 4.788 l 23.94,57.61 h -6.006 l -7.465,-18.01 h -25.887 l -7.385,18.01 h -6.086 z m 13.958,35.14 -11.604,-28.49 -11.767,28.49 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1190"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1196">
|
||||||
|
<path
|
||||||
|
d="m 421.293,2307.02 c 0,-2.97 0.514,-5.78 1.542,-8.44 1.028,-2.65 2.475,-4.96 4.342,-6.94 1.866,-1.97 4.098,-3.52 6.695,-4.66 2.596,-1.14 5.464,-1.7 8.602,-1.7 4.003,0 7.492,0.9 10.468,2.71 2.975,1.82 5.221,4.26 6.735,7.35 l -5.356,1.7 c -1.19,-2.16 -2.853,-3.85 -4.99,-5.07 -2.137,-1.22 -4.504,-1.83 -7.101,-1.83 -2.164,0 -4.179,0.44 -6.046,1.3 -1.866,0.87 -3.489,2.05 -4.869,3.53 -1.379,1.49 -2.461,3.26 -3.246,5.32 -0.784,2.05 -1.176,4.3 -1.176,6.73 0,2.38 0.405,4.63 1.217,6.74 0.811,2.11 1.92,3.94 3.327,5.48 1.407,1.54 3.043,2.76 4.91,3.65 1.866,0.89 3.854,1.34 5.964,1.34 1.353,0 2.692,-0.19 4.017,-0.57 1.326,-0.38 2.556,-0.91 3.692,-1.58 1.137,-0.68 2.11,-1.45 2.922,-2.32 0.811,-0.86 1.379,-1.78 1.704,-2.75 l 5.437,1.62 c -0.595,1.51 -1.461,2.91 -2.597,4.18 -1.136,1.27 -2.475,2.38 -4.017,3.32 -1.541,0.95 -3.246,1.68 -5.112,2.2 -1.867,0.51 -3.801,0.77 -5.802,0.77 -3.084,0 -5.924,-0.59 -8.521,-1.75 -2.597,-1.16 -4.842,-2.76 -6.736,-4.79 -1.893,-2.03 -3.367,-4.36 -4.422,-7.02 -1.055,-2.65 -1.583,-5.49 -1.583,-8.52 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1194"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1200">
|
||||||
|
<path
|
||||||
|
d="m 476.962,2329.1 c -2.001,0 -3.854,-0.34 -5.558,-1.02 -1.705,-0.67 -3.192,-1.61 -4.464,-2.8 -1.271,-1.19 -2.258,-2.58 -2.962,-4.18 -0.703,-1.59 -1.055,-3.31 -1.055,-5.15 0,-1.84 0.433,-3.54 1.299,-5.11 0.865,-1.57 2.083,-2.92 3.652,-4.06 1.568,-1.14 3.435,-2.02 5.599,-2.64 2.164,-0.62 4.544,-0.93 7.141,-0.93 2.164,0 4.355,0.19 6.573,0.57 2.218,0.38 4.193,0.92 5.924,1.62 v -3.81 c 0,-3.74 -1.055,-6.7 -3.165,-8.89 -2.11,-2.19 -5.031,-3.29 -8.764,-3.29 -2.164,0 -4.382,0.44 -6.654,1.3 -2.272,0.87 -4.572,2.11 -6.898,3.74 l -1.948,-3.66 c 5.465,-3.67 10.766,-5.51 15.906,-5.51 5.302,0 9.467,1.48 12.497,4.46 3.03,2.97 4.544,7.09 4.544,12.33 v 19.07 c 0,1.52 0.677,2.28 2.029,2.28 v 4.86 c -0.919,0.17 -1.623,0.25 -2.11,0.25 -1.406,0 -2.502,-0.35 -3.286,-1.06 -0.785,-0.7 -1.204,-1.67 -1.258,-2.92 l -0.162,-3.33 c -1.948,2.55 -4.396,4.5 -7.345,5.85 -2.948,1.35 -6.126,2.03 -9.535,2.03 z m 1.299,-4.22 c 2.867,0 5.504,-0.54 7.912,-1.63 2.407,-1.08 4.233,-2.51 5.478,-4.3 0.486,-0.48 0.852,-1.01 1.095,-1.58 0.244,-0.57 0.365,-1.09 0.365,-1.58 v -6.9 c -1.839,-0.7 -3.746,-1.24 -5.721,-1.62 -1.975,-0.38 -3.99,-0.57 -6.046,-0.57 -3.895,0 -7.06,0.81 -9.494,2.43 -2.435,1.63 -3.652,3.76 -3.652,6.41 0,1.3 0.257,2.52 0.771,3.66 0.514,1.13 1.217,2.12 2.11,2.96 0.893,0.84 1.961,1.5 3.205,1.99 1.245,0.48 2.57,0.73 3.977,0.73 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1198"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1204">
|
||||||
|
<path
|
||||||
|
d="m 528.158,2326.26 c -0.325,0.16 -0.798,0.38 -1.42,0.65 -0.622,0.27 -1.339,0.54 -2.151,0.81 -0.811,0.27 -1.731,0.51 -2.759,0.73 -1.028,0.21 -2.11,0.32 -3.246,0.32 -1.19,0 -2.326,-0.16 -3.408,-0.49 -1.082,-0.32 -2.029,-0.82 -2.84,-1.5 -0.812,-0.67 -1.461,-1.52 -1.948,-2.55 -0.487,-1.03 -0.73,-2.22 -0.73,-3.57 v -30.27 h -5.843 v -4.38 h 5.843 v -14.29 h 5.518 v 14.29 h 9.738 v 4.38 h -9.738 v 28.73 c 0.108,1.56 0.663,2.71 1.664,3.44 1,0.73 2.15,1.1 3.448,1.1 1.569,0 2.949,-0.26 4.139,-0.77 1.19,-0.52 1.948,-0.88 2.272,-1.1 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1202"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1208">
|
||||||
|
<path
|
||||||
|
d="m 547.959,2307.02 c 0,-2.97 0.514,-5.78 1.542,-8.44 1.027,-2.65 2.475,-4.96 4.341,-6.94 1.866,-1.97 4.098,-3.52 6.695,-4.66 2.597,-1.14 5.464,-1.7 8.602,-1.7 4.003,0 7.493,0.9 10.468,2.71 2.976,1.82 5.221,4.26 6.736,7.35 l -5.356,1.7 c -1.19,-2.16 -2.854,-3.85 -4.991,-5.07 -2.137,-1.22 -4.504,-1.83 -7.101,-1.83 -2.164,0 -4.179,0.44 -6.045,1.3 -1.867,0.87 -3.49,2.05 -4.869,3.53 -1.38,1.49 -2.462,3.26 -3.246,5.32 -0.785,2.05 -1.177,4.3 -1.177,6.73 0,2.38 0.406,4.63 1.217,6.74 0.812,2.11 1.921,3.94 3.327,5.48 1.407,1.54 3.044,2.76 4.91,3.65 1.866,0.89 3.855,1.34 5.965,1.34 1.352,0 2.691,-0.19 4.016,-0.57 1.326,-0.38 2.557,-0.91 3.693,-1.58 1.136,-0.68 2.11,-1.45 2.921,-2.32 0.812,-0.86 1.38,-1.78 1.704,-2.75 l 5.437,1.62 c -0.595,1.51 -1.46,2.91 -2.596,4.18 -1.136,1.27 -2.475,2.38 -4.017,3.32 -1.542,0.95 -3.246,1.68 -5.113,2.2 -1.866,0.51 -3.8,0.77 -5.802,0.77 -3.084,0 -5.924,-0.59 -8.521,-1.75 -2.597,-1.16 -4.842,-2.76 -6.735,-4.79 -1.894,-2.03 -3.368,-4.36 -4.423,-7.02 -1.055,-2.65 -1.582,-5.49 -1.582,-8.52 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1206"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1212">
|
||||||
|
<path
|
||||||
|
d="m 593.24,2269.05 h 5.519 v 49.66 c 0,1.57 0.432,2.8 1.298,3.69 0.866,0.89 2.083,1.34 3.652,1.34 0.595,0 1.298,-0.08 2.11,-0.24 0.811,-0.16 1.569,-0.38 2.272,-0.65 l 0.974,4.46 c -1.028,0.43 -2.286,0.79 -3.774,1.06 -1.487,0.27 -2.772,0.4 -3.854,0.4 -2.543,0 -4.545,-0.72 -6.005,-2.15 -1.461,-1.43 -2.192,-3.45 -2.192,-6.04 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1210"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1216">
|
||||||
|
<path
|
||||||
|
d="m 630.651,2329.1 c -3.084,0 -5.897,-0.59 -8.44,-1.75 -2.543,-1.16 -4.747,-2.74 -6.614,-4.75 -1.866,-2 -3.313,-4.32 -4.341,-6.97 -1.028,-2.66 -1.542,-5.44 -1.542,-8.36 0,-2.98 0.527,-5.79 1.582,-8.44 1.055,-2.65 2.516,-4.98 4.383,-6.98 1.866,-2 4.071,-3.6 6.613,-4.79 2.543,-1.19 5.329,-1.78 8.359,-1.78 3.029,0 5.829,0.59 8.399,1.78 2.57,1.19 4.788,2.79 6.654,4.79 1.867,2 3.327,4.33 4.382,6.98 1.055,2.65 1.583,5.46 1.583,8.44 0,2.92 -0.514,5.7 -1.542,8.36 -1.028,2.65 -2.475,4.97 -4.342,6.97 -1.866,2.01 -4.084,3.59 -6.654,4.75 -2.57,1.16 -5.397,1.75 -8.48,1.75 z m -15.338,-21.75 c 0,2.38 0.406,4.58 1.218,6.61 0.811,2.03 1.907,3.82 3.286,5.36 1.38,1.54 3.003,2.74 4.869,3.61 1.867,0.86 3.855,1.3 5.965,1.3 2.11,0 4.098,-0.45 5.964,-1.34 1.867,-0.89 3.503,-2.11 4.91,-3.65 1.406,-1.54 2.516,-3.34 3.327,-5.4 0.812,-2.06 1.217,-4.27 1.217,-6.65 0,-2.33 -0.405,-4.53 -1.217,-6.62 -0.811,-2.08 -1.921,-3.89 -3.327,-5.43 -1.407,-1.55 -3.043,-2.76 -4.91,-3.66 -1.866,-0.89 -3.854,-1.34 -5.964,-1.34 -2.11,0 -4.085,0.45 -5.924,1.34 -1.84,0.9 -3.463,2.13 -4.869,3.7 -1.407,1.56 -2.516,3.39 -3.327,5.47 -0.812,2.09 -1.218,4.32 -1.218,6.7 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1214"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1220">
|
||||||
|
<path
|
||||||
|
d="m 694.029,2328.28 h -5.518 v -23.61 c 0,-5.03 -0.744,-8.68 -2.232,-10.95 -1.488,-2.28 -3.773,-3.41 -6.857,-3.41 -1.623,0 -3.246,0.29 -4.869,0.89 -1.623,0.59 -3.124,1.43 -4.504,2.52 -1.379,1.08 -2.61,2.36 -3.692,3.85 -1.082,1.49 -1.867,3.1 -2.354,4.83 v 25.88 h -5.518 v -42.27 h 5.032 v 9.57 c 1.731,-3.08 4.206,-5.57 7.425,-7.46 3.219,-1.9 6.722,-2.84 10.509,-2.84 2.326,0 4.301,0.43 5.924,1.29 1.623,0.87 2.921,2.09 3.895,3.65 0.974,1.57 1.677,3.5 2.11,5.77 0.433,2.27 0.649,4.79 0.649,7.54 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1218"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1224">
|
||||||
|
<path
|
||||||
|
d="m 721.62,2329.1 c -3.084,0 -5.91,-0.59 -8.48,-1.75 -2.57,-1.16 -4.801,-2.76 -6.695,-4.79 -1.893,-2.03 -3.368,-4.36 -4.423,-7.02 -1.055,-2.65 -1.582,-5.49 -1.582,-8.52 0,-2.97 0.527,-5.77 1.582,-8.4 1.055,-2.62 2.516,-4.92 4.382,-6.89 1.867,-1.98 4.099,-3.55 6.695,-4.71 2.597,-1.16 5.41,-1.74 8.44,-1.74 3.084,0 5.91,0.58 8.48,1.74 2.57,1.16 4.775,2.74 6.614,4.75 1.839,2 3.273,4.3 4.301,6.89 1.028,2.6 1.542,5.36 1.542,8.28 0,0.44 0,0.87 0,1.3 0,0.43 -0.027,0.73 -0.081,0.89 h -36.193 c 0.162,2.28 0.689,4.37 1.582,6.29 0.893,1.92 2.042,3.59 3.449,4.99 1.407,1.41 3.016,2.5 4.828,3.29 1.813,0.78 3.747,1.18 5.803,1.18 1.352,0 2.705,-0.19 4.057,-0.57 1.353,-0.38 2.597,-0.89 3.733,-1.54 1.136,-0.65 2.164,-1.45 3.084,-2.4 0.919,-0.94 1.623,-1.99 2.11,-3.12 l 4.787,1.3 c -0.649,1.57 -1.568,2.99 -2.759,4.26 -1.19,1.27 -2.569,2.38 -4.138,3.32 -1.569,0.95 -3.3,1.68 -5.194,2.2 -1.893,0.51 -3.868,0.77 -5.924,0.77 z m 15.581,-24.19 c -0.162,-2.27 -0.69,-4.34 -1.582,-6.21 -0.893,-1.86 -2.029,-3.47 -3.409,-4.82 -1.379,-1.35 -2.975,-2.41 -4.788,-3.17 -1.812,-0.76 -3.746,-1.13 -5.802,-1.13 -2.056,0 -4.003,0.37 -5.843,1.13 -1.839,0.76 -3.449,1.82 -4.828,3.17 -1.38,1.35 -2.489,2.97 -3.327,4.87 -0.839,1.89 -1.339,3.95 -1.502,6.16 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1222"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1228">
|
||||||
|
<path
|
||||||
|
d="m 818.344,2286.01 h 5.437 l -18.178,42.27 h -4.544 l -9.089,-21.58 -9.008,21.58 h -4.544 l -18.178,-42.27 h 5.356 l 15.418,36.59 8.034,-19.31 -7.222,-17.2 h 4.626 l 5.518,13.79 5.518,-13.79 h 4.707 l -7.223,17.2 8.034,19.31 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1226"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1232">
|
||||||
|
<path
|
||||||
|
d="m 828.65,2328.28 v -42.27 h 5.518 v 42.27 z m 0,-51.12 v -8.11 h 5.518 v 8.11 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1230"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1236">
|
||||||
|
<path
|
||||||
|
d="m 864.193,2326.26 c -0.324,0.16 -0.798,0.38 -1.42,0.65 -0.622,0.27 -1.339,0.54 -2.15,0.81 -0.812,0.27 -1.731,0.51 -2.759,0.73 -1.028,0.21 -2.11,0.32 -3.246,0.32 -1.19,0 -2.327,-0.16 -3.409,-0.49 -1.082,-0.32 -2.028,-0.82 -2.84,-1.5 -0.811,-0.67 -1.461,-1.52 -1.947,-2.55 -0.487,-1.03 -0.731,-2.22 -0.731,-3.57 v -30.27 h -5.843 v -4.38 h 5.843 v -14.29 h 5.518 v 14.29 h 9.738 v 4.38 h -9.738 v 28.73 c 0.109,1.56 0.663,2.71 1.664,3.44 1.001,0.73 2.15,1.1 3.449,1.1 1.569,0 2.948,-0.26 4.139,-0.77 1.19,-0.52 1.947,-0.88 2.272,-1.1 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1234"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1240">
|
||||||
|
<path
|
||||||
|
d="m 904.201,2328.28 h -5.519 v -23.61 c 0,-4.81 -0.825,-8.41 -2.475,-10.79 -1.65,-2.38 -4.071,-3.57 -7.263,-3.57 -1.569,0 -3.124,0.31 -4.666,0.93 -1.542,0.62 -2.989,1.47 -4.341,2.56 -1.353,1.08 -2.53,2.35 -3.53,3.81 -1.001,1.46 -1.745,3.06 -2.232,4.79 v 25.88 h -5.518 v -59.23 h 5.518 v 26.53 c 1.677,-3.19 4.003,-5.71 6.979,-7.55 2.975,-1.83 6.194,-2.75 9.657,-2.75 2.434,0 4.49,0.44 6.167,1.33 1.677,0.9 3.057,2.14 4.139,3.74 1.082,1.59 1.866,3.51 2.353,5.76 0.487,2.24 0.731,4.72 0.731,7.42 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1238"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1244">
|
||||||
|
<path
|
||||||
|
d="m 983.314,2286.01 h 5.437 l -18.177,42.27 h -4.545 l -9.088,-21.58 -9.008,21.58 h -4.545 l -18.177,-42.27 h 5.356 l 15.418,36.59 8.034,-19.31 -7.222,-17.2 h 4.625 l 5.519,13.79 5.518,-13.79 h 4.707 l -7.223,17.2 8.034,19.31 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1242"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1248">
|
||||||
|
<path
|
||||||
|
d="m 993.62,2328.28 v -42.27 h 5.519 v 42.27 z m 0,-51.12 v -8.11 h 5.519 v 8.11 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1246"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1252">
|
||||||
|
<path
|
||||||
|
d="m 1044.42,2328.28 h -5.52 v -23.61 c 0,-5.03 -0.74,-8.68 -2.23,-10.95 -1.49,-2.28 -3.77,-3.41 -6.86,-3.41 -1.62,0 -3.24,0.29 -4.87,0.89 -1.62,0.59 -3.12,1.43 -4.5,2.52 -1.38,1.08 -2.61,2.36 -3.69,3.85 -1.08,1.49 -1.87,3.1 -2.36,4.83 v 25.88 h -5.51 v -42.27 h 5.03 v 9.57 c 1.73,-3.08 4.2,-5.57 7.42,-7.46 3.22,-1.9 6.73,-2.84 10.51,-2.84 2.33,0 4.3,0.43 5.93,1.29 1.62,0.87 2.92,2.09 3.89,3.65 0.97,1.57 1.68,3.5 2.11,5.77 0.43,2.27 0.65,4.79 0.65,7.54 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1250"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1256">
|
||||||
|
<path
|
||||||
|
d="m 1070.71,2328.85 c -2.92,0 -5.58,-0.61 -7.99,-1.82 -2.41,-1.22 -4.49,-2.83 -6.25,-4.83 -1.76,-2 -3.12,-4.3 -4.1,-6.9 -0.97,-2.6 -1.46,-5.27 -1.46,-8.03 0,-2.92 0.48,-5.72 1.42,-8.4 0.95,-2.68 2.29,-5.02 4.02,-7.02 1.73,-2 3.8,-3.6 6.21,-4.79 2.4,-1.19 5.07,-1.78 7.99,-1.78 3.63,0 6.76,0.9 9.41,2.71 2.66,1.82 4.93,4.1 6.82,6.86 v -8.84 h 4.95 v 42.44 c 0,2.92 -0.55,5.5 -1.66,7.75 -1.11,2.24 -2.6,4.12 -4.47,5.64 -1.86,1.51 -4.05,2.65 -6.57,3.4 -2.51,0.76 -5.18,1.14 -7.99,1.14 -4.87,0 -8.79,-0.86 -11.77,-2.6 -2.97,-1.73 -5.38,-4.05 -7.22,-6.97 l 3.41,-2.68 c 1.67,2.7 3.89,4.69 6.65,5.96 2.76,1.27 5.74,1.91 8.93,1.91 2.05,0 4,-0.28 5.84,-0.85 1.84,-0.57 3.45,-1.41 4.83,-2.52 1.38,-1.11 2.47,-2.51 3.29,-4.22 0.81,-1.7 1.21,-3.69 1.21,-5.96 v -8.36 c -1.62,2.7 -3.84,4.84 -6.65,6.41 -2.81,1.57 -5.76,2.35 -8.85,2.35 z m 1.55,-4.62 c 1.62,0 3.21,-0.3 4.78,-0.89 1.57,-0.6 2.99,-1.4 4.26,-2.4 1.28,-1 2.34,-2.12 3.21,-3.37 0.86,-1.24 1.43,-2.51 1.7,-3.81 v -13.07 c -0.59,-1.51 -1.4,-2.92 -2.43,-4.22 -1.03,-1.29 -2.19,-2.4 -3.49,-3.32 -1.3,-0.92 -2.69,-1.65 -4.18,-2.19 -1.49,-0.55 -2.99,-0.82 -4.5,-0.82 -2.39,0 -4.51,0.5 -6.37,1.5 -1.87,1.01 -3.45,2.32 -4.75,3.94 -1.3,1.62 -2.29,3.46 -2.96,5.52 -0.68,2.06 -1.02,4.14 -1.02,6.25 0,2.27 0.41,4.43 1.22,6.49 0.81,2.06 1.93,3.86 3.37,5.4 1.43,1.54 3.09,2.76 4.99,3.65 1.89,0.89 3.95,1.34 6.17,1.34 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1254"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.28,0,0,1,-97.8353,0)"
|
||||||
|
id="g1260">
|
||||||
|
<path
|
||||||
|
d="m 1115.51,2329.1 c -3.3,0 -6.52,-0.55 -9.66,-1.63 -3.14,-1.08 -5.84,-2.65 -8.11,-4.7 l 2.51,-3.74 c 2.38,1.95 4.8,3.41 7.27,4.39 2.46,0.97 5.09,1.46 7.91,1.46 3.41,0 6.12,-0.69 8.15,-2.07 2.03,-1.38 3.05,-3.34 3.05,-5.89 0,-1.19 -0.27,-2.17 -0.82,-2.96 -0.54,-0.78 -1.33,-1.47 -2.39,-2.07 -1.05,-0.59 -2.38,-1.12 -3.98,-1.58 -1.59,-0.46 -3.44,-0.93 -5.56,-1.42 -2.43,-0.59 -4.54,-1.19 -6.32,-1.78 -1.79,-0.6 -3.26,-1.28 -4.43,-2.03 -1.16,-0.76 -2.03,-1.69 -2.59,-2.8 -0.57,-1.11 -0.86,-2.51 -0.86,-4.18 0,-2.11 0.42,-3.98 1.26,-5.6 0.84,-1.63 1.98,-2.96 3.41,-4.02 1.43,-1.05 3.11,-1.85 5.03,-2.39 1.92,-0.54 3.96,-0.81 6.13,-0.81 3.24,0 6.19,0.52 8.84,1.58 2.65,1.05 4.79,2.45 6.41,4.18 l -2.67,3.24 c -1.57,-1.62 -3.48,-2.84 -5.72,-3.65 -2.25,-0.81 -4.59,-1.22 -7.02,-1.22 -1.47,0 -2.82,0.15 -4.06,0.45 -1.25,0.3 -2.34,0.77 -3.29,1.42 -0.94,0.65 -1.69,1.47 -2.23,2.48 -0.54,1 -0.81,2.17 -0.81,3.52 0,1.14 0.19,2.06 0.57,2.76 0.37,0.71 1,1.32 1.86,1.83 0.87,0.51 1.96,0.97 3.29,1.38 1.33,0.41 2.94,0.83 4.83,1.26 2.7,0.65 5.08,1.3 7.14,1.94 2.05,0.66 3.77,1.41 5.15,2.28 1.38,0.86 2.42,1.92 3.13,3.16 0.7,1.25 1.05,2.76 1.05,4.55 0,3.89 -1.49,6.98 -4.46,9.25 -2.98,2.27 -6.98,3.41 -12.01,3.41 z"
|
||||||
|
style="fill:#1d2167;fill-rule:nonzero"
|
||||||
|
id="path1258"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g></g>
|
||||||
|
<defs
|
||||||
|
id="defs1283"><linearGradient
|
||||||
|
id="_Linear1"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-158.501,-265.604,265.604,-158.501,4436.06,964.047)"><stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:rgb(49,54,158);stop-opacity:1"
|
||||||
|
id="stop1266" /><stop
|
||||||
|
offset="0.52"
|
||||||
|
style="stop-color:rgb(38,42,122);stop-opacity:1"
|
||||||
|
id="stop1268" /><stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:black;stop-opacity:1"
|
||||||
|
id="stop1270" /></linearGradient><linearGradient
|
||||||
|
id="_Linear2"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(160.563,96.0376,-96.0376,160.563,4771.78,656.669)"><stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:rgb(49,54,158);stop-opacity:1"
|
||||||
|
id="stop1273" /><stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:rgb(29,33,103);stop-opacity:1"
|
||||||
|
id="stop1275" /></linearGradient><linearGradient
|
||||||
|
id="_Linear3"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(76.53,136.554,-136.554,76.53,4737.26,847.244)"><stop
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:rgb(49,54,158);stop-opacity:1"
|
||||||
|
id="stop1278" /><stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:rgb(29,33,103);stop-opacity:1"
|
||||||
|
id="stop1280" /></linearGradient></defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 23 KiB |
+275
@@ -0,0 +1,275 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::env;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use atty::{self, Stream};
|
||||||
|
|
||||||
|
use clap::ArgMatches;
|
||||||
|
use clap_app;
|
||||||
|
use wild;
|
||||||
|
|
||||||
|
use console::Term;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use ansi_term;
|
||||||
|
|
||||||
|
use assets::BAT_THEME_DEFAULT;
|
||||||
|
use config::{get_args_from_config_file, get_args_from_env_var};
|
||||||
|
use errors::*;
|
||||||
|
use inputfile::InputFile;
|
||||||
|
use line_range::LineRange;
|
||||||
|
use style::{OutputComponent, OutputComponents, OutputWrap};
|
||||||
|
use syntax_mapping::SyntaxMapping;
|
||||||
|
use util::transpose;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum PagingMode {
|
||||||
|
Always,
|
||||||
|
QuitIfOneScreen,
|
||||||
|
Never,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Config<'a> {
|
||||||
|
/// List of files to print
|
||||||
|
pub files: Vec<InputFile<'a>>,
|
||||||
|
|
||||||
|
/// The explicitly configured language, if any
|
||||||
|
pub language: Option<&'a str>,
|
||||||
|
|
||||||
|
/// The character width of the terminal
|
||||||
|
pub term_width: usize,
|
||||||
|
|
||||||
|
/// The width of tab characters.
|
||||||
|
/// Currently, a value of 0 will cause tabs to be passed through without expanding them.
|
||||||
|
pub tab_width: usize,
|
||||||
|
|
||||||
|
/// Whether or not to simply loop through all input (`cat` mode)
|
||||||
|
pub loop_through: bool,
|
||||||
|
|
||||||
|
/// Whether or not the output should be colorized
|
||||||
|
pub colored_output: bool,
|
||||||
|
|
||||||
|
/// Whether or not the output terminal supports true color
|
||||||
|
pub true_color: bool,
|
||||||
|
|
||||||
|
/// Style elements (grid, line numbers, ...)
|
||||||
|
pub output_components: OutputComponents,
|
||||||
|
|
||||||
|
/// Text wrapping mode
|
||||||
|
pub output_wrap: OutputWrap,
|
||||||
|
|
||||||
|
/// Pager or STDOUT
|
||||||
|
pub paging_mode: PagingMode,
|
||||||
|
|
||||||
|
/// The range lines that should be printed, if specified
|
||||||
|
pub line_range: Option<LineRange>,
|
||||||
|
|
||||||
|
/// The syntax highlighting theme
|
||||||
|
pub theme: String,
|
||||||
|
|
||||||
|
/// File extension/name mappings
|
||||||
|
pub syntax_mapping: SyntaxMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_truecolor_terminal() -> bool {
|
||||||
|
env::var("COLORTERM")
|
||||||
|
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct App {
|
||||||
|
pub matches: ArgMatches<'static>,
|
||||||
|
interactive_output: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
#[cfg(windows)]
|
||||||
|
let _ = ansi_term::enable_ansi_support();
|
||||||
|
|
||||||
|
let interactive_output = atty::is(Stream::Stdout);
|
||||||
|
|
||||||
|
Ok(App {
|
||||||
|
matches: Self::matches(interactive_output)?,
|
||||||
|
interactive_output,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches(interactive_output: bool) -> Result<ArgMatches<'static>> {
|
||||||
|
let args = if wild::args_os().nth(1) == Some("cache".into())
|
||||||
|
|| wild::args_os().any(|arg| arg == "--no-config")
|
||||||
|
{
|
||||||
|
// Skip the arguments in bats config file
|
||||||
|
|
||||||
|
wild::args_os().collect::<Vec<_>>()
|
||||||
|
} else {
|
||||||
|
let mut cli_args = wild::args_os();
|
||||||
|
|
||||||
|
// Read arguments from bats config file
|
||||||
|
let mut args = get_args_from_env_var()
|
||||||
|
.unwrap_or_else(|| get_args_from_config_file())
|
||||||
|
.chain_err(|| "Could not parse configuration file")?;
|
||||||
|
|
||||||
|
// Put the zero-th CLI argument (program name) first
|
||||||
|
args.insert(0, cli_args.next().unwrap());
|
||||||
|
|
||||||
|
// .. and the rest at the end
|
||||||
|
cli_args.for_each(|a| args.push(a));
|
||||||
|
|
||||||
|
args
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(clap_app::build_app(interactive_output).get_matches_from(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> Result<Config> {
|
||||||
|
let files = self.files();
|
||||||
|
let output_components = self.output_components()?;
|
||||||
|
|
||||||
|
let paging_mode = match self.matches.value_of("paging") {
|
||||||
|
Some("always") => PagingMode::Always,
|
||||||
|
Some("never") => PagingMode::Never,
|
||||||
|
Some("auto") | _ => {
|
||||||
|
if files.contains(&InputFile::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.
|
||||||
|
if self.interactive_output && !atty::is(Stream::Stdin) {
|
||||||
|
PagingMode::QuitIfOneScreen
|
||||||
|
} else {
|
||||||
|
PagingMode::Never
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.interactive_output {
|
||||||
|
PagingMode::QuitIfOneScreen
|
||||||
|
} else {
|
||||||
|
PagingMode::Never
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut syntax_mapping = SyntaxMapping::new();
|
||||||
|
|
||||||
|
if let Some(values) = self.matches.values_of("map-syntax") {
|
||||||
|
for from_to in values {
|
||||||
|
let parts: Vec<_> = from_to.split(":").collect();
|
||||||
|
|
||||||
|
if parts.len() != 2 {
|
||||||
|
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is 'from:to'.".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
syntax_mapping.insert(parts[0].into(), parts[1].into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Config {
|
||||||
|
true_color: is_truecolor_terminal(),
|
||||||
|
language: self.matches.value_of("language"),
|
||||||
|
output_wrap: if !self.interactive_output {
|
||||||
|
// We don't have the tty width when piping to another program.
|
||||||
|
// There's no point in wrapping when this is the case.
|
||||||
|
OutputWrap::None
|
||||||
|
} else {
|
||||||
|
match self.matches.value_of("wrap") {
|
||||||
|
Some("character") => OutputWrap::Character,
|
||||||
|
Some("never") => OutputWrap::None,
|
||||||
|
Some("auto") | _ => {
|
||||||
|
if output_components.plain() {
|
||||||
|
OutputWrap::None
|
||||||
|
} else {
|
||||||
|
OutputWrap::Character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colored_output: match self.matches.value_of("color") {
|
||||||
|
Some("always") => true,
|
||||||
|
Some("never") => false,
|
||||||
|
Some("auto") | _ => self.interactive_output,
|
||||||
|
},
|
||||||
|
paging_mode,
|
||||||
|
term_width: self
|
||||||
|
.matches
|
||||||
|
.value_of("terminal-width")
|
||||||
|
.and_then(|w| w.parse().ok())
|
||||||
|
.unwrap_or(Term::stdout().size().1 as usize),
|
||||||
|
loop_through: !(self.interactive_output
|
||||||
|
|| self.matches.value_of("color") == Some("always")
|
||||||
|
|| self.matches.value_of("decorations") == Some("always")),
|
||||||
|
files,
|
||||||
|
tab_width: self
|
||||||
|
.matches
|
||||||
|
.value_of("tabs")
|
||||||
|
.map(String::from)
|
||||||
|
.or_else(|| env::var("BAT_TABS").ok())
|
||||||
|
.and_then(|t| t.parse().ok())
|
||||||
|
.unwrap_or(
|
||||||
|
if output_components.plain() && paging_mode == PagingMode::Never {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
8
|
||||||
|
},
|
||||||
|
),
|
||||||
|
theme: self
|
||||||
|
.matches
|
||||||
|
.value_of("theme")
|
||||||
|
.map(String::from)
|
||||||
|
.or_else(|| env::var("BAT_THEME").ok())
|
||||||
|
.unwrap_or(String::from(BAT_THEME_DEFAULT)),
|
||||||
|
line_range: transpose(self.matches.value_of("line-range").map(LineRange::from))?,
|
||||||
|
output_components,
|
||||||
|
syntax_mapping,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn files(&self) -> Vec<InputFile> {
|
||||||
|
self.matches
|
||||||
|
.values_of("FILE")
|
||||||
|
.map(|values| {
|
||||||
|
values
|
||||||
|
.map(|filename| {
|
||||||
|
if filename == "-" {
|
||||||
|
InputFile::StdIn
|
||||||
|
} else {
|
||||||
|
InputFile::Ordinary(filename)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| vec![InputFile::StdIn])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_components(&self) -> Result<OutputComponents> {
|
||||||
|
let matches = &self.matches;
|
||||||
|
Ok(OutputComponents(
|
||||||
|
if matches.value_of("decorations") == Some("never") {
|
||||||
|
HashSet::new()
|
||||||
|
} else if matches.is_present("number") {
|
||||||
|
[OutputComponent::Numbers].iter().cloned().collect()
|
||||||
|
} else if matches.is_present("plain") {
|
||||||
|
[OutputComponent::Plain].iter().cloned().collect()
|
||||||
|
} else {
|
||||||
|
let env_style_components: Option<Vec<OutputComponent>> =
|
||||||
|
transpose(env::var("BAT_STYLE").ok().map(|style_str| {
|
||||||
|
style_str
|
||||||
|
.split(",")
|
||||||
|
.map(|x| OutputComponent::from_str(&x))
|
||||||
|
.collect::<Result<Vec<OutputComponent>>>()
|
||||||
|
}))?;
|
||||||
|
|
||||||
|
values_t!(matches.values_of("style"), OutputComponent)
|
||||||
|
.ok()
|
||||||
|
.or(env_style_components)
|
||||||
|
.unwrap_or(vec![OutputComponent::Full])
|
||||||
|
.into_iter()
|
||||||
|
.map(|style| style.components(self.interactive_output))
|
||||||
|
.fold(HashSet::new(), |mut acc, components| {
|
||||||
|
acc.extend(components.iter().cloned());
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
+227
@@ -0,0 +1,227 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use syntect::dumps::{dump_to_file, from_binary, from_reader};
|
||||||
|
use syntect::highlighting::{Theme, ThemeSet};
|
||||||
|
use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder};
|
||||||
|
|
||||||
|
use dirs::PROJECT_DIRS;
|
||||||
|
|
||||||
|
use errors::*;
|
||||||
|
use inputfile::{InputFile, InputFileReader};
|
||||||
|
use syntax_mapping::SyntaxMapping;
|
||||||
|
|
||||||
|
pub const BAT_THEME_DEFAULT: &str = "Monokai Extended";
|
||||||
|
|
||||||
|
pub struct HighlightingAssets {
|
||||||
|
pub syntax_set: SyntaxSet,
|
||||||
|
pub theme_set: ThemeSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HighlightingAssets {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::from_cache().unwrap_or_else(|_| Self::from_binary())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_files(dir: Option<&Path>, start_empty: bool) -> Result<Self> {
|
||||||
|
let source_dir = dir.unwrap_or_else(|| PROJECT_DIRS.config_dir());
|
||||||
|
|
||||||
|
let mut theme_set = if start_empty {
|
||||||
|
ThemeSet {
|
||||||
|
themes: BTreeMap::new(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Self::get_integrated_themeset()
|
||||||
|
};
|
||||||
|
|
||||||
|
let theme_dir = source_dir.join("themes");
|
||||||
|
|
||||||
|
let res = theme_set.add_from_folder(&theme_dir);
|
||||||
|
if !res.is_ok() {
|
||||||
|
println!(
|
||||||
|
"No themes were found in '{}', using the default set",
|
||||||
|
theme_dir.to_string_lossy()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut syntax_set_builder = if start_empty {
|
||||||
|
let mut builder = SyntaxSetBuilder::new();
|
||||||
|
builder.add_plain_text_syntax();
|
||||||
|
builder
|
||||||
|
} else {
|
||||||
|
Self::get_integrated_syntaxset().into_builder()
|
||||||
|
};
|
||||||
|
|
||||||
|
let syntax_dir = source_dir.join("syntaxes");
|
||||||
|
if syntax_dir.exists() {
|
||||||
|
syntax_set_builder.add_from_folder(syntax_dir, true)?;
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"No syntaxes were found in '{}', using the default set.",
|
||||||
|
syntax_dir.to_string_lossy()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HighlightingAssets {
|
||||||
|
syntax_set: syntax_set_builder.build(),
|
||||||
|
theme_set,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_cache() -> Result<Self> {
|
||||||
|
let theme_set_path = theme_set_path();
|
||||||
|
let syntax_set_file = File::open(&syntax_set_path()).chain_err(|| {
|
||||||
|
format!(
|
||||||
|
"Could not load cached syntax set '{}'",
|
||||||
|
syntax_set_path().to_string_lossy()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let syntax_set: SyntaxSet = from_reader(BufReader::new(syntax_set_file))
|
||||||
|
.chain_err(|| "Could not parse cached syntax set")?;
|
||||||
|
|
||||||
|
let theme_set_file = File::open(&theme_set_path).chain_err(|| {
|
||||||
|
format!(
|
||||||
|
"Could not load cached theme set '{}'",
|
||||||
|
theme_set_path.to_string_lossy()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let theme_set: ThemeSet = from_reader(BufReader::new(theme_set_file))
|
||||||
|
.chain_err(|| "Could not parse cached theme set")?;
|
||||||
|
|
||||||
|
Ok(HighlightingAssets {
|
||||||
|
syntax_set,
|
||||||
|
theme_set,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_integrated_syntaxset() -> SyntaxSet {
|
||||||
|
from_binary(include_bytes!("../assets/syntaxes.bin"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_integrated_themeset() -> ThemeSet {
|
||||||
|
from_binary(include_bytes!("../assets/themes.bin"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_binary() -> Self {
|
||||||
|
let syntax_set = Self::get_integrated_syntaxset();
|
||||||
|
let theme_set = Self::get_integrated_themeset();
|
||||||
|
|
||||||
|
HighlightingAssets {
|
||||||
|
syntax_set,
|
||||||
|
theme_set,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self, dir: Option<&Path>) -> Result<()> {
|
||||||
|
let target_dir = dir.unwrap_or_else(|| PROJECT_DIRS.cache_dir());
|
||||||
|
let _ = fs::create_dir(target_dir);
|
||||||
|
let theme_set_path = target_dir.join("themes.bin");
|
||||||
|
let syntax_set_path = target_dir.join("syntaxes.bin");
|
||||||
|
|
||||||
|
print!(
|
||||||
|
"Writing theme set to {} ... ",
|
||||||
|
theme_set_path.to_string_lossy()
|
||||||
|
);
|
||||||
|
dump_to_file(&self.theme_set, &theme_set_path).chain_err(|| {
|
||||||
|
format!(
|
||||||
|
"Could not save theme set to {}",
|
||||||
|
theme_set_path.to_string_lossy()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
println!("okay");
|
||||||
|
|
||||||
|
print!(
|
||||||
|
"Writing syntax set to {} ... ",
|
||||||
|
syntax_set_path.to_string_lossy()
|
||||||
|
);
|
||||||
|
dump_to_file(&self.syntax_set, &syntax_set_path).chain_err(|| {
|
||||||
|
format!(
|
||||||
|
"Could not save syntax set to {}",
|
||||||
|
syntax_set_path.to_string_lossy()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
println!("okay");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_theme(&self, theme: &str) -> &Theme {
|
||||||
|
match self.theme_set.themes.get(theme) {
|
||||||
|
Some(theme) => theme,
|
||||||
|
None => {
|
||||||
|
use ansi_term::Colour::Yellow;
|
||||||
|
eprintln!(
|
||||||
|
"{}: Unknown theme '{}', using default.",
|
||||||
|
Yellow.paint("[bat warning]"),
|
||||||
|
theme
|
||||||
|
);
|
||||||
|
&self.theme_set.themes[BAT_THEME_DEFAULT]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_syntax(
|
||||||
|
&self,
|
||||||
|
language: Option<&str>,
|
||||||
|
filename: InputFile,
|
||||||
|
reader: &mut InputFileReader,
|
||||||
|
mapping: &SyntaxMapping,
|
||||||
|
) -> &SyntaxReference {
|
||||||
|
let syntax = match (language, filename) {
|
||||||
|
(Some(language), _) => self.syntax_set.find_syntax_by_token(language),
|
||||||
|
(None, InputFile::Ordinary(filename)) => {
|
||||||
|
let path = Path::new(filename);
|
||||||
|
let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
|
||||||
|
let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");
|
||||||
|
|
||||||
|
let file_name = mapping.replace(file_name);
|
||||||
|
let extension = mapping.replace(extension);
|
||||||
|
|
||||||
|
let ext_syntax = self
|
||||||
|
.syntax_set
|
||||||
|
.find_syntax_by_extension(&file_name)
|
||||||
|
.or_else(|| self.syntax_set.find_syntax_by_extension(&extension));
|
||||||
|
let line_syntax = if ext_syntax.is_none() {
|
||||||
|
String::from_utf8(reader.first_line.clone())
|
||||||
|
.ok()
|
||||||
|
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let syntax = ext_syntax.or(line_syntax);
|
||||||
|
syntax
|
||||||
|
}
|
||||||
|
(None, InputFile::StdIn) => String::from_utf8(reader.first_line.clone())
|
||||||
|
.ok()
|
||||||
|
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)),
|
||||||
|
(_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
|
||||||
|
};
|
||||||
|
|
||||||
|
syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme_set_path() -> PathBuf {
|
||||||
|
PROJECT_DIRS.cache_dir().join("themes.bin")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn syntax_set_path() -> PathBuf {
|
||||||
|
PROJECT_DIRS.cache_dir().join("syntaxes.bin")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config_dir() -> Cow<'static, str> {
|
||||||
|
PROJECT_DIRS.config_dir().to_string_lossy()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_assets() {
|
||||||
|
print!("Clearing theme set cache ... ");
|
||||||
|
fs::remove_file(theme_set_path()).ok();
|
||||||
|
println!("okay");
|
||||||
|
|
||||||
|
print!("Clearing syntax set cache ... ");
|
||||||
|
fs::remove_file(syntax_set_path()).ok();
|
||||||
|
println!("okay");
|
||||||
|
}
|
||||||
+332
@@ -0,0 +1,332 @@
|
|||||||
|
use clap::{App as ClapApp, AppSettings, Arg, ArgGroup, SubCommand};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
|
||||||
|
let clap_color_setting = if interactive_output {
|
||||||
|
AppSettings::ColoredHelp
|
||||||
|
} else {
|
||||||
|
AppSettings::ColorNever
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the current directory contains a file name cache, if it does
|
||||||
|
// do not make the arguements for subcommand 'cache' required.
|
||||||
|
let arg_group_required = !Path::new("cache").exists();
|
||||||
|
|
||||||
|
ClapApp::new(crate_name!())
|
||||||
|
.version(crate_version!())
|
||||||
|
.global_setting(clap_color_setting)
|
||||||
|
.global_setting(AppSettings::DeriveDisplayOrder)
|
||||||
|
.global_setting(AppSettings::UnifiedHelpMessage)
|
||||||
|
.global_setting(AppSettings::HidePossibleValuesInHelp)
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.setting(AppSettings::ArgsNegateSubcommands)
|
||||||
|
.setting(AppSettings::DisableHelpSubcommand)
|
||||||
|
.setting(AppSettings::VersionlessSubcommands)
|
||||||
|
.max_term_width(100)
|
||||||
|
.about(
|
||||||
|
"A cat(1) clone with wings.\n\n\
|
||||||
|
Use '--help' instead of '-h' to see a more detailed version of the help text.",
|
||||||
|
)
|
||||||
|
.long_about("A cat(1) clone with syntax highlighting and Git integration.")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("FILE")
|
||||||
|
.help("File(s) to print / concatenate. Use '-' for standard input.")
|
||||||
|
.long_help(
|
||||||
|
"File(s) to print / concatenate. Use a dash ('-') or no argument at all \
|
||||||
|
to read from standard input.",
|
||||||
|
)
|
||||||
|
.multiple(true)
|
||||||
|
.empty_values(false),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("language")
|
||||||
|
.short("l")
|
||||||
|
.long("language")
|
||||||
|
.overrides_with("language")
|
||||||
|
.help("Set the language for syntax highlighting.")
|
||||||
|
.long_help(
|
||||||
|
"Explicitly set the language for syntax highlighting. The language can be \
|
||||||
|
specified as a name (like 'C++' or 'LaTeX') or possible file extension \
|
||||||
|
(like 'cpp', 'hpp' or 'md'). Use '--list-languages' to show all supported \
|
||||||
|
language names and file extensions.",
|
||||||
|
)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("list-languages")
|
||||||
|
.long("list-languages")
|
||||||
|
.conflicts_with("list-themes")
|
||||||
|
.help("Display all supported languages.")
|
||||||
|
.long_help("Display a list of supported languages for syntax highlighting."),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("map-syntax")
|
||||||
|
.short("m")
|
||||||
|
.long("map-syntax")
|
||||||
|
.multiple(true)
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(1)
|
||||||
|
.value_name("from:to")
|
||||||
|
.help("Map a file extension or name to an existing syntax.")
|
||||||
|
.long_help(
|
||||||
|
"Map a file extension or file name to an existing syntax. For example, \
|
||||||
|
to highlight *.conf files with the INI syntax, use '-m conf:ini'. \
|
||||||
|
To highlight files named '.myignore' with the Git Ignore syntax, use \
|
||||||
|
'-m .myignore:gitignore'.",
|
||||||
|
)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("theme")
|
||||||
|
.long("theme")
|
||||||
|
.overrides_with("theme")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Set the color theme for syntax highlighting.")
|
||||||
|
.long_help(
|
||||||
|
"Set the theme for syntax highlighting. Use '--list-themes' to \
|
||||||
|
see all available themes. To set a default theme, export the \
|
||||||
|
BAT_THEME environment variable (e.g.: export \
|
||||||
|
BAT_THEME=\"TwoDark\").",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("list-themes")
|
||||||
|
.long("list-themes")
|
||||||
|
.help("Display all supported highlighting themes.")
|
||||||
|
.long_help("Display a list of supported themes for syntax highlighting."),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("style")
|
||||||
|
.long("style")
|
||||||
|
.value_name("style-components")
|
||||||
|
.use_delimiter(true)
|
||||||
|
.takes_value(true)
|
||||||
|
.possible_values(&[
|
||||||
|
"auto", "full", "plain", "changes", "header", "grid", "numbers",
|
||||||
|
])
|
||||||
|
.help(
|
||||||
|
"Comma-separated list of style elements to display \
|
||||||
|
(*auto*, full, plain, changes, header, grid, numbers).",
|
||||||
|
)
|
||||||
|
.long_help(
|
||||||
|
"Configure which elements (line numbers, file headers, grid \
|
||||||
|
borders, Git modifications, ..) to display in addition to the \
|
||||||
|
file contents. The argument is a comma-separated list of \
|
||||||
|
components to display (e.g. 'numbers,changes,grid') or a \
|
||||||
|
pre-defined style ('full'). To set a default theme, export the \
|
||||||
|
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"numbers\"). \
|
||||||
|
Possible values: *auto*, full, plain, changes, header, grid, numbers.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("plain")
|
||||||
|
.overrides_with("plain")
|
||||||
|
.short("p")
|
||||||
|
.long("plain")
|
||||||
|
.conflicts_with("style")
|
||||||
|
.conflicts_with("number")
|
||||||
|
.help("Show plain style (alias for '--style=plain').")
|
||||||
|
.long_help(
|
||||||
|
"Only show plain style, no decorations. This is an alias for \
|
||||||
|
'--style=plain'",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("number")
|
||||||
|
.long("number")
|
||||||
|
.overrides_with("number")
|
||||||
|
.short("n")
|
||||||
|
.conflicts_with("style")
|
||||||
|
.help("Show line numbers (alias for '--style=numbers').")
|
||||||
|
.long_help(
|
||||||
|
"Only show line numbers, no other decorations. This is an alias for \
|
||||||
|
'--style=numbers'",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("line-range")
|
||||||
|
.long("line-range")
|
||||||
|
.overrides_with("line-range")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("N:M")
|
||||||
|
.help("Only print the lines from N to M.")
|
||||||
|
.long_help(
|
||||||
|
"Only print the specified range of lines for each file. \
|
||||||
|
For example:\n \
|
||||||
|
'--line-range 30:40' prints lines 30 to 40\n \
|
||||||
|
'--line-range :40' prints lines 1 to 40\n \
|
||||||
|
'--line-range 40:' prints lines 40 to the end of the file",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("color")
|
||||||
|
.long("color")
|
||||||
|
.overrides_with("color")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("when")
|
||||||
|
.possible_values(&["auto", "never", "always"])
|
||||||
|
.hide_default_value(true)
|
||||||
|
.default_value("auto")
|
||||||
|
.help("When to use colors (*auto*, never, always).")
|
||||||
|
.long_help(
|
||||||
|
"Specify when to use colored output. The automatic mode \
|
||||||
|
only enables colors if an interactive terminal is detected. \
|
||||||
|
Possible values: *auto*, never, always.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("decorations")
|
||||||
|
.long("decorations")
|
||||||
|
.overrides_with("decorations")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("when")
|
||||||
|
.possible_values(&["auto", "never", "always"])
|
||||||
|
.default_value("auto")
|
||||||
|
.hide_default_value(true)
|
||||||
|
.help("When to show the decorations (*auto*, never, always).")
|
||||||
|
.long_help(
|
||||||
|
"Specify when to use the decorations that have been specified \
|
||||||
|
via '--style'. The automatic mode only enables decorations if \
|
||||||
|
an interactive terminal is detected. Possible values: *auto*, never, always.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("paging")
|
||||||
|
.long("paging")
|
||||||
|
.overrides_with("paging")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("when")
|
||||||
|
.possible_values(&["auto", "never", "always"])
|
||||||
|
.default_value("auto")
|
||||||
|
.hide_default_value(true)
|
||||||
|
.help("Specify when to use the pager (*auto*, never, always).")
|
||||||
|
.long_help(
|
||||||
|
"Specify when to use the pager. To control which pager \
|
||||||
|
is used, set the PAGER or BAT_PAGER environment \
|
||||||
|
variables (the latter takes precedence). The default \
|
||||||
|
pager is 'less'. To disable the pager permanently, set \
|
||||||
|
BAT_PAGER to an empty string. \
|
||||||
|
Possible values: *auto*, never, always.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("wrap")
|
||||||
|
.long("wrap")
|
||||||
|
.overrides_with("wrap")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("mode")
|
||||||
|
.possible_values(&["auto", "never", "character"])
|
||||||
|
.default_value("auto")
|
||||||
|
.hide_default_value(true)
|
||||||
|
.help("Specify the text-wrapping mode (*auto*, never, character).")
|
||||||
|
.long_help("Specify the text-wrapping mode (*auto*, never, character)."),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("tabs")
|
||||||
|
.long("tabs")
|
||||||
|
.overrides_with("tabs")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("T")
|
||||||
|
.validator(
|
||||||
|
|t| {
|
||||||
|
t.parse::<u32>()
|
||||||
|
.map_err(|_t| "must be a number")
|
||||||
|
.map(|_t| ()) // Convert to Result<(), &str>
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
}, // Convert to Result<(), String>
|
||||||
|
)
|
||||||
|
.help("Set the tab width to T spaces.")
|
||||||
|
.long_help(
|
||||||
|
"Set the tab width to T spaces. Use a width of 0 to pass tabs through \
|
||||||
|
directly",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("unbuffered")
|
||||||
|
.short("u")
|
||||||
|
.long("unbuffered")
|
||||||
|
.hidden_short_help(true)
|
||||||
|
.long_help(
|
||||||
|
"This option exists for POSIX-compliance reasons ('u' is for \
|
||||||
|
'unbuffered'). The output is always unbuffered - this option \
|
||||||
|
is simply ignored.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("terminal-width")
|
||||||
|
.long("terminal-width")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("width")
|
||||||
|
.hidden(true)
|
||||||
|
.help("Set the width of the terminal"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("no-config")
|
||||||
|
.long("no-config")
|
||||||
|
.hidden(true)
|
||||||
|
.help("Do not use the configuration file"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("config-file")
|
||||||
|
.long("config-file")
|
||||||
|
.conflicts_with("list-languages")
|
||||||
|
.conflicts_with("list-themes")
|
||||||
|
.hidden(true)
|
||||||
|
.help("Show path to the configuration file."),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("cache")
|
||||||
|
.about("Modify the syntax-definition and theme cache")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("init")
|
||||||
|
.long("init")
|
||||||
|
.short("i")
|
||||||
|
.help("Initialize the syntax/theme cache.")
|
||||||
|
.long_help(
|
||||||
|
"Initialize the syntax/theme cache by loading from the \
|
||||||
|
source directory (default: the configuration directory).",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("clear")
|
||||||
|
.long("clear")
|
||||||
|
.short("c")
|
||||||
|
.help("Remove the cached syntax definitions and themes."),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("config-dir")
|
||||||
|
.long("config-dir")
|
||||||
|
.short("d")
|
||||||
|
.help("Show bat's configuration directory."),
|
||||||
|
)
|
||||||
|
.group(
|
||||||
|
ArgGroup::with_name("cache-actions")
|
||||||
|
.args(&["init", "clear", "config-dir"])
|
||||||
|
.required(arg_group_required),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("source")
|
||||||
|
.long("source")
|
||||||
|
.requires("init")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("dir")
|
||||||
|
.help("Use a different directory to load syntaxes and themes from."),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("target")
|
||||||
|
.long("target")
|
||||||
|
.requires("init")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("dir")
|
||||||
|
.help(
|
||||||
|
"Use a different directory to store the cached syntax and theme set.",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(Arg::with_name("blank").long("blank").requires("init").help(
|
||||||
|
"Create completely new syntax and theme sets \
|
||||||
|
(instead of appending to the default sets).",
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.help_message("Print this help message.")
|
||||||
|
.version_message("Show version information.")
|
||||||
|
}
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use shell_words;
|
||||||
|
|
||||||
|
use dirs::PROJECT_DIRS;
|
||||||
|
use util::transpose;
|
||||||
|
|
||||||
|
pub fn config_file() -> PathBuf {
|
||||||
|
PROJECT_DIRS.config_dir().join("config")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
|
||||||
|
Ok(transpose(
|
||||||
|
fs::read_to_string(config_file())
|
||||||
|
.ok()
|
||||||
|
.map(|content| get_args_from_str(&content)),
|
||||||
|
)?
|
||||||
|
.unwrap_or(vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
|
||||||
|
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_args_from_str<'a>(content: &'a str) -> Result<Vec<OsString>, shell_words::ParseError> {
|
||||||
|
let args_per_line = content
|
||||||
|
.split('\n')
|
||||||
|
.map(|line| line.trim())
|
||||||
|
.filter(|line| !line.is_empty())
|
||||||
|
.filter(|line| !line.starts_with("#"))
|
||||||
|
.map(|line| shell_words::split(line))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
Ok(args_per_line
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.map(|line| line.into())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty() {
|
||||||
|
let args = get_args_from_str("").unwrap();
|
||||||
|
assert!(args.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single() {
|
||||||
|
assert_eq!(vec!["--plain"], get_args_from_str("--plain").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple() {
|
||||||
|
assert_eq!(
|
||||||
|
vec!["--plain", "--language=cpp"],
|
||||||
|
get_args_from_str("--plain --language=cpp").unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn quotes() {
|
||||||
|
assert_eq!(
|
||||||
|
vec!["--theme", "Sublime Snazzy"],
|
||||||
|
get_args_from_str("--theme \"Sublime Snazzy\"").unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line() {
|
||||||
|
let config = "
|
||||||
|
-p
|
||||||
|
--style numbers,changes
|
||||||
|
|
||||||
|
--color=always
|
||||||
|
";
|
||||||
|
assert_eq!(
|
||||||
|
vec!["-p", "--style", "numbers,changes", "--color=always"],
|
||||||
|
get_args_from_str(config).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments() {
|
||||||
|
let config = "
|
||||||
|
# plain style
|
||||||
|
-p
|
||||||
|
|
||||||
|
# show line numbers and Git modifications
|
||||||
|
--style numbers,changes
|
||||||
|
|
||||||
|
# Always show ANSI colors
|
||||||
|
--color=always
|
||||||
|
";
|
||||||
|
assert_eq!(
|
||||||
|
vec!["-p", "--style", "numbers,changes", "--color=always"],
|
||||||
|
get_args_from_str(config).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
use app::Config;
|
||||||
|
use assets::HighlightingAssets;
|
||||||
|
use errors::*;
|
||||||
|
use inputfile::{InputFile, InputFileReader};
|
||||||
|
use line_range::LineRange;
|
||||||
|
use output::OutputType;
|
||||||
|
use printer::{InteractivePrinter, Printer, SimplePrinter};
|
||||||
|
|
||||||
|
pub struct Controller<'a> {
|
||||||
|
config: &'a Config<'a>,
|
||||||
|
assets: &'a HighlightingAssets,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b> Controller<'b> {
|
||||||
|
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
|
||||||
|
Controller { config, assets }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&self) -> Result<bool> {
|
||||||
|
let mut output_type = OutputType::from_mode(self.config.paging_mode)?;
|
||||||
|
let writer = output_type.handle()?;
|
||||||
|
let mut no_errors: bool = true;
|
||||||
|
|
||||||
|
let stdin = io::stdin();
|
||||||
|
|
||||||
|
for input_file in &self.config.files {
|
||||||
|
match input_file.get_reader(&stdin) {
|
||||||
|
Err(error) => {
|
||||||
|
handle_error(&error);
|
||||||
|
no_errors = false;
|
||||||
|
}
|
||||||
|
Ok(mut reader) => {
|
||||||
|
let result = if self.config.loop_through {
|
||||||
|
let mut printer = SimplePrinter::new();
|
||||||
|
self.print_file(reader, &mut printer, writer, *input_file)
|
||||||
|
} else {
|
||||||
|
let mut printer = InteractivePrinter::new(
|
||||||
|
&self.config,
|
||||||
|
&self.assets,
|
||||||
|
*input_file,
|
||||||
|
&mut reader,
|
||||||
|
);
|
||||||
|
self.print_file(reader, &mut printer, writer, *input_file)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = result {
|
||||||
|
handle_error(&error);
|
||||||
|
no_errors = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(no_errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_file<'a, P: Printer>(
|
||||||
|
&self,
|
||||||
|
reader: InputFileReader,
|
||||||
|
printer: &mut P,
|
||||||
|
writer: &mut Write,
|
||||||
|
input_file: InputFile<'a>,
|
||||||
|
) -> Result<()> {
|
||||||
|
printer.print_header(writer, input_file)?;
|
||||||
|
self.print_file_ranges(printer, writer, reader, &self.config.line_range)?;
|
||||||
|
printer.print_footer(writer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_file_ranges<'a, P: Printer>(
|
||||||
|
&self,
|
||||||
|
printer: &mut P,
|
||||||
|
writer: &mut Write,
|
||||||
|
mut reader: InputFileReader,
|
||||||
|
line_ranges: &Option<LineRange>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut line_buffer = Vec::new();
|
||||||
|
|
||||||
|
let mut line_number: usize = 1;
|
||||||
|
|
||||||
|
while reader.read_line(&mut line_buffer)? {
|
||||||
|
match line_ranges {
|
||||||
|
&Some(ref range) => {
|
||||||
|
if line_number < range.lower {
|
||||||
|
// 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_number, &line_buffer)?;
|
||||||
|
} else if line_number > range.upper {
|
||||||
|
// no more lines in range, exit early
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
printer.print_line(false, writer, line_number, &line_buffer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&None => {
|
||||||
|
printer.print_line(false, writer, line_number, &line_buffer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line_number += 1;
|
||||||
|
line_buffer.clear();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
use ansi_term::Style;
|
||||||
|
use diff::LineChange;
|
||||||
|
use printer::{Colors, InteractivePrinter};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DecorationText {
|
||||||
|
pub width: usize,
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Decoration {
|
||||||
|
fn generate(
|
||||||
|
&self,
|
||||||
|
line_number: usize,
|
||||||
|
continuation: bool,
|
||||||
|
printer: &InteractivePrinter,
|
||||||
|
) -> DecorationText;
|
||||||
|
fn width(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LineNumberDecoration {
|
||||||
|
color: Style,
|
||||||
|
cached_wrap: DecorationText,
|
||||||
|
cached_wrap_invalid_at: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineNumberDecoration {
|
||||||
|
pub fn new(colors: &Colors) -> Self {
|
||||||
|
LineNumberDecoration {
|
||||||
|
color: colors.line_number,
|
||||||
|
cached_wrap_invalid_at: 10000,
|
||||||
|
cached_wrap: DecorationText {
|
||||||
|
text: colors.line_number.paint(" ".repeat(4)).to_string(),
|
||||||
|
width: 4,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoration for LineNumberDecoration {
|
||||||
|
fn generate(
|
||||||
|
&self,
|
||||||
|
line_number: usize,
|
||||||
|
continuation: bool,
|
||||||
|
_printer: &InteractivePrinter,
|
||||||
|
) -> DecorationText {
|
||||||
|
if continuation {
|
||||||
|
if line_number > self.cached_wrap_invalid_at {
|
||||||
|
let new_width = self.cached_wrap.width + 1;
|
||||||
|
return DecorationText {
|
||||||
|
text: self.color.paint(" ".repeat(new_width)).to_string(),
|
||||||
|
width: new_width,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cached_wrap.clone()
|
||||||
|
} else {
|
||||||
|
let plain: String = format!("{:4}", line_number);
|
||||||
|
DecorationText {
|
||||||
|
width: plain.len(),
|
||||||
|
text: self.color.paint(plain).to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LineChangesDecoration {
|
||||||
|
cached_none: DecorationText,
|
||||||
|
cached_added: DecorationText,
|
||||||
|
cached_removed_above: DecorationText,
|
||||||
|
cached_removed_below: DecorationText,
|
||||||
|
cached_modified: DecorationText,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineChangesDecoration {
|
||||||
|
#[inline]
|
||||||
|
fn generate_cached(style: Style, text: &str) -> DecorationText {
|
||||||
|
DecorationText {
|
||||||
|
text: style.paint(text).to_string(),
|
||||||
|
width: text.chars().count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(colors: &Colors) -> Self {
|
||||||
|
LineChangesDecoration {
|
||||||
|
cached_none: Self::generate_cached(Style::default(), " "),
|
||||||
|
cached_added: Self::generate_cached(colors.git_added, "+"),
|
||||||
|
cached_removed_above: Self::generate_cached(colors.git_removed, "‾"),
|
||||||
|
cached_removed_below: Self::generate_cached(colors.git_removed, "_"),
|
||||||
|
cached_modified: Self::generate_cached(colors.git_modified, "~"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoration for LineChangesDecoration {
|
||||||
|
fn generate(
|
||||||
|
&self,
|
||||||
|
line_number: usize,
|
||||||
|
continuation: bool,
|
||||||
|
printer: &InteractivePrinter,
|
||||||
|
) -> DecorationText {
|
||||||
|
if !continuation {
|
||||||
|
if let Some(ref changes) = printer.line_changes {
|
||||||
|
return match changes.get(&(line_number as u32)) {
|
||||||
|
Some(&LineChange::Added) => self.cached_added.clone(),
|
||||||
|
Some(&LineChange::RemovedAbove) => self.cached_removed_above.clone(),
|
||||||
|
Some(&LineChange::RemovedBelow) => self.cached_removed_below.clone(),
|
||||||
|
Some(&LineChange::Modified) => self.cached_modified.clone(),
|
||||||
|
_ => self.cached_none.clone(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cached_none.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> usize {
|
||||||
|
self.cached_none.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GridBorderDecoration {
|
||||||
|
cached: DecorationText,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GridBorderDecoration {
|
||||||
|
pub fn new(colors: &Colors) -> Self {
|
||||||
|
GridBorderDecoration {
|
||||||
|
cached: DecorationText {
|
||||||
|
text: colors.grid.paint("│").to_string(),
|
||||||
|
width: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoration for GridBorderDecoration {
|
||||||
|
fn generate(
|
||||||
|
&self,
|
||||||
|
_line_number: usize,
|
||||||
|
_continuation: bool,
|
||||||
|
_printer: &InteractivePrinter,
|
||||||
|
) -> DecorationText {
|
||||||
|
self.cached.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> usize {
|
||||||
|
self.cached.width
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
use git2::{DiffOptions, IntoCString, Repository};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum LineChange {
|
||||||
|
Added,
|
||||||
|
RemovedAbove,
|
||||||
|
RemovedBelow,
|
||||||
|
Modified,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type LineChanges = HashMap<u32, LineChange>;
|
||||||
|
|
||||||
|
pub fn get_git_diff(filename: &str) -> Option<LineChanges> {
|
||||||
|
let repo = Repository::discover(&filename).ok()?;
|
||||||
|
|
||||||
|
let repo_path_absolute = fs::canonicalize(repo.workdir()?).ok()?;
|
||||||
|
|
||||||
|
let filepath_absolute = fs::canonicalize(&filename).ok()?;
|
||||||
|
let filepath_relative_to_repo = filepath_absolute.strip_prefix(&repo_path_absolute).ok()?;
|
||||||
|
|
||||||
|
let mut diff_options = DiffOptions::new();
|
||||||
|
let pathspec = filepath_relative_to_repo.into_c_string().ok()?;
|
||||||
|
diff_options.pathspec(pathspec);
|
||||||
|
diff_options.context_lines(0);
|
||||||
|
|
||||||
|
let diff = repo
|
||||||
|
.diff_index_to_workdir(None, Some(&mut diff_options))
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
let mut line_changes: LineChanges = HashMap::new();
|
||||||
|
|
||||||
|
let mark_section =
|
||||||
|
|line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
|
||||||
|
for line in start..(end + 1) as u32 {
|
||||||
|
line_changes.insert(line, change);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = diff.foreach(
|
||||||
|
&mut |_, _| true,
|
||||||
|
None,
|
||||||
|
Some(&mut |delta, hunk| {
|
||||||
|
let path = delta.new_file().path().unwrap_or_else(|| Path::new(""));
|
||||||
|
|
||||||
|
if filepath_relative_to_repo != path {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let old_lines = hunk.old_lines();
|
||||||
|
let new_start = hunk.new_start();
|
||||||
|
let new_lines = hunk.new_lines();
|
||||||
|
let new_end = (new_start + new_lines) as i32 - 1;
|
||||||
|
|
||||||
|
if old_lines == 0 && new_lines > 0 {
|
||||||
|
mark_section(&mut line_changes, new_start, new_end, LineChange::Added);
|
||||||
|
} else if new_lines == 0 && old_lines > 0 {
|
||||||
|
if new_start == 0 {
|
||||||
|
mark_section(&mut line_changes, 1, 1, LineChange::RemovedAbove);
|
||||||
|
} else {
|
||||||
|
mark_section(
|
||||||
|
&mut line_changes,
|
||||||
|
new_start,
|
||||||
|
new_start as i32,
|
||||||
|
LineChange::RemovedBelow,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mark_section(&mut line_changes, new_start, new_end, LineChange::Modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
Some(line_changes)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
use directories::ProjectDirs;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref PROJECT_DIRS: ProjectDirs =
|
||||||
|
ProjectDirs::from("", "", crate_name!()).expect("Could not get home directory");
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead, BufReader};
|
||||||
|
|
||||||
|
use content_inspector::{self, ContentType};
|
||||||
|
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
|
||||||
|
|
||||||
|
pub struct InputFileReader<'a> {
|
||||||
|
inner: Box<dyn BufRead + 'a>,
|
||||||
|
pub first_line: Vec<u8>,
|
||||||
|
pub content_type: ContentType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> InputFileReader<'a> {
|
||||||
|
fn new<R: BufRead + 'a>(mut reader: R) -> InputFileReader<'a> {
|
||||||
|
let mut first_line = vec![];
|
||||||
|
reader.read_until(b'\n', &mut first_line).ok();
|
||||||
|
|
||||||
|
let content_type = content_inspector::inspect(&first_line[..]);
|
||||||
|
|
||||||
|
if content_type == ContentType::UTF_16LE {
|
||||||
|
reader.read_until(0x00, &mut first_line).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputFileReader {
|
||||||
|
inner: Box::new(reader),
|
||||||
|
first_line,
|
||||||
|
content_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
|
||||||
|
if self.first_line.is_empty() {
|
||||||
|
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
|
||||||
|
|
||||||
|
if self.content_type == ContentType::UTF_16LE {
|
||||||
|
self.inner.read_until(0x00, buf).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
} else {
|
||||||
|
buf.append(&mut self.first_line);
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum InputFile<'a> {
|
||||||
|
StdIn,
|
||||||
|
Ordinary(&'a str),
|
||||||
|
ThemePreviewFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> InputFile<'a> {
|
||||||
|
pub fn get_reader(&self, stdin: &'a io::Stdin) -> Result<InputFileReader> {
|
||||||
|
match self {
|
||||||
|
InputFile::StdIn => Ok(InputFileReader::new(stdin.lock())),
|
||||||
|
InputFile::Ordinary(filename) => {
|
||||||
|
let file = File::open(filename)?;
|
||||||
|
|
||||||
|
if file.metadata()?.is_dir() {
|
||||||
|
return Err(format!("'{}' is a directory.", filename).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(InputFileReader::new(BufReader::new(file)))
|
||||||
|
}
|
||||||
|
InputFile::ThemePreviewFile => Ok(InputFileReader::new(THEME_PREVIEW_FILE)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
let content = b"#!/bin/bash\necho hello";
|
||||||
|
let mut reader = InputFileReader::new(&content[..]);
|
||||||
|
|
||||||
|
assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]);
|
||||||
|
|
||||||
|
let mut buffer = vec![];
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(true, res.unwrap());
|
||||||
|
assert_eq!(b"#!/bin/bash\n", &buffer[..]);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(true, res.unwrap());
|
||||||
|
assert_eq!(b"echo hello", &buffer[..]);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(false, res.unwrap());
|
||||||
|
assert!(buffer.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn utf16le() {
|
||||||
|
let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00";
|
||||||
|
let mut reader = InputFileReader::new(&content[..]);
|
||||||
|
|
||||||
|
assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]);
|
||||||
|
|
||||||
|
let mut buffer = vec![];
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(true, res.unwrap());
|
||||||
|
assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &buffer[..]);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(true, res.unwrap());
|
||||||
|
assert_eq!(b"\x64\x00", &buffer[..]);
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
|
let res = reader.read_line(&mut buffer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert_eq!(false, res.unwrap());
|
||||||
|
assert!(buffer.is_empty());
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
use errors::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LineRange {
|
||||||
|
pub lower: usize,
|
||||||
|
pub upper: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineRange {
|
||||||
|
pub fn from(range_raw: &str) -> Result<LineRange> {
|
||||||
|
LineRange::parse_range(range_raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> LineRange {
|
||||||
|
LineRange {
|
||||||
|
lower: usize::min_value(),
|
||||||
|
upper: usize::max_value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_range(range_raw: &str) -> Result<LineRange> {
|
||||||
|
let mut new_range = LineRange::new();
|
||||||
|
|
||||||
|
if range_raw.bytes().nth(0).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':' {
|
||||||
|
new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
|
||||||
|
return Ok(new_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
let line_numbers: Vec<&str> = range_raw.split(':').collect();
|
||||||
|
if line_numbers.len() == 2 {
|
||||||
|
new_range.lower = line_numbers[0].parse()?;
|
||||||
|
new_range.upper = line_numbers[1].parse()?;
|
||||||
|
return Ok(new_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err("expected single ':' character".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_full() {
|
||||||
|
let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
|
||||||
|
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!(usize::min_value(), 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!(40, range.lower);
|
||||||
|
assert_eq!(usize::max_value(), range.upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_fail() {
|
||||||
|
let range = LineRange::from("40:50:80");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("40::80");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from(":40:");
|
||||||
|
assert!(range.is_err());
|
||||||
|
let range = LineRange::from("40");
|
||||||
|
assert!(range.is_err());
|
||||||
|
}
|
||||||
+193
-345
@@ -13,395 +13,243 @@ extern crate lazy_static;
|
|||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
extern crate atty;
|
extern crate atty;
|
||||||
extern crate console;
|
extern crate console;
|
||||||
|
extern crate content_inspector;
|
||||||
extern crate directories;
|
extern crate directories;
|
||||||
|
extern crate encoding;
|
||||||
extern crate git2;
|
extern crate git2;
|
||||||
|
extern crate shell_words;
|
||||||
extern crate syntect;
|
extern crate syntect;
|
||||||
|
extern crate wild;
|
||||||
|
|
||||||
|
mod app;
|
||||||
|
mod assets;
|
||||||
|
mod clap_app;
|
||||||
|
mod config;
|
||||||
|
mod controller;
|
||||||
|
mod decorations;
|
||||||
|
mod diff;
|
||||||
|
mod dirs;
|
||||||
|
mod inputfile;
|
||||||
|
mod line_range;
|
||||||
|
mod output;
|
||||||
|
mod preprocessor;
|
||||||
|
mod printer;
|
||||||
|
mod style;
|
||||||
|
mod syntax_mapping;
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
mod util;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::io;
|
||||||
use std::fs::{self, File};
|
use std::io::Write;
|
||||||
use std::io::{self, BufRead, StdoutLock, Write};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use ansi_term::Colour::{Fixed, Green, Red, White, Yellow};
|
use ansi_term::Colour::Green;
|
||||||
use ansi_term::Style;
|
use ansi_term::Style;
|
||||||
use atty::Stream;
|
|
||||||
use clap::{App, AppSettings, Arg, SubCommand};
|
|
||||||
use console::Term;
|
|
||||||
use directories::ProjectDirs;
|
|
||||||
use git2::{DiffOptions, IntoCString, Repository};
|
|
||||||
|
|
||||||
use syntect::dumps::{dump_to_file, from_binary, from_reader};
|
use app::{App, Config};
|
||||||
use syntect::easy::HighlightFile;
|
use assets::{clear_assets, config_dir, HighlightingAssets};
|
||||||
use syntect::highlighting::{Theme, ThemeSet};
|
use config::config_file;
|
||||||
use syntect::parsing::SyntaxSet;
|
use controller::Controller;
|
||||||
|
use inputfile::InputFile;
|
||||||
use terminal::as_terminal_escaped;
|
use style::{OutputComponent, OutputComponents};
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref PROJECT_DIRS: ProjectDirs = ProjectDirs::from("", "", crate_name!());
|
|
||||||
}
|
|
||||||
|
|
||||||
mod errors {
|
mod errors {
|
||||||
error_chain!{
|
error_chain! {
|
||||||
foreign_links {
|
foreign_links {
|
||||||
|
Clap(::clap::Error);
|
||||||
Io(::std::io::Error);
|
Io(::std::io::Error);
|
||||||
|
SyntectError(::syntect::LoadingError);
|
||||||
|
ParseIntError(::std::num::ParseIntError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_error(error: &Error) {
|
||||||
|
match error {
|
||||||
|
&Error(ErrorKind::Io(ref io_error), _)
|
||||||
|
if io_error.kind() == super::io::ErrorKind::BrokenPipe =>
|
||||||
|
{
|
||||||
|
super::process::exit(0);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
use ansi_term::Colour::Red;
|
||||||
|
eprintln!("{}: {}", Red.paint("[bat error]"), error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
|
||||||
struct Options {
|
fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
|
||||||
true_color: bool,
|
if matches.is_present("init") {
|
||||||
}
|
let source_dir = matches.value_of("source").map(Path::new);
|
||||||
|
let target_dir = matches.value_of("target").map(Path::new);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
let blank = matches.is_present("blank");
|
||||||
enum LineChange {
|
|
||||||
Added,
|
|
||||||
RemovedAbove,
|
|
||||||
RemovedBelow,
|
|
||||||
Modified,
|
|
||||||
}
|
|
||||||
|
|
||||||
type LineChanges = HashMap<u32, LineChange>;
|
let assets = HighlightingAssets::from_files(source_dir, blank)?;
|
||||||
|
assets.save(target_dir)?;
|
||||||
const PANEL_WIDTH: usize = 7;
|
} else if matches.is_present("clear") {
|
||||||
const GRID_COLOR: u8 = 238;
|
clear_assets();
|
||||||
|
} else if matches.is_present("config-dir") {
|
||||||
fn print_horizontal_line(
|
writeln!(io::stdout(), "{}", config_dir())?;
|
||||||
handle: &mut StdoutLock,
|
}
|
||||||
grid_char: char,
|
|
||||||
term_width: usize,
|
|
||||||
) -> Result<()> {
|
|
||||||
let hline = "─".repeat(term_width - (PANEL_WIDTH + 1));
|
|
||||||
let hline = format!("{}{}{}", "─".repeat(PANEL_WIDTH), grid_char, hline);
|
|
||||||
|
|
||||||
writeln!(handle, "{}", Fixed(GRID_COLOR).paint(hline))?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_file<P: AsRef<Path>>(
|
pub fn list_languages(config: &Config) -> Result<()> {
|
||||||
options: &Options,
|
let assets = HighlightingAssets::new();
|
||||||
theme: &Theme,
|
let mut languages = assets
|
||||||
syntax_set: &SyntaxSet,
|
.syntax_set
|
||||||
filename: P,
|
.syntaxes()
|
||||||
line_changes: &Option<LineChanges>,
|
.iter()
|
||||||
) -> Result<()> {
|
.filter(|syntax| !syntax.hidden && !syntax.file_extensions.is_empty())
|
||||||
let mut highlighter = HighlightFile::new(filename.as_ref(), syntax_set, theme)?;
|
.collect::<Vec<_>>();
|
||||||
|
languages.sort_by_key(|lang| lang.name.to_uppercase());
|
||||||
|
|
||||||
|
let longest = languages
|
||||||
|
.iter()
|
||||||
|
.map(|syntax| syntax.name.len())
|
||||||
|
.max()
|
||||||
|
.unwrap_or(32); // Fallback width if they have no language definitions.
|
||||||
|
|
||||||
|
let comma_separator = ", ";
|
||||||
|
let separator = " ";
|
||||||
|
// Line-wrapping for the possible file extension overflow.
|
||||||
|
let desired_width = config.term_width - longest - separator.len();
|
||||||
|
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut handle = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
let term = Term::stdout();
|
let style = if config.colored_output {
|
||||||
let (_, term_width) = term.size();
|
Green.normal()
|
||||||
let term_width = term_width as usize;
|
|
||||||
|
|
||||||
print_horizontal_line(&mut handle, '┬', term_width)?;
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
handle,
|
|
||||||
"{}{} File {}",
|
|
||||||
" ".repeat(PANEL_WIDTH),
|
|
||||||
Fixed(GRID_COLOR).paint("│"),
|
|
||||||
White.bold().paint(filename.as_ref().to_string_lossy())
|
|
||||||
)?;
|
|
||||||
|
|
||||||
print_horizontal_line(&mut handle, '┼', term_width)?;
|
|
||||||
|
|
||||||
for (idx, maybe_line) in highlighter.reader.lines().enumerate() {
|
|
||||||
let line_nr = idx + 1;
|
|
||||||
let line = maybe_line.unwrap_or_else(|_| "<INVALID UTF-8>".into());
|
|
||||||
let regions = highlighter.highlight_lines.highlight(&line);
|
|
||||||
|
|
||||||
let line_change = if let Some(ref changes) = *line_changes {
|
|
||||||
match changes.get(&(line_nr as u32)) {
|
|
||||||
Some(&LineChange::Added) => Green.paint("+"),
|
|
||||||
Some(&LineChange::RemovedAbove) => Red.paint("‾"),
|
|
||||||
Some(&LineChange::RemovedBelow) => Red.paint("_"),
|
|
||||||
Some(&LineChange::Modified) => Yellow.paint("~"),
|
|
||||||
_ => Style::default().paint(" "),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Style::default().paint(" ")
|
|
||||||
};
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
handle,
|
|
||||||
"{} {} {} {}",
|
|
||||||
Fixed(244).paint(format!("{:4}", line_nr)),
|
|
||||||
line_change,
|
|
||||||
Fixed(GRID_COLOR).paint("│"),
|
|
||||||
as_terminal_escaped(®ions, options.true_color)
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_horizontal_line(&mut handle, '┴', term_width)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_git_diff(filename: &str) -> Option<LineChanges> {
|
|
||||||
let repo = Repository::open_from_env().ok()?;
|
|
||||||
let workdir = repo.workdir()?;
|
|
||||||
let current_dir = env::current_dir().ok()?;
|
|
||||||
let filepath = current_dir.join(Path::new(&filename));
|
|
||||||
|
|
||||||
let mut diff_options = DiffOptions::new();
|
|
||||||
let pathspec = format!("*{}", filename).into_c_string().ok()?;
|
|
||||||
diff_options.pathspec(pathspec);
|
|
||||||
diff_options.context_lines(0);
|
|
||||||
|
|
||||||
let diff = repo.diff_index_to_workdir(None, Some(&mut diff_options))
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
let mut line_changes: LineChanges = HashMap::new();
|
|
||||||
|
|
||||||
let mark_section =
|
|
||||||
|line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
|
|
||||||
for line in start..(end + 1) as u32 {
|
|
||||||
line_changes.insert(line, change);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = diff.foreach(
|
|
||||||
&mut |_, _| true,
|
|
||||||
None,
|
|
||||||
Some(&mut |delta, hunk| {
|
|
||||||
let path = delta.new_file().path().unwrap_or_else(|| Path::new(""));
|
|
||||||
|
|
||||||
if filepath != workdir.join(path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let old_lines = hunk.old_lines();
|
|
||||||
let new_start = hunk.new_start();
|
|
||||||
let new_lines = hunk.new_lines();
|
|
||||||
let new_end = (new_start + new_lines) as i32 - 1;
|
|
||||||
|
|
||||||
if old_lines == 0 && new_lines > 0 {
|
|
||||||
mark_section(&mut line_changes, new_start, new_end, LineChange::Added);
|
|
||||||
} else if new_lines == 0 && old_lines > 0 {
|
|
||||||
if new_start == 0 {
|
|
||||||
mark_section(&mut line_changes, 1, 1, LineChange::RemovedAbove);
|
|
||||||
} else {
|
|
||||||
mark_section(
|
|
||||||
&mut line_changes,
|
|
||||||
new_start,
|
|
||||||
new_start as i32,
|
|
||||||
LineChange::RemovedBelow,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mark_section(&mut line_changes, new_start, new_end, LineChange::Modified);
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
Some(line_changes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_truecolor_terminal() -> bool {
|
|
||||||
env::var("COLORTERM")
|
|
||||||
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HighlightingAssets {
|
|
||||||
pub syntax_set: SyntaxSet,
|
|
||||||
pub theme_set: ThemeSet,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HighlightingAssets {
|
|
||||||
fn from_files() -> Result<Self> {
|
|
||||||
let config_dir = PROJECT_DIRS.config_dir();
|
|
||||||
|
|
||||||
let theme_dir = config_dir.join("themes");
|
|
||||||
|
|
||||||
let theme_set = ThemeSet::load_from_folder(&theme_dir).map_err(|_| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!(
|
|
||||||
"Could not load themes from '{}'",
|
|
||||||
theme_dir.to_string_lossy()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let mut syntax_set = SyntaxSet::new();
|
|
||||||
let syntax_dir = config_dir.join("syntax");
|
|
||||||
let _ = syntax_set.load_syntaxes(syntax_dir, false);
|
|
||||||
syntax_set.load_plain_text_syntax();
|
|
||||||
|
|
||||||
Ok(HighlightingAssets {
|
|
||||||
syntax_set,
|
|
||||||
theme_set,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save(&self) -> Result<()> {
|
|
||||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
|
||||||
let theme_set_path = cache_dir.join("theme_set");
|
|
||||||
let syntax_set_path = cache_dir.join("syntax_set");
|
|
||||||
|
|
||||||
let _ = fs::create_dir(cache_dir);
|
|
||||||
|
|
||||||
dump_to_file(&self.theme_set, &theme_set_path).map_err(|_| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!(
|
|
||||||
"Could not save theme set to {}",
|
|
||||||
theme_set_path.to_string_lossy()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
println!("Wrote theme set to {}", theme_set_path.to_string_lossy());
|
|
||||||
|
|
||||||
dump_to_file(&self.syntax_set, &syntax_set_path).map_err(|_| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!(
|
|
||||||
"Could not save syntax set to {}",
|
|
||||||
syntax_set_path.to_string_lossy()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
println!("Wrote syntax set to {}", syntax_set_path.to_string_lossy());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_cache() -> Result<Self> {
|
|
||||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
|
||||||
let theme_set_path = cache_dir.join("theme_set");
|
|
||||||
let syntax_set_path = cache_dir.join("syntax_set");
|
|
||||||
|
|
||||||
let syntax_set_file = File::open(&syntax_set_path).chain_err(|| {
|
|
||||||
format!(
|
|
||||||
"Could not load cached syntax set '{}'",
|
|
||||||
syntax_set_path.to_string_lossy()
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let mut syntax_set: SyntaxSet = from_reader(syntax_set_file).map_err(|_| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("Could not parse cached syntax set"),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
syntax_set.link_syntaxes();
|
|
||||||
|
|
||||||
let theme_set_file = File::open(&theme_set_path).chain_err(|| {
|
|
||||||
format!(
|
|
||||||
"Could not load cached theme set '{}'",
|
|
||||||
theme_set_path.to_string_lossy()
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let theme_set: ThemeSet = from_reader(theme_set_file).map_err(|_| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!("Could not parse cached theme set"),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(HighlightingAssets {
|
|
||||||
syntax_set,
|
|
||||||
theme_set,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_binary() -> Self {
|
|
||||||
let mut syntax_set: SyntaxSet = from_binary(include_bytes!("../assets/syntax_set"));
|
|
||||||
syntax_set.link_syntaxes();
|
|
||||||
let theme_set: ThemeSet = from_binary(include_bytes!("../assets/theme_set"));
|
|
||||||
|
|
||||||
HighlightingAssets {
|
|
||||||
syntax_set,
|
|
||||||
theme_set,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<()> {
|
|
||||||
let clap_color_setting = if atty::is(Stream::Stdout) {
|
|
||||||
AppSettings::ColoredHelp
|
|
||||||
} else {
|
} else {
|
||||||
AppSettings::ColorNever
|
Style::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let app_matches = App::new(crate_name!())
|
for lang in languages {
|
||||||
.version(crate_version!())
|
write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
|
||||||
.setting(clap_color_setting)
|
|
||||||
.setting(AppSettings::DeriveDisplayOrder)
|
|
||||||
.setting(AppSettings::UnifiedHelpMessage)
|
|
||||||
.setting(AppSettings::NextLineHelp)
|
|
||||||
.setting(AppSettings::DisableVersion)
|
|
||||||
.max_term_width(90)
|
|
||||||
.about(crate_description!())
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("FILE")
|
|
||||||
.help("File(s) to print")
|
|
||||||
.multiple(true)
|
|
||||||
.empty_values(false),
|
|
||||||
)
|
|
||||||
.subcommand(
|
|
||||||
SubCommand::with_name("init-cache")
|
|
||||||
.about("Load syntax definitions and themes into cache"),
|
|
||||||
)
|
|
||||||
.help_message("Print this help message.")
|
|
||||||
.version_message("Show version information.")
|
|
||||||
.get_matches();
|
|
||||||
|
|
||||||
match app_matches.subcommand() {
|
// Number of characters on this line so far, wrap before `desired_width`
|
||||||
("init-cache", Some(_)) => {
|
let mut num_chars = 0;
|
||||||
let assets = HighlightingAssets::from_files()?;
|
|
||||||
assets.save()?;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let options = Options {
|
|
||||||
true_color: is_truecolor_terminal(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let assets =
|
let mut extension = lang.file_extensions.iter().peekable();
|
||||||
HighlightingAssets::from_cache().unwrap_or(HighlightingAssets::from_binary());
|
while let Some(word) = extension.next() {
|
||||||
|
// If we can't fit this word in, then create a line break and align it in.
|
||||||
let theme = assets.theme_set.themes.get("Default").ok_or_else(|| {
|
let new_chars = word.len() + comma_separator.len();
|
||||||
io::Error::new(
|
if num_chars + new_chars >= desired_width {
|
||||||
io::ErrorKind::Other,
|
num_chars = 0;
|
||||||
format!("Could not find 'Default' theme"),
|
write!(stdout, "\n{:width$}{}", "", separator, width = longest)?;
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Some(files) = app_matches.values_of("FILE") {
|
|
||||||
for file in files {
|
|
||||||
let line_changes = get_git_diff(&file.to_string());
|
|
||||||
print_file(&options, theme, &assets.syntax_set, file, &line_changes)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_chars += new_chars;
|
||||||
|
write!(stdout, "{}", style.paint(&word[..]))?;
|
||||||
|
if extension.peek().is_some() {
|
||||||
|
write!(stdout, "{}", comma_separator)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(stdout)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_themes(cfg: &Config) -> Result<()> {
|
||||||
|
let assets = HighlightingAssets::new();
|
||||||
|
let themes = &assets.theme_set.themes;
|
||||||
|
let mut config = cfg.clone();
|
||||||
|
let mut style = HashSet::new();
|
||||||
|
style.insert(OutputComponent::Plain);
|
||||||
|
config.files = vec![InputFile::ThemePreviewFile];
|
||||||
|
config.output_components = OutputComponents(style);
|
||||||
|
|
||||||
|
let stdout = io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
if config.colored_output {
|
||||||
|
for (theme, _) in themes.iter() {
|
||||||
|
writeln!(
|
||||||
|
stdout,
|
||||||
|
"Theme: {}\n",
|
||||||
|
Style::new().bold().paint(theme.to_string())
|
||||||
|
)?;
|
||||||
|
config.theme = theme.to_string();
|
||||||
|
let _controller = Controller::new(&config, &assets).run();
|
||||||
|
writeln!(stdout)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (theme, _) in themes.iter() {
|
||||||
|
writeln!(stdout, "{}", theme)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_controller(config: &Config) -> Result<bool> {
|
||||||
|
let assets = HighlightingAssets::new();
|
||||||
|
let controller = Controller::new(&config, &assets);
|
||||||
|
controller.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Some(true)` on full success and
|
||||||
|
/// `Some(false)` if any intermediate errors occurred (were printed).
|
||||||
|
fn run() -> Result<bool> {
|
||||||
|
let app = App::new()?;
|
||||||
|
|
||||||
|
match app.matches.subcommand() {
|
||||||
|
("cache", Some(cache_matches)) => {
|
||||||
|
// If there is a file named 'cache' in the current working directory,
|
||||||
|
// arguments for subcommand 'cache' are not mandatory.
|
||||||
|
// If there are non-zero arguments, execute the subcommand cache, else, open the file cache.
|
||||||
|
if !cache_matches.args.is_empty() {
|
||||||
|
run_cache_subcommand(cache_matches)?;
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
let mut config = app.config()?;
|
||||||
|
config.files = vec![InputFile::Ordinary(&"cache")];
|
||||||
|
|
||||||
|
run_controller(&config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let config = app.config()?;
|
||||||
|
|
||||||
|
if app.matches.is_present("list-languages") {
|
||||||
|
list_languages(&config)?;
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
} else if app.matches.is_present("list-themes") {
|
||||||
|
list_themes(&config)?;
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
} else if app.matches.is_present("config-file") {
|
||||||
|
println!("{}", config_file().to_string_lossy());
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
run_controller(&config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let result = run();
|
let result = run();
|
||||||
|
|
||||||
if let Err(error) = result {
|
match result {
|
||||||
match error {
|
Err(error) => {
|
||||||
Error(ErrorKind::Io(ref io_error), _)
|
handle_error(&error);
|
||||||
if io_error.kind() == io::ErrorKind::BrokenPipe => {}
|
process::exit(1);
|
||||||
_ => {
|
}
|
||||||
eprintln!("{}: {}", Red.paint("[bat error]"), error);
|
Ok(false) => {
|
||||||
|
process::exit(1);
|
||||||
process::exit(1);
|
}
|
||||||
}
|
Ok(true) => {
|
||||||
};
|
process::exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::{Child, Command, Stdio};
|
||||||
|
|
||||||
|
use shell_words;
|
||||||
|
|
||||||
|
use app::PagingMode;
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
pub enum OutputType {
|
||||||
|
Pager(Child),
|
||||||
|
Stdout(io::Stdout),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputType {
|
||||||
|
pub fn from_mode(mode: PagingMode) -> Result<Self> {
|
||||||
|
use self::PagingMode::*;
|
||||||
|
Ok(match mode {
|
||||||
|
Always => OutputType::try_pager(false)?,
|
||||||
|
QuitIfOneScreen => OutputType::try_pager(true)?,
|
||||||
|
_ => OutputType::stdout(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to launch the pager. Fall back to stdout in case of errors.
|
||||||
|
fn try_pager(quit_if_one_screen: bool) -> Result<Self> {
|
||||||
|
let pager = env::var("BAT_PAGER")
|
||||||
|
.or_else(|_| env::var("PAGER"))
|
||||||
|
.unwrap_or(String::from("less"));
|
||||||
|
|
||||||
|
let pagerflags = shell_words::split(&pager)
|
||||||
|
.chain_err(|| "Could not parse (BAT_)PAGER environment variable.")?;
|
||||||
|
|
||||||
|
match pagerflags.split_first() {
|
||||||
|
Some((pager_name, args)) => {
|
||||||
|
let pager_path = PathBuf::from(pager_name);
|
||||||
|
let is_less = pager_path.file_stem() == Some(&OsString::from("less"));
|
||||||
|
|
||||||
|
let mut process = if is_less {
|
||||||
|
let mut p = Command::new(&pager_path);
|
||||||
|
if args.is_empty() {
|
||||||
|
p.args(vec!["--RAW-CONTROL-CHARS", "--no-init"]);
|
||||||
|
if quit_if_one_screen {
|
||||||
|
p.arg("--quit-if-one-screen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.env("LESSCHARSET", "UTF-8");
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
Command::new(&pager_path)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(process
|
||||||
|
.args(args)
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.map(OutputType::Pager)
|
||||||
|
.unwrap_or_else(|_| OutputType::stdout()))
|
||||||
|
}
|
||||||
|
None => Ok(OutputType::stdout()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stdout() -> Self {
|
||||||
|
OutputType::Stdout(io::stdout())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle(&mut self) -> Result<&mut Write> {
|
||||||
|
Ok(match *self {
|
||||||
|
OutputType::Pager(ref mut command) => command
|
||||||
|
.stdin
|
||||||
|
.as_mut()
|
||||||
|
.chain_err(|| "Could not open stdin for pager")?,
|
||||||
|
OutputType::Stdout(ref mut handle) => handle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OutputType {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let OutputType::Pager(ref mut command) = *self {
|
||||||
|
let _ = command.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
use console::AnsiCodeIterator;
|
||||||
|
|
||||||
|
/// Expand tabs like an ANSI-enabled expand(1).
|
||||||
|
pub fn expand(line: &str, width: usize, cursor: &mut usize) -> String {
|
||||||
|
let mut buffer = String::with_capacity(line.len() * 2);
|
||||||
|
|
||||||
|
for chunk in AnsiCodeIterator::new(line) {
|
||||||
|
match chunk {
|
||||||
|
(text, true) => buffer.push_str(text),
|
||||||
|
(mut text, false) => {
|
||||||
|
while let Some(index) = text.find('\t') {
|
||||||
|
// Add previous text.
|
||||||
|
if index > 0 {
|
||||||
|
*cursor += index;
|
||||||
|
buffer.push_str(&text[0..index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add tab.
|
||||||
|
let spaces = width - (*cursor % width);
|
||||||
|
*cursor += spaces;
|
||||||
|
buffer.push_str(&*" ".repeat(spaces));
|
||||||
|
|
||||||
|
// Next.
|
||||||
|
text = &text[index + 1..text.len()];
|
||||||
|
}
|
||||||
|
|
||||||
|
*cursor += text.len();
|
||||||
|
buffer.push_str(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer
|
||||||
|
}
|
||||||
+456
@@ -0,0 +1,456 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
use ansi_term::Colour::{Fixed, Green, Red, Yellow};
|
||||||
|
use ansi_term::Style;
|
||||||
|
|
||||||
|
use console::AnsiCodeIterator;
|
||||||
|
|
||||||
|
use syntect::easy::HighlightLines;
|
||||||
|
use syntect::highlighting::Theme;
|
||||||
|
use syntect::parsing::SyntaxSet;
|
||||||
|
|
||||||
|
use content_inspector::ContentType;
|
||||||
|
|
||||||
|
use encoding::all::{UTF_16BE, UTF_16LE};
|
||||||
|
use encoding::{DecoderTrap, Encoding};
|
||||||
|
|
||||||
|
use app::Config;
|
||||||
|
use assets::HighlightingAssets;
|
||||||
|
use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration};
|
||||||
|
use diff::get_git_diff;
|
||||||
|
use diff::LineChanges;
|
||||||
|
use errors::*;
|
||||||
|
use inputfile::{InputFile, InputFileReader};
|
||||||
|
use preprocessor::expand;
|
||||||
|
use style::OutputWrap;
|
||||||
|
use terminal::{as_terminal_escaped, to_ansi_color};
|
||||||
|
|
||||||
|
pub trait Printer {
|
||||||
|
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()>;
|
||||||
|
fn print_footer(&mut self, handle: &mut Write) -> Result<()>;
|
||||||
|
fn print_line(
|
||||||
|
&mut self,
|
||||||
|
out_of_range: bool,
|
||||||
|
handle: &mut Write,
|
||||||
|
line_number: usize,
|
||||||
|
line_buffer: &[u8],
|
||||||
|
) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SimplePrinter;
|
||||||
|
|
||||||
|
impl SimplePrinter {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
SimplePrinter {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Printer for SimplePrinter {
|
||||||
|
fn print_header(&mut self, _handle: &mut Write, _file: InputFile) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_footer(&mut self, _handle: &mut Write) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_line(
|
||||||
|
&mut self,
|
||||||
|
out_of_range: bool,
|
||||||
|
handle: &mut Write,
|
||||||
|
_line_number: usize,
|
||||||
|
line_buffer: &[u8],
|
||||||
|
) -> Result<()> {
|
||||||
|
if !out_of_range {
|
||||||
|
handle.write(line_buffer)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InteractivePrinter<'a> {
|
||||||
|
colors: Colors,
|
||||||
|
config: &'a Config<'a>,
|
||||||
|
decorations: Vec<Box<dyn Decoration>>,
|
||||||
|
panel_width: usize,
|
||||||
|
ansi_prefix_sgr: String,
|
||||||
|
content_type: ContentType,
|
||||||
|
pub line_changes: Option<LineChanges>,
|
||||||
|
highlighter: Option<HighlightLines<'a>>,
|
||||||
|
syntax_set: &'a SyntaxSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> InteractivePrinter<'a> {
|
||||||
|
pub fn new(
|
||||||
|
config: &'a Config,
|
||||||
|
assets: &'a HighlightingAssets,
|
||||||
|
file: InputFile,
|
||||||
|
reader: &mut InputFileReader,
|
||||||
|
) -> Self {
|
||||||
|
let theme = assets.get_theme(&config.theme);
|
||||||
|
|
||||||
|
let colors = if config.colored_output {
|
||||||
|
Colors::colored(theme, config.true_color)
|
||||||
|
} else {
|
||||||
|
Colors::plain()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create decorations.
|
||||||
|
let mut decorations: Vec<Box<dyn Decoration>> = Vec::new();
|
||||||
|
|
||||||
|
if config.output_components.numbers() {
|
||||||
|
decorations.push(Box::new(LineNumberDecoration::new(&colors)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.output_components.changes() {
|
||||||
|
decorations.push(Box::new(LineChangesDecoration::new(&colors)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut panel_width: usize =
|
||||||
|
decorations.len() + decorations.iter().fold(0, |a, x| a + x.width());
|
||||||
|
|
||||||
|
// The grid border decoration isn't added until after the panel_width calculation, since the
|
||||||
|
// print_horizontal_line, print_header, and print_footer functions all assume the panel
|
||||||
|
// width is without the grid border.
|
||||||
|
if config.output_components.grid() && !decorations.is_empty() {
|
||||||
|
decorations.push(Box::new(GridBorderDecoration::new(&colors)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the panel if the terminal is too small (i.e. can't fit 5 characters with the
|
||||||
|
// panel showing).
|
||||||
|
if config.term_width
|
||||||
|
< (decorations.len() + decorations.iter().fold(0, |a, x| a + x.width())) + 5
|
||||||
|
{
|
||||||
|
decorations.clear();
|
||||||
|
panel_width = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut line_changes = None;
|
||||||
|
|
||||||
|
let highlighter = if reader.content_type.is_binary() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
// Get the Git modifications
|
||||||
|
line_changes = if config.output_components.changes() {
|
||||||
|
match file {
|
||||||
|
InputFile::Ordinary(filename) => get_git_diff(filename),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine the type of syntax for highlighting
|
||||||
|
let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
|
||||||
|
Some(HighlightLines::new(syntax, theme))
|
||||||
|
};
|
||||||
|
|
||||||
|
InteractivePrinter {
|
||||||
|
panel_width,
|
||||||
|
colors,
|
||||||
|
config,
|
||||||
|
decorations,
|
||||||
|
content_type: reader.content_type,
|
||||||
|
ansi_prefix_sgr: String::new(),
|
||||||
|
line_changes,
|
||||||
|
highlighter,
|
||||||
|
syntax_set: &assets.syntax_set,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_horizontal_line(&mut self, handle: &mut Write, grid_char: char) -> Result<()> {
|
||||||
|
if self.panel_width == 0 {
|
||||||
|
writeln!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
self.colors.grid.paint("─".repeat(self.config.term_width))
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
||||||
|
let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
|
||||||
|
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
|
||||||
|
if self.config.tab_width > 0 {
|
||||||
|
expand(text, self.config.tab_width, cursor)
|
||||||
|
} else {
|
||||||
|
text.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Printer for InteractivePrinter<'a> {
|
||||||
|
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()> {
|
||||||
|
if !self.config.output_components.header() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.config.output_components.grid() {
|
||||||
|
self.print_horizontal_line(handle, '┬')?;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}{}",
|
||||||
|
" ".repeat(self.panel_width),
|
||||||
|
self.colors
|
||||||
|
.grid
|
||||||
|
.paint(if self.panel_width > 0 { "│ " } else { "" }),
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
write!(handle, "{}", " ".repeat(self.panel_width))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (prefix, name) = match file {
|
||||||
|
InputFile::Ordinary(filename) => ("File: ", filename),
|
||||||
|
_ => ("", "STDIN"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mode = match self.content_type {
|
||||||
|
ContentType::BINARY => " <BINARY>",
|
||||||
|
ContentType::UTF_16LE => " <UTF-16LE>",
|
||||||
|
ContentType::UTF_16BE => " <UTF-16BE>",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
handle,
|
||||||
|
"{}{}{}",
|
||||||
|
prefix,
|
||||||
|
self.colors.filename.paint(name),
|
||||||
|
mode
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if self.config.output_components.grid() {
|
||||||
|
if self.content_type.is_text() {
|
||||||
|
self.print_horizontal_line(handle, '┼')?;
|
||||||
|
} else {
|
||||||
|
self.print_horizontal_line(handle, '┴')?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_footer(&mut self, handle: &mut Write) -> Result<()> {
|
||||||
|
if self.config.output_components.grid() && self.content_type.is_text() {
|
||||||
|
self.print_horizontal_line(handle, '┴')
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_line(
|
||||||
|
&mut self,
|
||||||
|
out_of_range: bool,
|
||||||
|
handle: &mut Write,
|
||||||
|
line_number: usize,
|
||||||
|
line_buffer: &[u8],
|
||||||
|
) -> Result<()> {
|
||||||
|
let line = match self.content_type {
|
||||||
|
ContentType::BINARY => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
ContentType::UTF_16LE => UTF_16LE
|
||||||
|
.decode(&line_buffer, DecoderTrap::Strict)
|
||||||
|
.unwrap_or("Invalid UTF-16LE".into()),
|
||||||
|
ContentType::UTF_16BE => UTF_16BE
|
||||||
|
.decode(&line_buffer, DecoderTrap::Strict)
|
||||||
|
.unwrap_or("Invalid UTF-16BE".into()),
|
||||||
|
_ => String::from_utf8_lossy(&line_buffer).to_string(),
|
||||||
|
};
|
||||||
|
let regions = {
|
||||||
|
let highlighter = match self.highlighter {
|
||||||
|
Some(ref mut highlighter) => highlighter,
|
||||||
|
_ => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
highlighter.highlight(line.as_ref(), self.syntax_set)
|
||||||
|
};
|
||||||
|
|
||||||
|
if out_of_range {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cursor: usize = 0;
|
||||||
|
let mut cursor_max: usize = self.config.term_width;
|
||||||
|
let mut cursor_total: usize = 0;
|
||||||
|
let mut panel_wrap: Option<String> = None;
|
||||||
|
|
||||||
|
// Line decorations.
|
||||||
|
if self.panel_width > 0 {
|
||||||
|
let decorations = self
|
||||||
|
.decorations
|
||||||
|
.iter()
|
||||||
|
.map(|ref d| d.generate(line_number, false, self))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for deco in decorations {
|
||||||
|
write!(handle, "{} ", deco.text)?;
|
||||||
|
cursor_max -= deco.width + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line contents.
|
||||||
|
if self.config.output_wrap == OutputWrap::None {
|
||||||
|
let true_color = self.config.true_color;
|
||||||
|
let colored_output = self.config.colored_output;
|
||||||
|
|
||||||
|
for &(style, region) in regions.iter() {
|
||||||
|
let text = &*self.preprocess(region, &mut cursor_total);
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
as_terminal_escaped(style, &*text, true_color, colored_output,)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if line.bytes().next_back() != Some(b'\n') {
|
||||||
|
write!(handle, "\n")?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for &(style, region) in regions.iter() {
|
||||||
|
let mut ansi_iterator = AnsiCodeIterator::new(region);
|
||||||
|
let mut ansi_prefix: String = String::new();
|
||||||
|
for chunk in ansi_iterator {
|
||||||
|
match chunk {
|
||||||
|
// ANSI escape passthrough.
|
||||||
|
(text, true) => {
|
||||||
|
if text.chars().last().map_or(false, |c| c == 'm') {
|
||||||
|
ansi_prefix.push_str(text);
|
||||||
|
if text == "\x1B[0m" {
|
||||||
|
self.ansi_prefix_sgr = "\x1B[0m".to_owned();
|
||||||
|
} else {
|
||||||
|
self.ansi_prefix_sgr.push_str(text);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ansi_prefix.push_str(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular text.
|
||||||
|
(text, false) => {
|
||||||
|
let text = self.preprocess(
|
||||||
|
text.trim_right_matches(|c| c == '\r' || c == '\n'),
|
||||||
|
&mut cursor_total,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut chars = text.chars();
|
||||||
|
let mut remaining = text.chars().count();
|
||||||
|
|
||||||
|
while remaining > 0 {
|
||||||
|
let available = cursor_max - cursor;
|
||||||
|
|
||||||
|
// It fits.
|
||||||
|
if remaining <= available {
|
||||||
|
let text = chars.by_ref().take(remaining).collect::<String>();
|
||||||
|
cursor += remaining;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
as_terminal_escaped(
|
||||||
|
style,
|
||||||
|
&*format!(
|
||||||
|
"{}{}{}",
|
||||||
|
self.ansi_prefix_sgr, ansi_prefix, text
|
||||||
|
),
|
||||||
|
self.config.true_color,
|
||||||
|
self.config.colored_output,
|
||||||
|
)
|
||||||
|
)?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate wrap padding if not already generated.
|
||||||
|
if panel_wrap.is_none() {
|
||||||
|
panel_wrap = if self.panel_width > 0 {
|
||||||
|
Some(format!(
|
||||||
|
"{} ",
|
||||||
|
self.decorations
|
||||||
|
.iter()
|
||||||
|
.map(|ref d| d
|
||||||
|
.generate(line_number, true, self)
|
||||||
|
.text)
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ")
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Some("".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It wraps.
|
||||||
|
let text = chars.by_ref().take(available).collect::<String>();
|
||||||
|
cursor = 0;
|
||||||
|
remaining -= available;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}\n{}",
|
||||||
|
as_terminal_escaped(
|
||||||
|
style,
|
||||||
|
&*format!(
|
||||||
|
"{}{}{}",
|
||||||
|
self.ansi_prefix_sgr, ansi_prefix, text
|
||||||
|
),
|
||||||
|
self.config.true_color,
|
||||||
|
self.config.colored_output,
|
||||||
|
),
|
||||||
|
panel_wrap.clone().unwrap()
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the ANSI prefix buffer.
|
||||||
|
ansi_prefix.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(handle, "\n")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_GUTTER_COLOR: u8 = 238;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Colors {
|
||||||
|
pub grid: Style,
|
||||||
|
pub filename: Style,
|
||||||
|
pub git_added: Style,
|
||||||
|
pub git_removed: Style,
|
||||||
|
pub git_modified: Style,
|
||||||
|
pub line_number: Style,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colors {
|
||||||
|
fn plain() -> Self {
|
||||||
|
Colors::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn colored(theme: &Theme, true_color: bool) -> Self {
|
||||||
|
let gutter_color = theme
|
||||||
|
.settings
|
||||||
|
.gutter_foreground
|
||||||
|
.map(|c| to_ansi_color(c, true_color))
|
||||||
|
.unwrap_or(Fixed(DEFAULT_GUTTER_COLOR));
|
||||||
|
|
||||||
|
Colors {
|
||||||
|
grid: gutter_color.normal(),
|
||||||
|
filename: Style::new().bold(),
|
||||||
|
git_added: Green.normal(),
|
||||||
|
git_removed: Red.normal(),
|
||||||
|
git_modified: Yellow.normal(),
|
||||||
|
line_number: gutter_color.normal(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
|
||||||
|
pub enum OutputComponent {
|
||||||
|
Auto,
|
||||||
|
Changes,
|
||||||
|
Grid,
|
||||||
|
Header,
|
||||||
|
Numbers,
|
||||||
|
Full,
|
||||||
|
Plain,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
|
||||||
|
pub enum OutputWrap {
|
||||||
|
Character,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputComponent {
|
||||||
|
pub fn components(&self, interactive_terminal: bool) -> &'static [OutputComponent] {
|
||||||
|
match *self {
|
||||||
|
OutputComponent::Auto => {
|
||||||
|
if interactive_terminal {
|
||||||
|
OutputComponent::Full.components(interactive_terminal)
|
||||||
|
} else {
|
||||||
|
OutputComponent::Plain.components(interactive_terminal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OutputComponent::Changes => &[OutputComponent::Changes],
|
||||||
|
OutputComponent::Grid => &[OutputComponent::Grid],
|
||||||
|
OutputComponent::Header => &[OutputComponent::Header],
|
||||||
|
OutputComponent::Numbers => &[OutputComponent::Numbers],
|
||||||
|
OutputComponent::Full => &[
|
||||||
|
OutputComponent::Changes,
|
||||||
|
OutputComponent::Grid,
|
||||||
|
OutputComponent::Header,
|
||||||
|
OutputComponent::Numbers,
|
||||||
|
],
|
||||||
|
OutputComponent::Plain => &[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for OutputComponent {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
match s {
|
||||||
|
"auto" => Ok(OutputComponent::Auto),
|
||||||
|
"changes" => Ok(OutputComponent::Changes),
|
||||||
|
"grid" => Ok(OutputComponent::Grid),
|
||||||
|
"header" => Ok(OutputComponent::Header),
|
||||||
|
"numbers" => Ok(OutputComponent::Numbers),
|
||||||
|
"full" => Ok(OutputComponent::Full),
|
||||||
|
"plain" => Ok(OutputComponent::Plain),
|
||||||
|
_ => Err(format!("Unknown style '{}'", s).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct OutputComponents(pub HashSet<OutputComponent>);
|
||||||
|
|
||||||
|
impl OutputComponents {
|
||||||
|
pub fn changes(&self) -> bool {
|
||||||
|
self.0.contains(&OutputComponent::Changes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grid(&self) -> bool {
|
||||||
|
self.0.contains(&OutputComponent::Grid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> bool {
|
||||||
|
self.0.contains(&OutputComponent::Header)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn numbers(&self) -> bool {
|
||||||
|
self.0.contains(&OutputComponent::Numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn plain(&self) -> bool {
|
||||||
|
self.0.iter().all(|c| c == &OutputComponent::Plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SyntaxMapping(HashMap<String, String>);
|
||||||
|
|
||||||
|
impl SyntaxMapping {
|
||||||
|
pub fn new() -> SyntaxMapping {
|
||||||
|
SyntaxMapping(HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, from: String, to: String) -> Option<String> {
|
||||||
|
self.0.insert(from, to)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace<'a>(&self, input: &'a str) -> Cow<'a, str> {
|
||||||
|
let mut out = Cow::from(input);
|
||||||
|
if let Some(value) = self.0.get(input) {
|
||||||
|
out = Cow::from(value.clone())
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
let mut map = SyntaxMapping::new();
|
||||||
|
map.insert("Cargo.lock".into(), "toml".into());
|
||||||
|
map.insert(".ignore".into(), ".gitignore".into());
|
||||||
|
|
||||||
|
assert_eq!("toml", map.replace("Cargo.lock"));
|
||||||
|
assert_eq!("other.lock", map.replace("other.lock"));
|
||||||
|
|
||||||
|
assert_eq!(".gitignore", map.replace(".ignore"));
|
||||||
|
}
|
||||||
+28
-55
@@ -1,66 +1,39 @@
|
|||||||
use std::fmt::Write;
|
extern crate ansi_colours;
|
||||||
|
|
||||||
use ansi_term::Colour::{Fixed, RGB};
|
use ansi_term::Colour::{Fixed, RGB};
|
||||||
use syntect::highlighting;
|
use ansi_term::{self, Style};
|
||||||
|
|
||||||
/// Approximate a 24 bit color value by a 8 bit ANSI code
|
use syntect::highlighting::{self, FontStyle};
|
||||||
fn rgb2ansi(r: u8, g: u8, b: u8) -> u8 {
|
|
||||||
const BLACK: u8 = 16;
|
|
||||||
const WHITE: u8 = 231;
|
|
||||||
|
|
||||||
if r == g && g == b {
|
pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> ansi_term::Colour {
|
||||||
if r < 8 {
|
if true_color {
|
||||||
BLACK
|
RGB(color.r, color.g, color.b)
|
||||||
} else if r > 248 {
|
|
||||||
WHITE
|
|
||||||
} else {
|
|
||||||
let fr = f32::from(r);
|
|
||||||
(((fr - 8.) / 247.) * 24.) as u8 + 232
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let fr = f32::from(r);
|
Fixed(ansi_colours::ansi256_from_rgb((color.r, color.g, color.b)))
|
||||||
let fg = f32::from(g);
|
|
||||||
let fb = f32::from(b);
|
|
||||||
16 + (36 * (fr / 255. * 5.) as u8) + (6 * (fg / 255. * 5.) as u8) + (fb / 255. * 5.) as u8
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_terminal_escaped(v: &[(highlighting::Style, &str)], true_color: bool) -> String {
|
pub fn as_terminal_escaped(
|
||||||
let mut s: String = String::new();
|
style: highlighting::Style,
|
||||||
for &(ref style, text) in v.iter() {
|
text: &str,
|
||||||
let style = if true_color {
|
true_color: bool,
|
||||||
RGB(style.foreground.r, style.foreground.g, style.foreground.b)
|
colored: bool,
|
||||||
|
) -> String {
|
||||||
|
let style = if !colored {
|
||||||
|
Style::default()
|
||||||
|
} else {
|
||||||
|
let color = to_ansi_color(style.foreground, true_color);
|
||||||
|
|
||||||
|
if style.font_style.contains(FontStyle::BOLD) {
|
||||||
|
color.bold()
|
||||||
|
} else if style.font_style.contains(FontStyle::UNDERLINE) {
|
||||||
|
color.underline()
|
||||||
|
} else if style.font_style.contains(FontStyle::ITALIC) {
|
||||||
|
color.italic()
|
||||||
} else {
|
} else {
|
||||||
let ansi = rgb2ansi(style.foreground.r, style.foreground.g, style.foreground.b);
|
color.normal()
|
||||||
Fixed(ansi)
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(s, "{}", style.paint(text)).unwrap();
|
style.paint(text).to_string()
|
||||||
}
|
|
||||||
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rgb2ansi_black_white() {
|
|
||||||
assert_eq!(16, rgb2ansi(0x00, 0x00, 0x00));
|
|
||||||
assert_eq!(231, rgb2ansi(0xff, 0xff, 0xff));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rgb2ansi_gray() {
|
|
||||||
assert_eq!(241, rgb2ansi(0x6c, 0x6c, 0x6c));
|
|
||||||
assert_eq!(233, rgb2ansi(0x1c, 0x1c, 0x1c));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rgb2ansi_color() {
|
|
||||||
assert_eq!(96, rgb2ansi(0x87, 0x5f, 0x87));
|
|
||||||
assert_eq!(141, rgb2ansi(0xaf, 0x87, 0xff));
|
|
||||||
assert_eq!(193, rgb2ansi(0xd7, 0xff, 0xaf));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rgb2ansi_approx() {
|
|
||||||
assert_eq!(231, rgb2ansi(0xfe, 0xfe, 0xfe));
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/// Helper function that might appear in Rust stable at some point
|
||||||
|
/// (https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose)
|
||||||
|
pub fn transpose<T, E>(opt: Option<Result<T, E>>) -> Result<Option<T>, E> {
|
||||||
|
opt.map_or(Ok(None), |res| res.map(Some))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::transpose;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct TestError;
|
||||||
|
|
||||||
|
type TestResult<T> = Result<T, TestError>;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
let a: Option<TestResult<i32>> = Some(Ok(2));
|
||||||
|
assert_eq!(Ok(Some(2)), transpose(a));
|
||||||
|
|
||||||
|
let b: Option<TestResult<i32>> = Some(Err(TestError));
|
||||||
|
assert_eq!(Err(TestError), transpose(b));
|
||||||
|
|
||||||
|
let c: Option<TestResult<i32>> = None;
|
||||||
|
assert_eq!(Ok(None), transpose(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
test-src/* linguist-vendored
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
test-src/*
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if ! which hyperfine > /dev/null 2>&1; then
|
||||||
|
echo "'hyperfine' does not seem to be installed."
|
||||||
|
echo "You can get it here: https://github.com/sharkdp/hyperfine"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRC="test-src/jquery-3.3.1.js"
|
||||||
|
|
||||||
|
|
||||||
|
cmd_bat="bat --style=full --color=always --paging=never '$SRC'"
|
||||||
|
cmd_bat_simple="bat --plain --wrap=never --tabs=0 --color=always --paging=never '$SRC'"
|
||||||
|
cmd_pygmentize="pygmentize -g '$SRC'"
|
||||||
|
cmd_highlight="highlight -O truecolor '$SRC'"
|
||||||
|
cmd_ccat="ccat --color=always '$SRC'"
|
||||||
|
cmd_source_highlight="source-highlight --failsafe --infer-lang -f esc -i '$SRC'"
|
||||||
|
cmd_hicat="hicat '$SRC'"
|
||||||
|
cmd_coderay="coderay '$SRC'"
|
||||||
|
cmd_rouge="rougify '$SRC'"
|
||||||
|
|
||||||
|
hyperfine --warmup 3 \
|
||||||
|
"$cmd_bat" \
|
||||||
|
"$cmd_bat_simple" \
|
||||||
|
"$cmd_pygmentize" \
|
||||||
|
"$cmd_highlight" \
|
||||||
|
"$cmd_ccat" \
|
||||||
|
"$cmd_source_highlight" \
|
||||||
|
"$cmd_hicat" \
|
||||||
|
"$cmd_coderay" \
|
||||||
|
"$cmd_rouge" \
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if ! which hyperfine > /dev/null 2>&1; then
|
||||||
|
echo "'hyperfine' does not seem to be installed."
|
||||||
|
echo "You can get it here: https://github.com/sharkdp/hyperfine"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "### Startup time"
|
||||||
|
echo
|
||||||
|
|
||||||
|
hyperfine --warmup 3 bat
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "### Plain text"
|
||||||
|
echo
|
||||||
|
|
||||||
|
hyperfine --warmup 3 "bat --language txt --paging=never 'test-src/jquery-3.3.1.js'"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "### Time to syntax-highlight large files"
|
||||||
|
echo
|
||||||
|
|
||||||
|
for SRC in test-src/*; do
|
||||||
|
hyperfine --warmup 3 "bat --style=full --color=always --paging=never '$SRC'"
|
||||||
|
done
|
||||||
+10364
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Vendored
+602
@@ -0,0 +1,602 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2013-2014 RAD Game Tools and Valve Software
|
||||||
|
* Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "miniz.h"
|
||||||
|
|
||||||
|
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
|
||||||
|
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
|
||||||
|
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------- zlib-style API's */
|
||||||
|
|
||||||
|
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
|
||||||
|
{
|
||||||
|
mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
|
||||||
|
size_t block_len = buf_len % 5552;
|
||||||
|
if (!ptr)
|
||||||
|
return MZ_ADLER32_INIT;
|
||||||
|
while (buf_len)
|
||||||
|
{
|
||||||
|
for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
|
||||||
|
{
|
||||||
|
s1 += ptr[0], s2 += s1;
|
||||||
|
s1 += ptr[1], s2 += s1;
|
||||||
|
s1 += ptr[2], s2 += s1;
|
||||||
|
s1 += ptr[3], s2 += s1;
|
||||||
|
s1 += ptr[4], s2 += s1;
|
||||||
|
s1 += ptr[5], s2 += s1;
|
||||||
|
s1 += ptr[6], s2 += s1;
|
||||||
|
s1 += ptr[7], s2 += s1;
|
||||||
|
}
|
||||||
|
for (; i < block_len; ++i)
|
||||||
|
s1 += *ptr++, s2 += s1;
|
||||||
|
s1 %= 65521U, s2 %= 65521U;
|
||||||
|
buf_len -= block_len;
|
||||||
|
block_len = 5552;
|
||||||
|
}
|
||||||
|
return (s2 << 16) + s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
|
||||||
|
#if 0
|
||||||
|
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
|
||||||
|
{
|
||||||
|
static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||||
|
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
|
||||||
|
mz_uint32 crcu32 = (mz_uint32)crc;
|
||||||
|
if (!ptr)
|
||||||
|
return MZ_CRC32_INIT;
|
||||||
|
crcu32 = ~crcu32;
|
||||||
|
while (buf_len--)
|
||||||
|
{
|
||||||
|
mz_uint8 b = *ptr++;
|
||||||
|
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
|
||||||
|
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
|
||||||
|
}
|
||||||
|
return ~crcu32;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Faster, but larger CPU cache footprint.
|
||||||
|
*/
|
||||||
|
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
|
||||||
|
{
|
||||||
|
static const mz_uint32 s_crc_table[256] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
|
||||||
|
0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
|
||||||
|
0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
|
||||||
|
0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||||
|
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
|
||||||
|
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
|
||||||
|
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
|
||||||
|
0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
|
||||||
|
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
|
||||||
|
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
|
||||||
|
0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
|
||||||
|
0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
|
||||||
|
0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
|
||||||
|
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
|
||||||
|
0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
|
||||||
|
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
|
||||||
|
0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||||
|
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
|
||||||
|
0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
|
||||||
|
0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
|
||||||
|
0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
|
||||||
|
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
|
||||||
|
0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
|
||||||
|
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||||
|
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
|
||||||
|
0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
|
||||||
|
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
|
||||||
|
0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
|
||||||
|
0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
|
||||||
|
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
|
||||||
|
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
};
|
||||||
|
|
||||||
|
mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
|
||||||
|
const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
|
||||||
|
|
||||||
|
while (buf_len >= 4)
|
||||||
|
{
|
||||||
|
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
|
||||||
|
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
|
||||||
|
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
|
||||||
|
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
|
||||||
|
pByte_buf += 4;
|
||||||
|
buf_len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (buf_len)
|
||||||
|
{
|
||||||
|
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
|
||||||
|
++pByte_buf;
|
||||||
|
--buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~crc32;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void mz_free(void *p)
|
||||||
|
{
|
||||||
|
MZ_FREE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
|
||||||
|
{
|
||||||
|
(void)opaque, (void)items, (void)size;
|
||||||
|
return MZ_MALLOC(items * size);
|
||||||
|
}
|
||||||
|
void miniz_def_free_func(void *opaque, void *address)
|
||||||
|
{
|
||||||
|
(void)opaque, (void)address;
|
||||||
|
MZ_FREE(address);
|
||||||
|
}
|
||||||
|
void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
|
||||||
|
{
|
||||||
|
(void)opaque, (void)address, (void)items, (void)size;
|
||||||
|
return MZ_REALLOC(address, items * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mz_version(void)
|
||||||
|
{
|
||||||
|
return MZ_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MINIZ_NO_ZLIB_APIS
|
||||||
|
|
||||||
|
int mz_deflateInit(mz_streamp pStream, int level)
|
||||||
|
{
|
||||||
|
return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
|
||||||
|
{
|
||||||
|
tdefl_compressor *pComp;
|
||||||
|
mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
|
||||||
|
|
||||||
|
if (!pStream)
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
|
||||||
|
return MZ_PARAM_ERROR;
|
||||||
|
|
||||||
|
pStream->data_type = 0;
|
||||||
|
pStream->adler = MZ_ADLER32_INIT;
|
||||||
|
pStream->msg = NULL;
|
||||||
|
pStream->reserved = 0;
|
||||||
|
pStream->total_in = 0;
|
||||||
|
pStream->total_out = 0;
|
||||||
|
if (!pStream->zalloc)
|
||||||
|
pStream->zalloc = miniz_def_alloc_func;
|
||||||
|
if (!pStream->zfree)
|
||||||
|
pStream->zfree = miniz_def_free_func;
|
||||||
|
|
||||||
|
pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
|
||||||
|
if (!pComp)
|
||||||
|
return MZ_MEM_ERROR;
|
||||||
|
|
||||||
|
pStream->state = (struct mz_internal_state *)pComp;
|
||||||
|
|
||||||
|
if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
|
||||||
|
{
|
||||||
|
mz_deflateEnd(pStream);
|
||||||
|
return MZ_PARAM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_deflateReset(mz_streamp pStream)
|
||||||
|
{
|
||||||
|
if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
pStream->total_in = pStream->total_out = 0;
|
||||||
|
tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
|
||||||
|
return MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_deflate(mz_streamp pStream, int flush)
|
||||||
|
{
|
||||||
|
size_t in_bytes, out_bytes;
|
||||||
|
mz_ulong orig_total_in, orig_total_out;
|
||||||
|
int mz_status = MZ_OK;
|
||||||
|
|
||||||
|
if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if (!pStream->avail_out)
|
||||||
|
return MZ_BUF_ERROR;
|
||||||
|
|
||||||
|
if (flush == MZ_PARTIAL_FLUSH)
|
||||||
|
flush = MZ_SYNC_FLUSH;
|
||||||
|
|
||||||
|
if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
|
||||||
|
return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
|
||||||
|
|
||||||
|
orig_total_in = pStream->total_in;
|
||||||
|
orig_total_out = pStream->total_out;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
tdefl_status defl_status;
|
||||||
|
in_bytes = pStream->avail_in;
|
||||||
|
out_bytes = pStream->avail_out;
|
||||||
|
|
||||||
|
defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
|
||||||
|
pStream->next_in += (mz_uint)in_bytes;
|
||||||
|
pStream->avail_in -= (mz_uint)in_bytes;
|
||||||
|
pStream->total_in += (mz_uint)in_bytes;
|
||||||
|
pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
|
||||||
|
|
||||||
|
pStream->next_out += (mz_uint)out_bytes;
|
||||||
|
pStream->avail_out -= (mz_uint)out_bytes;
|
||||||
|
pStream->total_out += (mz_uint)out_bytes;
|
||||||
|
|
||||||
|
if (defl_status < 0)
|
||||||
|
{
|
||||||
|
mz_status = MZ_STREAM_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (defl_status == TDEFL_STATUS_DONE)
|
||||||
|
{
|
||||||
|
mz_status = MZ_STREAM_END;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!pStream->avail_out)
|
||||||
|
break;
|
||||||
|
else if ((!pStream->avail_in) && (flush != MZ_FINISH))
|
||||||
|
{
|
||||||
|
if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
|
||||||
|
break;
|
||||||
|
return MZ_BUF_ERROR; /* Can't make forward progress without some input.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mz_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_deflateEnd(mz_streamp pStream)
|
||||||
|
{
|
||||||
|
if (!pStream)
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if (pStream->state)
|
||||||
|
{
|
||||||
|
pStream->zfree(pStream->opaque, pStream->state);
|
||||||
|
pStream->state = NULL;
|
||||||
|
}
|
||||||
|
return MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
|
||||||
|
{
|
||||||
|
(void)pStream;
|
||||||
|
/* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
|
||||||
|
return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
mz_stream stream;
|
||||||
|
memset(&stream, 0, sizeof(stream));
|
||||||
|
|
||||||
|
/* In case mz_ulong is 64-bits (argh I hate longs). */
|
||||||
|
if ((source_len | *pDest_len) > 0xFFFFFFFFU)
|
||||||
|
return MZ_PARAM_ERROR;
|
||||||
|
|
||||||
|
stream.next_in = pSource;
|
||||||
|
stream.avail_in = (mz_uint32)source_len;
|
||||||
|
stream.next_out = pDest;
|
||||||
|
stream.avail_out = (mz_uint32)*pDest_len;
|
||||||
|
|
||||||
|
status = mz_deflateInit(&stream, level);
|
||||||
|
if (status != MZ_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = mz_deflate(&stream, MZ_FINISH);
|
||||||
|
if (status != MZ_STREAM_END)
|
||||||
|
{
|
||||||
|
mz_deflateEnd(&stream);
|
||||||
|
return (status == MZ_OK) ? MZ_BUF_ERROR : status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pDest_len = stream.total_out;
|
||||||
|
return mz_deflateEnd(&stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
|
||||||
|
{
|
||||||
|
return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
mz_ulong mz_compressBound(mz_ulong source_len)
|
||||||
|
{
|
||||||
|
return mz_deflateBound(NULL, source_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tinfl_decompressor m_decomp;
|
||||||
|
mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
|
||||||
|
int m_window_bits;
|
||||||
|
mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
|
||||||
|
tinfl_status m_last_status;
|
||||||
|
} inflate_state;
|
||||||
|
|
||||||
|
int mz_inflateInit2(mz_streamp pStream, int window_bits)
|
||||||
|
{
|
||||||
|
inflate_state *pDecomp;
|
||||||
|
if (!pStream)
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
|
||||||
|
return MZ_PARAM_ERROR;
|
||||||
|
|
||||||
|
pStream->data_type = 0;
|
||||||
|
pStream->adler = 0;
|
||||||
|
pStream->msg = NULL;
|
||||||
|
pStream->total_in = 0;
|
||||||
|
pStream->total_out = 0;
|
||||||
|
pStream->reserved = 0;
|
||||||
|
if (!pStream->zalloc)
|
||||||
|
pStream->zalloc = miniz_def_alloc_func;
|
||||||
|
if (!pStream->zfree)
|
||||||
|
pStream->zfree = miniz_def_free_func;
|
||||||
|
|
||||||
|
pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
|
||||||
|
if (!pDecomp)
|
||||||
|
return MZ_MEM_ERROR;
|
||||||
|
|
||||||
|
pStream->state = (struct mz_internal_state *)pDecomp;
|
||||||
|
|
||||||
|
tinfl_init(&pDecomp->m_decomp);
|
||||||
|
pDecomp->m_dict_ofs = 0;
|
||||||
|
pDecomp->m_dict_avail = 0;
|
||||||
|
pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
pDecomp->m_first_call = 1;
|
||||||
|
pDecomp->m_has_flushed = 0;
|
||||||
|
pDecomp->m_window_bits = window_bits;
|
||||||
|
|
||||||
|
return MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_inflateInit(mz_streamp pStream)
|
||||||
|
{
|
||||||
|
return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_inflate(mz_streamp pStream, int flush)
|
||||||
|
{
|
||||||
|
inflate_state *pState;
|
||||||
|
mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
|
||||||
|
size_t in_bytes, out_bytes, orig_avail_in;
|
||||||
|
tinfl_status status;
|
||||||
|
|
||||||
|
if ((!pStream) || (!pStream->state))
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if (flush == MZ_PARTIAL_FLUSH)
|
||||||
|
flush = MZ_SYNC_FLUSH;
|
||||||
|
if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
|
||||||
|
pState = (inflate_state *)pStream->state;
|
||||||
|
if (pState->m_window_bits > 0)
|
||||||
|
decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
|
||||||
|
orig_avail_in = pStream->avail_in;
|
||||||
|
|
||||||
|
first_call = pState->m_first_call;
|
||||||
|
pState->m_first_call = 0;
|
||||||
|
if (pState->m_last_status < 0)
|
||||||
|
return MZ_DATA_ERROR;
|
||||||
|
|
||||||
|
if (pState->m_has_flushed && (flush != MZ_FINISH))
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
pState->m_has_flushed |= (flush == MZ_FINISH);
|
||||||
|
|
||||||
|
if ((flush == MZ_FINISH) && (first_call))
|
||||||
|
{
|
||||||
|
/* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
|
||||||
|
decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
|
||||||
|
in_bytes = pStream->avail_in;
|
||||||
|
out_bytes = pStream->avail_out;
|
||||||
|
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
|
||||||
|
pState->m_last_status = status;
|
||||||
|
pStream->next_in += (mz_uint)in_bytes;
|
||||||
|
pStream->avail_in -= (mz_uint)in_bytes;
|
||||||
|
pStream->total_in += (mz_uint)in_bytes;
|
||||||
|
pStream->adler = tinfl_get_adler32(&pState->m_decomp);
|
||||||
|
pStream->next_out += (mz_uint)out_bytes;
|
||||||
|
pStream->avail_out -= (mz_uint)out_bytes;
|
||||||
|
pStream->total_out += (mz_uint)out_bytes;
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return MZ_DATA_ERROR;
|
||||||
|
else if (status != TINFL_STATUS_DONE)
|
||||||
|
{
|
||||||
|
pState->m_last_status = TINFL_STATUS_FAILED;
|
||||||
|
return MZ_BUF_ERROR;
|
||||||
|
}
|
||||||
|
return MZ_STREAM_END;
|
||||||
|
}
|
||||||
|
/* flush != MZ_FINISH then we must assume there's more input. */
|
||||||
|
if (flush != MZ_FINISH)
|
||||||
|
decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
|
||||||
|
|
||||||
|
if (pState->m_dict_avail)
|
||||||
|
{
|
||||||
|
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
|
||||||
|
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
|
||||||
|
pStream->next_out += n;
|
||||||
|
pStream->avail_out -= n;
|
||||||
|
pStream->total_out += n;
|
||||||
|
pState->m_dict_avail -= n;
|
||||||
|
pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
|
||||||
|
return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
in_bytes = pStream->avail_in;
|
||||||
|
out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
|
||||||
|
|
||||||
|
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
|
||||||
|
pState->m_last_status = status;
|
||||||
|
|
||||||
|
pStream->next_in += (mz_uint)in_bytes;
|
||||||
|
pStream->avail_in -= (mz_uint)in_bytes;
|
||||||
|
pStream->total_in += (mz_uint)in_bytes;
|
||||||
|
pStream->adler = tinfl_get_adler32(&pState->m_decomp);
|
||||||
|
|
||||||
|
pState->m_dict_avail = (mz_uint)out_bytes;
|
||||||
|
|
||||||
|
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
|
||||||
|
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
|
||||||
|
pStream->next_out += n;
|
||||||
|
pStream->avail_out -= n;
|
||||||
|
pStream->total_out += n;
|
||||||
|
pState->m_dict_avail -= n;
|
||||||
|
pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
|
||||||
|
else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
|
||||||
|
return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
|
||||||
|
else if (flush == MZ_FINISH)
|
||||||
|
{
|
||||||
|
/* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
|
||||||
|
if (status == TINFL_STATUS_DONE)
|
||||||
|
return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
|
||||||
|
/* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
|
||||||
|
else if (!pStream->avail_out)
|
||||||
|
return MZ_BUF_ERROR;
|
||||||
|
}
|
||||||
|
else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_inflateEnd(mz_streamp pStream)
|
||||||
|
{
|
||||||
|
if (!pStream)
|
||||||
|
return MZ_STREAM_ERROR;
|
||||||
|
if (pStream->state)
|
||||||
|
{
|
||||||
|
pStream->zfree(pStream->opaque, pStream->state);
|
||||||
|
pStream->state = NULL;
|
||||||
|
}
|
||||||
|
return MZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
|
||||||
|
{
|
||||||
|
mz_stream stream;
|
||||||
|
int status;
|
||||||
|
memset(&stream, 0, sizeof(stream));
|
||||||
|
|
||||||
|
/* In case mz_ulong is 64-bits (argh I hate longs). */
|
||||||
|
if ((source_len | *pDest_len) > 0xFFFFFFFFU)
|
||||||
|
return MZ_PARAM_ERROR;
|
||||||
|
|
||||||
|
stream.next_in = pSource;
|
||||||
|
stream.avail_in = (mz_uint32)source_len;
|
||||||
|
stream.next_out = pDest;
|
||||||
|
stream.avail_out = (mz_uint32)*pDest_len;
|
||||||
|
|
||||||
|
status = mz_inflateInit(&stream);
|
||||||
|
if (status != MZ_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = mz_inflate(&stream, MZ_FINISH);
|
||||||
|
if (status != MZ_STREAM_END)
|
||||||
|
{
|
||||||
|
mz_inflateEnd(&stream);
|
||||||
|
return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
|
||||||
|
}
|
||||||
|
*pDest_len = stream.total_out;
|
||||||
|
|
||||||
|
return mz_inflateEnd(&stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mz_error(int err)
|
||||||
|
{
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
int m_err;
|
||||||
|
const char *m_pDesc;
|
||||||
|
} s_error_descs[] =
|
||||||
|
{
|
||||||
|
{ MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
|
||||||
|
};
|
||||||
|
mz_uint i;
|
||||||
|
for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
|
||||||
|
if (s_error_descs[i].m_err == err)
|
||||||
|
return s_error_descs[i].m_pDesc;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*MINIZ_NO_ZLIB_APIS */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
hello world
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
extern crate assert_cmd;
|
||||||
|
|
||||||
|
use assert_cmd::prelude::*;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn bat() -> Command {
|
||||||
|
let mut cmd = Command::main_binary().unwrap();
|
||||||
|
cmd.current_dir("tests/examples");
|
||||||
|
cmd.arg("--no-config");
|
||||||
|
cmd.env_remove("PAGER");
|
||||||
|
cmd.env_remove("BAT_PAGER");
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
bat()
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("hello world\n")
|
||||||
|
.stderr("");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stdin() {
|
||||||
|
bat()
|
||||||
|
.with_stdin()
|
||||||
|
.buffer("foo\nbar\n")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("foo\nbar\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concatenate() {
|
||||||
|
bat()
|
||||||
|
.arg("test.txt")
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("hello world\nhello world\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concatenate_stdin() {
|
||||||
|
bat()
|
||||||
|
.arg("test.txt")
|
||||||
|
.arg("-")
|
||||||
|
.arg("test.txt")
|
||||||
|
.with_stdin()
|
||||||
|
.buffer("stdin\n")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("hello world\nstdin\nhello world\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn line_numbers() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("--style=numbers")
|
||||||
|
.arg("--decorations=always")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn line_range_2_3() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("--line-range=2:3")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 2\nline 3\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn line_range_first_two() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("--line-range=:2")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 1\nline 2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn line_range_last_3() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("--line-range=2:")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 2\nline 3\nline 4\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fail_non_existing() {
|
||||||
|
bat().arg("non-existing-file").assert().failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fail_directory() {
|
||||||
|
bat().arg("sub_directory").assert().failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn do_not_exit_directory() {
|
||||||
|
bat()
|
||||||
|
.arg("sub_directory")
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.stdout("hello world\n")
|
||||||
|
.failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pager_basic() {
|
||||||
|
bat()
|
||||||
|
.env("PAGER", "echo pager-output")
|
||||||
|
.arg("--paging=always")
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("pager-output\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pager_overwrite() {
|
||||||
|
bat()
|
||||||
|
.env("PAGER", "echo other-pager")
|
||||||
|
.env("BAT_PAGER", "echo pager-output")
|
||||||
|
.arg("--paging=always")
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("pager-output\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pager_disable() {
|
||||||
|
bat()
|
||||||
|
.env("PAGER", "echo other-pager")
|
||||||
|
.env("BAT_PAGER", "")
|
||||||
|
.arg("--paging=always")
|
||||||
|
.arg("test.txt")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("hello world\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
mod tester;
|
||||||
|
|
||||||
|
use tester::BatTester;
|
||||||
|
|
||||||
|
macro_rules! snapshot_tests {
|
||||||
|
($($test_name: ident: $style: expr => [wrap: $wrap:expr, tabs: $tabs:expr],)*) => {
|
||||||
|
$(
|
||||||
|
#[test]
|
||||||
|
fn $test_name() {
|
||||||
|
let bat_tester = BatTester::new();
|
||||||
|
bat_tester.test_snapshot(stringify!($test_name), $style, $tabs, $wrap);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot_tests! {
|
||||||
|
changes: "changes" => [wrap: false, tabs: 8],
|
||||||
|
grid: "grid" => [wrap: false, tabs: 8],
|
||||||
|
header: "header" => [wrap: false, tabs: 8],
|
||||||
|
numbers: "numbers" => [wrap: false, tabs: 8],
|
||||||
|
changes_grid: "changes,grid" => [wrap: false, tabs: 8],
|
||||||
|
changes_header: "changes,header" => [wrap: false, tabs: 8],
|
||||||
|
changes_numbers: "changes,numbers" => [wrap: false, tabs: 8],
|
||||||
|
grid_header: "grid,header" => [wrap: false, tabs: 8],
|
||||||
|
grid_numbers: "grid,numbers" => [wrap: false, tabs: 8],
|
||||||
|
header_numbers: "header,numbers" => [wrap: false, tabs: 8],
|
||||||
|
changes_grid_header: "changes,grid,header" => [wrap: false, tabs: 8],
|
||||||
|
changes_grid_numbers: "changes,grid,numbers" => [wrap: false, tabs: 8],
|
||||||
|
changes_header_numbers: "changes,header,numbers" => [wrap: false, tabs: 8],
|
||||||
|
grid_header_numbers: "grid,header,numbers" => [wrap: false, tabs: 8],
|
||||||
|
changes_grid_header_numbers: "changes,grid,header,numbers" => [wrap: false, tabs: 8],
|
||||||
|
full: "full" => [wrap: false, tabs: 8],
|
||||||
|
plain: "plain" => [wrap: false, tabs: 0],
|
||||||
|
tabs_passthrough_wrapped: "full" => [wrap: true, tabs: 0],
|
||||||
|
tabs_4_wrapped: "full" => [wrap: true, tabs: 4],
|
||||||
|
tabs_8_wrapped: "full" => [wrap: true, tabs: 8],
|
||||||
|
tabs_passthrough: "full" => [wrap: false, tabs: 0],
|
||||||
|
tabs_4: "full" => [wrap: false, tabs: 4],
|
||||||
|
tabs_8: "full" => [wrap: false, tabs: 8],
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user