mirror of
https://github.com/sharkdp/bat.git
synced 2026-11-10 21:06:07 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6eee1a8927 |
No files matched your search
@@ -166,8 +166,7 @@ jobs:
|
||||
- { target: arm-unknown-linux-gnueabihf , os: ubuntu-latest , dpkg_arch: armhf, use-cross: true }
|
||||
- { target: arm-unknown-linux-musleabihf, os: ubuntu-latest , dpkg_arch: musl-linux-armhf, use-cross: true }
|
||||
- { target: i686-pc-windows-msvc , os: windows-2025 , }
|
||||
# The timeout test's socketpair fails on the Ubuntu 26.04 runner.
|
||||
- { target: i686-unknown-linux-gnu , os: ubuntu-24.04 , dpkg_arch: i386, use-cross: true }
|
||||
- { target: i686-unknown-linux-gnu , os: ubuntu-latest , dpkg_arch: i386, use-cross: true }
|
||||
- { target: i686-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: musl-linux-i686, use-cross: true }
|
||||
- { target: x86_64-apple-darwin , os: macos-15-intel, }
|
||||
- { target: aarch64-apple-darwin , os: macos-latest , }
|
||||
@@ -458,7 +457,7 @@ jobs:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: vedantmgoyal9/winget-releaser@b7370d4d152efdce803a26cc6ca9eee58cb2ad54
|
||||
- uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f
|
||||
with:
|
||||
identifier: sharkdp.bat
|
||||
installers-regex: '-pc-windows-msvc\.zip$'
|
||||
|
||||
@@ -284,6 +284,3 @@
|
||||
[submodule "assets/syntaxes/02_Extra/Caddy"]
|
||||
path = assets/syntaxes/02_Extra/Caddy
|
||||
url = https://github.com/caddyserver/sublimetext.git
|
||||
[submodule "assets/syntaxes/02_Extra/CUE"]
|
||||
path = assets/syntaxes/02_Extra/CUE
|
||||
url = https://github.com/cue-lang/vscode-cue.git
|
||||
@@ -3,22 +3,15 @@
|
||||
|
||||
## Other
|
||||
|
||||
- Document submodule initialization when rebuilding syntax and theme assets, see #3801 (@xfocus3)
|
||||
- Fix anchor case in `doc/assets.md` links, see #4026 (@ump45nose)
|
||||
- Pin the i686 GNU CI runner to Ubuntu 24.04 to avoid `socketpair` failures on Ubuntu 26.04, see #4101 (@PerchAnton)
|
||||
- Fix dead Visual C++ Redistributable link in README, see #3895 (@1t1sCooL)
|
||||
- Document `StripAnsiMode` and its variants in rustdoc, see #4067 (@ump45nose)
|
||||
- Update Cargo dependencies to resolve current RustSec advisories, see #3861 (@TyceHerrman)
|
||||
- Add instructions for removing fish help abbreviations to README, see #3655 (@claw-explorer). Closes #3536
|
||||
- Add .NET slnx extension, see #3682 (@ltrzesniewski)
|
||||
|
||||
## Features
|
||||
|
||||
- Automatically build the syntax/theme cache on first run when custom themes or syntaxes are present but no cache exists yet, so newly installed dotfiles work without a manual `bat cache --build`. Use `--no-custom-assets` to opt out. Closes #4017, see #4038 (@mmustafasenoglu)
|
||||
- Add `-b` / `--number-nonblank` flag to only number non-blank lines, for `cat -b` compatibility. Closes #3856, see #3857 (@MeGaurav4)
|
||||
- Add a `--sanitize=<auto|always|never>` flag for safe display of untrusted input. It implies `--strip-ansi` at the same value and additionally substitutes terminal-active control bytes (cursor moves, charset switches, beep, etc.) and Unicode bidi / zero-width formatting characters with the Unicode replacement character (U+FFFD). Mitigates Trojan-Source-style spoofing (CVE-2021-42574). See #3729 (@curious-rabbit)
|
||||
- Map justfile, Justfile, .justfile, and *.justfile to Makefile syntax highlighting, see #3623 (@zachvalenta)
|
||||
- Map `.kube/config` to YAML syntax highlighting, see #3911 (@logarithmone1128)
|
||||
- Preserve `--diff` change markers and snip separators when `--plain` is set. Closes #3630, see #3643 (@mvanhorn)
|
||||
- Added support for `hidden_file_extensions` from `.sublime-syntax` files, see #3613 (@Matei02355)
|
||||
- Add word wrapping mode via `--wrap=word`, see #3597 (@veeceey)
|
||||
@@ -32,26 +25,8 @@
|
||||
- Syntax highlighting for Python files using uv as script runner in shebang #3689 (@janlarres)
|
||||
|
||||
## Bugfixes
|
||||
- Ignore empty `--ignored-suffix` values to avoid a stack overflow, see #4122 (@spicysharkco)
|
||||
- Fix `--number-nonblank` counting empty UTF-16 lines, see #4118 (@pcbeingused333)
|
||||
- Don't emit `--highlight-line` escape sequences (background color or `ansi` theme underline) when colors are disabled with `--color=never`. Closes #4099, see #4100 (@DeviousCardi)
|
||||
- Fix missing colors, pager, and decorations in mintty/MSYS2 and Cygwin terminals on Windows, see #4115 (@rezamuliawijaya)
|
||||
- Make full-path `--map-syntax` patterns and the built-in `$HOME` and `$XDG_CONFIG_HOME` mappings work on Windows, see #4113 (@b84330808)
|
||||
- Keep configuration and BAT_OPTS active for option-like filenames after `--`, and report invalid configuration for help-like filenames, see #4112 (@Marve10s)
|
||||
- Keep emoji sequences together within text chunks when wrapping content, and measure their combined display width, see #4108 (@Marve10s)
|
||||
- Preserve full-path syntax mappings when removing ignored filename suffixes, see #4111 (@Marve10s)
|
||||
- Fix UTF-16 line splitting at unaligned newline bytes corrupting text and shifting line ranges, see #4110 (@Marve10s)
|
||||
- Respect `NO_COLOR` for the `[bat error]` and `[bat warning]` prefixes, see #4048 (@qodelicious)
|
||||
- Offer the valid `--wrap` value `auto` instead of the rejected `always` in the PowerShell completion, see #4070 (@ump45nose)
|
||||
- Report `BAT_CONFIG_DIR` in `bat --diagnostic`, so bug reports show a config directory that overrides `$XDG_CONFIG_HOME`. See #4068 (@ump45nose)
|
||||
- Ignore a UTF-8 byte order mark at the start of the config file instead of treating it as part of the first argument, see #4103 (@jaeminbird)
|
||||
- Keep backslashes in the pager command on Windows, so `BAT_PAGER=C:\tools\less.exe` is found instead of becoming `C:toolsless.exe`, see #4104 (@jaeminbird)
|
||||
- Fix `bat` hanging forever on JavaScript (and Svelte) code where an expression is followed by a block comment, e.g. `a /* x */`. Closes #4080, see #4091 (@NavpreetSSidhu)
|
||||
- Fix the first line of UTF-16BE input swallowing the second line, which broke line numbers, `--line-range` and highlighting, see #4102 (@cindykrafft)
|
||||
- Exit quietly with status 0 instead of panicking when stdout is closed early (broken pipe) on auxiliary output paths such as `--completion`, `--config-file`, `--diagnostic`, `--generate-config-file`, `--set-terminal-title` and `cache --build`/`--clear`, matching the main output path since #232, closes #4034, see #4035 (@Mathjk)
|
||||
- Track strikethrough (SGR 9 / 29) in the ANSI style tracker so it is re-emitted like bold, dim, italic, and underline, and is no longer dropped after the first highlighted token when displaying ANSI input with syntax highlighting, see #4015 (@mikehasa)
|
||||
- Allow boolean flags to be given more than once, so that a flag set in the config file can also be passed on the command line without erroring, see #3912 (@logarithmone1128)
|
||||
- Allow options that take a value (`--binary`, `--italic-text`, `--nonprintable-notation`, `--fallback-syntax`, `--squeeze-limit`) to be given more than once, so that a value from the config file can be overridden on the command line, see #4102 (@Huang-404-Q)
|
||||
- Use parsed CLI arguments to detect number flags, see #3908 (@cuishuang)
|
||||
- Detect binary content beyond the first line, preventing encrypted files with early line breaks from being treated as text. Closes #3554, see #3877 (@Matei02355)
|
||||
- Use the last occurrence of numbering and plain flags in combined short arguments, see #3897 (@cuishuang)
|
||||
@@ -110,8 +85,6 @@
|
||||
- Add syntax highlighting for `Caddyfile` #3789 (@CosmicHorrorDev)
|
||||
- Include `.code-workspace` as a JSON extension #3809 (@dhruvkb)
|
||||
- Add syntax mapping for DNF repo configuration files, see #3814 (@injust)
|
||||
- Add syntax mapping for Podman `.quadlets` files, see #4069 (@injust)
|
||||
- Add syntax highlighting for CUE, see #4094 (@nikarh)
|
||||
|
||||
## Themes
|
||||
|
||||
@@ -127,7 +100,6 @@
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fix `capacity overflow` panic when wrapping a double-width character on a line narrower than the character while a background is painted (e.g. `--terminal-width=1 --wrap=character --highlight-line=1`). Closes #3844, see #4098 (@feafel)
|
||||
- Fix hang when using `--list-themes` with an explicit pager, see #3457 (@abhinavcool42)
|
||||
- Fix negative values of N not being parsed in <N:M> line ranges without `=` flag value separator, see #3442 (@lmmx)
|
||||
- Fix broken Docker syntax preventing use of custom assets, see #3476 (@keith-hall)
|
||||
|
||||
Generated
+25
-2
@@ -396,6 +396,12 @@ version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core_detect"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
@@ -660,11 +666,16 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
version = "0.8.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core_detect",
|
||||
"multiversion_no_op",
|
||||
"rustversion",
|
||||
"scopeguard",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1880,6 +1891,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multiversion_no_op"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.3"
|
||||
@@ -2461,6 +2478,12 @@ version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ tempfile = "3.27.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
nix = { version = "0.31", default-features = false, features = ["poll", "term"] }
|
||||
nix = { version = "0.31", default-features = false, features = ["term"] }
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.97"
|
||||
|
||||
@@ -417,7 +417,7 @@ scoop install bat
|
||||
|
||||
You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases),
|
||||
|
||||
You will need to install the [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) package.
|
||||
You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package.
|
||||
|
||||
### From binaries
|
||||
|
||||
@@ -431,12 +431,6 @@ If you want to build `bat` from source, you need Rust 1.79.0 or
|
||||
higher. You can then use `cargo` to build everything:
|
||||
|
||||
#### From local source
|
||||
|
||||
The checkout includes prebuilt syntax and theme assets. If you want to regenerate them
|
||||
from their sources, first initialize the Git submodules with
|
||||
`git submodule update --init --recursive`, then follow the [Development](#development)
|
||||
instructions. This includes the `help` syntax used to highlight command-line help.
|
||||
|
||||
```bash
|
||||
cargo install --path . --locked
|
||||
```
|
||||
@@ -800,7 +794,7 @@ Example configuration file:
|
||||
|
||||
### Prerequisites
|
||||
|
||||
You will need to install the [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) package.
|
||||
You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package.
|
||||
|
||||
### Paging
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
|
||||
$ArrayCompletion = @('bash', 'fish', 'zsh', 'ps1')
|
||||
$ArrayWhen = @('auto', 'never', 'always')
|
||||
$ArrayYesNo = @('never', 'always')
|
||||
$ArrayWrap = @('auto', 'never', 'character', 'word')
|
||||
$ArrayWrap = @('always', 'never', 'character', 'word')
|
||||
$ArrayBinary = @('no-printing', 'as-text')
|
||||
$ArrayPrint = @('unicode', 'caret')
|
||||
|
||||
|
||||
-10
@@ -12,13 +12,3 @@ index 05a4fed6..78a7bf55 100644
|
||||
scope: source.js
|
||||
variables:
|
||||
bin_digit: '[01_]'
|
||||
@@ -93,7 +93,8 @@ variables:
|
||||
(?! \+\+ | -- )
|
||||
(?=
|
||||
!= |
|
||||
- [-+*/%><=&|^\[(;,.:?] |
|
||||
+ [-+*%><=&|^\[(;,.:?] |
|
||||
+ /(?!\*) |
|
||||
(?:in|instanceof){{identifier_break}}
|
||||
)
|
||||
))
|
||||
Vendored
-1
Submodule assets/syntaxes/02_Extra/CUE deleted from 16796709f3.
-952
@@ -1,952 +0,0 @@
|
||||
%YAML 1.2
|
||||
---
|
||||
# http://www.sublimetext.com/docs/3/syntax.html
|
||||
name: CUE
|
||||
file_extensions:
|
||||
- cue
|
||||
scope: source.cue
|
||||
contexts:
|
||||
main:
|
||||
- include: invalid_slash
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(package)[ \t]+([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*)(?![\p{L}\p{Nd}_\$\#])'
|
||||
captures:
|
||||
1: keyword.other.package
|
||||
2: entity.name.namespace
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(import)[ \t]+(\()'
|
||||
captures:
|
||||
1: keyword.other.import
|
||||
2: punctuation.section.parens.begin
|
||||
push:
|
||||
- meta_scope: meta.imports
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.parens.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- match: '(?:([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)[ \t]+)?(")([^:"]+)(?:(:)([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*))?(")'
|
||||
scope: meta.import-spec
|
||||
captures:
|
||||
1: entity.name.namespace
|
||||
2: punctuation.definition.string.begin
|
||||
3: string.quoted.double-import
|
||||
4: punctuation.colon
|
||||
5: entity.name
|
||||
6: punctuation.definition.string.end
|
||||
- match: ;
|
||||
scope: punctuation.separator
|
||||
- include: invalid_in_parens
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(import)[ \t]+(?:([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)[ \t]+)?(")([^:"]+)(?:(:)([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*))?(")'
|
||||
scope: meta.import
|
||||
captures:
|
||||
1: keyword.other.import
|
||||
2: entity.name.namespace
|
||||
3: punctuation.definition.string.begin
|
||||
4: string.quoted.double-import
|
||||
5: punctuation.colon
|
||||
6: entity.name
|
||||
7: punctuation.definition.string.end
|
||||
- include: punctuation_comma
|
||||
- include: declaration
|
||||
- include: invalid_in_braces
|
||||
comment:
|
||||
- match: (//).*$\n?
|
||||
scope: comment.line
|
||||
captures:
|
||||
1: punctuation.definition.comment
|
||||
alias_postfix:
|
||||
- match: '(~)[ \t]*(?:([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)|(\()[ \t]*([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)(?:[ \t]*(,)[ \t]*([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_))?[ \t]*(\)))'
|
||||
captures:
|
||||
1: punctuation.alias
|
||||
2: variable.other
|
||||
3: punctuation.section.parens.begin
|
||||
4: variable.other
|
||||
5: punctuation.separator
|
||||
6: variable.other
|
||||
7: punctuation.section.parens.end
|
||||
attribute:
|
||||
- match: '(@)([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)(\()'
|
||||
captures:
|
||||
1: punctuation.definition.annotation
|
||||
2: variable.annotation
|
||||
3: punctuation.attribute-elements.begin
|
||||
push:
|
||||
- meta_scope: meta.annotation
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.attribute-elements.end
|
||||
pop: true
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: attribute_element
|
||||
attribute_element:
|
||||
- match: '[ \t]*(?<![\p{L}\p{Nd}_\$\#])((?:[\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)(?:\.(?:[\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+))*)[ \t]*(=)(?!=)'
|
||||
captures:
|
||||
1: variable.other
|
||||
2: punctuation.bind
|
||||
push:
|
||||
- match: '(?=[,\)])'
|
||||
pop: true
|
||||
- include: comment
|
||||
- include: attribute_nested
|
||||
- include: attribute_string
|
||||
- include: attribute_nested
|
||||
- include: attribute_string
|
||||
attribute_nested:
|
||||
- match: '[ \t]*(?:([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)[ \t]*)?(\()'
|
||||
captures:
|
||||
1: variable.other
|
||||
2: punctuation.attribute-elements.begin
|
||||
push:
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.attribute-elements.end
|
||||
pop: true
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: attribute_element
|
||||
attribute_string:
|
||||
- include: string
|
||||
- match: '(?:[^\n,"''#\(\)/]|/(?!/)|(?<!#)#++(?!["'']))+'
|
||||
scope: string.unquoted
|
||||
- match: '[^,\)]+'
|
||||
scope: invalid
|
||||
declaration:
|
||||
- include: attribute
|
||||
- include: alias_postfix
|
||||
- include: punctuation_ellipsis
|
||||
- include: punctuation_colon
|
||||
- include: punctuation_option
|
||||
- include: punctuation_bind
|
||||
- include: expression
|
||||
expression:
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(for)[ \t]+([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)(?:[ \t]*(,)[ \t]*([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_))?[ \t]+(in)(?![\p{L}\p{Nd}_\$\#])(?:[ \t]+(else|otherwise|fallback|try)(?![\p{L}\p{Nd}_\$\#]))?'
|
||||
captures:
|
||||
1: keyword.control.for
|
||||
2: variable.other
|
||||
3: punctuation.separator
|
||||
4: variable.other
|
||||
5: keyword.control.in
|
||||
6: variable.other
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(if)(?![\p{L}\p{Nd}_\$\#])(?:[ \t]+(else|otherwise|fallback|try)(?![\p{L}\p{Nd}_\$\#]))?'
|
||||
captures:
|
||||
1: keyword.control.conditional
|
||||
2: variable.other
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(try)[ \t]+([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+|_)[ \t]*(=)(?![=~])'
|
||||
captures:
|
||||
1: keyword.control.try
|
||||
2: variable.other
|
||||
3: punctuation.bind
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])try(?=[ \t]*\{|[ \t]+(?:for|if|let|try)(?![\p{L}\p{Nd}_\$\#]))'
|
||||
scope: keyword.control.try
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(?:else|otherwise|fallback)(?=[ \t]*\{)'
|
||||
scope: keyword.control.conditional
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])func(?=[ \t]*\()'
|
||||
scope: keyword.function
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(let)[ \t]+([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)[ \t]*(=)(?![=])'
|
||||
captures:
|
||||
1: keyword.control.let
|
||||
2: variable.other
|
||||
3: punctuation.bind
|
||||
- match: "->"
|
||||
scope: keyword.operator.arrow
|
||||
- match: '[\+\-\*]|/(?!/)'
|
||||
scope: keyword.operator
|
||||
- match: "=[=~]|![=~]|<=|>=|[<](?!=)|[>](?![=])"
|
||||
scope: keyword.operator.comparison
|
||||
- match: '&{2}|\|{2}|!(?![=~])'
|
||||
scope: keyword.operator.logical
|
||||
- match: '&(?!&)|\|(?!\|)'
|
||||
scope: keyword.operator.set
|
||||
- match: '(?<!\.)(\.)[ \t]*([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)(?![\p{L}\p{Nd}_\$\#])'
|
||||
captures:
|
||||
1: punctuation.accessor
|
||||
2: variable.other.member
|
||||
- match: '(?<!\.)(\.)(?=[ \t]*(?:#*"|//|$))'
|
||||
captures:
|
||||
1: punctuation.accessor
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])_(?!\|)(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: constant.language.top
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])_\|_(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: constant.language.bottom
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])null(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: constant.language.null
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(?:true|false)(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: constant.language.bool
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])[0-9](?:_?[0-9])*\.(?:[0-9](?:_?[0-9])*)?(?:[eE][\+\-]?[0-9](?:_?[0-9])*)?(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.float.decimal
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])[0-9](?:_?[0-9])*[eE][\+\-]?[0-9](?:_?[0-9])*(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.float.decimal
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])\.[0-9](?:_?[0-9])*(?:[eE][\+\-]?[0-9](?:_?[0-9])*)?(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.float.decimal
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])(?:0|[1-9](?:_?[0-9])*)(?:\.[0-9](?:_?[0-9])*)?(?:[KMGTP]i?)(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.other
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])\.[0-9](?:_?[0-9])*(?:[KMGTP]i?)(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.other
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])(?:0|[1-9](?:_?[0-9])*)(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.decimal
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])0b_?[0-1](?:_?[0-1])*(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.binary
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])0[xX]_?[0-9a-fA-F](?:_?[0-9a-fA-F])*(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.hexadecimal
|
||||
- match: '(?<![\p{L}\p{Nd}_\.])0o_?[0-7](?:_?[0-7])*(?![\p{L}\p{Nd}_]|\.(?!\.\.))'
|
||||
scope: constant.numeric.integer.octal
|
||||
- include: string
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(?:bool|u?int(?:8|16|32|64|128)?|float(?:32|64)?|string|bytes|number|rune)(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: support.type
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(?:__)?self(?![\p{L}\p{Nd}_\$\#])(?![ \t]*+(?:[?!][ \t]*+)?:|[ \t]*+~|[ \t]*+=(?![=~]))'
|
||||
scope: variable.language.self
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(len|close|and|or|div|mod|quo|rem|matchN|matchIf|error|validator)(\()'
|
||||
captures:
|
||||
1: support.function
|
||||
2: punctuation.section.parens.begin
|
||||
push:
|
||||
- meta_scope: meta.function-call
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.parens.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: attribute
|
||||
- include: alias_postfix
|
||||
- include: punctuation_colon
|
||||
- include: punctuation_option
|
||||
- include: punctuation_bind
|
||||
- include: punctuation_ellipsis
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)(\.)(\p{Lu}[\p{L}\p{Nd}_\$\#]*)(\()'
|
||||
captures:
|
||||
1: support.module
|
||||
2: punctuation
|
||||
3: support.function
|
||||
4: punctuation.section.parens.begin
|
||||
push:
|
||||
- meta_scope: meta.function-call
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.parens.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: attribute
|
||||
- include: alias_postfix
|
||||
- include: punctuation_colon
|
||||
- include: punctuation_option
|
||||
- include: punctuation_bind
|
||||
- include: punctuation_ellipsis
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])(?:[\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)(?![\p{L}\p{Nd}_\$\#])'
|
||||
scope: variable.other
|
||||
- match: '\{'
|
||||
captures:
|
||||
0: punctuation.definition.struct.begin
|
||||
push:
|
||||
- meta_scope: meta.struct
|
||||
- match: '\}'
|
||||
captures:
|
||||
0: punctuation.definition.struct.end
|
||||
pop: true
|
||||
- include: invalid_slash
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: punctuation_ellipsis
|
||||
- include: declaration
|
||||
- include: invalid_in_braces
|
||||
- match: '\['
|
||||
captures:
|
||||
0: punctuation.section.brackets.begin
|
||||
push:
|
||||
- meta_scope: meta.brackets
|
||||
- match: '\]'
|
||||
captures:
|
||||
0: punctuation.section.brackets.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- include: punctuation_colon
|
||||
- include: punctuation_comma
|
||||
- include: punctuation_ellipsis
|
||||
- include: punctuation_option
|
||||
- match: '(?<![\p{L}\p{Nd}_\$\#])([\p{L}\$\#][\p{L}\p{Nd}_\$\#]*|_[\p{L}\p{Nd}_\$\#]+)[ \t]*(=)(?![=~])'
|
||||
captures:
|
||||
1: variable.other
|
||||
2: punctuation.alias
|
||||
- include: expression
|
||||
- match: '[^\s\]]'
|
||||
scope: invalid
|
||||
- match: \(
|
||||
captures:
|
||||
0: punctuation.section.parens.begin
|
||||
push:
|
||||
- meta_scope: meta.parens
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.parens.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: comment
|
||||
- include: punctuation_comma
|
||||
- include: attribute
|
||||
- include: alias_postfix
|
||||
- include: punctuation_colon
|
||||
- include: punctuation_option
|
||||
- include: punctuation_bind
|
||||
- include: punctuation_ellipsis
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
invalid_in_braces:
|
||||
- match: '[^\s\}]'
|
||||
scope: invalid
|
||||
invalid_in_parens:
|
||||
- match: '[^\s\)]'
|
||||
scope: invalid
|
||||
invalid_slash:
|
||||
- match: '(?<=^|[\{,:])[ \t]*+(/)(?!/)'
|
||||
captures:
|
||||
1: invalid
|
||||
punctuation_bind:
|
||||
- match: "(?<![=!><])=(?![=~])"
|
||||
scope: punctuation.bind
|
||||
punctuation_colon:
|
||||
- match: (?<!:):(?!:)
|
||||
scope: punctuation.colon
|
||||
punctuation_comma:
|
||||
- match: ","
|
||||
scope: punctuation.separator
|
||||
punctuation_ellipsis:
|
||||
- match: '(?<!\.)\.{3}(?!\.)'
|
||||
scope: punctuation.ellipsis
|
||||
punctuation_option:
|
||||
- match: \?
|
||||
scope: punctuation.option
|
||||
string:
|
||||
- match: '####"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double-multiline
|
||||
- match: '"""####'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\####(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\####(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\####\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\####$
|
||||
scope: constant.character.escape
|
||||
- match: \\####.
|
||||
scope: invalid.illegal
|
||||
- match: '####"'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double
|
||||
- match: '"####'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\####(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\####(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\####\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\####.
|
||||
scope: invalid.illegal
|
||||
- match: "####'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single-multiline
|
||||
- match: "'''####"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\####(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\####(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\####\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\####$
|
||||
scope: constant.character.escape
|
||||
- match: \\####.
|
||||
scope: invalid.illegal
|
||||
- match: "####'"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single
|
||||
- match: "'####"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\####(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\####(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\####\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\####.
|
||||
scope: invalid.illegal
|
||||
- match: '###"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double-multiline
|
||||
- match: '"""###'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\###(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\###(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\###\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\###$
|
||||
scope: constant.character.escape
|
||||
- match: \\###.
|
||||
scope: invalid.illegal
|
||||
- match: '###"'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double
|
||||
- match: '"###'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\###(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\###(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\###\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\###.
|
||||
scope: invalid.illegal
|
||||
- match: "###'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single-multiline
|
||||
- match: "'''###"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\###(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\###(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\###\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\###$
|
||||
scope: constant.character.escape
|
||||
- match: \\###.
|
||||
scope: invalid.illegal
|
||||
- match: "###'"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single
|
||||
- match: "'###"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\###(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\###(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\###\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\###.
|
||||
scope: invalid.illegal
|
||||
- match: '##"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double-multiline
|
||||
- match: '"""##'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\##(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\##(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\##\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\##$
|
||||
scope: constant.character.escape
|
||||
- match: \\##.
|
||||
scope: invalid.illegal
|
||||
- match: '##"'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double
|
||||
- match: '"##'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\##(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\##(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\##\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\##.
|
||||
scope: invalid.illegal
|
||||
- match: "##'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single-multiline
|
||||
- match: "'''##"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\##(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\##(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\##\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\##$
|
||||
scope: constant.character.escape
|
||||
- match: \\##.
|
||||
scope: invalid.illegal
|
||||
- match: "##'"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single
|
||||
- match: "'##"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\##(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\##(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\##\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\##.
|
||||
scope: invalid.illegal
|
||||
- match: '#"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double-multiline
|
||||
- match: '"""#'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\#(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\#(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\#\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\#$
|
||||
scope: constant.character.escape
|
||||
- match: \\#.
|
||||
scope: invalid.illegal
|
||||
- match: '#"'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double
|
||||
- match: '"#'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\#(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\#(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\#\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\#.
|
||||
scope: invalid.illegal
|
||||
- match: "#'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single-multiline
|
||||
- match: "'''#"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\#(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\#(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\#\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\#$
|
||||
scope: constant.character.escape
|
||||
- match: \\#.
|
||||
scope: invalid.illegal
|
||||
- match: "#'"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single
|
||||
- match: "'#"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\#(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\#(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\#\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\#.
|
||||
scope: invalid.illegal
|
||||
- match: '"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double-multiline
|
||||
- match: '"""'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\$
|
||||
scope: constant.character.escape
|
||||
- match: \\.
|
||||
scope: invalid.illegal
|
||||
- match: '"'
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.double
|
||||
- match: '"'
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\(?:"|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: invalid.illegal
|
||||
- match: \\\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\.
|
||||
scope: invalid.illegal
|
||||
- match: "'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single-multiline
|
||||
- match: "'''"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\$
|
||||
scope: constant.character.escape
|
||||
- match: \\.
|
||||
scope: invalid.illegal
|
||||
- match: "'"
|
||||
captures:
|
||||
0: punctuation.definition.string.begin
|
||||
push:
|
||||
- meta_scope: meta.string
|
||||
- meta_content_scope: string.quoted.single
|
||||
- match: "'"
|
||||
captures:
|
||||
0: punctuation.definition.string.end
|
||||
pop: true
|
||||
- match: '\\(?:''|/|\\|[abfnrtv]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})'
|
||||
scope: constant.character.escape
|
||||
- match: '\\(?:[0-7]{3}|x[0-9A-Fa-f]{2})'
|
||||
scope: constant.character.escape
|
||||
- match: \\\(
|
||||
captures:
|
||||
0: punctuation.section.interpolation.begin
|
||||
push:
|
||||
- meta_scope: meta.interpolation
|
||||
- meta_content_scope: source.cue.embedded
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.section.interpolation.end
|
||||
pop: true
|
||||
- include: whitespace
|
||||
- include: punctuation_option
|
||||
- include: expression
|
||||
- include: invalid_in_parens
|
||||
- match: \\.
|
||||
scope: invalid.illegal
|
||||
whitespace:
|
||||
- match: '[ \t\r\n]+'
|
||||
+2
-6
@@ -6,7 +6,7 @@ Should you find that a particular syntax is not available within `bat` and think
|
||||
code. As a basis, syntect uses [Sublime Text](https://www.sublimetext.com/) syntax definitions
|
||||
in the `.sublime-syntax` format.
|
||||
|
||||
**Important:** Before proceeding, verify that the syntax you wish to add meets the [criteria for inclusion](#criteria-for-inclusion-of-new-syntaxes).
|
||||
**Important:** Before proceeding, verify that the syntax you wish to add meets the [criteria for inclusion](#Criteria-for-inclusion-of-new-syntaxes).
|
||||
|
||||
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`) using
|
||||
@@ -28,7 +28,7 @@ in the `.sublime-syntax` format.
|
||||
|
||||
5. Use `bat --list-languages` to check if the new languages are available. You may want to do something like ``export PATH="`pwd`/target/debug:$PATH"`` to ensure the locally compiled version is the one being used.
|
||||
|
||||
6. Add a syntax test for the new language. See [below](#syntax-tests) for details.
|
||||
6. Add a syntax test for the new language. See [below](#Syntax-tests) for details.
|
||||
|
||||
7. If you send a pull request with your changes, please do *not* include the changed `syntaxes.bin`
|
||||
file. A new binary cache file will be created once before every new release of `bat`. This
|
||||
@@ -103,7 +103,3 @@ The following files have been manually modified after converting from a `.tmLang
|
||||
* `Cabal.sublime_syntax` has been added manually from
|
||||
https://github.com/SublimeHaskell/SublimeHaskell/ - we don't want to include the whole submodule because it includes other syntaxes ("Haskell improved") as well.
|
||||
* `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean4/blob/master/vscode-lean4/syntaxes/lean4.json via conversion.
|
||||
* `CUE.sublime-syntax` has been added manually from https://github.com/cue-lang/vscode-cue/blob/master/extension/syntaxes/cue.tmLanguage.json via conversion.
|
||||
Sublime Text's converter rejects rules that only group other patterns (see https://github.com/cue-lang/cue/issues/3427), so they are inlined before converting:
|
||||
`jq 'walk(if type == "object" and has("patterns") then .patterns |= [.[] | if type == "object" and keys == ["patterns"] then .patterns[] else . end] else . end)'`.
|
||||
The converted syntax reproduces the token goldens in `extension/testdata/syntax` of that repository.
|
||||
+15
-25
@@ -1,5 +1,4 @@
|
||||
use std::convert::TryInto;
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use syntect::highlighting::ThemeSet;
|
||||
@@ -25,7 +24,7 @@ pub fn build(
|
||||
|
||||
let acknowledgements = build_acknowledgements(source_dir, include_acknowledgements)?;
|
||||
|
||||
print_unlinked_contexts(&syntax_set)?;
|
||||
print_unlinked_contexts(&syntax_set);
|
||||
|
||||
write_assets(
|
||||
&theme_set,
|
||||
@@ -47,18 +46,16 @@ fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> Result
|
||||
if theme_dir.exists() {
|
||||
let res = theme_set.add_from_folder(&theme_dir);
|
||||
if let Err(err) = res {
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
println!(
|
||||
"Failed to load one or more themes from '{}' (reason: '{err}')",
|
||||
theme_dir.to_string_lossy(),
|
||||
)?;
|
||||
);
|
||||
}
|
||||
} else {
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
println!(
|
||||
"No themes were found in '{}', using the default set",
|
||||
theme_dir.to_string_lossy()
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
theme_set.try_into()
|
||||
@@ -81,25 +78,23 @@ fn build_syntax_set_builder(
|
||||
if syntax_dir.exists() {
|
||||
syntax_set_builder.add_from_folder(syntax_dir, true)?;
|
||||
} else {
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
println!(
|
||||
"No syntaxes were found in '{}', using the default set.",
|
||||
syntax_dir.to_string_lossy()
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
Ok(syntax_set_builder)
|
||||
}
|
||||
|
||||
fn print_unlinked_contexts(syntax_set: &SyntaxSet) -> Result<()> {
|
||||
fn print_unlinked_contexts(syntax_set: &SyntaxSet) {
|
||||
let missing_contexts = syntax_set.find_unlinked_contexts();
|
||||
if !missing_contexts.is_empty() {
|
||||
writeln!(io::stdout(), "Some referenced contexts could not be found!")?;
|
||||
println!("Some referenced contexts could not be found!");
|
||||
for context in missing_contexts {
|
||||
writeln!(io::stdout(), "- {context}")?;
|
||||
println!("- {context}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_assets(
|
||||
@@ -132,13 +127,12 @@ fn write_assets(
|
||||
)?;
|
||||
}
|
||||
|
||||
write!(
|
||||
io::stdout(),
|
||||
print!(
|
||||
"Writing metadata to folder {} ... ",
|
||||
target_dir.to_string_lossy()
|
||||
)?;
|
||||
);
|
||||
crate::assets_metadata::AssetsMetadata::new(current_version).save_to_folder(target_dir)?;
|
||||
writeln!(io::stdout(), "okay")?;
|
||||
println!("okay");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -167,14 +161,10 @@ fn asset_to_cache<T: serde::Serialize>(
|
||||
description: &str,
|
||||
compressed: bool,
|
||||
) -> Result<()> {
|
||||
write!(
|
||||
io::stdout(),
|
||||
"Writing {description} to {} ... ",
|
||||
path.to_string_lossy()
|
||||
)?;
|
||||
print!("Writing {description} to {} ... ", path.to_string_lossy());
|
||||
let contents = asset_to_contents(asset, description, compressed)?;
|
||||
std::fs::write(path, &contents[..])
|
||||
.map_err(|_| format!("Could not save {description} to {}", path.to_string_lossy()))?;
|
||||
writeln!(io::stdout(), "okay")?;
|
||||
println!("okay");
|
||||
Ok(())
|
||||
}
|
||||
+22
-23
@@ -65,20 +65,12 @@ pub struct App {
|
||||
number_nonblank_from_cli: bool,
|
||||
}
|
||||
|
||||
/// True if stdout is attached to an interactive terminal. On Windows this also
|
||||
/// recognizes mintty/MSYS2 and Cygwin pseudo-terminals, which expose stdout as
|
||||
/// a named pipe that `std::io::IsTerminal` does not report as a terminal.
|
||||
/// Regular pipes (e.g. `bat file | grep`) are not affected.
|
||||
fn is_interactive_output() -> bool {
|
||||
std::io::stdout().is_terminal() || Term::stdout().features().is_msys_tty()
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Result<Self> {
|
||||
#[cfg(windows)]
|
||||
let _ = nu_ansi_term::enable_ansi_support();
|
||||
|
||||
let interactive_output = is_interactive_output();
|
||||
let interactive_output = std::io::stdout().is_terminal();
|
||||
|
||||
// Parse the original command line separately from config and environment arguments.
|
||||
// Using clap here keeps CLI-only detection consistent with the final parser, including
|
||||
@@ -87,7 +79,7 @@ impl App {
|
||||
let number_from_cli = cli_matches.get_flag("number");
|
||||
let number_nonblank_from_cli = cli_matches.get_flag("number-nonblank");
|
||||
|
||||
let matches = Self::matches(interactive_output, &cli_matches)?;
|
||||
let matches = Self::matches(interactive_output)?;
|
||||
|
||||
if matches.get_flag("help") {
|
||||
let help_type = if wild::args_os().any(|arg| arg == "--help") {
|
||||
@@ -177,8 +169,7 @@ impl App {
|
||||
};
|
||||
|
||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
||||
let config_dir = PROJECT_DIRS.config_dir();
|
||||
let assets = assets_from_cache_or_binary(use_custom_assets, config_dir, cache_dir)?;
|
||||
let assets = assets_from_cache_or_binary(use_custom_assets, cache_dir)?;
|
||||
Controller::new(&help_config, &assets)
|
||||
.run(inputs, None)
|
||||
.ok();
|
||||
@@ -204,13 +195,20 @@ impl App {
|
||||
clap_app::build_app(interactive_output).get_matches_from(wild::args_os())
|
||||
}
|
||||
|
||||
fn matches(interactive_output: bool, cli_matches: &ArgMatches) -> Result<ArgMatches> {
|
||||
let should_skip_config =
|
||||
cli_matches.get_flag("no-config") || cli_matches.get_flag("diagnostic");
|
||||
fn matches(interactive_output: bool) -> Result<ArgMatches> {
|
||||
// Check if we should skip config file processing for special arguments
|
||||
// that don't require full application setup (version, diagnostic)
|
||||
let should_skip_config = wild::args_os().any(|arg| {
|
||||
matches!(
|
||||
arg.to_str(),
|
||||
Some("-V" | "--version" | "--diagnostic" | "--diagnostics")
|
||||
)
|
||||
});
|
||||
|
||||
// Check if help was requested - help should read the config file but be
|
||||
// forgiving of invalid arguments (so configured theme etc. can be used)
|
||||
let help_requested = cli_matches.get_flag("help");
|
||||
let help_requested =
|
||||
wild::args_os().any(|arg| matches!(arg.to_str(), Some("-h" | "--help")));
|
||||
|
||||
if wild::args_os().nth(1) == Some("cache".into()) {
|
||||
// Skip the config file and env vars
|
||||
@@ -218,9 +216,9 @@ impl App {
|
||||
return Ok(clap_app::build_app(interactive_output).get_matches_from(args));
|
||||
}
|
||||
|
||||
if should_skip_config {
|
||||
if wild::args_os().any(|arg| arg == "--no-config") || should_skip_config {
|
||||
// Skip the arguments in bats config file when --no-config is present
|
||||
// or when user requests diagnostic information
|
||||
// or when user requests version or diagnostic information
|
||||
let args = Self::build_args_without_config();
|
||||
return Ok(clap_app::build_app(interactive_output).get_matches_from(args));
|
||||
}
|
||||
@@ -336,12 +334,13 @@ impl App {
|
||||
// later args take precedence over earlier ones, hence `.rev()`
|
||||
// see: https://github.com/sharkdp/bat/pull/2755#discussion_r1456416875
|
||||
for from_to in values.rev() {
|
||||
// The glob can contain colons itself, e.g. after a drive letter on Windows.
|
||||
let Some((from, to)) = from_to.rsplit_once(':') else {
|
||||
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is '<glob-pattern>:<syntax-name>'. For example: '*.cpp:C++'.".into());
|
||||
};
|
||||
let parts: Vec<_> = from_to.split(':').collect();
|
||||
|
||||
syntax_mapping.insert(from, MappingTarget::MapTo(to))?;
|
||||
if parts.len() != 2 {
|
||||
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is '<glob-pattern>:<syntax-name>'. For example: '*.cpp:C++'.".into());
|
||||
}
|
||||
|
||||
syntax_mapping.insert(parts[0], MappingTarget::MapTo(parts[1]))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-61
@@ -1,5 +1,5 @@
|
||||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -9,22 +9,16 @@ use bat::assets::HighlightingAssets;
|
||||
use bat::assets_metadata::AssetsMetadata;
|
||||
use bat::error::*;
|
||||
|
||||
pub fn clear_assets(cache_dir: &Path) -> Result<()> {
|
||||
clear_asset(cache_dir.join("themes.bin"), "theme set cache")?;
|
||||
clear_asset(cache_dir.join("syntaxes.bin"), "syntax set cache")?;
|
||||
clear_asset(cache_dir.join("metadata.yaml"), "metadata file")?;
|
||||
Ok(())
|
||||
pub fn clear_assets(cache_dir: &Path) {
|
||||
clear_asset(cache_dir.join("themes.bin"), "theme set cache");
|
||||
clear_asset(cache_dir.join("syntaxes.bin"), "syntax set cache");
|
||||
clear_asset(cache_dir.join("metadata.yaml"), "metadata file");
|
||||
}
|
||||
|
||||
pub fn assets_from_cache_or_binary(
|
||||
use_custom_assets: bool,
|
||||
config_dir: &Path,
|
||||
cache_dir: &Path,
|
||||
) -> Result<HighlightingAssets> {
|
||||
if use_custom_assets {
|
||||
ensure_cache_built(config_dir, cache_dir);
|
||||
}
|
||||
|
||||
if let Some(metadata) = AssetsMetadata::load_from_folder(cache_dir)? {
|
||||
if !metadata.is_compatible_with(crate_version!()) {
|
||||
return Err(format!(
|
||||
@@ -49,60 +43,15 @@ pub fn assets_from_cache_or_binary(
|
||||
Ok(custom_assets.unwrap_or_else(HighlightingAssets::from_binary))
|
||||
}
|
||||
|
||||
fn clear_asset(path: PathBuf, description: &str) -> Result<()> {
|
||||
write!(io::stdout(), "Clearing {description} ... ")?;
|
||||
fn clear_asset(path: PathBuf, description: &str) {
|
||||
print!("Clearing {description} ... ");
|
||||
match fs::remove_file(&path) {
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => {
|
||||
writeln!(io::stdout(), "skipped (not present)")?;
|
||||
println!("skipped (not present)");
|
||||
}
|
||||
Err(err) => {
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
"could not remove the cache file {path:?}: {err}"
|
||||
)?;
|
||||
println!("could not remove the cache file {path:?}: {err}");
|
||||
}
|
||||
Ok(_) => writeln!(io::stdout(), "okay")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build the cache on first run when custom themes or syntaxes are present
|
||||
/// but no cache exists yet (see #4017). A failed build is not fatal: warn
|
||||
/// and fall back to the integrated assets.
|
||||
#[cfg(feature = "build-assets")]
|
||||
fn ensure_cache_built(config_dir: &Path, cache_dir: &Path) {
|
||||
if cache_exists(cache_dir) || !custom_sources_exist(config_dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
eprintln!("bat: custom themes or syntaxes found, building cache ...");
|
||||
if let Err(err) = bat::assets::build(config_dir, true, false, cache_dir, crate_version!()) {
|
||||
eprintln!("bat: automatic cache build failed ({err}), falling back to integrated assets.");
|
||||
Ok(_) => println!("okay"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "build-assets"))]
|
||||
fn ensure_cache_built(_config_dir: &Path, _cache_dir: &Path) {}
|
||||
|
||||
#[cfg(feature = "build-assets")]
|
||||
fn cache_exists(cache_dir: &Path) -> bool {
|
||||
cache_dir.join("themes.bin").is_file()
|
||||
&& cache_dir.join("syntaxes.bin").is_file()
|
||||
&& cache_dir.join("metadata.yaml").is_file()
|
||||
}
|
||||
|
||||
#[cfg(feature = "build-assets")]
|
||||
fn custom_sources_exist(config_dir: &Path) -> bool {
|
||||
dir_has_files(&config_dir.join("themes")) || dir_has_files(&config_dir.join("syntaxes"))
|
||||
}
|
||||
|
||||
#[cfg(feature = "build-assets")]
|
||||
fn dir_has_files(dir: &Path) -> bool {
|
||||
fs::read_dir(dir)
|
||||
.map(|entries| {
|
||||
entries
|
||||
.filter_map(|entry| entry.ok())
|
||||
.any(|entry| entry.path().is_file())
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
@@ -65,7 +65,6 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("nonprintable-notation")
|
||||
.long("nonprintable-notation")
|
||||
.overrides_with("nonprintable-notation")
|
||||
.action(ArgAction::Set)
|
||||
.default_value("unicode")
|
||||
.value_parser(["unicode", "caret"])
|
||||
@@ -82,7 +81,6 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("binary")
|
||||
.long("binary")
|
||||
.overrides_with("binary")
|
||||
.action(ArgAction::Set)
|
||||
.default_value("no-printing")
|
||||
.value_parser(["no-printing", "as-text"])
|
||||
@@ -127,7 +125,6 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("fallback-syntax")
|
||||
.long("fallback-syntax")
|
||||
.overrides_with("fallback-syntax")
|
||||
.visible_alias("fallback-language")
|
||||
.help("Set a fallback language for undetected syntaxes.")
|
||||
.long_help(
|
||||
@@ -320,7 +317,6 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("italic-text")
|
||||
.long("italic-text")
|
||||
.overrides_with("italic-text")
|
||||
.value_name("when")
|
||||
.value_parser(["always", "never"])
|
||||
.default_value("never")
|
||||
@@ -488,7 +484,6 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("squeeze-limit")
|
||||
.long("squeeze-limit")
|
||||
.overrides_with("squeeze-limit")
|
||||
.value_parser(|s: &str| s.parse::<usize>().map_err(|_| "Requires a non-negative number".to_owned()))
|
||||
.long_help("Set the maximum number of consecutive empty lines to be printed.")
|
||||
.hide_short_help(true)
|
||||
|
||||
+7
-15
@@ -32,13 +32,12 @@ pub fn config_file() -> PathBuf {
|
||||
pub fn generate_config_file() -> bat::error::Result<()> {
|
||||
let config_file = config_file();
|
||||
if config_file.is_file() {
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
println!(
|
||||
"A config file already exists at: {}",
|
||||
config_file.to_string_lossy()
|
||||
)?;
|
||||
);
|
||||
|
||||
write!(io::stdout(), "Overwrite? (y/N): ")?;
|
||||
print!("Overwrite? (y/N): ");
|
||||
io::stdout().flush()?;
|
||||
let mut decision = String::new();
|
||||
io::stdin().read_line(&mut decision)?;
|
||||
@@ -94,11 +93,10 @@ pub fn generate_config_file() -> bat::error::Result<()> {
|
||||
)
|
||||
})?;
|
||||
|
||||
writeln!(
|
||||
io::stdout(),
|
||||
println!(
|
||||
"Success! Config file written to {}",
|
||||
config_file.to_string_lossy()
|
||||
)?;
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -110,7 +108,7 @@ pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseEr
|
||||
let user_config = config_file();
|
||||
|
||||
if let Ok(c) = fs::read_to_string(&system_config) {
|
||||
config.push_str(strip_bom(&c));
|
||||
config.push_str(&c);
|
||||
config.push('\n');
|
||||
}
|
||||
|
||||
@@ -118,7 +116,7 @@ pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseEr
|
||||
// which can happen when BAT_CONFIG_DIR is set to e.g. "/etc/bat". See #3589.
|
||||
if !same_file(&system_config, &user_config) {
|
||||
if let Ok(c) = fs::read_to_string(&user_config) {
|
||||
config.push_str(strip_bom(&c));
|
||||
config.push_str(&c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,12 +134,6 @@ pub fn get_args_from_env_opts_var() -> Option<Result<Vec<OsString>, shell_words:
|
||||
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
|
||||
}
|
||||
|
||||
/// Editors on Windows (e.g. `Set-Content -Encoding UTF8` in Windows PowerShell)
|
||||
/// may prepend a UTF-8 byte order mark, which would otherwise end up in the first argument.
|
||||
fn strip_bom(content: &str) -> &str {
|
||||
content.strip_prefix('\u{feff}').unwrap_or(content)
|
||||
}
|
||||
|
||||
fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseError> {
|
||||
let args_per_line = content
|
||||
.split('\n')
|
||||
|
||||
+26
-38
@@ -74,9 +74,9 @@ fn run_cache_subcommand(
|
||||
#[cfg(feature = "build-assets")]
|
||||
build_assets(matches, config_dir, cache_dir)?;
|
||||
#[cfg(not(feature = "build-assets"))]
|
||||
writeln!(io::stdout(), "bat has been built without the 'build-assets' feature. The 'cache --build' option is not available.")?;
|
||||
println!("bat has been built without the 'build-assets' feature. The 'cache --build' option is not available.");
|
||||
} else if matches.get_flag("clear") {
|
||||
clear_assets(cache_dir)?;
|
||||
clear_assets(cache_dir);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -97,10 +97,10 @@ where
|
||||
map
|
||||
}
|
||||
|
||||
pub fn get_languages(config: &Config, config_dir: &Path, cache_dir: &Path) -> Result<String> {
|
||||
pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
let mut result: String = String::new();
|
||||
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, config_dir, cache_dir)?;
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
||||
let mut languages = assets
|
||||
.get_syntaxes()?
|
||||
.iter()
|
||||
@@ -205,7 +205,7 @@ pub fn list_themes(
|
||||
cache_dir: &Path,
|
||||
theme_options: ThemeOptions,
|
||||
) -> Result<()> {
|
||||
let assets = assets_from_cache_or_binary(cfg.use_custom_assets, config_dir, cache_dir)?;
|
||||
let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?;
|
||||
let mut config = cfg.clone();
|
||||
let mut style = HashSet::new();
|
||||
style.insert(StyleComponent::Plain);
|
||||
@@ -262,17 +262,13 @@ pub fn list_themes(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_terminal_title_to(new_terminal_title: String) -> Result<()> {
|
||||
fn set_terminal_title_to(new_terminal_title: String) {
|
||||
let osc_command_for_setting_terminal_title = "\x1b]0;";
|
||||
let osc_end_command = "\x07";
|
||||
// Prevent BEL/ESC/C1 bytes in the title from terminating or nesting the OSC.
|
||||
let safe_title = bat::sanitize_for_terminal(&new_terminal_title);
|
||||
write!(
|
||||
io::stdout(),
|
||||
"{osc_command_for_setting_terminal_title}{safe_title}{osc_end_command}"
|
||||
)?;
|
||||
io::stdout().flush()?;
|
||||
Ok(())
|
||||
print!("{osc_command_for_setting_terminal_title}{safe_title}{osc_end_command}");
|
||||
io::stdout().flush().unwrap();
|
||||
}
|
||||
|
||||
fn get_new_terminal_title(inputs: &Vec<Input>) -> String {
|
||||
@@ -286,22 +282,17 @@ fn get_new_terminal_title(inputs: &Vec<Input>) -> String {
|
||||
new_terminal_title
|
||||
}
|
||||
|
||||
fn run_controller(
|
||||
inputs: Vec<Input>,
|
||||
config: &Config,
|
||||
config_dir: &Path,
|
||||
cache_dir: &Path,
|
||||
) -> Result<bool> {
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, config_dir, cache_dir)?;
|
||||
fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Result<bool> {
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
||||
let controller = Controller::new(config, &assets);
|
||||
if config.paging_mode != PagingMode::Never && config.set_terminal_title {
|
||||
set_terminal_title_to(get_new_terminal_title(&inputs))?;
|
||||
set_terminal_title_to(get_new_terminal_title(&inputs));
|
||||
}
|
||||
controller.run(inputs, None)
|
||||
}
|
||||
|
||||
#[cfg(feature = "bugreport")]
|
||||
fn invoke_bugreport(app: &App, cache_dir: &Path) -> Result<()> {
|
||||
fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
use bugreport::{bugreport, collector::*, format::Markdown, report::ReportEntry};
|
||||
|
||||
struct ColorSchemeCollector;
|
||||
@@ -338,7 +329,6 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) -> Result<()> {
|
||||
.info(CommandLine::default())
|
||||
.info(EnvironmentVariables::list(&[
|
||||
"BAT_CACHE_PATH",
|
||||
"BAT_CONFIG_DIR",
|
||||
"BAT_CONFIG_PATH",
|
||||
"BAT_OPTS",
|
||||
"BAT_PAGER",
|
||||
@@ -380,8 +370,7 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) -> Result<()> {
|
||||
))
|
||||
};
|
||||
|
||||
writeln!(io::stdout(), "{}", report.format::<Markdown>())?;
|
||||
Ok(())
|
||||
report.print::<Markdown>();
|
||||
}
|
||||
|
||||
/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Ok(true)` on full success and
|
||||
@@ -393,22 +382,21 @@ fn run() -> Result<bool> {
|
||||
|
||||
if app.matches.get_flag("diagnostic") {
|
||||
#[cfg(feature = "bugreport")]
|
||||
invoke_bugreport(&app, cache_dir)?;
|
||||
invoke_bugreport(&app, cache_dir);
|
||||
#[cfg(not(feature = "bugreport"))]
|
||||
writeln!(io::stdout(), "bat has been built without the 'bugreport' feature. The '--diagnostic' option is not available.")?;
|
||||
println!("bat has been built without the 'bugreport' feature. The '--diagnostic' option is not available.");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
#[cfg(feature = "application")]
|
||||
if let Some(shell) = app.matches.get_one::<String>("completion") {
|
||||
let completion = match shell.as_str() {
|
||||
"bash" => completions::BASH_COMPLETION,
|
||||
"fish" => completions::FISH_COMPLETION,
|
||||
"ps1" => completions::PS1_COMPLETION,
|
||||
"zsh" => completions::ZSH_COMPLETION,
|
||||
match shell.as_str() {
|
||||
"bash" => println!("{}", completions::BASH_COMPLETION),
|
||||
"fish" => println!("{}", completions::FISH_COMPLETION),
|
||||
"ps1" => println!("{}", completions::PS1_COMPLETION),
|
||||
"zsh" => println!("{}", completions::ZSH_COMPLETION),
|
||||
_ => unreachable!("No completion for shell '{shell}' available."),
|
||||
};
|
||||
writeln!(io::stdout(), "{completion}")?;
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -429,7 +417,7 @@ fn run() -> Result<bool> {
|
||||
let inputs = vec![Input::ordinary_file("cache")];
|
||||
let config = app.config(&inputs)?;
|
||||
|
||||
run_controller(inputs, &config, config_dir, cache_dir)
|
||||
run_controller(inputs, &config, cache_dir)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -437,17 +425,17 @@ fn run() -> Result<bool> {
|
||||
let config = app.config(&inputs)?;
|
||||
|
||||
if app.matches.get_flag("list-languages") {
|
||||
let languages: String = get_languages(&config, config_dir, cache_dir)?;
|
||||
let languages: String = get_languages(&config, cache_dir)?;
|
||||
let inputs: Vec<Input> = vec![Input::from_reader(Box::new(languages.as_bytes()))];
|
||||
let mut plain_config = config.clone();
|
||||
plain_config.style_components =
|
||||
StyleComponents::new(StyleComponent::Plain.components(false));
|
||||
run_controller(inputs, &plain_config, config_dir, cache_dir)
|
||||
run_controller(inputs, &plain_config, cache_dir)
|
||||
} else if app.matches.get_flag("list-themes") {
|
||||
list_themes(&config, config_dir, cache_dir, app.theme_options())?;
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("config-file") {
|
||||
writeln!(io::stdout(), "{}", config_file().to_string_lossy())?;
|
||||
println!("{}", config_file().to_string_lossy());
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("generate-config-file") {
|
||||
generate_config_file()?;
|
||||
@@ -462,7 +450,7 @@ fn run() -> Result<bool> {
|
||||
writeln!(io::stdout(), "{}", bat::assets::get_acknowledgements())?;
|
||||
Ok(true)
|
||||
} else {
|
||||
run_controller(inputs, &config, config_dir, cache_dir)
|
||||
run_controller(inputs, &config, cache_dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -98,20 +98,20 @@ pub struct Config<'a> {
|
||||
/// cached assets) are not available, assets from the binary will be used instead.
|
||||
pub use_custom_assets: bool,
|
||||
|
||||
/// Whether or not to use $LESSOPEN if set
|
||||
// Whether or not to use $LESSOPEN if set
|
||||
#[cfg(feature = "lessopen")]
|
||||
pub use_lessopen: bool,
|
||||
|
||||
/// Whether or not to set terminal title when using a pager
|
||||
// Whether or not to set terminal title when using a pager
|
||||
pub set_terminal_title: bool,
|
||||
|
||||
/// The maximum number of consecutive empty lines to display
|
||||
pub squeeze_lines: Option<usize>,
|
||||
|
||||
/// Whether or not to strip ANSI escape codes from the input
|
||||
// Whether or not to strip ANSI escape codes from the input
|
||||
pub strip_ansi: StripAnsiMode,
|
||||
|
||||
/// Substitute terminal-active and spoofing-relevant bytes; implies strip_ansi.
|
||||
// Substitute terminal-active and spoofing-relevant bytes; implies strip_ansi.
|
||||
pub sanitize: StripAnsiMode,
|
||||
|
||||
/// Whether or not to produce no output when input is empty
|
||||
|
||||
+3
-17
@@ -18,8 +18,6 @@ use std::io::{self, BufRead, Write};
|
||||
use std::mem;
|
||||
|
||||
use clircle::{Clircle, Identifier};
|
||||
use content_inspector::ContentType;
|
||||
use encoding_rs::{UTF_16BE, UTF_16LE};
|
||||
|
||||
pub struct Controller<'a> {
|
||||
config: &'a Config<'a>,
|
||||
@@ -282,21 +280,9 @@ impl Controller<'_> {
|
||||
// line counter for empty lines (content-free lines that contain
|
||||
// only the line terminator).
|
||||
if self.config.number_nonblank
|
||||
&& match reader.content_type {
|
||||
Some(ContentType::UTF_16LE) => UTF_16LE
|
||||
.decode_with_bom_removal(¤t_line_buffer)
|
||||
.0
|
||||
.trim_end_matches(['\r', '\n'])
|
||||
.is_empty(),
|
||||
Some(ContentType::UTF_16BE) => UTF_16BE
|
||||
.decode_with_bom_removal(¤t_line_buffer)
|
||||
.0
|
||||
.trim_end_matches(['\r', '\n'])
|
||||
.is_empty(),
|
||||
_ => current_line_buffer
|
||||
.iter()
|
||||
.all(|&b| b == b'\r' || b == b'\n'),
|
||||
}
|
||||
&& current_line_buffer
|
||||
.iter()
|
||||
.all(|&b| b == b'\r' || b == b'\n')
|
||||
{
|
||||
buffered_lines
|
||||
.push_back((mem::take(&mut current_line_buffer), current_line_number));
|
||||
|
||||
+2
-13
@@ -53,17 +53,6 @@ impl From<String> for Error {
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Paint a `[bat error]`/`[bat warning]` style prefix, unless the user asked
|
||||
/// for no colors by setting the `NO_COLOR` environment variable.
|
||||
#[doc(hidden)]
|
||||
pub fn paint_prefix(color: nu_ansi_term::Color, prefix: &str) -> String {
|
||||
if std::env::var_os("NO_COLOR").is_some_and(|x| !x.is_empty()) {
|
||||
prefix.to_owned()
|
||||
} else {
|
||||
color.paint(prefix).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
||||
use nu_ansi_term::Color::Red;
|
||||
|
||||
@@ -75,7 +64,7 @@ pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
||||
writeln!(
|
||||
output,
|
||||
"{}: Error while parsing metadata.yaml file: {error}",
|
||||
paint_prefix(Red, "[bat error]"),
|
||||
Red.paint("[bat error]"),
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
@@ -83,7 +72,7 @@ pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
||||
writeln!(
|
||||
&mut std::io::stderr().lock(),
|
||||
"{}: {error}",
|
||||
paint_prefix(Red, "[bat error]"),
|
||||
Red.paint("[bat error]"),
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
|
||||
+1
-40
@@ -291,12 +291,7 @@ impl<'a> InputReader<'a> {
|
||||
|
||||
if content_type == Some(ContentType::UTF_16LE) {
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A)?;
|
||||
} else if content_type == Some(ContentType::UTF_16BE)
|
||||
// In UTF-16BE a newline is encoded as 0x00 0x0A, so `read_until(b'\n')` above
|
||||
// may already have read a complete first line. Only keep reading if it did not
|
||||
// (e.g. the 0x0A byte was part of another character such as U+4E0A).
|
||||
&& !(first_line.len() % 2 == 0 && first_line.ends_with(&[0x00, 0x0A]))
|
||||
{
|
||||
} else if content_type == Some(ContentType::UTF_16BE) {
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00)?;
|
||||
}
|
||||
|
||||
@@ -380,7 +375,6 @@ fn read_utf16_line<R: BufRead>(
|
||||
}
|
||||
buf.extend_from_slice(&temp);
|
||||
if buf.len() >= 2
|
||||
&& buf.len().is_multiple_of(2)
|
||||
&& buf[buf.len() - 2] == preceded_by_char
|
||||
&& buf[buf.len() - 1] == read_until_char
|
||||
{
|
||||
@@ -617,39 +611,6 @@ fn unbuffered_eof_handling() {
|
||||
assert!(buffer.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf16_newlines_are_code_unit_aligned() {
|
||||
let cases: &[&[&[u8]]] = &[
|
||||
&[b"\xFF\xFE\x85\x0A\x00\x25\x0A\x00", b"\x7A\x00"],
|
||||
&[
|
||||
b"\xFF\xFE\x73\x00\x0A\x00",
|
||||
b"\x85\x0A\x00\x25\x0A\x00",
|
||||
b"\x7A\x00",
|
||||
],
|
||||
&[
|
||||
b"\xFE\xFF\x4E\x0A\x00\x0A",
|
||||
b"\x25\x00\x0A\x85\x00\x0A",
|
||||
b"\x00\x7A",
|
||||
],
|
||||
];
|
||||
|
||||
for &lines in cases {
|
||||
let content = lines.concat();
|
||||
let mut reader = InputReader::new(&content[..]);
|
||||
assert_eq!(lines[0], &reader.first_line[..]);
|
||||
|
||||
for &line in lines {
|
||||
let mut buffer = vec![];
|
||||
assert!(reader.read_line(&mut buffer).unwrap());
|
||||
assert_eq!(line, &buffer[..]);
|
||||
}
|
||||
|
||||
let mut buffer = vec![];
|
||||
assert!(!reader.read_line(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf16le_issue3367() {
|
||||
let content = b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00\
|
||||
|
||||
+3
-3
@@ -355,13 +355,13 @@ fn test_parse_context_fail() {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum RangeCheckResult {
|
||||
/// Within one of the given ranges
|
||||
// Within one of the given ranges
|
||||
InRange,
|
||||
|
||||
/// Before the first range or within two ranges
|
||||
// Before the first range or within two ranges
|
||||
BeforeOrBetweenRanges,
|
||||
|
||||
/// Line number is outside of all ranges and larger than the last range.
|
||||
// Line number is outside of all ranges and larger than the last range.
|
||||
AfterLastRange,
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -1,10 +1,7 @@
|
||||
#[macro_export]
|
||||
macro_rules! bat_warning {
|
||||
($($arg:tt)*) => ({
|
||||
eprintln!(
|
||||
"{}: {}",
|
||||
$crate::error::paint_prefix(nu_ansi_term::Color::Yellow, "[bat warning]"),
|
||||
format!($($arg)*)
|
||||
);
|
||||
use nu_ansi_term::Color::Yellow;
|
||||
eprintln!("{}: {}", Yellow.paint("[bat warning]"), format!($($arg)*));
|
||||
})
|
||||
}
|
||||
+1
-81
@@ -108,7 +108,7 @@ pub(crate) fn get_pager(config_pager: Option<&str>) -> Result<Option<Pager>, Par
|
||||
_ => ("less", PagerSource::Default),
|
||||
};
|
||||
|
||||
let parts = split_command(cmd)?;
|
||||
let parts = shell_words::split(cmd)?;
|
||||
match parts.split_first() {
|
||||
Some((bin, args)) => {
|
||||
let kind = PagerKind::from_bin(bin);
|
||||
@@ -136,83 +136,3 @@ pub(crate) fn get_pager(config_pager: Option<&str>) -> Result<Option<Pager>, Par
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits a pager command into the program and its arguments.
|
||||
fn split_command(cmd: &str) -> Result<Vec<String>, ParseError> {
|
||||
if cfg!(windows) {
|
||||
split_command_windows(cmd)
|
||||
} else {
|
||||
shell_words::split(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `shell_words::split`, but `\` is not an escape character, since it is
|
||||
/// the path separator on Windows: `C:\tools\less.exe` must not become
|
||||
/// `C:toolsless.exe`. Single and double quotes still group words.
|
||||
fn split_command_windows(cmd: &str) -> Result<Vec<String>, ParseError> {
|
||||
let mut words = Vec::new();
|
||||
let mut word = String::new();
|
||||
let mut in_word = false;
|
||||
let mut quote = None;
|
||||
|
||||
for c in cmd.chars() {
|
||||
match quote {
|
||||
Some(q) if c == q => quote = None,
|
||||
Some(_) => word.push(c),
|
||||
None if c == '"' || c == '\'' => {
|
||||
quote = Some(c);
|
||||
in_word = true;
|
||||
}
|
||||
None if c.is_whitespace() => {
|
||||
if in_word {
|
||||
words.push(std::mem::take(&mut word));
|
||||
in_word = false;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
word.push(c);
|
||||
in_word = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if quote.is_some() {
|
||||
return Err(ParseError);
|
||||
}
|
||||
if in_word {
|
||||
words.push(word);
|
||||
}
|
||||
Ok(words)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::split_command_windows;
|
||||
|
||||
#[test]
|
||||
fn split_command_windows_keeps_backslashes() {
|
||||
let cases: &[(&str, &[&str])] = &[
|
||||
(r"C:\tools\less.exe", &[r"C:\tools\less.exe"]),
|
||||
(r"C:\tools\less.exe -R", &[r"C:\tools\less.exe", "-R"]),
|
||||
(
|
||||
r#""C:\Program Files\Less\less.exe" -R"#,
|
||||
&[r"C:\Program Files\Less\less.exe", "-R"],
|
||||
),
|
||||
(
|
||||
r"'C:\Program Files\Less\less.exe'",
|
||||
&[r"C:\Program Files\Less\less.exe"],
|
||||
),
|
||||
(r#"less --prompt="a b" """#, &["less", "--prompt=a b", ""]),
|
||||
(" less -R ", &["less", "-R"]),
|
||||
("", &[]),
|
||||
];
|
||||
for (cmd, expected) in cases {
|
||||
assert_eq!(split_command_windows(cmd).unwrap(), *expected, "{cmd}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_command_windows_rejects_unclosed_quote() {
|
||||
assert!(split_command_windows(r#""C:\tools\less.exe"#).is_err());
|
||||
}
|
||||
}
|
||||
@@ -302,21 +302,11 @@ pub fn strip_overstrike(line: &str, first_backspace: usize) -> String {
|
||||
output
|
||||
}
|
||||
|
||||
/// Specify when to strip ANSI escape sequences from the input.
|
||||
///
|
||||
/// Used for both the `--strip-ansi` and the `--sanitize` option, the latter
|
||||
/// implying the former with the same value.
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Default)]
|
||||
pub enum StripAnsiMode {
|
||||
/// Keep escape sequences in the output
|
||||
#[default]
|
||||
Never,
|
||||
|
||||
/// Strip escape sequences from the output
|
||||
Always,
|
||||
|
||||
/// Strip escape sequences unless the syntax highlighting language is plain
|
||||
/// text, in which case they may be part of what the input wants to display
|
||||
Auto,
|
||||
}
|
||||
|
||||
|
||||
+15
-25
@@ -16,7 +16,7 @@ use content_inspector::ContentType;
|
||||
use encoding_rs::{UTF_16BE, UTF_16LE};
|
||||
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
|
||||
use crate::config::Config;
|
||||
@@ -50,14 +50,6 @@ fn char_width(c: char) -> usize {
|
||||
c.width().unwrap_or(if c.is_control() { 2 } else { 0 })
|
||||
}
|
||||
|
||||
fn grapheme_width(grapheme: &str) -> usize {
|
||||
if grapheme.chars().any(char::is_control) {
|
||||
grapheme.chars().map(char_width).sum()
|
||||
} else {
|
||||
grapheme.width()
|
||||
}
|
||||
}
|
||||
|
||||
const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI {
|
||||
raw_sequence: "\x1B[4m",
|
||||
parameters: "4",
|
||||
@@ -728,15 +720,13 @@ impl Printer for InteractivePrinter<'_> {
|
||||
let mut cursor_total: usize = 0;
|
||||
let mut panel_wrap: Option<String> = None;
|
||||
|
||||
// Line highlighting. It is done purely with escape sequences (background
|
||||
// color or underline), so it must be skipped when colors are disabled.
|
||||
let highlight_this_line = self.config.colored_output
|
||||
&& self
|
||||
.config
|
||||
.highlighted_lines
|
||||
.0
|
||||
.check(line_number, max_buffered_line_number)
|
||||
== RangeCheckResult::InRange;
|
||||
// Line highlighting
|
||||
let highlight_this_line = self
|
||||
.config
|
||||
.highlighted_lines
|
||||
.0
|
||||
.check(line_number, max_buffered_line_number)
|
||||
== RangeCheckResult::InRange;
|
||||
|
||||
if highlight_this_line && self.config.theme == "ansi" {
|
||||
self.ansi_style.update(ANSI_UNDERLINE_ENABLE);
|
||||
@@ -836,7 +826,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
let text = self
|
||||
.preprocess(text.trim_end_matches(['\r', '\n']), &mut cursor_total);
|
||||
|
||||
let mut max_width = cursor_max.saturating_sub(cursor);
|
||||
let mut max_width = cursor_max - cursor;
|
||||
|
||||
// line buffer (avoid calling write! for every character)
|
||||
let mut line_buf = String::with_capacity(max_width * 4);
|
||||
@@ -849,13 +839,13 @@ impl Printer for InteractivePrinter<'_> {
|
||||
// For word wrapping, track last whitespace position.
|
||||
let mut last_ws_idx: Option<usize> = None;
|
||||
|
||||
for grapheme in text.graphemes(true) {
|
||||
for c in text.chars() {
|
||||
// calculate the displayed width for next character
|
||||
let cw = grapheme_width(grapheme);
|
||||
let cw = char_width(c);
|
||||
current_width += cw;
|
||||
|
||||
// Track whitespace positions for word wrapping.
|
||||
if word_wrap && grapheme.starts_with(char::is_whitespace) {
|
||||
if word_wrap && c.is_whitespace() {
|
||||
last_ws_idx = Some(line_buf.len());
|
||||
}
|
||||
|
||||
@@ -927,7 +917,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
// Word wrap: carry remainder to next line.
|
||||
let remainder = line_buf[rs..].to_string();
|
||||
let rem_width: usize =
|
||||
remainder.graphemes(true).map(grapheme_width).sum();
|
||||
remainder.chars().map(char_width).sum();
|
||||
line_buf.clear();
|
||||
line_buf.push_str(&remainder);
|
||||
current_width = rem_width + cw;
|
||||
@@ -938,7 +928,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
last_ws_idx = None;
|
||||
}
|
||||
|
||||
line_buf.push_str(grapheme);
|
||||
line_buf.push(c);
|
||||
}
|
||||
|
||||
// flush the buffer
|
||||
@@ -975,7 +965,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
write!(
|
||||
handle,
|
||||
"{}",
|
||||
ansi_style.paint(" ".repeat(cursor_max.saturating_sub(cursor)))
|
||||
ansi_style.paint(" ".repeat(cursor_max - cursor))
|
||||
)?;
|
||||
}
|
||||
writeln!(handle)?;
|
||||
|
||||
+2
-122
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
path::Path,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
@@ -24,19 +24,6 @@ pub(crate) enum Case {
|
||||
Insensitive,
|
||||
}
|
||||
|
||||
/// On Windows, `PathAbs` and `fs::canonicalize` return verbatim paths (`\\?\C:\dir\file`,
|
||||
/// `\\?\UNC\server\share\file`), which a pattern such as `C:/dir/*` would not match.
|
||||
fn without_verbatim_prefix(path: &Path) -> Option<PathBuf> {
|
||||
if !cfg!(windows) {
|
||||
return None;
|
||||
}
|
||||
let path = path.to_str()?;
|
||||
match path.strip_prefix(r"\\?\UNC\") {
|
||||
Some(rest) => Some(format!(r"\\{rest}").into()),
|
||||
None => path.strip_prefix(r"\\?\").map(PathBuf::from),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_glob_matcher(from: &str, case: Case) -> Result<GlobMatcher> {
|
||||
let matcher = GlobBuilder::new(from)
|
||||
.case_insensitive(matches!(case, Case::Insensitive))
|
||||
@@ -175,14 +162,9 @@ impl<'a> SyntaxMapping<'a> {
|
||||
pub fn get_syntax_for(&self, path: impl AsRef<Path>) -> Option<MappingTarget<'a>> {
|
||||
// Try matching on the file name as-is.
|
||||
let candidate = Candidate::new(&path);
|
||||
let simplified_path = without_verbatim_prefix(path.as_ref());
|
||||
let candidate_simplified = simplified_path.as_ref().map(Candidate::new);
|
||||
let candidate_filename = path.as_ref().file_name().map(Candidate::new);
|
||||
for (glob, syntax) in self.all_mappings() {
|
||||
if glob.is_match_candidate(&candidate)
|
||||
|| candidate_simplified
|
||||
.as_ref()
|
||||
.is_some_and(|simplified| glob.is_match_candidate(simplified))
|
||||
|| candidate_filename
|
||||
.as_ref()
|
||||
.is_some_and(|filename| glob.is_match_candidate(filename))
|
||||
@@ -194,10 +176,7 @@ impl<'a> SyntaxMapping<'a> {
|
||||
let file_name = path.as_ref().file_name()?;
|
||||
self.ignored_suffixes
|
||||
.try_with_stripped_suffix(file_name, |stripped_file_name| {
|
||||
if Path::new(stripped_file_name).file_name().is_none() {
|
||||
return Ok(self.get_syntax_for(stripped_file_name));
|
||||
}
|
||||
Ok(self.get_syntax_for(path.as_ref().with_file_name(stripped_file_name)))
|
||||
Ok(self.get_syntax_for(stripped_file_name))
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
@@ -267,105 +246,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn custom_mappings_match_verbatim_paths() {
|
||||
let mut map = SyntaxMapping::new();
|
||||
map.insert("C:/dir/*.myconf", MappingTarget::MapTo("INI"))
|
||||
.unwrap();
|
||||
map.insert(r"\\server\share\*.myconf", MappingTarget::MapTo("TOML"))
|
||||
.unwrap();
|
||||
map.insert(r"\\?\C:\literal\*.myconf", MappingTarget::MapTo("JSON"))
|
||||
.unwrap();
|
||||
|
||||
for (path, expected) in [
|
||||
(r"C:\dir\file.myconf", Some(MappingTarget::MapTo("INI"))),
|
||||
(r"\\?\C:\dir\file.myconf", Some(MappingTarget::MapTo("INI"))),
|
||||
(r"\\?\D:\dir\file.myconf", None),
|
||||
(
|
||||
r"\\?\C:\literal\file.myconf",
|
||||
Some(MappingTarget::MapTo("JSON")),
|
||||
),
|
||||
(
|
||||
r"\\?\UNC\server\share\file.myconf",
|
||||
Some(MappingTarget::MapTo("TOML")),
|
||||
),
|
||||
] {
|
||||
assert_eq!(map.get_syntax_for(path), expected, "{path}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_mappings_with_ignored_suffix_preserve_paths() {
|
||||
for (pattern, parent) in [
|
||||
("/path/to/file.demo", "/path/to"),
|
||||
("/path/to/*.demo", "/path/to"),
|
||||
("path/to/*.demo", "path/to"),
|
||||
] {
|
||||
let mut map = SyntaxMapping::new();
|
||||
map.insert(pattern, MappingTarget::MapTo("JSON")).unwrap();
|
||||
map.insert_ignored_suffix(".custom");
|
||||
|
||||
for suffix in ["", ".bak", ".bak.old", ".custom.custom"] {
|
||||
let path = Path::new(parent).join(format!("file.demo{suffix}"));
|
||||
assert_eq!(
|
||||
map.get_syntax_for(&path),
|
||||
Some(MappingTarget::MapTo("JSON")),
|
||||
"{pattern}: {}",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
assert_eq!(map.get_syntax_for("/path/elsewhere/file.demo.bak"), None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_mappings_with_ignored_suffix_preserve_precedence() {
|
||||
for (first, second) in [("/path/to/*.demo", "*.demo"), ("*.demo", "/path/to/*.demo")] {
|
||||
let mut map = SyntaxMapping::new();
|
||||
map.insert(first, MappingTarget::MapTo("first")).unwrap();
|
||||
map.insert(second, MappingTarget::MapTo("second")).unwrap();
|
||||
assert_eq!(
|
||||
map.get_syntax_for("/path/to/file.demo.bak"),
|
||||
Some(MappingTarget::MapTo("first"))
|
||||
);
|
||||
|
||||
map.insert("*.bak", MappingTarget::MapTo("backup")).unwrap();
|
||||
assert_eq!(
|
||||
map.get_syntax_for("/path/to/file.demo.bak"),
|
||||
Some(MappingTarget::MapTo("backup"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_mappings_with_empty_stripped_filename() {
|
||||
let mut map = SyntaxMapping::new();
|
||||
map.insert("to", MappingTarget::MapTo("parent")).unwrap();
|
||||
map.insert_ignored_suffix(".custom");
|
||||
|
||||
for name in [
|
||||
"~", ".bak", ".custom", "~.bak", ".~", "..bak", "..custom", "...bak",
|
||||
] {
|
||||
assert_eq!(map.get_syntax_for(Path::new("/path/to").join(name)), None);
|
||||
}
|
||||
|
||||
map.insert("", MappingTarget::MapTo("empty")).unwrap();
|
||||
assert_eq!(
|
||||
map.get_syntax_for("/path/to/~.bak"),
|
||||
Some(MappingTarget::MapTo("empty"))
|
||||
);
|
||||
|
||||
for (pattern, name) in [(".", ".~"), (".", "..bak"), ("..", "...bak")] {
|
||||
let mut map = SyntaxMapping::new();
|
||||
map.insert(pattern, MappingTarget::MapTo("dot")).unwrap();
|
||||
assert_eq!(
|
||||
map.get_syntax_for(Path::new("/path/to").join(name)),
|
||||
Some(MappingTarget::MapTo("dot"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_mappings_override_builtin() {
|
||||
let mut map = SyntaxMapping::new();
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# kubectl's config file has no extension. The format is YAML.
|
||||
# https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
|
||||
[mappings]
|
||||
"YAML" = ["**/.kube/config"]
|
||||
@@ -1,6 +1,5 @@
|
||||
# see `man quadlet`
|
||||
[mappings]
|
||||
"INI" = [
|
||||
"*.quadlets",
|
||||
"**/containers/systemd/**/*.{container,volume,network,kube,image,build,pod,artifact}",
|
||||
]
|
||||
@@ -39,9 +39,7 @@ impl Default for IgnoredSuffixes<'_> {
|
||||
|
||||
impl<'a> IgnoredSuffixes<'a> {
|
||||
pub fn add_suffix(&mut self, suffix: &'a str) {
|
||||
if !suffix.is_empty() {
|
||||
self.values.push(suffix)
|
||||
}
|
||||
self.values.push(suffix)
|
||||
}
|
||||
|
||||
pub fn strip_suffix(&self, file_name: &'a str) -> Option<&'a str> {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
pub enum WrappingMode {
|
||||
Character,
|
||||
Word,
|
||||
/// The bool specifies whether wrapping has been explicitly disabled by the user via --wrap=never
|
||||
// The bool specifies whether wrapping has been explicitly disabled by the user via --wrap=never
|
||||
NoWrapping(bool),
|
||||
}
|
||||
|
||||
|
||||
+11
-864
File diff suppressed because it is too large.
Load diff
-184
@@ -1,184 +0,0 @@
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Package example demonstrates CUE syntax.[0m
|
||||
[38;2;249;38;114mpackage[0m[38;2;248;248;242m [0m[38;2;166;226;46mexample[0m
|
||||
|
||||
[38;2;249;38;114mimport[0m[38;2;248;248;242m [0m[38;2;248;248;242m([0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mstrings[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mlist[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;166;226;46myamlpkg[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mencoding/yaml[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m)[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Definitions and constraints[0m
|
||||
[38;2;255;255;255m#Port[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint[0m[38;2;248;248;242m [0m[38;2;249;38;114m&[0m[38;2;248;248;242m [0m[38;2;249;38;114m>[0m[38;2;190;132;255m0[0m[38;2;248;248;242m [0m[38;2;249;38;114m&[0m[38;2;248;248;242m [0m[38;2;249;38;114m<=[0m[38;2;190;132;255m65535[0m
|
||||
|
||||
[38;2;255;255;255m#Service[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mname[0m[38;2;249;38;114m![0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m[38;2;248;248;242m [0m[38;2;249;38;114m&[0m[38;2;248;248;242m [0m[38;2;249;38;114m=~[0m[38;2;248;248;242m"[0m[38;2;230;219;116m^[a-z][a-z0-9-]*$[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mimage[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mreplicas[0m[38;2;248;248;242m?[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46muint[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;190;132;255m1[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mports[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;248;248;242m...[0m[38;2;255;255;255m#Port[0m[38;2;248;248;242m][0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255menv[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[3;38;2;166;226;46mstring[0m[38;2;248;248;242m][0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mlabels[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mapp[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mname[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m...[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255m_hidden[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255mtrue[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255m#nested[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mbool[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Concrete values[0m
|
||||
[38;2;255;255;255mservices[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;255;255;255mName[0m[38;2;248;248;242m=[0m[3;38;2;166;226;46mstring[0m[38;2;248;248;242m][0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255m#Service[0m[38;2;248;248;242m [0m[38;2;249;38;114m&[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m[38;2;255;255;255mname[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mName[0m[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255mservices[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mfrontend[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mimage[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mnginx:1.25[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mreplicas[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m3[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mports[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;190;132;255m80[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m443[0m[38;2;248;248;242m][0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255menv[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mLOG_LEVEL[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116minfo[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mTIMEOUT[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m30s[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255mservices[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mbackend[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mimage[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mregistry.example.com/backend:[0m[38;2;230;219;116m\([0m[38;2;255;255;255mversion[0m[38;2;230;219;116m)[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mports[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;190;132;255m8080[0m[38;2;248;248;242m][0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255menv[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mDATABASE_URL[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mpostgres://db:5432/app[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255mversion[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mv1.2.3[0m[38;2;248;248;242m"[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Numbers[0m
|
||||
[38;2;255;255;255mnumbers[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mdecimal[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1_000_000[0m
|
||||
[38;2;248;248;242m [0m[3;38;2;166;226;46mfloat[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m3.14159[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mexponent[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m6.022e23[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mhex[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m0xFF_FF[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255moctal[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m0o755[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mbinary[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m0b1010_1010[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mmultiplier[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1.5Gi[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mkilo[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m4K[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Strings and bytes[0m
|
||||
[38;2;255;255;255mstrs[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255msimple[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mhello, world[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mescaped[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mtab[0m[38;2;190;132;255m\t[0m[38;2;230;219;116mnewline[0m[38;2;190;132;255m\n[0m[38;2;230;219;116municode[0m[38;2;190;132;255m\u00e9[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[3;38;2;166;226;46mbytes[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m'[0m[38;2;230;219;116mraw bytes [0m[38;2;190;132;255m\x00[0m[38;2;190;132;255m\xff[0m[38;2;248;248;242m'[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mraw[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m#"[0m[38;2;230;219;116mno \(interpolation) here[0m[38;2;248;248;242m"#[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mmultiline[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"""[0m
|
||||
[38;2;230;219;116m multiple[0m
|
||||
[38;2;230;219;116m lines with [0m[38;2;230;219;116m\([0m[38;2;255;255;255mversion[0m[38;2;230;219;116m)[0m
|
||||
[38;2;230;219;116m [0m[38;2;248;248;242m"""[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mmultiBytes[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m'''[0m
|
||||
[38;2;230;219;116m byte[0m
|
||||
[38;2;230;219;116m lines[0m
|
||||
[38;2;230;219;116m [0m[38;2;248;248;242m'''[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Builtin types and values[0m
|
||||
[38;2;255;255;255mtypes[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mn[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255mnull[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mb[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mbool[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;190;132;255mfalse[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mi[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint8[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint16[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint32[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint64[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mf[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mfloat32[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mfloat64[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255ms[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255my[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mbytes[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mr[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mrune[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mt[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m_[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mx[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mnumber[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Bottom (error) value[0m
|
||||
[38;2;255;255;255mbottom[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m_|_[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Operators and builtins[0m
|
||||
[38;2;255;255;255mops[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255msum[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m [0m[38;2;249;38;114m+[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;249;38;114m*[0m[38;2;190;132;255m3[0m[38;2;248;248;242m [0m[38;2;249;38;114m-[0m[38;2;248;248;242m [0m[38;2;190;132;255m4[0m[38;2;249;38;114m/[0m[38;2;190;132;255m2[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mdivided[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mdiv[0m[38;2;248;248;242m([0m[38;2;190;132;255m7[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mmodulo[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mmod[0m[38;2;248;248;242m([0m[38;2;190;132;255m7[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mquotient[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mquo[0m[38;2;248;248;242m([0m[38;2;249;38;114m-[0m[38;2;190;132;255m7[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mrest[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mrem[0m[38;2;248;248;242m([0m[38;2;249;38;114m-[0m[38;2;190;132;255m7[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255meq[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m [0m[38;2;249;38;114m==[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mne[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116ma[0m[38;2;248;248;242m"[0m[38;2;248;248;242m [0m[38;2;249;38;114m!=[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mb[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mboth[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255mtrue[0m[38;2;248;248;242m [0m[38;2;249;38;114m&&[0m[38;2;248;248;242m [0m[38;2;190;132;255mfalse[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255meither[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255mtrue[0m[38;2;248;248;242m [0m[38;2;249;38;114m||[0m[38;2;248;248;242m [0m[38;2;190;132;255mfalse[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mnot[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;249;38;114m![0m[38;2;190;132;255mtrue[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mmatch[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mabc[0m[38;2;248;248;242m"[0m[38;2;248;248;242m [0m[38;2;249;38;114m=~[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m^a[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mnomatch[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mabc[0m[38;2;248;248;242m"[0m[38;2;248;248;242m [0m[38;2;249;38;114m!~[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m^z[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mlength[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mlen[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[38;2;190;132;255m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m3[0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mclosed[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mclose[0m[38;2;248;248;242m([0m[38;2;248;248;242m{[0m[38;2;255;255;255ma[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m}[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mupper[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242mstrings[0m[38;2;248;248;242m.[0m[38;2;102;217;239mToUpper[0m[38;2;248;248;242m([0m[38;2;248;248;242m"[0m[38;2;230;219;116mcue[0m[38;2;248;248;242m"[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255msorted[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242mlist[0m[38;2;248;248;242m.[0m[38;2;102;217;239mSort[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[38;2;190;132;255m3[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m][0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mlist[0m[38;2;248;248;242m.[0m[38;2;255;255;255mAscending[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mdisj[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mor[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[38;2;190;132;255m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m3[0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mconj[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mand[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[3;38;2;166;226;46mint[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;249;38;114m>[0m[38;2;190;132;255m0[0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255masYAML[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242myamlpkg[0m[38;2;248;248;242m.[0m[38;2;102;217;239mMarshal[0m[38;2;248;248;242m([0m[38;2;248;248;242m{[0m[38;2;255;255;255ma[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m}[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Nested calls, grouping and interpolated calls[0m
|
||||
[38;2;255;255;255mcalls[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mallPorts[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242mlist[0m[38;2;248;248;242m.[0m[38;2;102;217;239mConcat[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;190;132;255m22[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m25[0m[38;2;248;248;242m][0m[38;2;248;248;242m,[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242mlist[0m[38;2;248;248;242m.[0m[38;2;102;217;239mConcat[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[38;2;249;38;114mfor[0m[38;2;248;248;242m [0m[38;2;255;255;255m_[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255ms[0m[38;2;248;248;242m [0m[38;2;249;38;114min[0m[38;2;248;248;242m [0m[38;2;255;255;255mservices[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m[38;2;255;255;255ms[0m[38;2;248;248;242m.[0m[38;2;255;255;255mports[0m[38;2;248;248;242m}[0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m[38;2;248;248;242m,[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mnested[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mlen[0m[38;2;248;248;242m([0m[38;2;248;248;242mstrings[0m[38;2;248;248;242m.[0m[38;2;102;217;239mSplit[0m[38;2;248;248;242m([0m[38;2;248;248;242m"[0m[38;2;230;219;116ma,b[0m[38;2;248;248;242m"[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m,[0m[38;2;248;248;242m"[0m[38;2;248;248;242m)[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mgrouped[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m([0m[38;2;248;248;242m([0m[38;2;190;132;255m1[0m[38;2;248;248;242m [0m[38;2;249;38;114m+[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m)[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;248;248;242m [0m[38;2;190;132;255m3[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255minterp[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mx-[0m[38;2;230;219;116m\([0m[38;2;230;219;116mstrings[0m[38;2;230;219;116m.[0m[38;2;102;217;239mToUpper[0m[38;2;230;219;116m([0m[38;2;230;219;116m"[0m[38;2;230;219;116my[0m[38;2;230;219;116m"[0m[38;2;230;219;116m)[0m[38;2;230;219;116m)[0m[38;2;230;219;116m-[0m[38;2;230;219;116m\([0m[38;2;102;217;239mlen[0m[38;2;230;219;116m([0m[38;2;230;219;116m[[0m[38;2;190;132;255m1[0m[38;2;230;219;116m,[0m[38;2;230;219;116m [0m[38;2;190;132;255m2[0m[38;2;230;219;116m][0m[38;2;230;219;116m)[0m[38;2;230;219;116m)[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Comprehensions[0m
|
||||
[38;2;249;38;114mlet[0m[38;2;248;248;242m [0m[38;2;255;255;255mprefix[0m[38;2;248;248;242m [0m[38;2;248;248;242m=[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116msvc-[0m[38;2;248;248;242m"[0m
|
||||
|
||||
[38;2;255;255;255mserviceNames[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;249;38;114mfor[0m[38;2;248;248;242m [0m[38;2;255;255;255mk[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mv[0m[38;2;248;248;242m [0m[38;2;249;38;114min[0m[38;2;248;248;242m [0m[38;2;255;255;255mservices[0m[38;2;248;248;242m [0m[38;2;249;38;114mif[0m[38;2;248;248;242m [0m[38;2;255;255;255mv[0m[38;2;248;248;242m.[0m[38;2;255;255;255mreplicas[0m[38;2;248;248;242m [0m[38;2;249;38;114m>[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m[38;2;255;255;255mprefix[0m[38;2;248;248;242m [0m[38;2;249;38;114m+[0m[38;2;248;248;242m [0m[38;2;255;255;255mk[0m[38;2;248;248;242m}[0m[38;2;248;248;242m][0m
|
||||
|
||||
[38;2;255;255;255mportMap[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;249;38;114mfor[0m[38;2;248;248;242m [0m[38;2;255;255;255mname[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255msvc[0m[38;2;248;248;242m [0m[38;2;249;38;114min[0m[38;2;248;248;242m [0m[38;2;255;255;255mservices[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;249;38;114mfor[0m[38;2;248;248;242m [0m[38;2;255;255;255mi[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mp[0m[38;2;248;248;242m [0m[38;2;249;38;114min[0m[38;2;248;248;242m [0m[38;2;255;255;255msvc[0m[38;2;248;248;242m.[0m[38;2;255;255;255mports[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m\([0m[38;2;255;255;255mname[0m[38;2;230;219;116m)[0m[38;2;230;219;116m-[0m[38;2;230;219;116m\([0m[38;2;255;255;255mi[0m[38;2;230;219;116m)[0m[38;2;248;248;242m"[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mp[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255mbyPort[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;249;38;114mfor[0m[38;2;248;248;242m [0m[38;2;255;255;255mname[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255msvc[0m[38;2;248;248;242m [0m[38;2;249;38;114min[0m[38;2;248;248;242m [0m[38;2;255;255;255mservices[0m
|
||||
[38;2;248;248;242m [0m[38;2;249;38;114mif[0m[38;2;248;248;242m [0m[38;2;102;217;239mlen[0m[38;2;248;248;242m([0m[38;2;255;255;255msvc[0m[38;2;248;248;242m.[0m[38;2;255;255;255mports[0m[38;2;248;248;242m)[0m[38;2;248;248;242m [0m[38;2;249;38;114m>[0m[38;2;248;248;242m [0m[38;2;190;132;255m0[0m
|
||||
[38;2;248;248;242m [0m[38;2;249;38;114mlet[0m[38;2;248;248;242m [0m[38;2;255;255;255mfirst[0m[38;2;248;248;242m [0m[38;2;248;248;242m=[0m[38;2;248;248;242m [0m[38;2;255;255;255msvc[0m[38;2;248;248;242m.[0m[38;2;255;255;255mports[0m[38;2;248;248;242m[[0m[38;2;190;132;255m0[0m[38;2;248;248;242m][0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m\([0m[38;2;255;255;255mfirst[0m[38;2;230;219;116m)[0m[38;2;248;248;242m"[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mname[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m([0m[38;2;255;255;255mname[0m[38;2;248;248;242m [0m[38;2;249;38;114m+[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116m-image[0m[38;2;248;248;242m"[0m[38;2;248;248;242m)[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255msvc[0m[38;2;248;248;242m.[0m[38;2;255;255;255mimage[0m
|
||||
[38;2;248;248;242m [0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;249;38;114mif[0m[38;2;248;248;242m [0m[38;2;255;255;255mversion[0m[38;2;248;248;242m [0m[38;2;249;38;114m!=[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;248;248;242m"[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mhasVersion[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255mtrue[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Aliases, optional and required fields, pattern constraints[0m
|
||||
[38;2;255;255;255mX[0m[38;2;248;248;242m=[0m[38;2;255;255;255mouter[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255minner[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mref[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255mX[0m[38;2;248;248;242m.[0m[38;2;255;255;255minner[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255moptional[0m[38;2;248;248;242m?[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m
|
||||
[38;2;255;255;255mrequired[0m[38;2;249;38;114m![0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint[0m
|
||||
[38;2;248;248;242m[[0m[38;2;249;38;114m=~[0m[38;2;248;248;242m"[0m[38;2;230;219;116m^x-[0m[38;2;248;248;242m"[0m[38;2;248;248;242m][0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mstring[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Attributes[0m
|
||||
[38;2;255;255;255mconfig[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mport[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mint[0m[38;2;248;248;242m [0m[38;2;248;248;242m@[0m[38;2;248;248;242mtag[0m[38;2;248;248;242m([0m[38;2;230;219;116mport[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mtype[0m[38;2;248;248;242m=[0m[38;2;230;219;116mint[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mdebug[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mbool[0m[38;2;248;248;242m [0m[38;2;248;248;242m@[0m[38;2;248;248;242mjson[0m[38;2;248;248;242m([0m[38;2;248;248;242m"[0m[38;2;230;219;116m,omitempty[0m[38;2;248;248;242m"[0m[38;2;248;248;242m)[0m[38;2;248;248;242m [0m[38;2;248;248;242m@[0m[38;2;248;248;242myaml[0m[38;2;248;248;242m([0m[38;2;248;248;242m"[0m[38;2;230;219;116mdebug[0m[38;2;248;248;242m"[0m[38;2;248;248;242m)[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Embedding and default values[0m
|
||||
[38;2;255;255;255m#Base[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mkind[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;248;248;242m"[0m[38;2;230;219;116mbase[0m[38;2;248;248;242m"[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mderived[0m[38;2;248;248;242m"[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255mderived[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;255;255;255m#Base[0m[38;2;248;248;242m [0m[38;2;249;38;114m&[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m[38;2;255;255;255mkind[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m"[0m[38;2;230;219;116mderived[0m[38;2;248;248;242m"[0m[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;255;255;255m#Limits[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mcpu[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m{[0m[38;2;255;255;255mmin[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mnumber[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mmax[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[3;38;2;166;226;46mnumber[0m[38;2;248;248;242m}[0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;248;248;242m{[0m[38;2;255;255;255mmin[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m0[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;255;255;255mmax[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;190;132;255m1[0m[38;2;248;248;242m}[0m
|
||||
[38;2;248;248;242m [0m[38;2;255;255;255mtags[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;248;248;242m...[0m[3;38;2;166;226;46mstring[0m[38;2;248;248;242m][0m[38;2;248;248;242m [0m[38;2;249;38;114m|[0m[38;2;248;248;242m [0m[38;2;249;38;114m*[0m[38;2;248;248;242m[[0m[38;2;248;248;242m][0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;117;113;94m//[0m[38;2;117;113;94m Lists[0m
|
||||
[38;2;255;255;255memptyList[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;248;248;242m][0m
|
||||
[38;2;255;255;255mopenList[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;190;132;255m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;248;248;242m...[0m[38;2;248;248;242m][0m
|
||||
[38;2;255;255;255mtypedList[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;248;248;242m...[0m[3;38;2;166;226;46mstring[0m[38;2;248;248;242m][0m
|
||||
[38;2;255;255;255mnestedList[0m[38;2;248;248;242m:[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;248;248;242m[[0m[38;2;190;132;255m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m2[0m[38;2;248;248;242m][0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;248;248;242m[[0m[38;2;190;132;255m3[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;190;132;255m4[0m[38;2;248;248;242m][0m[38;2;248;248;242m][0m
|
||||
@@ -1,5 +0,0 @@
|
||||
[38;2;248;248;242m{[0m[38;2;255;255;255ma[0m
|
||||
[38;2;248;248;242m [0m[38;2;117;113;94m/*[0m[38;2;117;113;94m comment [0m[38;2;117;113;94m*/[0m
|
||||
[38;2;248;248;242m}[0m
|
||||
|
||||
[38;2;248;248;242m{[0m[38;2;255;255;255ma[0m[38;2;248;248;242m [0m[38;2;117;113;94m/*[0m[38;2;117;113;94m comment [0m[38;2;117;113;94m*/[0m[38;2;248;248;242m}[0m
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
// Package example demonstrates CUE syntax.
|
||||
package example
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"list"
|
||||
yamlpkg "encoding/yaml"
|
||||
)
|
||||
|
||||
// Definitions and constraints
|
||||
#Port: int & >0 & <=65535
|
||||
|
||||
#Service: {
|
||||
name!: string & =~"^[a-z][a-z0-9-]*$"
|
||||
image: string
|
||||
replicas?: uint | *1
|
||||
ports: [...#Port]
|
||||
env: [string]: string
|
||||
labels: {
|
||||
app: name
|
||||
...
|
||||
}
|
||||
_hidden: true
|
||||
#nested: bool
|
||||
}
|
||||
|
||||
// Concrete values
|
||||
services: [Name=string]: #Service & {name: Name}
|
||||
|
||||
services: frontend: {
|
||||
image: "nginx:1.25"
|
||||
replicas: 3
|
||||
ports: [80, 443]
|
||||
env: {
|
||||
LOG_LEVEL: "info"
|
||||
TIMEOUT: "30s"
|
||||
}
|
||||
}
|
||||
|
||||
services: backend: {
|
||||
image: "registry.example.com/backend:\(version)"
|
||||
ports: [8080]
|
||||
env: DATABASE_URL: "postgres://db:5432/app"
|
||||
}
|
||||
|
||||
version: "v1.2.3"
|
||||
|
||||
// Numbers
|
||||
numbers: {
|
||||
decimal: 1_000_000
|
||||
float: 3.14159
|
||||
exponent: 6.022e23
|
||||
hex: 0xFF_FF
|
||||
octal: 0o755
|
||||
binary: 0b1010_1010
|
||||
multiplier: 1.5Gi
|
||||
kilo: 4K
|
||||
}
|
||||
|
||||
// Strings and bytes
|
||||
strs: {
|
||||
simple: "hello, world"
|
||||
escaped: "tab\tnewline\nunicode\u00e9"
|
||||
bytes: 'raw bytes \x00\xff'
|
||||
raw: #"no \(interpolation) here"#
|
||||
multiline: """
|
||||
multiple
|
||||
lines with \(version)
|
||||
"""
|
||||
multiBytes: '''
|
||||
byte
|
||||
lines
|
||||
'''
|
||||
}
|
||||
|
||||
// Builtin types and values
|
||||
types: {
|
||||
n: null
|
||||
b: bool | *false
|
||||
i: int8 | int16 | int32 | int64
|
||||
f: float32 | float64
|
||||
s: string
|
||||
y: bytes
|
||||
r: rune
|
||||
t: _
|
||||
x: number
|
||||
}
|
||||
|
||||
// Bottom (error) value
|
||||
bottom: _|_ | 1
|
||||
|
||||
// Operators and builtins
|
||||
ops: {
|
||||
sum: 1 + 2*3 - 4/2
|
||||
divided: div(7, 2)
|
||||
modulo: mod(7, 2)
|
||||
quotient: quo(-7, 2)
|
||||
rest: rem(-7, 2)
|
||||
eq: 1 == 1
|
||||
ne: "a" != "b"
|
||||
both: true && false
|
||||
either: true || false
|
||||
not: !true
|
||||
match: "abc" =~ "^a"
|
||||
nomatch: "abc" !~ "^z"
|
||||
length: len([1, 2, 3])
|
||||
closed: close({a: 1})
|
||||
upper: strings.ToUpper("cue")
|
||||
sorted: list.Sort([3, 1, 2], list.Ascending)
|
||||
disj: or([1, 2, 3])
|
||||
conj: and([int, >0])
|
||||
asYAML: yamlpkg.Marshal({a: 1})
|
||||
}
|
||||
|
||||
// Nested calls, grouping and interpolated calls
|
||||
calls: {
|
||||
allPorts: list.Concat([
|
||||
[22, 25],
|
||||
list.Concat([for _, s in services {s.ports}]),
|
||||
])
|
||||
nested: len(strings.Split("a,b", ","))
|
||||
grouped: ((1 + 2) * 3)
|
||||
interp: "x-\(strings.ToUpper("y"))-\(len([1, 2]))"
|
||||
}
|
||||
|
||||
// Comprehensions
|
||||
let prefix = "svc-"
|
||||
|
||||
serviceNames: [for k, v in services if v.replicas > 1 {prefix + k}]
|
||||
|
||||
portMap: {
|
||||
for name, svc in services {
|
||||
for i, p in svc.ports {
|
||||
"\(name)-\(i)": p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byPort: {
|
||||
for name, svc in services
|
||||
if len(svc.ports) > 0
|
||||
let first = svc.ports[0] {
|
||||
"\(first)": name
|
||||
(name + "-image"): svc.image
|
||||
}
|
||||
}
|
||||
|
||||
if version != "" {
|
||||
hasVersion: true
|
||||
}
|
||||
|
||||
// Aliases, optional and required fields, pattern constraints
|
||||
X=outer: {
|
||||
inner: 1
|
||||
ref: X.inner
|
||||
}
|
||||
|
||||
optional?: string
|
||||
required!: int
|
||||
[=~"^x-"]: string
|
||||
|
||||
// Attributes
|
||||
config: {
|
||||
port: int @tag(port, type=int)
|
||||
debug: bool @json(",omitempty") @yaml("debug")
|
||||
}
|
||||
|
||||
// Embedding and default values
|
||||
#Base: {
|
||||
kind: *"base" | "derived"
|
||||
}
|
||||
|
||||
derived: #Base & {kind: "derived"}
|
||||
|
||||
#Limits: {
|
||||
cpu: {min: number, max: number} | *{min: 0, max: 1}
|
||||
tags: [...string] | *[]
|
||||
}
|
||||
|
||||
// Lists
|
||||
emptyList: []
|
||||
openList: [1, 2, ...]
|
||||
typedList: [...string]
|
||||
nestedList: [[1, 2], [3, 4]]
|
||||
@@ -1,5 +0,0 @@
|
||||
{a
|
||||
/* comment */
|
||||
}
|
||||
|
||||
{a /* comment */}
|
||||
Reference in new issue
Block a user