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

Compare commits

..

355 Commits

Author SHA1 Message Date
sharkdp 79f016e15c Update syntaxes 2019-08-31 20:58:16 +02:00
sharkdp 26f9125ebb Re-formulate help text 2019-08-31 20:56:53 +02:00
sharkdp 9814eab13f Suppress warning in -A mode 2019-08-31 20:56:53 +02:00
sharkdp 82ca8804a2 Handle non-unicode characters in the preprocessor 2019-08-31 20:56:53 +02:00
pjsier b48b9fcf3b Display binary file content for bat -A 2019-08-31 20:56:53 +02:00
sharkdp c64ab29739 Update min. required rust version 2019-08-31 14:48:42 +02:00
sharkdp 83dd3fb551 Update man page 2019-08-31 14:47:04 +02:00
sharkdp ed345f2889 Fix headline 2019-08-31 14:44:11 +02:00
sharkdp d2492980c0 Update syntaxes and themes 2019-08-31 14:43:20 +02:00
sharkdp 47d5130764 Bump version 2019-08-31 14:43:04 +02:00
sharkdp 4ba45e2ba2 Add first version of 'man page' syntax, closes #523 2019-08-31 14:32:37 +02:00
sharkdp 7076ae5cd9 Update dependencies 2019-08-31 14:14:08 +02:00
sharkdp 2e71146801 Fix another instance of the 'bat cache' bug, closes #584 2019-08-31 14:13:36 +02:00
sharkdp f3824bad17 Add explicit terminal width for test 2019-08-31 13:46:48 +02:00
sharkdp ec908d5937 Run 'cargo fmt' 2019-08-31 13:46:48 +02:00
sharkdp 3a75d85b80 Add test for 'snip' feature 2019-08-31 13:46:48 +02:00
sharkdp 63d652dab5 Add 'dyn' keyword for trait references 2019-08-31 13:46:48 +02:00
Ethan P 7f2e61d579 Add new style component to separate multiple '--line-range's 2019-08-31 13:46:48 +02:00
sharkdp e289a2c698 Add short '-L' option as an alias for --list-languages 2019-08-31 13:22:16 +02:00
sharkdp 83a213bae7 Add 'strace' syntax, closes #599 2019-08-31 13:13:42 +02:00
sharkdp 3967e28ded Add SCSS and Sass syntax, closes #637 2019-08-31 13:09:38 +02:00
sharkdp 2dc2a3712a Add Verilog syntax, closes #616 2019-08-31 12:59:02 +02:00
sharkdp 10e0f9efb0 Install fish completions in DEB package, closes #554 2019-08-28 21:06:52 +02:00
dependabot-preview[bot] f8ea075e78 Bump console from 0.7.7 to 0.8.0
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.7 to 0.8.0.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.7...0.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-26 21:44:57 +02:00
dependabot-preview[bot] c187dce2c2 Bump lazy_static from 1.3.0 to 1.4.0
Bumps [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs) from 1.3.0 to 1.4.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.3.0...1.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-26 07:13:01 +02:00
dependabot-preview[bot] 108c907d69 Bump git2 from 0.9.2 to 0.10.0
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.9.2 to 0.10.0.
- [Release notes](https://github.com/rust-lang/git2-rs/releases)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.9.2...git2-curl-0.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-24 08:47:50 +02:00
sharkdp 187a3b9341 Use consistent syntax for command-line options
closes #574
2019-08-15 21:57:32 +02:00
David Peter 9c2d4f6a51 Add libc6-dev dependency for aarch64 2019-08-10 15:58:13 +02:00
sharkdp c1126157d4 Re-enable aarch64 builds 2019-08-10 15:58:13 +02:00
dependabot-preview[bot] dcfa810112 Bump syntect from 3.2.0 to 3.2.1
Bumps [syntect](https://github.com/trishume/syntect) from 3.2.0 to 3.2.1.
- [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.2.0...v3.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-10 14:06:13 +02:00
Dan Davison f963104006 Add GraphQL sublime syntax submodule 2019-08-10 13:17:02 +02:00
sharkdp 45e1c0ea6f Temporarily disable aarch64 2019-08-02 21:14:44 +02:00
sharkdp 590a1e9a4b Bump minimum supported version to 1.33 2019-08-02 21:00:33 +02:00
sharkdp 8e2c6abb13 Update dependencies 2019-08-02 20:57:16 +02:00
Wild Kat 28266ee441 use explicit dyn with Write to appease compiler 2019-08-02 18:50:55 +02:00
Ethan P 21821f1d4c Updated snapshot tests 2019-07-26 06:51:33 +02:00
Ethan P 772ce2e4fe Print a horizontal header line when 'grid' style without 'header' style 2019-07-26 06:51:33 +02:00
dependabot-preview[bot] 35ca1c5191 Bump atty from 0.2.12 to 0.2.13
Bumps [atty](https://github.com/softprops/atty) from 0.2.12 to 0.2.13.
- [Release notes](https://github.com/softprops/atty/releases)
- [Changelog](https://github.com/softprops/atty/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/atty/compare/0.2.12...0.2.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-25 21:34:19 +02:00
dependabot-preview[bot] 0cc60a1519 Bump wild from 2.0.1 to 2.0.2
Bumps [wild](https://gitlab.com/kornelski/wild) from 2.0.1 to 2.0.2.
- [Release notes](https://gitlab.com/kornelski/wild/tags)
- [Commits](https://gitlab.com/kornelski/wild/commits/master)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-24 21:50:05 +02:00
dependabot-preview[bot] ee6659dacf Bump ansi_term from 0.11.0 to 0.12.0
Bumps [ansi_term](https://github.com/ogham/rust-ansi-term) from 0.11.0 to 0.12.0.
- [Release notes](https://github.com/ogham/rust-ansi-term/releases)
- [Commits](https://github.com/ogham/rust-ansi-term/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-24 21:45:44 +02:00
sharkdp 76c615a304 Allow leading minus in '--terminal-width <value>'
closes #611
2019-07-24 21:44:25 +02:00
Igor Gnatenko e8c04672f0 Small improvements for Fedora instructions
Anything older than F29 is EOL now, so no need to mention it. Also in F29+ you can use standard `dnf install`.
2019-07-24 21:38:11 +02:00
dependabot-preview[bot] 7f5a5612e4 Bump atty from 0.2.11 to 0.2.12
Bumps [atty](https://github.com/softprops/atty) from 0.2.11 to 0.2.12.
- [Release notes](https://github.com/softprops/atty/releases)
- [Changelog](https://github.com/softprops/atty/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/atty/compare/0.2.11...0.2.12)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-12 07:15:42 +02:00
dependabot-preview[bot] eee5d424bb [Security] Bump smallvec from 0.6.9 to 0.6.10
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 0.6.9 to 0.6.10. **This update includes security fixes.**
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-07 15:34:01 +02:00
dependabot-preview[bot] e5311e4b30 Bump console from 0.7.6 to 0.7.7
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.6 to 0.7.7.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.6...0.7.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-05 14:34:15 +02:00
dependabot-preview[bot] a1b9334a44 Bump console from 0.7.5 to 0.7.6
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.5 to 0.7.6.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.5...0.7.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-20 10:04:08 +02:00
Chloe Kudryavtsev d86b7cf7e0 Add Alpine Linux installation instructions
Resolves #586
2019-06-11 07:40:23 +02:00
dependabot-preview[bot] 67834da681 Bump git2 from 0.9.0 to 0.9.1
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/rust-lang/git2-rs/releases)
- [Commits](https://github.com/rust-lang/git2-rs/compare/0.9.0...0.9.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-10 11:15:51 +02:00
toku-sa-n dcdf8dfaa7 Add install instructions(ja) for Gentoo Users. 2019-06-09 17:50:18 +02:00
toku-sa-n 9a44fa11c0 Add install instructions for Gentoo Users. 2019-06-09 17:50:18 +02:00
sharkdp 4ee0b2e16d Merge branch 'issmirnov-ssh-config' 2019-06-07 08:17:17 +02:00
sharkdp 518997135e Merge branch 'ssh-config' of https://github.com/issmirnov/bat into issmirnov-ssh-config 2019-06-07 08:17:04 +02:00
Ivan Smirnov 69fc1caead Add support for "etc/hosts" files.
- Syntax author: https://github.com/brandonwamboldt/sublime-hosts

Since the upstream version only has a tmLanguage, added a sublime-syntax
file manually.
2019-06-07 08:02:38 +02:00
Ivan Smirnov 175dd4c290 Add SSH config syntax
Tested:
```
bash assets/create.sh
cargo build
target/debug/bat --language ssh_config ~/.ssh/config
```
2019-06-06 20:01:23 -07:00
dependabot-preview[bot] e9210c0f6c Bump git2 from 0.8.0 to 0.9.0
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/rust-lang/git2-rs/releases)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.8.0...0.9.0)
2019-06-05 07:17:09 +02:00
sharkdp 3795acbd17 Add '.env' (DotENV) syntax 2019-05-31 21:05:34 +02:00
sharkdp c7d08cfcfd Add 'requirements.txt' syntax 2019-05-31 20:58:08 +02:00
dependabot-preview[bot] 8ec96da9f0 Bump dirs from 2.0.0 to 2.0.1
Bumps [dirs](https://github.com/soc/dirs-rs) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/soc/dirs-rs/releases)
- [Commits](https://github.com/soc/dirs-rs/commits)
2019-05-31 08:57:04 +02:00
Fernando Mendes c9d7e3652b Enforce the creation of the full cache dir path
Fixes #576
2019-05-30 22:28:52 +02:00
Brice Waegeneire dfa024f9e6 Add Org mode syntax, closes sharkdp#36 2019-05-29 19:52:06 +02:00
dependabot-preview[bot] b2757cb461 Bump dirs from 1.0.5 to 2.0.0
Bumps [dirs](https://github.com/soc/dirs-rs) from 1.0.5 to 2.0.0.
- [Release notes](https://github.com/soc/dirs-rs/releases)
- [Commits](https://github.com/soc/dirs-rs/commits)
2019-05-28 21:32:57 +02:00
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
sharkdp e09499b3df Move config-dir and cache-dir from 'bat cache' to 'bat' 2019-02-07 23:27:53 +01:00
sharkdp cff01d81fa Rename 'bat cache --init' to 'bat cache --build' 2019-02-07 23:27:53 +01:00
sharkdp 31608c9a03 Update syntaxes 2019-02-07 23:01:06 +01:00
sharkdp 357ce84c56 Bump version to 0.10 2019-02-07 23:00:40 +01:00
sharkdp 3a5c52641b Update assets/syntaxes/Packages 2019-02-07 22:53:18 +01:00
sharkdp 6e8fca5bb2 Replace less command line arguments only for PAGER 2019-02-07 22:37:33 +01:00
Park Juhyung 63c77383ce Ignore flags from PAGER env var if the program is 'less' 2019-02-07 22:37:33 +01:00
sharkdp 4df22e617f Update documentation 2019-02-07 22:19:32 +01:00
sharkdp 6473e8c1be Remove import 2019-02-07 22:19:32 +01:00
sharkdp 972a764a74 Simplify Optional handling 2019-02-07 22:19:32 +01:00
sharkdp 54143d1403 Add --cache-dir option 2019-02-07 22:19:32 +01:00
sharkdp 6523bbf62f Replace 'is_absolute_path' with map and filter 2019-02-07 22:19:32 +01:00
Lavi 05e2c2c66b removed compile errors and warnings on non-macs 2019-02-07 22:19:32 +01:00
Lavi 69227222b5 config and cache now check XDG env vars first
`XDG_CACHE_HOME` and `XDG_CONFIG_HOME` are checked first and fall-back
to `~/.cache/` and `~/.config/`.
2019-02-07 22:19:32 +01:00
Lavi 49af3e854b Set cache_dir on MacOS to ~/.cache/bat/ 2019-02-07 22:19:32 +01:00
Lavi 6a8e4757b7 Updated bat config dir for MacOs
Removed directories crate and using dirs_rs
Changed bat config file and cache dir on MacOs:
config: ~/.config/bat/config
cache: ~/.config/bat/cache/
2019-02-07 22:19:32 +01:00
Harald Hoyer 91deef8b13 add varlink syntax
Varlink is an interface description format and protocol that aims
to make services accessible to both humans and machines in the
simplest feasible way.

See: https://varlink.org/ and https://github.com/varlink/ for
more information
2019-02-07 07:40:22 +01:00
Reid Wagner 61e888de7f Check result of read_until, and return Error if 0, which indicates EOF was found before delimeter. 2019-02-07 07:32:28 +01:00
Okumura Takahiro f3f9f10f05 Add Jsonnet (*.jsonnet) syntax
Jsonnet: https://jsonnet.org/
sublime-syntax: https://github.com/gburiola/sublime-jsonnet-syntax
2019-02-04 23:28:39 +01:00
object_1037 29ffa2a832 add Fedora instructions 2019-02-03 12:58:04 +01:00
object_1037 42a873fdb8 update README-ja.md 2019-02-03 12:58:04 +01:00
dependabot[bot] 82f048aedb Bump assert_cmd from 0.10.2 to 0.11.0
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 0.10.2 to 0.11.0.
- [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.10.2...v0.11.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-29 08:13:31 +01:00
Benjamin Santos ae08785ec8 Add Terraform syntax 2019-01-28 20:09:56 +01:00
sharkdp a500629359 Completely disable generation of shell completion files 2019-01-26 19:11:54 +01:00
Gergely Gombos 724a5fac99 Fix Fedora instructions in README
Correct instructions regarding Fedora Modular repos.
2019-01-26 19:11:37 +01:00
sharkdp c483e49b92 Consistent naming for submodules 2019-01-20 10:22:35 +01:00
Benjamin 94c9b40694 Protobuf-syntax and ProtobufText syntax (#474) 2019-01-20 10:20:53 +01:00
dependabot[bot] 0c9dc3b257 Bump console from 0.7.3 to 0.7.5
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.3 to 0.7.5.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.3...0.7.5)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-18 07:25:29 +01:00
Benjamin Santos 3b5174bb1d Add syslog-syntax 2019-01-18 07:24:46 +01:00
David Peter 3324505383 Update README.md 2019-01-16 20:04:46 +01:00
dependabot[bot] de7872f8a8 Bump console from 0.7.2 to 0.7.3
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.2 to 0.7.3.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.2...0.7.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-14 09:12:12 +01:00
dependabot[bot] abf0229741 Bump escargot from 0.3.1 to 0.4.0
Bumps [escargot](https://github.com/crate-ci/escargot) from 0.3.1 to 0.4.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.3.1...v0.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-01 12:32:25 +01:00
dependabot[bot] e04bccd12d Bump console from 0.7.1 to 0.7.2
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-24 08:41:06 +01:00
David Peter 668c8a6703 Merge pull request #453 from sharkdp/line-highlight
Line highlight
2018-12-18 09:06:28 +01:00
sharkdp bd68684537 Fix the number of values to one 2018-12-16 22:35:22 +01:00
sharkdp c2847f6a9f Short options for line-range and highlight-line 2018-12-16 22:17:39 +01:00
sharkdp cf7ed042c1 Colorize the whole line 2018-12-16 21:53:15 +01:00
sharkdp 6b92814ea0 Allow for multiple highlighted lines 2018-12-16 21:00:18 +01:00
sharkdp a236a9b195 Merge branch 'master' of https://github.com/tskinn/bat into tskinn-master 2018-12-16 20:43:36 +01:00
sharkdp b68c5d8576 Bump minimum required Rust version to 1.30 2018-12-14 23:34:13 +01:00
sharkdp fee57d71d9 Print ANSI-reset code before newline
fixes #379
2018-12-14 23:34:13 +01:00
sharkdp 5d3205acc0 Add x86_64 Assembly manually 2018-12-14 23:07:11 +01:00
sharkdp 4e6816abd6 Remove problematic 'Assembly (x86_64)' submodule 2018-12-14 23:07:11 +01:00
dependabot[bot] 72e8036edc Bump git2 from 0.7.5 to 0.8.0
Bumps [git2](https://github.com/alexcrichton/git2-rs) from 0.7.5 to 0.8.0.
- [Release notes](https://github.com/alexcrichton/git2-rs/releases)
- [Commits](https://github.com/alexcrichton/git2-rs/compare/libgit2-sys-0.7.5...git2-curl-0.8.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-14 22:55:25 +01:00
sharkdp 397def1320 Omit launching of pager if NO file exists
closes #387
2018-12-14 22:53:31 +01:00
sharkdp d2d29180a7 Add ARM assembly 2018-12-14 22:52:57 +01:00
sharkdp 2f263c9fbf Add x86_64 assembly 2018-12-14 22:46:50 +01:00
ufuji1984 4ff360669f add quotes around filename
and make it more concise by using map_err
2018-12-11 22:24:52 +01:00
ufuji1984 549e5d7355 Report filename if File::open return Err
From issue #441
2018-12-11 22:24:52 +01:00
Markus Thömmes dd48d29c28 Add AsciiDoc syntax. 2018-12-11 21:12:29 +01:00
sharkdp 98ee5f7400 Add vimpager to alternatives, closes #429 2018-12-07 20:28:47 +01:00
dependabot[bot] 638c04c13e Bump console from 0.7.0 to 0.7.1
Bumps [console](https://github.com/mitsuhiko/console) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.7.0...0.7.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-03 07:04:34 +01:00
David Peter b1c865acaa Update README.md 2018-12-02 22:02:39 +01:00
Lavi Blumberg d3d795ffb2 Removed confusing variable from examples in README.md
Removed confusing the variable `BAT_CONFIG_DIR` from examples because it
 is not a real configuration option for bat.
2018-12-02 20:19:12 +01:00
David Peter 0571c51487 Add copyright notice in MIT license 2018-12-02 18:35:29 +01:00
Ole Martin Ruud 348c9f3562 Enhance SyntaxMapping with impl Trait 2018-11-27 20:36:23 +01:00
Ole Martin Ruud 6b6a8f8e16 Fix doc comment typo 2018-11-27 20:34:32 +01:00
Keith Devens 6aa002850c Correct typo in readme 2018-11-26 20:11:25 +01:00
dependabot[bot] 49c22c8d39 Bump console from 0.6.2 to 0.7.0
Bumps [console](https://github.com/mitsuhiko/console) from 0.6.2 to 0.7.0.
- [Release notes](https://github.com/mitsuhiko/console/releases)
- [Commits](https://github.com/mitsuhiko/console/compare/0.6.2...0.7.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-23 08:04:46 +01:00
dependabot[bot] 673caf6b59 Bump assert_cmd from 0.10.1 to 0.10.2
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 0.10.1 to 0.10.2.
- [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.10.1...v0.10.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-21 19:11:22 +01:00
David Peter e6ffab3cb4 Update assets/README.md 2018-11-19 18:48:36 +01:00
Jerome Leclanche 4e43f8fa74 Highlight XDG desktop entry as .ini file
Reference: https://standards.freedesktop.org/desktop-entry-spec/latest/
2018-11-19 18:48:36 +01:00
David Peter bac1b16885 Consistent spelling of "color" 2018-11-18 12:11:07 +01:00
Ahmed El Gabri 778a4929a8 Add twig support 2018-11-18 11:58:05 +01:00
sh-tech 5c22dd4248 add close tag 2018-11-15 08:53:03 +01:00
sh-tech 214cd0f8ea add link to original README 2018-11-15 08:53:03 +01:00
sh-tech 9fd61fcb6d add table of contents 2018-11-15 08:53:03 +01:00
sh-tech edf1d3b256 modify url 2018-11-15 08:53:03 +01:00
sh-tech eca47b2a28 translate Project goals, alternatives 2018-11-15 08:53:03 +01:00
sh-tech 62424e70d7 translate Customization 2018-11-15 08:53:03 +01:00
sh-tech 4791f15222 translate Installation 2018-11-15 08:53:03 +01:00
sh-tech 159f234b78 translate Key Features & How to Use 2018-11-15 08:53:03 +01:00
sh-tech 3ec96127f2 translate table of contents 2018-11-15 08:53:03 +01:00
sh-tech a9acb2711b copy README.md (NOT translate yet) 2018-11-15 08:53:03 +01:00
sharkdp a3182e68e4 Update .gitattributes 2018-11-12 21:49:19 +01:00
sharkdp 0691b18231 Add assets/.gitattributes 2018-11-11 14:50:59 +01:00
sharkdp c711cd1b2e Update .gitattributes 2018-11-11 14:50:05 +01:00
sharkdp 14e6b41a5f Add .gitattributes 2018-11-11 14:49:24 +01:00
Arnav Borborah 532af6556d Use Rust inclusive range (stable in 1.26) 2018-11-11 14:42:22 +01:00
David Peter 26717b0cd2 Update README.md 2018-11-11 14:39:04 +01:00
David Peter 1f177f0a1c Update README.md 2018-11-11 14:35:08 +01:00
David Peter 54c81fa543 Update README.md 2018-11-11 14:32:59 +01:00
David Peter 34dee9e3aa Updates for README 2018-11-11 14:28:18 +01:00
David Peter c073d4a118 Add new image 2018-11-11 13:19:34 +01:00
sharkdp e79c5516bf Bump version, update assets 2018-11-11 12:55:38 +01:00
sharkdp 4776c2a575 Update man page 2018-11-11 12:31:28 +01:00
sharkdp f98a96c1ed Update help text 2018-11-11 12:26:39 +01:00
sharkdp 8a3446d219 Update dependencies 2018-11-11 12:17:58 +01:00
David Peter 5d5bf616ca Update README.md 2018-11-11 12:17:15 +01:00
sharkdp b68c038db8 Update link to new issue 2018-11-11 11:08:08 +01:00
dependabot[bot] 1117d2f9cb Bump syntect from 3.0.1 to 3.0.2
Bumps [syntect](https://github.com/trishume/syntect) from 3.0.1 to 3.0.2.
- [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.1...v3.0.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-11 11:08:08 +01:00
David Peter d0ba5bcb32 Wording 2018-11-11 11:07:55 +01:00
Ricky f8d39d5624 Resolving requested changes 2018-11-11 11:07:55 +01:00
Ricky 9998e2eac6 Initial commit of updated README for config file formatting 2018-11-11 11:07:55 +01:00
sharkdp 7cac07d845 issue #383: Handle cases like PAGER=/usr/bin/bat 2018-11-06 19:53:32 +01:00
Rodrigo Orem 148caa1381 Fix code style 2018-11-06 19:35:41 +01:00
Rodrigo Orem ab27cac0cc Remove args when change from bat to less 2018-11-06 19:35:41 +01:00
Rodrigo Orem 01fcbf2183 Better placement of bat detection 2018-11-06 19:35:41 +01:00
Rodrigo Orem 8a0c30b385 Avoid endless bat executions with PAGER="bat"
From issue #383
2018-11-06 19:35:41 +01:00
Dany Marcoux bc21c4d0e0 Add openSUSE installation instructions 2018-11-06 19:21:33 +01:00
dependabot[bot] 0800562ba2 Bump content_inspector from 0.2.3 to 0.2.4
Bumps [content_inspector](https://github.com/sharkdp/content_inspector) from 0.2.3 to 0.2.4.
- [Release notes](https://github.com/sharkdp/content_inspector/releases)
- [Commits](https://github.com/sharkdp/content_inspector/compare/v0.2.3...v0.2.4)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-05 19:37:58 +01:00
sharkdp 1f9befbcd1 Update SHA1 in TOML submodule 2018-11-05 19:37:23 +01:00
sharkdp a5c779c518 Update path to TOML syntax remote 2018-11-05 19:23:44 +01:00
dependabot[bot] f37f100352 Bump lazy_static from 1.1.0 to 1.2.0
Bumps [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs) from 1.1.0 to 1.2.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.1.0...1.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-05 07:22:39 +01:00
Nisheet Sinvhal 18d1a3b973 Changed italics to use-italic-text in config
Better placing of italics in help and also added long_help for it
2018-11-04 19:40:05 +01:00
Nisheet Sinvhal dc10246bd2 Linting 2018-11-04 19:40:05 +01:00
Nisheet Sinvhal 44bdae0212 Linting 2018-11-04 19:40:05 +01:00
Nisheet Sinvhal 1ece38a4c4 Changed flag name 2018-11-04 19:40:05 +01:00
Nisheet Sinvhal e90308e1f8 italics enable|disable working 2018-11-04 19:40:05 +01:00
Nisheet Sinvhal d702d6740c Added args 2018-11-04 19:40:05 +01:00
sharkdp c6a526f99c Run 'cargo run' only once 2018-11-04 12:24:56 +01:00
sharkdp 278d841408 Move '--paging' arg to config file. 2018-11-04 11:19:49 +01:00
sharkdp 5f576f1ecf Remove all relevant environment variables during testing 2018-11-04 11:19:49 +01:00
sharkdp 48c6ea6b25 Simplify integration test setup 2018-11-04 11:19:49 +01:00
Ricky 558134f6c8 Changed to unwrap methods, added integration tests 2018-11-04 11:19:49 +01:00
Ricky 1dd57e6d7e Ran rust fmt 2018-11-04 11:19:49 +01:00
Ricky 20ba84d1fa Added in environment variable and the result is a file check in config.rs 2018-11-04 11:19:49 +01:00
sharkdp e81f9b23e6 Fix --show-all for UTF-16 encoding 2018-11-01 22:00:47 +01:00
sharkdp 50dc4a79b0 Display line-feed as instead of 2018-11-01 22:00:47 +01:00
sharkdp 8fa8f44706 Use character if tab-width == 1. 2018-11-01 22:00:47 +01:00
sharkdp ecd862d9ff Feature: Highlight non-printable characters
Adds a new `-A`/`--show-all` option (in analogy to GNU Linux `cat`s option) that
highlights non-printable characters like space, tab or newline.

This works in two steps:
- **Preprocessing**: replace space by `•`, replace tab by `├──┤`, replace
newline by `␤`, etc.
- **Highlighting**: Use a newly written Sublime syntax to highlight
these special symbols.

Note: This feature is not technically a drop-in replacement for GNU `cat`s
`--show-all` but it has the same purpose.
2018-11-01 22:00:47 +01:00
sharkdp cbed338c3a Remove generation code for tabs_ tests 2018-11-01 15:30:58 +01:00
sharkdp 4492d99556 Change default tab width to 4 2018-11-01 15:30:58 +01:00
sharkdp d96ee2261f Remove tab-related text 2018-11-01 15:30:58 +01:00
sharkdp dda27b253b Allow offset values in --terminal-width
Allows the `width` argument to `--terminal-width` to be an offset
instead of an absolute number. Examples:

    --terminal-width=80   # Set output width to 80 characters
    --terminal-width=-2   # Set output width to actual_width - 2

closes #376
2018-10-31 22:21:22 +01:00
sharkdp 78f26d0caf Temporarily disable shipping of shell completions
closes #372
2018-10-31 22:03:05 +01:00
David Peter abcd09f869 Remove commented-out code 2018-10-21 22:52:26 +02:00
Sindre Johansen 41a5ff039b Only use the last argument of {style,plain,number} 2018-10-21 22:52:26 +02:00
Sindre Johansen 155bad3862 Rustfmt 2018-10-21 22:52:26 +02:00
Sindre Johansen 7c98a1c901 When specifying style multiple times the last occurence wins
Closes: #367
2018-10-21 22:52:26 +02:00
David Peter c1246fcd53 Update help text 2018-10-21 22:42:11 +02:00
David Peter 9f401ea122 Update docstring 2018-10-21 22:42:11 +02:00
Park Juhyung 9c782fb692 Fix format error 2018-10-21 22:42:11 +02:00
Park Juhyung 154186a58d Add --pager option 2018-10-21 22:42:11 +02:00
David Peter b22a9f8fe3 Update README.md 2018-10-20 14:56:25 +02:00
David Peter 5219c40ed8 PAGER: Wrapper script is not needed anymore 2018-10-20 14:54:44 +02:00
sharkdp a25ee0e6fd Add sublime-snazzy theme 2018-10-20 11:32:25 +02:00
sharkdp 496e0bc046 Allow for multiple line ranges
See #23
2018-10-20 10:44:13 +02:00
sharkdp 7082fd09f0 Modify TravisCI caching policy 2018-10-19 23:06:25 +02:00
David Peter 857cc215b4 Move link to header line 2018-10-19 22:00:05 +02:00
yobrave 481268f018 Doc: add Chinese readme link
#251
2018-10-19 22:00:05 +02:00
sharkdp f7d9f49503 Remove leftovers from tab-tests 2018-10-19 21:57:35 +02:00
Lawrence Chou 88fcfd76aa cargo fmt 2018-10-19 21:04:46 +02:00
Lawrence Chou 76e34b29ec Avoid empty line in snapshot 2018-10-19 21:04:46 +02:00
Lawrence Chou 01984e1d02 Test 'tabs' with 'numbers' 2018-10-19 21:04:46 +02:00
Lawrence Chou 536390509f remove --wrap for now 2018-10-19 21:04:46 +02:00
Lawrence Chou 58198d0700 rewrite 6 snapshot tests as integration test 2018-10-19 21:04:46 +02:00
Lawrence Chou afc5aacb28 Move tabs_* snapshot tests to integration_tests 2018-10-19 21:04:46 +02:00
sharkdp 30b742e984 --map-syntax takes just one value 2018-10-17 23:27:44 +02:00
sharkdp 671deeef8c Update help text 2018-10-17 23:17:28 +02:00
sharkdp a892caeb33 Bump bat version to 0.8 2018-10-17 23:15:59 +02:00
sharkdp a770cbf25e Update assets 2018-10-17 23:14:07 +02:00
sharkdp 931c6e9414 Update man page 2018-10-17 23:13:50 +02:00
sharkdp 8dc7e2efa3 Add --config-file option 2018-10-17 23:08:37 +02:00
sharkdp 10965a6122 Implement syntax mapping
This adds a `-m`/`--map-syntax` option that allows users to (re)map
certain file extensions or file names to an existing syntax.

For example:
```
bat --map-syntax .config:json
```

The option can be use multiple times. Note that you can easily make
these mappings permanent by using `bat`s new configuration file.

closes #169
2018-10-17 23:08:19 +02:00
sharkdp e43d97dc15 Small cleanup 2018-10-17 21:12:23 +02:00
sharkdp 2c7087b8de Add integration tests for pager handling 2018-10-17 21:08:32 +02:00
sharkdp bb1f5aa841 Add proper handling of empty PAGER variables 2018-10-17 21:08:32 +02:00
sharkdp 2109a7830b Add error handling for parsing errors 2018-10-17 21:08:32 +02:00
sharkdp ec27c78a8a Remove duplicate 'extern crate' 2018-10-17 21:08:32 +02:00
Morten Linderud 67fe833bc8 Add arguments from PAGER/BAT_PAGER
Solves #352

Signed-off-by: Morten Linderud <morten@linderud.pw>
2018-10-17 21:08:32 +02:00
sharkdp e956225b4d Update syntect to 3.0.1
closes #314
2018-10-16 23:06:46 +02:00
sharkdp 314ec881ef Bump Rust version 2018-10-16 22:09:15 +02:00
sharkdp 25a6a55437 Revert "Fix for older version of Rust"
This reverts commit c530fadc44.
2018-10-16 22:09:15 +02:00
sharkdp 5bff4548be Add BAT_OPTS environment variable 2018-10-16 22:09:15 +02:00
sharkdp 866b9e16a8 Add error handling 2018-10-16 22:09:15 +02:00
sharkdp 5af176c94f Move transpose to util module 2018-10-16 22:09:15 +02:00
sharkdp 9e7da05459 Fix for older version of Rust 2018-10-16 22:09:15 +02:00
sharkdp 1ae02c65fb Fix include 2018-10-16 22:09:15 +02:00
sharkdp 495e7fd3b1 Add --no-config option 2018-10-16 22:09:15 +02:00
sharkdp b48f0fe389 Fix tests 2018-10-16 22:09:15 +02:00
sharkdp c19c704a43 Add more tests 2018-10-16 22:09:15 +02:00
sharkdp 693bd5929d Add possibility for spaces on a single line 2018-10-16 22:09:15 +02:00
sharkdp 8275b0436d Add simple configuration file
This allows users to create simple configuration file
(`~/.config/bat/config` on Linux) that has the following format:

    ```bash
    --flag1
    --flag2
    --option1=value1
    # lines beginning with '#' are ignored
    --option2=value2
    # empty lines and trailing whitespace are also ignored

    --option3=value3
    ```
2018-10-16 22:09:15 +02:00
sharkdp 278bde5cee Continue with output after "is directory"-error 2018-10-11 21:54:19 +02:00
Russ Taylor eee7e5a575 Removes duplicate explanation. 2018-10-11 20:58:44 +02:00
Russ Taylor ad7b634ee6 Fixes #328 - adds info for light backgrounds. 2018-10-11 20:58:44 +02:00
David Peter 1310f83c8d Update Docker alias for bat 2018-10-11 20:57:46 +02:00
David Peter 897b9e7030 Add Docker instructions, closes #331 2018-10-11 20:05:17 +02:00
sharkdp 1891e194b5 Add simple integration tests 2018-10-11 07:06:13 +02:00
Taylor cea05e9f22 be consistent 2018-10-10 22:19:40 -06:00
sharkdp d2d01b9fe8 Always remove the local cache when creating new assets 2018-10-10 21:49:03 +02:00
sharkdp 2a7851530d Fix formatting 2018-10-10 20:45:10 +02:00
Taylor 1a6709c2cb add line highlight 2018-10-09 22:25:33 -06:00
sharkdp 5842d58c01 Updates for syntect 3.0 2018-10-09 22:04:51 +02:00
Tim Sampson e3c71adba7 syntax: Add robot framework support 2018-10-09 20:27:01 +02:00
Merlin Göttlinger 504f28b3a1 Documented nix availability 2018-10-09 20:07:27 +02:00
Fredrik Fornwall d977ba9194 Update dependencies 2018-10-08 22:33:09 +02:00
Tim Sampson 9c09799e1f misc: add exec bit for create.sh 2018-10-08 20:20:05 +02:00
David Peter d83c93c805 Update README.md 2018-10-07 18:39:52 +02:00
sharkdp fc8fd1e63f cargo fmt 2018-10-07 17:49:38 +02:00
sharkdp 404d6a4a81 Update content_inspector version 2018-10-07 17:49:38 +02:00
sharkdp 25d96da4a2 Add support for UTF-16LE and UTF-16BE 2018-10-07 17:49:38 +02:00
sharkdp e97095b724 Use first-line detection for STDIN 2018-10-07 15:34:37 +02:00
sharkdp ce96df00b6 Do not display binary files in interactive mode
closes #248
2018-10-07 15:34:37 +02:00
sharkdp f98fc5f06a Simplify access to first line 2018-10-07 15:34:37 +02:00
sharkdp 1dbb4ef683 Update minimum Rust version to 1.27 2018-10-07 15:34:37 +02:00
sharkdp 0502a3bd4a Add first-line detection for all input types
closes #205
2018-10-07 15:34:37 +02:00
sharkdp 869cf6368c Add possibility to get first line 2018-10-07 15:34:37 +02:00
sharkdp 078228deac Add unit test for InputFileReader 2018-10-07 15:34:37 +02:00
sharkdp e09d7dabb8 Move snapshot tests into separate module 2018-10-07 15:34:37 +02:00
sharkdp 6d1cc8c2c8 Move read_line functionality to inputfile module 2018-10-07 15:34:37 +02:00
sharkdp 87f021078e Use dyn Trait for trait objects 2018-10-07 15:34:37 +02:00
sharkdp d5b0502419 Move get_reader into inputfile module 2018-10-07 15:34:37 +02:00
sharkdp 860f3e9006 Move InputFile to separate module 2018-10-07 15:34:37 +02:00
sharkdp 1be346a038 Add 'plain' version of bat to the benchmarks 2018-10-07 10:57:08 +02:00
sharkdp f9fd5e4851 Simplify -h help text 2018-10-07 10:43:39 +02:00
sharkdp da09f3877b Remove unnecessary scope 2018-10-07 10:09:10 +02:00
sharkdp e30e1bab2e Move theme-preview section into own paragraph 2018-10-06 21:12:12 +02:00
Russ Taylor f140f6da46 Fixes #273 - describes 'musl' builds. 2018-10-06 21:07:01 +02:00
Grégoire Paris 3446fdf5f2 Document how to rapidly preview theme on a file 2018-10-06 21:06:31 +02:00
sharkdp e1345cdc2a Update VimL syntax 2018-10-05 18:44:51 +02:00
sharkdp a2676ccc55 Workaround for #81 2018-10-04 11:09:41 +02:00
Richard Hozák b39e28d2c8 Add support for wildcards in Windows CMD (#329)
Windows does not support wildcard expansion in cmd, this adds 'wild' crate (as discussed in #309) that handles everything transparently, so wildcards work everywhere.

Fixes #309
2018-10-03 22:59:11 +02:00
davideGiovannini 0d71968615 Generate shell completions with clap during build (#327)
* Generate shell completions with clap during build

* Updated ci release script, added SHELL_COMPLETIONS_DIR override to build.rs and fixed dependency version
2018-10-03 09:39:30 +02:00
sharkdp 80da0dc619 run cargo fmt 2018-09-26 19:16:03 +02:00
sharkdp 64903bb858 Typo 2018-09-26 19:13:32 +02:00
sharkdp 3456ce1187 Add a small tutorial 2018-09-26 18:08:24 +02:00
sharkdp 886a5b3d24 Document the situation with less and scrolling
closes #312
closes #246
2018-09-26 18:03:46 +02:00
sharkdp 238482e5f3 Update syntax-set, fixes #314 2018-09-23 10:30:19 +02:00
Michal Nazarewicz 79b960e17e Use ansi_colours package for better true-colour approximation 2018-09-23 10:19:19 +02:00
sharkdp 6aa626f1c4 Document INI syntax modifications 2018-09-22 11:23:29 +02:00
Tuk Bredsdorff 1b30539493 Added Mercurial's hgrc-files to the list of INI-extensions 2018-09-22 11:23:29 +02:00
Katrin Leinweber 96b24d8a7e Fix typos 2018-09-20 19:16:51 +02:00
sharkdp 20b02e72b3 Disable wrapping when --style is plain
closes #289
2018-09-18 21:31:56 +02:00
eth-p 254efac9c2 Added section to README on using Cygwin. 2018-09-14 18:30:43 +02:00
Jeroen Hoek dcec322117 Update README (libz-dev may be required)
On Ubuntu 18.04 I had to install `cmake` as well as `libz-dev` to get
bat to compile.
2018-09-14 14:12:44 +02:00
Alexander Eimer d781156327 Adds ansible install instructions for ansible to readme 2018-09-12 23:06:33 +02:00
124 changed files with 10528 additions and 1860 deletions
+63 -1
View File
@@ -6,7 +6,7 @@
url = https://github.com/sublimehq/Packages/
[submodule "assets/syntaxes/TOML"]
path = assets/syntaxes/TOML
url = https://github.com/sharkdp/sublime_toml_highlighting
url = https://github.com/jasonwilliams/sublime_toml_highlighting
[submodule "assets/syntaxes/Julia"]
path = assets/syntaxes/Julia
url = https://github.com/JuliaEditorSupport/Julia-sublime
@@ -91,3 +91,65 @@
[submodule "assets/syntaxes/PowerShell"]
path = assets/syntaxes/PowerShell
url = https://github.com/PowerShell/EditorSyntax
[submodule "assets/syntaxes/Robot"]
path = assets/syntaxes/Robot
url = https://github.com/andriyko/sublime-robot-framework-assistant.git
[submodule "assets/themes/sublime-snazzy"]
path = assets/themes/sublime-snazzy
url = https://github.com/greggb/sublime-snazzy
[submodule "assets/syntaxes/HTML (Twig)"]
path = assets/syntaxes/HTML (Twig)
url = https://github.com/Anomareh/PHP-Twig.tmbundle.git
[submodule "assets/syntaxes/AsciiDoc"]
path = assets/syntaxes/AsciiDoc
url = https://github.com/SublimeText/AsciiDoc.git
[submodule "assets/syntaxes/Assembly (ARM)"]
path = assets/syntaxes/Assembly (ARM)
url = https://github.com/tvi/Sublime-ARM-Assembly
[submodule "assets/syntaxes/syslog-syntax"]
path = assets/syntaxes/Syslog
url = https://github.com/caos21/syslog-syntax.git
branch = master
[submodule "assets/syntaxes/protobuf-syntax-highlighting"]
path = assets/syntaxes/Protobuf
url = https://github.com/VcamX/protobuf-syntax-highlighting.git
branch = master
[submodule "assets/syntaxes/Terraform"]
path = assets/syntaxes/Terraform
url = https://github.com/alexlouden/Terraform.tmLanguage.git
[submodule "assets/syntaxes/Jsonnet"]
path = assets/syntaxes/Jsonnet
url = https://github.com/gburiola/sublime-jsonnet-syntax.git
[submodule "assets/syntaxes/varlink"]
path = assets/syntaxes/varlink
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
[submodule "assets/syntaxes/Org mode"]
path = assets/syntaxes/Org mode
url = https://github.com/jezcope/Org.tmbundle.git
[submodule "assets/syntaxes/requirementstxt"]
path = assets/syntaxes/requirementstxt
url = https://github.com/wuub/requirementstxt
[submodule "assets/syntaxes/DotENV"]
path = assets/syntaxes/DotENV
url = https://github.com/zaynali53/DotENV
[submodule "assets/syntaxes/hosts"]
path = assets/syntaxes/hosts
url = https://github.com/brandonwamboldt/sublime-hosts
[submodule "assets/syntaxes/ssh-config"]
path = assets/syntaxes/ssh-config
url = https://github.com/robballou/sublimetext-sshconfig.git
[submodule "assets/syntaxes/GraphQL"]
path = assets/syntaxes/GraphQL
url = https://github.com/dncrews/GraphQL-SublimeText3.git
[submodule "assets/syntaxes/Verilog"]
path = assets/syntaxes/Verilog
url = https://github.com/pro711/sublime-verilog
[submodule "assets/syntaxes/SCSS_Sass"]
path = assets/syntaxes/SCSS_Sass
url = https://github.com/braver/SublimeSass
[submodule "assets/syntaxes/Strace"]
path = assets/syntaxes/Strace
url = https://github.com/djuretic/SublimeStrace
+12 -5
View File
@@ -1,5 +1,5 @@
language: rust
cache: cargo
matrix:
include:
# Stable channel.
@@ -29,18 +29,18 @@ matrix:
- TARGET=aarch64-unknown-linux-gnu
- CC_aarch64-unknown-linux-gnu=/usr/bin/aarch64-linux-gnu-gcc-4.8
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc-4.8
# Minimum Rust supported channel.
- os: linux
rust: 1.26.0
rust: 1.35.0
env: TARGET=x86_64-unknown-linux-gnu
- os: linux
rust: 1.26.0
rust: 1.35.0
env:
- TARGET=x86_64-unknown-linux-musl
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
- os: osx
rust: 1.26.0
rust: 1.35.0
env: TARGET=x86_64-apple-darwin
# Code formatting check
@@ -103,3 +103,10 @@ deploy:
notifications:
email:
on_success: never
# Caching
cache:
directories:
- /home/travis/.cargo
before_cache:
- rm -rf /home/travis/.cargo/registry
Generated
+819 -423
View File
File diff suppressed because it is too large Load Diff
+21 -9
View File
@@ -7,31 +7,38 @@ license = "MIT/Apache-2.0"
name = "bat"
readme = "README.md"
repository = "https://github.com/sharkdp/bat"
version = "0.7.0"
version = "0.12.0"
exclude = [
"assets/syntaxes/*",
"assets/themes/*",
]
build = "build.rs"
edition = '2018'
[dependencies]
atty = "0.2.2"
ansi_term = "0.11"
console = "0.6"
directories = "1.0"
lazy_static = "1.0"
atty = "0.2.13"
ansi_term = "0.12"
ansi_colours = "^1.0"
console = "0.8"
dirs = "2.0"
lazy_static = "1.4"
wild = "2.0"
content_inspector = "0.2.4"
encoding = "0.2"
shell-words = "0.1.0"
[dependencies.git2]
version = "0.7"
version = "0.10"
default-features = false
features = []
[dependencies.syntect]
version = "2.1"
version = "3.2.1"
default-features = false
features = ["parsing", "yaml-load", "dump-load", "dump-create"]
[dependencies.clap]
version = "2.32"
version = "2.33"
default-features = false
features = ["suggestions", "color", "wrap_help"]
@@ -42,3 +49,8 @@ features = []
[dev-dependencies]
tempdir = "0.3"
assert_cmd = "0.11.1"
escargot = "0.5.0"
[build-dependencies]
clap = "2.33"
+2
View File
@@ -1,3 +1,5 @@
Copyright (c) 2018 bat-developers (https://github.com/sharkdp/bat).
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
+271 -39
View File
@@ -12,7 +12,8 @@
<a href="#how-to-use">How To Use</a> •
<a href="#installation">Installation</a> •
<a href="#customization">Customization</a> •
<a href="#project-goals-and-alternatives">Project goals, alternatives</a>
<a href="#project-goals-and-alternatives">Project goals, alternatives</a>
Translation [<a href="https://github.com/chinanf-boy/bat-zh">中文</a>][<a href="doc/README-ja.md">日本文</a>]
</p>
### Syntax highlighting
@@ -29,6 +30,13 @@ languages:
![Git integration example](https://i.imgur.com/2lSW4RE.png)
### Show non-printable characters
You can use the `-A`/`--show-all` option to show and highlight non-printable
characters:
![Non-printable character example](https://i.imgur.com/WndGp9H.png)
### Automatic paging
`bat` can pipe its own output to `less` if the output is too large for one screen.
@@ -36,8 +44,9 @@ languages:
### File concatenation
Oh.. you can also use it to concatenate files :wink:. Whenever
`bat` detects a non-interactive terminal, it will fall back to printing
the plain file contents.
`bat` detects a non-interactive terminal (i.e. when you pipe into another process
or into a file), `bat` will act as a drop-in replacement for `cat` and
fall back to printing the plain file contents.
## How to use
@@ -53,17 +62,24 @@ Display multiple files at once
> bat src/*.rs
```
Read from stdin, explicitly specify the language
Read from stdin, determine the syntax automatically
```bash
> curl -s https://sh.rustup.rs | bat
```
Read from stdin, specify the language explicitly
```bash
> yaml2json .travis.yml | json_pp | bat -l json
```
Show and highlight non-printable characters:
```bash
> curl -s https://raw.githubusercontent.com/sharkdp/bat/master/src/main.rs | bat -l rs
> bat -A /etc/hosts
```
As a replacement for `cat`:
Use it as a `cat` replacement:
```bash
bat > note.md # quickly create a new file
@@ -75,6 +91,58 @@ bat -n main.rs # show line numbers (only)
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.
#### `man`
`bat` can be used as a pager for `man`. It can be used like this:
```
export MANPAGER="sh -c 'col -b | bat -l man -p'"
man 2 select
```
The [Manpage syntax](assets/syntaxes/Manpage.sublime-syntax) is developed in this repository and still needs some work.
## Installation
### On Ubuntu
@@ -83,7 +151,16 @@ bat f - g # output 'f', then stdin, then 'g'.
Download the latest `.deb` package from the [release page](https://github.com/sharkdp/bat/releases)
and install it via:
``` bash
sudo dpkg -i bat_0.7.0_amd64.deb # adapt version number and architecture
sudo dpkg -i bat_0.12.0_amd64.deb # adapt version number and architecture
```
### On Alpine Linux
You can install [the `bat` package](https://pkgs.alpinelinux.org/packages?name=bat)
from the official sources, provided you have the appropriate repository enabled:
```bash
apk add bat
```
### On Arch Linux
@@ -95,6 +172,23 @@ from the official sources:
pacman -S bat
```
### On Fedora
You can install [the `bat` package](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) from the official [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/) repository.
```bash
dnf install bat
```
### On Gentoo Linux
You can install [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat)
from the official sources:
```bash
emerge sys-apps/bat
```
### On Void Linux
You can install `bat` via xbps-install:
@@ -117,6 +211,22 @@ cd /usr/ports/textproc/bat
make install
```
### Via nix
You can install `bat` using the [nix package manager](https://nixos.org/nix):
```bash
nix-env -i bat
```
### On openSUSE
You can install `bat` with zypper:
```
zypper install bat
```
### On macOS
You can install `bat` with [Homebrew](http://braumeister.org/formula/bat):
@@ -127,31 +237,72 @@ brew install bat
### On Windows
You can download pre-built binaries from the [Release page](https://github.com/sharkdp/bat/releases),
or install it with [scoop](https://scoop.sh/):
You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases),
or install it with [scoop](https://scoop.sh/) or [Chocolatey](https://chocolatey.org):
```bash
scoop install bat
```
```bash
choco install bat
```
[See below](#using-bat-on-windows) for notes.
### Via Docker
There is a [Docker image](https://hub.docker.com/r/danlynn/bat/) that you can use to run `bat` in a container:
```bash
docker pull danlynn/bat
alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat'
```
### Via Ansible
You can install `bat` with [Ansible](https://www.ansible.com/):
```bash
# Install role on local machine
ansible-galaxy install aeimer.install_bat
```
```yaml
---
# Playbook to install bat
- host: all
roles:
- aeimer.install_bat
```
- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat)
- [GitHub](https://github.com/aeimer/ansible-install-bat)
This should work with the following distributions:
- Debian/Ubuntu
- ARM (eg. Raspberry PI)
- Arch Linux
- Void Linux
- FreeBSD
- MacOS
### From binaries
Check out the [Release page](https://github.com/sharkdp/bat/releases) for
prebuilt versions of `bat` for many different architectures.
prebuilt versions of `bat` for many different architectures. Statically-linked
binaries are also available: look for archives with `musl` in the file name.
### From source
If you want to build `bat` from source, you need Rust 1.26 or
If you want to build `bat` from source, you need Rust 1.35 or
higher. You can then use `cargo` to build everything:
```bash
cargo install bat
```
On macOS, you might have to install `cmake` (`brew install cmake`) in order for
some dependencies to be built.
You may have to install `cmake` and the `libz` development package
(`libz-dev` or `libz-devel`) in order for the build to succeed.
## Customization
@@ -160,15 +311,28 @@ some dependencies to be built.
Use `bat --list-themes` to get a list of all available themes for syntax
highlighting. To select the `TwoDark` theme, call `bat` with the
`--theme=TwoDark` option or set the `BAT_THEME` environment variable to
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shells startup file to
make the change permanent.
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to
make the change permanent. Alternatively, use `bat`s
[configuration file](https://github.com/sharkdp/bat#configuration-file).
If you want to preview the different themes on a custom file, you can use
the following command (you need [`fzf`](https://github.com/junegunn/fzf) for this):
``` bash
bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
```
`bat` looks good on a dark background by default. However, if your terminal uses a
light background, some themes like `GitHub` or `OneHalfLight` will work better for you.
You can also use a custom theme by following the
['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes).
### Output style
You can use the `--style` option to control the appearance of `bat`s output.
You can use `--style=numbers,changes`, for example, to show only Git changes
and line numbers but no grid and no file header. Use the `BAT_STYLE` environment
variable to make these changes permanent.
and line numbers but no grid and no file header. Set the `BAT_STYLE` environment
variable to make these changes permanent or use `bat`s
[configuration file](https://github.com/sharkdp/bat#configuration-file).
### Adding new syntaxes / language definitions
@@ -180,10 +344,8 @@ and theme. To add new syntax definitions, do the following.
Create a folder with syntax definition files:
```bash
BAT_CONFIG_DIR="$(bat cache --config-dir)"
mkdir -p "$BAT_CONFIG_DIR/syntaxes"
cd "$BAT_CONFIG_DIR/syntaxes"
mkdir -p "$(bat --config-dir)/syntaxes"
cd "$(bat --config-dir)/syntaxes"
# Put new '.sublime-syntax' language definition files
# in this folder (or its subdirectories), for example:
@@ -193,7 +355,7 @@ git clone https://github.com/tellnobody1/sublime-purescript-syntax
Now use the following command to parse these files into a binary cache:
```bash
bat cache --init
bat cache --build
```
Finally, use `bat --list-languages` to check if the new languages are available.
@@ -210,16 +372,14 @@ This works very similar to how we add new syntax definitions.
First, create a folder with the new syntax highlighting themes:
```bash
BAT_CONFIG_DIR="$(bat cache --config-dir)"
mkdir -p "$BAT_CONFIG_DIR/themes"
cd "$BAT_CONFIG_DIR/themes"
mkdir -p "$(bat --config-dir)/themes"
cd "$(bat --config-dir)/themes"
# Download a theme in '.tmTheme' format, for example:
git clone https://github.com/greggb/sublime-snazzy
# Update the binary cache
bat cache --init
bat cache --build
```
Finally, use `bat --list-themes` to check if the new themes are available.
@@ -229,13 +389,69 @@ Finally, use `bat --list-themes` to check if the new themes are available.
`bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not
set, `less` is used by default. If you want to use a different pager, you can either modify the
`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in
`PAGER`. If you want to pass command-line arguments to the pager, you need to create a small shell
script as a wrapper, for example:
`PAGER`.
If you want to pass command-line arguments to the pager, you can also set them via the
`PAGER`/`BAT_PAGER` variables:
```bash
#!/bin/bash
export BAT_PAGER="less -RF"
```
less --tabs 4 -RF "$@"
Instead of using environment variables, you can also use `bat`s [configuration file](https://github.com/sharkdp/bat#configuration-file) to configure the pager (`--pager` option).
**Note**: By default, if the pager is set to `less` (and no command-line options are specified),
`bat` will pass the following command line
options to the pager: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` and `-X`/`--no-init`.
The first (`-R`) is needed to interpret ANSI colors correctly. The second option (`-F`) instructs
less to exit immediately if the output size is smaller than the vertical size of the terminal.
This is convenient for small files because you do not have to press `q` to quit the pager. The
third option (`-X`) is needed to fix a bug with the `--quit-if-one-screen` feature in old versions
of `less`. Unfortunately, it also breaks mouse-wheel support in `less`. If you want to enable
mouse-wheel scrolling, you can either pass just `-R` (as in the example above, this will disable
the quit-if-one-screen feature), or you can use a recent version of `less` and pass `-RF` which
will hopefully enable both quit-if-one-screen and mouse-wheel scrolling.
If scrolling still doesn't work for you, you can try to pass the `-S` option in addition.
## Configuration file
`bat` can also be customized with a configuration file. The location of the file is dependent
on your operating system. To get the default path for your system, call
```
bat --config-file
```
Alternatively, you can use the `BAT_CONFIG_PATH` environment variable to point `bat` to a
non-default location of the configuration file:
```bash
export BAT_CONFIG_PATH="/path/to/bat.conf"
```
### Format
The configuration file is a simple list of command line arguments. Use `bat --help` to see a full list of possible options and values. In addition, you can add comments by prepending a line with the `#` character.
Example configuration file:
```bash
# Set the theme to "TwoDark"
--theme="TwoDark"
# Show line numbers, Git modifications and file header (but no grid)
--style="numbers,changes,header"
# Use italic text on the terminal (not supported on all terminals)
--italic-text=always
# Add mouse scrolling support in less (does not work with older
# versions of "less")
--pager="less -FR"
# Use C++ syntax (instead of C) for .h header files
--map-syntax h:cpp
# Use "gitignore" highlighting for ".ignore" files
--map-syntax .ignore:.gitignore
```
## Using `bat` on Windows
@@ -247,19 +463,39 @@ less --tabs 4 -RF "$@"
Windows only includes a very limited pager in the form of `more`. You can download a Windows binary
for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through
Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in
your `PATH` or [define an environment variable](#using-a-different-pager).
your `PATH` or [define an environment variable](#using-a-different-pager). The [Chocolatey package](#on-windows) installs `less` automatically.
### Colours
### Colors
Windows 10 natively supports colours in both `conhost.exe` (Command Prompt) and PowerShell since
Windows 10 natively supports colors in both `conhost.exe` (Command Prompt) and PowerShell since
[v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)), as
well as in newer versions of bash. On earlier versions of Windows, you can use
[Cmder](http://cmder.net/), which includes [ConEmu](https://conemu.github.io/).
**Note:** The Git and MSYS versions of `less` do not correctly interpret colours on Windows. If you
**Note:** The Git and MSYS versions of `less` do not correctly interpret colors on Windows. If you
dont have any other pagers installed, you can disable paging entirely by passing `--paging=never`
or by setting `BAT_PAGER` to an empty string.
### Cygwin
`bat` on Windows does not natively support Cygwin's unix-style paths (`/cygdrive/*`). When passed an absolute cygwin path as an argument, `bat` will encounter the following error: `The system cannot find the path specified. (os error 3)`
This can be solved by creating a wrapper or adding the following function to your `.bash_profile` file:
```shell
bat() {
local index
local args=("$@")
for index in $(seq 0 ${#args[@]}) ; do
case "${args[index]}" in
-*) continue;;
*) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";;
esac
done
command bat "${args[@]}"
}
```
## Troubleshooting
### Terminals & colors
@@ -279,10 +515,6 @@ are supported (and fall back to 8-bit colors).
Please try a different theme (see `bat --list-themes` for a list). The `OneHalfDark` and
`OneHalfLight` themes provide grid and line colors that are brighter.
### Error when compiling: "cannot find -lz"
Please install the `zlib-devel` package and try again.
## Development
```bash
+1
View File
@@ -0,0 +1 @@
* linguist-vendored
+13
View File
@@ -0,0 +1,13 @@
diff --git syntaxes/Packages/Java/JavaDoc.sublime-syntax syntaxes/Packages/Java/JavaDoc.sublime-syntax
index 422a6a9..40a741e 100644
--- syntaxes/Packages/Java/JavaDoc.sublime-syntax
+++ syntaxes/Packages/Java/JavaDoc.sublime-syntax
@@ -13,7 +13,7 @@ variables:
contexts:
prototype:
# https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#leadingasterisks
- - match: ^\s*(\*)\s*(?!\s*@)
+ - match: ^\s*(\*)(?!/)\s*(?!\s*@)
captures:
1: punctuation.definition.comment.javadoc
+11 -3
View File
@@ -13,12 +13,15 @@ In order to add new syntaxes to `bat`, follow these steps:
Sublime Text and convert it to a `.sublime-syntax` file via *Tools* -> *Developer* ->
*New Syntax from XXX.tmLanguage...*. Save the new file in the `assets/syntaxes` folder.
3. Run the `create.sh` script. It calls `bat cache --init` to parse all available
3. Run the `create.sh` script. It calls `bat cache --build` to parse all available
`.sublime-syntax` files and serialize them to a `syntaxes.bin` file (in this folder).
4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the
`bat` binary.
5. If you send a pull request with your changes, please do *not* include the changed `syntaxes.bin`
file. A new binary cache file will be created once before every new release of `bat`.
### Troubleshooting
Make sure that the local cache does not interfere with the internally stored syntaxes and
@@ -28,5 +31,10 @@ themes (`bat cache --clear`).
The following files have been manually modified after converting from a `.tmLanguage` file:
* `VimL.sublime-syntax` => added `.vimrc` file type.
* `Dart.sublime-syntax` => removed `#regex.dart` include,
* `Dart.sublime-syntax` => removed `#regex.dart` include.
* `INI.sublime-syntax` => added `.hgrc`, `hgrc`, and `desktop` file types.
* `Org mode.sublime-syntax` => removed `task` file type.
### Non-submodule additions
* `Assembly (x86_64)` has been manually added from https://github.com/13xforever/x86-assembly-textmate-bundle due to `git clone` recursion problems
+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"
Vendored Regular → Executable
+13 -1
View File
@@ -1,5 +1,17 @@
#!/bin/bash
set -euo pipefail
ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
bat cache --init --blank --source="$ASSET_DIR" --target="$ASSET_DIR"
# Always remove the local cache to avoid any confusion
bat cache --clear
# TODO: Remove this (and the reverse part below) when
# https://github.com/trishume/syntect/issues/222 has been fixed
JAVADOC_FILE="${ASSET_DIR}/syntaxes/Packages/Java/JavaDoc.sublime-syntax"
JAVADOC_PATCH="${ASSET_DIR}/JavaDoc.sublime-syntax.patch"
patch "$JAVADOC_FILE" "$JAVADOC_PATCH"
bat cache --build --blank --source="$ASSET_DIR" --target="$ASSET_DIR"
patch -R "$JAVADOC_FILE" "$JAVADOC_PATCH"
BIN
View File
Binary file not shown.
Vendored Submodule
+1
+283
View File
@@ -0,0 +1,283 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: AsciiDoc
comment: |
A very early hack. Mostly ripped from other syntaxes.
Only the very basic stuff is working.
file_extensions:
- adoc
- asciidoc
- asc
scope: text.html.asciidoc
contexts:
main:
- include: heading_inline
- include: heading-block
- include: heading-blockattr
- match: \$\$(?!\$)
push:
- meta_scope: comment.block.passthrough.macro.doubledollar.asciidoc
- match: \$\$(?!\$)
pop: true
- match: \+\+\+(?!\+)
push:
- meta_scope: comment.block.passthrough.macro.tripeplus.asciidoc
- match: \+\+\+(?!\+)
pop: true
- match: (//).*$\n?
scope: comment.line.double-slash.asciidoc
- match: |-
(?x)^
(?= ([/+-.*_=]{4,})\s*$
| ([ \t]{1,})
| [=]{1,6}\s*+
| [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$
)
push:
- meta_scope: meta.block-level.asciidoc
- match: |-
(?x)^
(?! \1
| ([ \t]{1,})
| [=]{1,6}\s*+
| [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$
)
pop: true
- include: block_quote
- include: block_raw
- include: heading_inline
- include: heading-block
- include: separator
- match: '^[ ]{0,3}([*+-])(?=\s)'
captures:
1: punctuation.definition.list_item.asciidoc
push:
- meta_scope: markup.list.unnumbered.asciidoc
- match: ^(?=\S)
captures:
1: punctuation.definition.list_item.asciidoc
pop: true
- include: list-paragraph
- match: '^[ ]{0,3}[0-9]+(\.)(?=\s)'
captures:
1: punctuation.definition.list_item.asciidoc
push:
- meta_scope: markup.list.numbered.asciidoc
- match: ^(?=\S)
captures:
1: punctuation.definition.list_item.asciidoc
pop: true
- include: list-paragraph
- match: '^([/+-.*_=]){4,}\s*$'
push:
- meta_scope: comment.block.asciidoc
- match: '^\1{4,}\s*$'
pop: true
- match: '^([/+.]){4,}\s*$'
comment: asciidoc formatting is disabled inside certain blocks.
push:
- meta_scope: meta.disable-asciidoc
- match: '^[/+.]{4,}\s*$'
pop: true
- match: '^(?=\S)(?![=-]{3,}(?=$))(?!\.\S+)'
push:
- meta_scope: meta.paragraph.asciidoc
- match: '^(?:\s*$|(?=[ ]{,3}>.))|(?=[ \t]*\n)(?<=^===|^====|=====|^---|^----|-----)[ \t]*\n'
pop: true
- include: inline
- include: scope:text.html.basic
- match: '^(={3,})(?=[ \t]*$)'
scope: markup.heading.0.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
- match: '^(-{3,})(?=[ \t]*$)'
scope: markup.heading.1.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
- match: '^(~{3,})(?=[ \t]*$)'
scope: markup.heading.2.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
- match: '^(\^{3,})(?=[ \t]*$)'
scope: markup.heading.3.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
- match: '^(\+{3,})(?=[ \t]*$)'
scope: markup.heading.4.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
attribute-entry:
- match: '^:[-_. A-Za-z0-9]+:\s*(.*)\s*$'
scope: variable.other
attribute-reference:
- match: "{[-_. A-Za-z0-9]+}"
scope: variable.other
attribute-reference-predefined:
- match: "{(?i:amp|asciidoc-dir|asciidoc-file|asciidoc-version|author|authored|authorinitials|backend-docbook|backend-xhtml11|backend-html4|docbook-article|xhtml11-article|html4-article|docbook-book|xhtml11-book|html4-book|docbook-manpage|xhtml11-manpage|html4-manpage|backend|backslash|basebackend|brvbar|date|docdate|doctime|docname|docfile|docdir|doctitle|doctype-article|doctype-book|doctype-manpage|doctype|email|empty|encoding|filetype|firstname|gt|id|indir|infile|lastname|level|listindex|localdate|localtime|lt|manname|manpurpose|mantitle|manvolnum|middlename|nbsp|outdir|outfile|reftext|revision|sectnum|showcomments|title|two_colons|two_semicolons|user-dir|verbose)}"
scope: support.variable
block_quote:
- match: '^([/+-.*_=]){4,}\s*$'
push:
- meta_scope: comment.block.asciidoc
- match: '^\1{4,}\s*$'
pop: true
block_raw:
- match: '\G([ ]{4}|\t).*$\n?'
scope: markup.raw.block.asciidoc
bracket:
- match: '<(?![a-z/?\$!])'
comment: |
asciidoc will convert this for us. We match it so that the
HTML grammar will not mark it up as invalid.
scope: meta.other.valid-bracket.asciidoc
character-replacements:
- match: \(C\)|\(R\)|\(TM\)|--(?!-)|\.\.\.(?!\.)|->|<-|=>|<=
scope: constant.character.asciidoc
escape:
- match: '\\[-`*_#+.!(){}\[\]\\>:]'
scope: constant.character.escape.asciidoc
heading:
- match: '(?m)^(\S+)$([=-~^+])+\s*$'
scope: markup.heading.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
heading-block:
- match: ^\.(\w.*)$
scope: markup.heading.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
heading-blockattr:
- match: '^\[\[?(\w.*)\]$'
scope: markup.heading.asciidoc
captures:
1: punctuation.definition.heading.asciidoc
heading_inline:
- match: '\G(={1,6})(?!=)\s*(?=\S)'
captures:
1: punctuation.definition.heading.asciidoc
push:
- meta_scope: markup.heading.asciidoc
- meta_content_scope: entity.name.section.asciidoc
- match: \s*(=*)$\n?
captures:
1: punctuation.definition.heading.asciidoc
pop: true
- include: inline
inline:
- include: line-break
- include: line-page-break
- include: line-ruler
- include: escape
- include: passthrough-macro-trippleplus-inline
- include: passthrough-macro-doubledollar-inline
- include: character-replacements
- include: bracket
- include: raw
- include: text-quote-single
- include: text-quote-double
- include: text-quote-other
- include: text-bold-unconstrained
- include: text-italic-unconstrained
- include: text-monospace-unconstrained
- include: text-unquoted-unconstrained
- include: text-bold
- include: text-italic
- include: text-monospace
- include: text-unquoted
- include: attribute-entry
- include: attribute-reference-predefined
- include: attribute-reference
line-break:
- match: (?<=\S)\s+\+$
scope: constant.character.escape.asciidoc
line-page-break:
- match: "^<{3,}$"
scope: constant.character.escape.asciidoc
line-ruler:
- match: "^'{3,}$"
scope: constant.character.escape.asciidoc
list-paragraph:
- match: \G\s+(?=\S)
push:
- meta_scope: meta.paragraph.list.asciidoc
- match: ^\s*$
pop: true
- include: inline
passthrough-macro-doubledollar-inline:
- match: '(?:\[.*\])?\$\$(?!\$).+\$\$(?!\$)'
scope: comment.block.passthrough.asciidoc
passthrough-macro-trippleplus-inline:
- match: '(?:\[.*\])?\+\+\+(?!\+).+\+\+\+(?!\+)'
scope: comment.block.passthrough.asciidoc
raw:
- match: '(`+)(?:[^`]|(?!(?<!`)\1(?!`))`)*+(\1)'
scope: markup.raw.inline.asciidoc
captures:
1: punctuation.definition.raw.asciidoc
2: punctuation.definition.raw.asciidoc
separator:
- match: '\G[ ]{,3}([-*_])([ ]{,2}\1){2,}[ \t]*$\n?'
scope: meta.separator.asciidoc
text-bold:
- match: (?<!\w)(\*)(?=\S)
captures:
1: punctuation.definition.bold.asciidoc
push:
- meta_scope: markup.bold.asciidoc
- match: (?<=\S)(\1)(?!\w)
captures:
1: punctuation.definition.bold.asciidoc
pop: true
text-bold-unconstrained:
- match: (\*\*)(?=\S)
captures:
1: punctuation.definition.bold.asciidoc
push:
- meta_scope: markup.bold.asciidoc
- match: (?<=\S)(\1)
captures:
1: punctuation.definition.bold.asciidoc
pop: true
text-italic:
- match: (?<!\w)('|_)(?=\S)
captures:
1: punctuation.definition.italic.asciidoc
push:
- meta_scope: markup.italic.asciidoc
- match: (?<=\S)(\1)((?!\1)|(?=\1\1))(?!\w)
captures:
1: punctuation.definition.italic.asciidoc
pop: true
text-italic-unconstrained:
- match: (__)(?=\S)
captures:
1: punctuation.definition.italic.asciidoc
push:
- meta_scope: markup.italic.asciidoc
- match: (?<=\S)(\1)
captures:
1: punctuation.definition.italic.asciidoc
pop: true
text-monospace:
- match: '(?<!\w)([\+`])[^\+]*(\1)(?!\w)'
scope: string.interpolated.asciidoc
text-monospace-unconstrained:
- match: (\+\+).*(\1)
scope: string.interpolated.asciidoc
text-quote-double:
- match: '(?<!\w)(?:\[.*\])?``(?!`).*''''(?!'')(?!\w)'
scope: string.quoted.double.asciidoc
text-quote-other:
- match: '(?<!\w)(?:\[.*\])?([~^]).*(\1)(?!\w)'
scope: string.quoted.single.asciidoc
text-quote-single:
- match: '(?<!\w)(?:\[.*\])?`(?!`).*''(?!'')(?!\w)'
comment: "TODO: Sub- and Superscript are really unconstrained"
scope: string.quoted.single.asciidoc
text-unquoted:
- match: (?<!\w)(#).*(\1)(?!\w)
scope: string.unquoted.asciidoc
text-unquoted-unconstrained:
- match: (##).*(\1)
scope: string.unquoted.asciidoc
+172
View File
@@ -0,0 +1,172 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: ARM Assembly
file_extensions:
- s
- S
scope: source.asm.arm
contexts:
main:
- match: "@.*$"
scope: comment.line
- match: //.*$
scope: comment.line
- match: ;.*$
scope: comment.line
- match: ^\s*\#\s*if\s+0\b
push:
- meta_scope: comment.preprocessor
- match: ^\s*\#\s*endif\b
pop: true
- match: /\*
push:
- meta_scope: comment.block
- match: \*/
pop: true
- match: |-
(?x)
^\s*\#\s*(define)\s+ # define
((?<id>[a-zA-Z_][a-zA-Z0-9_]*)) # macro name
(?: # and optionally:
(\() # an open parenthesis
(
\s* \g<id> \s* # first argument
((,) \s* \g<id> \s*)* # additional arguments
(?:\.\.\.)? # varargs ellipsis?
)
(\)) # a close parenthesis
)?
captures:
1: keyword.control.import.define.c
2: entity.name.function.preprocessor.c
4: punctuation.definition.parameters.c
5: variable.parameter.preprocessor.c
7: punctuation.separator.parameters.c
8: punctuation.definition.parameters.c
push:
- meta_scope: meta.preprocessor.macro.c
- match: (?=(?://|/\*))|$
pop: true
- match: (?>\\\s*\n)
scope: punctuation.separator.continuation.c
- include: $top_level_main
- match: ^\s*#\s*(error|warning)\b
captures:
1: keyword.control.import.error.c
push:
- meta_scope: meta.preprocessor.diagnostic.c
- match: $
captures:
1: keyword.control.import.error.c
pop: true
- match: (?>\\\s*\n)
scope: punctuation.separator.continuation.c
- match: ^\s*#\s*(include|import)\b\s+
captures:
1: keyword.control.import.include.c
push:
- meta_scope: meta.preprocessor.c.include
- match: (?=(?://|/\*))|$
captures:
1: keyword.control.import.include.c
pop: true
- match: (?>\\\s*\n)
scope: punctuation.separator.continuation.c
- match: '"'
captures:
0: punctuation.definition.string.begin.c
push:
- meta_scope: string.quoted.double.include.c
- match: '"'
captures:
0: punctuation.definition.string.end.c
pop: true
- match: <
captures:
0: punctuation.definition.string.begin.c
push:
- meta_scope: string.quoted.other.lt-gt.include.c
- match: ">"
captures:
0: punctuation.definition.string.end.c
pop: true
- match: '((?i)([xw][0-9]|[xw]1[0-9]||[xw]2[0-9]|[wx]30|wzr|xzr|wsp|fpsr|fpcr|[rcp]1[0-5]|[rcp][0-9]|a[1-4]|v[1-8]|sl|sb|fp|ip|sp|lr|(c|s)psr(_c)?|pc|[sd]3[0-1]|[sd][12][0-9]|[sd][0-9]|fpsid|fpscr|fpexc|q3[0-1]|q2[0-9]|q1[0-9]|q[0-9]|APSR_nzcv|sy)!?(?-i))?\b'
scope: storage.other.register
- match: \.(?i)(globl|global|macro|endm|purgem|if|elseif|else|endif|section|text|arm|align|balign|irp|rept|endr|req|unreq|error|short|func|endfunc|hidden|type|fpu|arch|code|altmacro|object_arch|word|int|string)(?-i)\b
scope: keyword.control.directive
- match: armv(2a?|3m?|4t?|5t?e?6(j|t2|zk?|-m)?|7v?e?(-(a|r|m))?|8-a(\+crc)?)
scope: keyword.control.arch.arm
- match: ^\s*#\s*(define|defined|elif|else|if|ifdef|ifndef|line|pragma|undef|endif)\b
captures:
1: keyword.control.import.c
push:
- meta_scope: meta.preprocessor.c
- match: (?=(?://|/\*))|$
captures:
1: keyword.control.import.c
pop: true
- match: (?>\\\s*\n)
scope: punctuation.separator.continuation.c
- match: |-
(?x)\b((?i)
(
(bf(c|i)|(u|s)bfx|(u|s)xta?(h|b)?) |
(v(add|cvt|sub|mov|trn|cmp|div|qdmulh|mrs|mul|ld1|qadd|qshrun|st[1234]|addw|mull|mlal|rshrn|swp|qmovun)|qmovun)(\.([isup]?8|[isupf]?16|[isuf]?32|[isu]?64))* |
(and|m(rs|sr)|eor|sub|rsb|add|adc|sbc|rsc|tst|teq|cmp|cmn|orr|mov|bic|mvn |
(neg) |
(lsr|lsl|ror|asr) # shift ops either pseudo ops or actual shifts
)s? |
(mul|mla|mull|smlabb) |
(mov(w|t)) |
rev(8|16)? |
(pld|adr|adrl|vswp)
)
(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b
scope: support.function.mnemonic.arithmetic
- match: |-
(?x)\b((?i)(
swi|svc|wfi|
dmb | clrex | dsb | isb |
v(ldr|str|push|pop) |
(push|pop) |
(st|ld)(
p |
r(ex|s?(h|b)|d)? |
m(
(f|e)(d|a) |
(d|i)(b|a)
)?
) |
b(l|x|lx|lr|r)? |
(i|e)?ret|
b\.(eq|ne|hs|cs|lo|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|nv)+ |
(c|t)?bn?z|
)+(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))\b
scope: support.function.mnemonic.memory
- match: '\b((?i)(def(b|w|s)|equ|(include|get)(\s+([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*?)\.s)?)?(?-i))\b'
scope: meta.preprocessor.c.include
- match: \b((?i)(align)(?-i))?\b
scope: storage.type.c.memaccess
- match: \s+\".+\"
scope: string
- match: \b((?i)nop(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b
scope: comment.nop
- match: '\s\['
push:
- meta_scope: storage.type.c.memaccess
- match: '\]'
pop: true
- match: (?>\\\s*\n)
scope: punctuation.separator.continuation.c
- include: $top_level_main
- match: (\b|\s+)\=\b
scope: keyword.control.evaluation
- match: '(\b|\s+)(\#)?-?(0x|&)[0-9a-fA-F_]+\b'
scope: constant.numeric.hex
- match: '(\b|\s+)\#-?[0-9a-zA-Z_]+\b'
scope: constant.numeric.literal
- match: '(\b|\s+)[0-9]+\b'
scope: constant.numeric.dec
- match: '\b([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*)\b'
scope: meta.function.source.arm.label
File diff suppressed because it is too large Load Diff
Vendored Submodule
+1
Submodule assets/syntaxes/DotENV added at f6cad1140c
+88
View File
@@ -0,0 +1,88 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: DotENV
file_extensions:
- .env
- .envrc
- .env.dist
- .env.local
- .env.sample
- .env.example
- .env.test
- .env.test.local
- .env.dev
- .env.development
- .env.development.local
- .env.prod
- .env.production
- .env.production.local
- .env.dusk.local
scope: source.env
contexts:
main:
- match: (#).*$\n?
comment: "Comments - starts with #"
scope: comment.line.number-sign.env
captures:
1: punctuation.definition.comment.env
- match: (\")
comment: Strings (double)
captures:
1: punctuation.definition.string.begin.env
push:
- meta_scope: string.quoted.double.env
- match: (\")
captures:
1: punctuation.definition.string.end
pop: true
- include: interpolation
- include: variable
- include: escape-characters
- match: (\')
comment: Strings (single)
captures:
1: punctuation.definition.string.begin.env
push:
- meta_scope: string.quoted.single.env
- match: (\')
captures:
1: punctuation.definition.string.end
pop: true
- match: '(?<=[\w])\s?='
comment: Assignment Operator
scope: keyword.operator.assignment.env
- match: '([\w]+)(?=\s?\=)'
comment: Variable
scope: variable.other.env
- match: (?i)\s?(export)
comment: Keywords
scope: keyword.other.env
- match: (?i)(?<=\=)\s?(true|false|null)
comment: Constants
scope: constant.language.env
- match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)\b'
comment: Numeric
scope: constant.numeric.env
escape-characters:
- match: '\\[nrt\\\$\"\'']'
scope: constant.character.escape.env
interpolation:
- match: '(\$\{|\{)'
comment: 'Template Syntax: "foo ${bar} {$baz}"'
captures:
1: string.interpolated.env keyword.other.template.begin.env
push:
- match: '(\})'
captures:
1: string.interpolated.env keyword.other.template.end.env
pop: true
- match: '(?x)(\$+)?([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*?\b)'
captures:
1: punctuation.definition.variable.env variable.other.env
2: variable.other.env
variable:
- match: '(?x)(\$+)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*?\b)'
captures:
1: punctuation.definition.variable.env variable.other.env
2: variable.other.env
+567 -129
View File
@@ -9,63 +9,230 @@ file_extensions:
scope: source.fsharp
contexts:
main:
- include: compiler_directives
- include: comments
- include: constants
- include: structure
- include: attributes
- include: strings
- include: chars
- include: double_tick
- include: definition
- include: method_calls
- include: abstract_definition
- include: attributes
- include: modules
- include: anonymous_functions
- include: du_declaration
- include: record_declaration
- include: records
- include: strp_inlined
- 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:
- match: \b(fun)\b
captures:
1: keyword.other.function-definition.fsharp
1: keyword.fsharp
push:
- meta_scope: meta.function.anonymous
- meta_scope: function.anonymous
- match: (->)
captures:
1: keyword.other.fsharp
1: keyword.fsharp
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
attributes:
- match: '\[\<'
push:
- meta_scope: support.function.attribute.fsharp
- match: '\>\]'
- match: '\>\]|\]'
pop: true
- include: main
characters:
- match: (')
cexprs:
- match: '\b(async|seq|promise|task|maybe|asyncMaybe|controller|scope|application|pipeline)\s*\{'
scope: cexpr.fsharp
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.single.fsharp
- match: (')
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\""ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
0: keyword.fsharp
chars:
- match: ('\\?.')
scope: char.fsharp
captures:
1: string.quoted.single.fsharp
comments:
- match: \(\*\*?(\*)\)
scope: comment.block.fsharp
- match: (\(\*(?!\)))
captures:
1: comment.block.empty.fsharp
- match: '\(\*[^\)]'
1: comment.block.fsharp
push:
- meta_scope: comment.block.fsharp
- match: \*\)
- match: (\*\))
captures:
1: comment.block.fsharp
pop: true
- include: comments
- match: //.*$
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:
- match: \(\)
scope: constant.language.unit.fsharp
@@ -73,123 +240,349 @@ contexts:
scope: constant.numeric.floating-point.fsharp
- match: '\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))'
scope: constant.numeric.integer.nativeint.fsharp
- match: \b(true|false|null|unit)\b
scope: constant.others.fsharp
definition:
- match: '\b(val|val|let|and|member|override|use)\s?(rec|inline|mutable)?(\s+\(?([a-zA-Z.\|_][a-zA-Z0-9.|_]*)\)?\w*)\b'
- 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:
1: keyword.other.binding.fsharp
2: keyword.other.function-recursive.fsharp
3: variable.other.binding.fsharp
1: keyword.fsharp
2: keyword.fsharp
3: support.function.attribute.fsharp
4: keyword.fsharp
5: variable.fsharp
push:
- meta_scope: meta.binding.fsharp
- match: "=|$"
- meta_scope: binding.fsharp
- match: \s*(with\b|=|\n+=|(?<=\=))
captures:
1: punctuation.separator.function.type-constraint.fsharp
1: keyword.fsharp
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
- match: \b(let)\s+((\(\))|(_))\s+=
scope: meta.expression.fsharp
- include: 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|use|use\!|struct|while|mutable)(?!')\b
scope: keyword.fsharp
- match: ":"
scope: keyword.fsharp
- include: constants
- match: '((''|\^)[[:alpha:]0-9''._]+)'
captures:
1: keyword.other.binding.fsharp
2: keyword.other.function-recursive.fsharp
4: constant.language.unit.fsharp
5: constant.language.ignored.fsharp
keywords:
- match: ^\s*#\s*(light|if|else|endif|r|I|load|time|help|quit)\b
1: entity.name.type.fsharp
- match: (<)
captures:
1: keyword.symbol.fsharp
push:
- meta_scope: meta.preprocessor.fsharp
- match: (\s|$)
pop: true
- match: \b(new|in|as|if|then|else|elif|for|begin|end|match|with|type|inherit|true|false|null|do)\b
scope: keyword.other.fsharp
- match: '(\|>|\|?>|\->|\<\-|:>|:|\[|\]|\;|\||_)'
scope: entity.name
method_calls:
- match: '(?<!\w)([a-z]\w*)(\.)'
push:
- meta_scope: meta.method-call.fsharp
- match: '[A-Z]\w*(\.)'
scope: meta.method.fsharp
- match: (>)
captures:
1: punctuation.separator.method-call.fsharp
- match: (?=.)
1: keyword.symbol.fsharp
pop: true
modules:
- match: '\b(namespace|module)\s+([a-zA-Z][a-zA-Z0-9''_.]*)'
- match: '((''|\^)[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- include: tuple_signature
- include: generic_declaration
- match: '(?!when|and|or\b)\b([\w0-9''`^._]+)'
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
push:
- meta_scope: meta.module.namespace.fsharp
- meta_scope: namespace.open.fsharp
- match: (\s|$)
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
- match: '(\.)([[:alpha:]][[:alpha:]0-9''_]*)'
scope: entity.name.section.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '\b(open)\s+([A-Z][a-zA-Z0-9''_]*)(?=(\.[A-Z][a-zA-Z0-9_]*)*)'
1: punctuation.separator.namespace-reference.fsharp
2: entity.name.section.fsharp
- match: '^\s*(module)\s+([A-Z][[:alpha:]0-9''_]*)\s*(=)\s*([A-Z][[:alpha:]0-9''_]*)'
captures:
1: keyword.other.fsharp
2: support.other.module.fsharp
1: keyword.fsharp
2: entity.name.type.namespace.fsharp
3: punctuation.separator.namespace-definition.fsharp
4: entity.name.section.fsharp
push:
- meta_scope: meta.module.open.fsharp
- meta_scope: namespace.alias.fsharp
- match: (\s|$)
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
- match: '(\.)([A-Z][[:alpha:]0-9''_]*)'
scope: entity.name.section.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '^\s*(module)\s+([A-Z][a-zA-Z0-9''_]*)\s*(=)\s*([A-Z][a-zA-Z0-9''_]*)'
1: punctuation.separator.namespace-reference.fsharp
2: entity.name.section.fsharp
record_declaration:
- match: '(\{)'
captures:
1: keyword.other.module-definition.fsharp
2: entity.name.type.module.fsharp
3: punctuation.separator.module-definition.fsharp
4: support.other.module.fsharp
1: keyword.symbol.fsharp
push:
- meta_scope: meta.module.alias.fsharp
- match: (\s|$)
- match: '(?<=\})'
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
- include: comments
- match: '(((mutable)\s[[:alpha:]]+)|[[:alpha:]0-9''`<>^._]*)\s*((?<!:):(?!:))\s*'
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '(?<!\w)([A-Z][a-zA-Z0-9_]*)(\.)'
3: keyword.fsharp
4: keyword.symbol.fsharp
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:
1: support.other.module.fsharp
2: punctuation.separator.module-reference.fsharp
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
- match: "({)"
captures:
1: keyword.symbol.fsharp
push:
- meta_scope: meta.module.reference.fsharp
- match: '[A-Z][a-zA-Z0-9_]+(\.)'
scope: support.other.module.fsharp
- match: "(})"
captures:
1: punctuation.separator.module-reference.fsharp
- match: (?=.)
1: keyword.symbol.fsharp
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:
- match: '(?=[^\\])(""")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (""")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '(?=[^\\])(@")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (")
- meta_scope: string.quoted.literal.fsharp
- match: (")(?!")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '"(")'
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: '(?=[^\\])(")'
captures:
1: punctuation.definition.string.begin.fsharp
@@ -201,34 +594,79 @@ contexts:
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})'
- 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}).'
- match: '\\(?![\\''''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
- match: '(?=[^\\])('')'
- include: string_formatter
strp_inlined:
- match: (\()
captures:
1: punctuation.definition.string.begin.fsharp
1: keyword.symbol.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (')
- match: (\))
captures:
1: punctuation.definition.string.end.fsharp
1: keyword.symbol.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
structure:
- match: \(
- include: strp_inlined_body
strp_inlined_body:
- include: comments
- include: anonymous_functions
- match: '(\^[[:alpha:]0-9''._]+)'
captures:
1: entity.name.type.fsharp
- match: \b(and|when|or)\b
scope: keyword.fsharp
- match: (\()
captures:
1: keyword.symbol.fsharp
push:
- meta_scope: meta.paren-group.fsharp
- match: \)
- match: (\))
captures:
1: keyword.symbol.fsharp
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:
- match: \(\)
scope: variable.parameter.unit.fsharp
- match: '[a-zA-Z]\w*'
scope: variable.parameter.fsharp
scope: constant.language.unit.fsharp
- match: '(\?{0,1})(``[[:alpha:]0-9''`^:,._ ]+``|[[:alpha:]0-9''`<>^._ ]\w*)'
captures:
1: keyword.symbol.fsharp
2: variable.parameter.fsharp
Vendored Submodule
+1
Submodule assets/syntaxes/GraphQL added at 66ce8713d8
+662
View File
@@ -0,0 +1,662 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: HTML (Twig)
file_extensions:
- twig
- html.twig
scope: text.html.twig
contexts:
main:
- match: '(<)([a-zA-Z0-9:]++)(?=[^>]*></\2>)'
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.html
push:
- meta_scope: meta.tag.any.html
- match: (>(<)/)(\2)(>)
captures:
1: punctuation.definition.tag.html
2: meta.scope.between-tag-pair.html
3: entity.name.tag.html
4: punctuation.definition.tag.html
pop: true
- include: tag-stuff
- match: (<\?)(xml)
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.xml.html
push:
- meta_scope: meta.tag.preprocessor.xml.html
- match: (\?>)
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.xml.html
pop: true
- include: tag-generic-attribute
- include: string-double-quoted
- include: string-single-quoted
- match: <!--
captures:
0: punctuation.definition.comment.html
push:
- meta_scope: comment.block.html
- match: '--\s*>'
captures:
0: punctuation.definition.comment.html
pop: true
- match: "--"
scope: invalid.illegal.bad-comments-or-CDATA.html
- include: embedded-code
- match: <!
captures:
0: punctuation.definition.tag.html
push:
- meta_scope: meta.tag.sgml.html
- match: ">"
captures:
0: punctuation.definition.tag.html
pop: true
- match: (?i:DOCTYPE)
captures:
1: entity.name.tag.doctype.html
push:
- meta_scope: meta.tag.sgml.doctype.html
- match: (?=>)
captures:
1: entity.name.tag.doctype.html
pop: true
- match: '"[^">]*"'
scope: string.quoted.double.doctype.identifiers-and-DTDs.html
- match: '\[CDATA\['
push:
- meta_scope: constant.other.inline-data.html
- match: "]](?=>)"
pop: true
- match: (\s*)(?!--|>)\S(\s*)
scope: invalid.illegal.bad-comments-or-CDATA.html
- include: embedded-code
- match: '(?:^\s+)?(<)((?i:style))\b(?![^>]*/>)'
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.style.html
3: punctuation.definition.tag.html
push:
- meta_scope: source.css.embedded.html
- match: (</)((?i:style))(>)(?:\s*\n)?
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.style.html
3: punctuation.definition.tag.html
pop: true
- include: tag-stuff
- match: (>)
captures:
1: punctuation.definition.tag.html
push:
- match: (?=</(?i:style))
pop: true
- include: embedded-code
- include: scope:source.css
- match: '(?:^\s+)?(<)((?i:script))\b(?![^>]*/>)'
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.script.html
push:
- meta_scope: source.js.embedded.html
- match: (?<=</(script|SCRIPT))(>)(?:\s*\n)?
captures:
2: punctuation.definition.tag.html
pop: true
- include: tag-stuff
- match: (?<!</(?:script|SCRIPT))(>)
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.script.html
push:
- match: (</)((?i:script))
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.script.html
pop: true
- match: (//).*?((?=</script)|$\n?)
scope: comment.line.double-slash.js
captures:
1: punctuation.definition.comment.js
- match: /\*
captures:
0: punctuation.definition.comment.js
push:
- meta_scope: comment.block.js
- match: \*/|(?=</script)
captures:
0: punctuation.definition.comment.js
pop: true
- include: php
- include: twig-print-tag
- include: twig-statement-tag
- include: twig-comment-tag
- include: scope:source.js
- match: (</?)((?i:body|head|html)\b)
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.structure.any.html
push:
- meta_scope: meta.tag.structure.any.html
- match: (>)
captures:
1: punctuation.definition.tag.html
2: entity.name.tag.structure.any.html
pop: true
- include: tag-stuff
- match: (</?)((?i:address|blockquote|dd|div|dl|dt|fieldset|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|noframes|object|ol|p|ul|applet|center|dir|hr|menu|pre)\b)
captures:
1: punctuation.definition.tag.begin.html
2: entity.name.tag.block.any.html
push:
- meta_scope: meta.tag.block.any.html
- match: (>)
captures:
1: punctuation.definition.tag.end.html
pop: true
- include: tag-stuff
- match: (</?)((?i:a|abbr|acronym|area|b|base|basefont|bdo|big|br|button|caption|cite|code|col|colgroup|del|dfn|em|font|head|html|i|img|input|ins|isindex|kbd|label|legend|li|link|map|meta|noscript|optgroup|option|param|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|var)\b)
captures:
1: punctuation.definition.tag.begin.html
2: entity.name.tag.inline.any.html
push:
- meta_scope: meta.tag.inline.any.html
- match: "((?: ?/)?>)"
captures:
1: punctuation.definition.tag.end.html
pop: true
- include: tag-stuff
- match: "(</?)([a-zA-Z0-9:]+)"
captures:
1: punctuation.definition.tag.begin.html
2: entity.name.tag.other.html
push:
- meta_scope: meta.tag.other.html
- match: (>)
captures:
1: punctuation.definition.tag.end.html
pop: true
- include: tag-stuff
- include: entities
- match: <>
scope: invalid.illegal.incomplete.html
- match: <
scope: invalid.illegal.bad-angle-bracket.html
- include: twig-print-tag
- include: twig-statement-tag
- include: twig-comment-tag
embedded-code:
- include: ruby
- include: php
- include: twig-print-tag
- include: twig-statement-tag
- include: twig-comment-tag
- include: python
entities:
- match: "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)"
scope: constant.character.entity.html
captures:
1: punctuation.definition.entity.html
3: punctuation.definition.entity.html
- match: "&"
scope: invalid.illegal.bad-ampersand.html
php:
- match: (?=(^\s*)?<\?)
push:
- match: (?!(^\s*)?<\?)
pop: true
- include: scope:text.html.php
python:
- match: (?:^\s*)<\?python(?!.*\?>)
push:
- meta_scope: source.python.embedded.html
- match: \?>(?:\s*$\n)?
pop: true
- include: scope:source.python
ruby:
- match: "<%+#"
captures:
0: punctuation.definition.comment.erb
push:
- meta_scope: comment.block.erb
- match: "%>"
captures:
0: punctuation.definition.comment.erb
pop: true
- match: <%+(?!>)=?
captures:
0: punctuation.section.embedded.ruby
push:
- meta_scope: source.ruby.embedded.html
- match: "-?%>"
captures:
0: punctuation.section.embedded.ruby
pop: true
- match: (#).*?(?=-?%>)
scope: comment.line.number-sign.ruby
captures:
1: punctuation.definition.comment.ruby
- include: scope:source.ruby
- match: <\?r(?!>)=?
captures:
0: punctuation.section.embedded.ruby.nitro
push:
- meta_scope: source.ruby.nitro.embedded.html
- match: '-?\?>'
captures:
0: punctuation.section.embedded.ruby.nitro
pop: true
- match: (#).*?(?=-?\?>)
scope: comment.line.number-sign.ruby.nitro
captures:
1: punctuation.definition.comment.ruby.nitro
- include: scope:source.ruby
string-double-quoted:
- match: '"'
captures:
0: punctuation.definition.string.begin.html
push:
- meta_scope: string.quoted.double.html
- match: '"'
captures:
0: punctuation.definition.string.end.html
pop: true
- include: embedded-code
- include: entities
string-single-quoted:
- match: "'"
captures:
0: punctuation.definition.string.begin.html
push:
- meta_scope: string.quoted.single.html
- match: "'"
captures:
0: punctuation.definition.string.end.html
pop: true
- include: embedded-code
- include: entities
tag-generic-attribute:
- match: '\b([a-zA-Z\-:]+)'
scope: entity.other.attribute-name.html
tag-id-attribute:
- match: \b(id)\b\s*(=)
captures:
1: entity.other.attribute-name.id.html
2: punctuation.separator.key-value.html
push:
- meta_scope: meta.attribute-with-value.id.html
- match: (?<='|")
captures:
1: entity.other.attribute-name.id.html
2: punctuation.separator.key-value.html
pop: true
- match: '"'
captures:
0: punctuation.definition.string.begin.html
push:
- meta_scope: string.quoted.double.html
- meta_content_scope: meta.toc-list.id.html
- match: '"'
captures:
0: punctuation.definition.string.end.html
pop: true
- include: embedded-code
- include: entities
- match: "'"
captures:
0: punctuation.definition.string.begin.html
push:
- meta_scope: string.quoted.single.html
- meta_content_scope: meta.toc-list.id.html
- match: "'"
captures:
0: punctuation.definition.string.end.html
pop: true
- include: embedded-code
- include: entities
tag-stuff:
- include: tag-id-attribute
- include: tag-generic-attribute
- include: string-double-quoted
- include: string-single-quoted
- include: embedded-code
twig-arrays:
- match: '(?<=[\s\(\{\[:,])\['
captures:
0: punctuation.section.array.begin.twig
push:
- meta_scope: meta.array.twig
- match: '\]'
captures:
0: punctuation.section.array.end.twig
pop: true
- include: twig-arrays
- include: twig-hashes
- include: twig-constants
- include: twig-strings
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- match: ","
scope: punctuation.separator.object.twig
twig-comment-tag:
- match: '\{#-?'
captures:
0: punctuation.definition.comment.begin.twig
push:
- meta_scope: comment.block.twig
- match: '-?#\}'
captures:
0: punctuation.definition.comment.end.twig
pop: true
twig-constants:
- match: '(?i)(?<=[\s\[\(\{:,])(?:true|false|null|none)(?=[\s\)\]\}\,])'
scope: constant.language.twig
- match: '(?<=[\s\[\(\{:,]|\.\.|\*\*)[0-9]+(?:\.[0-9]+)?(?=[\s\)\]\}\,]|\.\.|\*\*)'
scope: constant.numeric.twig
twig-filters:
- match: '(?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\''\"]\|)|\{%\sfilter\s)(abs|capitalize|e(?:scape)?|first|join|(?:json|url)_encode|keys|last|length|lower|nl2br|number_format|raw|reverse|round|sort|striptags|title|trim|upper)(?=[\s\|\]\}\):,]|\.\.|\*\*)'
captures:
1: support.function.twig
twig-filters-ud:
- match: '(?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\''\"]\|)|\{%\sfilter\s)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)'
captures:
1: meta.function-call.other.twig
twig-filters-warg:
- match: '(?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\''\"]\|)|\{%\sfilter\s)(batch|convert_encoding|date|date_modify|default|e(?:scape)?|format|join|merge|number_format|replace|round|slice|split|trim)(\()'
captures:
1: support.function.twig
2: punctuation.definition.parameters.begin.twig
push:
- meta_content_scope: meta.function.arguments.twig
- match: \)
captures:
0: punctuation.definition.parameters.end.twig
pop: true
- include: twig-constants
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
- include: twig-hashes
twig-filters-warg-ud:
- match: '(?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\''\"]\|)|\{%\sfilter\s)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(\()'
captures:
1: meta.function-call.other.twig
2: punctuation.definition.parameters.begin.twig
push:
- meta_content_scope: meta.function.arguments.twig
- match: \)
captures:
0: punctuation.definition.parameters.end.twig
pop: true
- include: twig-constants
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
- include: twig-hashes
twig-functions:
- match: (?<=is\s)(defined|empty|even|iterable|odd)
captures:
1: support.function.twig
twig-functions-warg:
- match: '(?<=[\s\(\[\{:,])(attribute|block|constant|cycle|date|divisible by|dump|include|max|min|parent|random|range|same as|source|template_from_string)(\()'
captures:
1: support.function.twig
2: punctuation.definition.parameters.begin.twig
push:
- meta_content_scope: meta.function.arguments.twig
- match: \)
captures:
0: punctuation.definition.parameters.end.twig
pop: true
- include: twig-constants
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
twig-hashes:
- match: '(?<=[\s\(\{\[:,])\{'
captures:
0: punctuation.section.hash.begin.twig
push:
- meta_scope: meta.hash.twig
- match: '\}'
captures:
0: punctuation.section.hash.end.twig
pop: true
- include: twig-hashes
- include: twig-arrays
- include: twig-constants
- include: twig-strings
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- match: ":"
scope: punctuation.separator.key-value.twig
- match: ","
scope: punctuation.separator.object.twig
twig-keywords:
- match: (?<=\s)((?:end)?(?:autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)|as|do|else|elseif|extends|flush|from|ignore missing|import|include|only|use|with)(?=\s)
scope: keyword.control.twig
twig-macros:
- match: |-
(?x)
(?<=[\s\(\[\{:,])
([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
(?:
(\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
)?
(\()
captures:
1: meta.function-call.twig
2: punctuation.separator.property.twig
3: variable.other.property.twig
4: punctuation.definition.parameters.begin.twig
push:
- meta_content_scope: meta.function.arguments.twig
- match: \)
captures:
0: punctuation.definition.parameters.end.twig
pop: true
- include: twig-constants
- include: twig-operators
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
- include: twig-hashes
twig-objects:
- match: '(?<=[\s\{\[\(:,])([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(?=[\s\}\[\]\(\)\.\|,:])'
captures:
1: variable.other.twig
twig-operators:
- match: (?<=\s)(\+|-|//?|%|\*\*?)(?=\s)
captures:
1: keyword.operator.arithmetic.twig
- match: (?<=\s)(=|~)(?=\s)
captures:
1: keyword.operator.assignment.twig
- match: (?<=\s)(b-(?:and|or|xor))(?=\s)
captures:
1: keyword.operator.bitwise.twig
- match: '(?<=\s)((?:!|=)=|<=?|>=?|(?:not )?in|is(?: not)?|(?:ends|starts) with|matches)(?=\s)'
captures:
1: keyword.operator.comparison.twig
- match: (?<=\s)(\?|:|and|not|or)(?=\s)
captures:
1: keyword.operator.logical.twig
- match: '(?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]\)''"])\.\.(?=[a-zA-Z0-9_\x{7f}-\x{ff}''"])'
captures:
0: keyword.operator.other.twig
- match: '(?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]\}\)''"])\|(?=[a-zA-Z_\x{7f}-\x{ff}])'
captures:
0: keyword.operator.other.twig
twig-print-tag:
- match: '\{\{-?'
captures:
0: punctuation.section.tag.twig
push:
- meta_scope: meta.tag.template.value.twig
- match: '-?\}\}'
captures:
0: punctuation.section.tag.twig
pop: true
- include: twig-constants
- include: twig-operators
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
- include: twig-hashes
twig-properties:
- match: |-
(?x)
(?<=[a-zA-Z0-9_\x{7f}-\x{ff}])
(\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
(?=[\.\s\|\[\)\]\}:,])
captures:
1: punctuation.separator.property.twig
2: variable.other.property.twig
- match: |-
(?x)
(?<=[a-zA-Z0-9_\x{7f}-\x{ff}])
(\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
(\()
captures:
1: punctuation.separator.property.twig
2: variable.other.property.twig
3: punctuation.definition.parameters.begin.twig
push:
- meta_content_scope: meta.function.arguments.twig
- match: \)
captures:
0: punctuation.definition.parameters.end.twig
pop: true
- include: twig-constants
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-objects
- include: twig-properties
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-strings
- include: twig-arrays
- match: |-
(?x)
(?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]])
(?:
(\[)('[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*')(\])
|(\[)("[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*")(\])
|(\[)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(\])
)
captures:
1: punctuation.section.array.begin.twig
2: variable.other.property.twig
3: punctuation.section.array.end.twig
4: punctuation.section.array.begin.twig
5: variable.other.property.twig
6: punctuation.section.array.end.twig
7: punctuation.section.array.begin.twig
8: variable.other.property.twig
9: punctuation.section.array.end.twig
twig-statement-tag:
- match: '\{%-?'
captures:
0: punctuation.section.tag.twig
push:
- meta_scope: meta.tag.template.block.twig
- match: '-?%\}'
captures:
0: punctuation.section.tag.twig
pop: true
- include: twig-constants
- include: twig-keywords
- include: twig-operators
- include: twig-functions-warg
- include: twig-functions
- include: twig-macros
- include: twig-filters-warg
- include: twig-filters
- include: twig-filters-warg-ud
- include: twig-filters-ud
- include: twig-objects
- include: twig-properties
- include: twig-strings
- include: twig-arrays
- include: twig-hashes
twig-strings:
- match: (?:(?<!\\)|(?<=\\\\))'
captures:
0: punctuation.definition.string.begin.twig
push:
- meta_scope: string.quoted.single.twig
- match: (?:(?<!\\)|(?<=\\\\))'
captures:
0: punctuation.definition.string.end.twig
pop: true
- match: (?:(?<!\\)|(?<=\\\\))"
captures:
0: punctuation.definition.string.begin.twig
push:
- meta_scope: string.quoted.double.twig
- match: (?:(?<!\\)|(?<=\\\\))"
captures:
0: punctuation.definition.string.end.twig
pop: true
+23
View File
@@ -0,0 +1,23 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: hosts
file_extensions:
- hosts
scope: source.hosts
contexts:
main:
- scope: comment.line.number-sign
match: \#.*
comment: comment
- match: ^\s*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-f:]+)
comment: ipaddress
scope: constant.numeric.ipaddress
- match: \s(localhost|ip6-loopback|ip6-localhost|ip6-localnet|ip6-mcastprefix|ip6-allnodes|ip6-allrouters|ip6-allhosts|broadcasthost)\b
scope: keyword.host.predefined}
comment: prefdfined
+3
View File
@@ -12,9 +12,12 @@ file_extensions:
- lng
- cfg
- CFG
- desktop
- url
- URL
- .editorconfig
- .hgrc
- hgrc
scope: source.ini
contexts:
main:
Vendored Submodule
+1
Submodule assets/syntaxes/Jsonnet added at 80775c616e
+44
View File
@@ -0,0 +1,44 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Manpage
file_extensions:
- man
scope: source.man
variables:
section_heading: '^\S.*$'
contexts:
main:
- match: ^
push: first_line
first_line:
- match: '([A-Z0-9]+)(\()([^)]+)(\))'
captures:
1: meta.preprocessor
2: keyword.operator
3: string.quoted.other
4: keyword.operator
- match: '$'
push: body
body:
- match: '^(SYNOPSIS|SYNTAX|SINTASSI|SKŁADNIA|СИНТАКСИС|書式)'
push: Packages/C/C.sublime-syntax
scope: markup.heading
with_prototype:
- match: '(?={{section_heading}})'
pop: true
- match: '^\S.*$'
scope: markup.heading
- match: '\b([a-z0-9_]+)(\()([^)]*)(\))'
captures:
1: entity.name.function
2: keyword.operator
3: constant.numeric
4: keyword.operator
Vendored Submodule
+1
+219
View File
@@ -0,0 +1,219 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: orgmode
file_extensions:
- org
scope: text.orgmode
contexts:
main:
- match: |-
(?x)
^(\*+) # leading stars
\s*([A-Z_]{2,})? # todo keywords
\s*(\[\#[A-Ca-c]\])? # priority
\s*(?=\s+[A-Za-z0-9]+) # expected heading text
comment: Outline headings
captures:
1: punctuation.definition.heading.orgmode
2: keyword.other.todo.orgmode
3: constant.other.priority.orgmode
push:
- meta_scope: markup.heading.orgmode
- meta_content_scope: entity.name.section.orgmode
- match: (?=\s*$\n?)
pop: true
- include: heading-inline
- match: "^-{5,}$"
scope: meta.separator.orgmode
- match: '^\s*([-+]|\s+\*)\s+(.*?)\s+::'
captures:
1: keyword.operator.list.orgmode
2: markup.bold.definition.orgmode
push:
- meta_scope: meta.list.definition.orgmode
- match: $
pop: true
- include: inline
- match: '^\s*?([-+]|\s+\*|\d+[).])'
captures:
1: keyword.operator.list.orgmode
push:
- meta_scope: meta.list.plain.orgmode
- match: $
pop: true
- include: list-inline
- match: (?i)^#\+(BEGIN_(QUOTE|VERSE|CENTER))$
captures:
1: keyword.control.block.orgmode
push:
- meta_scope: markup.quote.orgmode
- match: (?i)^#\+(END_\2)$
captures:
1: keyword.control.block.orgmode
pop: true
- match: "^#[^+].*$"
scope: comment.line.number-sign.orgmode
- match: ^:(PROPERTIES):$
captures:
1: keyword.control.drawer.orgmode
push:
- meta_scope: meta.drawer.properties.orgmode
- match: ^:(END):$
captures:
1: keyword.control.drawer.orgmode
pop: true
- include: properties
- match: ^:(.+):$
captures:
1: keyword.control.drawer.orgmode
push:
- meta_scope: meta.drawer.other.orgmode
- match: ^:(END):$
captures:
1: keyword.control.drawer.orgmode
pop: true
- match: (?i)#\+(BEGIN_LaTeX)$
captures:
1: keyword.control.block.orgmode
push:
- meta_scope: meta.block.latex.orgmode
- match: (?i)#\+(END_LaTeX)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:text.tex.latex
- match: (?i)#\+(BEGIN_HTML)$
captures:
1: keyword.control.block.orgmode
push:
- meta_scope: meta.block.html.orgmode
- match: (?i)#\+(END_HTML)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:text.html.basic
- match: (?i)#\+(BEGIN_SRC)\s+(python)\s*(.*)$
captures:
1: keyword.control.block.orgmode
2: constant.other.language.orgmode
3: string.other.header-args.orgmode
push:
- meta_scope: meta.block.source.python.orgmode
- match: (?i)#\+(END_SRC)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:source.python
- match: (?i)#\+(BEGIN_SRC)\s+(ruby)\s*(.*)$
captures:
1: keyword.control.block.orgmode
2: constant.other.language.orgmode
3: string.other.header-args.orgmode
push:
- meta_scope: meta.block.source.ruby.orgmode
- match: (?i)#\+(END_SRC)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:source.ruby
- match: (?i)#\+(BEGIN_SRC)\s+((?:emacs-)?lisp)\s*(.*)$
captures:
1: keyword.control.block.orgmode
2: constant.other.language.orgmode
3: string.other.header-args.orgmode
push:
- meta_scope: meta.block.source.lisp.orgmode
- match: (?i)#\+(END_SRC)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:source.lisp
- match: (?i)#\+(BEGIN_SRC)\s+(sh)\s*(.*)$
captures:
1: keyword.control.block.orgmode
2: constant.other.language.orgmode
3: string.other.header-args.orgmode
push:
- meta_scope: meta.block.source.shell.orgmode
- match: (?i)#\+(END_SRC)$
captures:
1: keyword.control.block.orgmode
pop: true
- include: scope:source.shell
- match: '(?i)#\+(BEGIN_(SRC|EXAMPLE))(?:\s+([\w-]+)?\s*(.*))?$'
captures:
1: keyword.control.block.orgmode
3: constant.other.language.orgmode
4: string.other.header-args.orgmode
push:
- meta_scope: meta.block.source.other.orgmode
- meta_content_scope: markup.raw.block.orgmode
- match: (?i)#\+(END_\2)$
captures:
1: keyword.control.block.orgmode
pop: true
- match: '#\+(OPTIONS):'
captures:
1: keyword.control.pragma.orgmode
push:
- meta_scope: meta.pragma.options.orgmode
- match: $
pop: true
- match: '([^\s]+):([^\s]+)'
scope: meta.option.orgmode
captures:
1: variable.parameter.option.orgmode
2: string.other.option.orgmode
- match: '#\+(CALL):\s+[A-Za-z-]+(?:\[([^\]]*)\])?\(?'
captures:
1: keyword.control.pragma.orgmode
2: string.other.header-args.orgmode
push:
- meta_scope: meta.pragma.call.orgmode
- match: '\)?([^)]*)$'
captures:
1: string.other.header-args.orgmode
pop: true
- match: (\w+)=
scope: meta.assignment.orgmode
captures:
1: variable.parameter.header-args.orgmode
- match: '^#\+([a-zA-Z_-]+): ?(.*)$'
scope: meta.pragma.orgmode
captures:
1: keyword.control.pragma.orgmode
2: string.unquoted.pragma.orgmode
- include: inline
heading-inline:
- match: ':([^:^\s]*)(?=:)'
scope: meta.keyword.orgmode
captures:
1: string.quoted.keyword.orgmode
- include: inline
inline:
- match: '(?<=^|[.,:;\s])/[^/]+/(?=$|[.,:;\s])'
scope: markup.italic.orgmode
- match: '(?<=^|[.,:;\s])\*[^*]+\*(?=$|[.,:;\s])'
scope: markup.bold.orgmode
- match: '(?<=^|[.,:;\s])_[^_]+_(?=$|[.,:;\s])'
scope: markup.underline.orgmode
- match: '(?<=^|[.,:;\s])([~=]).+?\1(?=$|[.,:;\s])'
scope: markup.raw.inline.orgmode
- match: '\[(?:\[([^\]]*)\])?\[([^\]]*)\]\]'
scope: meta.link.orgmode
captures:
1: markup.underline.link.orgmode
2: string.other.link.orgmode
- match: (?:http|ftp)s?:\/\/\S+
scope: markup.underline.url.orgmode
list-inline:
- match: '\[[ -X]\]'
scope: keyword.operator.checkbox.orgmode
- include: inline
properties:
- match: '^:([A-Za-z_]+):\s(.*)$'
scope: meta.property.orgmode
captures:
1: keyword.control.property.orgmode
2: string.unquoted.propval.orgmode
Vendored Submodule
+1
Vendored Submodule
+1
Submodule assets/syntaxes/Robot added at 8e5a349a3e
+54
View File
@@ -0,0 +1,54 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Robot Framework syntax highlighting.
file_extensions:
- robot
scope: source.robot
contexts:
main:
- match: '\$\{(\d+|\d+\.\d*|0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+)\}'
comment: "Robot Framework numbers, like ${1} or ${12.3}"
scope: constant.numeric.robot
- match: '(?i)(%\{[\w|\s]+\})'
comment: "Robot Framework environment variable, like %{USER}"
scope: variable.parameter.robot
- match: '((?<!\\)|(?<=\\\\))[$&]{'
comment: Robot Framework scalar and dictionary variables
push:
- meta_scope: entity.name.class
- match: '\}'
pop: true
- match: '((?<!\\)(@{)|(?<=\\\\)(@{))'
comment: Robot Framework list variables
push:
- meta_scope: entity.name.class
- match: '(}\[.+])|(})'
pop: true
- match: '(?i)^(\|\s*)?(\*{1,3} ?)(settings?|variables?|keywords?|test cases?)( ?\*{1,3})?(\s*\|)?'
comment: Robot Framework data tables
scope: string.robot.header
- match: '(?i)(^\|\s*)?\[?Documentation\]?\s+'
comment: Test case, keyword and settings table documentation
push:
- meta_scope: comment
- match: ^(?!\s*+\.\.\.)
pop: true
- match: '(^| {2,}|\t|\\| {1,})(?<!\\\\)#'
comment: Comment character
push:
- meta_scope: comment
- match: $
pop: true
- match: '(?i)\s+\[(Tags|Setup|Teardown|Template|Timeout|Arguments|Return)\]'
comment: Tests case and keyword settings
scope: storage.type
- match: (?i)^(\|\s*)?(Library|Resource|Test Timeout|Test Template|Test Teardown|Test Setup|Default Tags|Force Tags|Metadata|Variables|Suite Setup|Suite Teardown)(?:( )|( \| ))
comment: Settings table settings, like Library
scope: constant.language
- match: '^(\|\s+)?(?!^\.{3})(?![\|$&])\S+'
comment: Keywords and test cases
push:
- meta_scope: keyword.control.robot
- match: '($|\||\s{2,})'
pop: true
Vendored Submodule
+1
Vendored Submodule
+1
Submodule assets/syntaxes/Strace added at 3ec51e0bca
Vendored Submodule
+1
Submodule assets/syntaxes/Syslog added at 7628d4e0b8
Vendored Submodule
+1
Vendored Submodule
+1
Submodule assets/syntaxes/Verilog added at 532e87c1b4
+149
View File
@@ -0,0 +1,149 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Verilog
file_extensions:
- v
- V
scope: source.verilog
contexts:
main:
- match: '^\s*(module|function|primitive)\s+\b([a-zA-Z_][a-zA-Z0-9_]*)\b'
scope: meta.entity.module.verilog
captures:
1: storage.type.verilog
2: entity.name.type.class.verilog
- match: '^\s*(?!else)(?!begin)([a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*(\()'
scope: meta.definition.verilog
captures:
1: entity.name.type.class.verilog
2: entity.name.type.instance.verilog
3: keyword.operator.parenthesis.round.verilog
- match: '^\s*(?!else)(?!begin)([a-zA-Z_][a-zA-Z0-9_]*)\s+([#])(\()([ ._+`,a-zA-Z0-9]+)(\))\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*(\()'
scope: meta.definition.withparameter.verilog
captures:
1: entity.name.type.class.verilog
2: keyword.other.verilog
3: keyword.operator.parenthesis.round.verilog
4: keyword.other.verilog
5: keyword.operator.parenthesis.round.verilog
6: entity.name.type.instance.verilog
7: keyword.operator.parenthesis.round.verilog
- match: '^\s*\b(?!else)(?!begin)([a-zA-Z_][a-zA-Z0-9_]*)\b\s+([#])'
scope: meta.definition.withparameter.verilog
captures:
1: entity.name.type.class.verilog
2: keyword.other.verilog
- match: '^\s*(defparam)\s+([a-zA-Z_][a-zA-Z0-9_]*)(.[a-zA-Z_][a-zA-Z0-9_]*)\s*(=)'
scope: meta.definition.defparam.verilog
captures:
1: keyword.other.verilog
2: entity.name.type.instance.verilog
3: meta.module.parameters.verilog
4: keyword.other.verilog
- match: \b(automatic|cell|config|deassign|defparam|design|disable|edge|endconfig|endgenerate|endspecify|endtable|endtask|event|generate|genvar|ifnone|incdir|include|instance|liblist|library|localparam|macromodule|negedge|noshowcancelled|posedge|pulsestyle_onevent|pulsestyle_ondetect|real|realtime|scalared|showcancelled|specify|specparam|table|task|time|use|vectored)\b
scope: keyword.other.verilog
- match: "(#[0-9]+)"
scope: keyword.delay.verilog
- match: \b(initial|always|wait|force|release|assign)\b
scope: keyword.control.verilog
- match: \b(begin|end|fork|join)\b
scope: keyword.other.verilog
- match: \b(forever|repeat|while|for|if|else|case|casex|casez|default|endcase)\b
scope: keyword.control.verilog
- match: '^\s*(`include)\s+(["<].*[">])'
scope: meta.include.verilog
captures:
1: meta.preprocessor.verilog
2: entity.name.type.include.verilog
- match: '^\s*(`ifdef|`ifndef|`undef|`define)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b'
scope: meta.preprocessor.ifdef.verilog
captures:
1: meta.preprocessor.verilog
2: constant.other.define.verilog
- match: '`(celldefine|default_nettype|define|else|elsif|endcelldefine|endif|ifdef|ifndef|include|line|nounconnected_drive|resetall|timescale|unconnected_drive|undef)\b'
scope: meta.preprocessor.verilog
- match: "[.][_a-zA-Z0-9]+"
scope: meta.module.parameters.verilog
- match: '`\b([a-zA-Z_][a-zA-Z0-9_]*)\b'
scope: constant.other.define.verilog
- include: comments
- match: \b(endmodule|endfunction|endprimitive)\b
scope: storage.type.verilog
- match: '^\s*\b([a-zA-Z_][a-zA-Z0-9_]*)\b\s*(:)\s*'
scope: meta.case.verilog
captures:
1: entity.name.state.verilog
2: keyword.operator.bitwise.verilog
- include: all-types
- match: (==|===|!=|!==|<=|>=|<|>)
scope: keyword.operator.comparison.verilog
- match: (\-|\+|\*|\/|%)
scope: keyword.operator.arithmetic.verilog
- match: (!|&&|\|\|)
scope: keyword.operator.logical.verilog
- match: (&|\||\^|~|<<|>>|\?|:)
scope: keyword.operator.bitwise.verilog
- match: "({|})"
scope: keyword.operator.parenthesis.curly.verilog
- match: (\(|\))
scope: keyword.operator.parenthesis.round.verilog
- match: '(\[|\])'
scope: keyword.operator.parenthesis.square.verilog
- match: "([;,])"
scope: keyword.delimiter.verilog
- match: (#|@|=)
scope: keyword.other.verilog
- match: '\b(output|input|inout|and|nand|nor|or|xor|xnor|buf|not|bufif[01]|notif[01]|r?[npc]mos|tran|r?tranif[01]|pullup|pulldown)\b'
scope: support.type.verilog
- match: '((\b\d+)?''s?([bB]\s*(([0-1_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[oO]\s*(([0-7_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[dD]\s*(([0-9_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[hH]\s*(([0-9a-fA-F_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*)))((e|E)(\+|-)?[0-9]+)?\b)|(\b\d+\b)'
scope: constant.numeric.verilog
- include: strings
- match: '\$\b([a-zA-Z_][a-zA-Z0-9_]*)\b'
scope: support.function.verilog
all-types:
- include: storage-type-verilog
- include: storage-modifier-verilog
comments:
- match: /\*
captures:
0: punctuation.definition.comment.verilog
push:
- meta_scope: comment.block.verilog
- match: \*/
captures:
0: punctuation.definition.comment.verilog
pop: true
- match: (//).*$\n?
scope: comment.line.double-slash.verilog
captures:
1: punctuation.definition.comment.verilog
storage-modifier-verilog:
- match: '\b(signed|unsigned|small|medium|large|supply[01]|strong[01]|pull[01]|weak[01]|highz[01])\b'
scope: storage.modifier.verilog
storage-type-verilog:
- match: '\b(wire|tri|tri[01]|supply[01]|wand|triand|wor|trior|trireg|reg|parameter|integer)\b'
scope: storage.type.verilog
strings:
- match: '"'
captures:
0: punctuation.definition.string.begin.verilog
push:
- meta_scope: string.quoted.double.verilog
- match: '"'
captures:
0: punctuation.definition.string.end.verilog
pop: true
- match: \\.
scope: constant.character.escape.verilog
- match: "'"
captures:
0: punctuation.definition.string.begin.verilog
push:
- meta_scope: string.quoted.single.verilog
- match: "'"
captures:
0: punctuation.definition.string.end.verilog
pop: true
- match: \\.
scope: constant.character.escape.verilog
+1 -1
View File
@@ -63,7 +63,7 @@ contexts:
- match: \b(if|while|for|try|return|throw|end(if|for|while|try)?|au(g|group)|else(if|)?|do|in|catch|finally|:)\b
scope: keyword.control.viml
number_hex:
- match: "#[0-9a-f]{6}"
- match: "0x[0-9a-f]+"
scope: constant.numeric.hex
number_int:
- match: '-?\d+'
File diff suppressed because it is too large Load Diff
Vendored Submodule
+1
Submodule assets/syntaxes/hosts added at 21250a7117
+19
View File
@@ -0,0 +1,19 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: requirements.txt
file_extensions:
- requirements.txt
scope: source.requirementstxt
contexts:
main:
- match: (#).*$\n?
scope: comment.line.requirementstxt
captures:
1: punctuation.definition.comment.requirementstxt
- match: '(?i)^[a-z0-9_\-\.]+'
scope: string.package_name.requirementstxt
- match: (?i)==|<|<=|>=|>
scope: keyword.operator.logical.punctuation.requirementstxt
- match: '(?i)\d+\.[\da-z\-_\.]*'
scope: constant.numeric.verions.requirementstxt
+31
View File
@@ -0,0 +1,31 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Highlight non-printables
file_extensions:
- show-nonprintable
scope: whitespace
contexts:
main:
- match: "•"
scope: support.function.show-nonprintable.space
- match: "├─*┤"
scope: constant.character.escape.show-nonprintable.tab
- match: "↹"
scope: constant.character.escape.show-nonprintable.tab
- match: "␊"
scope: keyword.operator.show-nonprintable.line-feed
- match: "␍"
scope: string.show-nonprintable.carriage-return
- match: "␀"
scope: entity.other.attribute-name.show-nonprintable.null
- match: "␇"
scope: entity.other.attribute-name.show-nonprintable.bell
- match: "␛"
scope: entity.other.attribute-name.show-nonprintable.escape
- match: "␈"
scope: entity.other.attribute-name.show-nonprintable.backspace
- match: "\\\\x[A-Z0-9][A-Z0-9]"
scope: comment.block.show-nonprintable.backspace
- match: "\\\\u\\{[a-z0-9]+\\}"
scope: comment.block.show-nonprintable.backspace
Vendored Submodule
+1
Vendored Submodule
+1
Submodule assets/syntaxes/varlink added at 04f30d4b83
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>
+31
View File
@@ -0,0 +1,31 @@
// TODO: Re-enable generation of shell completion files (below) when clap 3 is out.
// For more details, see https://github.com/sharkdp/bat/issues/372
fn main() {}
// #[macro_use]
// extern crate clap;
// use clap::Shell;
// use std::fs;
// include!("src/clap_app.rs");
// const BIN_NAME: &str = "bat";
// fn main() {
// let outdir = std::env::var_os("SHELL_COMPLETIONS_DIR").or(std::env::var_os("OUT_DIR"));
// let outdir = match outdir {
// None => return,
// Some(outdir) => outdir,
// };
// fs::create_dir_all(&outdir).unwrap();
// let mut app = build_app(true);
// app.gen_completions(BIN_NAME, Shell::Bash, &outdir);
// app.gen_completions(BIN_NAME, Shell::Fish, &outdir);
// app.gen_completions(BIN_NAME, Shell::Zsh, &outdir);
// app.gen_completions(BIN_NAME, Shell::PowerShell, &outdir);
// }
+1
View File
@@ -0,0 +1 @@
* linguist-vendored
+54
View File
@@ -27,6 +27,7 @@ pack() {
# create a "staging" directory
mkdir "$tempdir/$package_name"
mkdir "$tempdir/$package_name/autocomplete"
# copying the main binary
cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/"
@@ -38,6 +39,13 @@ pack() {
cp LICENSE-MIT "$tempdir/$package_name"
cp LICENSE-APACHE "$tempdir/$package_name"
# various autocomplete
# 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".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"
# archiving
pushd "$tempdir"
tar czf "$out_dir/$package_name.tar.gz" "$package_name"/*
@@ -52,6 +60,11 @@ make_deb() {
local dpkgname
local conflictname
local gcc_prefix
local homepage
local maintainer
homepage="https://github.com/sharkdp/bat"
maintainer="David Peter <mail@david-peter.de>"
case $TARGET in
x86_64*)
@@ -94,10 +107,51 @@ make_deb() {
install -Dm644 "doc/$PROJECT_NAME.1" "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
gzip --best "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
# completions
install -Dm644 assets/completions/bat.fish "$tempdir/usr/share/fish/completions/$PROJECT_NAME.fish"
# readme and license
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-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
mkdir "$tempdir/DEBIAN"
+2
View File
@@ -11,6 +11,8 @@ Set-Location $STAGE
$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"
Copy-Item "$SRC_DIR\target\release\bat.exe" '.\'
# TODO: disabled for now, see issue #372
# Copy-Item $SRC_DIR\target\release\build\bat-*\out\_bat.ps1 '.\'
# readme and license
Copy-Item $SRC_DIR\README.md '.\'
+2 -1
View File
@@ -33,5 +33,6 @@ if [[ $TARGET == aarch64-unknown-linux-gnu ]]; then
sudo apt-get install -y \
gcc-4.8-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
gcc-aarch64-linux-gnu
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross
fi
+455
View File
@@ -0,0 +1,455 @@
<p align="center">
<img src="logo-header.svg" alt="bat - a cat clone with wings"><br>
<a href="https://travis-ci.org/sharkdp/bat"><img src="https://travis-ci.org/sharkdp/bat.svg?branch=master" alt="Build Status"></a>
<a href="https://ci.appveyor.com/project/sharkdp/bat"><img src="https://ci.appveyor.com/api/projects/status/cptsmtbiwbnr2vhf?svg=true"></a>
<img src="https://img.shields.io/crates/l/bat.svg" alt="license">
<a href="https://crates.io/crates/bat"><img src="https://img.shields.io/crates/v/bat.svg?colorB=319e8c" alt="Version info"></a><br>
A <i>cat(1)</i> clone with syntax highlighting and Git integration.
</p>
<p align="center">
<a href="#syntax-highlighting">特徴</a> •
<a href="#how-to-use">使い方</a> •
<a href="#installation">インストール</a> •
<a href="#customization">カスタマイズ</a> •
<a href="#project-goals-and-alternatives">プロジェクトの目標と既存の類似したOSS</a> •
翻訳 [<a href="https://github.com/chinanf-boy/bat-zh">中文</a>][<a href="README-ja">日本文</a>]
</p>
### シンタックスハイライト
`bat` は多くのプログラミング言語やマークアップ言語のシンタックスハイライトに対応しています。
![Syntax highlighting example](https://imgur.com/rGsdnDe.png)
### Gitの統合
`bat``git` とも連携しており、差分を表現する記号が表示されます(図の左端):
![Git integration example](https://i.imgur.com/2lSW4RE.png)
### 空白文字の可視化
`-A`/`--show-all` オプションをつけることで、空白文字を可視化できます:
![Non-printable character example](https://i.imgur.com/WndGp9H.png)
### 自動呼び出し
出力が1つの画面に対して大きすぎる場合、`bat` は自身の出力を `less` にパイプで繋げることが可能です。
### ファイルの連結
あなたはさらにファイルを連結させるに使うことも可能です:wink:。
`bat` は非対話型のターミナルを検出すると、いつでも `cat` の完全互換として振る舞い、
プレーンなファイルを表示します。
## 使い方
単一のファイルを表示させたい
```bash
> bat README.md
```
複数のファイルを一度に表示させたい場合
```bash
> bat src/*.rs
```
標準入力から自動的に構文を決定させたい場合
```bash
> curl -s https://sh.rustup.rs | bat
```
Read from stdin, specify the language explicitly
標準入力から明示的に言語を指定したい場合
```bash
> yaml2json .travis.yml | json_pp | bat -l json
```
空白文字を可視化させたい場合:
```bash
> bat -A /etc/hosts
```
`cat` の代わりに `bat` を使用する際の例:
```bash
bat > note.md # quickly create a new file
bat header.md content.md footer.md > document.md
bat -n main.rs # show line numbers (only)
bat f - g # output 'f', then stdin, then 'g'.
```
## インストール
### Ubuntu
*... や他のDebianベースのLinuxディストリビューション*
最新の `.deb` パッケージを[こちら](https://github.com/sharkdp/bat/releases)からダウンロードして、インストールしてください:
``` bash
sudo dpkg -i bat_0.12.0_amd64.deb # adapt version number and architecture
```
### Arch Linux
[Arch Linuxの公式リソース](https://www.archlinux.org/packages/community/x86_64/bat/)からインストールできます。
```bash
pacman -S bat
```
### Void Linux
xbps-ininstall経由で `bat` をインストールできます。
```
xbps-install -S bat
```
### Fedora
[Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/)経由で `bat` をインストールできます。これはFedora 29以上ではデフォルトで有効化されています。 もしそうでなければ、 `dnf install fedora-repos-modular` を実行してセットアップし、 `fedora-modular` と `fedora-updates-modular` が `/etc/yum.repos.d` で有効化されていることを確認してください。
```bash
dnf module install bat
```
### Gentoo Linux
[Gentoo Linuxの公式リソース](https://packages.gentoo.org/packages/sys-apps/bat)からインストールできます。
```bash
emerge sys-apps/bat
```
### FreeBSD
事前にコンパイル済みである[pkg](https://www.freshports.org/textproc/bat)をインストールできます:
```bash
pkg install bat
```
または、FreeBSDのportsから自身でビルドすることも可能です:
```bash
cd /usr/ports/textproc/bat
make install
```
### nix
`bat` を[nix package manager](https://nixos.org/nix)経由でインストールすることができます:
```bash
nix-env -i bat
```
### openSUSE
You can install `bat` with zypper:
`bat` をzypperでインストールすることができます:
```
zypper install bat
```
### macOS
[Homebrew](http://braumeister.org/formula/bat)でインストールすることができます:
```bash
brew install bat
```
### Windows
You can download prebuilt binaries from the [Release page],
or install it with :
事前にビルド済みのバイナリを[リリースページ](https://github.com/sharkdp/bat/releases)からダウンロードすることができます。または、[scoop](https://scoop.sh/)でインストールすることも可能です。
```bash
scoop install bat
```
[See below](#using-bat-on-windows) for notes.
### Docker
コンテナ内で`bat` を使いたい方のために[Docker image](https://hub.docker.com/r/danlynn/bat/)が用意されています。
```bash
docker pull danlynn/bat
alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat'
```
### Ansible
[Ansible](https://www.ansible.com/)でインストールすることができます:
```bash
# Install role on local machine
ansible-galaxy install aeimer.install_bat
```
```yaml
---
# Playbook to install bat
- host: all
roles:
- aeimer.install_bat
```
- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat)
- [GitHub](https://github.com/aeimer/ansible-install-bat)
これは以下のディストリビューションで動作するはずです:
- Debian/Ubuntu
- ARM (eg. Raspberry PI)
- Arch Linux
- Void Linux
- FreeBSD
- MacOS
### From binaries
多くの異なるアーキテクチャのためのプレビルドバージョンを[リリースページ](https://github.com/sharkdp/bat/releases)からチェックしてみてください。静的にリンクされている多くのバイナリも利用できます: ファイル名に `musl` を含むアーカイブを探します。
### From source
`bat` をソースからビルドしたいならば、Rust 1.29 以上の環境が必要です。そして、 `cargo` をビルドに対して使用します:
```bash
cargo install bat
```
`cmake` と `libz` 開発パッケージ(`libz-dev` または `libz-devel`)が正しくビルドをするためにインストールする必要があるかもしれません。
## カスタマイズ
### ハイライト テーマ
`bat --list-themes` を使うと現在利用可能なシンタックスハイライトのテーマを入手できます。 `TwoDark` テーマを選ぶためには `--theme=TwoDark` オプションをつけるか `BAT_THEME` という環境変数に `TwoDark` を代入する必要があります。 シェルの起動ファイルに `export BAT_THEME="TwoDark"` と定義すればその設定が変わることはないでしょう。あるいは、 `bat` の[設定ファイル](https://github.com/sharkdp/bat#configuration-file)を利用してください。
もし、ファイルにより異なるテーマを利用したい場合は、以下の[`fzf`](https://github.com/junegunn/fzf)を利用した以下のコマンドを使うことができます:
``` bash
bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
```
`bat` はデフォルトだと黒い背景色のターミナルに適しています。しかし、`GitHub` や `OneHalfLight` のような白い背景色のテーマでもいい感じにすることができます。
以下のカスタムテーマを参考にしてみてください。
['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes)
### 出力のスタイル
`--style` を使うことで `bat` の表示の見た目を変更することができます。例えば、 `--style=numbers,changes` と入力します。すると、Gitの差分と行番号だけが表示され、グリッド線とファイルヘッダーは表示されません。
環境変数に `BAT_STYLE` を定義するとこれらの設定を永続的に使用することができます。
[設定ファイル](https://github.com/sharkdp/bat#configuration-file)を参考にしても良いでしょう。
### 新しい構文の追加 / 言語の定義
`bat` はシンタックスハイライトのための[`syntext`](https://github.com/trishume/syntect/)という最高にイケてるライブラリを使用しています。`syntect` はSublime Textのために作られた[`.sublime-syntax` file](https://www.sublimetext.com/docs/3/syntax.html)テーマです。新しい構文を定義するために以下の手順を行います。
構文定義ファイルを入れておくためのフォルダを作る:
```bash
mkdir -p "$(bat --config-dir)/syntaxes"
cd "$(bat --config-dir)/syntaxes"
# Put new '.sublime-syntax' language definition files
# in this folder (or its subdirectories), for example:
git clone https://github.com/tellnobody1/sublime-purescript-syntax
```
次のコマンドを使用して、これらのファイルをバイナリキャッシュに解析します:
```bash
bat cache --build
```
最後に `bat --list-languages` と入力すると新しい言語が利用可能かどうかチェックします。
デフォルトの設定に戻したいときは以下のコマンドを実行します:
```bash
bat cache --clear
```
### 新しいテーマの追加
これは構文を新しく定義するやり方と非常に似ています。
まず、新しいシンタックスハイライトのテーマのフォルダを作ります:
```bash
mkdir -p "$(bat --config-dir)/themes"
cd "$(bat --config-dir)/themes"
# Download a theme in '.tmTheme' format, for example:
git clone https://github.com/greggb/sublime-snazzy
# Update the binary cache
bat cache --build
```
最後に、 `bat --list-themes` で新しいテーマが利用可能がチェックします
### 異なるページャーの使用
`bat` は環境変数 `PAGER` に使用するページャーを明記します。
この環境変数が定義されていない場合、デフォルトで `less` が使用されます。もし、異なるページャーが使用したい場合は、`PAGER` を修正してください。または、`PAGER` を上書きする環境変数として `BAT_PAGER` を定義することも可能です。
もし、ページャーにコマンドライン引数を渡したい場合は、 `PAGER`/`BAT_PAGER` 環境変数を定義してください:
```bash
export BAT_PAGER="less -RF"
```
環境変数を利用する代わりに、 `bat` の[設定ファイル](https://github.com/sharkdp/bat#configuration-file)の `--pager` オプションを使用することも可能です。
**注意**: デフォルトにより、ページャーが `less` にセットされているならば `bat` は以下のコマンドラインを受け付けるでしょう。
ページャーのオプション: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` , `-X`/`--no-init`
最初の `-R` はANSIカラーを正しく解釈するために必要です。2番目の `-F` は出力サイズがターミナルの縦のサイズよりも小さいならば `less` に即座に終了するように命令します。したがって、少量のファイルのためにページャーを終了する `q` を押す必要がありません。3番目のオプションの `-X` は `less` の古いバージョンの機能である `--quit-if-one-screen` でバグを修正するために必要です。運の悪いことに、これは `less` のマウス-ホイールのサポートを無効にします。もし、マウス-ホイール スクローリングを有効にしたいなら、`-R` だけをオプションとしてつけてください(ただし、これは `--quit-if-one-screen` を無効にするでしょう)。または、 `less` の最近バージョンを利用し、 `-RF` をつけてください。 これは望ましいことに `--quit-if-one-screen` と マウス-ホイールスクローリングの両方を有効にするでしょう。
スクロールが未だ動作しないのであれば、加えて `-S` オプションを追加してみてください。
## 設定ファイル
`bat` は設定ファイルでカスタマイズすることが可能です。ファイルの場所はOSに依存します。使用しているOSのデフォルトパスを調べるには以下のコマンドを実行してください:
```
bat --config-file
```
また、環境変数 `BAT_CONFIG_PATH` に設定ファイルの場所を明記することもできます:
```bash
export BAT_CONFIG_PATH="/path/to/bat.conf"
```
### フォーマット
この設定ファイルはコマンドライン引数の単純なリストです。 `bat --help` を利用すると、利用可能なオプションとその値を閲覧することができます。さらに、`#` でコメント文を加えることができます。
設定ファイルの例:
```bash
# Set the theme to "TwoDark"
--theme="TwoDark"
# Show line numbers, Git modifications and file header (but no grid)
--style="numbers,changes,header"
# Use italic text on the terminal (not supported on all terminals)
--italic-text=always
# Add mouse scrolling support in less (does not work with older
# versions of "less")
--pager="less -FR"
# Use C++ syntax (instead of C) for .h header files
--map-syntax h:cpp
# Use "gitignore" highlighting for ".ignore" files
--map-syntax .ignore:.gitignore
```
## Windows での `bat` の利用
Windows 上で `bat` はほとんど動作しますが、いくつかの機能は設定を必要をする場合があります。
### ページング
Windows only includes a very limited pager in the form of `more`. You can download a Windows binary
for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through
Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in
your `PATH` or [define an environment variable](#using-a-different-pager).
### 色
Windows 10 は[v1151](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update))からbashの新しいバージョンと同様に `conhost.exe`(コマンドプロンプト)と PowerShell の色をネイティブサポートしていません。Windows の新しいバージョンでは、[Cmder](http://cmder.net/)を使うことができます。これは[ConEmu](https://conemu.github.io/)を含んでいます。
**注意:** Git と MSYS の `less` はWindows上で色を正しく解釈しません。もし、あなたが他のページャーをインストールしていないのであれば、 `--paging=never` オプションを付け加えるまたは `BAT_PAGER` に空文字を設定することでページングを完全に無効にできます。
### Cygwin
Windows上の `bat` は Cygwin のunix風のpath(`/cygdrive/*`)をネイティブサポートしていません。
絶対的なcygwinパスを引数として受けたときに、 `bat` は以下のエラーを返すでしょう: `The system cannot find the path specified. (os error 3)`
wrapperを作成するまたは以下の関数を `.bash_profile` に追記することでこの問題を解決することができます:
```shell
bat() {
local index
local args=("$@")
for index in $(seq 0 ${#args[@]}) ; do
case "${args[index]}" in
-*) continue;;
*) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";;
esac
done
command bat "${args[@]}"
}
```
## トラブルシューティング
### ターミナルと色
`bat` はターミナルがトゥルーカラーをサポートしている/していない関係なくサポートします。しかし、シンタックスハイライトのテーマの色が8-bitカラーに最適化されていない場合、24-bitであるトゥルーカラーをサポートしているターミナルを使用することを強く推奨します(`terminator`, `konsole`, `iTerm2`, ...)。
この[記事](https://gist.github.com/XVilka/8346728)には24-bitカラーがサポートされているターミナルの一覧が掲載されています。
本当の色をターミナルにセットするために、環境変数 `COLORTERM` に `truecolor` か `24bit` のどちらかを代入してください。さもなければ、 `bat` はどの色を使うのか決定することができません。または、24-bit エスケープシーケンスがサポートされません(そして、8-bit colorに戻ります)。
### 行番号とグリッド線がほとんど見えない
異なるテーマを試してみてください(`bat --list-themes` でテーマを閲覧できます)。 `OneHalfDark` と `OneHalfLight` テーマはグリッド線と線の色を明るくします。
## 開発
```bash
# Recursive clone to retrieve all submodules
git clone --recursive https://github.com/sharkdp/bat
# Build (debug version)
cd bat
cargo build
# Run unit tests and integration tests
cargo test
# Install (release version)
cargo install
# Build a bat binary with modified syntaxes and themes
bash assets/create.sh
cargo install -f
```
## プロジェクトの目標と既存の類似したOSS
`bat` は以下の目標を達成しようと試みています:
- 美しい高度なシンタックスハイライトの提供
- ファイルの差分を表示するためのGitとの連携
- (POSIX) `cat` との完全互換
- ユーザーフレンドリーがコマンドラインインターフェースの提供
既存の類似したOSSはたくさんあります。
`bat` とこれらを比較した表が[こちら](alternatives.md)にあります。
+2 -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: |
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: |
| Languages (circa) | 100 | 300 | 200 | 7 | 80 | 130 | 30 | 130 |
| 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: |
| 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 |
@@ -21,3 +21,4 @@ request.
Some other alternatives that are also related, but not yet included in the table:
- [lesspipe](https://github.com/wofr06/lesspipe)
- [vimpager](https://github.com/rkitover/vimpager)
+77 -35
View File
@@ -10,22 +10,35 @@ bat [OPTIONS] [FILE]...
bat <SUBCOMMAND>
.SH "OPTIONS"
.HP
General remarks
.IP
Command-line options like '-l'/'--language' that take values can be specified as
either '--language value', '--language=value', '-l value' or '-lvalue'.
.HP
\fB\-l\fR, \fB\-\-language\fR <language>
.IP
Explicitly set the language for syntax highlighting. The language can be
specified as a name (like 'C++' or 'LaTeX') or possible file extension (like
\&'cpp', 'hpp' or 'md'). Use '\-\-list\-languages' to show all supported language
names and file extensions.
specified as a name (like 'C++' or 'LaTeX') or possible file extension
(like 'cpp', 'hpp' or 'md'). Use '\-\-list\-languages' to show all supported
language names and file extensions.
.HP
\fB\-\-list\-languages\fR
\fB\-L\fR, \fB\-\-list\-languages\fR
.IP
Display a list of supported languages for syntax highlighting.
.HP
\fB\-m\fR, \fB\-\-map\-syntax\fR <from:to>...
.IP
Map a file extension or file name to an existing syntax. For example, to
highlight *.conf files with the INI syntax, use '\-m conf:ini'. To
highlight files named '.myignore' with the Git Ignore syntax, use '\-m
\&.myignore:gitignore'.
.HP
\fB\-\-theme\fR <theme>
.IP
Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all
available themes. To set a default theme, export the BAT_THEME environment
variable (e.g.: export BAT_THEME="TwoDark").
available themes. To set a default theme, add the '\-\-theme="..."' option
to the configuration file or export the BAT_THEME environment variable
(e.g.: export BAT_THEME="...").
.HP
\fB\-\-list\-themes\fR
.IP
@@ -34,23 +47,30 @@ Display a list of supported themes for syntax highlighting.
\fB\-\-style\fR <style\-components>
.IP
Configure which elements (line numbers, file headers, grid borders, Git
modifications, ..) to display in addition to the file contents. The argument
is a comma\-separated list of components to display (e.g.
modifications, ..) to display in addition to the file contents. The
argument is a comma\-separated list of components to display (e.g.
\&'numbers,changes,grid') or a pre\-defined style ('full'). To set a default
theme, export the BAT_STYLE environment variable (e.g.: export
BAT_STYLE="numbers"). [possible values: auto, full, plain, changes, header,
grid, numbers]
style, add the '\-\-style=".."' option to the configuration file or export
the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible
values: *auto*, full, plain, changes, header, grid, numbers, snip.
.HP
\fB\-p\fR
\fB\-p\fR, \fB\-\-plain\fR
.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
\fB\-n\fR, \fB\-\-number\fR
.IP
Only show line numbers, no other decorations. This is an alias for
\&'\-\-style=numbers'
.HP
\fB\-\-line\-range\fR <N:M>
\fB\-A\fR, \fB\-\-show\-all\fR
.IP
Show non\-printable characters like space, tab or newline. Use '\-\-tabs' to
control the width of the tab\-placeholders.
.HP
\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
.IP
Only print the specified range of lines for each file. For example:
.RS
@@ -62,40 +82,63 @@ prints lines 1 to 40
prints lines 40 to the end of the file
.RE
.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>
.IP
Specify when to use colored output. The automatic mode only enables colors if
an interactive terminal is detected. [default: auto] [possible values: auto,
never, always]
Specify when to use colored output. The automatic mode only enables colors
if an interactive terminal is detected. Possible values: *auto*, never,
always.
.HP
\fB\-\-italic\-text\fR <when>
.IP
Specify when to use ANSI sequences for italic text in the output. Possible
values: always, *never*.
.HP
\fB\-\-decorations\fR <when>
.IP
Specify when to use the decorations that have been specified via '\-\-style'.
The automatic mode only enables decorations if an interactive terminal is
detected. [default: auto] [possible values: auto, never, always]
Specify when to use the decorations that have been specified via
\&'\-\-style'. The automatic mode only enables decorations if an interactive
terminal is detected. Possible values: *auto*, never, always.
.HP
\fB\-\-paging\fR <when>
.IP
Specify when to use the pager. To control which pager is used, set the PAGER
or BAT_PAGER environment variables (the latter takes precedence). The default
pager is 'less'. To disable the pager permanently, set BAT_PAGER to an empty
string. [default: auto] [possible values: auto, never, always]
Specify when to use the pager. To control which pager is used, set the
PAGER or BAT_PAGER environment variables (the latter takes precedence) or
use the '\-\-pager' option. To disable the pager permanently, set BAT_PAGER
to an empty string or set '\-\-paging=never' in the configuration file.
Possible values: *auto*, never, always.
.HP
\fB\-\-pager\fR <command>
.IP
Determine which pager is used. This option will overwrite the PAGER and
BAT_PAGER environment variables. The default pager is 'less'. To disable
the pager completely, use the '\-\-paging' option. Example: '\-\-pager "less
\fB\-RF\fR"'.
.HP
\fB\-\-wrap\fR <mode>
.TP
Specify the text\-wrapping mode. [default: auto]
[possible values: auto,
.IP
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
\fB\-u\fR
\fB\-\-tabs\fR <T>
.IP
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered'). The
output is always unbuffered \- this option is simply ignored.
Set the tab width to T spaces. Use a width of 0 to pass tabs through
directly
.HP
\fB\-\-tabs\fR <tabs>
\fB\-u\fR, \fB\-\-unbuffered\fR
.IP
Sets the tab width. Use a width of 0 to pass tabs through directly
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered').
The output is always unbuffered \- this option is simply ignored.
.HP
\fB\-\-terminal\-width\fR <width>
.IP
Explicitly set the width of the terminal instead of determining it
automatically. If prefixed with '+' or '\-', the value will be treated as
an offset to the actual terminal width. See also: '\-\-wrap'.
.HP
\fB\-h\fR, \fB\-\-help\fR
.IP
@@ -113,5 +156,4 @@ from standard input.
.SH "SUBCOMMANDS"
.IP
cache
.IP
Modify the syntax\-definition and theme cache. See "bat cache --help" for more information
Modify the syntax\-definition and theme cache
+151 -304
View File
@@ -1,21 +1,26 @@
use std::collections::HashSet;
use std::env;
use std::path::Path;
use std::str::FromStr;
use atty::{self, Stream};
use clap::{App as ClapApp, AppSettings, Arg, ArgGroup, ArgMatches, SubCommand};
use crate::clap_app;
use clap::ArgMatches;
use wild;
use console::Term;
#[cfg(windows)]
use ansi_term;
use assets::BAT_THEME_DEFAULT;
use errors::*;
use line_range::LineRange;
use style::{OutputComponent, OutputComponents, OutputWrap};
use crate::assets::BAT_THEME_DEFAULT;
use crate::config::{get_args_from_config_file, get_args_from_env_var};
use crate::errors::*;
use crate::inputfile::InputFile;
use crate::line_range::{LineRange, LineRanges};
use crate::style::{OutputComponent, OutputComponents, OutputWrap};
use crate::syntax_mapping::SyntaxMapping;
use crate::util::transpose;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PagingMode {
@@ -24,13 +29,6 @@ pub enum PagingMode {
Never,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum InputFile<'a> {
StdIn,
Ordinary(&'a str),
ThemePreviewFile,
}
#[derive(Clone)]
pub struct Config<'a> {
/// List of files to print
@@ -39,6 +37,9 @@ pub struct Config<'a> {
/// The explicitly configured language, if any
pub language: Option<&'a str>,
/// Whether or not to show/replace non-printable characters like space, tab and newline.
pub show_nonprintable: bool,
/// The character width of the terminal
pub term_width: usize,
@@ -64,11 +65,23 @@ pub struct Config<'a> {
/// Pager or STDOUT
pub paging_mode: PagingMode,
/// The range lines that should be printed, if specified
pub line_range: Option<LineRange>,
/// Specifies the lines that should be printed
pub line_ranges: LineRanges,
/// The syntax highlighting theme
pub theme: String,
/// File extension/name mappings
pub syntax_mapping: SyntaxMapping,
/// Command to start the pager
pub pager: Option<&'a str>,
/// Whether or not to use ANSI italics
pub use_italic_text: bool,
/// Lines to highlight
pub highlight_lines: Vec<usize>,
}
fn is_truecolor_terminal() -> bool {
@@ -77,284 +90,49 @@ fn is_truecolor_terminal() -> bool {
.unwrap_or(false)
}
/// Helper function that should might appear in Rust stable at some point
/// (https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose)
fn transpose<T>(opt: Option<Result<T>>) -> Result<Option<T>> {
opt.map_or(Ok(None), |res| res.map(Some))
}
pub struct App {
pub matches: ArgMatches<'static>,
interactive_output: bool,
}
impl App {
pub fn new() -> Self {
pub fn new() -> Result<Self> {
#[cfg(windows)]
let _ = ansi_term::enable_ansi_support();
let interactive_output = atty::is(Stream::Stdout);
App {
matches: Self::matches(interactive_output),
Ok(App {
matches: Self::matches(interactive_output)?,
interactive_output,
}
})
}
fn matches(interactive_output: bool) -> ArgMatches<'static> {
let clap_color_setting = if interactive_output {
AppSettings::ColoredHelp
fn matches(interactive_output: bool) -> Result<ArgMatches<'static>> {
let args = if wild::args_os().nth(1) == Some("cache".into())
|| wild::args_os().any(|arg| arg == "--no-config")
{
// Skip the arguments in bats config file
wild::args_os().collect::<Vec<_>>()
} else {
AppSettings::ColorNever
let mut cli_args = wild::args_os();
// Read arguments from bats config file
let mut args = get_args_from_env_var()
.unwrap_or_else(get_args_from_config_file)
.chain_err(|| "Could not parse configuration file")?;
// Put the zero-th CLI argument (program name) first
args.insert(0, cli_args.next().unwrap());
// .. and the rest at the end
cli_args.for_each(|a| args.push(a));
args
};
// Check if the current directory contains a file name cache, if it does
// do not make the arguements for subcommand 'cache' required.
let arg_group_required = !Path::new("cache").exists();
ClapApp::new(crate_name!())
.version(crate_version!())
.global_setting(clap_color_setting)
.global_setting(AppSettings::DeriveDisplayOrder)
.global_setting(AppSettings::UnifiedHelpMessage)
.global_setting(AppSettings::NextLineHelp)
.setting(AppSettings::InferSubcommands)
.setting(AppSettings::ArgsNegateSubcommands)
.setting(AppSettings::DisableHelpSubcommand)
.setting(AppSettings::VersionlessSubcommands)
.max_term_width(90)
.about(
"A cat(1) clone with wings.\n\n\
Use '--help' instead of '-h' to see a more detailed version of the help text.",
).long_about("A cat(1) clone with syntax highlighting and Git integration.")
.arg(
Arg::with_name("FILE")
.help("File(s) to print / concatenate. Use '-' for standard input.")
.long_help(
"File(s) to print / concatenate. Use a dash ('-') or no argument at all \
to read from standard input.",
).multiple(true)
.empty_values(false),
)
.arg(
Arg::with_name("language")
.short("l")
.long("language")
.overrides_with("language")
.help("Set the language for syntax highlighting.")
.long_help(
"Explicitly set the language for syntax highlighting. The language can be \
specified as a name (like 'C++' or 'LaTeX') or possible file extension \
(like 'cpp', 'hpp' or 'md'). Use '--list-languages' to show all supported \
language names and file extensions."
).takes_value(true),
).arg(
Arg::with_name("list-languages")
.long("list-languages")
.conflicts_with("list-themes")
.help("Display all supported languages.")
.long_help("Display a list of supported languages for syntax highlighting."),
).arg(
Arg::with_name("theme")
.long("theme")
.overrides_with("theme")
.takes_value(true)
.help("Set the color theme for syntax highlighting.")
.long_help(
"Set the theme for syntax highlighting. Use '--list-themes' to \
see all available themes. To set a default theme, export the \
BAT_THEME environment variable (e.g.: export \
BAT_THEME=\"TwoDark\").",
),
).arg(
Arg::with_name("list-themes")
.long("list-themes")
.help("Display all supported highlighting themes.")
.long_help("Display a list of supported themes for syntax highlighting."),
).arg(
Arg::with_name("style")
.long("style")
.value_name("style-components")
.use_delimiter(true)
.takes_value(true)
.possible_values(&[
"auto", "full", "plain", "changes", "header", "grid", "numbers",
])
.help("Comma-separated list of style elements to display.")
.long_help(
"Configure which elements (line numbers, file headers, grid \
borders, Git modifications, ..) to display in addition to the \
file contents. The argument is a comma-separated list of \
components to display (e.g. 'numbers,changes,grid') or a \
pre-defined style ('full'). To set a default theme, export the \
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"numbers\").",
),
).arg(
Arg::with_name("plain")
.overrides_with("plain")
.short("p")
.long("plain")
.conflicts_with("style")
.conflicts_with("number")
.help("Show plain style (alias for '--style=plain').")
.long_help(
"Only show plain style, no decorations. This is an alias for \
'--style=plain'",
),
).arg(
Arg::with_name("number")
.long("number")
.overrides_with("number")
.short("n")
.conflicts_with("style")
.help("Show line numbers (alias for '--style=numbers').")
.long_help(
"Only show line numbers, no other decorations. This is an alias for \
'--style=numbers'",
),
).arg(
Arg::with_name("line-range")
.long("line-range")
.overrides_with("line-range")
.takes_value(true)
.value_name("N:M")
.help("Only print the lines from N to M.")
.long_help(
"Only print the specified range of lines for each file. \
For example:\n \
'--line-range 30:40' prints lines 30 to 40\n \
'--line-range :40' prints lines 1 to 40\n \
'--line-range 40:' prints lines 40 to the end of the file",
),
).arg(
Arg::with_name("color")
.long("color")
.overrides_with("color")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.default_value("auto")
.help("When to use colors.")
.long_help("Specify when to use colored output. The automatic mode \
only enables colors if an interactive terminal is detected."),
).arg(
Arg::with_name("decorations")
.long("decorations")
.overrides_with("decorations")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.default_value("auto")
.help("When to show the decorations specified by '--style'.")
.long_help("Specify when to use the decorations that have been specified \
via '--style'. The automatic mode only enables decorations if \
an interactive terminal is detected."),
).arg(
Arg::with_name("paging")
.long("paging")
.overrides_with("paging")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.default_value("auto")
.help("Specify when to use the pager.")
.long_help("Specify when to use the pager. To control which pager \
is used, set the PAGER or BAT_PAGER environment \
variables (the latter takes precedence). The default \
pager is 'less'. To disable the pager permanently, set \
BAT_PAGER to an empty string."),
).arg(
Arg::with_name("wrap")
.long("wrap")
.overrides_with("wrap")
.takes_value(true)
.value_name("mode")
.possible_values(&["auto", "never", "character"])
.default_value("auto")
.help("Specify the text-wrapping mode.")
.long_help("Specify the text-wrapping mode."),
).arg(
Arg::with_name("unbuffered")
.short("u")
.hidden_short_help(true)
.long_help(
"This option exists for POSIX-compliance reasons ('u' is for \
'unbuffered'). The output is always unbuffered - this option \
is simply ignored.",
),
).arg(
Arg::with_name("tabs")
.long("tabs")
.takes_value(true)
.value_name("tabs")
.validator(
|t| t.parse::<u32>()
.map_err(|_t| "must be a number")
.map(|_t| ()) // Convert to Result<(), &str>
.map_err(|e| e.to_string()) // Convert to Result<(), String>
)
.help("Sets the tab width.")
.long_help("Sets the tab width. Use a width of 0 to pass tabs through \
directly"),
).arg(
Arg::with_name("terminal-width")
.long("terminal-width")
.takes_value(true)
.value_name("width")
.hidden(true)
.help("Set the width of the terminal"),
).subcommand(
SubCommand::with_name("cache")
.about("Modify the syntax-definition and theme cache")
.arg(
Arg::with_name("init")
.long("init")
.short("i")
.help("Initialize the syntax/theme cache.")
.long_help(
"Initialize the syntax/theme cache by loading from the \
source directory (default: the configuration directory).",
),
).arg(
Arg::with_name("clear")
.long("clear")
.short("c")
.help("Remove the cached syntax definitions and themes."),
).arg(
Arg::with_name("config-dir")
.long("config-dir")
.short("d")
.help("Show bat's configuration directory."),
).group(
ArgGroup::with_name("cache-actions")
.args(&["init", "clear", "config-dir"])
.required(arg_group_required),
).arg(
Arg::with_name("source")
.long("source")
.requires("init")
.takes_value(true)
.value_name("dir")
.help("Use a different directory to load syntaxes and themes from."),
).arg(
Arg::with_name("target")
.long("target")
.requires("init")
.takes_value(true)
.value_name("dir")
.help(
"Use a different directory to store the cached syntax and theme set.",
),
).arg(
Arg::with_name("blank")
.long("blank")
.requires("init")
.help("Create completely new syntax and theme sets \
(instead of appending to the default sets).")
),
).help_message("Print this help message.")
.version_message("Show version information.")
.get_matches()
Ok(clap_app::build_app(interactive_output).get_matches_from(args))
}
pub fn config(&self) -> Result<Config> {
@@ -364,27 +142,51 @@ impl App {
let paging_mode = match self.matches.value_of("paging") {
Some("always") => PagingMode::Always,
Some("never") => PagingMode::Never,
Some("auto") | _ => if files.contains(&InputFile::StdIn) {
// If we are reading from stdin, only enable paging if we write to an
// interactive terminal and if we do not *read* from an interactive
// terminal.
if self.interactive_output && !atty::is(Stream::Stdin) {
Some("auto") | _ => {
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
// interactive terminal and if we do not *read* from an interactive
// terminal.
if self.interactive_output && !atty::is(Stream::Stdin) {
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
} else if self.interactive_output {
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
} else {
if self.interactive_output {
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
},
}
};
let mut syntax_mapping = SyntaxMapping::new();
if let Some(values) = self.matches.values_of("map-syntax") {
for from_to in values {
let parts: Vec<_> = from_to.split(':').collect();
if parts.len() != 2 {
return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is 'from:to'.".into());
}
syntax_mapping.insert(parts[0], parts[1]);
}
}
Ok(Config {
true_color: is_truecolor_terminal(),
language: self.matches.value_of("language"),
language: self.matches.value_of("language").or_else(|| {
if self.matches.is_present("show-all") {
Some("show-nonprintable")
} else {
None
}
}),
show_nonprintable: self.matches.is_present("show-all"),
output_wrap: if !self.interactive_output {
// We don't have the tty width when piping to another program.
// There's no point in wrapping when this is the case.
@@ -393,11 +195,13 @@ impl App {
match self.matches.value_of("wrap") {
Some("character") => OutputWrap::Character,
Some("never") => OutputWrap::None,
Some("auto") | _ => if output_components.plain() {
OutputWrap::None
} else {
OutputWrap::Character
},
Some("auto") | _ => {
if output_components.plain() {
OutputWrap::None
} else {
OutputWrap::Character
}
}
}
},
colored_output: match self.matches.value_of("color") {
@@ -409,7 +213,23 @@ impl App {
term_width: self
.matches
.value_of("terminal-width")
.and_then(|w| w.parse().ok())
.and_then(|w| {
if w.starts_with('+') || w.starts_with('-') {
// Treat argument as a delta to the current terminal width
w.parse().ok().map(|delta: i16| {
let old_width: u16 = Term::stdout().size().1;
let new_width: i32 = i32::from(old_width) + i32::from(delta);
if new_width <= 0 {
old_width as usize
} else {
new_width as usize
}
})
} else {
w.parse().ok()
}
})
.unwrap_or(Term::stdout().size().1 as usize),
loop_through: !(self.interactive_output
|| self.matches.value_of("color") == Some("always")
@@ -425,7 +245,7 @@ impl App {
if output_components.plain() && paging_mode == PagingMode::Never {
0
} else {
8
4
},
),
theme: self
@@ -433,9 +253,27 @@ impl App {
.value_of("theme")
.map(String::from)
.or_else(|| env::var("BAT_THEME").ok())
.unwrap_or(String::from(BAT_THEME_DEFAULT)),
line_range: transpose(self.matches.value_of("line-range").map(LineRange::from))?,
.unwrap_or_else(|| String::from(BAT_THEME_DEFAULT)),
line_ranges: LineRanges::from(
transpose(
self.matches
.values_of("line-range")
.map(|vs| vs.map(LineRange::from).collect()),
)?
.unwrap_or_else(|| vec![]),
),
output_components,
syntax_mapping,
pager: self.matches.value_of("pager"),
use_italic_text: match self.matches.value_of("italic-text") {
Some("always") => true,
_ => false,
},
highlight_lines: self
.matches
.values_of("highlight-line")
.and_then(|ws| ws.map(|w| w.parse().ok()).collect())
.unwrap_or_default(),
})
}
@@ -450,8 +288,10 @@ impl App {
} else {
InputFile::Ordinary(filename)
}
}).collect()
}).unwrap_or_else(|| vec![InputFile::StdIn])
})
.collect()
})
.unwrap_or_else(|| vec![InputFile::StdIn])
}
fn output_components(&self) -> Result<OutputComponents> {
@@ -467,15 +307,22 @@ impl App {
let env_style_components: Option<Vec<OutputComponent>> =
transpose(env::var("BAT_STYLE").ok().map(|style_str| {
style_str
.split(",")
.split(',')
.map(|x| OutputComponent::from_str(&x))
.collect::<Result<Vec<OutputComponent>>>()
}))?;
values_t!(matches.values_of("style"), OutputComponent)
.ok()
matches
.value_of("style")
.map(|styles| {
styles
.split(',')
.map(|style| style.parse::<OutputComponent>())
.filter_map(|style| style.ok())
.collect::<Vec<_>>()
})
.or(env_style_components)
.unwrap_or(vec![OutputComponent::Full])
.unwrap_or_else(|| vec![OutputComponent::Full])
.into_iter()
.map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| {
+73 -76
View File
@@ -1,22 +1,18 @@
use directories::ProjectDirs;
use errors::*;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fs::{self, File};
use std::io::BufReader;
use std::path::{Path, PathBuf};
use syntect::dumps::{dump_to_file, from_binary, from_reader};
use syntect::highlighting::{Theme, ThemeSet};
use syntect::parsing::{SyntaxDefinition, SyntaxSet};
use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder};
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;
use crate::dirs::PROJECT_DIRS;
use app::InputFile;
lazy_static! {
static ref PROJECT_DIRS: ProjectDirs =
ProjectDirs::from("", "", crate_name!()).expect("Could not get home directory");
}
use crate::errors::*;
use crate::inputfile::{InputFile, InputFileReader};
use crate::syntax_mapping::SyntaxMapping;
pub const BAT_THEME_DEFAULT: &str = "Monokai Extended";
@@ -30,41 +26,38 @@ impl HighlightingAssets {
Self::from_cache().unwrap_or_else(|_| Self::from_binary())
}
fn empty() -> Self {
let mut syntax_set = SyntaxSet::new();
syntax_set.load_plain_text_syntax();
let theme_set = ThemeSet {
themes: BTreeMap::new(),
};
HighlightingAssets {
syntax_set,
theme_set,
}
}
pub fn from_files(dir: Option<&Path>, start_empty: bool) -> Result<Self> {
let source_dir = dir.unwrap_or_else(|| PROJECT_DIRS.config_dir());
let mut assets = if start_empty {
Self::empty()
let mut theme_set = if start_empty {
ThemeSet {
themes: BTreeMap::new(),
}
} else {
Self::from_binary_unlinked()
Self::get_integrated_themeset()
};
let theme_dir = source_dir.join("themes");
let res = extend_theme_set(&mut assets.theme_set, &theme_dir);
if !res.is_ok() {
let res = theme_set.add_from_folder(&theme_dir);
if res.is_err() {
println!(
"No themes were found in '{}', using the default set",
theme_dir.to_string_lossy()
);
}
let mut syntax_set_builder = if start_empty {
let mut builder = SyntaxSetBuilder::new();
builder.add_plain_text_syntax();
builder
} else {
Self::get_integrated_syntaxset().into_builder()
};
let syntax_dir = source_dir.join("syntaxes");
if syntax_dir.exists() {
assets.syntax_set.load_syntaxes(syntax_dir, true)?;
syntax_set_builder.add_from_folder(syntax_dir, true)?;
} else {
println!(
"No syntaxes were found in '{}', using the default set.",
@@ -72,7 +65,10 @@ impl HighlightingAssets {
);
}
Ok(assets)
Ok(HighlightingAssets {
syntax_set: syntax_set_builder.build(),
theme_set,
})
}
fn from_cache() -> Result<Self> {
@@ -83,9 +79,8 @@ impl HighlightingAssets {
syntax_set_path().to_string_lossy()
)
})?;
let mut syntax_set: SyntaxSet =
from_reader(syntax_set_file).chain_err(|| "Could not parse cached syntax set")?;
syntax_set.link_syntaxes();
let syntax_set: SyntaxSet = from_reader(BufReader::new(syntax_set_file))
.chain_err(|| "Could not parse cached syntax set")?;
let theme_set_file = File::open(&theme_set_path).chain_err(|| {
format!(
@@ -93,8 +88,8 @@ impl HighlightingAssets {
theme_set_path.to_string_lossy()
)
})?;
let theme_set: ThemeSet =
from_reader(theme_set_file).chain_err(|| "Could not parse cached theme set")?;
let theme_set: ThemeSet = from_reader(BufReader::new(theme_set_file))
.chain_err(|| "Could not parse cached theme set")?;
Ok(HighlightingAssets {
syntax_set,
@@ -102,9 +97,17 @@ impl HighlightingAssets {
})
}
fn from_binary_unlinked() -> Self {
let syntax_set: SyntaxSet = from_binary(include_bytes!("../assets/syntaxes.bin"));
let theme_set: ThemeSet = from_binary(include_bytes!("../assets/themes.bin"));
fn get_integrated_syntaxset() -> SyntaxSet {
from_binary(include_bytes!("../assets/syntaxes.bin"))
}
fn get_integrated_themeset() -> ThemeSet {
from_binary(include_bytes!("../assets/themes.bin"))
}
fn from_binary() -> Self {
let syntax_set = Self::get_integrated_syntaxset();
let theme_set = Self::get_integrated_themeset();
HighlightingAssets {
syntax_set,
@@ -112,15 +115,9 @@ impl HighlightingAssets {
}
}
fn from_binary() -> Self {
let mut assets = Self::from_binary_unlinked();
assets.syntax_set.link_syntaxes();
assets
}
pub fn save(&self, dir: Option<&Path>) -> Result<()> {
let target_dir = dir.unwrap_or_else(|| PROJECT_DIRS.cache_dir());
let _ = fs::create_dir(target_dir);
let _ = fs::create_dir_all(target_dir);
let theme_set_path = target_dir.join("themes.bin");
let syntax_set_path = target_dir.join("syntaxes.bin");
@@ -166,29 +163,40 @@ impl HighlightingAssets {
}
}
pub fn get_syntax(&self, language: Option<&str>, filename: InputFile) -> &SyntaxDefinition {
pub fn get_syntax(
&self,
language: Option<&str>,
filename: InputFile,
reader: &mut InputFileReader,
mapping: &SyntaxMapping,
) -> &SyntaxReference {
let syntax = match (language, filename) {
(Some(language), _) => self.syntax_set.find_syntax_by_token(language),
(None, InputFile::Ordinary(filename)) => {
#[cfg(not(unix))]
let may_read_from_file = true;
let path = Path::new(filename);
let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
let extension = path.extension().and_then(|x| x.to_str()).unwrap_or("");
// Do not peek at the file (to determine the syntax) if it is a FIFO because they can
// only be read once.
#[cfg(unix)]
let may_read_from_file = !fs::metadata(filename)
.map(|m| m.file_type().is_fifo())
.unwrap_or(false);
let file_name = mapping.replace(file_name);
let extension = mapping.replace(extension);
if may_read_from_file {
self.syntax_set
.find_syntax_for_file(filename)
.unwrap_or(None)
let ext_syntax = self
.syntax_set
.find_syntax_by_extension(&file_name)
.or_else(|| self.syntax_set.find_syntax_by_extension(&extension));
let line_syntax = if ext_syntax.is_none() {
String::from_utf8(reader.first_line.clone())
.ok()
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l))
} else {
None
}
};
ext_syntax.or(line_syntax)
}
(None, InputFile::StdIn) => None,
(None, InputFile::StdIn) => String::from_utf8(reader.first_line.clone())
.ok()
.and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)),
(_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
};
@@ -196,21 +204,6 @@ impl HighlightingAssets {
}
}
// TODO: this function will soon be part of syntect's `ThemeSet`.
fn extend_theme_set<P: AsRef<Path>>(theme_set: &mut ThemeSet, folder: P) -> Result<()> {
let paths = ThemeSet::discover_theme_paths(folder)?;
for p in &paths {
let theme = ThemeSet::get_theme(p)?;
let basename = p
.file_stem()
.and_then(|x| x.to_str())
.ok_or("Could not get theme basename")?;
theme_set.themes.insert(basename.to_owned(), theme);
}
Ok(())
}
fn theme_set_path() -> PathBuf {
PROJECT_DIRS.cache_dir().join("themes.bin")
}
@@ -223,6 +216,10 @@ pub fn config_dir() -> Cow<'static, str> {
PROJECT_DIRS.config_dir().to_string_lossy()
}
pub fn cache_dir() -> Cow<'static, str> {
PROJECT_DIRS.cache_dir().to_string_lossy()
}
pub fn clear_assets() {
print!("Clearing theme set cache ... ");
fs::remove_file(theme_set_path()).ok();
+432
View File
@@ -0,0 +1,432 @@
use clap::{App as ClapApp, AppSettings, Arg, ArgGroup, SubCommand};
use std::path::Path;
pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
let clap_color_setting = if interactive_output {
AppSettings::ColoredHelp
} else {
AppSettings::ColorNever
};
// Check if the current directory contains a file name cache, if it does
// do not make the arguements for subcommand 'cache' required.
let arg_group_required = !Path::new("cache").exists();
ClapApp::new(crate_name!())
.version(crate_version!())
.global_setting(clap_color_setting)
.global_setting(AppSettings::DeriveDisplayOrder)
.global_setting(AppSettings::UnifiedHelpMessage)
.global_setting(AppSettings::HidePossibleValuesInHelp)
.setting(AppSettings::ArgsNegateSubcommands)
.setting(AppSettings::AllowExternalSubcommands)
.setting(AppSettings::DisableHelpSubcommand)
.setting(AppSettings::VersionlessSubcommands)
.max_term_width(100)
.about(
"A cat(1) clone with wings.\n\n\
Use '--help' instead of '-h' to see a more detailed version of the help text.",
)
.long_about("A cat(1) clone with syntax highlighting and Git integration.")
.arg(
Arg::with_name("FILE")
.help("File(s) to print / concatenate. Use '-' for standard input.")
.long_help(
"File(s) to print / concatenate. Use a dash ('-') or no argument at all \
to read from standard input.",
)
.multiple(true)
.empty_values(false),
)
.arg(
Arg::with_name("language")
.short("l")
.long("language")
.overrides_with("language")
.help("Set the language for syntax highlighting.")
.long_help(
"Explicitly set the language for syntax highlighting. The language can be \
specified as a name (like 'C++' or 'LaTeX') or possible file extension \
(like 'cpp', 'hpp' or 'md'). Use '--list-languages' to show all supported \
language names and file extensions.",
)
.takes_value(true),
)
.arg(
Arg::with_name("list-languages")
.long("list-languages")
.short("L")
.conflicts_with("list-themes")
.help("Display all supported languages.")
.long_help("Display a list of supported languages for syntax highlighting."),
)
.arg(
Arg::with_name("map-syntax")
.short("m")
.long("map-syntax")
.multiple(true)
.takes_value(true)
.number_of_values(1)
.value_name("from:to")
.help("Map a file extension or name to an existing syntax.")
.long_help(
"Map a file extension or file name to an existing syntax. For example, \
to highlight *.conf files with the INI syntax, use '-m conf:ini'. \
To highlight files named '.myignore' with the Git Ignore syntax, use \
'-m .myignore:gitignore'.",
)
.takes_value(true),
)
.arg(
Arg::with_name("theme")
.long("theme")
.overrides_with("theme")
.takes_value(true)
.help("Set the color theme for syntax highlighting.")
.long_help(
"Set the theme for syntax highlighting. Use '--list-themes' to \
see all available themes. To set a default theme, add the \
'--theme=\"...\"' option to the configuration file or export the \
BAT_THEME environment variable (e.g.: export \
BAT_THEME=\"...\").",
),
)
.arg(
Arg::with_name("list-themes")
.long("list-themes")
.help("Display all supported highlighting themes.")
.long_help("Display a list of supported themes for syntax highlighting."),
)
.arg(
Arg::with_name("style")
.long("style")
.value_name("style-components")
// Need to turn this off for overrides_with to work as we want. See the bottom most
// example at https://docs.rs/clap/2.32.0/clap/struct.Arg.html#method.overrides_with
.use_delimiter(false)
.takes_value(true)
.overrides_with("style")
.overrides_with("plain")
.overrides_with("number")
// Cannot use clap's built in validation because we have to turn off clap's delimiters
.validator(|val| {
let mut invalid_vals = val.split(',').filter(|style| {
!&[
"auto", "full", "plain", "changes", "header", "grid", "numbers", "snip"
]
.contains(style)
});
if let Some(invalid) = invalid_vals.next() {
Err(format!("Unknown style, '{}'", invalid))
} else {
Ok(())
}
})
.help(
"Comma-separated list of style elements to display \
(*auto*, full, plain, changes, header, grid, numbers, snip).",
)
.long_help(
"Configure which elements (line numbers, file headers, grid \
borders, Git modifications, ..) to display in addition to the \
file contents. The argument is a comma-separated list of \
components to display (e.g. 'numbers,changes,grid') or a \
pre-defined style ('full'). To set a default style, add the \
'--style=\"..\"' option to the configuration file or export the \
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\"). \
Possible values: *auto*, full, plain, changes, header, grid, numbers, snip.",
),
)
.arg(
Arg::with_name("plain")
.overrides_with("plain")
.overrides_with("number")
.short("p")
.long("plain")
.multiple(true)
.help("Show plain style (alias for '--style=plain').")
.long_help(
"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 --pager=never').",
),
)
.arg(
Arg::with_name("number")
.long("number")
.overrides_with("number")
.short("n")
.help("Show line numbers (alias for '--style=numbers').")
.long_help(
"Only show line numbers, no other decorations. This is an alias for \
'--style=numbers'",
),
)
.arg(
Arg::with_name("show-all")
.long("show-all")
.alias("show-nonprintable")
.short("A")
.conflicts_with("language")
.help("Show non-printable characters (space, tab, newline, ..).")
.long_help(
"Show non-printable characters like space, tab or newline. \
This option can also be used to print binary files. \
Use '--tabs' to control the width of the tab-placeholders."
),
)
.arg(
Arg::with_name("line-range")
.long("line-range")
.short("r")
.multiple(true)
.takes_value(true)
.number_of_values(1)
.value_name("N:M")
.help("Only print the lines from N to M.")
.long_help(
"Only print the specified range of lines for each file. \
For example:\n \
'--line-range 30:40' prints lines 30 to 40\n \
'--line-range :40' prints lines 1 to 40\n \
'--line-range 40:' prints lines 40 to the end of the file",
),
)
.arg(
Arg::with_name("highlight-line")
.long("highlight-line")
.short("H")
.takes_value(true)
.number_of_values(1)
.multiple(true)
.value_name("N")
.help("Highlight the given line.")
.long_help(
"Highlight the N-th line with a different background color",
),
)
.arg(
Arg::with_name("color")
.long("color")
.overrides_with("color")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.hide_default_value(true)
.default_value("auto")
.help("When to use colors (*auto*, never, always).")
.long_help(
"Specify when to use colored output. The automatic mode \
only enables colors if an interactive terminal is detected. \
Possible values: *auto*, never, always.",
),
)
.arg(
Arg::with_name("italic-text")
.long("italic-text")
.takes_value(true)
.value_name("when")
.possible_values(&["always", "never"])
.default_value("never")
.hide_default_value(true)
.help("Use italics in output (always, *never*)")
.long_help("Specify when to use ANSI sequences for italic text in the output. Possible values: always, *never*."),
)
.arg(
Arg::with_name("decorations")
.long("decorations")
.overrides_with("decorations")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.default_value("auto")
.hide_default_value(true)
.help("When to show the decorations (*auto*, never, always).")
.long_help(
"Specify when to use the decorations that have been specified \
via '--style'. The automatic mode only enables decorations if \
an interactive terminal is detected. Possible values: *auto*, never, always.",
),
)
.arg(
Arg::with_name("paging")
.long("paging")
.overrides_with("paging")
.takes_value(true)
.value_name("when")
.possible_values(&["auto", "never", "always"])
.default_value("auto")
.hide_default_value(true)
.help("Specify when to use the pager (*auto*, never, always).")
.long_help(
"Specify when to use the pager. To control which pager \
is used, set the PAGER or BAT_PAGER environment \
variables (the latter takes precedence) or use the '--pager' option. \
To disable the pager permanently, set BAT_PAGER to an empty string \
or set '--paging=never' in the configuration file. \
Possible values: *auto*, never, always.",
),
)
.arg(
Arg::with_name("pager")
.long("pager")
.overrides_with("pager")
.takes_value(true)
.value_name("command")
.hidden_short_help(true)
.help("Determine which pager to use.")
.long_help(
"Determine which pager is used. This option will overwrite \
the PAGER and BAT_PAGER environment variables. The default \
pager is 'less'. To disable the pager completely, use the \
'--paging' option. \
Example: '--pager \"less -RF\"'.",
),
)
.arg(
Arg::with_name("wrap")
.long("wrap")
.overrides_with("wrap")
.takes_value(true)
.value_name("mode")
.possible_values(&["auto", "never", "character"])
.default_value("auto")
.hide_default_value(true)
.help("Specify the text-wrapping mode (*auto*, never, character).")
.long_help("Specify the text-wrapping mode (*auto*, never, character). \
The '--terminal-width' option can be used in addition to \
control the output width."),
)
.arg(
Arg::with_name("tabs")
.long("tabs")
.overrides_with("tabs")
.takes_value(true)
.value_name("T")
.validator(
|t| {
t.parse::<u32>()
.map_err(|_t| "must be a number")
.map(|_t| ()) // Convert to Result<(), &str>
.map_err(|e| e.to_string())
}, // Convert to Result<(), String>
)
.help("Set the tab width to T spaces.")
.long_help(
"Set the tab width to T spaces. Use a width of 0 to pass tabs through \
directly",
),
)
.arg(
Arg::with_name("unbuffered")
.short("u")
.long("unbuffered")
.hidden_short_help(true)
.long_help(
"This option exists for POSIX-compliance reasons ('u' is for \
'unbuffered'). The output is always unbuffered - this option \
is simply ignored.",
),
)
.arg(
Arg::with_name("terminal-width")
.long("terminal-width")
.takes_value(true)
.value_name("width")
.hidden_short_help(true)
.allow_hyphen_values(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(
"Explicitly set the width of the terminal instead of determining it \
automatically. If prefixed with '+' or '-', the value will be treated \
as an offset to the actual terminal width. See also: '--wrap'.",
),
)
.arg(
Arg::with_name("no-config")
.long("no-config")
.hidden(true)
.help("Do not use the configuration file"),
)
.arg(
Arg::with_name("config-file")
.long("config-file")
.conflicts_with("list-languages")
.conflicts_with("list-themes")
.hidden(true)
.help("Show path to the configuration file."),
)
.arg(
Arg::with_name("config-dir")
.long("config-dir")
.hidden(true)
.help("Show bat's configuration directory."),
)
.arg(
Arg::with_name("cache-dir")
.long("cache-dir")
.hidden(true)
.help("Show bat's cache directory."),
)
.subcommand(
SubCommand::with_name("cache")
.about("Modify the syntax-definition and theme cache")
.arg(
Arg::with_name("build")
.long("build")
.short("b")
.help("Initialize (or update) the syntax/theme cache.")
.long_help(
"Initialize (or update) the syntax/theme cache by loading from \
the source directory (default: the configuration directory).",
),
)
.arg(
Arg::with_name("clear")
.long("clear")
.short("c")
.help("Remove the cached syntax definitions and themes."),
)
.group(
ArgGroup::with_name("cache-actions")
.args(&["build", "clear"])
.required(arg_group_required),
)
.arg(
Arg::with_name("source")
.long("source")
.requires("build")
.takes_value(true)
.value_name("dir")
.help("Use a different directory to load syntaxes and themes from."),
)
.arg(
Arg::with_name("target")
.long("target")
.requires("build")
.takes_value(true)
.value_name("dir")
.help(
"Use a different directory to store the cached syntax and theme set.",
),
)
.arg(Arg::with_name("blank").long("blank").requires("build").help(
"Create completely new syntax and theme sets \
(instead of appending to the default sets).",
)),
)
.help_message("Print this help message.")
.version_message("Show version information.")
}
+105
View File
@@ -0,0 +1,105 @@
use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use shell_words;
use crate::dirs::PROJECT_DIRS;
use crate::util::transpose;
pub fn config_file() -> PathBuf {
env::var("BAT_CONFIG_PATH")
.ok()
.map(PathBuf::from)
.filter(|config_path| config_path.is_file())
.unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
}
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
Ok(transpose(
fs::read_to_string(config_file())
.ok()
.map(|content| get_args_from_str(&content)),
)?
.unwrap_or_else(|| vec![]))
}
pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
}
fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseError> {
let args_per_line = content
.split('\n')
.map(|line| line.trim())
.filter(|line| !line.is_empty())
.filter(|line| !line.starts_with('#'))
.map(|line| shell_words::split(line))
.collect::<Result<Vec<_>, _>>()?;
Ok(args_per_line
.iter()
.flatten()
.map(|line| line.into())
.collect())
}
#[test]
fn empty() {
let args = get_args_from_str("").unwrap();
assert!(args.is_empty());
}
#[test]
fn single() {
assert_eq!(vec!["--plain"], get_args_from_str("--plain").unwrap());
}
#[test]
fn multiple() {
assert_eq!(
vec!["--plain", "--language=cpp"],
get_args_from_str("--plain --language=cpp").unwrap()
);
}
#[test]
fn quotes() {
assert_eq!(
vec!["--theme", "Sublime Snazzy"],
get_args_from_str("--theme \"Sublime Snazzy\"").unwrap()
);
}
#[test]
fn multi_line() {
let config = "
-p
--style numbers,changes
--color=always
";
assert_eq!(
vec!["-p", "--style", "numbers,changes", "--color=always"],
get_args_from_str(config).unwrap()
);
}
#[test]
fn comments() {
let config = "
# plain style
-p
# show line numbers and Git modifications
--style numbers,changes
# Always show ANSI colors
--color=always
";
assert_eq!(
vec!["-p", "--style", "numbers,changes", "--color=always"],
get_args_from_str(config).unwrap()
);
}
+91 -67
View File
@@ -1,14 +1,13 @@
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::io::{self, Write};
use std::path::Path;
use app::{Config, InputFile};
use assets::HighlightingAssets;
use errors::*;
use line_range::LineRange;
use output::OutputType;
use printer::{InteractivePrinter, Printer, SimplePrinter};
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
use crate::app::{Config, PagingMode};
use crate::assets::HighlightingAssets;
use crate::errors::*;
use crate::inputfile::{InputFile, InputFileReader};
use crate::line_range::{LineRanges, RangeCheckResult};
use crate::output::OutputType;
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
pub struct Controller<'a> {
config: &'a Config<'a>,
@@ -21,22 +20,52 @@ impl<'b> Controller<'b> {
}
pub fn run(&self) -> Result<bool> {
let mut output_type = OutputType::from_mode(self.config.paging_mode);
// Do not launch the pager if NONE of the input files exist
let mut paging_mode = self.config.paging_mode;
if self.config.paging_mode != PagingMode::Never {
let call_pager = self.config.files.iter().any(|file| {
if let InputFile::Ordinary(path) = file {
return Path::new(path).exists();
} else {
return true;
}
});
if !call_pager {
paging_mode = PagingMode::Never;
}
}
let mut output_type = OutputType::from_mode(paging_mode, self.config.pager)?;
let writer = output_type.handle()?;
let mut no_errors: bool = true;
for filename in &self.config.files {
let result = if self.config.loop_through {
let mut printer = SimplePrinter::new();
self.print_file(&mut printer, writer, *filename)
} else {
let mut printer = InteractivePrinter::new(&self.config, &self.assets, *filename);
self.print_file(&mut printer, writer, *filename)
};
let stdin = io::stdin();
if let Err(error) = result {
handle_error(&error);
no_errors = false;
for input_file in &self.config.files {
match input_file.get_reader(&stdin) {
Err(error) => {
handle_error(&error);
no_errors = false;
}
Ok(mut reader) => {
let result = if self.config.loop_through {
let mut printer = SimplePrinter::new();
self.print_file(reader, &mut printer, writer, *input_file)
} else {
let mut printer = InteractivePrinter::new(
&self.config,
&self.assets,
*input_file,
&mut reader,
);
self.print_file(reader, &mut printer, writer, *input_file)
};
if let Err(error) = result {
handle_error(&error);
no_errors = false;
}
}
}
}
@@ -45,66 +74,61 @@ impl<'b> Controller<'b> {
fn print_file<'a, P: Printer>(
&self,
reader: InputFileReader,
printer: &mut P,
writer: &mut Write,
filename: InputFile<'a>,
writer: &mut dyn Write,
input_file: InputFile<'a>,
) -> Result<()> {
let stdin = io::stdin();
{
let reader: Box<BufRead> = match filename {
InputFile::StdIn => Box::new(stdin.lock()),
InputFile::Ordinary(filename) => {
let file = File::open(filename)?;
if file.metadata()?.is_dir() {
return Err(format!("'{}' is a directory.", filename).into());
}
Box::new(BufReader::new(file))
}
InputFile::ThemePreviewFile => Box::new(THEME_PREVIEW_FILE),
};
printer.print_header(writer, filename)?;
self.print_file_ranges(printer, writer, reader, &self.config.line_range)?;
printer.print_footer(writer)?;
printer.print_header(writer, input_file)?;
if !reader.first_line.is_empty() {
self.print_file_ranges(printer, writer, reader, &self.config.line_ranges)?;
}
printer.print_footer(writer)?;
Ok(())
}
fn print_file_ranges<'a, P: Printer>(
fn print_file_ranges<P: Printer>(
&self,
printer: &mut P,
writer: &mut Write,
mut reader: Box<BufRead + 'a>,
line_ranges: &Option<LineRange>,
writer: &mut dyn Write,
mut reader: InputFileReader,
line_ranges: &LineRanges,
) -> Result<()> {
let mut line_buffer = Vec::new();
let mut line_number: usize = 1;
while reader.read_until(b'\n', &mut line_buffer)? > 0 {
{
match line_ranges {
&Some(ref range) => {
if line_number < range.lower {
// Call the printer in case we need to call the syntax highlighter
// for this line. However, set `out_of_range` to `true`.
printer.print_line(true, writer, line_number, &line_buffer)?;
} else if line_number > range.upper {
// no more lines in range, exit early
break;
} else {
printer.print_line(false, writer, line_number, &line_buffer)?;
}
}
&None => {
printer.print_line(false, writer, line_number, &line_buffer)?;
}
let mut first_range: bool = true;
let mut mid_range: bool = false;
while reader.read_line(&mut line_buffer)? {
match line_ranges.check(line_number) {
RangeCheckResult::OutsideRange => {
// Call the printer in case we need to call the syntax highlighter
// for this line. However, set `out_of_range` to `true`.
printer.print_line(true, writer, line_number, &line_buffer)?;
mid_range = false;
}
line_number += 1;
RangeCheckResult::InRange => {
if self.config.output_components.snip() {
if first_range {
first_range = false;
mid_range = true;
} else if !mid_range {
mid_range = true;
printer.print_snip(writer)?;
}
}
printer.print_line(false, writer, line_number, &line_buffer)?;
}
RangeCheckResult::AfterLastRange => {
break;
}
}
line_number += 1;
line_buffer.clear();
}
Ok(())
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::diff::LineChange;
use crate::printer::{Colors, InteractivePrinter};
use ansi_term::Style;
use diff::LineChange;
use printer::{Colors, InteractivePrinter};
#[derive(Clone)]
pub struct DecorationText {
+1 -1
View File
@@ -34,7 +34,7 @@ pub fn get_git_diff(filename: &str) -> Option<LineChanges> {
let mark_section =
|line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
for line in start..(end + 1) as u32 {
for line in start..=end as u32 {
line_changes.insert(line, change);
}
};
+57
View File
@@ -0,0 +1,57 @@
use crate::dirs_rs;
use std::path::{Path, PathBuf};
#[cfg(target_os = "macos")]
use std::env;
/// Wrapper for 'dirs' that treats MacOS more like Linux, by following the XDG specification.
/// This means that the `XDG_CACHE_HOME` and `XDG_CONFIG_HOME` environment variables are
/// checked first. The fallback directories are `~/.cache/bat` and `~/.config/bat`, respectively.
pub struct BatProjectDirs {
cache_dir: PathBuf,
config_dir: PathBuf,
}
impl BatProjectDirs {
fn new() -> Option<BatProjectDirs> {
#[cfg(target_os = "macos")]
let cache_dir_op = env::var_os("XDG_CACHE_HOME")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.or_else(|| dirs_rs::home_dir().map(|d| d.join(".cache")));
#[cfg(not(target_os = "macos"))]
let cache_dir_op = dirs_rs::cache_dir();
let cache_dir = cache_dir_op.map(|d| d.join("bat"))?;
#[cfg(target_os = "macos")]
let config_dir_op = env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.or_else(|| dirs_rs::home_dir().map(|d| d.join(".config")));
#[cfg(not(target_os = "macos"))]
let config_dir_op = dirs_rs::config_dir();
let config_dir = config_dir_op.map(|d| d.join("bat"))?;
Some(BatProjectDirs {
cache_dir,
config_dir,
})
}
pub fn cache_dir(&self) -> &Path {
&self.cache_dir
}
pub fn config_dir(&self) -> &Path {
&self.config_dir
}
}
lazy_static! {
pub static ref PROJECT_DIRS: BatProjectDirs =
BatProjectDirs::new().expect("Could not get home directory");
}
+135
View File
@@ -0,0 +1,135 @@
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use content_inspector::{self, ContentType};
use crate::errors::*;
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
pub struct InputFileReader<'a> {
inner: Box<dyn BufRead + 'a>,
pub first_line: Vec<u8>,
pub content_type: Option<ContentType>,
}
impl<'a> InputFileReader<'a> {
fn new<R: BufRead + 'a>(mut reader: R) -> InputFileReader<'a> {
let mut first_line = vec![];
reader.read_until(b'\n', &mut first_line).ok();
let content_type = if first_line.is_empty() {
None
} else {
Some(content_inspector::inspect(&first_line[..]))
};
if content_type == Some(ContentType::UTF_16LE) {
reader.read_until(0x00, &mut first_line).ok();
}
InputFileReader {
inner: Box::new(reader),
first_line,
content_type,
}
}
pub fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
if self.first_line.is_empty() {
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
if self.content_type == Some(ContentType::UTF_16LE) {
self.inner.read_until(0x00, buf).ok();
}
Ok(res)
} else {
buf.append(&mut self.first_line);
Ok(true)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum InputFile<'a> {
StdIn,
Ordinary(&'a str),
ThemePreviewFile,
}
impl<'a> InputFile<'a> {
pub fn get_reader(&self, stdin: &'a io::Stdin) -> Result<InputFileReader> {
match self {
InputFile::StdIn => Ok(InputFileReader::new(stdin.lock())),
InputFile::Ordinary(filename) => {
let file = File::open(filename).map_err(|e| format!("'{}': {}", filename, e))?;
if file.metadata()?.is_dir() {
return Err(format!("'{}' is a directory.", filename).into());
}
Ok(InputFileReader::new(BufReader::new(file)))
}
InputFile::ThemePreviewFile => Ok(InputFileReader::new(THEME_PREVIEW_FILE)),
}
}
}
#[test]
fn basic() {
let content = b"#!/bin/bash\necho hello";
let mut reader = InputFileReader::new(&content[..]);
assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]);
let mut buffer = vec![];
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(true, res.unwrap());
assert_eq!(b"#!/bin/bash\n", &buffer[..]);
buffer.clear();
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(true, res.unwrap());
assert_eq!(b"echo hello", &buffer[..]);
buffer.clear();
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(false, res.unwrap());
assert!(buffer.is_empty());
}
#[test]
fn utf16le() {
let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00";
let mut reader = InputFileReader::new(&content[..]);
assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]);
let mut buffer = vec![];
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(true, res.unwrap());
assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &buffer[..]);
buffer.clear();
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(true, res.unwrap());
assert_eq!(b"\x64\x00", &buffer[..]);
buffer.clear();
let res = reader.read_line(&mut buffer);
assert!(res.is_ok());
assert_eq!(false, res.unwrap());
assert!(buffer.is_empty());
}
+101 -1
View File
@@ -1,4 +1,4 @@
use errors::*;
use crate::errors::*;
#[derive(Clone)]
pub struct LineRange {
@@ -38,6 +38,10 @@ impl LineRange {
Err("expected single ':' character".into())
}
pub fn is_inside(&self, line: usize) -> bool {
line >= self.lower && line <= self.upper
}
}
#[test]
@@ -72,3 +76,99 @@ fn test_parse_fail() {
let range = LineRange::from("40");
assert!(range.is_err());
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum RangeCheckResult {
// Within one of the given ranges
InRange,
// Before the first range or within two ranges
OutsideRange,
// Line number is outside of all ranges and larger than the last range.
AfterLastRange,
}
#[derive(Clone)]
pub struct LineRanges {
ranges: Vec<LineRange>,
largest_upper_bound: usize,
}
impl LineRanges {
pub fn from(ranges: Vec<LineRange>) -> LineRanges {
let largest_upper_bound = ranges
.iter()
.map(|r| r.upper)
.max()
.unwrap_or(usize::max_value());
LineRanges {
ranges,
largest_upper_bound,
}
}
pub fn check(&self, line: usize) -> RangeCheckResult {
if self.ranges.is_empty() | self.ranges.iter().any(|r| r.is_inside(line)) {
RangeCheckResult::InRange
} else if line < self.largest_upper_bound {
RangeCheckResult::OutsideRange
} else {
RangeCheckResult::AfterLastRange
}
}
}
#[cfg(test)]
fn ranges(rs: &[&str]) -> LineRanges {
LineRanges::from(rs.iter().map(|r| LineRange::from(r).unwrap()).collect())
}
#[test]
fn test_ranges_simple() {
let ranges = ranges(&["3:8"]);
assert_eq!(RangeCheckResult::OutsideRange, ranges.check(2));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
}
#[test]
fn test_ranges_advanced() {
let ranges = ranges(&["3:8", "11:20", "25:30"]);
assert_eq!(RangeCheckResult::OutsideRange, ranges.check(2));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::OutsideRange, ranges.check(9));
assert_eq!(RangeCheckResult::InRange, ranges.check(11));
assert_eq!(RangeCheckResult::OutsideRange, ranges.check(22));
assert_eq!(RangeCheckResult::InRange, ranges.check(28));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(31));
}
#[test]
fn test_ranges_open_low() {
let ranges = ranges(&["3:8", ":5"]);
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
assert_eq!(RangeCheckResult::InRange, ranges.check(7));
assert_eq!(RangeCheckResult::AfterLastRange, ranges.check(9));
}
#[test]
fn test_ranges_open_high() {
let ranges = ranges(&["3:", "2:5"]);
assert_eq!(RangeCheckResult::OutsideRange, ranges.check(1));
assert_eq!(RangeCheckResult::InRange, ranges.check(3));
assert_eq!(RangeCheckResult::InRange, ranges.check(5));
assert_eq!(RangeCheckResult::InRange, ranges.check(9));
}
#[test]
fn test_ranges_empty() {
let ranges = ranges(&[]);
assert_eq!(RangeCheckResult::InRange, ranges.check(1));
}
+77 -51
View File
@@ -13,21 +13,31 @@ extern crate lazy_static;
extern crate ansi_term;
extern crate atty;
extern crate console;
extern crate directories;
extern crate content_inspector;
extern crate dirs as dirs_rs;
extern crate encoding;
extern crate git2;
extern crate shell_words;
extern crate syntect;
extern crate wild;
mod app;
mod assets;
mod clap_app;
mod config;
mod controller;
mod decorations;
mod diff;
mod dirs;
mod inputfile;
mod line_range;
mod output;
mod preprocessor;
mod printer;
mod style;
mod syntax_mapping;
mod terminal;
mod util;
use std::collections::HashSet;
use std::io;
@@ -38,10 +48,12 @@ use std::process;
use ansi_term::Colour::Green;
use ansi_term::Style;
use app::{App, Config, InputFile};
use assets::{clear_assets, config_dir, HighlightingAssets};
use controller::Controller;
use style::{OutputComponent, OutputComponents};
use crate::app::{App, Config};
use crate::assets::{cache_dir, clear_assets, config_dir, HighlightingAssets};
use crate::config::config_file;
use crate::controller::Controller;
use crate::inputfile::InputFile;
use crate::style::{OutputComponent, OutputComponents};
mod errors {
error_chain! {
@@ -55,7 +67,7 @@ mod errors {
pub fn handle_error(error: &Error) {
match error {
&Error(ErrorKind::Io(ref io_error), _)
Error(ErrorKind::Io(ref io_error), _)
if io_error.kind() == super::io::ErrorKind::BrokenPipe =>
{
super::process::exit(0);
@@ -68,10 +80,10 @@ mod errors {
}
}
use errors::*;
use crate::errors::*;
fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
if matches.is_present("init") {
if matches.is_present("build") {
let source_dir = matches.value_of("source").map(Path::new);
let target_dir = matches.value_of("target").map(Path::new);
@@ -81,8 +93,6 @@ fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
assets.save(target_dir)?;
} else if matches.is_present("clear") {
clear_assets();
} else if matches.is_present("config-dir") {
writeln!(io::stdout(), "{}", config_dir())?;
}
Ok(())
@@ -98,48 +108,54 @@ pub fn list_languages(config: &Config) -> Result<()> {
.collect::<Vec<_>>();
languages.sort_by_key(|lang| lang.name.to_uppercase());
let longest = languages
.iter()
.map(|syntax| syntax.name.len())
.max()
.unwrap_or(32); // Fallback width if they have no language definitions.
let comma_separator = ", ";
let separator = " ";
// Line-wrapping for the possible file extension overflow.
let desired_width = config.term_width - longest - separator.len();
let stdout = io::stdout();
let mut stdout = stdout.lock();
let style = if config.colored_output {
Green.normal()
} else {
Style::default()
};
for lang in languages {
write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
// 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)?;
}
if config.loop_through {
for lang in languages {
write!(stdout, "{}:{}\n", lang.name, lang.file_extensions.join(","))?;
}
} else {
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 style = if config.colored_output {
Green.normal()
} else {
Style::default()
};
for lang in languages {
write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
// 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(())
@@ -183,10 +199,10 @@ fn run_controller(config: &Config) -> Result<bool> {
controller.run()
}
/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Some(true)` on full success and
/// `Some(false)` if any intermediate errors occurred (were printed).
/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Ok(true)` on full success and
/// `Ok(false)` if any intermediate errors occurred (were printed).
fn run() -> Result<bool> {
let app = App::new();
let app = App::new()?;
match app.matches.subcommand() {
("cache", Some(cache_matches)) => {
@@ -213,6 +229,16 @@ fn run() -> Result<bool> {
} else if app.matches.is_present("list-themes") {
list_themes(&config)?;
Ok(true)
} else if app.matches.is_present("config-file") {
println!("{}", config_file().to_string_lossy());
Ok(true)
} else if app.matches.is_present("config-dir") {
writeln!(io::stdout(), "{}", config_dir())?;
Ok(true)
} else if app.matches.is_present("cache-dir") {
writeln!(io::stdout(), "{}", cache_dir())?;
Ok(true)
} else {
run_controller(&config)
+73 -30
View File
@@ -4,8 +4,10 @@ use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{Child, Command, Stdio};
use app::PagingMode;
use errors::*;
use shell_words;
use crate::app::PagingMode;
use crate::errors::*;
pub enum OutputType {
Pager(Child),
@@ -13,49 +15,90 @@ pub enum OutputType {
}
impl OutputType {
pub fn from_mode(mode: PagingMode) -> Self {
pub fn from_mode(mode: PagingMode, pager: Option<&str>) -> Result<Self> {
use self::PagingMode::*;
match mode {
Always => OutputType::try_pager(false),
QuitIfOneScreen => OutputType::try_pager(true),
Ok(match mode {
Always => OutputType::try_pager(false, pager)?,
QuitIfOneScreen => OutputType::try_pager(true, pager)?,
_ => OutputType::stdout(),
}
})
}
/// Try to launch the pager. Fall back to stdout in case of errors.
fn try_pager(quit_if_one_screen: bool) -> Self {
let pager = env::var("BAT_PAGER")
.or_else(|_| env::var("PAGER"))
.unwrap_or(String::from("less"));
fn try_pager(quit_if_one_screen: bool, pager_from_config: Option<&str>) -> Result<Self> {
let mut replace_arguments_to_less = false;
let less_path = PathBuf::from(&pager);
let is_less = less_path.file_stem() == Some(&OsString::from("less"));
let mut process = if is_less {
let mut args = vec!["--RAW-CONTROL-CHARS", "--no-init"];
if quit_if_one_screen {
args.push("--quit-if-one-screen");
let pager_from_env = match (env::var("BAT_PAGER"), env::var("PAGER")) {
(Ok(bat_pager), _) => Some(bat_pager),
(_, Ok(pager)) => {
// less needs to be called with the '-R' option in order to properly interpret the
// ANSI color sequences printed by bat. If someone has set PAGER="less -F", we
// therefore need to overwrite the arguments and add '-R'.
//
// We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER
// or bats '--pager' command line option.
replace_arguments_to_less = true;
Some(pager)
}
let mut p = Command::new(&less_path);
p.args(&args).env("LESSCHARSET", "UTF-8");
p
} else {
Command::new(pager)
_ => None,
};
process
.stdin(Stdio::piped())
.spawn()
.map(OutputType::Pager)
.unwrap_or_else(|_| OutputType::stdout())
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
.or(pager_from_env)
.unwrap_or_else(|| String::from("less"));
let pagerflags =
shell_words::split(&pager).chain_err(|| "Could not parse pager command.")?;
match pagerflags.split_first() {
Some((pager_name, args)) => {
let mut pager_path = PathBuf::from(pager_name);
if pager_path.file_stem() == Some(&OsString::from("bat")) {
pager_path = PathBuf::from("less");
}
let is_less = pager_path.file_stem() == Some(&OsString::from("less"));
let mut process = if is_less {
let mut p = Command::new(&pager_path);
if args.is_empty() || replace_arguments_to_less {
p.args(vec!["--RAW-CONTROL-CHARS", "--no-init"]);
if quit_if_one_screen {
p.arg("--quit-if-one-screen");
}
} else {
p.args(args);
}
p.env("LESSCHARSET", "UTF-8");
p
} else {
let mut p = Command::new(&pager_path);
p.args(args);
p
};
Ok(process
.stdin(Stdio::piped())
.spawn()
.map(OutputType::Pager)
.unwrap_or_else(|_| OutputType::stdout()))
}
None => Ok(OutputType::stdout()),
}
}
fn stdout() -> Self {
OutputType::Stdout(io::stdout())
}
pub fn handle(&mut self) -> Result<&mut Write> {
pub fn handle(&mut self) -> Result<&mut dyn Write> {
Ok(match *self {
OutputType::Pager(ref mut command) => command
.stdin
+114 -1
View File
@@ -1,7 +1,7 @@
use console::AnsiCodeIterator;
/// Expand tabs like an ANSI-enabled expand(1).
pub fn expand(line: &str, width: usize, cursor: &mut usize) -> String {
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2);
for chunk in AnsiCodeIterator::new(line) {
@@ -32,3 +32,116 @@ pub fn expand(line: &str, width: usize, cursor: &mut usize) -> String {
buffer
}
fn try_parse_utf8_char(input: &[u8]) -> Option<(char, usize)> {
let str_from_utf8 = |seq| std::str::from_utf8(seq).ok();
let decoded = None
.or(input.get(0..1).and_then(str_from_utf8).map(|c| (c, 1)))
.or(input.get(0..2).and_then(str_from_utf8).map(|c| (c, 2)))
.or(input.get(0..3).and_then(str_from_utf8).map(|c| (c, 3)))
.or(input.get(0..4).and_then(str_from_utf8).map(|c| (c, 4)));
let decoded_char = decoded.map(|(seq, n)| (seq.chars().next().unwrap(), n));
decoded_char
}
pub fn replace_nonprintable(input: &[u8], tab_width: usize) -> String {
let mut output = String::new();
let tab_width = if tab_width == 0 { 4 } else { tab_width };
let mut idx = 0;
let len = input.len();
while idx < len {
if let Some((chr, skip_ahead)) = try_parse_utf8_char(&input[idx..]) {
idx += skip_ahead;
match chr {
// space
' ' => output.push('•'),
// tab
'\t' => {
if tab_width == 1 {
output.push('↹');
} else {
output.push('├');
output.push_str(&"".repeat(tab_width - 2));
output.push('┤');
}
}
// line feed
'\x0A' => output.push('␊'),
// carriage return
'\x0D' => output.push('␍'),
// null
'\x00' => output.push('␀'),
// bell
'\x07' => output.push('␇'),
// backspace
'\x08' => output.push('␈'),
// escape
'\x1B' => output.push('␛'),
// printable ASCII
c if c.is_ascii_alphanumeric()
|| c.is_ascii_punctuation()
|| c.is_ascii_graphic() =>
{
output.push(c)
}
// everything else
c => output.push_str(&c.escape_unicode().collect::<String>()),
}
} else {
output.push_str(&format!("\\x{:02X}", input[idx]));
idx += 1;
}
}
output
}
#[test]
fn test_try_parse_utf8_char() {
assert_eq!(try_parse_utf8_char(&[0x20]), Some((' ', 1)));
assert_eq!(try_parse_utf8_char(&[0x20, 0x20]), Some((' ', 1)));
assert_eq!(try_parse_utf8_char(&[0x20, 0xef]), Some((' ', 1)));
assert_eq!(try_parse_utf8_char(&[0x00]), Some(('\x00', 1)));
assert_eq!(try_parse_utf8_char(&[0x1b]), Some(('\x1b', 1)));
assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4]), Some(('ä', 2)));
assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4, 0xef]), Some(('ä', 2)));
assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4, 0x20]), Some(('ä', 2)));
assert_eq!(try_parse_utf8_char(&[0xe2, 0x82, 0xac]), Some(('€', 3)));
assert_eq!(
try_parse_utf8_char(&[0xe2, 0x82, 0xac, 0xef]),
Some(('€', 3))
);
assert_eq!(
try_parse_utf8_char(&[0xe2, 0x82, 0xac, 0x20]),
Some(('€', 3))
);
assert_eq!(try_parse_utf8_char(&[0xe2, 0x88, 0xb0]), Some(('∰', 3)));
assert_eq!(
try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82]),
Some(('🌂', 4))
);
assert_eq!(
try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82, 0xef]),
Some(('🌂', 4))
);
assert_eq!(
try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82, 0x20]),
Some(('🌂', 4))
);
assert_eq!(try_parse_utf8_char(&[]), None);
assert_eq!(try_parse_utf8_char(&[0xef]), None);
assert_eq!(try_parse_utf8_char(&[0xef, 0x20]), None);
assert_eq!(try_parse_utf8_char(&[0xf0, 0xf0]), None);
}
+254 -51
View File
@@ -1,4 +1,3 @@
use std::boxed::Box;
use std::io::Write;
use std::vec::Vec;
@@ -8,25 +7,38 @@ use ansi_term::Style;
use console::AnsiCodeIterator;
use syntect::easy::HighlightLines;
use syntect::highlighting::Color;
use syntect::highlighting::Theme;
use syntect::parsing::SyntaxSet;
use app::{Config, InputFile};
use assets::HighlightingAssets;
use decorations::{Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration};
use diff::get_git_diff;
use diff::LineChanges;
use errors::*;
use preprocessor::expand;
use style::OutputWrap;
use terminal::{as_terminal_escaped, to_ansi_color};
use content_inspector::ContentType;
use encoding::all::{UTF_16BE, UTF_16LE};
use encoding::{DecoderTrap, Encoding};
use crate::app::Config;
use crate::assets::HighlightingAssets;
use crate::decorations::{
Decoration, GridBorderDecoration, LineChangesDecoration, LineNumberDecoration,
};
use crate::diff::get_git_diff;
use crate::diff::LineChanges;
use crate::errors::*;
use crate::inputfile::{InputFile, InputFileReader};
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::OutputWrap;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
pub trait Printer {
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()>;
fn print_footer(&mut self, handle: &mut Write) -> Result<()>;
fn print_header(&mut self, handle: &mut dyn Write, file: InputFile) -> Result<()>;
fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>;
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
handle: &mut dyn Write,
line_number: usize,
line_buffer: &[u8],
) -> Result<()>;
@@ -41,23 +53,27 @@ impl SimplePrinter {
}
impl Printer for SimplePrinter {
fn print_header(&mut self, _handle: &mut Write, _file: InputFile) -> Result<()> {
fn print_header(&mut self, _handle: &mut dyn Write, _file: InputFile) -> Result<()> {
Ok(())
}
fn print_footer(&mut self, _handle: &mut Write) -> Result<()> {
fn print_footer(&mut self, _handle: &mut dyn Write) -> Result<()> {
Ok(())
}
fn print_snip(&mut self, _handle: &mut dyn Write) -> Result<()> {
Ok(())
}
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
handle: &mut dyn Write,
_line_number: usize,
line_buffer: &[u8],
) -> Result<()> {
if !out_of_range {
handle.write(line_buffer)?;
handle.write_all(line_buffer)?;
}
Ok(())
}
@@ -66,17 +82,27 @@ impl Printer for SimplePrinter {
pub struct InteractivePrinter<'a> {
colors: Colors,
config: &'a Config<'a>,
decorations: Vec<Box<Decoration>>,
decorations: Vec<Box<dyn Decoration>>,
panel_width: usize,
ansi_prefix_sgr: String,
content_type: Option<ContentType>,
pub line_changes: Option<LineChanges>,
highlighter: HighlightLines<'a>,
highlighter: Option<HighlightLines<'a>>,
syntax_set: &'a SyntaxSet,
background_color_highlight: Option<Color>,
}
impl<'a> InteractivePrinter<'a> {
pub fn new(config: &'a Config, assets: &'a HighlightingAssets, file: InputFile) -> Self {
pub fn new(
config: &'a Config,
assets: &'a HighlightingAssets,
file: InputFile,
reader: &mut InputFileReader,
) -> Self {
let theme = assets.get_theme(&config.theme);
let background_color_highlight = theme.settings.line_highlight;
let colors = if config.colored_output {
Colors::colored(theme, config.true_color)
} else {
@@ -84,7 +110,7 @@ impl<'a> InteractivePrinter<'a> {
};
// Create decorations.
let mut decorations: Vec<Box<Decoration>> = Vec::new();
let mut decorations: Vec<Box<dyn Decoration>> = Vec::new();
if config.output_components.numbers() {
decorations.push(Box::new(LineNumberDecoration::new(&colors)));
@@ -113,32 +139,44 @@ impl<'a> InteractivePrinter<'a> {
panel_width = 0;
}
// Get the Git modifications
let line_changes = if config.output_components.changes() {
match file {
InputFile::Ordinary(filename) => get_git_diff(filename),
_ => None,
}
} else {
None
};
let mut line_changes = None;
// Determine the type of syntax for highlighting
let syntax = assets.get_syntax(config.language, file);
let highlighter = HighlightLines::new(syntax, theme);
let highlighter = if reader
.content_type
.map_or(false, |c| c.is_binary() && !config.show_nonprintable)
{
None
} else {
// Get the Git modifications
line_changes = if config.output_components.changes() {
match file {
InputFile::Ordinary(filename) => get_git_diff(filename),
_ => None,
}
} else {
None
};
// Determine the type of syntax for highlighting
let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
Some(HighlightLines::new(syntax, theme))
};
InteractivePrinter {
panel_width,
colors,
config,
decorations,
content_type: reader.content_type,
ansi_prefix_sgr: String::new(),
line_changes,
highlighter,
syntax_set: &assets.syntax_set,
background_color_highlight,
}
}
fn print_horizontal_line(&mut self, handle: &mut Write, grid_char: char) -> Result<()> {
fn print_horizontal_line(&mut self, handle: &mut dyn Write, grid_char: char) -> Result<()> {
if self.panel_width == 0 {
writeln!(
handle,
@@ -154,9 +192,27 @@ impl<'a> InteractivePrinter<'a> {
Ok(())
}
fn create_fake_panel(&self, text: &str) -> String {
if self.panel_width == 0 {
"".to_string()
} else {
let text_truncated: String = text.chars().take(self.panel_width - 1).collect();
let text_filled: String = format!(
"{}{}",
text_truncated,
" ".repeat(self.panel_width - 1 - text_truncated.len())
);
if self.config.output_components.grid() {
format!("{}", text_filled)
} else {
format!("{}", text_filled)
}
}
}
fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
if self.config.tab_width > 0 {
expand(text, self.config.tab_width, cursor)
expand_tabs(text, self.config.tab_width, cursor)
} else {
text.to_string()
}
@@ -164,8 +220,27 @@ impl<'a> 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 dyn Write, file: InputFile) -> Result<()> {
if !self.config.output_components.header() {
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
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). You can use 'bat -A' \
to show the binary file contents.",
Yellow.paint("[bat warning]"),
input
)?;
} else {
if self.config.output_components.grid() {
self.print_horizontal_line(handle, '┬')?;
}
}
return Ok(());
}
@@ -189,32 +264,100 @@ impl<'a> Printer for InteractivePrinter<'a> {
_ => ("", "STDIN"),
};
writeln!(handle, "{}{}", prefix, self.colors.filename.paint(name))?;
let mode = match self.content_type {
Some(ContentType::BINARY) => " <BINARY>",
Some(ContentType::UTF_16LE) => " <UTF-16LE>",
Some(ContentType::UTF_16BE) => " <UTF-16BE>",
None => " <EMPTY>",
_ => "",
};
writeln!(
handle,
"{}{}{}",
prefix,
self.colors.filename.paint(name),
mode
)?;
if self.config.output_components.grid() {
self.print_horizontal_line(handle, '┼')?;
if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable {
self.print_horizontal_line(handle, '┼')?;
} else {
self.print_horizontal_line(handle, '┴')?;
}
}
Ok(())
}
fn print_footer(&mut self, handle: &mut Write) -> Result<()> {
if self.config.output_components.grid() {
fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()> {
if self.config.output_components.grid()
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
{
self.print_horizontal_line(handle, '┴')
} else {
Ok(())
}
}
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()> {
let panel = self.create_fake_panel(" ...");
let panel_count = panel.chars().count();
let title = "8<";
let title_count = title.chars().count();
let snip_left = "".repeat((self.config.term_width - panel_count - (title_count / 2)) / 4);
let snip_left_count = snip_left.chars().count(); // Can't use .len() with Unicode.
let snip_right =
"".repeat((self.config.term_width - panel_count - snip_left_count - title_count) / 2);
write!(
handle,
"{}\n",
self.colors
.grid
.paint(format!("{}{}{}{}", panel, snip_left, title, snip_right))
)?;
Ok(())
}
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
handle: &mut dyn Write,
line_number: usize,
line_buffer: &[u8],
) -> Result<()> {
let line = String::from_utf8_lossy(&line_buffer).to_string();
let regions = self.highlighter.highlight(line.as_ref());
let line = if self.config.show_nonprintable {
replace_nonprintable(&line_buffer, self.config.tab_width)
} else {
match self.content_type {
Some(ContentType::BINARY) | None => {
return Ok(());
}
Some(ContentType::UTF_16LE) => UTF_16LE
.decode(&line_buffer, DecoderTrap::Replace)
.map_err(|_| "Invalid UTF-16LE")?,
Some(ContentType::UTF_16BE) => UTF_16BE
.decode(&line_buffer, DecoderTrap::Replace)
.map_err(|_| "Invalid UTF-16BE")?,
_ => String::from_utf8_lossy(&line_buffer).to_string(),
}
};
let regions = {
let highlighter = match self.highlighter {
Some(ref mut highlighter) => highlighter,
_ => {
return Ok(());
}
};
highlighter.highlight(line.as_ref(), self.syntax_set)
};
if out_of_range {
return Ok(());
@@ -225,6 +368,17 @@ impl<'a> Printer for InteractivePrinter<'a> {
let mut cursor_total: usize = 0;
let mut panel_wrap: Option<String> = None;
// Line highlighting
let highlight_this_line = self
.config
.highlight_lines
.iter()
.any(|&l| l == line_number);
let background_color = self
.background_color_highlight
.filter(|_| highlight_this_line);
// Line decorations.
if self.panel_width > 0 {
let decorations = self
@@ -243,43 +397,76 @@ impl<'a> Printer for InteractivePrinter<'a> {
if self.config.output_wrap == OutputWrap::None {
let true_color = self.config.true_color;
let colored_output = self.config.colored_output;
let italics = self.config.use_italic_text;
for &(style, region) in regions.iter() {
let text = &*self.preprocess(region, &mut cursor_total);
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
write!(
handle,
"{}",
as_terminal_escaped(style, &*text, true_color, colored_output,)
as_terminal_escaped(
style,
text_trimmed,
true_color,
colored_output,
italics,
background_color
)
)?;
if text.len() != text_trimmed.len() {
if let Some(background_color) = background_color {
let mut ansi_style = Style::default();
ansi_style.background = Some(to_ansi_color(background_color, true_color));
let width = if cursor_total <= cursor_max {
cursor_max - cursor_total + 1
} else {
0
};
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
}
write!(handle, "{}", &text[text_trimmed.len()..])?;
}
}
if line.bytes().next_back() != Some(b'\n') {
write!(handle, "\n")?;
writeln!(handle)?;
}
} else {
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();
for chunk in ansi_iterator {
match chunk {
// ANSI escape passthrough.
(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);
if text == "\x1B[0m" {
self.ansi_prefix_sgr = "\x1B[0m".to_owned();
} else {
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);
} else {
// It's probably a VT100 code.
// Passing it through is the safest bet.
write!(handle, "{}", text)?;
}
}
// Regular text.
(text, false) => {
let text = self.preprocess(
text.trim_right_matches(|c| c == '\r' || c == '\n'),
text.trim_end_matches(|c| c == '\r' || c == '\n'),
&mut cursor_total,
);
@@ -305,6 +492,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
),
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
)
)?;
break;
@@ -319,7 +508,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
.iter()
.map(|ref d| d
.generate(line_number, true, self)
.text).collect::<Vec<String>>()
.text)
.collect::<Vec<String>>()
.join(" ")
))
} else {
@@ -343,6 +533,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
),
self.config.true_color,
self.config.colored_output,
self.config.use_italic_text,
background_color
),
panel_wrap.clone().unwrap()
)?;
@@ -355,7 +547,18 @@ impl<'a> Printer for InteractivePrinter<'a> {
}
}
write!(handle, "\n")?;
if let Some(background_color) = background_color {
let mut ansi_style = Style::default();
ansi_style.background =
Some(to_ansi_color(background_color, self.config.true_color));
write!(
handle,
"{}",
ansi_style.paint(" ".repeat(cursor_max - cursor))
)?;
}
writeln!(handle)?;
}
Ok(())
+19 -9
View File
@@ -1,7 +1,7 @@
use std::collections::HashSet;
use std::str::FromStr;
use errors::*;
use crate::errors::*;
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum OutputComponent {
@@ -10,6 +10,7 @@ pub enum OutputComponent {
Grid,
Header,
Numbers,
Snip,
Full,
Plain,
}
@@ -21,22 +22,26 @@ pub enum OutputWrap {
}
impl OutputComponent {
pub fn components(&self, interactive_terminal: bool) -> &'static [OutputComponent] {
match *self {
OutputComponent::Auto => if interactive_terminal {
OutputComponent::Full.components(interactive_terminal)
} else {
OutputComponent::Plain.components(interactive_terminal)
},
pub fn components(self, interactive_terminal: bool) -> &'static [OutputComponent] {
match self {
OutputComponent::Auto => {
if interactive_terminal {
OutputComponent::Full.components(interactive_terminal)
} else {
OutputComponent::Plain.components(interactive_terminal)
}
}
OutputComponent::Changes => &[OutputComponent::Changes],
OutputComponent::Grid => &[OutputComponent::Grid],
OutputComponent::Header => &[OutputComponent::Header],
OutputComponent::Numbers => &[OutputComponent::Numbers],
OutputComponent::Snip => &[OutputComponent::Snip],
OutputComponent::Full => &[
OutputComponent::Changes,
OutputComponent::Grid,
OutputComponent::Header,
OutputComponent::Numbers,
OutputComponent::Snip,
],
OutputComponent::Plain => &[],
}
@@ -53,6 +58,7 @@ impl FromStr for OutputComponent {
"grid" => Ok(OutputComponent::Grid),
"header" => Ok(OutputComponent::Header),
"numbers" => Ok(OutputComponent::Numbers),
"snip" => Ok(OutputComponent::Snip),
"full" => Ok(OutputComponent::Full),
"plain" => Ok(OutputComponent::Plain),
_ => Err(format!("Unknown style '{}'", s).into()),
@@ -80,7 +86,11 @@ impl OutputComponents {
self.0.contains(&OutputComponent::Numbers)
}
pub fn snip(&self) -> bool {
self.0.contains(&OutputComponent::Snip)
}
pub fn plain(&self) -> bool {
self.0.is_empty()
self.0.iter().all(|c| c == &OutputComponent::Plain)
}
}
+35
View File
@@ -0,0 +1,35 @@
use std::borrow::Cow;
use std::collections::HashMap;
#[derive(Debug, Clone, Default)]
pub struct SyntaxMapping(HashMap<String, String>);
impl SyntaxMapping {
pub fn new() -> SyntaxMapping {
Default::default()
}
pub fn insert(&mut self, from: impl Into<String>, to: impl Into<String>) -> Option<String> {
self.0.insert(from.into(), to.into())
}
pub fn replace<'a>(&self, input: impl Into<Cow<'a, str>>) -> Cow<'a, str> {
let input = input.into();
match self.0.get(input.as_ref()) {
Some(s) => Cow::from(s.clone()),
None => input,
}
}
}
#[test]
fn basic() {
let mut map = SyntaxMapping::new();
map.insert("Cargo.lock", "toml");
map.insert(".ignore", ".gitignore");
assert_eq!("toml", map.replace("Cargo.lock"));
assert_eq!("other.lock", map.replace("other.lock"));
assert_eq!(".gitignore", map.replace(".ignore"));
}
+15 -47
View File
@@ -1,32 +1,21 @@
extern crate ansi_colours;
use ansi_term::Colour::{Fixed, RGB};
use ansi_term::{self, Style};
use syntect::highlighting::{self, FontStyle};
/// Approximate a 24 bit color value by a 8 bit ANSI code
fn rgb2ansi(r: u8, g: u8, b: u8) -> u8 {
const BLACK: u8 = 16;
const WHITE: u8 = 231;
if r == g && g == b {
if r < 8 {
BLACK
} else if r > 248 {
WHITE
} else {
((r - 8) as u16 * 24 / 247) as u8 + 232
}
} else {
36 * (r / 51) + 6 * (g / 51) + (b / 51) + 16
}
}
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)
} else {
let ansi_code = rgb2ansi(color.r, color.g, color.b);
Fixed(ansi_code)
Fixed(ansi_colours::ansi256_from_rgb((color.r, color.g, color.b)))
}
}
@@ -35,8 +24,10 @@ pub fn as_terminal_escaped(
text: &str,
true_color: bool,
colored: bool,
italics: bool,
background_color: Option<highlighting::Color>,
) -> String {
let style = if !colored {
let mut style = if !colored {
Style::default()
} else {
let color = to_ansi_color(style.foreground, true_color);
@@ -45,36 +36,13 @@ pub fn as_terminal_escaped(
color.bold()
} else if style.font_style.contains(FontStyle::UNDERLINE) {
color.underline()
} else if style.font_style.contains(FontStyle::ITALIC) {
} else if italics && style.font_style.contains(FontStyle::ITALIC) {
color.italic()
} else {
color.normal()
}
};
style.background = background_color.map(|c| to_ansi_color(c, true_color));
style.paint(text).to_string()
}
#[test]
fn test_rgb2ansi_black_white() {
assert_eq!(16, rgb2ansi(0x00, 0x00, 0x00));
assert_eq!(231, rgb2ansi(0xff, 0xff, 0xff));
}
#[test]
fn test_rgb2ansi_gray() {
assert_eq!(241, rgb2ansi(0x6c, 0x6c, 0x6c));
assert_eq!(233, rgb2ansi(0x1c, 0x1c, 0x1c));
}
#[test]
fn test_rgb2ansi_color() {
assert_eq!(96, rgb2ansi(0x87, 0x5f, 0x87));
assert_eq!(141, rgb2ansi(0xaf, 0x87, 0xff));
assert_eq!(193, rgb2ansi(0xd7, 0xff, 0xaf));
}
#[test]
fn test_rgb2ansi_approx() {
assert_eq!(231, rgb2ansi(0xfe, 0xfe, 0xfe));
}
+27
View File
@@ -0,0 +1,27 @@
/// Helper function that might appear in Rust stable at some point
/// (https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose)
pub fn transpose<T, E>(opt: Option<Result<T, E>>) -> Result<Option<T>, E> {
opt.map_or(Ok(None), |res| res.map(Some))
}
#[cfg(test)]
mod tests {
use super::transpose;
#[derive(Debug, PartialEq)]
struct TestError;
type TestResult<T> = Result<T, TestError>;
#[test]
fn basic() {
let a: Option<TestResult<i32>> = Some(Ok(2));
assert_eq!(Ok(Some(2)), transpose(a));
let b: Option<TestResult<i32>> = Some(Err(TestError));
assert_eq!(Err(TestError), transpose(b));
let c: Option<TestResult<i32>> = None;
assert_eq!(Ok(None), transpose(c));
}
}
+4
View File
@@ -0,0 +1,4 @@
examples/* linguist-vendored
snapshots/* linguist-vendored
benchmarks/* linguist-vendored
benchmarks/test-src/* linguist-vendored
-1
View File
@@ -1 +0,0 @@
test-src/* linguist-vendored
+2
View File
@@ -10,6 +10,7 @@ SRC="test-src/jquery-3.3.1.js"
cmd_bat="bat --style=full --color=always --paging=never '$SRC'"
cmd_bat_simple="bat --plain --wrap=never --tabs=0 --color=always --paging=never '$SRC'"
cmd_pygmentize="pygmentize -g '$SRC'"
cmd_highlight="highlight -O truecolor '$SRC'"
cmd_ccat="ccat --color=always '$SRC'"
@@ -20,6 +21,7 @@ cmd_rouge="rougify '$SRC'"
hyperfine --warmup 3 \
"$cmd_bat" \
"$cmd_bat_simple" \
"$cmd_pygmentize" \
"$cmd_highlight" \
"$cmd_ccat" \
+5
View File
@@ -0,0 +1,5 @@
# Make sure that the pager gets executed
--paging=always
# Output a dummy message for the integration test.
--pager="echo dummy-pager-from-config"
+1
View File
@@ -0,0 +1 @@
test
+1
View File
@@ -0,0 +1 @@
test
View File
+4
View File
@@ -0,0 +1,4 @@
line 1
line 2
line 3
line 4
+1
View File
@@ -0,0 +1 @@
Single Line
+9
View File
@@ -0,0 +1,9 @@
1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
+1
View File
@@ -0,0 +1 @@
hello world
Binary file not shown.
+495
View File
@@ -0,0 +1,495 @@
extern crate assert_cmd;
extern crate escargot;
#[macro_use]
extern crate lazy_static;
use assert_cmd::prelude::*;
use escargot::CargoRun;
use std::process::Command;
lazy_static! {
static ref CARGO_RUN: CargoRun = escargot::CargoBuild::new()
.bin("bat")
.current_release()
.run()
.unwrap();
}
fn bat_with_config() -> Command {
let mut cmd = CARGO_RUN.command();
cmd.current_dir("tests/examples");
cmd.env_remove("PAGER");
cmd.env_remove("BAT_PAGER");
cmd.env_remove("BAT_CONFIG_PATH");
cmd.env_remove("BAT_STYLE");
cmd.env_remove("BAT_THEME");
cmd.env_remove("BAT_TABS");
cmd
}
fn bat() -> Command {
let mut cmd = bat_with_config();
cmd.arg("--no-config");
cmd
}
#[test]
fn basic() {
bat()
.arg("test.txt")
.assert()
.success()
.stdout("hello world\n")
.stderr("");
}
#[test]
fn stdin() {
bat()
.with_stdin()
.buffer("foo\nbar\n")
.assert()
.success()
.stdout("foo\nbar\n");
}
#[test]
fn concatenate() {
bat()
.arg("test.txt")
.arg("test.txt")
.assert()
.success()
.stdout("hello world\nhello world\n");
}
#[test]
fn concatenate_stdin() {
bat()
.arg("test.txt")
.arg("-")
.arg("test.txt")
.with_stdin()
.buffer("stdin\n")
.assert()
.success()
.stdout("hello world\nstdin\nhello world\n");
}
#[test]
fn 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]
fn line_numbers() {
bat()
.arg("multiline.txt")
.arg("--style=numbers")
.arg("--decorations=always")
.assert()
.success()
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
}
#[test]
fn line_range_2_3() {
bat()
.arg("multiline.txt")
.arg("--line-range=2:3")
.assert()
.success()
.stdout("line 2\nline 3\n");
}
#[test]
fn line_range_first_two() {
bat()
.arg("multiline.txt")
.arg("--line-range=:2")
.assert()
.success()
.stdout("line 1\nline 2\n");
}
#[test]
fn line_range_last_3() {
bat()
.arg("multiline.txt")
.arg("--line-range=2:")
.assert()
.success()
.stdout("line 2\nline 3\nline 4\n");
}
#[test]
fn line_range_multiple() {
bat()
.arg("multiline.txt")
.arg("--line-range=1:2")
.arg("--line-range=4:4")
.assert()
.success()
.stdout("line 1\nline 2\nline 4\n");
}
#[test]
fn tabs_numbers() {
bat()
.arg("tabs.txt")
.arg("--tabs=4")
.arg("--style=numbers")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 1 2 3 4
2 1 ?
3 22 ?
4 333 ?
5 4444 ?
6 55555 ?
7 666666 ?
8 7777777 ?
9 88888888 ?
",
);
}
#[test]
fn tabs_passthrough_wrapped() {
bat()
.arg("tabs.txt")
.arg("--tabs=0")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn tabs_4_wrapped() {
bat()
.arg("tabs.txt")
.arg("--tabs=4")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn tabs_8_wrapped() {
bat()
.arg("tabs.txt")
.arg("--tabs=8")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn tabs_passthrough() {
bat()
.arg("tabs.txt")
.arg("--tabs=0")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn tabs_4() {
bat()
.arg("tabs.txt")
.arg("--tabs=4")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn tabs_8() {
bat()
.arg("tabs.txt")
.arg("--tabs=8")
.arg("--style=plain")
.arg("--decorations=always")
.assert()
.success()
.stdout(
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
",
);
}
#[test]
fn fail_non_existing() {
bat().arg("non-existing-file").assert().failure();
}
#[test]
fn fail_directory() {
bat().arg("sub_directory").assert().failure();
}
#[test]
fn do_not_exit_directory() {
bat()
.arg("sub_directory")
.arg("test.txt")
.assert()
.stdout("hello world\n")
.failure();
}
#[test]
fn pager_basic() {
bat()
.env("PAGER", "echo pager-output")
.arg("--paging=always")
.arg("test.txt")
.assert()
.success()
.stdout("pager-output\n");
}
#[test]
fn pager_overwrite() {
bat()
.env("PAGER", "echo other-pager")
.env("BAT_PAGER", "echo pager-output")
.arg("--paging=always")
.arg("test.txt")
.assert()
.success()
.stdout("pager-output\n");
}
#[test]
fn pager_disable() {
bat()
.env("PAGER", "echo other-pager")
.env("BAT_PAGER", "")
.arg("--paging=always")
.arg("test.txt")
.assert()
.success()
.stdout("hello world\n");
}
#[test]
fn config_location_test() {
bat_with_config()
.env("BAT_CONFIG_PATH", "bat.conf")
.arg("--config-file")
.assert()
.success()
.stdout("bat.conf\n");
}
#[test]
fn config_read_arguments_from_file() {
bat_with_config()
.env("BAT_CONFIG_PATH", "bat.conf")
.arg("test.txt")
.assert()
.success()
.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_with_config()
.arg("cache")
.assert()
.success()
.stdout("test\n")
.stderr("");
}
#[test]
fn can_print_file_starting_with_cache() {
bat_with_config()
.arg("cache.c")
.assert()
.success()
.stdout("test\n")
.stderr("");
}
#[test]
fn does_not_print_unwanted_file_named_cache() {
bat_with_config().arg("cach").assert().failure();
}
#[test]
fn snip() {
bat()
.arg("multiline.txt")
.arg("--style=numbers,snip")
.arg("--decorations=always")
.arg("--line-range=1:2")
.arg("--line-range=4:")
.arg("--terminal-width=80")
.assert()
.success()
.stdout(
" 1 line 1
2 line 2
...─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8< ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
4 line 4
",
);
}
+35
View File
@@ -0,0 +1,35 @@
mod tester;
use crate::tester::BatTester;
macro_rules! snapshot_tests {
($($test_name: ident: $style: expr,)*) => {
$(
#[test]
fn $test_name() {
let bat_tester = BatTester::new();
bat_tester.test_snapshot(stringify!($test_name), $style);
}
)*
};
}
snapshot_tests! {
changes: "changes",
grid: "grid",
header: "header",
numbers: "numbers",
changes_grid: "changes,grid",
changes_header: "changes,header",
changes_numbers: "changes,numbers",
grid_header: "grid,header",
grid_numbers: "grid,numbers",
header_numbers: "header,numbers",
changes_grid_header: "changes,grid,header",
changes_grid_numbers: "changes,grid,numbers",
changes_header_numbers: "changes,header,numbers",
grid_header_numbers: "grid,header,numbers",
changes_grid_header_numbers: "changes,grid,header,numbers",
full: "full",
plain: "plain",
}
-7
View File
@@ -17,13 +17,6 @@ def generate_snapshots():
for style in collective_styles:
generate_style_snapshot(style)
generate_snapshot("tabs_passthrough", "--tabs=0 --style=full --wrap=never")
generate_snapshot("tabs_passthrough_wrapped", "--tabs=0 --style=full --wrap=character")
generate_snapshot("tabs_4", "--tabs=4 --style=full --wrap=never")
generate_snapshot("tabs_4_wrapped", "--tabs=4 --style=full --wrap=character")
generate_snapshot("tabs_8", "--tabs=8 --style=full --wrap=never")
generate_snapshot("tabs_8_wrapped", "--tabs=8 --style=full --wrap=character")
def generate_style_snapshot(style):
generate_snapshot(style.replace(",", "_"), "--style={}".format(style))
+1 -15
View File
@@ -16,21 +16,7 @@ _ fn main() {
fn area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}
+
+ fn perimeter(rectangle: &Rectangle) -> u32 {
+ (rectangle.width + rectangle.height) * 2
+ }
+
// Tab alignment:
/*
Indent
1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
~ */
@@ -1,3 +1,4 @@
──┬─────────────────────────────────────────────────────────────────────────────
│ struct Rectangle {
│ width: u32,
│ height: u32,
@@ -16,22 +17,8 @@ _ │ fn main() {
│ fn area(rectangle: &Rectangle) -> u32 {
│ rectangle.width * rectangle.height
│ }
+
+ │ fn perimeter(rectangle: &Rectangle) -> u32 {
+ │ (rectangle.width + rectangle.height) * 2
+ │ }
+ │
│ // Tab alignment:
│ /*
│ Indent
│ 1 2 3 4
│ 1 ?
│ 22 ?
│ 333 ?
│ 4444 ?
│ 55555 ?
│ 666666 ?
│ 7777777 ?
│ 88888888 ?
~ │ */
──┴─────────────────────────────────────────────────────────────────────────────
@@ -19,22 +19,8 @@ _ │ fn main() {
│ fn area(rectangle: &Rectangle) -> u32 {
│ rectangle.width * rectangle.height
│ }
+
+ │ fn perimeter(rectangle: &Rectangle) -> u32 {
+ │ (rectangle.width + rectangle.height) * 2
+ │ }
+ │
│ // Tab alignment:
│ /*
│ Indent
│ 1 2 3 4
│ 1 ?
│ 22 ?
│ 333 ?
│ 4444 ?
│ 55555 ?
│ 666666 ?
│ 7777777 ?
│ 88888888 ?
~ │ */
──┴─────────────────────────────────────────────────────────────────────────────

Some files were not shown because too many files have changed in this diff Show More