1
0
mirror of https://github.com/sharkdp/bat synced 2026-08-03 18:51:44 +00:00

Compare commits

...

66 Commits

Author SHA1 Message Date
sharkdp 416a0fd439 Fix autocompletion-path 2019-05-15 23:24:37 +02:00
sharkdp 9b1b3dda14 Only print the header for empty files
Instead of printing
```
───────┬─────────────────────────────────────────────────────────
       │ File: some-file
───────┼─────────────────────────────────────────────────────────
───────┴─────────────────────────────────────────────────────────
```
for empty files, bat will now print
```
───────┬─────────────────────────────────────────────────────────
       │ File: some-file   <EMPTY>
───────┴─────────────────────────────────────────────────────────
```
2019-05-15 22:37:03 +02:00
sharkdp ae7db313a6 Update man page 2019-05-15 22:14:40 +02:00
sharkdp 3c4384990d Update syntaxes and themes 2019-05-15 22:12:02 +02:00
sharkdp 260814c377 Bump version to 0.11 2019-05-15 22:07:35 +02:00
sharkdp 3675a82a1b Update dependencies 2019-05-15 22:06:28 +02:00
sharkdp 5b2b594919 Revert "Run 'cargo fmt'" (outdated rustfmt)
This reverts commit dd40f7545d.
2019-05-15 08:07:08 +02:00
sharkdp 9d53ce6be6 Fix warning 2019-05-14 23:42:23 +02:00
sharkdp 51e05499a9 Update dependencies 2019-05-14 23:40:21 +02:00
sharkdp dd40f7545d Run 'cargo fmt' 2019-05-14 23:40:07 +02:00
sharkdp c709bf2103 Print a warning message instead of just '<BINARY>' 2019-05-14 23:35:22 +02:00
Maksim Panfilov f37dbb80a8 Added printing of "<BINARY>" for binary files in the interactive mode if header decorations are turned off 2019-05-14 23:35:22 +02:00
sharkdp 0a1e08da96 Extend help text for --terminal-width and --wrap, closes #535 2019-05-14 23:24:13 +02:00
Ethan P 06b8dcb7eb Update fish completions for new --list-languages format 2019-05-14 22:50:42 +02:00
Ethan P 493a4e719e Added non-interactive mode for --list-languages
This makes scripting it a lot easier and less hacky.
2019-05-14 22:50:42 +02:00
Ethan P 27e0ca98d9 Remove language completions for config files 2019-05-14 22:50:42 +02:00
Ethan P 1b2066c5f2 Add fish shell argument completions for --language option 2019-05-14 22:50:42 +02:00
dependabot[bot] 4ec3cdb5b8 Bump error-chain from 0.12.0 to 0.12.1
Bumps [error-chain](https://github.com/rust-lang-nursery/error-chain) from 0.12.0 to 0.12.1.
- [Release notes](https://github.com/rust-lang-nursery/error-chain/releases)
- [Changelog](https://github.com/rust-lang-nursery/error-chain/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang-nursery/error-chain/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-13 18:32:28 +02:00
sharkdp 72152296c7 Fix accidental printing of files named 'cache'
This also adds two regression tests, so this will hopefully not pop up
again.

closes #557
2019-05-10 17:55:46 -05:00
Ethan P 2b9d25df05 Replace iterator with string starts_with and ends_with 2019-05-10 17:52:35 -05:00
Ethan P cc8186103b Reformatted with cargo fmt. 2019-05-10 17:52:35 -05:00
Ethan P 0ad09df7ab Improved logic when encountering ANSI in character wrap mode
Fixes #551
2019-05-10 17:52:35 -05:00
Ethan P 7ef0fe091d Cleaned up terminal-width validation even more 2019-05-10 17:50:58 -05:00
Ethan P 89fcbb2b15 Cleaned up terminal-width validation slightly 2019-05-10 17:50:58 -05:00
Ethan P a7e2bb86cb Add validation for --terminal-width option 2019-05-10 17:50:58 -05:00
sharkdp 1ce0bc8e0d Slightly modified help text 2019-05-10 11:04:46 -05:00
Ethan P fde00eec98 Add -pp for plain styling and no pager 2019-05-10 11:01:02 -05:00
Mitchell Kember bb6594e691 Add 3 new themes: ansi-light, ansi-dark, base16
Also, interpret transparent colors (#RRGGBB00) as specifying a terminal
color palette number with RR. The three new themes use this.
2019-05-08 07:35:43 -05:00
rasmuskriest e7c5561df7 Update Chocolatey package name to bat 2019-04-25 17:58:15 +02:00
rasmuskriest 0aabbc03d7 Add Chocolatey package instructions 2019-04-25 17:58:15 +02:00
Alexander Hultnér 8a5b59febc Updated manual to include -H, --highlight-line <N> 2019-04-25 17:57:01 +02:00
Tim Sampson 7afdd44c43 cache/misc: be more cautious with bash 2019-04-25 17:52:21 +02:00
Tim Sampson d72549a873 add fish shell syntax definition 2019-04-25 17:52:21 +02:00
evdev 1ba8540e5f Updated packaging script to include manual fish shell completions 2019-04-13 10:59:22 +02:00
evdev a6cee4da67 Removed completions file accidentaly left in root dir 2019-04-13 10:59:22 +02:00
evdev cd6850947e Updated fish completions to include parameter completion for available themes, added cache subcommand completions 2019-04-13 10:59:22 +02:00
evdev 14bfedeb20 Updated fish completions to include parameter completion for flags: color, italic-text, decorations, paging, wrap 2019-04-13 10:59:22 +02:00
evdev 8fe65252f7 WIP: added manual minimal fish shell completions for current flags. Does not include flag sub-options like language lists or subcommands 2019-04-13 10:59:22 +02:00
evdev 5e9351445f WIP: added manual minimal fish shell completions for current flags. Does not include flag sub-options like language lists or subcommands 2019-04-13 10:59:22 +02:00
dependabot[bot] 2fdfb8de40 Bump escargot from 0.4.0 to 0.5.0
Bumps [escargot](https://github.com/crate-ci/escargot) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/crate-ci/escargot/releases)
- [Changelog](https://github.com/crate-ci/escargot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/escargot/compare/v0.4.0...v0.5.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-09 21:48:33 +02:00
dependabot[bot] f8c759edff Bump clap from 2.32.0 to 2.33.0
Bumps [clap](https://github.com/clap-rs/clap) from 2.32.0 to 2.33.0.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-08 13:00:03 +02:00
dependabot[bot] e34431f922 Bump assert_cmd from 0.11.0 to 0.11.1
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/assert-rs/assert_cmd/releases)
- [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/assert_cmd/compare/v0.11.0...v0.11.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-04 21:11:46 +02:00
Björn c96927b550 Update F# syntax 2019-04-04 21:11:19 +02:00
Laurent Arnoud 921cc0d1cb Add copyright file on Debian package 2019-03-17 18:59:28 +01:00
dependabot[bot] dbc49e534a Bump syntect from 3.1.0 to 3.2.0
Bumps [syntect](https://github.com/trishume/syntect) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/trishume/syntect/releases)
- [Changelog](https://github.com/trishume/syntect/blob/master/CHANGELOG.md)
- [Commits](https://github.com/trishume/syntect/compare/v3.1.0...v3.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-11 06:37:16 +01:00
David Peter 7755ed79e0 Delete .DS_Store 2019-03-11 06:35:21 +01:00
Daniele Esposti 50aabf331d Updated minimum version of Rust 2019-03-09 07:43:41 +01:00
Daniele Esposti f259ff2920 Formatted code 2019-03-09 07:43:41 +01:00
Daniele Esposti 82f14121bd Applied linter fixes 2019-03-09 07:43:41 +01:00
Daniele Esposti a21ae614e6 Migrated to Rust 2018 2019-03-09 07:43:41 +01:00
dependabot[bot] b94c94e845 Bump lazy_static from 1.2.0 to 1.3.0
Bumps [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/rust-lang-nursery/lazy-static.rs/releases)
- [Commits](https://github.com/rust-lang-nursery/lazy-static.rs/compare/1.2.0...1.3.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-08 21:45:42 +01:00
dependabot[bot] 161d107ec3 Bump dirs from 1.0.4 to 1.0.5
Bumps [dirs](https://github.com/soc/dirs-rs) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/soc/dirs-rs/releases)
- [Commits](https://github.com/soc/dirs-rs/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-05 22:31:16 +01:00
dependabot[bot] ecf147fd96 Bump syntect from 3.0.2 to 3.1.0
Bumps [syntect](https://github.com/trishume/syntect) from 3.0.2 to 3.1.0.
- [Release notes](https://github.com/trishume/syntect/releases)
- [Changelog](https://github.com/trishume/syntect/blob/master/CHANGELOG.md)
- [Commits](https://github.com/trishume/syntect/compare/v3.0.2...v3.1.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-02-25 07:03:17 +01:00
sharkdp f0771d6532 Do not replace arguments to pager when --pager is used, closes #509 2019-02-18 20:28:44 +01:00
Geoff Shannon d8f28c177a Make fd link actually link to fd 2019-02-17 09:19:42 +01:00
David Peter fbee9df719 Add "git show" section 2019-02-11 22:04:22 +01:00
David Peter 6e9ca7d6dc Add "xclip" section 2019-02-11 22:01:03 +01:00
David Peter a9ec5c063a Add documentation about "tail -f" 2019-02-11 21:54:16 +01:00
David Peter 8470fd7173 Add "Integration with other tools" section 2019-02-11 21:38:18 +01:00
Reid Wagner 76b7418e35 Only print contents if file wasn't empty, or EOF wasn't first thing received from stdin. 2019-02-11 20:33:16 +01:00
Reid Wagner 10c5f79640 Revert "Check result of read_until, and return Error if 0, which indicates EOF was found before delimeter."
This reverts commit 61e888de7f.
2019-02-11 20:33:16 +01:00
sharkdp 9e11d66979 Handle UTF-16 encoding errors with replacement characters 2019-02-10 10:18:07 +01:00
sharkdp fa3244f7c1 Add test for UTF-16LE encoding 2019-02-10 10:18:07 +01:00
sharkdp 906774e6d3 Integration tests for single-line files 2019-02-10 10:18:07 +01:00
Reid Wagner cec9cc073c Add integration tests running bat with empty input files. 2019-02-08 23:30:33 +01:00
David Peter a16789a060 Update alternatives.md 2019-02-07 23:52:31 +01:00
41 changed files with 4052 additions and 626 deletions
+3
View File
@@ -123,3 +123,6 @@
[submodule "assets/syntaxes/varlink"] [submodule "assets/syntaxes/varlink"]
path = assets/syntaxes/varlink path = assets/syntaxes/varlink
url = https://github.com/varlink/syntax-highlight-varlink.git url = https://github.com/varlink/syntax-highlight-varlink.git
[submodule "assets/syntaxes/sublime-fish"]
path = assets/syntaxes/sublime-fish
url = https://github.com/Phidica/sublime-fish.git
+3 -3
View File
@@ -32,15 +32,15 @@ matrix:
# Minimum Rust supported channel. # Minimum Rust supported channel.
- os: linux - os: linux
rust: 1.30.0 rust: 1.31.0
env: TARGET=x86_64-unknown-linux-gnu env: TARGET=x86_64-unknown-linux-gnu
- os: linux - os: linux
rust: 1.30.0 rust: 1.31.0
env: env:
- TARGET=x86_64-unknown-linux-musl - TARGET=x86_64-unknown-linux-musl
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc - CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
- os: osx - os: osx
rust: 1.30.0 rust: 1.31.0
env: TARGET=x86_64-apple-darwin env: TARGET=x86_64-apple-darwin
# Code formatting check # Code formatting check
Generated
+396 -303
View File
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -7,12 +7,13 @@ license = "MIT/Apache-2.0"
name = "bat" name = "bat"
readme = "README.md" readme = "README.md"
repository = "https://github.com/sharkdp/bat" repository = "https://github.com/sharkdp/bat"
version = "0.10.0" version = "0.11.0"
exclude = [ exclude = [
"assets/syntaxes/*", "assets/syntaxes/*",
"assets/themes/*", "assets/themes/*",
] ]
build = "build.rs" build = "build.rs"
edition = '2018'
[dependencies] [dependencies]
atty = "0.2.2" atty = "0.2.2"
@@ -20,7 +21,7 @@ ansi_term = "0.11"
ansi_colours = "^1.0" ansi_colours = "^1.0"
console = "0.7" console = "0.7"
dirs = "1.0" dirs = "1.0"
lazy_static = "1.2" lazy_static = "1.3"
wild = "2.0" wild = "2.0"
content_inspector = "0.2.4" content_inspector = "0.2.4"
encoding = "0.2" encoding = "0.2"
@@ -32,12 +33,12 @@ default-features = false
features = [] features = []
[dependencies.syntect] [dependencies.syntect]
version = "3.0.2" version = "3.2.0"
default-features = false default-features = false
features = ["parsing", "yaml-load", "dump-load", "dump-create"] features = ["parsing", "yaml-load", "dump-load", "dump-create"]
[dependencies.clap] [dependencies.clap]
version = "2.32" version = "2.33"
default-features = false default-features = false
features = ["suggestions", "color", "wrap_help"] features = ["suggestions", "color", "wrap_help"]
@@ -48,8 +49,8 @@ features = []
[dev-dependencies] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"
assert_cmd = "0.11.0" assert_cmd = "0.11.1"
escargot = "0.4.0" escargot = "0.5.0"
[build-dependencies] [build-dependencies]
clap = "2.32" clap = "2.33"
+49 -4
View File
@@ -91,6 +91,47 @@ bat -n main.rs # show line numbers (only)
bat f - g # output 'f', then stdin, then 'g'. bat f - g # output 'f', then stdin, then 'g'.
``` ```
### Integration with other tools
#### `find` or `fd`
You can use the `-exec` option of `find` to preview all search results with `bat`:
```bash
find … -exec bat {} +
```
If you happen to use [`fd`](https://github.com/sharkdp/fd), you can use the `-X`/`--exec-batch` option to do the same:
```bash
fd … -X bat
```
#### `tail -f`
`bat` can be combined with `tail -f` to continuously monitor a given file with syntax highlighting.
```bash
tail -f /var/log/pacman.log | bat --paging=never -l log
```
Note that we have to switch off paging in order for this to work. We have also specified the syntax
explicitly (`-l log`), as it can not be auto-detected in this case.
### `git show`
You can combine `bat` with `git show` to view an older version of a given file with proper syntax
highlighting:
```bash
git show v0.6.0:src/main.rs | bat -l rs
```
#### `xclip`
The line numbers and Git modification markers in the output of `bat` can make it hard to copy
the contents of a file. To prevent this, you can call `bat` with the `-p`/`--plain` option or
simply pipe the output into `xclip`:
```bash
bat main.cpp | xclip
```
`bat` will detect that the output is being redirected and print the plain file contents.
## Installation ## Installation
### On Ubuntu ### On Ubuntu
@@ -99,7 +140,7 @@ bat f - g # output 'f', then stdin, then 'g'.
Download the latest `.deb` package from the [release page](https://github.com/sharkdp/bat/releases) Download the latest `.deb` package from the [release page](https://github.com/sharkdp/bat/releases)
and install it via: and install it via:
``` bash ``` bash
sudo dpkg -i bat_0.10.0_amd64.deb # adapt version number and architecture sudo dpkg -i bat_0.11.0_amd64.deb # adapt version number and architecture
``` ```
### On Arch Linux ### On Arch Linux
@@ -168,12 +209,16 @@ brew install bat
### On Windows ### On Windows
You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases), You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases),
or install it with [scoop](https://scoop.sh/): or install it with [scoop](https://scoop.sh/) or [Chocolatey](https://chocolatey.org):
```bash ```bash
scoop install bat scoop install bat
``` ```
```bash
choco install bat
```
[See below](#using-bat-on-windows) for notes. [See below](#using-bat-on-windows) for notes.
### Via Docker ### Via Docker
@@ -220,7 +265,7 @@ binaries are also available: look for archives with `musl` in the file name.
### From source ### From source
If you want to build `bat` from source, you need Rust 1.30 or If you want to build `bat` from source, you need Rust 1.31 or
higher. You can then use `cargo` to build everything: higher. You can then use `cargo` to build everything:
```bash ```bash
@@ -389,7 +434,7 @@ Example configuration file:
Windows only includes a very limited pager in the form of `more`. You can download a Windows binary Windows only includes a very limited pager in the form of `more`. You can download a Windows binary
for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through
Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in
your `PATH` or [define an environment variable](#using-a-different-pager). your `PATH` or [define an environment variable](#using-a-different-pager). The [Chocolatey package](#on-windows) installs `less` automatically.
### Colors ### Colors
+76
View File
@@ -0,0 +1,76 @@
# Fish Shell Completions
# Place or symlink to $XDG_CONFIG_HOME/fish/completions/bat.fish ($XDG_CONFIG_HOME is usually set to ~/.config)
# Helper function:
function __bat_autocomplete_languages --description "A helper function used by "(status filename)
bat --list-languages | awk -F':' '
{
lang=$1
split($2, exts, ",")
for (i in exts) {
ext=exts[i]
if (ext !~ /[A-Z].*/ && ext !~ /^\..*rc$/) {
print ext"\t"lang
}
}
}
' | sort
end
# Completions:
complete -c bat -l color -xka "auto never always" -d "Specify when to use colored output (default: auto)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l config-dir -d "Display location of 'bat' configuration directory" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l config-file -d "Display location of 'bat' configuration file" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l decorations -xka "auto never always" -d "Specify when to use the decorations specified with '--style' (default: auto)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s h -l help -d "Print help message" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s H -l highlight-line -x -d "<N> Highlight the N-th line with a different background color" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l italic-text -xka "always never" -d "Specify when to use ANSI sequences for italic text (default: never)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s l -l language -d "Set the language for syntax highlighting" -n "not __fish_seen_subcommand_from cache" -xa "(__bat_autocomplete_languages)"
complete -c bat -s r -l line-range -x -d "<N:M> Only print the specified range of lines for each file" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l list-languages -d "Display list of supported languages for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l list-themes -d "Display a list of supported themes for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s m -l map-syntax -x -d "<from:to> Map a file extension or file name to an existing syntax" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s n -l number -d "Only show line numbers, no other decorations. Alias for '--style=numbers'" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l pager -x -d "<command> Specify which pager program to use (default: less)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l paging -xka "auto never always" -d "Specify when to use the pager (default: auto)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s p -l plain -d "Only show plain style, no decorations. Alias for '--style=plain'" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s A -l show-all -d "Show non-printable characters like space/tab/newline" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l style -xka "auto full plain changes header grid numbers" -d "Comma-separated list of style elements or presets to display with file contents" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l tabs -x -d "<T> Set the tab width to T spaces (width of 0 passes tabs through directly)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l terminal-width -x -d "<width> Explicitly set terminal width; Prefix with '+' or '-' to offset (default width is auto determined)" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l theme -xka "(bat --list-themes | cat)" -d "Set the theme for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s u -l unbuffered -d "POSIX-compliant unbuffered output. Option is ignored" -n "not __fish_seen_subcommand_from cache"
complete -c bat -s V -l version -d "Show version information" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l wrap -xka "auto never character" -d "<mode> Specify the text-wrapping mode (default: auto)" -n "not __fish_seen_subcommand_from cache"
# Sub-command 'cache' completions
complete -c bat -a "cache" -d "Modify the syntax/language definition cache" -n "not __fish_seen_subcommand_from cache"
complete -c bat -l build -f -d "Parse syntaxes/language definitions into cache" -n "__fish_seen_subcommand_from cache"
complete -c bat -l clear -f -d "Reset syntaxes/language definitions to default settings" -n "__fish_seen_subcommand_from cache"
+1
View File
@@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
BIN
View File
Binary file not shown.
+567 -129
View File
@@ -9,63 +9,230 @@ file_extensions:
scope: source.fsharp scope: source.fsharp
contexts: contexts:
main: main:
- include: compiler_directives
- include: comments - include: comments
- include: constants - include: constants
- include: structure
- include: attributes
- include: strings - include: strings
- include: chars
- include: double_tick
- include: definition - include: definition
- include: method_calls - include: abstract_definition
- include: attributes
- include: modules - include: modules
- include: anonymous_functions - include: anonymous_functions
- include: du_declaration
- include: record_declaration
- include: records
- include: strp_inlined
- include: keywords - include: keywords
- include: cexprs
- include: text
abstract_definition:
- match: '\b(abstract)\s+(member)?(\s+\[\<.*\>\])?\s*([_[:alpha:]0-9,\._`\s]+)(:)'
captures:
1: keyword.fsharp
2: keyword.fsharp
3: support.function.attribute.fsharp
5: keyword.fsharp
push:
- meta_scope: abstract.definition.fsharp
- match: \s*(with)\b|=|$
captures:
1: keyword.fsharp
pop: true
- include: comments
- include: common_declaration
- match: '(\?{0,1})([[:alpha:]0-9''`^._ ]+)\s*(:)(\s*([[:alpha:]0-9''`^._ ]+)){0,1}'
captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
3: keyword.symbol.fsharp
4: entity.name.type.fsharp
- match: '(?!with|get|set\b)\b([\w0-9''`^._]+)'
captures:
1: entity.name.type.fsharp
- include: keywords
anonymous_functions: anonymous_functions:
- match: \b(fun)\b - match: \b(fun)\b
captures: captures:
1: keyword.other.function-definition.fsharp 1: keyword.fsharp
push: push:
- meta_scope: meta.function.anonymous - meta_scope: function.anonymous
- match: (->) - match: (->)
captures: captures:
1: keyword.other.fsharp 1: keyword.fsharp
pop: true pop: true
- include: comments
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: \s*(?=(->))
captures:
1: keyword.symbol.fsharp
pop: true
- include: member_declaration
- include: variables - include: variables
attributes: attributes:
- match: '\[\<' - match: '\[\<'
push: push:
- meta_scope: support.function.attribute.fsharp - meta_scope: support.function.attribute.fsharp
- match: '\>\]' - match: '\>\]|\]'
pop: true pop: true
- include: main - include: main
characters: cexprs:
- match: (') - match: '\b(async|seq|promise|task|maybe|asyncMaybe|controller|scope|application|pipeline)\s*\{'
scope: cexpr.fsharp
captures: captures:
1: punctuation.definition.string.begin.fsharp 0: keyword.fsharp
push: chars:
- meta_scope: string.quoted.single.fsharp - match: ('\\?.')
- match: (') scope: char.fsharp
captures: captures:
1: punctuation.definition.string.end.fsharp 1: string.quoted.single.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\""ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
comments: comments:
- match: \(\*\*?(\*)\) - match: (\(\*(?!\)))
scope: comment.block.fsharp
captures: captures:
1: comment.block.empty.fsharp 1: comment.block.fsharp
- match: '\(\*[^\)]'
push: push:
- meta_scope: comment.block.fsharp - meta_scope: comment.block.fsharp
- match: \*\) - match: (\*\))
captures:
1: comment.block.fsharp
pop: true pop: true
- include: comments
- match: //.*$ - match: //.*$
scope: comment.line.double-slash.fsharp scope: comment.line.double-slash.fsharp
common_binding_definition:
- include: comments
- include: attributes
- match: (:)\s*(\()\s*(static member|member)
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
3: keyword.fsharp
push:
- match: (\))\s*((?=,)|(?=\=))
captures:
1: keyword.symbol.fsharp
pop: true
- match: '(\^[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- include: variables
- include: keywords
- match: (:)\s*(\()
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
push:
- match: '(\)\s*(([?[:alpha:]0-9''`^._ ]*)))'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
pop: true
- include: tuple_signature
- match: '(:)\s*(\^[[:alpha:]0-9''._]+)\s*(when)'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
3: keyword.fsharp
push:
- match: (?=:)
captures:
1: keyword.symbol.fsharp
pop: true
- match: \b(and|when|or)\b
scope: keyword.fsharp
- match: "([[:alpha:]0-9'^._]+)"
comment: Because we first capture the keywords, we can capture what looks like a word and assume it's an entity definition
captures:
1: entity.name.type.fsharp
- match: (\(|\))
scope: keyword.symbol.fsharp
- match: '(:)\s*([?[:alpha:]0-9''`^._ ]+)'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
- match: '(->)\s*(\()?\s*([?[:alpha:]0-9''`^._ ]+)*'
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
3: entity.name.type.fsharp
- match: (\*)\s*(\()
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
push:
- match: '(\)\s*(([?[:alpha:]0-9''`^._ ]+))+)'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
pop: true
- include: tuple_signature
- match: '(\*)(\s*([?[:alpha:]0-9''`^._ ]+))*'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
- match: '(<(?![[:space:]]*\)))'
captures:
1: keyword.symbol.fsharp
push:
- match: ((?<!:)>)
captures:
1: keyword.symbol.fsharp
pop: true
- include: generic_declaration
- match: "({)"
captures:
1: keyword.symbol.fsharp
push:
- match: "(})"
captures:
1: keyword.symbol.fsharp
pop: true
- include: record_signature
- include: definition
- include: variables
- include: keywords
common_declaration:
- match: '\s*(->)\s*([[:alpha:]0-9''`^._ ]+)(<)'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
3: keyword.symbol.fsharp
push:
- match: (>)
captures:
1: keyword.symbol.fsharp
pop: true
- match: "([[:alpha:]0-9'`^._ ]+)"
captures:
1: entity.name.type.fsharp
- include: keywords
- match: '\s*(->)\s*(?!with|get|set\b)\b([\w0-9''`^._]+)'
captures:
1: keyword.symbol.fsharp
2: entity.name.type.fsharp
- match: '(\?{0,1})([[:alpha:]0-9''`^._ ]+)\s*(:)(\s*([?[:alpha:]0-9''`^._ ]+)(<))'
captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
3: keyword.symbol.fsharp
4: keyword.symbol.fsharp
5: entity.name.type.fsharp
push:
- match: (>)
captures:
1: keyword.symbol.fsharp
pop: true
- match: "([[:alpha:]0-9'`^._ ]+)"
captures:
1: entity.name.type.fsharp
- include: keywords
compiler_directives:
- match: \s?(#if|#elif|#else|#elseif|#endif|#light|#nowarn)
scope: compiler_directive.fsharp
captures:
constants: constants:
- match: \(\) - match: \(\)
scope: constant.language.unit.fsharp scope: constant.language.unit.fsharp
@@ -73,123 +240,349 @@ contexts:
scope: constant.numeric.floating-point.fsharp scope: constant.numeric.floating-point.fsharp
- match: '\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))' - match: '\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))'
scope: constant.numeric.integer.nativeint.fsharp scope: constant.numeric.integer.nativeint.fsharp
- match: \b(true|false|null|unit)\b
scope: constant.others.fsharp
definition: definition:
- match: '\b(val|val|let|and|member|override|use)\s?(rec|inline|mutable)?(\s+\(?([a-zA-Z.\|_][a-zA-Z0-9.|_]*)\)?\w*)\b' - match: '\b(let mutable|static let mutable|let inline|let|member val|static member inline|static member|default|member|override|let!)(\s+rec|mutable)?(\s+\[\<.*\>\])?\s*(private|internal|public)?\s+(\[[^-=]*\]|[_[:alpha:]]([_[:alpha:]0-9,\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9,\._`\s]+|(?<=,)\s)*)?'
captures: captures:
1: keyword.other.binding.fsharp 1: keyword.fsharp
2: keyword.other.function-recursive.fsharp 2: keyword.fsharp
3: variable.other.binding.fsharp 3: support.function.attribute.fsharp
4: keyword.fsharp
5: variable.fsharp
push: push:
- meta_scope: meta.binding.fsharp - meta_scope: binding.fsharp
- match: "=|$" - match: \s*(with\b|=|\n+=|(?<=\=))
captures: captures:
1: punctuation.separator.function.type-constraint.fsharp 1: keyword.fsharp
pop: true pop: true
- include: common_binding_definition
- match: '\b(static val mutable|val mutable|val)(\s+rec|mutable)?(\s+\[\<.*\>\])?\s*(private|internal|public)?\s+(\[[^-=]*\]|[_[:alpha:]]([_[:alpha:]0-9,\._]+)*|``[_[:alpha:]]([_[:alpha:]0-9,\._`\s]+|(?<=,)\s)*)?'
captures:
1: keyword.fsharp
2: keyword.fsharp
3: support.function.attribute.fsharp
4: keyword.fsharp
5: variable.fsharp
push:
- meta_scope: binding.fsharp
- match: \n$
pop: true
- include: common_binding_definition
double_tick:
- match: (``)(.*)(``)
scope: variable.other.binding.fsharp
captures:
1: string.quoted.single.fsharp
2: variable.other.binding.fsharp
3: string.quoted.single.fsharp
du_declaration:
- match: \b(of)\b
captures:
1: keyword.fsharp
push:
- meta_scope: du_declaration.fsharp
- match: $|(\|)
captures:
1: keyword.symbol.fsharp
pop: true
- include: comments
- match: '([[:alpha:]0-9''`<>^._]+|``[[:alpha:]0-9'' <>^._]+``)\s*(:)\s*([[:alpha:]0-9''`<>^._]+|``[[:alpha:]0-9'' <>^._]+``)'
captures:
1: variable.parameter.fsharp
2: keyword.symbol.fsharp
3: entity.name.type.fsharp
- match: "([[:alpha:]0-9'`^._]+)|``([[:alpha:]0-9'^._ ]+)``"
captures:
1: entity.name.type.fsharp
- include: keywords
generic_declaration:
- match: (:)\s*(\()\s*(static member|member)
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
3: keyword.fsharp
push:
- match: (\))
captures:
1: keyword.symbol.fsharp
pop: true
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: (\))
captures:
1: keyword.symbol.fsharp
pop: true
- include: member_declaration
- match: '((''|\^)[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- include: variables - include: variables
- match: \b(let)\s+((\(\))|(_))\s+= - include: keywords
scope: meta.expression.fsharp - match: \b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\!|return\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|use|use\!|struct|while|mutable)(?!')\b
scope: keyword.fsharp
- match: ":"
scope: keyword.fsharp
- include: constants
- match: '((''|\^)[[:alpha:]0-9''._]+)'
captures: captures:
1: keyword.other.binding.fsharp 1: entity.name.type.fsharp
2: keyword.other.function-recursive.fsharp - match: (<)
4: constant.language.unit.fsharp captures:
5: constant.language.ignored.fsharp 1: keyword.symbol.fsharp
keywords:
- match: ^\s*#\s*(light|if|else|endif|r|I|load|time|help|quit)\b
push: push:
- meta_scope: meta.preprocessor.fsharp - match: (>)
- match: (\s|$)
pop: true
- match: \b(new|in|as|if|then|else|elif|for|begin|end|match|with|type|inherit|true|false|null|do)\b
scope: keyword.other.fsharp
- match: '(\|>|\|?>|\->|\<\-|:>|:|\[|\]|\;|\||_)'
scope: entity.name
method_calls:
- match: '(?<!\w)([a-z]\w*)(\.)'
push:
- meta_scope: meta.method-call.fsharp
- match: '[A-Z]\w*(\.)'
scope: meta.method.fsharp
captures: captures:
1: punctuation.separator.method-call.fsharp 1: keyword.symbol.fsharp
- match: (?=.)
pop: true pop: true
modules: - match: '((''|\^)[[:alpha:]0-9''._]+)'
- match: '\b(namespace|module)\s+([a-zA-Z][a-zA-Z0-9''_.]*)' captures:
1: entity.name.type.fsharp
- include: tuple_signature
- include: generic_declaration
- match: '(?!when|and|or\b)\b([\w0-9''`^._]+)'
captures: captures:
1: keyword.other.fsharp 1: entity.name.type.fsharp
- match: (\|)
captures:
1: keyword.symbol.fsharp
- include: keywords
keywords:
- match: \b(private|to|public|internal|function|yield!|yield|class|exception|match|delegate|of|new|in|as|if|then|else|elif|for|begin|end|inherit|do|let\!|return\!|return|interface|with|abstract|property|union|enum|member|try|finally|and|when|or|use|use\!|struct|while|mutable)(?!')\b
scope: keyword.fsharp
- match: '(&&&|\|\|\||\^\^\^|~~~|<<<|>>>|\|>|\->|\<\-|:>|:\?>|:|\[|\]|\;|<>|=|@|\|\||&&|{|}|\||_|\.\.|\,|\+|\-|\*|\/|\^|\!|\>|\>\=|\>\>|\<|\<\=|\(|\)|\<\<)'
scope: keyword.symbol.fsharp
member_declaration:
- include: comments
- include: common_declaration
- match: (:)\s*(\()\s*(static member|member)
captures:
1: keyword.symbol.fsharp
2: keyword.symbol.fsharp
3: keyword.fsharp
push:
- match: (\))\s*((?=,)|(?=\=))
captures:
1: keyword.symbol.fsharp
pop: true
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: (\))
captures:
1: keyword.symbol.fsharp
pop: true
- include: member_declaration
- match: '(\^[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- include: variables
- include: keywords
- match: '(\^[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- match: \b(and|when|or)\b
scope: keyword.fsharp
- match: (\(|\))
scope: keyword.symbol.fsharp
- match: '(\?{0,1})([[:alpha:]0-9''`^._]+|``[[:alpha:]0-9''`^:,._ ]+``)\s*(:{0,1})(\s*([?[:alpha:]0-9''`<>._ ]+)){0,1}'
captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
3: keyword.symbol.fsharp
4: entity.name.type.fsharp
- include: keywords
modules:
- match: '\b(namespace|module)\s*(public|internal|private)?\s+([[:alpha:]][[:alpha:]0-9''_. ]*)'
captures:
1: keyword.fsharp
2: keyword.fsharp
3: entity.name.section.fsharp
push:
- meta_scope: entity.name.section.fsharp
- match: (\s?=|\s|$)
captures:
1: keyword.symbol.fsharp
pop: true
- match: '(\.)([A-Z][[:alpha:]0-9''_]*)'
scope: entity.name.section.fsharp
captures:
1: punctuation.separator.namespace-reference.fsharp
2: entity.name.section.fsharp
- match: '\b(open)\s+([[:alpha:]][[:alpha:]0-9''_]*)(?=(\.[A-Z][[:alpha:]0-9_]*)*)'
captures:
1: keyword.fsharp
2: entity.name.section.fsharp 2: entity.name.section.fsharp
push: push:
- meta_scope: meta.module.namespace.fsharp - meta_scope: namespace.open.fsharp
- match: (\s|$) - match: (\s|$)
pop: true pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)' - match: '(\.)([[:alpha:]][[:alpha:]0-9''_]*)'
scope: support.other.module.fsharp scope: entity.name.section.fsharp
captures: captures:
1: punctuation.separator.module-reference.fsharp 1: punctuation.separator.namespace-reference.fsharp
2: support.other.module.fsharp 2: entity.name.section.fsharp
- match: '\b(open)\s+([A-Z][a-zA-Z0-9''_]*)(?=(\.[A-Z][a-zA-Z0-9_]*)*)' - match: '^\s*(module)\s+([A-Z][[:alpha:]0-9''_]*)\s*(=)\s*([A-Z][[:alpha:]0-9''_]*)'
captures: captures:
1: keyword.other.fsharp 1: keyword.fsharp
2: support.other.module.fsharp 2: entity.name.type.namespace.fsharp
3: punctuation.separator.namespace-definition.fsharp
4: entity.name.section.fsharp
push: push:
- meta_scope: meta.module.open.fsharp - meta_scope: namespace.alias.fsharp
- match: (\s|$) - match: (\s|$)
pop: true pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)' - match: '(\.)([A-Z][[:alpha:]0-9''_]*)'
scope: support.other.module.fsharp scope: entity.name.section.fsharp
captures: captures:
1: punctuation.separator.module-reference.fsharp 1: punctuation.separator.namespace-reference.fsharp
2: support.other.module.fsharp 2: entity.name.section.fsharp
- match: '^\s*(module)\s+([A-Z][a-zA-Z0-9''_]*)\s*(=)\s*([A-Z][a-zA-Z0-9''_]*)' record_declaration:
- match: '(\{)'
captures: captures:
1: keyword.other.module-definition.fsharp 1: keyword.symbol.fsharp
2: entity.name.type.module.fsharp
3: punctuation.separator.module-definition.fsharp
4: support.other.module.fsharp
push: push:
- meta_scope: meta.module.alias.fsharp - match: '(?<=\})'
- match: (\s|$)
pop: true pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)' - include: comments
scope: support.other.module.fsharp - match: '(((mutable)\s[[:alpha:]]+)|[[:alpha:]0-9''`<>^._]*)\s*((?<!:):(?!:))\s*'
captures: captures:
1: punctuation.separator.module-reference.fsharp 3: keyword.fsharp
2: support.other.module.fsharp 4: keyword.symbol.fsharp
- match: '(?<!\w)([A-Z][a-zA-Z0-9_]*)(\.)' push:
- match: '$|(;|\})'
captures:
1: keyword.symbol.fsharp
pop: true
- include: comments
- match: "([[:alpha:]0-9'`^_ ]+)"
captures:
1: entity.name.type.fsharp
- include: keywords
- include: compiler_directives
- include: constants
- include: strings
- include: chars
- include: double_tick
- include: definition
- include: attributes
- include: anonymous_functions
- include: keywords
- include: cexprs
- include: text
record_signature:
- match: "[[:alpha:]0-9'`^_ ]+(=)([[:alpha:]0-9'`^_ ]+)"
captures: captures:
1: support.other.module.fsharp 1: keyword.symbol.fsharp
2: punctuation.separator.module-reference.fsharp 2: variable.parameter.fsharp
- match: "({)"
captures:
1: keyword.symbol.fsharp
push: push:
- meta_scope: meta.module.reference.fsharp - match: "(})"
- match: '[A-Z][a-zA-Z0-9_]+(\.)'
scope: support.other.module.fsharp
captures: captures:
1: punctuation.separator.module-reference.fsharp 1: keyword.symbol.fsharp
- match: (?=.)
pop: true pop: true
- match: "[[:alpha:]0-9'`^_ ]+(=)([[:alpha:]0-9'`^_ ]+)"
captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
- include: record_signature
- include: keywords
records:
- match: '\b(type)[\s]+(private|internal|public)?\s*'
captures:
1: keyword.fsharp
2: keyword.fsharp
push:
- meta_scope: record.fsharp
- match: '\s*((with)|((as)\s+([[:alpha:]0-9'']+))|(=)|[\n=]|(\(\)))'
captures:
2: keyword.fsharp
3: keyword.fsharp
4: keyword.fsharp
5: variable.parameter.fsharp
6: keyword.symbol.fsharp
7: constant.language.unit.fsharp
pop: true
- include: comments
- include: attributes
- match: "([[:alpha:]0-9'^._]+|``[[:alpha:]0-9'`^:,._ ]+``)"
captures:
1: entity.name.type.fsharp
- match: (<)
captures:
1: keyword.fsharp
push:
- match: ((?<!:)>)
captures:
1: keyword.fsharp
pop: true
- match: '((''|\^)``[[:alpha:]0-9`^:,._ ]+``|(''|\^)[[:alpha:]0-9`^:._]+)'
captures:
1: entity.name.type.fsharp
- match: \b(interface|with|abstract|and|when|or|not|struct|equality|comparison|unmanaged|delegate|enum)\b
scope: keyword.fsharp
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: (\))
captures:
1: keyword.symbol.fsharp
pop: true
- match: (static member|member|new)
captures:
1: keyword.fsharp
- include: common_binding_definition
- match: '([\w0-9''`^._]+)'
captures:
1: entity.name.type.fsharp
- include: keywords
- match: \s*(private|internal|public)
captures:
1: keyword.symbol.fsharp
2: keyword.fsharp
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: '\s*(?=(=)|[\n=]|(\(\))|(as))'
captures:
1: keyword.symbol.fsharp
pop: true
- include: member_declaration
- include: keywords
string_formatter:
- match: (%0?-?(\d+)?((a|t)|(\.\d+)?(f|F|e|E|g|G|M)|(b|c|s|d|i|x|X|o|u)|(s|b|O)|(\+?A)))
scope: entity.name.type.format.specifier.fsharp
captures:
1: keyword.format.specifier.fsharp
strings: strings:
- match: '(?=[^\\])(""")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (""")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '(?=[^\\])(@")' - match: '(?=[^\\])(@")'
captures: captures:
1: punctuation.definition.string.begin.fsharp 1: punctuation.definition.string.begin.fsharp
push: push:
- meta_scope: string.quoted.double.fsharp - meta_scope: string.quoted.literal.fsharp
- match: (") - match: (")(?!")
captures: captures:
1: punctuation.definition.string.end.fsharp 1: punctuation.definition.string.end.fsharp
pop: true pop: true
- match: '\\$[ \t]*' - match: '"(")'
scope: punctuation.separator.string.ignore-eol.fsharp scope: constant.character.string.escape.fsharp
- match: '(?=[^\\])(""")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.triple.fsharp
- match: (""")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- include: string_formatter
- match: '(?=[^\\])(")' - match: '(?=[^\\])(")'
captures: captures:
1: punctuation.definition.string.begin.fsharp 1: punctuation.definition.string.begin.fsharp
@@ -201,34 +594,79 @@ contexts:
pop: true pop: true
- match: '\\$[ \t]*' - match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})' - match: '\\([\\''''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp scope: constant.character.string.escape.fsharp
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).' - match: '\\(?![\\''''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp scope: invalid.illeagal.character.string.fsharp
- match: '(?=[^\\])('')' - include: string_formatter
strp_inlined:
- match: (\()
captures: captures:
1: punctuation.definition.string.begin.fsharp 1: keyword.symbol.fsharp
push: push:
- meta_scope: string.quoted.double.fsharp - match: (\))
- match: (')
captures: captures:
1: punctuation.definition.string.end.fsharp 1: keyword.symbol.fsharp
pop: true pop: true
- match: '\\$[ \t]*' - include: strp_inlined_body
scope: punctuation.separator.string.ignore-eol.fsharp strp_inlined_body:
- match: '\\([\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})' - include: comments
scope: constant.character.string.escape.fsharp - include: anonymous_functions
- match: '\\(?![\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).' - match: '(\^[[:alpha:]0-9''._]+)'
scope: invalid.illeagal.character.string.fsharp captures:
structure: 1: entity.name.type.fsharp
- match: \( - match: \b(and|when|or)\b
scope: keyword.fsharp
- match: (\()
captures:
1: keyword.symbol.fsharp
push: push:
- meta_scope: meta.paren-group.fsharp - match: (\))
- match: \) captures:
1: keyword.symbol.fsharp
pop: true pop: true
- include: main - include: strp_inlined_body
- match: '(static member|member)\s*([[:alpha:]0-9''`<>^._]+|``[[:alpha:]0-9'' <>^._]+``)\s*(:)'
captures:
1: keyword.fsharp
2: variable.fsharp
3: keyword.symbol.fsharp
- include: compiler_directives
- include: constants
- include: strings
- include: chars
- include: double_tick
- include: keywords
- include: text
- include: definition
- include: attributes
- include: keywords
- include: cexprs
- include: text
text:
- match: \\
scope: text.fsharp
tuple_signature:
- match: "(([?[:alpha:]0-9'`^._ ]+))+"
captures:
1: entity.name.type.fsharp
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- match: (\))
captures:
1: keyword.symbol.fsharp
pop: true
- match: "(([?[:alpha:]0-9'`^._ ]+))+"
captures:
1: entity.name.type.fsharp
- include: tuple_signature
- include: keywords
variables: variables:
- match: \(\) - match: \(\)
scope: variable.parameter.unit.fsharp scope: constant.language.unit.fsharp
- match: '[a-zA-Z]\w*' - match: '(\?{0,1})(``[[:alpha:]0-9''`^:,._ ]+``|[[:alpha:]0-9''`<>^._ ]\w*)'
scope: variable.parameter.fsharp captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+504
View File
@@ -0,0 +1,504 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
The colors in this theme are encoded as #RRGGBBAA where RR is an ANSI
palette number from 00 to 0f, and AA is the special value 00 to indicate
that this encoding is being used.
-->
<key>author</key>
<string>Template: Chris Kempson, Scheme: Mitchell Kember</string>
<key>name</key>
<string>ANSI Dark</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#00000000</string>
<key>caret</key>
<string>#07000000</string>
<key>foreground</key>
<string>#07000000</string>
<key>invisibles</key>
<string>#07000000</string>
<key>lineHighlight</key>
<string>#07000000</string>
<key>selection</key>
<string>#07000000</string>
<key>gutter</key>
<string>#00000000</string>
<key>gutterForeground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Text</string>
<key>scope</key>
<string>variable.parameter.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comments</string>
<key>scope</key>
<string>comment, punctuation.definition.comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Delimiters</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Operators</string>
<key>scope</key>
<string>keyword.operator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keywords</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variables</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Functions</string>
<key>scope</key>
<string>entity.name.function, meta.require, support.function.any-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Methods</string>
<key>scope</key>
<string>keyword.other.special-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Strings, Inherited Class</string>
<key>scope</key>
<string>string, constant.other.symbol, entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Integers</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Floats</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constants</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attributes</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attribute IDs</string>
<key>scope</key>
<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Selector</string>
<key>scope</key>
<string>meta.selector</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Values</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Units</string>
<key>scope</key>
<string>keyword.other.unit</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Bold</string>
<key>scope</key>
<string>markup.bold, punctuation.definition.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic</string>
<key>scope</key>
<string>markup.italic, punctuation.definition.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Code</string>
<key>scope</key>
<string>markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Url</string>
<key>scope</key>
<string>meta.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Quotes</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Colors</string>
<key>scope</key>
<string>constant.other.color</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regular Expressions</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Escape Characters</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>punctuation.section.embedded, variable.interpolation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#01000000</string>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Broken</string>
<key>scope</key>
<string>invalid.broken</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#03000000</string>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>uuid</string>
</dict>
</plist>
+504
View File
@@ -0,0 +1,504 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
The colors in this theme are encoded as #RRGGBBAA where RR is an ANSI
palette number from 00 to 0f, and AA is the special value 00 to indicate
that this encoding is being used.
-->
<key>author</key>
<string>Template: Chris Kempson, Scheme: Mitchell Kember</string>
<key>name</key>
<string>ANSI Light</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#07000000</string>
<key>caret</key>
<string>#00000000</string>
<key>foreground</key>
<string>#00000000</string>
<key>invisibles</key>
<string>#00000000</string>
<key>lineHighlight</key>
<string>#00000000</string>
<key>selection</key>
<string>#00000000</string>
<key>gutter</key>
<string>#07000000</string>
<key>gutterForeground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Text</string>
<key>scope</key>
<string>variable.parameter.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comments</string>
<key>scope</key>
<string>comment, punctuation.definition.comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Delimiters</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Operators</string>
<key>scope</key>
<string>keyword.operator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keywords</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variables</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Functions</string>
<key>scope</key>
<string>entity.name.function, meta.require, support.function.any-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Methods</string>
<key>scope</key>
<string>keyword.other.special-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Strings, Inherited Class</string>
<key>scope</key>
<string>string, constant.other.symbol, entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Integers</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Floats</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constants</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attributes</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attribute IDs</string>
<key>scope</key>
<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Selector</string>
<key>scope</key>
<string>meta.selector</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Values</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Units</string>
<key>scope</key>
<string>keyword.other.unit</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Bold</string>
<key>scope</key>
<string>markup.bold, punctuation.definition.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic</string>
<key>scope</key>
<string>markup.italic, punctuation.definition.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Code</string>
<key>scope</key>
<string>markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Url</string>
<key>scope</key>
<string>meta.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Quotes</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Colors</string>
<key>scope</key>
<string>constant.other.color</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regular Expressions</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Escape Characters</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>punctuation.section.embedded, variable.interpolation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#01000000</string>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Broken</string>
<key>scope</key>
<string>invalid.broken</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#03000000</string>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>uuid</string>
</dict>
</plist>
+543
View File
@@ -0,0 +1,543 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
The colors in this theme are encoded as #RRGGBBAA where RR is an ANSI
palette number from 00 to 0f, and AA is the special value 00 to indicate
that this encoding is being used.
-->
<key>author</key>
<string>Template: Chris Kempson, Scheme: Mitchell Kember</string>
<key>name</key>
<string>Base16</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#00000000</string>
<key>caret</key>
<string>#07000000</string>
<key>foreground</key>
<string>#07000000</string>
<key>invisibles</key>
<string>#08000000</string>
<key>lineHighlight</key>
<string>#08000000</string>
<key>selection</key>
<string>#0b000000</string>
<key>gutter</key>
<string>#0a000000</string>
<key>gutterForeground</key>
<string>#08000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Text</string>
<key>scope</key>
<string>variable.parameter.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comments</string>
<key>scope</key>
<string>comment, punctuation.definition.comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#08000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Delimiters</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Operators</string>
<key>scope</key>
<string>keyword.operator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keywords</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variables</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Functions</string>
<key>scope</key>
<string>entity.name.function, meta.require, support.function.any-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Labels</string>
<key>scope</key>
<string>entity.name.label</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0e000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>support.class, entity.name.class, entity.name.type.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Classes</string>
<key>scope</key>
<string>meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0f000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Methods</string>
<key>scope</key>
<string>keyword.other.special-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Strings, Inherited Class</string>
<key>scope</key>
<string>string, constant.other.symbol, entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Integers</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Floats</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constants</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tags</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attributes</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Attribute IDs</string>
<key>scope</key>
<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Selector</string>
<key>scope</key>
<string>meta.selector</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Values</string>
<key>scope</key>
<string>none</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Headings</string>
<key>scope</key>
<string>markup.heading punctuation.definition.heading, entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#04000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Units</string>
<key>scope</key>
<string>keyword.other.unit</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Bold</string>
<key>scope</key>
<string>markup.bold, punctuation.definition.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#03000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic</string>
<key>scope</key>
<string>markup.italic, punctuation.definition.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Code</string>
<key>scope</key>
<string>markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Link Url</string>
<key>scope</key>
<string>meta.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Quotes</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#09000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Separator</string>
<key>scope</key>
<string>meta.separator</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0b000000</string>
<key>foreground</key>
<string>#07000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#02000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#01000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Colors</string>
<key>scope</key>
<string>constant.other.color</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regular Expressions</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Escape Characters</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#06000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>punctuation.section.embedded, variable.interpolation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#05000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#01000000</string>
<key>foreground</key>
<string>#0f000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Broken</string>
<key>scope</key>
<string>invalid.broken</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#09000000</string>
<key>foreground</key>
<string>#00000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Deprecated</string>
<key>scope</key>
<string>invalid.deprecated</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0e000000</string>
<key>foreground</key>
<string>#0f000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Unimplemented</string>
<key>scope</key>
<string>invalid.unimplemented</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#08000000</string>
<key>foreground</key>
<string>#0f000000</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>uuid</string>
</dict>
</plist>
+44
View File
@@ -43,6 +43,7 @@ pack() {
# TODO: disabled for now, see issue #372 # TODO: disabled for now, see issue #372
# cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".bash "$tempdir/$package_name/autocomplete/${PROJECT_NAME}.bash-completion" # cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".bash "$tempdir/$package_name/autocomplete/${PROJECT_NAME}.bash-completion"
# cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".fish "$tempdir/$package_name/autocomplete" # cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/"$PROJECT_NAME".fish "$tempdir/$package_name/autocomplete"
cp assets/completions/bat.fish "$tempdir/$package_name/autocomplete"
# cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/_"$PROJECT_NAME" "$tempdir/$package_name/autocomplete" # cp target/"$TARGET"/release/build/"$PROJECT_NAME"-*/out/_"$PROJECT_NAME" "$tempdir/$package_name/autocomplete"
# archiving # archiving
@@ -59,6 +60,11 @@ make_deb() {
local dpkgname local dpkgname
local conflictname local conflictname
local gcc_prefix local gcc_prefix
local homepage
local maintainer
homepage="https://github.com/sharkdp/bat"
maintainer="David Peter <mail@david-peter.de>"
case $TARGET in case $TARGET in
x86_64*) x86_64*)
@@ -105,6 +111,44 @@ make_deb() {
install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md" install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md"
install -Dm644 LICENSE-MIT "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-MIT" install -Dm644 LICENSE-MIT "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-MIT"
install -Dm644 LICENSE-APACHE "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-APACHE" install -Dm644 LICENSE-APACHE "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-APACHE"
cat > "$tempdir/usr/share/doc/$PROJECT_NAME/copyright" <<EOF
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: $PROJECT_NAME
Source: $homepage
Files: *
Copyright: $maintainer
License: Apache-2.0 or MIT
License: Apache-2.0
On Debian systems, the complete text of the Apache-2.0 can be found in the
file /usr/share/common-licenses/Apache-2.0.
License: MIT
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
.
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
EOF
# Control file # Control file
mkdir "$tempdir/DEBIAN" mkdir "$tempdir/DEBIAN"
+1 -1
View File
@@ -97,7 +97,7 @@ bat f - g # output 'f', then stdin, then 'g'.
最新の `.deb` パッケージを[こちら](https://github.com/sharkdp/bat/releases)からダウンロードして、インストールしてください: 最新の `.deb` パッケージを[こちら](https://github.com/sharkdp/bat/releases)からダウンロードして、インストールしてください:
``` bash ``` bash
sudo dpkg -i bat_0.10.0_amd64.deb # adapt version number and architecture sudo dpkg -i bat_0.11.0_amd64.deb # adapt version number and architecture
``` ```
### Arch Linux ### Arch Linux
+1 -1
View File
@@ -9,7 +9,7 @@ if you are not looking for a program like `bat`, this comparison might not be fo
| Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: | | Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: |
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: | | Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: |
| Languages (circa) | 100 | 300 | 200 | 7 | 80 | 130 | 30 | 130 | | Languages (circa) | 110 | 300 | 200 | 7 | 80 | 130 | 30 | 130 |
| Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: | | Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: |
| Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Execution time [ms] (`jquery-3.3.1.js`) | 624 | 789 | 400 | 80 | 300 | 316 | 157 | 695 | | Execution time [ms] (`jquery-3.3.1.js`) | 624 | 789 | 400 | 80 | 300 | 316 | 157 | 695 |
+11 -4
View File
@@ -47,7 +47,9 @@ values: *auto*, full, plain, changes, header, grid, numbers.
.HP .HP
\fB\-p\fR, \fB\-\-plain\fR \fB\-p\fR, \fB\-\-plain\fR
.IP .IP
Only show plain style, no decorations. This is an alias for '\-\-style=plain' Only show plain style, no decorations. This is an alias for '\-\-style=plain'. When '\-p'
is used twice ('\-pp'), it also disables automatic paging (alias for '\-\-style=plain
\fB\-\-pager\fR=\fI\,never\/\fR').
.HP .HP
\fB\-n\fR, \fB\-\-number\fR \fB\-n\fR, \fB\-\-number\fR
.IP .IP
@@ -58,7 +60,7 @@ Only show line numbers, no other decorations. This is an alias for '\-\-style=nu
Show non\-printable characters like space, tab or newline. Use '\-\-tabs' to control the Show non\-printable characters like space, tab or newline. Use '\-\-tabs' to control the
width of the tab\-placeholders. width of the tab\-placeholders.
.HP .HP
\fB\-\-line\-range\fR <N:M>... \fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
.IP .IP
Only print the specified range of lines for each file. For example: Only print the specified range of lines for each file. For example:
.RS .RS
@@ -70,6 +72,10 @@ prints lines 1 to 40
prints lines 40 to the end of the file prints lines 40 to the end of the file
.RE .RE
.HP .HP
\fB\-H\fR, \fB\-\-highlight\-line\fR <N>...
.IP
Highlight the N\-th line with a different background color
.HP
\fB\-\-color\fR <when> \fB\-\-color\fR <when>
.IP .IP
Specify when to use colored output. The automatic mode only enables colors if an Specify when to use colored output. The automatic mode only enables colors if an
@@ -101,7 +107,8 @@ the '\-\-paging' option. Example: '\-\-pager "less \fB\-RF\fR"'.
.HP .HP
\fB\-\-wrap\fR <mode> \fB\-\-wrap\fR <mode>
.IP .IP
Specify the text\-wrapping mode (*auto*, never, character). Specify the text\-wrapping mode (*auto*, never, character). The '\-\-terminal\-width' option
can be used in addition to control the output width.
.HP .HP
\fB\-\-tabs\fR <T> \fB\-\-tabs\fR <T>
.IP .IP
@@ -116,7 +123,7 @@ always unbuffered \- this option is simply ignored.
.IP .IP
Explicitly set the width of the terminal instead of determining it automatically. If Explicitly set the width of the terminal instead of determining it automatically. If
prefixed with '+' or '\-', the value will be treated as an offset to the actual terminal prefixed with '+' or '\-', the value will be treated as an offset to the actual terminal
width. width. See also: '\-\-wrap'.
.HP .HP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-\-help\fR
.IP .IP
+25 -24
View File
@@ -4,8 +4,8 @@ use std::str::FromStr;
use atty::{self, Stream}; use atty::{self, Stream};
use crate::clap_app;
use clap::ArgMatches; use clap::ArgMatches;
use clap_app;
use wild; use wild;
use console::Term; use console::Term;
@@ -13,14 +13,14 @@ use console::Term;
#[cfg(windows)] #[cfg(windows)]
use ansi_term; use ansi_term;
use assets::BAT_THEME_DEFAULT; use crate::assets::BAT_THEME_DEFAULT;
use config::{get_args_from_config_file, get_args_from_env_var}; use crate::config::{get_args_from_config_file, get_args_from_env_var};
use errors::*; use crate::errors::*;
use inputfile::InputFile; use crate::inputfile::InputFile;
use line_range::{LineRange, LineRanges}; use crate::line_range::{LineRange, LineRanges};
use style::{OutputComponent, OutputComponents, OutputWrap}; use crate::style::{OutputComponent, OutputComponents, OutputWrap};
use syntax_mapping::SyntaxMapping; use crate::syntax_mapping::SyntaxMapping;
use util::transpose; use crate::util::transpose;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum PagingMode { pub enum PagingMode {
@@ -120,7 +120,7 @@ impl App {
// Read arguments from bats config file // Read arguments from bats config file
let mut args = get_args_from_env_var() let mut args = get_args_from_env_var()
.unwrap_or_else(|| get_args_from_config_file()) .unwrap_or_else(get_args_from_config_file)
.chain_err(|| "Could not parse configuration file")?; .chain_err(|| "Could not parse configuration file")?;
// Put the zero-th CLI argument (program name) first // Put the zero-th CLI argument (program name) first
@@ -143,7 +143,10 @@ impl App {
Some("always") => PagingMode::Always, Some("always") => PagingMode::Always,
Some("never") => PagingMode::Never, Some("never") => PagingMode::Never,
Some("auto") | _ => { Some("auto") | _ => {
if files.contains(&InputFile::StdIn) { if self.matches.occurrences_of("plain") > 1 {
// If we have -pp as an option when in auto mode, the pager should be disabled.
PagingMode::Never
} else if files.contains(&InputFile::StdIn) {
// If we are reading from stdin, only enable paging if we write to an // If we are reading from stdin, only enable paging if we write to an
// interactive terminal and if we do not *read* from an interactive // interactive terminal and if we do not *read* from an interactive
// terminal. // terminal.
@@ -152,12 +155,10 @@ impl App {
} else { } else {
PagingMode::Never PagingMode::Never
} }
} else if self.interactive_output {
PagingMode::QuitIfOneScreen
} else { } else {
if self.interactive_output { PagingMode::Never
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
} }
} }
}; };
@@ -166,7 +167,7 @@ impl App {
if let Some(values) = self.matches.values_of("map-syntax") { if let Some(values) = self.matches.values_of("map-syntax") {
for from_to in values { for from_to in values {
let parts: Vec<_> = from_to.split(":").collect(); let parts: Vec<_> = from_to.split(':').collect();
if parts.len() != 2 { if parts.len() != 2 {
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is 'from:to'.".into()); return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is 'from:to'.".into());
@@ -213,11 +214,11 @@ impl App {
.matches .matches
.value_of("terminal-width") .value_of("terminal-width")
.and_then(|w| { .and_then(|w| {
if w.starts_with("+") || w.starts_with("-") { if w.starts_with('+') || w.starts_with('-') {
// Treat argument as a delta to the current terminal width // Treat argument as a delta to the current terminal width
w.parse().ok().map(|delta: i16| { w.parse().ok().map(|delta: i16| {
let old_width: u16 = Term::stdout().size().1; let old_width: u16 = Term::stdout().size().1;
let new_width: i32 = old_width as i32 + delta as i32; let new_width: i32 = i32::from(old_width) + i32::from(delta);
if new_width <= 0 { if new_width <= 0 {
old_width as usize old_width as usize
@@ -252,14 +253,14 @@ impl App {
.value_of("theme") .value_of("theme")
.map(String::from) .map(String::from)
.or_else(|| env::var("BAT_THEME").ok()) .or_else(|| env::var("BAT_THEME").ok())
.unwrap_or(String::from(BAT_THEME_DEFAULT)), .unwrap_or_else(|| String::from(BAT_THEME_DEFAULT)),
line_ranges: LineRanges::from( line_ranges: LineRanges::from(
transpose( transpose(
self.matches self.matches
.values_of("line-range") .values_of("line-range")
.map(|vs| vs.map(LineRange::from).collect()), .map(|vs| vs.map(LineRange::from).collect()),
)? )?
.unwrap_or(vec![]), .unwrap_or_else(|| vec![]),
), ),
output_components, output_components,
syntax_mapping, syntax_mapping,
@@ -306,7 +307,7 @@ impl App {
let env_style_components: Option<Vec<OutputComponent>> = let env_style_components: Option<Vec<OutputComponent>> =
transpose(env::var("BAT_STYLE").ok().map(|style_str| { transpose(env::var("BAT_STYLE").ok().map(|style_str| {
style_str style_str
.split(",") .split(',')
.map(|x| OutputComponent::from_str(&x)) .map(|x| OutputComponent::from_str(&x))
.collect::<Result<Vec<OutputComponent>>>() .collect::<Result<Vec<OutputComponent>>>()
}))?; }))?;
@@ -315,13 +316,13 @@ impl App {
.value_of("style") .value_of("style")
.map(|styles| { .map(|styles| {
styles styles
.split(",") .split(',')
.map(|style| style.parse::<OutputComponent>()) .map(|style| style.parse::<OutputComponent>())
.filter_map(|style| style.ok()) .filter_map(|style| style.ok())
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.or(env_style_components) .or(env_style_components)
.unwrap_or(vec![OutputComponent::Full]) .unwrap_or_else(|| vec![OutputComponent::Full])
.into_iter() .into_iter()
.map(|style| style.components(self.interactive_output)) .map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| { .fold(HashSet::new(), |mut acc, components| {
+7 -7
View File
@@ -8,11 +8,11 @@ use syntect::dumps::{dump_to_file, from_binary, from_reader};
use syntect::highlighting::{Theme, ThemeSet}; use syntect::highlighting::{Theme, ThemeSet};
use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder}; use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder};
use dirs::PROJECT_DIRS; use crate::dirs::PROJECT_DIRS;
use errors::*; use crate::errors::*;
use inputfile::{InputFile, InputFileReader}; use crate::inputfile::{InputFile, InputFileReader};
use syntax_mapping::SyntaxMapping; use crate::syntax_mapping::SyntaxMapping;
pub const BAT_THEME_DEFAULT: &str = "Monokai Extended"; pub const BAT_THEME_DEFAULT: &str = "Monokai Extended";
@@ -40,7 +40,7 @@ impl HighlightingAssets {
let theme_dir = source_dir.join("themes"); let theme_dir = source_dir.join("themes");
let res = theme_set.add_from_folder(&theme_dir); let res = theme_set.add_from_folder(&theme_dir);
if !res.is_ok() { if res.is_err() {
println!( println!(
"No themes were found in '{}', using the default set", "No themes were found in '{}', using the default set",
theme_dir.to_string_lossy() theme_dir.to_string_lossy()
@@ -191,8 +191,8 @@ impl HighlightingAssets {
} else { } else {
None None
}; };
let syntax = ext_syntax.or(line_syntax);
syntax ext_syntax.or(line_syntax)
} }
(None, InputFile::StdIn) => String::from_utf8(reader.first_line.clone()) (None, InputFile::StdIn) => String::from_utf8(reader.first_line.clone())
.ok() .ok()
+20 -5
View File
@@ -18,7 +18,6 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.global_setting(AppSettings::DeriveDisplayOrder) .global_setting(AppSettings::DeriveDisplayOrder)
.global_setting(AppSettings::UnifiedHelpMessage) .global_setting(AppSettings::UnifiedHelpMessage)
.global_setting(AppSettings::HidePossibleValuesInHelp) .global_setting(AppSettings::HidePossibleValuesInHelp)
.setting(AppSettings::InferSubcommands)
.setting(AppSettings::ArgsNegateSubcommands) .setting(AppSettings::ArgsNegateSubcommands)
.setting(AppSettings::DisableHelpSubcommand) .setting(AppSettings::DisableHelpSubcommand)
.setting(AppSettings::VersionlessSubcommands) .setting(AppSettings::VersionlessSubcommands)
@@ -109,7 +108,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.overrides_with("number") .overrides_with("number")
// Cannot use clap's built in validation because we have to turn off clap's delimiters // Cannot use clap's built in validation because we have to turn off clap's delimiters
.validator(|val| { .validator(|val| {
let mut invalid_vals = val.split(",").filter(|style| { let mut invalid_vals = val.split(',').filter(|style| {
!&[ !&[
"auto", "full", "plain", "changes", "header", "grid", "numbers", "auto", "full", "plain", "changes", "header", "grid", "numbers",
] ]
@@ -143,10 +142,12 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.overrides_with("number") .overrides_with("number")
.short("p") .short("p")
.long("plain") .long("plain")
.multiple(true)
.help("Show plain style (alias for '--style=plain').") .help("Show plain style (alias for '--style=plain').")
.long_help( .long_help(
"Only show plain style, no decorations. This is an alias for \ "Only show plain style, no decorations. This is an alias for \
'--style=plain'", '--style=plain'. When '-p' is used twice ('-pp'), it also disables \
automatic paging (alias for '--style=plain --pager=never').",
), ),
) )
.arg( .arg(
@@ -290,7 +291,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.default_value("auto") .default_value("auto")
.hide_default_value(true) .hide_default_value(true)
.help("Specify the text-wrapping mode (*auto*, never, character).") .help("Specify the text-wrapping mode (*auto*, never, character).")
.long_help("Specify the text-wrapping mode (*auto*, never, character)."), .long_help("Specify the text-wrapping mode (*auto*, never, character). \
The '--terminal-width' option can be used in addition to \
control the output width."),
) )
.arg( .arg(
Arg::with_name("tabs") Arg::with_name("tabs")
@@ -329,10 +332,22 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.takes_value(true) .takes_value(true)
.value_name("width") .value_name("width")
.hidden_short_help(true) .hidden_short_help(true)
.validator(
|t| {
let is_offset = t.starts_with('+') || t.starts_with('-');
t.parse::<i32>()
.map_err(|_e| "must be an offset or number")
.and_then(|v| if v == 0 && !is_offset {
Err("terminal width cannot be zero".into())
} else {
Ok(())
})
.map_err(|e| e.to_string())
})
.help( .help(
"Explicitly set the width of the terminal instead of determining it \ "Explicitly set the width of the terminal instead of determining it \
automatically. If prefixed with '+' or '-', the value will be treated \ automatically. If prefixed with '+' or '-', the value will be treated \
as an offset to the actual terminal width.", as an offset to the actual terminal width. See also: '--wrap'.",
), ),
) )
.arg( .arg(
+6 -6
View File
@@ -5,15 +5,15 @@ use std::path::PathBuf;
use shell_words; use shell_words;
use dirs::PROJECT_DIRS; use crate::dirs::PROJECT_DIRS;
use util::transpose; use crate::util::transpose;
pub fn config_file() -> PathBuf { pub fn config_file() -> PathBuf {
env::var("BAT_CONFIG_PATH") env::var("BAT_CONFIG_PATH")
.ok() .ok()
.map(PathBuf::from) .map(PathBuf::from)
.filter(|config_path| config_path.is_file()) .filter(|config_path| config_path.is_file())
.unwrap_or(PROJECT_DIRS.config_dir().join("config")) .unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
} }
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> { pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
@@ -22,19 +22,19 @@ pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseEr
.ok() .ok()
.map(|content| get_args_from_str(&content)), .map(|content| get_args_from_str(&content)),
)? )?
.unwrap_or(vec![])) .unwrap_or_else(|| vec![]))
} }
pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> { pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s)) env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
} }
fn get_args_from_str<'a>(content: &'a str) -> Result<Vec<OsString>, shell_words::ParseError> { fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseError> {
let args_per_line = content let args_per_line = content
.split('\n') .split('\n')
.map(|line| line.trim()) .map(|line| line.trim())
.filter(|line| !line.is_empty()) .filter(|line| !line.is_empty())
.filter(|line| !line.starts_with("#")) .filter(|line| !line.starts_with('#'))
.map(|line| shell_words::split(line)) .map(|line| shell_words::split(line))
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
+11 -10
View File
@@ -1,13 +1,13 @@
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::Path; use std::path::Path;
use app::{Config, PagingMode}; use crate::app::{Config, PagingMode};
use assets::HighlightingAssets; use crate::assets::HighlightingAssets;
use errors::*; use crate::errors::*;
use inputfile::{InputFile, InputFileReader}; use crate::inputfile::{InputFile, InputFileReader};
use line_range::{LineRanges, RangeCheckResult}; use crate::line_range::{LineRanges, RangeCheckResult};
use output::OutputType; use crate::output::OutputType;
use printer::{InteractivePrinter, Printer, SimplePrinter}; use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
pub struct Controller<'a> { pub struct Controller<'a> {
config: &'a Config<'a>, config: &'a Config<'a>,
@@ -43,7 +43,6 @@ impl<'b> Controller<'b> {
for input_file in &self.config.files { for input_file in &self.config.files {
match input_file.get_reader(&stdin) { match input_file.get_reader(&stdin) {
Err(Error(ErrorKind::ImmediateEOF, _)) => (),
Err(error) => { Err(error) => {
handle_error(&error); handle_error(&error);
no_errors = false; no_errors = false;
@@ -81,13 +80,15 @@ impl<'b> Controller<'b> {
input_file: InputFile<'a>, input_file: InputFile<'a>,
) -> Result<()> { ) -> Result<()> {
printer.print_header(writer, input_file)?; printer.print_header(writer, input_file)?;
self.print_file_ranges(printer, writer, reader, &self.config.line_ranges)?; if !reader.first_line.is_empty() {
self.print_file_ranges(printer, writer, reader, &self.config.line_ranges)?;
}
printer.print_footer(writer)?; printer.print_footer(writer)?;
Ok(()) Ok(())
} }
fn print_file_ranges<'a, P: Printer>( fn print_file_ranges<P: Printer>(
&self, &self,
printer: &mut P, printer: &mut P,
writer: &mut Write, writer: &mut Write,
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::diff::LineChange;
use crate::printer::{Colors, InteractivePrinter};
use ansi_term::Style; use ansi_term::Style;
use diff::LineChange;
use printer::{Colors, InteractivePrinter};
#[derive(Clone)] #[derive(Clone)]
pub struct DecorationText { pub struct DecorationText {
+1 -1
View File
@@ -1,4 +1,4 @@
use dirs_rs; use crate::dirs_rs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
+18 -16
View File
@@ -3,41 +3,43 @@ use std::io::{self, BufRead, BufReader};
use content_inspector::{self, ContentType}; use content_inspector::{self, ContentType};
use errors::*; use crate::errors::*;
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs"); const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
pub struct InputFileReader<'a> { pub struct InputFileReader<'a> {
inner: Box<dyn BufRead + 'a>, inner: Box<dyn BufRead + 'a>,
pub first_line: Vec<u8>, pub first_line: Vec<u8>,
pub content_type: ContentType, pub content_type: Option<ContentType>,
} }
impl<'a> InputFileReader<'a> { impl<'a> InputFileReader<'a> {
fn new<R: BufRead + 'a>(mut reader: R) -> Result<InputFileReader<'a>> { fn new<R: BufRead + 'a>(mut reader: R) -> InputFileReader<'a> {
let mut first_line = vec![]; let mut first_line = vec![];
if reader.read_until(b'\n', &mut first_line)? == 0 { reader.read_until(b'\n', &mut first_line).ok();
return Err(ErrorKind::ImmediateEOF.into());
}
let content_type = content_inspector::inspect(&first_line[..]); let content_type = if first_line.is_empty() {
None
} else {
Some(content_inspector::inspect(&first_line[..]))
};
if content_type == ContentType::UTF_16LE { if content_type == Some(ContentType::UTF_16LE) {
reader.read_until(0x00, &mut first_line).ok(); reader.read_until(0x00, &mut first_line).ok();
} }
Ok(InputFileReader { InputFileReader {
inner: Box::new(reader), inner: Box::new(reader),
first_line, first_line,
content_type, content_type,
}) }
} }
pub fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> { pub fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
if self.first_line.is_empty() { if self.first_line.is_empty() {
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?; let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
if self.content_type == ContentType::UTF_16LE { if self.content_type == Some(ContentType::UTF_16LE) {
self.inner.read_until(0x00, buf).ok(); self.inner.read_until(0x00, buf).ok();
} }
@@ -59,7 +61,7 @@ pub enum InputFile<'a> {
impl<'a> InputFile<'a> { impl<'a> InputFile<'a> {
pub fn get_reader(&self, stdin: &'a io::Stdin) -> Result<InputFileReader> { pub fn get_reader(&self, stdin: &'a io::Stdin) -> Result<InputFileReader> {
match self { match self {
InputFile::StdIn => InputFileReader::new(stdin.lock()), InputFile::StdIn => Ok(InputFileReader::new(stdin.lock())),
InputFile::Ordinary(filename) => { InputFile::Ordinary(filename) => {
let file = File::open(filename).map_err(|e| format!("'{}': {}", filename, e))?; let file = File::open(filename).map_err(|e| format!("'{}': {}", filename, e))?;
@@ -67,9 +69,9 @@ impl<'a> InputFile<'a> {
return Err(format!("'{}' is a directory.", filename).into()); return Err(format!("'{}' is a directory.", filename).into());
} }
InputFileReader::new(BufReader::new(file)) Ok(InputFileReader::new(BufReader::new(file)))
} }
InputFile::ThemePreviewFile => InputFileReader::new(THEME_PREVIEW_FILE), InputFile::ThemePreviewFile => Ok(InputFileReader::new(THEME_PREVIEW_FILE)),
} }
} }
} }
@@ -77,7 +79,7 @@ impl<'a> InputFile<'a> {
#[test] #[test]
fn basic() { fn basic() {
let content = b"#!/bin/bash\necho hello"; let content = b"#!/bin/bash\necho hello";
let mut reader = InputFileReader::new(&content[..]).unwrap(); let mut reader = InputFileReader::new(&content[..]);
assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]); assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]);
@@ -106,7 +108,7 @@ fn basic() {
#[test] #[test]
fn utf16le() { fn utf16le() {
let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00"; let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00";
let mut reader = InputFileReader::new(&content[..]).unwrap(); let mut reader = InputFileReader::new(&content[..]);
assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]); assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]);
+5 -11
View File
@@ -1,4 +1,4 @@
use errors::*; use crate::errors::*;
#[derive(Clone)] #[derive(Clone)]
pub struct LineRange { pub struct LineRange {
@@ -109,18 +109,12 @@ impl LineRanges {
} }
pub fn check(&self, line: usize) -> RangeCheckResult { pub fn check(&self, line: usize) -> RangeCheckResult {
if self.ranges.is_empty() { if self.ranges.is_empty() | self.ranges.iter().any(|r| r.is_inside(line)) {
RangeCheckResult::InRange RangeCheckResult::InRange
} else if line < self.largest_upper_bound {
RangeCheckResult::OutsideRange
} else { } else {
if self.ranges.iter().any(|r| r.is_inside(line)) { RangeCheckResult::AfterLastRange
RangeCheckResult::InRange
} else {
if line < self.largest_upper_bound {
RangeCheckResult::OutsideRange
} else {
RangeCheckResult::AfterLastRange
}
}
} }
} }
} }
+52 -49
View File
@@ -48,12 +48,12 @@ use std::process;
use ansi_term::Colour::Green; use ansi_term::Colour::Green;
use ansi_term::Style; use ansi_term::Style;
use app::{App, Config}; use crate::app::{App, Config};
use assets::{cache_dir, clear_assets, config_dir, HighlightingAssets}; use crate::assets::{cache_dir, clear_assets, config_dir, HighlightingAssets};
use config::config_file; use crate::config::config_file;
use controller::Controller; use crate::controller::Controller;
use inputfile::InputFile; use crate::inputfile::InputFile;
use style::{OutputComponent, OutputComponents}; use crate::style::{OutputComponent, OutputComponents};
mod errors { mod errors {
error_chain! { error_chain! {
@@ -63,14 +63,11 @@ mod errors {
SyntectError(::syntect::LoadingError); SyntectError(::syntect::LoadingError);
ParseIntError(::std::num::ParseIntError); ParseIntError(::std::num::ParseIntError);
} }
errors {
ImmediateEOF
}
} }
pub fn handle_error(error: &Error) { pub fn handle_error(error: &Error) {
match error { match error {
&Error(ErrorKind::Io(ref io_error), _) Error(ErrorKind::Io(ref io_error), _)
if io_error.kind() == super::io::ErrorKind::BrokenPipe => if io_error.kind() == super::io::ErrorKind::BrokenPipe =>
{ {
super::process::exit(0); super::process::exit(0);
@@ -83,7 +80,7 @@ mod errors {
} }
} }
use errors::*; use crate::errors::*;
fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> { fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
if matches.is_present("build") { if matches.is_present("build") {
@@ -111,48 +108,54 @@ pub fn list_languages(config: &Config) -> Result<()> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
languages.sort_by_key(|lang| lang.name.to_uppercase()); languages.sort_by_key(|lang| lang.name.to_uppercase());
let longest = languages
.iter()
.map(|syntax| syntax.name.len())
.max()
.unwrap_or(32); // Fallback width if they have no language definitions.
let comma_separator = ", ";
let separator = " ";
// Line-wrapping for the possible file extension overflow.
let desired_width = config.term_width - longest - separator.len();
let stdout = io::stdout(); let stdout = io::stdout();
let mut stdout = stdout.lock(); let mut stdout = stdout.lock();
let style = if config.colored_output { if config.loop_through {
Green.normal() for lang in languages {
} else { write!(stdout, "{}:{}\n", lang.name, lang.file_extensions.join(","))?;
Style::default() }
}; } else {
let longest = languages
for lang in languages { .iter()
write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?; .map(|syntax| syntax.name.len())
.max()
// Number of characters on this line so far, wrap before `desired_width` .unwrap_or(32); // Fallback width if they have no language definitions.
let mut num_chars = 0;
let comma_separator = ", ";
let mut extension = lang.file_extensions.iter().peekable(); let separator = " ";
while let Some(word) = extension.next() { // Line-wrapping for the possible file extension overflow.
// If we can't fit this word in, then create a line break and align it in. let desired_width = config.term_width - longest - separator.len();
let new_chars = word.len() + comma_separator.len();
if num_chars + new_chars >= desired_width { let style = if config.colored_output {
num_chars = 0; Green.normal()
write!(stdout, "\n{:width$}{}", "", separator, width = longest)?; } else {
} Style::default()
};
num_chars += new_chars;
write!(stdout, "{}", style.paint(&word[..]))?; for lang in languages {
if extension.peek().is_some() { write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
write!(stdout, "{}", comma_separator)?;
} // Number of characters on this line so far, wrap before `desired_width`
let mut num_chars = 0;
let mut extension = lang.file_extensions.iter().peekable();
while let Some(word) = extension.next() {
// If we can't fit this word in, then create a line break and align it in.
let new_chars = word.len() + comma_separator.len();
if num_chars + new_chars >= desired_width {
num_chars = 0;
write!(stdout, "\n{:width$}{}", "", separator, width = longest)?;
}
num_chars += new_chars;
write!(stdout, "{}", style.paint(&word[..]))?;
if extension.peek().is_some() {
write!(stdout, "{}", comma_separator)?;
}
}
writeln!(stdout)?;
} }
writeln!(stdout)?;
} }
Ok(()) Ok(())
+9 -4
View File
@@ -6,8 +6,8 @@ use std::process::{Child, Command, Stdio};
use shell_words; use shell_words;
use app::PagingMode; use crate::app::PagingMode;
use errors::*; use crate::errors::*;
pub enum OutputType { pub enum OutputType {
Pager(Child), Pager(Child),
@@ -43,10 +43,15 @@ impl OutputType {
_ => None, _ => None,
}; };
let pager_from_config = pager_from_config.map(|p| p.to_string());
if pager_from_config.is_some() {
replace_arguments_to_less = false;
}
let pager = pager_from_config let pager = pager_from_config
.map(|p| p.to_string())
.or(pager_from_env) .or(pager_from_env)
.unwrap_or(String::from("less")); .unwrap_or_else(|| String::from("less"));
let pagerflags = let pagerflags =
shell_words::split(&pager).chain_err(|| "Could not parse pager command.")?; shell_words::split(&pager).chain_err(|| "Could not parse pager command.")?;
+59 -31
View File
@@ -16,16 +16,18 @@ use content_inspector::ContentType;
use encoding::all::{UTF_16BE, UTF_16LE}; use encoding::all::{UTF_16BE, UTF_16LE};
use encoding::{DecoderTrap, Encoding}; use encoding::{DecoderTrap, Encoding};
use app::Config; use crate::app::Config;
use assets::HighlightingAssets; use crate::assets::HighlightingAssets;
use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration}; use crate::decorations::{
use diff::get_git_diff; Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration,
use diff::LineChanges; };
use errors::*; use crate::diff::get_git_diff;
use inputfile::{InputFile, InputFileReader}; use crate::diff::LineChanges;
use preprocessor::{expand_tabs, replace_nonprintable}; use crate::errors::*;
use style::OutputWrap; use crate::inputfile::{InputFile, InputFileReader};
use terminal::{as_terminal_escaped, to_ansi_color}; use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::OutputWrap;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
pub trait Printer { pub trait Printer {
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()>; fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()>;
@@ -64,7 +66,7 @@ impl Printer for SimplePrinter {
line_buffer: &[u8], line_buffer: &[u8],
) -> Result<()> { ) -> Result<()> {
if !out_of_range { if !out_of_range {
handle.write(line_buffer)?; handle.write_all(line_buffer)?;
} }
Ok(()) Ok(())
} }
@@ -76,7 +78,7 @@ pub struct InteractivePrinter<'a> {
decorations: Vec<Box<dyn Decoration>>, decorations: Vec<Box<dyn Decoration>>,
panel_width: usize, panel_width: usize,
ansi_prefix_sgr: String, ansi_prefix_sgr: String,
content_type: ContentType, content_type: Option<ContentType>,
pub line_changes: Option<LineChanges>, pub line_changes: Option<LineChanges>,
highlighter: Option<HighlightLines<'a>>, highlighter: Option<HighlightLines<'a>>,
syntax_set: &'a SyntaxSet, syntax_set: &'a SyntaxSet,
@@ -132,7 +134,7 @@ impl<'a> InteractivePrinter<'a> {
let mut line_changes = None; let mut line_changes = None;
let highlighter = if reader.content_type.is_binary() { let highlighter = if reader.content_type.map_or(false, |c| c.is_binary()) {
None None
} else { } else {
// Get the Git modifications // Get the Git modifications
@@ -192,6 +194,20 @@ impl<'a> InteractivePrinter<'a> {
impl<'a> Printer for InteractivePrinter<'a> { impl<'a> Printer for InteractivePrinter<'a> {
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()> { fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()> {
if !self.config.output_components.header() { if !self.config.output_components.header() {
if Some(ContentType::BINARY) == self.content_type {
let input = match file {
InputFile::Ordinary(filename) => format!("file '{}'", filename),
_ => "STDIN".into(),
};
writeln!(
handle,
"{}: Binary content from {} will not be printed to the terminal \
(but will be present if the output of 'bat' is piped).",
Yellow.paint("[bat warning]"),
input
)?;
}
return Ok(()); return Ok(());
} }
@@ -216,9 +232,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
}; };
let mode = match self.content_type { let mode = match self.content_type {
ContentType::BINARY => " <BINARY>", Some(ContentType::BINARY) => " <BINARY>",
ContentType::UTF_16LE => " <UTF-16LE>", Some(ContentType::UTF_16LE) => " <UTF-16LE>",
ContentType::UTF_16BE => " <UTF-16BE>", Some(ContentType::UTF_16BE) => " <UTF-16BE>",
None => " <EMPTY>",
_ => "", _ => "",
}; };
@@ -231,7 +248,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
)?; )?;
if self.config.output_components.grid() { if self.config.output_components.grid() {
if self.content_type.is_text() { if self.content_type.map_or(false, |c| c.is_text()) {
self.print_horizontal_line(handle, '┼')?; self.print_horizontal_line(handle, '┼')?;
} else { } else {
self.print_horizontal_line(handle, '┴')?; self.print_horizontal_line(handle, '┴')?;
@@ -242,7 +259,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
} }
fn print_footer(&mut self, handle: &mut Write) -> Result<()> { fn print_footer(&mut self, handle: &mut Write) -> Result<()> {
if self.config.output_components.grid() && self.content_type.is_text() { if self.config.output_components.grid() && self.content_type.map_or(false, |c| c.is_text())
{
self.print_horizontal_line(handle, '┴') self.print_horizontal_line(handle, '┴')
} else { } else {
Ok(()) Ok(())
@@ -257,20 +275,20 @@ impl<'a> Printer for InteractivePrinter<'a> {
line_buffer: &[u8], line_buffer: &[u8],
) -> Result<()> { ) -> Result<()> {
let mut line = match self.content_type { let mut line = match self.content_type {
ContentType::BINARY => { Some(ContentType::BINARY) | None => {
return Ok(()); return Ok(());
} }
ContentType::UTF_16LE => UTF_16LE Some(ContentType::UTF_16LE) => UTF_16LE
.decode(&line_buffer, DecoderTrap::Strict) .decode(&line_buffer, DecoderTrap::Replace)
.unwrap_or("Invalid UTF-16LE".into()), .map_err(|_| "Invalid UTF-16LE")?,
ContentType::UTF_16BE => UTF_16BE Some(ContentType::UTF_16BE) => UTF_16BE
.decode(&line_buffer, DecoderTrap::Strict) .decode(&line_buffer, DecoderTrap::Replace)
.unwrap_or("Invalid UTF-16BE".into()), .map_err(|_| "Invalid UTF-16BE")?,
_ => String::from_utf8_lossy(&line_buffer).to_string(), _ => String::from_utf8_lossy(&line_buffer).to_string(),
}; };
if self.config.show_nonprintable { if self.config.show_nonprintable {
line = replace_nonprintable(&mut line, self.config.tab_width); line = replace_nonprintable(&line, self.config.tab_width);
} }
let regions = { let regions = {
@@ -355,25 +373,35 @@ impl<'a> Printer for InteractivePrinter<'a> {
} }
if line.bytes().next_back() != Some(b'\n') { if line.bytes().next_back() != Some(b'\n') {
write!(handle, "\n")?; writeln!(handle)?;
} }
} else { } else {
for &(style, region) in regions.iter() { for &(style, region) in regions.iter() {
let mut ansi_iterator = AnsiCodeIterator::new(region); let ansi_iterator = AnsiCodeIterator::new(region);
let mut ansi_prefix: String = String::new(); let mut ansi_prefix: String = String::new();
for chunk in ansi_iterator { for chunk in ansi_iterator {
match chunk { match chunk {
// ANSI escape passthrough. // ANSI escape passthrough.
(text, true) => { (text, true) => {
if text.chars().last().map_or(false, |c| c == 'm') { let is_ansi_csi = text.starts_with("\x1B[");
if is_ansi_csi && text.ends_with('m') {
// It's an ANSI SGR sequence.
// We should be mostly safe to just append these together.
ansi_prefix.push_str(text); ansi_prefix.push_str(text);
if text == "\x1B[0m" { if text == "\x1B[0m" {
self.ansi_prefix_sgr = "\x1B[0m".to_owned(); self.ansi_prefix_sgr = "\x1B[0m".to_owned();
} else { } else {
self.ansi_prefix_sgr.push_str(text); self.ansi_prefix_sgr.push_str(text);
} }
} else { } else if is_ansi_csi {
// It's a regular CSI sequence.
// We should be mostly safe to just append these together.
ansi_prefix.push_str(text); ansi_prefix.push_str(text);
} else {
// It's probably a VT100 code.
// Passing it through is the safest bet.
write!(handle, "{}", text)?;
} }
} }
@@ -472,7 +500,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
ansi_style.paint(" ".repeat(cursor_max - cursor)) ansi_style.paint(" ".repeat(cursor_max - cursor))
)?; )?;
} }
write!(handle, "\n")?; writeln!(handle)?;
} }
Ok(()) Ok(())
+3 -3
View File
@@ -1,7 +1,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::str::FromStr; use std::str::FromStr;
use errors::*; use crate::errors::*;
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum OutputComponent { pub enum OutputComponent {
@@ -21,8 +21,8 @@ pub enum OutputWrap {
} }
impl OutputComponent { impl OutputComponent {
pub fn components(&self, interactive_terminal: bool) -> &'static [OutputComponent] { pub fn components(self, interactive_terminal: bool) -> &'static [OutputComponent] {
match *self { match self {
OutputComponent::Auto => { OutputComponent::Auto => {
if interactive_terminal { if interactive_terminal {
OutputComponent::Full.components(interactive_terminal) OutputComponent::Full.components(interactive_terminal)
+2 -2
View File
@@ -1,12 +1,12 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct SyntaxMapping(HashMap<String, String>); pub struct SyntaxMapping(HashMap<String, String>);
impl SyntaxMapping { impl SyntaxMapping {
pub fn new() -> SyntaxMapping { pub fn new() -> SyntaxMapping {
SyntaxMapping(HashMap::new()) Default::default()
} }
pub fn insert(&mut self, from: impl Into<String>, to: impl Into<String>) -> Option<String> { pub fn insert(&mut self, from: impl Into<String>, to: impl Into<String>) -> Option<String> {
+7 -1
View File
@@ -6,7 +6,13 @@ use ansi_term::{self, Style};
use syntect::highlighting::{self, FontStyle}; use syntect::highlighting::{self, FontStyle};
pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> ansi_term::Colour { pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> ansi_term::Colour {
if true_color { if color.a == 0 {
// Themes can specify one of the user-configurable terminal colors by
// encoding them as #RRGGBBAA with AA set to 00 (transparent) and RR set
// to the color palette number. The built-in themes ansi-light,
// ansi-dark, and base16 use this.
Fixed(color.r)
} else if true_color {
RGB(color.r, color.g, color.b) RGB(color.r, color.g, color.b)
} else { } else {
Fixed(ansi_colours::ansi256_from_rgb((color.r, color.g, color.b))) Fixed(ansi_colours::ansi256_from_rgb((color.r, color.g, color.b)))
+1
View File
@@ -0,0 +1 @@
test
View File
+1
View File
@@ -0,0 +1 @@
Single Line
Binary file not shown.
+100
View File
@@ -76,6 +76,79 @@ fn concatenate_stdin() {
.stdout("hello world\nstdin\nhello world\n"); .stdout("hello world\nstdin\nhello world\n");
} }
#[test]
fn concatenate_empty_first() {
bat()
.arg("empty.txt")
.arg("test.txt")
.assert()
.success()
.stdout("hello world\n");
}
#[test]
fn concatenate_empty_last() {
bat()
.arg("test.txt")
.arg("empty.txt")
.assert()
.success()
.stdout("hello world\n");
}
#[test]
fn concatenate_empty_both() {
bat()
.arg("empty.txt")
.arg("empty.txt")
.assert()
.success()
.stdout("");
}
#[test]
fn concatenate_empty_between() {
bat()
.arg("test.txt")
.arg("empty.txt")
.arg("test.txt")
.assert()
.success()
.stdout("hello world\nhello world\n");
}
#[test]
fn concatenate_empty_first_and_last() {
bat()
.arg("empty.txt")
.arg("test.txt")
.arg("empty.txt")
.assert()
.success()
.stdout("hello world\n");
}
#[test]
fn concatenate_single_line() {
bat()
.arg("single-line.txt")
.arg("single-line.txt")
.assert()
.success()
.stdout("Single LineSingle Line");
}
#[test]
fn concatenate_single_line_empty() {
bat()
.arg("single-line.txt")
.arg("empty.txt")
.arg("single-line.txt")
.assert()
.success()
.stdout("Single LineSingle Line");
}
#[test] #[test]
fn line_numbers() { fn line_numbers() {
bat() bat()
@@ -363,3 +436,30 @@ fn config_read_arguments_from_file() {
.success() .success()
.stdout("dummy-pager-from-config\n"); .stdout("dummy-pager-from-config\n");
} }
#[test]
fn utf16() {
// The output will be converted to UTF-8 with a leading UTF-8 BOM
bat()
.arg("--plain")
.arg("--decorations=always")
.arg("test_UTF-16LE.txt")
.assert()
.success()
.stdout(std::str::from_utf8(b"\xEF\xBB\xBFhello world\n").unwrap());
}
#[test]
fn can_print_file_named_cache() {
bat()
.arg("cache")
.assert()
.success()
.stdout("test\n")
.stderr("");
}
#[test]
fn does_not_print_unwanted_file_named_cache() {
bat_with_config().arg("cach").assert().failure();
}
+1 -1
View File
@@ -1,6 +1,6 @@
mod tester; mod tester;
use tester::BatTester; use crate::tester::BatTester;
macro_rules! snapshot_tests { macro_rules! snapshot_tests {
($($test_name: ident: $style: expr,)*) => { ($($test_name: ident: $style: expr,)*) => {