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

Compare commits

...

319 Commits

Author SHA1 Message Date
sharkdp 732750c274 Bump version 2018-09-12 22:03:48 +02:00
sharkdp 6b6baa3118 Update dependencies 2018-09-12 22:01:27 +02:00
sharkdp 54c434934e Bump version, update assets 2018-09-12 22:01:01 +02:00
sharkdp ad6e0a2581 Update man page 2018-09-12 22:00:28 +02:00
sharkdp bd619db3ca Mention BAT_STYLE in README.md 2018-09-12 21:57:54 +02:00
sharkdp e098eb43a2 Do not show file header for directories
This also adds a better error message.

closes #292
2018-09-12 21:53:41 +02:00
David Peter ea369ee17f Merge pull request #298 from ms2300/bat_style
#208 Added BAT_STYLE env variable functionality
2018-09-12 21:48:34 +02:00
sharkdp 63d32bc818 Merge remote-tracking branch 'upstream/master' into bat_style 2018-09-12 21:40:41 +02:00
sharkdp dccf8d8221 Use a more streamlined version of style-component collection 2018-09-12 21:35:23 +02:00
sharkdp 97129ab9d8 Add PowerShell syntax, closes #306 2018-09-12 20:53:49 +02:00
David Peter 52d0d6ca30 Merge pull request #302 from eth-p/feature-tabs
Tab expansion support.

closes #166 
closes #184
2018-09-12 20:50:05 +02:00
sharkdp a05494e9d9 Make tests more robust 2018-09-12 20:32:49 +02:00
sharkdp 84ac92efbb Fix test for --style=plain 2018-09-12 20:32:33 +02:00
sharkdp b4c6e412dc Make generate_snapshots script more robust 2018-09-12 20:28:42 +02:00
sharkdp 3e21d69a92 Re-generate files again 2018-09-12 20:28:30 +02:00
sharkdp b7690d4bb1 Undo change in sample.modified.rs 2018-09-12 20:28:21 +02:00
eth-p d404139ff7 Added validation for --tabs.
Also added a comment to explain what 0 represents.
2018-09-12 10:08:58 -07:00
eth-p 9ef1e9f792 Update snapshots. 2018-09-11 15:04:44 -07:00
eth-p 503fe0b641 Fix sample.modified.rs 2018-09-11 15:03:13 -07:00
eth-p 1807f9653c Merge remote-tracking branch 'upstream/master' into feature-tabs
# Conflicts:
#	src/printer.rs
2018-09-11 14:03:47 -07:00
eth-p 1e74f0e2a9 Ran cargo fmt. 2018-09-11 13:47:35 -07:00
eth-p c1e1f753cf Added three new snapshot tests for --tabs and --wrap. 2018-09-11 13:47:01 -07:00
eth-p d90797f8e9 Fixed tab expansion not working in --wrap=never mode. 2018-09-11 13:45:49 -07:00
eth-p b4096e5627 Moved tab expansion to happen after syntax highlighting. 2018-09-11 13:02:22 -07:00
shik Chen 4e3ab4d399 Query git diff only when needed
In large git repo like chromium, it takes too long time to query git
diff.
2018-09-11 21:09:38 +02:00
rachitchokshi f0d936763c provide armhf deb packages (#301)
* Enabled deb packaging for armhf architecture

closes #280.
2018-09-11 21:03:53 +02:00
ms2300 7897260bf0 BAT_STYLE accounts for multiple styles (ie numbers,header) 2018-09-10 21:58:19 -06:00
eth-p eb6e43b9a9 Disabled tab expansion when decorations and pager are not used. 2018-09-10 20:12:13 -07:00
eth-p 7cdcdbb31d Updated snapshots. 2018-09-10 19:20:09 -07:00
eth-p 9159341714 Modified snapshot tests to support tab expansion.
This changes how the files are named (to allow for snapshots that aren't
directly related to the --style argument) and fixes the
generate_snapshots.py script to work with the latest version of bat.

Three new tests are also introduced:
- tabs_4 - Tab expansion with a width of 4.
- tabs_8 - Tab expansion with a width of 8.
- tabs_passthrough - No tab expansion.
2018-09-10 19:19:43 -07:00
eth-p b23ff24ebc Added tab expansion preprocessing step. 2018-09-10 18:11:59 -07:00
Rogach e1ecc17f69 print additional newline if last line in input file was not terminated with a newline (fixes #299) 2018-09-10 22:18:16 +02:00
rachitchokshi 0fe3badf19 adding deb packaging for arm64 (#1) 2018-09-10 21:24:15 +02:00
rachitchokshi 89d4cb951a Updated before_deploy.bash to call version of strip specific to aarch64 target 2018-09-10 21:24:15 +02:00
rachitchokshi e9681bf22d Testing build by removing dependency 'libz-sys = "1.0.20"' 2018-09-10 21:24:15 +02:00
rachitchokshi 1b6df8a480 Enabled build target aarch64-unknown-linux-gnu for arm64 architecture 2018-09-10 21:24:15 +02:00
ms2300 cf24986edb Run formatting for bat_style changes 2018-09-10 00:07:46 -06:00
ms2300 b9c556a0b6 Updated long help to reflect BAT_STYLE changes 2018-09-09 18:35:40 -06:00
ms2300 9d6bde48fa Added BAT_STYLE env variable functionality 2018-09-09 18:28:04 -06:00
Aankhen d6c8fee044 README.md: Add Using bat on Windows 2018-09-09 12:22:05 +02:00
sharkdp 8b4abb03db Run 'cargo fmt' 2018-09-08 09:52:21 +02:00
eth-p 375cf76e15 Formatted for newest rustfmt. 2018-09-08 09:52:21 +02:00
eth-p 1a4acc435e Typo 2018-09-08 09:52:21 +02:00
eth-p d8030626f8 Automatically disable wrapping when style is plain. 2018-09-08 09:52:21 +02:00
eth-p fb61aa4f60 Wrapping disabled when --plain is used. (#289) 2018-09-08 09:52:21 +02:00
Aankhen 76df41fa97 src/output.rs: Handle less in a portable way. 2018-09-07 21:47:31 +02:00
Miguel Madrid Mencía 97efd75cee Add Crystal syntax 2018-09-05 23:45:09 +02:00
Shreyansh Chouhan 53d0c1deca Can read files named "cache" now, cache subcommand working too (#275)
Now if a cache file exists in the current directory, and the user passes
no arguments to the cache command, the cache file would be displayed.
If however the user uses cache command with arguments, the cache command
would be executed as normal regardless of whether the file cache exists
in the current directory or not.

Though now there won't be an error message displayed if the user uses the cache sub command without arguments in any directory that contains a file named cache.
2018-09-05 23:22:12 +02:00
David Peter 155179a07a Update alternatives.md 2018-09-05 22:01:42 +02:00
sharkdp ba00caf9c3 Add Swift syntax 2018-09-05 21:56:49 +02:00
sharkdp ac418ba21c Add PureScript syntax 2018-09-05 21:50:16 +02:00
sharkdp acde83af31 Add note about 'lesspipe', closes #242 2018-09-05 21:44:53 +02:00
sharkdp 021a68eb21 Add F# syntax, closes #284 2018-09-05 21:38:35 +02:00
David Peter 566aab3b05 Merge pull request #279 from tobenna/add-jsx-syntax
Add support for JSX in javascript and typescript
2018-09-05 21:33:50 +02:00
sharkdp f88eba6476 Add section concerning missing zlib-devel
closes #229
2018-09-05 21:13:43 +02:00
sharkdp 1d9e7ac4c2 Support "(/usr)/bin/less" as PAGER too
closes #271
2018-09-05 21:10:11 +02:00
David Peter 80ae2ecbf8 Merge branch 'master' into add-jsx-syntax 2018-09-05 20:51:03 +02:00
David Peter 96d4492d27 Merge pull request #282 from tobenna/support-cabal-syntax
Syntax highlighting for .cabal
2018-09-05 20:44:25 +02:00
David Peter c90f0b8e21 Merge branch 'master' into support-cabal-syntax 2018-09-05 20:43:50 +02:00
David Peter 4b866ab6af Merge branch 'master' into add-jsx-syntax 2018-09-05 20:36:31 +02:00
Tobenna 2dbd91e543 Add Dart syntax 2018-09-05 20:33:16 +02:00
Tobenna Ndu 785da3d9df Add support for cabal syntax 2018-09-05 14:42:27 +01:00
Tobenna d455cb7c32 Add support for JSX in javascript and typescript 2018-09-05 08:49:33 +01:00
sharkdp d2b4766f92 Small README update 2018-09-04 08:25:24 +02:00
Roald 5cf92b4f94 Windows download with scoop 2018-09-04 08:23:38 +02:00
sharkdp 7b803a50af Ignore enable_ansi_support errors
- Call `enable_ansi_support` only once.
- Ignore errors that appear when trying to enable ANSI support. This
  will hopefully fix #252 and #264
2018-09-03 22:15:38 +02:00
sharkdp 67ec5fe2b7 Add OneHalf themes, closes #256 2018-09-03 22:12:41 +02:00
sharkdp 3447ed4def Add CSV syntax, closes #254 2018-09-03 21:49:26 +02:00
David Peter 532fb921a6 Update README.md 2018-09-01 00:59:30 +02:00
sharkdp ba4d5a2e7d Bump version number 2018-09-01 00:30:43 +02:00
sharkdp 026273a05c Enable ANSI support on Windows 2018-09-01 00:23:15 +02:00
sharkdp 8903b64830 Fix for Rust 1.26 2018-08-31 23:57:27 +02:00
sharkdp 194155f062 Fix relative-path computation for Windows 2018-08-31 23:57:27 +02:00
sharkdp a6ff3b900d Fix terminal width to 80 characters in tests 2018-08-31 23:57:27 +02:00
sharkdp 8a52bcf92d Add hidden --terminal-width option 2018-08-31 23:57:27 +02:00
sharkdp 0b1535f63b Split snapshot tests into individual tests 2018-08-31 23:57:27 +02:00
sharkdp 0a5b3eaf3e Re-enable tests on windows 2018-08-31 23:57:27 +02:00
sharkdp 11294249f8 Add new key for AppVeyor 2018-08-31 23:57:27 +02:00
anykao 35a1236ad0 Update tests.rs 2018-08-31 23:57:27 +02:00
anykao af8da50c2c Update appveyor.yml 2018-08-31 23:57:27 +02:00
anykao 649d1e3df2 Update appveyor.yml 2018-08-31 23:57:27 +02:00
anykao 199cfd4519 Update appveyor.yml 2018-08-31 23:57:27 +02:00
David Peter c7cce0752b Add AppVeyor badge 2018-08-31 23:57:27 +02:00
anykao 3a89486189 Create before_deploy.ps1 2018-08-31 23:57:27 +02:00
anykao 720a2fb7a5 Create appveyor.yml 2018-08-31 23:57:27 +02:00
sharkdp e3c990f11e Respect color settings for list-themes and list-languages 2018-08-31 21:57:18 +02:00
sharkdp 90c7d0c365 Use stdout locks 2018-08-31 21:48:26 +02:00
mchlrhw 56002267d2 Fix panic when running bat --list-languages | head
Fixes: https://github.com/sharkdp/bat/issues/232
2018-08-31 21:43:49 +02:00
David Peter 84734eac9d Update alternatives.md 2018-08-31 00:39:26 +02:00
sharkdp acdea97e71 Add --plain 2018-08-28 23:37:49 +02:00
sharkdp 839e4ee611 Bump version 2018-08-28 23:21:35 +02:00
sharkdp c7afcdebf8 Move theme_preview file to constant 2018-08-28 22:16:42 +02:00
sharkdp 08e6db1581 Add Troubleshooting section
see #220
2018-08-28 22:08:34 +02:00
sharkdp 4d08ecd828 Fix headline levels 2018-08-28 21:04:41 +02:00
sharkdp 28e1d0e613 Add development section to README 2018-08-28 21:03:03 +02:00
sharkdp d11839ad03 Update install instructions 2018-08-28 20:55:15 +02:00
sharkdp 8cacd9b432 Include theme_preview file in binary 2018-08-28 20:24:13 +02:00
sharkdp 6f67444c99 Run cargo fmt 2018-08-28 20:24:13 +02:00
sharkdp fd2b376ea0 Small style changes to --list-themes 2018-08-28 20:24:13 +02:00
sharkdp cda54e4f61 Fix build for Rust 1.26 2018-08-28 20:24:13 +02:00
ms2300 3b90ada735 Mutation done correctly 2018-08-28 20:24:13 +02:00
ms2300 1837d364fe Added bold to theme titles 2018-08-28 20:24:13 +02:00
ms2300 4ea3e6bbb7 Changed preview code 2018-08-28 20:24:13 +02:00
ms2300 38544ed735 Changed to plain style 2018-08-28 20:24:13 +02:00
ms2300 5444b0dfed Fixes mut issue 2018-08-28 20:24:13 +02:00
ms2300 f3dde0185d Modifying changing config for efficiency 2018-08-28 20:24:13 +02:00
ms2300 2e3784aa30 #213 : output hello world for each theme when --list-theme is flagged 2018-08-28 20:24:13 +02:00
sharkdp 1088455702 Add syntaxes for Elm, Kotlin, Puppet, TypeScript
closes #215
closes #216
closes #217
closes #218
2018-08-28 19:36:31 +02:00
Colin Dean 4f812c32ab Adds zenburn theme submodule
Work towards #224 but @sharkdp is going to rebuild themes.bin
2018-08-28 07:37:27 +02:00
sharkdp b6c59a5bd4 Add man page to releases 2018-08-27 23:10:14 +02:00
sharkdp b682679776 Add initial version of man page, see #52 2018-08-27 22:57:47 +02:00
ms2300 81771432fb #212 : added -p as an alias for --style=plain 2018-08-27 17:56:50 +02:00
sharkdp 627181bcb6 Always call the syntax highlighter 2018-08-23 23:35:57 +02:00
sharkdp 226d9a573a Add simple loop-through mode
Use a loop-through mode that simply copies input to output if a
non-interactive terminal is detected.

see #150
2018-08-23 23:13:24 +02:00
sharkdp 246cf79dbd Split into Controller and Printer 2018-08-23 22:37:27 +02:00
sharkdp ea955c734d Refactoring, introduce Printer trait 2018-08-23 19:44:14 +02:00
sharkdp 6223ad6d52 Document Config struct 2018-08-22 22:36:59 +02:00
sharkdp 31a9335bd5 Document Config struct 2018-08-22 22:36:37 +02:00
sharkdp 9316f2a758 Major refactoring and cleanup 2018-08-22 22:29:12 +02:00
sharkdp c884c3cc12 Re-order options in help texts 2018-08-22 19:34:30 +02:00
sharkdp 08850f0474 Update the --help text 2018-08-22 19:27:11 +02:00
Tim Sampson 8e6c5bc562 doc: mention BAT_THEME in help output 2018-08-22 18:14:01 +02:00
sharkdp 052425b12f Load customized themes in addition to defaults
- New themes in `$BAT_CONFIG_DIR/themes` are now loaded *in addition* to
  the default themes (they may also override).
- The `Default.tmTheme` symlink is not necessary anymore.

This relates to #172
2018-08-20 21:39:21 +02:00
sharkdp 2df3305b94 Add new '--blank' option for 'bat cache --init'
closes #206
2018-08-20 21:34:08 +02:00
sharkdp 6882fc1512 Clean up help messages 2018-08-20 21:34:08 +02:00
sharkdp 2508323264 Extract grid and line-number color from theme
This changes the output color of the grid and the line numbers to use
the "gutter" foreground color defined in the Sublime `.tmTheme` files.

Sublime Text does the same.

Note: we could go one step further and also extract the "GitGutter"
colors from the themes. These could be used instead of red/green/yellow
to signify Git modifications. The problem is that they are quite a bit
harder to extract from the syntect `Theme` object.

closes #178
2018-08-19 12:32:35 +02:00
sharkdp 297afad337 Bump version 2018-08-19 12:31:35 +02:00
sharkdp 1dddce3aa1 Separate syntax set and theme set
This commit separates the handling of syntax sets and theme sets. It
also changes the way how new syntax definitions are loaded from `bat`'s
configuration folder. New syntax definitions are now loaded *in
addition* to the ones that are stored in the `bat` binary by default.

This fixes #172
2018-08-19 11:08:23 +02:00
sharkdp 76be0d3933 Add arm as a compile target 2018-08-19 09:50:24 +02:00
sharkdp e5b8c4471a Bump minimum required rust version 2018-08-18 21:30:12 +02:00
sharkdp b191691767 Revert "replace trait object BufRead by generic"
This reverts commit 037861e588.
2018-08-18 21:25:58 +02:00
Michal Nazarewicz 5c95b8803b Avoid floating point arithmetic in RGB→8-bit ANSI approximation 2018-08-18 20:58:03 +02:00
sharkdp 5b421b455d Update dependencies 2018-08-18 20:44:25 +02:00
sharkdp a6d6c28723 Add documentation on new pager-customization 2018-08-18 20:22:11 +02:00
sharkdp 2966939e38 Update submodules 2018-08-18 19:30:35 +02:00
sharkdp d179693d1d Use BAT_PAGER and PAGER environment variables, closes #158 2018-08-18 18:48:22 +02:00
sharkdp 268577c6f9 Run 'cargo fmt' 2018-08-18 17:54:26 +02:00
TA Thanh Dinh 037861e588 replace trait object BufRead by generic 2018-08-18 17:54:26 +02:00
sharkdp 94ccc646e8 Update README 2018-07-23 21:58:06 +02:00
sharkdp 0cc5d1dab6 Update error-chain to fix compiler warnings 2018-07-23 21:54:30 +02:00
sharkdp 28397b8f78 Always show a warning when theme is unknown 2018-07-23 21:51:49 +02:00
sharkdp c899849101 Use map instead of and_then(..Some(..)) 2018-07-23 21:51:49 +02:00
sharkdp bf53b64125 Small style fix 2018-07-23 21:51:49 +02:00
Armando Perez c68aa0f424 Allow specifying the theme via the BAT_THEME environment variable
The `--theme` command line option stills takes precedence and this
change preserves how errors are handled when it's used: If a theme name
that doesn't exist is specified using the argument, this error is fatal.
However, if a theme that doesn't exist is specified using the environment
variable, the error is logged to `stderr` and the "Default" theme is
loaded as a fallback.
2018-07-23 21:51:49 +02:00
sharkdp 6b57f4eebc Style changes 2018-07-18 00:06:24 +02:00
eth-p 0ddd388a29 Improve logic for SGR sequence passthrough 2018-07-18 00:06:24 +02:00
eth-p 34811b8161 Fix #182 2018-07-18 00:06:24 +02:00
David Peter 8b92aae23f Fix Travis link 2018-07-17 23:37:03 +02:00
sharkdp 3a0941cabe Update syntaxes.bin 2018-07-17 23:28:44 +02:00
sharkdp 52877c6d67 Add Nix syntax, closes #180 2018-07-17 23:28:31 +02:00
sharkdp 455de98a89 Update sublimehq/Packages, closes #183 2018-07-17 23:27:19 +02:00
Stéphane Campinas 8c6a74a6c5 typo 2018-07-06 19:09:53 +02:00
Gert Hulselmans 3f8b340ed8 Add AWK syntax. 2018-06-15 16:41:51 +02:00
sharkdp 65e6970907 Change help text for --line-range 2018-06-12 08:18:44 +02:00
sharkdp 90cc019482 Run 'cargo fmt' 2018-06-12 08:18:44 +02:00
Taylor eaf0b99d25 update 2018-06-12 08:18:44 +02:00
Taylor Skinner 3b1dcca5d0 use map() 2018-06-12 08:18:44 +02:00
Taylor Skinner 26dbdf4fa0 update line-ranges 2018-06-12 08:18:44 +02:00
Taylor Skinner 6691786d82 add line-range 2018-06-12 08:18:44 +02:00
Conrad Kleinespel 50209bfe21 updates archlinux install instructions 2018-06-08 16:15:27 +02:00
sharkdp c91511cca1 Always run snapshot test 2018-06-02 19:03:38 +02:00
sharkdp c9f7a0c126 Use separate Git repository for snapshot testing
closes #161
2018-06-02 19:00:05 +02:00
Ezinwa Okpoechi 69c798eafd Fix command typo 2018-06-01 17:01:28 +02:00
sharkdp 195d5e0e16 Update Cargo.lock 2018-06-01 00:35:20 +02:00
sharkdp 86c1777205 Skip snapshot test if Git is not available
closes #161
2018-06-01 00:33:39 +02:00
sharkdp 16874ab016 Exclude assets from upload 2018-05-31 23:49:02 +02:00
sharkdp bf5883f06f Updates for 0.4 2018-05-31 22:57:18 +02:00
sharkdp e27bdfc7d6 Fix clippy warnings 2018-05-31 15:27:55 +02:00
David Peter a7f4f202cb Update README.md 2018-05-30 21:32:40 +02:00
David Peter 397223374a Add TOC 2018-05-30 21:23:24 +02:00
David Peter 0c2da90fa4 Change color of crates.io badge 2018-05-30 21:10:14 +02:00
David Peter fe29da6e76 Add license badge 2018-05-30 21:02:40 +02:00
sharkdp 0eccfb50d9 Update header 2018-05-30 20:54:46 +02:00
sharkdp f74263e71d Update syntect 2018-05-30 20:50:50 +02:00
sharkdp 54f4896ced Update syntaxes, fix CMake syntax problem 2018-05-30 20:43:50 +02:00
sharkdp 9d92350cbb Use default Markdown syntax, closes #157 2018-05-30 20:40:02 +02:00
sharkdp 26d409db65 Add 'rouge' to list of alternatives 2018-05-30 19:24:30 +02:00
sharkdp 06cd4b2ce8 Add 'coderay' to list of alternatives 2018-05-30 19:16:08 +02:00
sharkdp a348a9f68e Handle syntax-set loading errors 2018-05-25 22:42:06 +02:00
sharkdp 39e2971e96 Add .ignore files to avoid searching asset folders 2018-05-25 17:44:50 +02:00
TA Thanh Dinh a13eb60df3 Using slice notation instead of as_ref 2018-05-25 17:38:54 +02:00
sharkdp 9342d0bb24 Explicitly specify which args override themselves 2018-05-24 22:53:23 +02:00
sharkdp 36d7250af2 Allow arguments to override themselves 2018-05-24 22:53:23 +02:00
Ezinwa Okpoechi 2ce8655167 Build bat before generating snapshots 2018-05-24 19:10:24 +02:00
Ezinwa Okpoechi a452467e06 Remove unnecessary space if there are no decorations 2018-05-24 19:10:24 +02:00
Ezinwa Okpoechi 2ea3758c4b Justify header when there are decorations but no grid 2018-05-24 19:10:24 +02:00
Gert Hulselmans 65bb4c7ee6 Print themes directory in error message if no themes could be loaded from it.
Before this patch:
    $ bat cache --init
    [bat error]: Could not load themes from '{}'

After:
    $ bat cache --init
    [bat error]: Could not load themes from '/home/user/.config/bat/themes'
2018-05-24 09:09:23 +02:00
sharkdp 556149ad3a Add comparison benchmark 2018-05-22 23:32:46 +02:00
Gert Hulselmans 33bbf25468 Fix launching of pager so text is interpreted as UTF-8 by default.
This fixes issue https://github.com/sharkdp/bat/issues/98
2018-05-22 22:41:58 +02:00
sharkdp 5ee8913538 Add logo header to README 2018-05-22 22:39:20 +02:00
David Peter 9b1c1c0271 Add more benchmark results 2018-05-22 22:27:25 +02:00
Ezinwa Okpoechi 2712d63a4b Move asset clearing to assets module 2018-05-21 23:20:45 +02:00
Ezinwa Okpoechi b21fb6bca8 Extract features to separate module 2018-05-21 23:20:45 +02:00
Ezinwa Okpoechi ee43377a9c Move colors to printer module 2018-05-21 19:24:02 +02:00
Ezinwa Okpoechi 120b33a9db Move output to separate module 2018-05-21 19:24:02 +02:00
sharkdp 17b37fedcb Add project goals and list of alternatives 2018-05-21 00:28:30 +02:00
sharkdp 1013cdd80a Bump version 2018-05-19 17:55:07 +02:00
sharkdp be0a2d6048 Extended help texts for '--help' 2018-05-19 17:54:05 +02:00
sharkdp d1a1943998 Add -u and -n options, see #134 2018-05-19 16:58:45 +02:00
sharkdp 2a9f5a24ed Permissive error handling, closes #17 2018-05-19 12:50:41 +02:00
sharkdp a0ae089c4a Reset line number to 0 for new files 2018-05-19 12:25:07 +02:00
sharkdp 96cc391f2d Skip '--quit-if-one-screen' for --paging=always
closes #97
2018-05-19 10:54:54 +02:00
sharkdp a1e1170319 Add a few popular Sublime Text themes 2018-05-18 20:41:40 +02:00
sharkdp 54a331d162 Add syntax docu, add VimL, CMake, INI, LESS syntax
closes #99
closes #106
2018-05-18 19:57:58 +02:00
sharkdp 5e3b17e6f7 Fix code formatting 2018-05-18 17:44:43 +02:00
eth-p 486e6a19cd Fixed #124 2018-05-18 17:44:43 +02:00
Ezinwa Okpoechi 247dfbee83 Extract syntax finding to assets module 2018-05-18 16:45:59 +02:00
Ezinwa Okpoechi 882931a77b Update snapshots 2018-05-18 16:44:34 +02:00
Ezinwa Okpoechi 12cb438aa4 Handle line with invalid UTF-8 2018-05-18 16:44:34 +02:00
Ezinwa Okpoechi d0782ef954 Add line with invalid UTF-8 2018-05-18 16:44:34 +02:00
sharkdp c826c2a438 Better error handling 2018-05-16 22:55:37 +02:00
sharkdp 9aa97b6c22 Update to latest syntect, closes #100 2018-05-16 22:55:37 +02:00
sharkdp f7890870ea Add syntax for Dockerfiles
closes #101
2018-05-16 22:04:12 +02:00
sharkdp 145b99f01c Include syntaxes and themes in repository
This changes a few things:

- All syntaxes and themes are now stored (as submodules) under
  assets/syntaxes and assets/themes

- The default directories for syntaxes and themes are "syntaxes"
  and "themes" (used to be "syntax" and "themes")

- The "bat cache" command can now take a `--source <dir>` and
  `--target <dir>` option.

- The cached files have been renamed to "themes.bin" and "syntaxes.bin"
2018-05-16 22:04:12 +02:00
Mateusz Piotrowski 9af1d2b891 Add FreeBSD installation instructions
Closes #41.
2018-05-16 20:25:14 +02:00
David Peter 2eee68599d Merge pull request #102 from eth-p/master
Added text wrapping. (Fixes #54)
2018-05-16 08:41:49 +02:00
eth-p d569693dab Formatted with newer cargo fmt.
It should pass all the checks now.
2018-05-16 08:29:41 +02:00
eth-p 900f61032d Fix #117 2018-05-15 14:09:51 -07:00
eth-p d0ca566979 Replace for_line and for_wrap with generate 2018-05-15 13:55:38 -07:00
eth-p a5a7dc14e4 Fix \r character being printed with wrapping enabled. 2018-05-14 14:36:08 -07:00
sharkdp 54b33c8c21 Add simple benchmark scripts 2018-05-14 22:20:26 +02:00
rleungx a5de77af4d address comment 2018-05-14 20:30:16 +02:00
rleungx 870ff7b538 sort the language listing 2018-05-14 20:30:16 +02:00
sharkdp 15b9acd12f Updates for new rustfmt 2018-05-14 19:04:13 +02:00
eth-p b327127f37 Split decorations into a separate file and optimized them a bit. 2018-05-13 18:44:07 -07:00
eth-p 9214a4a4f0 PR #102 Followed @sharkdp's suggestions 2018-05-13 12:45:16 -07:00
sharkdp fcecd97224 Add ansi_term import for Windows, see #107 2018-05-13 21:19:26 +02:00
eth-p 870b3c0daf PR #102 Followed @BrainMaestro's suggestions
Also ran cargo fmt.
2018-05-13 03:26:23 -07:00
sharkdp b9c780c8c8 Ignore errors when clearing cache, closes #91 2018-05-13 10:34:35 +02:00
sharkdp ca865f9d26 Enable ANSI support on Windows 10 2018-05-13 09:58:16 +02:00
sharkdp 3ee0e56315 Update create.sh script 2018-05-13 09:53:30 +02:00
Eric Davies 091b0b6437 Add Julia highlighting support 2018-05-13 09:53:00 +02:00
eth-p 9f005d115d Update snapshot test files. 2018-05-12 14:04:54 -07:00
eth-p b4cfc9633c Fix double spaces when outputting without wrapping. 2018-05-12 14:02:47 -07:00
eth-p f7e055b6b7 Merge branch 'master' of https://github.com/sharkdp/bat 2018-05-12 14:00:25 -07:00
eth-p d4b438b9d3 Fix padding, add --wrap argument, disable wrap for non-tty. (Fixed)
I'm not quite sure what was up with git on that last commit, but it's
all properly committed now.
2018-05-12 13:44:10 -07:00
eth-p cd26d403a3 Fix padding, add --wrap argument, disable wrap for non-tty.
Now bat(1) can be used like cat(1) again!
2018-05-12 13:23:33 -07:00
eth-p f95a23f948 Fix off-by-one error with text wrapping and --style grid 2018-05-12 12:07:41 -07:00
Ezinwa Okpoechi 0886a24685 Add snapshot testing 2018-05-12 18:07:30 +02:00
Ezinwa Okpoechi 53eb9c57d6 Add generated snapshots 2018-05-12 18:07:30 +02:00
Ezinwa Okpoechi 026a9ebae3 Add sample files and snapshot generator 2018-05-12 18:07:30 +02:00
Ethan P bdd10b8bec Merge branch 'master' into master 2018-05-12 06:40:47 -07:00
eth-p fc160b0dcd PR #102 Review Changes
- Reformatted code.
- Removed leftover code.
- Removed leftover comments.
- Fixed compiling on Rust 1.24.0
2018-05-12 06:32:23 -07:00
sharkdp cb7b158172 Add bold, italic and underline font styles 2018-05-12 13:23:39 +02:00
eth-p fcc36b1f79 Forgot to add styling to the horizontal line. 2018-05-11 22:49:26 -07:00
eth-p 4e4110bf50 Added line wrapping. 2018-05-11 21:59:26 -07:00
Ryan Leung 22c8978fca add theme option (#95)
closes #89
2018-05-11 13:53:17 +02:00
Ezinwa Okpoechi f711fb5006 Split style to separate module 2018-05-11 10:15:26 +02:00
Ezinwa Okpoechi 64a9341b73 Split app to separate module 2018-05-11 10:15:26 +02:00
sharkdp ccf88fd5d8 Add and use --style=auto by default 2018-05-10 16:22:24 +02:00
David Peter 6343535eb2 Add 32bit support (#87)
* Add 32bit support, closes #84
* Remove error-chain backtrace support
2018-05-10 14:36:05 +02:00
sharkdp e2ac6de783 Fix clippy warnings 2018-05-10 13:15:59 +02:00
Ezinwa Okpoechi 25cee002f9 Split modules (#86)
* Split diffing to separate module
* Split assets to separate module
2018-05-10 12:36:09 +02:00
sharkdp 13a53d230b Add MacOS install instructions, closes #33 2018-05-10 12:35:07 +02:00
sharkdp ea27053a63 Remove unused lifetimes 2018-05-10 12:20:38 +02:00
Pit Kleyersburg b2b932f3ed Fix header-line if grid is not requested 2018-05-10 12:20:38 +02:00
Pit Kleyersburg 747d074be1 Replace Cow by String 2018-05-10 12:20:38 +02:00
Pit Kleyersburg 61109ece15 Create OutputComponents struct, use HashSet 2018-05-10 12:20:38 +02:00
Pit Kleyersburg 389edd7239 Combine OutputComponents and PredefinedStyles
This commit tries to simply the change. Instead of separating an
`OutputComponent` and a `PredefinedStyle`, I have combined the two into
just `OutputComponent`.

To still have the styles work, I added an impl to `OutputComponent` with
a function `components` which returns the components related to the
specified component.

For a simple output component this is trivial, but for the predefined
styles this is a list of other components.

The evaluating of the command-line parameter simplified significantly,
making use of Claps `values_t!` macro to parse the supplied parameters
into a `Vec<OutputComponent>`. After that it is simply a task of
combining all supplied output components into one vector.

Important: this means that the styles are now additive, rather than one
of the predefined styles overruling other parameters supplied.
2018-05-10 12:20:38 +02:00
Pit Kleyersburg 23813cc08b Make --style parameter more flexible
The `--style` parameter now accepts a comma-separated list of strings,
where every element defines either a single output component (`changes`,
`grid`, `header`, `numbers`) or a predefined style (`full`,
`line-numbers`, `plain`).

If available, bat picks the first predefined style in the user-supplied
style-list and ignores everything else. If no predefined style was
requested, the other parameters that are simple output components will
be used.

Examples:

    --style changes,full,numbers

  Will internally be reduced to only the predefined style `full`.

    --style plain,full

  Will internally be reduced to only the predefined style `plain`.

    --style changes,numbers

  Will not be reduced, because the list does not contain any predefined
  styles.

(Note: if `grid` is requested but no other parameters, bat still creates
the left-most column with a width of `PANEL_WIDTH`. I didn't want to
introduce further logic in this PR that drops or adapts the width of the
left column.)
2018-05-10 12:20:38 +02:00
David Peter fdeb98e859 Add usage examples 2018-05-09 00:33:49 +02:00
David Peter 6a417886aa Add comment about paging & concatenation 2018-05-09 00:12:25 +02:00
sharkdp 8b9991d780 Append newline at the end of the file if necessary 2018-05-08 23:49:59 +02:00
sharkdp f59ddd1e36 Update dependencies 2018-05-08 23:49:07 +02:00
sharkdp f90b9d1acc Do not peek at FIFOs, closes #80 2018-05-08 23:23:41 +02:00
sharkdp f7af537018 Filter out languages without extensions 2018-05-08 22:57:29 +02:00
sharkdp fd68af8031 Paint file extensions in green 2018-05-08 22:57:29 +02:00
sharkdp ebdef04c8f Compute 'longest' for non-hidden languages only 2018-05-08 22:57:29 +02:00
sharkdp a4150600af Correctly update num_chars 2018-05-08 22:57:29 +02:00
Connor Kuehl 49223eed06 Remove term_width from Printer, its options owns it. 2018-05-08 22:57:29 +02:00
Connor Kuehl 7dc7133b3c Add revisions for line-wrapping and terminal width.
* Adds separator.length() to calculation for desired width.
* Replaces use of term_width with options.term_width.
* Adds the comma and space separator to calculation for line-wrapping.
2018-05-08 22:57:29 +02:00
Connor Kuehl e5e47716b0 Add term_width to options struct, move getting term_width to run() 2018-05-08 22:57:29 +02:00
Connor Kuehl b4f8cd3bae Filter out languages that are hidden. 2018-05-08 22:57:29 +02:00
Connor Kuehl ee3a37f3fc WIP edit desired width. 2018-05-08 22:57:29 +02:00
Connor Kuehl 4c60ab12cc Add simple line-wrapping for file extensions. 2018-05-08 22:57:29 +02:00
Connor Kuehl ac32dd17c9 Adds requested revisions.
* removes redundant `.takes_value(false)`.
* changes Arg name to "list-languages" to be consistent with long-form.
* replaces unnecessary match statement with is_present().
* replaces unnecessary match statement on iter and uses unwrap_or()
instead.
* replaces for-loop with a call to join().
2018-05-08 22:57:29 +02:00
Connor Kuehl 4e3c57cc7c Rename and add comment to the match block. 2018-05-08 22:57:29 +02:00
Connor Kuehl 438a9a99ed Size language name column width to the length of the longest language. 2018-05-08 22:57:29 +02:00
Connor Kuehl 9b0877102c Display language and extensions from loaded assets. 2018-05-08 22:57:29 +02:00
Connor Kuehl 67bed73e15 Add --list-languages argument to clap. 2018-05-08 22:57:29 +02:00
sharkdp ef7c39b159 Improve cache subcommand
* Remove the old `init-cache` subcommand

* Introduce a new `cache` subcommand that can be used like this:

    * `bat cache -h` - Show help
    * `bat cache --init` - Initialize cache from config dir
    * `bat cache --clear` - Reset the cache
    * `bat cache --config-dir` - Show config directory

* Update README

closes #44
2018-05-08 20:11:25 +02:00
sharkdp 8a399c8d7d Disable paging-mode if we read from an interactive TTY 2018-05-07 23:27:38 +02:00
sharkdp 9a0e444e09 Simplify stdout handling 2018-05-07 23:27:38 +02:00
sharkdp 438f3df345 Paint STDOUT bold, unify writeln statement 2018-05-07 23:27:38 +02:00
sharkdp 7e2e0c82ac Add support for reading from stdin, closes #2 2018-05-07 23:27:38 +02:00
sharkdp da92154163 Re-format README 2018-05-07 20:06:01 +02:00
sharkdp 179bd4f525 Mention cmake in build instructions, closes #57 2018-05-07 20:03:56 +02:00
Ezinwa Okpoechi 53d67e2b6e Add printer
This adds a separate struct that handles printing of the different
tokens.
2018-05-07 08:57:21 +02:00
sharkdp b625d07c34 Use syntect newlines mode (instead of nonewlines) 2018-05-06 19:50:48 +02:00
Ezinwa Okpoechi ec606e5dcc Add option to disable automatic paging 2018-05-06 19:50:05 +02:00
Ezinwa Okpoechi c253821a5e Open pager once for multiple files 2018-05-06 19:50:05 +02:00
sharkdp ccb1d78b22 Remove short versions for --style and --color for now 2018-05-06 18:23:43 +02:00
sharkdp 9eb64b97fe Discover syntaxes by name and extention 2018-05-06 18:20:35 +02:00
sharkdp 15f0268bdc Use 'plain' style for non-interactive terminals 2018-05-06 16:15:22 +02:00
sharkdp 3fa70deaa7 Run 'cargo fmt' and enforce via Travis 2018-05-06 15:10:46 +02:00
Ezinwa Okpoechi d4553c6b38 Add color flag
Colors are disabled if the terminal is not interactive unless explicitly
set otherwise
2018-05-06 14:47:53 +02:00
sharkdp 23d92d7641 Add TOML sublime syntax, closes #37 2018-05-06 14:34:10 +02:00
sharkdp 92729430fc Add elixir sublime syntax 2018-05-06 14:26:58 +02:00
sharkdp 3eb79d63ce Compute pathspec from absolute.strip_prefix(workdir) 2018-05-06 11:22:48 +02:00
Nakul Chaudhari 0483407775 Remove user specific change 2018-05-06 11:22:48 +02:00
Nakul Chaudhari cbdf5c50c4 Fix bug where git modification markers would not be shown if directory
was not cwd

Git ignore Idea dir

Fix #22
2018-05-06 11:22:48 +02:00
Ezinwa Okpoechi 418b3c5ea1 Add less pager 2018-05-05 09:01:30 +02:00
Nakul Chaudhari 9dca3126b3 Hide everything but content for plain option style
fix #5
2018-05-03 22:49:37 +02:00
nakulcg 7df9a5fe82 Add --style option to disable line numbers and git markers (#43)
closes #5
2018-05-03 20:34:23 +02:00
Ezinwa Okpoechi 4bba08062c Add option to specify language 2018-05-03 17:00:35 +02:00
sharkdp 4e8ea815af Bump version 2018-05-03 09:07:58 +02:00
sharkdp b7bc2d54ba Add statically-linked version of bat, closes #46 2018-05-03 09:07:00 +02:00
bspeice 21f9e2b0f7 Bump minimum required version to 1.24
#40
2018-05-03 08:22:31 +02:00
David Peter 92aa2b547e Update README.md 2018-05-02 23:29:52 +02:00
sharkdp 65f66d0bee Small update to README 2018-05-02 22:21:56 +02:00
sharkdp f5a9236a47 Bump version 2018-05-02 22:03:43 +02:00
sharkdp edbe8f3e1a Remove openssl dependency 2018-05-02 20:45:07 +02:00
sharkdp ed09a80a73 Bump version to 0.2.1 2018-05-01 12:46:33 +02:00
sharkdp 802540ea08 Add test-output 2018-05-01 10:45:51 +02:00
sharkdp dbf84e77e0 Use openssl 2018-05-01 10:45:51 +02:00
Wesley Moore 8f18567f2d Add Arch Linux installation instructions to README 2018-05-01 10:04:14 +02:00
David Peter e4d7e004ee Update README.md 2018-05-01 09:25:13 +02:00
sharkdp 51b57ccdb7 Update syntax_set, closes #25, fixes #28 2018-05-01 09:23:04 +02:00
sharkdp 25f83610f9 Remove explicit bincode dependency 2018-04-30 20:11:21 +02:00
113 changed files with 26799 additions and 840 deletions
+93
View File
@@ -0,0 +1,93 @@
[submodule "assets/syntaxes/Elixir"]
path = assets/syntaxes/Elixir
url = https://github.com/princemaple/elixir-sublime-syntax/
[submodule "assets/syntaxes/Packages"]
path = assets/syntaxes/Packages
url = https://github.com/sublimehq/Packages/
[submodule "assets/syntaxes/TOML"]
path = assets/syntaxes/TOML
url = https://github.com/sharkdp/sublime_toml_highlighting
[submodule "assets/syntaxes/Julia"]
path = assets/syntaxes/Julia
url = https://github.com/JuliaEditorSupport/Julia-sublime
[submodule "assets/themes/sublime-monokai-extended"]
path = assets/themes/sublime-monokai-extended
url = https://github.com/jonschlinkert/sublime-monokai-extended
[submodule "assets/syntaxes/Docker"]
path = assets/syntaxes/Docker
url = https://github.com/asbjornenge/Docker.tmbundle
[submodule "assets/syntaxes/VimL"]
path = assets/syntaxes/VimL
url = https://github.com/SalGnt/Sublime-VimL
[submodule "assets/syntaxes/INI"]
path = assets/syntaxes/INI
url = https://github.com/clintberry/sublime-text-2-ini
[submodule "assets/syntaxes/CMake"]
path = assets/syntaxes/CMake
url = https://github.com/zyxar/Sublime-CMakeLists
[submodule "assets/syntaxes/LESS"]
path = assets/syntaxes/LESS
url = https://github.com/danro/LESS-sublime
[submodule "assets/themes/DarkNeon"]
path = assets/themes/DarkNeon
url = https://github.com/RainyDayMedia/DarkNeon
[submodule "assets/themes/github-sublime-theme"]
path = assets/themes/github-sublime-theme
url = https://github.com/AlexanderEkdahl/github-sublime-theme
[submodule "assets/themes/1337-Scheme"]
path = assets/themes/1337-Scheme
url = https://github.com/MarkMichos/1337-Scheme
[submodule "assets/themes/TwoDark"]
path = assets/themes/TwoDark
url = https://github.com/erremauro/TwoDark
[submodule "assets/syntaxes/AWK"]
path = assets/syntaxes/AWK
url = https://github.com/JohnNilsson/awk-sublime
[submodule "assets/syntaxes/Nix"]
path = assets/syntaxes/Nix
url = https://github.com/wmertens/sublime-nix
[submodule "assets/themes/zenburn"]
path = assets/themes/zenburn
url = https://github.com/colinta/zenburn.git
[submodule "assets/syntaxes/Kotlin"]
path = assets/syntaxes/Kotlin
url = https://github.com/vkostyukov/kotlin-sublime-package
[submodule "assets/syntaxes/Elm"]
path = assets/syntaxes/Elm
url = https://github.com/elm-community/SublimeElmLanguageSupport
[submodule "assets/syntaxes/TypeScript"]
path = assets/syntaxes/TypeScript
url = https://github.com/Microsoft/TypeScript-Sublime-Plugin
[submodule "assets/syntaxes/Puppet"]
path = assets/syntaxes/Puppet
url = https://github.com/russCloak/SublimePuppet
[submodule "assets/syntaxes/CSV"]
path = assets/syntaxes/CSV
url = https://github.com/wadetb/Sublime-Text-Advanced-CSV
[submodule "assets/themes/onehalf"]
path = assets/themes/onehalf
url = https://github.com/sonph/onehalf
[submodule "assets/syntaxes/JavaScript (Babel)"]
path = assets/syntaxes/JavaScript (Babel)
url = https://github.com/babel/babel-sublime
[submodule "assets/syntaxes/Cabal"]
path = assets/syntaxes/Cabal
url = https://github.com/SublimeHaskell/SublimeHaskell
[submodule "assets/syntaxes/Dart"]
path = assets/syntaxes/Dart
url = https://github.com/guillermooo/dart-sublime-bundle
[submodule "assets/syntaxes/FSharp"]
path = assets/syntaxes/FSharp
url = https://github.com/hoest/sublimetext-fsharp
[submodule "assets/syntaxes/PureScript"]
path = assets/syntaxes/PureScript
url = https://github.com/tellnobody1/sublime-purescript-syntax
[submodule "assets/syntaxes/Swift"]
path = assets/syntaxes/Swift
url = https://github.com/quiqueg/Swift-Sublime-Package
[submodule "assets/syntaxes/Crystal"]
path = assets/syntaxes/Crystal
url = https://github.com/crystal-lang-tools/sublime-crystal.git
[submodule "assets/syntaxes/PowerShell"]
path = assets/syntaxes/PowerShell
url = https://github.com/PowerShell/EditorSyntax
+41 -13
View File
@@ -6,25 +6,55 @@ matrix:
- os: linux - os: linux
rust: stable rust: stable
env: TARGET=x86_64-unknown-linux-gnu env: TARGET=x86_64-unknown-linux-gnu
- os: linux
rust: stable
env:
- TARGET=x86_64-unknown-linux-musl
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
- os: linux
rust: stable
env: TARGET=i686-unknown-linux-gnu
- os: osx - os: osx
rust: stable rust: stable
env: TARGET=x86_64-apple-darwin env: TARGET=x86_64-apple-darwin
- os: linux
rust: stable
env:
- TARGET=arm-unknown-linux-gnueabihf
- CC_arm_unknown_linux_gnueabihf=/usr/bin/arm-linux-gnueabihf-gcc-4.8
- CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc-4.8
- os: linux
rust: stable
env:
- TARGET=aarch64-unknown-linux-gnu
- CC_aarch64-unknown-linux-gnu=/usr/bin/aarch64-linux-gnu-gcc-4.8
- CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc-4.8
# Minimum Rust supported channel. # Minimum Rust supported channel.
- os: linux - os: linux
rust: 1.22.1 rust: 1.26.0
env: TARGET=x86_64-unknown-linux-gnu env: TARGET=x86_64-unknown-linux-gnu
- os: linux
rust: 1.26.0
env:
- TARGET=x86_64-unknown-linux-musl
- CC_x86_64_unknown_linux_musl=/usr/bin/musl-gcc
- os: osx - os: osx
rust: 1.22.1 rust: 1.26.0
env: TARGET=x86_64-apple-darwin env: TARGET=x86_64-apple-darwin
addons: # Code formatting check
apt: - os: linux
packages: rust: nightly
# needed for i686-unknown-linux-gnu target # skip the global install step
- gcc-multilib install:
# needed to build deb packages - cargo install --debug --force rustfmt-nightly
- fakeroot script: cargo fmt -- --check
sudo: required
before_install:
- ci/before_install.bash
env: env:
global: global:
@@ -39,9 +69,7 @@ install:
- if [[ $TRAVIS_OS_NAME = linux && $HOST != $TARGET ]]; then rustup target add $TARGET; fi - if [[ $TRAVIS_OS_NAME = linux && $HOST != $TARGET ]]; then rustup target add $TARGET; fi
script: script:
# Incorporate TARGET env var to the build and test process - ci/script.bash
- cargo build --target $TARGET --verbose
- cargo test --target $TARGET --verbose
before_deploy: before_deploy:
- bash ci/before_deploy.bash - bash ci/before_deploy.bash
Generated
+348 -387
View File
File diff suppressed because it is too large Load Diff
+22 -8
View File
@@ -7,24 +7,38 @@ license = "MIT/Apache-2.0"
name = "bat" name = "bat"
readme = "README.md" readme = "README.md"
repository = "https://github.com/sharkdp/bat" repository = "https://github.com/sharkdp/bat"
version = "0.2.0" version = "0.7.0"
exclude = [
"assets/syntaxes/*",
"assets/themes/*",
]
[dependencies] [dependencies]
atty = "0.2.2" atty = "0.2.2"
ansi_term = "0.9" ansi_term = "0.11"
bincode = "1.0"
console = "0.6" console = "0.6"
git2 = "0.6" directories = "1.0"
error-chain = "0.11"
directories = "0.9"
lazy_static = "1.0" lazy_static = "1.0"
[dependencies.git2]
version = "0.7"
default-features = false
features = []
[dependencies.syntect] [dependencies.syntect]
version = "2" version = "2.1"
default-features = false default-features = false
features = ["parsing", "yaml-load", "dump-load", "dump-create"] features = ["parsing", "yaml-load", "dump-load", "dump-create"]
[dependencies.clap] [dependencies.clap]
version = "2" version = "2.32"
default-features = false default-features = false
features = ["suggestions", "color", "wrap_help"] features = ["suggestions", "color", "wrap_help"]
[dependencies.error-chain]
version = "0.12"
default-features = false
features = []
[dev-dependencies]
tempdir = "0.3"
+284 -36
View File
@@ -1,69 +1,317 @@
# bat <p align="center">
<img src="doc/logo-header.svg" alt="bat - a cat clone with wings"><br>
<a href="https://travis-ci.org/sharkdp/bat"><img src="https://travis-ci.org/sharkdp/bat.svg?branch=master" alt="Build Status"></a>
<a href="https://ci.appveyor.com/project/sharkdp/bat"><img src="https://ci.appveyor.com/api/projects/status/cptsmtbiwbnr2vhf?svg=true"></a>
<img src="https://img.shields.io/crates/l/bat.svg" alt="license">
<a href="https://crates.io/crates/bat"><img src="https://img.shields.io/crates/v/bat.svg?colorB=319e8c" alt="Version info"></a><br>
A <i>cat(1)</i> clone with syntax highlighting and Git integration.
</p>
[![Build Status](https://travis-ci.org/sharkdp/bat.svg?branch=master)](https://travis-ci.org/sharkdp/bat) <p align="center">
[![Version info](https://img.shields.io/crates/v/bat.svg)](https://crates.io/crates/bat) <a href="#syntax-highlighting">Key Features</a> •
<a href="#how-to-use">How To Use</a> •
A *cat(1)* clone with syntax highlighting and Git integration. <a href="#installation">Installation</a> •
<a href="#customization">Customization</a> •
## Features <a href="#project-goals-and-alternatives">Project goals, alternatives</a>
</p>
### Syntax highlighting ### Syntax highlighting
`bat` supports syntax highlighting for a large number of programming and markup languages: `bat` supports syntax highlighting for a large number of programming and markup
languages:
![Syntax highlighting example](https://imgur.com/rGsdnDe.png) ![Syntax highlighting example](https://imgur.com/rGsdnDe.png)
### Git integration ### Git integration
`bat` communicates with `git` to show modifications with respect to the index (see left side bar): `bat` communicates with `git` to show modifications with respect to the index
(see left side bar):
![Git integration example](https://i.imgur.com/2lSW4RE.png) ![Git integration example](https://i.imgur.com/2lSW4RE.png)
### Automatic paging
`bat` can pipe its own output to `less` if the output is too large for one screen.
### File concatenation
Oh.. you can also use it to concatenate files :wink:. Whenever
`bat` detects a non-interactive terminal, it will fall back to printing
the plain file contents.
## How to use
Display a single file on the terminal
```bash
> bat README.md
```
Display multiple files at once
```bash
> bat src/*.rs
```
Read from stdin, explicitly specify the language
```bash
> yaml2json .travis.yml | json_pp | bat -l json
```
```bash
> curl -s https://raw.githubusercontent.com/sharkdp/bat/master/src/main.rs | bat -l rs
```
As a replacement for `cat`:
```bash
bat > note.md # quickly create a new file
bat header.md content.md footer.md > document.md
bat -n main.rs # show line numbers (only)
bat f - g # output 'f', then stdin, then 'g'.
```
## Installation ## Installation
Check out the [Release page](https://github.com/sharkdp/bat/releases) for binary builds and Debian packages. ### On Ubuntu
*... and other Debian-based Linux distributions.*
Download the latest `.deb` package from the [release page](https://github.com/sharkdp/bat/releases)
and install it via:
``` bash
sudo dpkg -i bat_0.7.0_amd64.deb # adapt version number and architecture
```
### On Arch Linux
You can install [the `bat` package](https://www.archlinux.org/packages/community/x86_64/bat/)
from the official sources:
```bash
pacman -S bat
```
### On Void Linux
You can install `bat` via xbps-install:
```
xbps-install -S bat
```
### On FreeBSD
You can install a precompiled [`bat` package](https://www.freshports.org/textproc/bat) with pkg:
```bash
pkg install bat
```
or build it on your own from the FreeBSD ports:
```bash
cd /usr/ports/textproc/bat
make install
```
### On macOS
You can install `bat` with [Homebrew](http://braumeister.org/formula/bat):
```bash
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/):
```bash
scoop install bat
```
[See below](#using-bat-on-windows) for notes.
### From binaries
Check out the [Release page](https://github.com/sharkdp/bat/releases) for
prebuilt versions of `bat` for many different architectures.
### From source ### From source
If you want to build to compile `bat` from source, you need Rust 1.22 or higher. If you want to build `bat` from source, you need Rust 1.26 or
Make sure that you have the devel-version of libopenssl installed (see instructions higher. You can then use `cargo` to build everything:
[here](https://github.com/sfackler/rust-openssl)). You can then use `cargo` to build everything:
``` bash ```bash
cargo install bat cargo install bat
``` ```
On macOS, you might have to install `cmake` (`brew install cmake`) in order for
some dependencies to be built.
## Customization ## Customization
`bat` uses the excellent [`syntect`](https://github.com/trishume/syntect/) library for syntax highlighting. `syntect` can read any Sublime Text language definition and theme. ### Highlighting theme
To build your own language-set and theme, follow these steps: Use `bat --list-themes` to get a list of all available themes for syntax
highlighting. To select the `TwoDark` theme, call `bat` with the
`--theme=TwoDark` option or set the `BAT_THEME` environment variable to
`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shells startup file to
make the change permanent.
Create a folder with a syntax highlighting theme: ### Output style
``` bash
mkdir -p ~/.config/bat/themes
cd ~/.config/bat/themes
# Download a theme, for example: You can use the `--style` option to control the appearance of `bat`s output.
git clone https://github.com/jonschlinkert/sublime-monokai-extended You can use `--style=numbers,changes`, for example, to show only Git changes
and line numbers but no grid and no file header. Use the `BAT_STYLE` environment
variable to make these changes permanent.
# Create a 'Default.tmTheme' link ### Adding new syntaxes / language definitions
ln -s "sublime-monokai-extended/Monokai Extended.tmTheme" Default.tmTheme
`bat` uses the excellent [`syntect`](https://github.com/trishume/syntect/)
library for syntax highlighting. `syntect` can read any
[Sublime Text `.sublime-syntax` file](https://www.sublimetext.com/docs/3/syntax.html)
and theme. To add new syntax definitions, do the following.
Create a folder with syntax definition files:
```bash
BAT_CONFIG_DIR="$(bat cache --config-dir)"
mkdir -p "$BAT_CONFIG_DIR/syntaxes"
cd "$BAT_CONFIG_DIR/syntaxes"
# Put new '.sublime-syntax' language definition files
# in this folder (or its subdirectories), for example:
git clone https://github.com/tellnobody1/sublime-purescript-syntax
``` ```
Create a folder with language definition files: Now use the following command to parse these files into a binary cache:
``` bash
mkdir -p ~/.config/bat/syntax
cd ~/.config/bat/syntax
# Download some language definition files, for example: ```bash
git clone https://github.com/sublimehq/Packages/ bat cache --init
rm -rf Packages/Markdown
git clone https://github.com/jonschlinkert/sublime-markdown-extended
``` ```
Finally, use the following command to parse all these files into a binary Finally, use `bat --list-languages` to check if the new languages are available.
cache:
``` bash If you ever want to go back to the default settings, call:
bat init-cache
```bash
bat cache --clear
``` ```
### Adding new themes
This works very similar to how we add new syntax definitions.
First, create a folder with the new syntax highlighting themes:
```bash
BAT_CONFIG_DIR="$(bat cache --config-dir)"
mkdir -p "$BAT_CONFIG_DIR/themes"
cd "$BAT_CONFIG_DIR/themes"
# Download a theme in '.tmTheme' format, for example:
git clone https://github.com/greggb/sublime-snazzy
# Update the binary cache
bat cache --init
```
Finally, use `bat --list-themes` to check if the new themes are available.
### Using a different pager
`bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not
set, `less` is used by default. If you want to use a different pager, you can either modify the
`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in
`PAGER`. If you want to pass command-line arguments to the pager, you need to create a small shell
script as a wrapper, for example:
```bash
#!/bin/bash
less --tabs 4 -RF "$@"
```
## Using `bat` on Windows
`bat` mostly works out-of-the-box on Windows, but a few features may need extra configuration.
### Paging
Windows only includes a very limited pager in the form of `more`. You can download a Windows binary
for `less` [from its homepage](http://www.greenwoodsoftware.com/less/download.html) or [through
Chocolatey](https://chocolatey.org/packages/Less). To use it, place the binary in a directory in
your `PATH` or [define an environment variable](#using-a-different-pager).
### Colours
Windows 10 natively supports colours in both `conhost.exe` (Command Prompt) and PowerShell since
[v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)), as
well as in newer versions of bash. On earlier versions of Windows, you can use
[Cmder](http://cmder.net/), which includes [ConEmu](https://conemu.github.io/).
**Note:** The Git and MSYS versions of `less` do not correctly interpret colours on Windows. If you
dont have any other pagers installed, you can disable paging entirely by passing `--paging=never`
or by setting `BAT_PAGER` to an empty string.
## Troubleshooting
### Terminals & colors
`bat` handles terminals *with* and *without* truecolor support. However, the colors in the syntax
highlighting themes are not optimized for 8-bit colors and it is therefore strongly recommended
that you use a terminal with 24-bit truecolor support (`terminator`, `konsole`, `iTerm2`, ...).
See [this article](https://gist.github.com/XVilka/8346728) for more details and a full list of
terminals with truecolor support.
Make sure that your truecolor terminal sets the `COLORTERM` variable to either `truecolor` or
`24bit`. Otherwise, `bat` will not be able to determine whether or not 24-bit escape sequences
are supported (and fall back to 8-bit colors).
### Line numbers and grid are hardly visible
Please try a different theme (see `bat --list-themes` for a list). The `OneHalfDark` and
`OneHalfLight` themes provide grid and line colors that are brighter.
### Error when compiling: "cannot find -lz"
Please install the `zlib-devel` package and try again.
## Development
```bash
# Recursive clone to retrieve all submodules
git clone --recursive https://github.com/sharkdp/bat
# Build (debug version)
cd bat
cargo build
# Run unit tests and integration tests
cargo test
# Install (release version)
cargo install
# Build a bat binary with modified syntaxes and themes
bash assets/create.sh
cargo install -f
```
## Project goals and alternatives
`bat` tries to achieve the following goals:
- Provide beautiful, advanced syntax highlighting
- Integrate with Git to show file modifications
- Be a drop-in replacement for (POSIX) `cat`
- Offer a user-friendly command-line interface
There are a lot of alternatives, if you are looking for similar programs. See
[this document](doc/alternatives.md) for a comparison.
+49
View File
@@ -0,0 +1,49 @@
environment:
global:
TARGET: x86_64-pc-windows-msvc
RUST_VERSION: stable
CRATE_NAME: bat
CARGO_HOME: "c:\\cargo"
RUSTUP_HOME: "c:\\rustup"
install:
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -y --default-host %TARGET%
- set PATH=%PATH%;C:\cargo\bin
- rustc -Vv
- cargo -V
build: false
test_script:
- cargo test --target %TARGET% --verbose
- cargo run --target %TARGET% -- src/main.rs README.md --paging=never
before_deploy:
# Generate artifacts for release
- cargo build --release --verbose
- ps: ci\before_deploy.ps1
deploy:
description: 'Automatically deployed release'
artifact: /.*\.zip/
# Here's how:
# - Go to 'https://github.com/settings/tokens/new' and generate a Token with only the
# `public_repo` scope enabled
# - Then go to 'https://ci.appveyor.com/tools/encrypt' and enter the newly generated token.
# - Enter the "encrypted value" below
auth_token:
secure: oO4/J+hcFXgXcEqEc8gzlQNqLG0IxU78s4EyH+uczGdsyWajb3yipxPR6nXUvmoj
provider: GitHub
on:
RUST_VERSION: stable
appveyor_repo_tag: true
cache:
- C:\Users\appveyor\.cargo\registry
- target
notifications:
- provider: Email
on_build_success: false
on_build_failure: false
on_build_status_changed: false
+2
View File
@@ -0,0 +1,2 @@
syntaxes/*
themes/*
+32
View File
@@ -0,0 +1,32 @@
## Syntax Highlighting in bat
`bat` uses the [syntect](https://github.com/trishume/syntect) library to highlight source
code. As a basis, syntect uses [Sublime Text](https://www.sublimetext.com/) syntax definitions
in the `.sublime-syntax` format.
In order to add new syntaxes to `bat`, follow these steps:
1. Find a Sublime Text syntax for the given language, preferably in a separate Git repository
which can be included as a submodule (under `assets/syntaxes`).
2. If the Sublime Text syntax is only available as a `.tmLanguage` file, open the file in
Sublime Text and convert it to a `.sublime-syntax` file via *Tools* -> *Developer* ->
*New Syntax from XXX.tmLanguage...*. Save the new file in the `assets/syntaxes` folder.
3. Run the `create.sh` script. It calls `bat cache --init` to parse all available
`.sublime-syntax` files and serialize them to a `syntaxes.bin` file (in this folder).
4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the
`bat` binary.
### Troubleshooting
Make sure that the local cache does not interfere with the internally stored syntaxes and
themes (`bat cache --clear`).
### Manual modifications
The following files have been manually modified after converting from a `.tmLanguage` file:
* `VimL.sublime-syntax` => added `.vimrc` file type.
* `Dart.sublime-syntax` => removed `#regex.dart` include,
+3 -25
View File
@@ -1,27 +1,5 @@
set -e #!/bin/bash
THEME_FOLDER="$HOME/.config/bat/themes" ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SYNTAX_FOLDER="$HOME/.config/bat/syntax"
if [ ! -e "$THEME_FOLDER" ]; then bat cache --init --blank --source="$ASSET_DIR" --target="$ASSET_DIR"
mkdir -p "$THEME_FOLDER"
(
cd "$THEME_FOLDER"
git clone https://github.com/jonschlinkert/sublime-monokai-extended
ln -s "sublime-monokai-extended/Monokai Extended.tmTheme" Default.tmTheme
)
fi
if [ ! -e "$SYNTAX_FOLDER" ]; then
mkdir -p "$SYNTAX_FOLDER"
(
cd "$SYNTAX_FOLDER"
git clone https://github.com/sublimehq/Packages/
rm -rf Packages/Markdown
git clone https://github.com/jonschlinkert/sublime-markdown-extended
)
fi
bat init-cache
cp "$HOME/.cache/bat"/* .
BIN
View File
Binary file not shown.
Binary file not shown.
Submodule assets/syntaxes/AWK added at 1ce5f90d44
Submodule assets/syntaxes/CSV added at 4786d037a7
+46
View File
@@ -0,0 +1,46 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Advanced CSV
file_extensions:
- csv
- tsv
scope: text.advanced_csv
contexts:
main:
- match: (\")
captures:
1: string.quoted.double.advanced_csv
push:
- meta_scope: meta.quoted.advanced_csv
- match: (\")
captures:
1: string.quoted.double.advanced_csv
pop: true
- include: main
- match: '(\[([+-]?\d*)(\:)?([+-]?\d*)(\,)?([+-]?\d*)(\:)?([+-]?\d*)\])?\s*([<>v^])?\s*(=)'
captures:
1: keyword.operator.advanced_csv
2: constant.numeric.formula.advanced_csv
4: constant.numeric.formula.advanced_csv
6: constant.numeric.formula.advanced_csv
8: constant.numeric.formula.advanced_csv
9: keyword.operator.advanced_csv
10: keyword.operator.advanced_csv
push:
- meta_scope: meta.range.advanced_csv
- match: (?=(\")|$)
pop: true
- include: scope:source.python
- match: '(?<=^|,|\s|\")([0-9.eE+-]+)(?=$|,|\s|\")'
scope: meta.number.advanced_csv
captures:
1: constant.numeric.advanced_csv
- match: '(?<=^|,|\s|\")([^, \t\"]+)(?=$|,|\s|\")'
scope: meta.nonnumber.advanced_csv
captures:
1: storage.type.advanced_csv
- match: (\,)
scope: meta.delimiter.advanced_csv
captures:
1: keyword.operator.advanced_csv
+47
View File
@@ -0,0 +1,47 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Cabal
file_extensions:
- cabal
scope: source.cabal
contexts:
main:
- match: ^(\s*)(exposed-modules):$
captures:
2: constant.other.cabal
push:
- meta_scope: exposed.modules.cabal
- match: ^(?!\1\s)
pop: true
- include: module_name
- match: ^(\s*)(build-depends):$
captures:
2: constant.other.cabal
push:
- meta_scope: exposed.modules.cabal
- match: ^(?!\1\s)
pop: true
- match: "([<>=]+)|([&|]+)"
scope: keyword.operator.haskell
- match: ((\d+|\*)\.)*(\d+|\*)
scope: constant.numeric.haskell
- match: '([\w\-]+)'
scope: support.function.haskell
- match: '^\s*([a-zA-Z_-]+)(:)\s+'
scope: entity.cabal
captures:
1: constant.other.cabal
2: punctuation.entity.cabal
- match: '^(?i)(executable|library|test-suite|benchmark|flag|source-repository)\s+([^\s,]+)\s*$'
scope: entity.cabal
captures:
1: keyword.entity.cabal
2: string.cabal
- match: ^(?i)library\s*$
scope: keyword.entity.cabal
- match: "--.*$"
scope: comment.cabal
module_name:
- match: '([A-Z][A-Za-z_''0-9]*)(\.[A-Z][A-Za-z_''0-9]*)*'
scope: storage.module.haskell
File diff suppressed because it is too large Load Diff
+369
View File
@@ -0,0 +1,369 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Dart
file_extensions:
- dart
scope: source.dart
contexts:
main:
- match: ^(#!.*)$
scope: meta.preprocessor.script.dart
- match: ^\s*\b(library|import|export|part of|part)\b
captures:
0: keyword.other.import.dart
push:
- meta_scope: meta.declaration.dart
- match: ;
captures:
0: punctuation.terminator.dart
pop: true
- include: strings
- match: \b(as|show|hide|deferred)\b
scope: keyword.other.import.dart
- include: comments
- include: constants-and-special-vars
- include: annotations
- include: decl-typedef
- include: decl-class
- include: decl-enum
- include: decl-function
- include: keywords
- include: strings
annotations:
- match: '^(?:\s*)((@)([a-zA-Z0-9_]+))'
captures:
1: annotation.dart
2: entity.name.function.annotation.dart
3: support.type.dart
comments:
- match: /\*\*/
scope: comment.block.empty.dart
captures:
0: punctuation.definition.comment.dart
- include: comments-inline
comments-inline:
- match: /\*
push:
- meta_scope: comment.block.dart
- match: \*/
pop: true
- include: scope:text.dart-doccomments
- match: (///)
captures:
1: marker.dart
push:
- meta_scope: comment.line.triple-slash.dart
- match: $
pop: true
- include: scope:text.dart-doccomments
- match: (//)
captures:
1: marker.dart
push:
- meta_scope: comment.line.double-slash.dart
- match: $
pop: true
- include: scope:text.dart-doccomments
constants-and-special-vars:
- match: \b(true|false|null)\b
scope: constant.language.dart
- match: \b(this|super)\b
scope: variable.language.dart
- match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)\b'
scope: constant.numeric.dart
decl-class:
- match: \bclass\b
captures:
0: keyword.control.new.dart
push:
- meta_scope: meta.declaration.class.dart
- match: "(?={)"
pop: true
- include: keywords
- match: "[A-Za-z_][A-Za-z0-9_]*"
scope: class.name.dart
decl-enum:
- match: \benum\b
captures:
0: keyword.declaration.dart
push:
- meta_scope: meta.declaration.enum.dart
- match: "(?={)"
pop: true
- include: keywords
- match: "[A-Za-z_][A-Za-z0-9_]*"
scope: enum.name.dart
decl-function:
- match: ^\s*(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(get)\s+(\w+)\s+(?==>)
comment: A getter with a primitive return type.
scope: meta.declaration.function.dart
captures:
1: storage.type.primitive.dart
2: keyword.declaration.dart
3: function.name.dart
- match: ^\s*(?:\b(\w+)\b\s+)?(get)\s+(\w+)\s+(?==>)
comment: A getter with a user-defined return type or no return type.
scope: meta.declaration.function.dart
captures:
1: type.user-defined.dart
2: keyword.declaration.dart
3: function.name.dart
- match: ^\s*(set)\s+(\w+)(?=\()
comment: A setter.
captures:
1: keyword.declaration.dart
2: function.name.dart
push:
- meta_scope: meta.declaration.function.dart
- match: \)
pop: true
- include: comments-inline
- include: decl-function-parameter
- include: strings
- include: keywords
- match: ^\s*(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(\w+)(?=\()
comment: A function with a primitive return type.
captures:
1: storage.type.primitive.dart
2: function.name.dart
push:
- meta_scope: meta.declaration.function.dart
- match: \)
pop: true
- include: comments-inline
- include: decl-function-parameter
- include: strings
- include: keywords
- match: ^\s*(?:\b(return)\b)\s+(\w+)(?=\()
comment: A function invocation after 'return'
captures:
1: keyword.control.dart
2: function.name.dart
push:
- meta_scope: meta.invocation.function.dart
- match: \)
pop: true
- include: comments-inline
- include: decl-function-parameter
- include: strings
- include: keywords
- match: ^\s*\b(new)\b\s+(\w+)(?=\()
comment: A class instantiation after 'new'
captures:
1: keyword.declaration.dart
2: function.name.dart
push:
- meta_scope: meta.invocation.function.dart
- match: \)
pop: true
- include: comments-inline
- include: decl-function-parameter
- include: strings
- include: keywords
decl-function-parameter:
- include: constants-and-special-vars
- match: (?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b)\s+(\w+)(?=\()
comment: A function with a primitive return type.
captures:
1: storage.type.primitive.dart
2: function.name.dart
push:
- meta_scope: meta.parameter.function.dart
- match: \)
pop: true
- include: decl-function-parameter
- include: strings
- include: keywords
- match: \b(new)\b\s+(\w+)(?=\()
comment: A class instantiation after 'new'
captures:
1: keyword.declaration.dart
2: function.name.dart
push:
- meta_scope: meta.invocation.function.dart
- match: \)
pop: true
- include: decl-function-parameter
- include: strings
- include: keywords
- match: (?:\b(\w+)\b)\s+(\w+)(?=\()
comment: A function with a user-defined return type.
captures:
1: type.user-defined.dart
2: function.name.dart
push:
- meta_scope: meta.parameter.function.dart
- match: \)
pop: true
- include: decl-function-parameter
- include: strings
- include: keywords
- match: (\w+)(?=\()
comment: A function with no return type.
captures:
1: function.name.dart
push:
- meta_scope: meta.parameter.function.dart
- match: \)
pop: true
- include: decl-function-parameter
- include: strings
- include: keywords
decl-typedef:
- match: typedef
captures:
0: keyword.control.new.dart
push:
- meta_scope: meta.declaration.typedef.dart
- match: ;
captures:
0: punctuation.terminator.dart
pop: true
- match: '(?:\b(void|bool|num|int|double|dynamic|var|String|List|Map)\b|([a-zA-Z_][a-zA-Z0-9_]*))\s+([a-zA-Z_][a-zA-Z0-9_]+)'
captures:
1: storage.type.primitive.dart
2: typedef.return.dart
3: typedef.name.dart
- match: \(
push:
- meta_scope: typedef.params.dart
- match: \)
pop: true
- include: keywords
keywords:
- match: \bassert\b
scope: keyword.control.assert.dart
- match: \bas\b
scope: keyword.cast.dart
- match: \b(try|catch|finally|throw|on|rethrow)\b
scope: keyword.control.catch-exception.dart
- match: \s+\?\s+|\s+:\s+
scope: keyword.control.ternary.dart
- match: \b(break|case|continue|default|do|else|for|if|in|return|switch|while)\b
scope: keyword.control.dart
- match: \b(async\*|async|await\*|await|yield)\b
scope: keyword.control.async.dart
- match: \b(new)\b
scope: keyword.control.new.dart
- match: \b(abstract|extends|external|factory|implements|with|interface|get|native|operator|set|typedef)\b
scope: keyword.declaration.dart
- match: \b(is\!?)\b
scope: keyword.operator.dart
- match: (<<|>>>?|~|\^|\||&)
scope: keyword.operator.bitwise.dart
- match: ((&|\^|\||<<|>>>?)=)
scope: keyword.operator.assignment.bitwise.dart
- match: (===?|!==?|<=?|>=?)
scope: keyword.operator.comparison.dart
- match: '(([+*/%-]|\~)=)'
scope: keyword.operator.assignment.arithmetic.dart
- match: (=)
scope: keyword.operator.assignment.dart
- match: (\-\-|\+\+)
scope: keyword.operator.increment-decrement.dart
- match: (\-|\+|\*|\/|\~\/|%)
scope: keyword.operator.arithmetic.dart
- match: (!|&&|\|\|)
scope: keyword.operator.logical.dart
- match: ;
scope: punctuation.terminator.dart
- match: \b(static|final|const)\b
scope: storage.modifier.dart
- match: \b(?:void|bool|num|int|double|dynamic|var|String|List|Map)\b
scope: storage.type.primitive.dart
regexp:
- match: '\\[^''"]'
scope: constant.character.escaped.regex.dart
- match: \(
push:
- meta_content_scope: meta.capture.regex.dart
- match: \)
pop: true
- match: \?(:|=|!)
scope: ignore.capture.regex.dart
- match: \*|\+|\?|\.|\|
scope: keyword.other.regex.dart
- match: \^|\$
scope: keyword.other.regex.dart
- match: \.
scope: constant.other.regex.dart
- match: '\[(\^)?'
captures:
1: keyword.other.negation.regex.dart
push:
- meta_scope: constant.character.range.regex.dart
- match: '\]'
pop: true
- match: '\\[^"'']'
scope: constant.character.escaped.regex.dart
- match: '\{(?:\d+)?,(?:\d+)?\}'
scope: keyword.other.regex.dart
string-interp:
- match: '(\$)(\{)'
captures:
1: keyword.other.dart
2: keyword.other.dart
push:
- meta_scope: interpolation.dart
- meta_content_scope: source.dart
- match: '(\})'
captures:
1: keyword.other.dart
pop: true
- include: main
- match: (\$)(\w+)
captures:
1: keyword.other.dart
2: variable.parameter.dart
- match: \\.
scope: constant.character.escape.dart
strings:
- match: (?<!r)"""
push:
- meta_scope: string.interpolated.triple.double.dart
- match: '"""(?!")'
pop: true
- include: string-interp
- match: (?<!r)'''
push:
- meta_scope: string.interpolated.triple.single.dart
- match: "'''(?!')"
pop: true
- include: string-interp
- match: r"""
push:
- meta_scope: string.quoted.triple.double.dart
- match: '"""(?!")'
pop: true
- match: r'''
push:
- meta_scope: string.quoted.triple.single.dart
- match: "'''(?!')"
pop: true
- match: (?<!\\|r)"
push:
- meta_scope: string.interpolated.double.dart
- match: '"'
pop: true
- match: \n
scope: invalid.string.newline
- include: string-interp
- match: r"
push:
- meta_scope: string.quoted.double.dart
- match: '"'
pop: true
- include: regexp
- match: (?<!\|r)'
push:
- meta_scope: string.interpolated.single.dart
- match: "'"
pop: true
- include: string-interp
- match: r'
push:
- meta_scope: string.quoted.single.dart
- match: "'"
pop: true
- include: regexp
Submodule assets/syntaxes/Elm added at dfbb8bdc9a
+234
View File
@@ -0,0 +1,234 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: "F#"
file_extensions:
- fs
- fsi
- fsx
scope: source.fsharp
contexts:
main:
- include: comments
- include: constants
- include: structure
- include: attributes
- include: strings
- include: definition
- include: method_calls
- include: modules
- include: anonymous_functions
- include: keywords
anonymous_functions:
- match: \b(fun)\b
captures:
1: keyword.other.function-definition.fsharp
push:
- meta_scope: meta.function.anonymous
- match: (->)
captures:
1: keyword.other.fsharp
pop: true
- include: variables
attributes:
- match: '\[\<'
push:
- meta_scope: support.function.attribute.fsharp
- match: '\>\]'
pop: true
- include: main
characters:
- match: (')
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.single.fsharp
- match: (')
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\""ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
comments:
- match: \(\*\*?(\*)\)
scope: comment.block.fsharp
captures:
1: comment.block.empty.fsharp
- match: '\(\*[^\)]'
push:
- meta_scope: comment.block.fsharp
- match: \*\)
pop: true
- include: comments
- match: //.*$
scope: comment.line.double-slash.fsharp
constants:
- match: \(\)
scope: constant.language.unit.fsharp
- match: '\b-?[0-9][0-9_]*((\.([0-9][0-9_]*([eE][+-]??[0-9][0-9_]*)?)?)|([eE][+-]??[0-9][0-9_]*))'
scope: constant.numeric.floating-point.fsharp
- match: '\b(-?((0(x|X)[0-9a-fA-F][0-9a-fA-F_]*)|(0(o|O)[0-7][0-7_]*)|(0(b|B)[01][01_]*)|([0-9][0-9_]*)))'
scope: constant.numeric.integer.nativeint.fsharp
definition:
- match: '\b(val|val|let|and|member|override|use)\s?(rec|inline|mutable)?(\s+\(?([a-zA-Z.\|_][a-zA-Z0-9.|_]*)\)?\w*)\b'
captures:
1: keyword.other.binding.fsharp
2: keyword.other.function-recursive.fsharp
3: variable.other.binding.fsharp
push:
- meta_scope: meta.binding.fsharp
- match: "=|$"
captures:
1: punctuation.separator.function.type-constraint.fsharp
pop: true
- include: variables
- match: \b(let)\s+((\(\))|(_))\s+=
scope: meta.expression.fsharp
captures:
1: keyword.other.binding.fsharp
2: keyword.other.function-recursive.fsharp
4: constant.language.unit.fsharp
5: constant.language.ignored.fsharp
keywords:
- match: ^\s*#\s*(light|if|else|endif|r|I|load|time|help|quit)\b
push:
- meta_scope: meta.preprocessor.fsharp
- match: (\s|$)
pop: true
- match: \b(new|in|as|if|then|else|elif|for|begin|end|match|with|type|inherit|true|false|null|do)\b
scope: keyword.other.fsharp
- match: '(\|>|\|?>|\->|\<\-|:>|:|\[|\]|\;|\||_)'
scope: entity.name
method_calls:
- match: '(?<!\w)([a-z]\w*)(\.)'
push:
- meta_scope: meta.method-call.fsharp
- match: '[A-Z]\w*(\.)'
scope: meta.method.fsharp
captures:
1: punctuation.separator.method-call.fsharp
- match: (?=.)
pop: true
modules:
- match: '\b(namespace|module)\s+([a-zA-Z][a-zA-Z0-9''_.]*)'
captures:
1: keyword.other.fsharp
2: entity.name.section.fsharp
push:
- meta_scope: meta.module.namespace.fsharp
- match: (\s|$)
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '\b(open)\s+([A-Z][a-zA-Z0-9''_]*)(?=(\.[A-Z][a-zA-Z0-9_]*)*)'
captures:
1: keyword.other.fsharp
2: support.other.module.fsharp
push:
- meta_scope: meta.module.open.fsharp
- match: (\s|$)
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '^\s*(module)\s+([A-Z][a-zA-Z0-9''_]*)\s*(=)\s*([A-Z][a-zA-Z0-9''_]*)'
captures:
1: keyword.other.module-definition.fsharp
2: entity.name.type.module.fsharp
3: punctuation.separator.module-definition.fsharp
4: support.other.module.fsharp
push:
- meta_scope: meta.module.alias.fsharp
- match: (\s|$)
pop: true
- match: '(\.)([A-Z][a-zA-Z0-9''_]*)'
scope: support.other.module.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
2: support.other.module.fsharp
- match: '(?<!\w)([A-Z][a-zA-Z0-9_]*)(\.)'
captures:
1: support.other.module.fsharp
2: punctuation.separator.module-reference.fsharp
push:
- meta_scope: meta.module.reference.fsharp
- match: '[A-Z][a-zA-Z0-9_]+(\.)'
scope: support.other.module.fsharp
captures:
1: punctuation.separator.module-reference.fsharp
- match: (?=.)
pop: true
strings:
- match: '(?=[^\\])(""")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (""")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '(?=[^\\])(@")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '(?=[^\\])(")'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (")
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\''ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
- match: '(?=[^\\])('')'
captures:
1: punctuation.definition.string.begin.fsharp
push:
- meta_scope: string.quoted.double.fsharp
- match: (')
captures:
1: punctuation.definition.string.end.fsharp
pop: true
- match: '\\$[ \t]*'
scope: punctuation.separator.string.ignore-eol.fsharp
- match: '\\([\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8})'
scope: constant.character.string.escape.fsharp
- match: '\\(?![\\"ntbr]|u[a-fA-F0-9]{4}|u[a-fA-F0-9]{8}).'
scope: invalid.illeagal.character.string.fsharp
structure:
- match: \(
push:
- meta_scope: meta.paren-group.fsharp
- match: \)
pop: true
- include: main
variables:
- match: \(\)
scope: variable.parameter.unit.fsharp
- match: '[a-zA-Z]\w*'
scope: variable.parameter.fsharp
Submodule assets/syntaxes/INI added at 8dd3e316ad
+43
View File
@@ -0,0 +1,43 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: INI
file_extensions:
- ini
- INI
- inf
- INF
- reg
- REG
- lng
- cfg
- CFG
- url
- URL
- .editorconfig
scope: source.ini
contexts:
main:
- match: ^\s*(;|#).*$\n?
scope: comment.line.semicolon.ini
captures:
1: punctuation.definition.comment.ini
- match: '^\s*(\[)(.*?)(\])'
scope: meta.tag.section.ini
captures:
1: punctuation.definition.section.ini
2: entity.section.ini
3: punctuation.definition.section.ini
- match: '^(\s*(["'']?)(.+?)(\2)\s*(=))?\s*((["'']?)(.*?)(\7))\s*(;.*)?$\n?'
scope: meta.declaration.ini
captures:
1: meta.property.ini
2: punctuation.definition.quote.ini
3: keyword.name.ini
4: punctuation.definition.quote.ini
5: punctuation.definition.equals.ini
6: meta.value.ini
7: punctuation.definition.quote.ini
8: string.name.value.ini
9: punctuation.definition.quote.ini
10: comment.declarationline.semicolon.ini
File diff suppressed because it is too large Load Diff
+398
View File
@@ -0,0 +1,398 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Kotlin
file_extensions:
- kt
- kts
scope: source.Kotlin
contexts:
main:
- include: comments
- match: '^\s*(package)\b(?:\s*([^ ;$]+)\s*)?'
captures:
1: keyword.other.kotlin
2: entity.name.package.kotlin
- include: imports
- include: statements
classes:
- match: (?<!::)(?=\b(?:companion|class|object|interface)\b)
push:
- match: '(?=$|\})'
pop: true
- include: comments
- match: \b(companion\s*)?(class|object|interface)\b
captures:
1: storage.modifier.kotlin
2: storage.modifier.kotlin
push:
- match: '(?=<|\{|\(|:|$)'
pop: true
- include: comments
- match: \w+
scope: entity.name.type.class.kotlin
- match: <
push:
- match: ">"
pop: true
- include: generics
- match: \(
push:
- match: \)
pop: true
- include: parameters
- match: (:)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: "(?={|$)"
pop: true
- match: \w+
scope: entity.other.inherited-class.kotlin
- match: \(
push:
- match: \)
pop: true
- include: expressions
- match: '\{'
push:
- match: '\}'
pop: true
- include: statements
comments:
- match: /\*
captures:
0: punctuation.definition.comment.kotlin
push:
- meta_scope: comment.block.kotlin
- match: \*/
captures:
0: punctuation.definition.comment.kotlin
pop: true
- match: \s*((//).*$\n?)
captures:
1: comment.line.double-slash.kotlin
2: punctuation.definition.comment.kotlin
constants:
- match: \b(true|false|null|this|super)\b
scope: constant.language.kotlin
- match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)([LlFf])?\b'
scope: constant.numeric.kotlin
- match: '\b([A-Z][A-Z0-9_]+)\b'
scope: constant.other.kotlin
expressions:
- match: \(
push:
- match: \)
pop: true
- include: expressions
- include: types
- include: strings
- include: constants
- include: comments
- include: keywords
functions:
- match: (?=\s*\b(?:fun)\b)
push:
- match: '(?=$|\})'
pop: true
- match: \b(fun)\b
captures:
1: keyword.other.kotlin
push:
- match: (?=\()
pop: true
- match: <
push:
- match: ">"
pop: true
- include: generics
- match: '([\.<\?>\w]+\.)?(\w+)'
captures:
2: entity.name.function.kotlin
- match: \(
push:
- match: \)
pop: true
- include: parameters
- match: (:)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: "(?={|=|$)"
pop: true
- include: types
- match: '\{'
push:
- match: '(?=\})'
pop: true
- include: statements
- match: (=)
captures:
1: keyword.operator.assignment.kotlin
push:
- match: (?=$)
pop: true
- include: expressions
generics:
- match: (:)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: (?=,|>)
pop: true
- include: types
- include: keywords
- match: \w+
scope: storage.type.generic.kotlin
getters-and-setters:
- match: \b(get)\b\s*\(\s*\)
captures:
1: entity.name.function.kotlin
push:
- match: '\}|(?=\bset\b)|$'
pop: true
- match: (=)
captures:
1: keyword.operator.assignment.kotlin
push:
- match: (?=$|\bset\b)
pop: true
- include: expressions
- match: '\{'
push:
- match: '\}'
pop: true
- include: expressions
- match: \b(set)\b\s*(?=\()
captures:
1: entity.name.function.kotlin
push:
- match: '\}|(?=\bget\b)|$'
pop: true
- match: \(
push:
- match: \)
pop: true
- include: parameters
- match: (=)
captures:
1: keyword.operator.assignment.kotlin
push:
- match: (?=$|\bset\b)
pop: true
- include: expressions
- match: '\{'
push:
- match: '\}'
pop: true
- include: expressions
imports:
- match: '^\s*(import)\s+[^ $]+\s+(as)?'
captures:
1: keyword.other.kotlin
2: keyword.other.kotlin
keywords:
- match: \b(var|val|public|private|protected|abstract|final|sealed|enum|open|attribute|annotation|override|inline|vararg|in|out|internal|data|tailrec|operator|infix|const|yield|typealias|typeof|reified|suspend)\b
scope: storage.modifier.kotlin
- match: \b(try|catch|finally|throw)\b
scope: keyword.control.catch-exception.kotlin
- match: \b(if|else|while|for|do|return|when|where|break|continue)\b
scope: keyword.control.kotlin
- match: \b(in|is|!in|!is|as|as\?|assert)\b
scope: keyword.operator.kotlin
- match: (==|!=|===|!==|<=|>=|<|>)
scope: keyword.operator.comparison.kotlin
- match: (=)
scope: keyword.operator.assignment.kotlin
- match: (::)
scope: keyword.operator.kotlin
- match: (:)
scope: keyword.operator.declaration.kotlin
- match: \b(by)\b
scope: keyword.other.by.kotlin
- match: (\?\.)
scope: keyword.operator.safenav.kotlin
- match: (\.)
scope: keyword.operator.dot.kotlin
- match: (\?:)
scope: keyword.operator.elvis.kotlin
- match: (\-\-|\+\+)
scope: keyword.operator.increment-decrement.kotlin
- match: (\+=|\-=|\*=|\/=)
scope: keyword.operator.arithmetic.assign.kotlin
- match: (\.\.)
scope: keyword.operator.range.kotlin
- match: (\-|\+|\*|\/|%)
scope: keyword.operator.arithmetic.kotlin
- match: (!|&&|\|\|)
scope: keyword.operator.logical.kotlin
- match: (;)
scope: punctuation.terminator.kotlin
namespaces:
- match: \b(namespace)\b
scope: keyword.other.kotlin
- match: '\{'
push:
- match: '\}'
pop: true
- include: statements
parameters:
- match: (:)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: (?=,|\)|=)
pop: true
- include: types
- match: (=)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: (?=,|\))
pop: true
- include: expressions
- include: keywords
- match: \w+
scope: variable.parameter.function.kotlin
statements:
- include: namespaces
- include: typedefs
- include: classes
- include: functions
- include: variables
- include: getters-and-setters
- include: expressions
strings:
- match: '"""'
captures:
0: punctuation.definition.string.begin.kotlin
push:
- meta_scope: string.quoted.third.kotlin
- match: '"""'
captures:
0: punctuation.definition.string.end.kotlin
pop: true
- match: '(\$\w+|\$\{[^\}]+\})'
scope: variable.parameter.template.kotlin
- match: \\.
scope: constant.character.escape.kotlin
- match: '"'
captures:
0: punctuation.definition.string.begin.kotlin
push:
- meta_scope: string.quoted.double.kotlin
- match: '"'
captures:
0: punctuation.definition.string.end.kotlin
pop: true
- match: '(\$\w+|\$\{[^\}]+\})'
scope: variable.parameter.template.kotlin
- match: \\.
scope: constant.character.escape.kotlin
- match: "'"
captures:
0: punctuation.definition.string.begin.kotlin
push:
- meta_scope: string.quoted.single.kotlin
- match: "'"
captures:
0: punctuation.definition.string.end.kotlin
pop: true
- match: \\.
scope: constant.character.escape.kotlin
- match: "`"
captures:
0: punctuation.definition.string.begin.kotlin
push:
- meta_scope: string.quoted.single.kotlin
- match: "`"
captures:
0: punctuation.definition.string.end.kotlin
pop: true
typedefs:
- match: (?=\s*(?:type))
push:
- match: (?=$)
pop: true
- match: \b(type)\b
scope: keyword.other.kotlin
- match: <
push:
- match: ">"
pop: true
- include: generics
- include: expressions
types:
- match: \b(Nothing|Any|Unit|String|CharSequence|Int|Boolean|Char|Long|Double|Float|Short|Byte|dynamic)\b
scope: storage.type.buildin.kotlin
- match: \b(IntArray|BooleanArray|CharArray|LongArray|DoubleArray|FloatArray|ShortArray|ByteArray)\b
scope: storage.type.buildin.array.kotlin
- match: \b(Array|Collection|List|Map|Set|MutableList|MutableMap|MutableSet|Sequence)<\b
captures:
1: storage.type.buildin.collection.kotlin
push:
- match: ">"
pop: true
- include: types
- include: keywords
- match: \w+<
push:
- match: ">"
pop: true
- include: types
- include: keywords
- match: '\{'
push:
- match: '\}'
pop: true
- include: statements
- match: \(
push:
- match: \)
pop: true
- include: types
- match: (->)
scope: keyword.operator.declaration.kotlin
variables:
- match: (?=\s*\b(?:var|val)\b)
push:
- match: (?=:|=|(\b(by)\b)|$)
pop: true
- match: \b(var|val)\b
captures:
1: keyword.other.kotlin
push:
- match: (?=:|=|(\b(by)\b)|$)
pop: true
- match: <
push:
- match: ">"
pop: true
- include: generics
- match: '([\.<\?>\w]+\.)?(\w+)'
captures:
2: entity.name.variable.kotlin
- match: (:)
captures:
1: keyword.operator.declaration.kotlin
push:
- match: (?==|$)
pop: true
- include: types
- include: getters-and-setters
- match: \b(by)\b
captures:
1: keyword.other.kotlin
push:
- match: (?=$)
pop: true
- include: expressions
- match: (=)
captures:
1: keyword.operator.assignment.kotlin
push:
- match: (?=$)
pop: true
- include: expressions
- include: getters-and-setters
Submodule assets/syntaxes/Nix added at ebf06571f3
+609
View File
@@ -0,0 +1,609 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Nix
file_extensions:
- nix
scope: source.nix
contexts:
main:
- include: expression
comment:
- match: '/\*([^*]|\*[^\/])*'
push:
- meta_scope: comment.block.nix
- match: \*\/
pop: true
- include: comment-remark
- match: '\#'
push:
- meta_scope: comment.line.number-sign.nix
- match: $
pop: true
- include: comment-remark
attribute-bind:
- include: attribute-name
- include: attribute-bind-from-equals
attribute-bind-from-equals:
- match: \=
captures:
0: keyword.operator.bind.nix
push:
- match: \;
captures:
0: punctuation.terminator.bind.nix
pop: true
- include: expression
attribute-inherit:
- match: \binherit\b
captures:
0: keyword.other.inherit.nix
push:
- match: \;
captures:
0: punctuation.terminator.inherit.nix
pop: true
- match: \(
captures:
0: punctuation.section.function.arguments.nix
push:
- match: (?=\;)
pop: true
- match: \)
captures:
0: punctuation.section.function.arguments.nix
push:
- match: (?=\;)
pop: true
- include: bad-reserved
- include: attribute-name-single
- include: others
- include: expression
- match: '(?=[a-zA-Z\_])'
push:
- match: (?=\;)
pop: true
- include: bad-reserved
- include: attribute-name-single
- include: others
- include: others
attribute-name:
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
scope: entity.other.attribute-name.multipart.nix
- match: \.
- include: string-quoted
- include: interpolation
attribute-name-single:
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
scope: entity.other.attribute-name.single.nix
attrset-contents:
- include: attribute-inherit
- include: bad-reserved
- include: attribute-bind
- include: others
attrset-definition:
- match: '(?=\{)'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: '(\{)'
captures:
0: punctuation.definition.attrset.nix
push:
- match: '(\})'
captures:
0: punctuation.definition.attrset.nix
pop: true
- include: attrset-contents
- match: '(?<=\})'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
attrset-definition-brace-opened:
- match: '(?<=\})'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- match: (?=.?)
push:
- match: '\}'
captures:
0: punctuation.definition.attrset.nix
pop: true
- include: attrset-contents
attrset-for-sure:
- match: (?=\brec\b)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: \brec\b
captures:
0: keyword.other.nix
push:
- match: '(?=\{)'
pop: true
- include: others
- include: attrset-definition
- include: others
- match: '(?=\{\s*(\}|[^,?]*(=|;)))'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: attrset-definition
- include: others
attrset-or-function:
- match: '\{'
captures:
0: punctuation.definition.attrset-or-function.nix
push:
- match: '(?=([\])};]|\b(else|then)\b))'
pop: true
- match: '(?=(\s*\}|\"|\binherit\b|\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*(\s*\.|\s*=[^=])))'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: attrset-definition-brace-opened
- match: '(?=(\.\.\.|\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*\s*[,?]))'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-definition-brace-opened
- include: bad-reserved
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
captures:
0: variable.parameter.function.maybe.nix
push:
- match: '(?=([\])};]|\b(else|then)\b))'
pop: true
- match: (?=\.)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: attrset-definition-brace-opened
- match: \s*(\,)
captures:
1: keyword.operator.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-definition-brace-opened
- match: (?=\=)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: attribute-bind-from-equals
- include: attrset-definition-brace-opened
- match: (?=\?)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-parameter-default
- match: \,
captures:
0: keyword.operator.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-definition-brace-opened
- include: others
- include: others
bad-reserved:
- match: '(?<![\w''-])(if|then|else|assert|with|let|in|rec|inherit)(?![\w''-])'
scope: invalid.illegal.reserved.nix
comment-remark:
- match: (TODO|FIXME|BUG|\!\!\!):?
captures:
1: markup.bold.comment.nix
constants:
- match: \b(builtins|true|false|null)\b
captures:
0: constant.language.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- match: \b(scopedImport|import|isNull|abort|throw|baseNameOf|dirOf|removeAttrs|map|toString|derivationStrict|derivation)\b
captures:
0: support.function.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- match: '\b[0-9]+\b'
captures:
0: constant.numeric.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
expression:
- include: parens-and-cont
- include: list-and-cont
- include: string
- include: interpolation
- include: with-assert
- include: function-for-sure
- include: attrset-for-sure
- include: attrset-or-function
- include: let
- include: if
- include: operator-unary
- include: constants
- include: bad-reserved
- include: parameter-name-and-cont
- include: others
expression-cont:
- match: (?=.?)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: parens
- include: list
- include: string
- include: interpolation
- include: function-for-sure
- include: attrset-for-sure
- include: attrset-or-function
- match: '(\bor\b|\.|==|!=|!|\<\=|\<|\>\=|\>|&&|\|\||-\>|//|\?|\+\+|-|\*|/(?=([^*]|$))|\+)'
scope: keyword.operator.nix
- include: constants
- include: bad-reserved
- include: parameter-name
- include: others
function-body:
- match: '(@\s*([a-zA-Z\_][a-zA-Z0-9\_\''\-]*)\s*)?(\:)'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression
function-body-from-colon:
- match: (\:)
captures:
0: punctuation.definition.function.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression
function-contents:
- include: bad-reserved
- include: function-parameter
- include: others
function-definition:
- match: (?=.?)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-body-from-colon
- match: (?=.?)
push:
- match: (?=\:)
pop: true
- match: '(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*)'
captures:
0: variable.parameter.function.4.nix
push:
- match: (?=\:)
pop: true
- match: \@
push:
- match: (?=\:)
pop: true
- include: function-header-until-colon-no-arg
- include: others
- include: others
- match: '(?=\{)'
push:
- match: (?=\:)
pop: true
- include: function-header-until-colon-with-arg
- include: others
function-definition-brace-opened:
- match: (?=.?)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-body-from-colon
- match: (?=.?)
push:
- match: (?=\:)
pop: true
- include: function-header-close-brace-with-arg
- match: (?=.?)
push:
- match: '(?=\})'
pop: true
- include: function-contents
- include: others
function-for-sure:
- match: '(?=(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*\s*[:@]|\{[^}]*\}\s*:|\{[^#}"''/=]*[,\?]))'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: function-definition
function-header-close-brace-no-arg:
- match: '\}'
captures:
0: punctuation.definition.entity.function.nix
push:
- match: (?=\:)
pop: true
- include: others
function-header-close-brace-with-arg:
- match: '\}'
captures:
0: punctuation.definition.entity.function.nix
push:
- match: (?=\:)
pop: true
- include: function-header-terminal-arg
- include: others
function-header-open-brace:
- match: '\{'
captures:
0: punctuation.definition.entity.function.2.nix
push:
- match: '(?=\})'
pop: true
- include: function-contents
function-header-terminal-arg:
- match: (?=@)
push:
- match: (?=\:)
pop: true
- match: \@
push:
- match: (?=\:)
pop: true
- match: '(\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*)'
push:
- meta_scope: variable.parameter.function.3.nix
- match: (?=\:)
pop: true
- include: others
- include: others
function-header-until-colon-no-arg:
- match: '(?=\{)'
push:
- match: (?=\:)
pop: true
- include: function-header-open-brace
- include: function-header-close-brace-no-arg
function-header-until-colon-with-arg:
- match: '(?=\{)'
push:
- match: (?=\:)
pop: true
- include: function-header-open-brace
- include: function-header-close-brace-with-arg
function-parameter:
- match: (\.\.\.)
push:
- meta_scope: keyword.operator.nix
- match: '(,|(?=\}))'
pop: true
- include: others
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
captures:
0: variable.parameter.function.1.nix
push:
- match: '(,|(?=\}))'
captures:
0: keyword.operator.nix
pop: true
- include: whitespace
- include: comment
- include: function-parameter-default
- include: expression
- include: others
function-parameter-default:
- match: \?
captures:
0: keyword.operator.nix
push:
- match: "(?=[,}])"
pop: true
- include: expression
if:
- match: (?=\bif\b)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: \bif\b
captures:
0: keyword.other.nix
push:
- match: \bth(?=en\b)
captures:
0: keyword.other.nix
pop: true
- include: expression
- match: (?<=th)en\b
captures:
0: keyword.other.nix
push:
- match: \bel(?=se\b)
captures:
0: keyword.other.nix
pop: true
- include: expression
- match: (?<=el)se\b
captures:
0: keyword.other.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
captures:
0: keyword.other.nix
pop: true
- include: expression
illegal:
- match: .
scope: invalid.illegal
interpolation:
- match: '\$\{'
captures:
0: punctuation.section.embedded.begin.nix
push:
- meta_scope: markup.italic
- match: '\}'
captures:
0: punctuation.section.embedded.end.nix
pop: true
- include: expression
let:
- match: (?=\blet\b)
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: \blet\b
captures:
0: keyword.other.nix
push:
- match: '(?=([\])};,]|\b(in|else|then)\b))'
pop: true
- match: '(?=\{)'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: '\{'
push:
- match: '\}'
pop: true
- include: attrset-contents
- match: '(^|(?<=\}))'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- include: others
- include: attrset-contents
- include: others
- match: \bin\b
captures:
0: keyword.other.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression
list:
- match: '\['
captures:
0: punctuation.definition.list.nix
push:
- match: '\]'
captures:
0: punctuation.definition.list.nix
pop: true
- include: expression
list-and-cont:
- match: '(?=\[)'
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: list
- include: expression-cont
operator-unary:
- match: (!|-)
scope: keyword.operator.unary.nix
others:
- include: whitespace
- include: comment
- include: illegal
parameter-name:
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
captures:
0: variable.parameter.name.nix
parameter-name-and-cont:
- match: '\b[a-zA-Z\_][a-zA-Z0-9\_\''\-]*'
captures:
0: variable.parameter.name.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
parens:
- match: \(
captures:
0: punctuation.definition.expression.nix
push:
- match: \)
captures:
0: punctuation.definition.expression.nix
pop: true
- include: expression
parens-and-cont:
- match: (?=\()
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: parens
- include: expression-cont
string:
- match: (?=\'\')
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- match: \'\'
captures:
0: punctuation.definition.string.other.start.nix
push:
- meta_scope: string.quoted.other.nix
- match: \'\'(?!\$|\'|\\.)
captures:
0: punctuation.definition.string.other.end.nix
pop: true
- match: \'\'(\$|\'|\\.)
scope: constant.character.escape.nix
- include: interpolation
- include: expression-cont
- match: (?=\")
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: string-quoted
- include: expression-cont
- match: '([a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+)'
captures:
0: string.unquoted.path.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- match: '(\<[a-zA-Z0-9\.\_\-\+]+(\/[a-zA-Z0-9\.\_\-\+]+)*\>)'
captures:
0: string.unquoted.spath.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
- match: '([a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\'']+)'
captures:
0: string.unquoted.url.nix
push:
- match: '(?=([\])};,]|\b(else|then)\b))'
pop: true
- include: expression-cont
string-quoted:
- match: \"
captures:
0: punctuation.definition.string.double.start.nix
push:
- meta_scope: string.quoted.double.nix
- match: \"
captures:
0: punctuation.definition.string.double.end.nix
pop: true
- match: \\.
scope: constant.character.escape.nix
- include: interpolation
whitespace:
- match: \s+
with-assert:
- match: '(?<![\w''-])(with|assert)(?![\w''-])'
captures:
0: keyword.other.nix
push:
- match: \;
pop: true
- include: expression
+466
View File
@@ -0,0 +1,466 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: PowerShell
file_extensions:
- ps1
- psm1
- psd1
scope: source.powershell
contexts:
main:
- match: "<#"
captures:
0: punctuation.definition.comment.block.begin.powershell
push:
- meta_scope: comment.block.powershell
- match: "#>"
captures:
0: punctuation.definition.comment.block.end.powershell
pop: true
- include: commentEmbeddedDocs
- match: '[2-6]>&1|>>|>|<<|<|>|>\||[1-6]>|[1-6]>>'
scope: keyword.operator.redirection.powershell
- include: commands
- include: commentLine
- include: variable
- include: interpolatedStringContent
- include: function
- include: attribute
- include: UsingDirective
- include: type
- include: hashtable
- include: doubleQuotedString
- include: scriptblock
- include: doubleQuotedStringEscapes
- match: (?<!')'
captures:
0: punctuation.definition.string.begin.powershell
push:
- meta_scope: string.quoted.single.powershell
- match: "'(?!')"
captures:
0: punctuation.definition.string.end.powershell
pop: true
- match: "''"
scope: constant.character.escape.powershell
- match: \@"(?=$)
push:
- meta_scope: string.quoted.double.heredoc.powershell
- match: ^"@
pop: true
- include: variableNoProperty
- include: doubleQuotedStringEscapes
- include: interpolation
- match: \@'(?=$)
push:
- meta_scope: string.quoted.single.heredoc.powershell
- match: ^'@
pop: true
- match: "''"
scope: constant.character.escape.powershell
- include: numericConstant
- match: (@)(\()
captures:
1: keyword.other.array.begin.powershell
2: punctuation.section.group.begin.powershell
push:
- meta_scope: meta.group.array-expression.powershell
- match: \)
captures:
0: punctuation.section.group.end.powershell
pop: true
- include: main
- match: (\$)(\()
comment: "TODO: move to repo; make recursive."
captures:
1: punctuation.definition.variable.powershell
2: punctuation.section.group.begin.powershell
push:
- meta_scope: meta.group.complex.subexpression.powershell
- match: \)
captures:
0: punctuation.section.group.end.powershell
pop: true
- include: main
- match: '(\b(([A-Za-z0-9\-_\.]+)\.(?i:exe|com|cmd|bat))\b)'
scope: support.function.powershell
- match: (?<!\w|-|\.)((?i:begin|break|catch|continue|data|default|define|do|dynamicparam|else|elseif|end|exit|finally|for|from|if|in|inlinescript|parallel|param|process|return|sequence|switch|throw|trap|try|until|var|while)|%|\?)(?!\w)
scope: keyword.control.powershell
- match: '(?<!\w|-|[^\)]\.)((?i:(foreach|where)(?!-object))|%|\?)(?!\w)'
scope: keyword.control.powershell
- match: (?<!\w)(--%)(?!\w)
comment: This should be moved to the repository at some point.
captures:
1: keyword.control.powershell
push:
- match: $
pop: true
- match: .+
scope: string.unquoted.powershell
- match: (?<!\w)((?i:hidden|static))(?!\w)
comment: This should only be relevant inside a class but will require a rework of how classes are matched. This is a temp fix.
scope: storage.modifier.powershell
- match: '(?<!\w|-)((?i:class)|%|\?)(?:\s)+((?:\p{L}|\d|_|-|)+)\b'
comment: capture should be entity.name.type, but it doesn't provide a good color in the default schema.
captures:
1: storage.type.powershell
2: entity.name.function
- match: (?<!\w)-(?i:is(?:not)?|as)\b
scope: keyword.operator.comparison.powershell
- match: '(?<!\w)-(?i:[ic]?(?:eq|ne|[gl][te]|(?:not)?(?:like|match|contains|in)|replace))(?!\p{L})'
scope: keyword.operator.comparison.powershell
- match: '(?<!\w)-(?i:join|split)(?!\p{L})|!'
scope: keyword.operator.unary.powershell
- match: '(?<!\w)-(?i:and|or|not|xor)(?!\p{L})|!'
scope: keyword.operator.logical.powershell
- match: '(?<!\w)-(?i:band|bor|bnot|bxor|shl|shr)(?!\p{L})'
scope: keyword.operator.bitwise.powershell
- match: '(?<!\w)-(?i:f)(?!\p{L})'
scope: keyword.operator.string-format.powershell
- match: "[+%*/-]?=|[+/*%-]"
scope: keyword.operator.assignment.powershell
- match: '\|{2}|&{2}|;'
scope: punctuation.terminator.statement.powershell
- match: '&|(?<!\w)\.(?= )|`|,|\|'
scope: keyword.operator.other.powershell
- match: (?<!\s|^)\.\.(?=\-?\d|\(|\$)
comment: This is very imprecise, is there a syntax for 'must come after...'
scope: keyword.operator.range.powershell
RequiresDirective:
- match: (?<=#)(?i:(requires))\s
captures:
0: keyword.control.requires.powershell
push:
- meta_scope: meta.requires.powershell
- match: $
pop: true
- match: \-(?i:Modules|PSSnapin|RunAsAdministrator|ShellId|Version)
scope: keyword.other.powershell
- match: '(?<!-)\b\p{L}+|\d+(?:\.\d+)*'
scope: variable.parameter.powershell
- include: hashtable
UsingDirective:
- match: (?<!\w)(?i:(using))\s+(?i:(namespace|module))\s+(?i:((?:\w+(?:\.)?)+))
captures:
1: keyword.control.using.powershell
2: keyword.other.powershell
3: variable.parameter.powershell
attribute:
- match: '(\[)\s*\b(?i)(cmdletbinding|alias|outputtype|parameter|validatenotnull|validatenotnullorempty|validatecount|validateset|allownull|allowemptycollection|allowemptystring|validatescript|validaterange|validatepattern|validatelength)\b'
captures:
1: punctuation.section.bracket.begin.powershell
2: support.function.attribute.powershell
push:
- meta_scope: meta.attribute.powershell
- match: '(\])'
captures:
1: punctuation.section.bracket.end.powershell
pop: true
- match: \(
captures:
0: punctuation.section.group.begin.powershell
push:
- match: \)
captures:
0: punctuation.section.group.end.powershell
pop: true
- include: variable
- include: variableNoProperty
- include: hashtable
- include: scriptblock
- include: doubleQuotedStringEscapes
- include: doubleQuotedString
- include: type
- include: numericConstant
- include: doubleQuotedString
- include: main
- match: (?i)\b(mandatory|valuefrompipeline|valuefrompipelinebypropertyname|valuefromremainingarguments|position|parametersetname|defaultparametersetname|supportsshouldprocess|supportspaging|positionalbinding|helpuri|confirmimpact|helpmessage)\b(?:\s+)?(=)?
captures:
1: variable.parameter.attribute.powershell
2: keyword.operator.assignment.powershell
- match: (?<!')'
captures:
0: punctuation.definition.string.begin.powershell
push:
- meta_scope: string.quoted.single.powershell
- match: "'(?!')"
captures:
0: punctuation.definition.string.end.powershell
pop: true
- match: "''"
scope: constant.character.escape.powershell
commands:
- match: '(?:(\p{L}|\d|_|-|\\|\:)*\\)?\b(?i:Add|Approve|Assert|Backup|Block|Build|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Deploy|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Write)\-.+?(?:\.(?i:exe|cmd|bat|ps1))?\b'
comment: "Verb-Noun pattern:"
scope: support.function.powershell
- match: (?<!\w)(?i:foreach-object)(?!\w)
comment: Builtin cmdlets with reserved verbs
scope: support.function.powershell
- match: (?<!\w)(?i:where-object)(?!\w)
comment: Builtin cmdlets with reserved verbs
scope: support.function.powershell
- match: (?<!\w)(?i:sort-object)(?!\w)
comment: Builtin cmdlets with reserved verbs
scope: support.function.powershell
- match: (?<!\w)(?i:tee-object)(?!\w)
comment: Builtin cmdlets with reserved verbs
scope: support.function.powershell
commentEmbeddedDocs:
- match: ^(?i:(?:\s?|#)+(\.)(COMPONENT|DESCRIPTION|EXAMPLE|EXTERNALHELP|FORWARDHELPCATEGORY|FORWARDHELPTARGETNAME|FUNCTIONALITY|INPUTS|LINK|NOTES|OUTPUTS|REMOTEHELPRUNSPACE|ROLE|SYNOPSIS))
scope: comment.documentation.embedded.powershell
captures:
1: constant.string.documentation.powershell
2: keyword.operator.documentation.powershell
- match: '(?i:\s?(\.)(PARAMETER|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP)\s+([a-z0-9-_]+))'
scope: comment.documentation.embedded.powershell
captures:
1: constant.string.documentation.powershell
2: keyword.operator.documentation.powershell
3: keyword.operator.documentation.powershell
commentLine:
- match: '(?<![`\\-])#'
captures:
0: punctuation.definition.comment.powershell
push:
- meta_scope: comment.line.powershell
- match: $\n?
captures:
0: punctuation.definition.comment.powershell
pop: true
- include: commentEmbeddedDocs
- include: RequiresDirective
doubleQuotedString:
- match: (?<!(?<!`)")"
captures:
0: punctuation.definition.string.begin.powershell
push:
- meta_scope: string.quoted.double.powershell
- match: '"(?!")'
captures:
0: punctuation.definition.string.end.powershell
pop: true
- match: '(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,64}\b'
- include: variableNoProperty
- include: variable
- include: doubleQuotedStringEscapes
- include: interpolation
- match: '`\s*$'
scope: keyword.other.powershell
doubleQuotedStringEscapes:
- match: '`[0abnfrvt"''$`]'
scope: constant.character.escape.powershell
- match: '""'
scope: constant.character.escape.powershell
function:
- match: '^(?:\s*+)(?i)(function|filter|configuration|workflow)\s+(?:(global|local|script|private):)?((?:\p{L}|\d|_|-|\.)+)'
captures:
0: meta.function.powershell
1: storage.type.powershell
2: storage.modifier.scope.powershell
3: entity.name.function.powershell
push:
- match: '(?=\{|\()'
pop: true
- include: commentLine
hashtable:
- match: '(@)(\{)'
captures:
1: keyword.other.hashtable.begin.powershell
2: punctuation.section.braces.begin.powershell
push:
- meta_scope: meta.hashtable.powershell
- match: '(\})'
captures:
1: punctuation.section.braces.end.powershell
pop: true
- match: \b((?:\'|\")?)(\w+)((?:\'|\")?)(?:\s+)?(=)(?:\s+)?
scope: meta.hashtable.assignment.powershell
captures:
1: punctuation.definition.string.begin.powershell
2: variable.other.readwrite.powershell
3: punctuation.definition.string.end.powershell
4: keyword.operator.assignment.powershell
- include: scriptblock
- include: main
interpolatedStringContent:
- match: \(
captures:
0: punctuation.section.group.begin.powershell
push:
- meta_content_scope: interpolated.simple.source.powershell
- match: \)
captures:
0: punctuation.section.group.end.powershell
pop: true
- include: main
- include: interpolation
- include: interpolatedStringContent
interpolation:
- match: (\$)(\()
captures:
1: punctuation.definition.variable.powershell
2: punctuation.section.group.begin.powershell
push:
- meta_content_scope: interpolated.complex.source.powershell
- match: \)
captures:
0: punctuation.section.group.end.powershell
pop: true
- include: main
- include: interpolation
- include: interpolatedStringContent
numericConstant:
- match: '(?<!\w)([-+]?0(?:x|X)[0-9a-fA-F_]+(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.hex.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?(?:[0-9_]+)?\.[0-9_]+(?:(?:e|E)[0-9]+)?(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.integer.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?0(?:b|B)[01_]+(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.octal.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?[0-9_]+(?:e|E)(?:[0-9_])?+(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.integer.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?[0-9_]+\.(?:e|E)(?:[0-9_])?+(?:F|f|D|d|M|m)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.integer.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?[0-9_]+[\.]?(?:F|f|D|d|M|m))((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.integer.powershell
2: keyword.other.powershell
- match: '(?<!\w)([-+]?[0-9_]+[\.]?(?:U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?)((?i:[kmgtp]b)?)\b'
captures:
1: constant.numeric.integer.powershell
2: keyword.other.powershell
scriptblock:
- match: '\{'
captures:
0: punctuation.section.braces.begin.powershell
push:
- meta_scope: meta.scriptblock.powershell
- match: '\}'
captures:
0: punctuation.section.braces.end.powershell
pop: true
- include: main
type:
- match: '\['
captures:
0: punctuation.section.bracket.begin.powershell
push:
- match: '\]'
captures:
0: punctuation.section.bracket.end.powershell
pop: true
- match: '(?!\d+|\.)(?:\p{L}|\p{N}|\.)+'
scope: storage.type.powershell
- include: main
variable:
- match: (\$)(?i:(False|Null|True))\b
comment: These are special constants.
captures:
0: constant.language.powershell
1: punctuation.definition.variable.powershell
- match: '(\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
comment: These are the other built-in constants.
captures:
0: support.constant.variable.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: '(\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
comment: Automatic variables are not constants, but they are read-only. In monokai (default) color schema support.variable doesn't have color, so we use constant.
captures:
0: support.constant.automatic.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: '(\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))((?:\.(?:\p{L}|\d|_)+)*\b)?\b'
comment: Style preference variables as language variables so that they stand out.
captures:
0: variable.language.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: '(?i:(\$|@)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)?'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: storage.modifier.scope.powershell
4: variable.other.member.powershell
- match: '(?i:(\$)(\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)?'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: punctuation.section.braces.begin.powershell
3: storage.modifier.scope.powershell
5: punctuation.section.braces.end.powershell
6: variable.other.member.powershell
- match: '(?i:(\$|@)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+))((?:\.(?:\p{L}|\d|_)+)*\b)?'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: support.variable.drive.powershell
4: variable.other.member.powershell
- match: '(?i:(\$)(\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\}))((?:\.(?:\p{L}|\d|_)+)*\b)?'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: punctuation.section.braces.begin.powershell
3: support.variable.drive.powershell
5: punctuation.section.braces.end.powershell
6: variable.other.member.powershell
variableNoProperty:
- match: (\$)(?i:(False|Null|True))\b
comment: These are special constants.
captures:
0: constant.language.powershell
1: punctuation.definition.variable.powershell
- match: (\$)(?i:(Error|ExecutionContext|Host|Home|PID|PsHome|PsVersionTable|ShellID))\b
comment: These are the other built-in constants.
captures:
0: support.constant.variable.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: (\$)(?i:(\$|\^|\?|_|Args|ConsoleFileName|Event|EventArgs|EventSubscriber|ForEach|Input|LastExitCode|Matches|MyInvocation|NestedPromptLevel|Profile|PSBoundParameters|PsCmdlet|PsCulture|PSDebugContext|PSItem|PSCommandPath|PSScriptRoot|PsUICulture|Pwd|Sender|SourceArgs|SourceEventArgs|StackTrace|Switch|This))\b
comment: Automatic variables are not constants, but they are read-only...
captures:
0: support.variable.automatic.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: (\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|ProgressPreference|PsCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|VerbosePreference|WarningPreference|WhatIfPreference))\b
comment: Style preference variables as language variables so that they stand out.
captures:
0: variable.language.powershell
1: punctuation.definition.variable.powershell
3: variable.other.member.powershell
- match: '(?i:(\$|@)(global|local|private|script|using|workflow):((?:\p{L}|\d|_)+))'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: storage.modifier.scope.powershell
4: variable.other.member.powershell
- match: '(?i:(\$)(\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: storage.modifier.scope.powershell
4: keyword.other.powershell
5: variable.other.member.powershell
- match: '(?i:(\$)((?:\p{L}|\d|_)+:)?((?:\p{L}|\d|_)+))'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: support.variable.drive.powershell
4: variable.other.member.powershell
- match: '(?i:(\$)(\{)((?:\p{L}|\d|_)+:)?([^}]*[^}`])(\}))'
captures:
0: variable.other.readwrite.powershell
1: punctuation.definition.variable.powershell
2: punctuation.section.braces.begin
3: support.variable.drive.powershell
5: punctuation.section.braces.end
+371
View File
@@ -0,0 +1,371 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Swift
file_extensions:
- swift
first_line_match: ^#!/.*\bswift
scope: source.swift
contexts:
main:
- include: shebang-line
- include: comment
- include: attribute
- include: literal
- include: operator
- include: declaration
- include: storage-type
- include: keyword
- include: type
- include: boolean
comment:
- include: documentation-comment
- include: block-comment
- include: in-line-comment
access-level-modifier:
- match: \b(open|public|internal|fileprivate|private)\b(?:\(set\))?
comment: access-level-modifier
scope: keyword.other.access-level-modifier.swift
arithmetic-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.arithmetic.swift
array-type:
- match: \b(Array)(<)
captures:
1: support.type.array.swift
2: punctuation.array.begin.swift
push:
- meta_scope: meta.array.swift
- match: (>)
captures:
1: punctuation.array.end.swift
pop: true
- include: main
assignment-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/|%|<<|>>|&|\^|\||&&|\|\|)?=(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.assignment.swift
attribute:
- match: '((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))(\()'
captures:
1: storage.modifier.attribute.swift
2: punctuation.definition.attribute.swift
3: punctuation.definition.attribute-arguments.begin.swift
push:
- meta_content_scope: meta.attribute.arguments.swift
- match: \)
captures:
0: punctuation.definition.attribute-arguments.end.swift
pop: true
- include: main
- match: '((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))'
captures:
1: storage.modifier.attribute.swift
2: punctuation.definition.attribute.swift
bitwise-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])(&|\||\^|<<|>>)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.bitwise.swift
block-comment:
- match: /\*
comment: Block comment
captures:
0: punctuation.definition.comment.block.begin.swift
push:
- meta_scope: comment.block.swift
- match: \*/
captures:
0: punctuation.definition.comment.block.end.swift
pop: true
boolean:
- match: \b(true|false)\b
scope: keyword.constant.boolean.swift
branch-statement-keyword:
- include: if-statement-keyword
- include: switch-statement-keyword
catch-statement-keyword:
- match: \b(catch|do)\b
comment: catch-statement
scope: kewyord.control.catch.swift
code-block:
- match: '(\{)'
comment: code-block
captures:
1: punctuation.definition.code-block.begin.swift
push:
- match: '(\})'
captures:
1: punctuation.definition.code-block.end.swift
pop: true
- include: main
collection-type:
- include: array-type
- include: dictionary-type
- match: \b(Array|Dictionary)\b
scope: support.type.swift
comparative-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])((=|!)==?|(<|>)=?|~=)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.comparative.swift
control-transfer-statement-keyword:
- match: \b(continue|break|fallthrough|return)\b
comment: control-transfer-statement
scope: keyword.control.transfer.swift
custom-operator:
- match: '(?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:])'
scope: keyword.operator.custom.prefix.unary.swift
- match: '(?<![\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:\.])'
scope: keyword.operator.custom.postfix.unary.swift
- match: '(?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?=[\s)\]},;:])'
scope: keyword.operator.custom.binary.swift
declaration:
- include: import-declaration
- include: function-declaration
declaration-modifier:
- match: \b(class|convenience|dynamic|final|lazy|(non)?mutating|optional|override|required|static|unowned((un)?safe)?|weak)\b
comment: declaration-modifier
scope: keyword.other.declaration-modifier.swift
dictionary-type:
- match: \b(Dictionary)(<)
captures:
1: support.type.dictionary.swift
2: punctuation.dictionary.begin.swift
push:
- meta_scope: meta.dictionary.swift
- match: (>)
captures:
1: punctuation.dictionary.end.swift
pop: true
- include: main
documentation-comment:
- match: /\*\*
comment: Documentation comment
captures:
0: punctuation.definition.comment.block.documentation.begin.swift
push:
- meta_scope: comment.block.documentation.swift
- match: \*/
captures:
0: punctuation.definition.comment.block.documentation.end.swift
pop: true
floating-point-literal:
- match: '\b([0-9][0-9_]*)(\.([0-9][0-9_]*))?([eE][+\-]?([0-9][0-9_]*))?\b'
comment: floating-point-literal -> (decimal-literal)(decimal-fraction)?(decimal-exponent)?
- match: '\b(0x\h[\h_]*)(\.(0x\h[\h_]*))?([pP][+\-]?(0x\h[\h_]*))\b'
comment: floating-point-literal -> (hexadecimal-literal)(hexadecimal-fraction)?(hexadecimal-exponent)
function-body:
- include: code-block
function-declaration:
- match: '\b(func)\s+(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)\s*(?=\(|<)'
comment: function-declaration
captures:
1: storage.type.function.swift
2: entity.type.function.swift
push:
- meta_scope: meta.function-declaration.swift
- match: '(?<=\})'
pop: true
- include: generic-parameter-clause
- include: parameter-clause
- include: function-result
- include: function-body
function-result:
- match: '(?<![/=\-+!*%<>&|\^~.])(\->)(?![/=\-+!*%<>&|\^~.])\s*'
comment: function-result
captures:
1: keyword.operator.function-result.swift
push:
- meta_scope: meta.function-result.swift
- match: '\s*(?=\{)'
pop: true
- include: type
generic-parameter-clause:
- match: (<)
comment: generic-parameter-clause
captures:
1: punctuation.definition.generic-parameter-clause.begin.swift
push:
- meta_scope: meta.generic-parameter-clause.swift
- match: (>)
captures:
1: punctuation.definition.generic-parameter-clause.end.swift
pop: true
- include: main
identifier:
- match: '(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B)'
comment: identifier
scope: meta.identifier.swift
if-statement-keyword:
- match: \b(if|else)\b
comment: if-statement
scope: keyword.control.if.swift
import-declaration:
- match: '\b(import)\s+(?:(typealias|struct|class|enum|protocol|var|func)\s+)?((?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)(?:\.(?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+))*)'
comment: import-declaration
scope: meta.import.swift
captures:
1: keyword.other.import.swift
2: storage.modifier.swift
3: support.type.module.import.swift
in-line-comment:
- match: (//).*
comment: In-line comment
scope: comment.line.double-slash.swift
captures:
1: punctuation.definition.comment.line.double-slash.swift
increment-decrement-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])(\+\+|\-\-)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.increment-or-decrement.swift
integer-literal:
- match: '(\B\-|\b)(0b[01][01_]*)\b'
comment: binary-literal
scope: constant.numeric.integer.binary.swift
- match: '(\B\-|\b)(0o[0-7][0-7_]*)\b'
comment: octal-literal
scope: constant.numeric.integer.octal.swift
- match: '(\B\-|\b)([0-9][0-9_]*)\b'
comment: decimal-literal
scope: constant.numeric.integer.decimal.swift
- match: '(\B\-|\b)(0x\h[\h_]*)\b'
comment: hexadecimal-literal
scope: constant.numeric.integer.hexadecimal.swift
integer-type:
- match: \bU?Int(8|16|32|64)?\b
comment: Int types
scope: support.type.swift
keyword:
- include: branch-statement-keyword
- include: control-transfer-statement-keyword
- include: loop-statement-keyword
- include: catch-statement-keyword
- include: operator-declaration-modifier
- include: declaration-modifier
- include: access-level-modifier
- match: \b(class|deinit|enum|extension|func|import|init|let|protocol|static|struct|subscript|typealias|var|throws|rethrows)\b
comment: declaration keyword
scope: keyword.declaration.swift
- match: \b(break|case|continue|default|do|else|fallthrough|if|in|for|return|switch|where|while|repeat|catch|guard|defer|try|throw)\b
comment: statement keyword
scope: keyword.statement.swift
- match: \b(as|dynamicType|is|new|super|self|Self|Type)\b
comment: expression and type keyword
scope: keyword.other.statement.swift
- match: \b(associativity|didSet|get|infix|inout|left|mutating|none|nonmutating|operator|override|postfix|precedence|prefix|right|set|unowned((un)?safe)?|weak|willSet)\b
comment: other keyword
scope: keyword.other.swift
literal:
- include: integer-literal
- include: floating-point-literal
- include: nil-literal
- include: string-literal
- include: special-literal
logical-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])(!|&&|\|\|)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.logical.swift
loop-statement-keyword:
- match: \b(while|repeat|for|in)\b
comment: loop-statement
scope: keyword.control.loop.swift
nil-literal:
- match: \bnil\b
comment: nil-literal
scope: constant.nil.swift
operator:
- include: comparative-operator
- include: assignment-operator
- include: logical-operator
- include: remainder-operator
- include: increment-decrement-operator
- include: overflow-operator
- include: range-operator
- include: bitwise-operator
- include: arithmetic-operator
- include: ternary-operator
- include: type-casting-operator
- include: custom-operator
operator-declaration-modifier:
- match: \b(operator|prefix|infix|postfix)\b
comment: operator-declaration
scope: keyword.other.operator.swift
optional-type:
- match: \b(Optional)(<)
scope: meta.optional.swift
overflow-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])\&(\+|\-|\*|\/|%)(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.overflow.swift
parameter-clause:
- match: (\()
comment: parameter-clause
captures:
1: punctuation.definition.function-arguments.begin.swift
push:
- meta_scope: meta.parameter-clause.swift
- match: (\))
captures:
1: punctuation.definition.function-arguments.end.swift
pop: true
- include: main
primitive-type:
- match: \b(Int|Float|Double|String|Bool|Character|Void)\b
comment: Primitive types
scope: support.type.swift
protocol-composition-type:
- match: \b(protocol)(<)
scope: meta.protocol.swift
range-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])\.\.(?:\.)?(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.range.swift
remainder-operator:
- match: '(?<![/=\-+!*%<>&|\^~.])\%(?![/=\-+!*%<>&|\^~.])'
scope: keyword.operator.remainder.swift
shebang-line:
- match: ^(#!).*$
comment: Shebang line
scope: comment.line.shebang.swift
captures:
1: punctuation.definition.comment.line.shebang.swift
special-literal:
- match: \b__(FILE|LINE|COLUMN|FUNCTION)__\b
scope: keyword.other.literal.swift
storage-type:
- match: \b(var|func|let|class|enum|struct|protocol|extension|typealias)\b
scope: storage.type.swift
string-literal:
- match: \"
captures:
0: string.quoted.double.swift
push:
- meta_scope: meta.literal.string.swift
- match: \"
captures:
0: string.quoted.double.swift
pop: true
- match: '\\([0tnr\"\''\\]|x\h{2}|u\h{4}|U\h{8})'
scope: constant.character.escape.swift
- match: (\\\()
captures:
1: support.punctuation.expression.begin.swift
push:
- meta_content_scope: meta.expression.swift
- match: (\))
captures:
1: support.punctuation.expression.end.swift
pop: true
- include: scope:source.swift
- match: (\"|\\)
scope: invalid.illegal.swift
- match: (.)
scope: string.quoted.double.swift
switch-statement-keyword:
- match: \b(switch|case|default|where)\b
comment: switch-statement
scope: keyword.control.switch.swift
ternary-operator:
- match: '(?<=[\s(\[{,;:])(\?|:)(?=[\s)\]},;:])'
scope: keyword.operator.ternary.swift
type:
- include: primitive-type
- include: integer-type
- include: collection-type
- include: optional-type
- include: protocol-composition-type
type-casting-operator:
- match: \b(is\b|as(\?\B|\b))
scope: keyword.operator.type-casting.swift
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+91
View File
@@ -0,0 +1,91 @@
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: VimL
file_extensions:
- vim
- .vimrc
scope: source.viml
contexts:
main:
- include: comment
- include: string_quoted_double
- include: string_quoted_single
- include: string_regex
- include: inline_comment
- include: number_int
- include: number_hex
- include: keyword
- include: support_function
- include: support_variable
- include: support_type
- include: function_params
- include: function_definition
- include: function_call
- include: function
- include: variable
- include: expr
comment:
- match: ^\s*".*$
scope: comment.line.quotes.viml
captures:
1: punctuation.definition.comment.vim
expr:
- match: (\|\||&&|==(\?|#)?|(!|>|<)=(#|\?)?|(=|!)~(#|\?)?|(>|<)(#|\?)is|isnot|\.|\*|\\|%)
scope: storage.function.viml
function:
- match: \b(fu(n|nction)?|end(f|fu|fun|function)?)\b
scope: storage.function.viml
function_call:
- match: '(([sgbwtl]|)?:?[0-9a-zA-Z_#]+)(?=\()'
scope: support.function.any-method
function_definition:
- match: '^\s*(function)\s*!?\s+(?=(s:)?[0-9a-zA-Z_#]+\s*\()'
captures:
1: storage.function.viml
push:
- meta_scope: meta.function.viml
- match: (\()
captures:
1: punctuation.definition.parameters.begin.viml
pop: true
- match: "(s:)?[0-9a-zA-Z_#]+"
scope: entity.name.function.viml
function_params:
- match: '-\w+='
scope: support.type.viml
inline_comment:
- match: '(?!\$)(")(?!\{).*$\n?'
scope: comment.line.quotes.viml
captures:
1: punctuation.definition.comment.vim
keyword:
- match: \b(if|while|for|try|return|throw|end(if|for|while|try)?|au(g|group)|else(if|)?|do|in|catch|finally|:)\b
scope: keyword.control.viml
number_hex:
- match: "#[0-9a-f]{6}"
scope: constant.numeric.hex
number_int:
- match: '-?\d+'
scope: constant.numeric.integer
string_quoted_double:
- match: '"(\\\\|\\"|\n[^\S\n]*\\|[^\n"])*"'
scope: string.quoted.double.viml
string_quoted_single:
- match: '''(''''|\n[^\S\n]*\\|[^\n''])*'''
scope: string.quoted.single.viml
string_regex:
- match: '/(\\\\|\\/|\n[^\S\n]*\\|[^\n/])*/'
scope: string.regexp.viml
support_function:
- match: \b(set(local|global)?|let|command|filetype|colorscheme|\w*map|\w*a(b|brev)?|syn|exe(c|cute)?|ec(ho|)?|au(tocmd|)?)\b
scope: support.function.viml
support_type:
- match: <.*?>
scope: support.type.viml
support_variable:
- match: '\b(am(enu|)?|(hl|inc)?search|[Bb]uf([Nn]ew[Ff]ile|[Rr]ead)?|[Ff]ile[Tt]ype)\b'
scope: support.variable.viml
variable:
- match: '([sSgGbBwWlLaAvV]:|@|$|&(?!&))\w*'
scope: variable.other.viml
+5
View File
@@ -0,0 +1,5 @@
// Output the square of a number.
fn print_square(num: f64) {
let result = f64::powf(num, 2.0);
println!("The square of {:.2} is {:.2}.", num, result);
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+31 -5
View File
@@ -11,19 +11,29 @@ pack() {
local tempdir local tempdir
local out_dir local out_dir
local package_name local package_name
local gcc_prefix
tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp) tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp)
out_dir=$(pwd) out_dir=$(pwd)
package_name="$PROJECT_NAME-$TRAVIS_TAG-$TARGET" package_name="$PROJECT_NAME-$TRAVIS_TAG-$TARGET"
if [[ $TARGET == "arm-unknown-linux-gnueabihf" ]]; then
gcc_prefix="arm-linux-gnueabihf-"
elif [[ $TARGET == "aarch64-unknown-linux-gnu" ]]; then
gcc_prefix="aarch64-linux-gnu-"
else
gcc_prefix=""
fi
# create a "staging" directory # create a "staging" directory
mkdir "$tempdir/$package_name" mkdir "$tempdir/$package_name"
# copying the main binary # copying the main binary
cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/" cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/"
strip "$tempdir/$package_name/$PROJECT_NAME" "${gcc_prefix}"strip "$tempdir/$package_name/$PROJECT_NAME"
# readme and license # manpage, readme and license
cp "doc/$PROJECT_NAME.1" "$tempdir/$package_name"
cp README.md "$tempdir/$package_name" cp README.md "$tempdir/$package_name"
cp LICENSE-MIT "$tempdir/$package_name" cp LICENSE-MIT "$tempdir/$package_name"
cp LICENSE-APACHE "$tempdir/$package_name" cp LICENSE-APACHE "$tempdir/$package_name"
@@ -41,17 +51,28 @@ make_deb() {
local version local version
local dpkgname local dpkgname
local conflictname local conflictname
local gcc_prefix
case $TARGET in case $TARGET in
x86_64*) x86_64*)
architecture=amd64 architecture=amd64
gcc_prefix=""
;; ;;
i686*) i686*)
architecture=i386 architecture=i386
gcc_prefix=""
;;
aarch64*)
architecture=arm64
gcc_prefix="aarch64-linux-gnu-"
;;
arm*hf)
architecture=armhf
gcc_prefix="arm-linux-gnueabihf-"
;; ;;
*) *)
echo "ERROR: unknown target" >&2 echo "make_deb: skipping target '${TARGET}'" >&2
return 1 return 0
;; ;;
esac esac
version=${TRAVIS_TAG#v} version=${TRAVIS_TAG#v}
@@ -67,7 +88,11 @@ make_deb() {
# copy the main binary # copy the main binary
install -Dm755 "target/$TARGET/release/$PROJECT_NAME" "$tempdir/usr/bin/$PROJECT_NAME" install -Dm755 "target/$TARGET/release/$PROJECT_NAME" "$tempdir/usr/bin/$PROJECT_NAME"
strip "$tempdir/usr/bin/$PROJECT_NAME" "${gcc_prefix}"strip "$tempdir/usr/bin/$PROJECT_NAME"
# manpage
install -Dm644 "doc/$PROJECT_NAME.1" "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
gzip --best "$tempdir/usr/share/man/man1/$PROJECT_NAME.1"
# readme and license # readme and license
install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md" install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md"
@@ -86,6 +111,7 @@ Architecture: $architecture
Provides: $PROJECT_NAME Provides: $PROJECT_NAME
Conflicts: $conflictname Conflicts: $conflictname
Description: A cat(1) clone with wings. Description: A cat(1) clone with wings.
A cat(1) clone with syntax highlighting and Git integration.
EOF EOF
fakeroot dpkg-deb --build "$tempdir" "${dpkgname}_${version}_${architecture}.deb" fakeroot dpkg-deb --build "$tempdir" "${dpkgname}_${version}_${architecture}.deb"
+26
View File
@@ -0,0 +1,26 @@
# This script takes care of packaging the build artifacts that will go in the
# release zipfile
$SRC_DIR = $PWD.Path
$STAGE = [System.Guid]::NewGuid().ToString()
Set-Location $ENV:Temp
New-Item -Type Directory -Name $STAGE
Set-Location $STAGE
$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"
Copy-Item "$SRC_DIR\target\release\bat.exe" '.\'
# readme and license
Copy-Item $SRC_DIR\README.md '.\'
Copy-Item $SRC_DIR\LICENSE-MIT '.\'
Copy-Item $SRC_DIR\LICENSE-APACHE '.\'
7z a "$ZIP" *
Push-AppveyorArtifact "$ZIP"
Set-Location ..
Remove-Item $STAGE -Force -Recurse
Set-Location $SRC_DIR
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -ex
if [ "$TRAVIS_OS_NAME" != linux ]; then
exit 0
fi
sudo apt-get update
# needed for musl targets
sudo apt-get install -y musl-tools
# needed to build deb packages
sudo apt-get install -y fakeroot
# needed for i686 linux gnu target
if [[ $TARGET == i686-unknown-linux-gnu ]]; then
sudo apt-get install -y gcc-multilib
fi
# needed for cross-compiling for arm
if [[ $TARGET == arm-unknown-linux-gnueabihf ]]; then
sudo apt-get install -y \
gcc-4.8-arm-linux-gnueabihf \
binutils-arm-linux-gnueabihf \
libc6-armhf-cross \
libc6-dev-armhf-cross
fi
# needed for cross-compiling for arm64
if [[ $TARGET == aarch64-unknown-linux-gnu ]]; then
sudo apt-get install -y \
gcc-4.8-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
gcc-aarch64-linux-gnu
fi
Executable
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -ex
# Incorporate TARGET env var to the build and test process
cargo build --target "$TARGET" --verbose
# We cannot run arm executables on linux
if [[ $TARGET != arm-unknown-linux-gnueabihf ]] && [[ $TARGET != aarch64-unknown-linux-gnu ]]; then
cargo test --target "$TARGET" --verbose
# Run 'bat' on its own source code and the README
cargo run --target "$TARGET" -- src/main.rs README.md --paging=never
fi
+23
View File
@@ -0,0 +1,23 @@
# Alternatives
The following table tries to give an overview *from `bat`s perspective*, i.e. we only compare
categories which are relevant for `bat`. Some of these projects have completely different goals and
if you are not looking for a program like `bat`, this comparison might not be for you.
| | bat | [pygments](http://pygments.org/) | [highlight](http://www.andre-simon.de/doku/highlight/highlight.php) | [ccat](https://github.com/jingweno/ccat) | [source-highlight](https://www.gnu.org/software/src-highlite/) | [hicat](https://github.com/rstacruz/hicat) | [coderay](https://github.com/rubychan/coderay) | [rouge](https://github.com/jneen/rouge) |
|----------------------------------------------|---------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------|------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|
| Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: |
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: |
| Languages (circa) | 100 | 300 | 200 | 7 | 80 | 130 | 30 | 130 |
| Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: |
| Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Execution time [ms] (`jquery-3.3.1.js`) | 624 | 789 | 400 | 80 | 300 | 316 | 157 | 695 |
| Execution time [ms] (`miniz.c`) | 66 | 656 | 26 | 8 | 53 | 141 | 75 | 254 |
| Execution time [ms] (370 kB XML file) | 238 | 487 | 129 | 111 | 110 | 339 | 147 | 359 |
If you think that some entries in this table are outdated or wrong, please open a ticket or pull
request.
Some other alternatives that are also related, but not yet included in the table:
- [lesspipe](https://github.com/wofr06/lesspipe)
+117
View File
@@ -0,0 +1,117 @@
.TH BAT "1"
.SH NAME
bat \- manual page for bat
.SH DESCRIPTION
bat - a cat(1) clone with syntax highlighting and Git integration.
.SH "USAGE"
.IP
bat [OPTIONS] [FILE]...
.IP
bat <SUBCOMMAND>
.SH "OPTIONS"
.HP
\fB\-l\fR, \fB\-\-language\fR <language>
.IP
Explicitly set the language for syntax highlighting. The language can be
specified as a name (like 'C++' or 'LaTeX') or possible file extension (like
\&'cpp', 'hpp' or 'md'). Use '\-\-list\-languages' to show all supported language
names and file extensions.
.HP
\fB\-\-list\-languages\fR
.IP
Display a list of supported languages for syntax highlighting.
.HP
\fB\-\-theme\fR <theme>
.IP
Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all
available themes. To set a default theme, export the BAT_THEME environment
variable (e.g.: export BAT_THEME="TwoDark").
.HP
\fB\-\-list\-themes\fR
.IP
Display a list of supported themes for syntax highlighting.
.HP
\fB\-\-style\fR <style\-components>
.IP
Configure which elements (line numbers, file headers, grid borders, Git
modifications, ..) to display in addition to the file contents. The argument
is a comma\-separated list of components to display (e.g.
\&'numbers,changes,grid') or a pre\-defined style ('full'). To set a default
theme, export the BAT_STYLE environment variable (e.g.: export
BAT_STYLE="numbers"). [possible values: auto, full, plain, changes, header,
grid, numbers]
.HP
\fB\-p\fR
.IP
Only show plain style, no decorations. This is an alias for '\-\-style=plain'
.HP
\fB\-n\fR, \fB\-\-number\fR
.IP
Only show line numbers, no other decorations. This is an alias for
\&'\-\-style=numbers'
.HP
\fB\-\-line\-range\fR <N:M>
.IP
Only print the specified range of lines for each file. For example:
.RS
.IP "\-\-line\-range 30:40"
prints lines 30 to 40
.IP "\-\-line\-range :40"
prints lines 1 to 40
.IP "\-\-line\-range 40:"
prints lines 40 to the end of the file
.RE
.HP
\fB\-\-color\fR <when>
.IP
Specify when to use colored output. The automatic mode only enables colors if
an interactive terminal is detected. [default: auto] [possible values: auto,
never, always]
.HP
\fB\-\-decorations\fR <when>
.IP
Specify when to use the decorations that have been specified via '\-\-style'.
The automatic mode only enables decorations if an interactive terminal is
detected. [default: auto] [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]
.HP
\fB\-\-wrap\fR <mode>
.TP
Specify the text\-wrapping mode. [default: auto]
[possible values: auto,
.IP
never, character]
.HP
\fB\-u\fR
.IP
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered'). The
output is always unbuffered \- this option is simply ignored.
.HP
\fB\-\-tabs\fR <tabs>
.IP
Sets the tab width. Use a width of 0 to pass tabs through directly
.HP
\fB\-h\fR, \fB\-\-help\fR
.IP
Print this help message.
.HP
\fB\-V\fR, \fB\-\-version\fR
.IP
Show version information.
.SH "ARGS"
.IP
<FILE>...
.IP
File(s) to print / concatenate. Use a dash ('\-') or no argument at all to read
from standard input.
.SH "SUBCOMMANDS"
.IP
cache
.IP
Modify the syntax\-definition and theme cache. See "bat cache --help" for more information
+326
View File
@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1000"
height="286.64285"
viewBox="0 0 1000 286.64285"
version="1.1"
xml:space="preserve"
style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996"
id="svg1285"
sodipodi:docname="logo-header.svg"
inkscape:version="0.92.2 2405546, 2018-03-11"><metadata
id="metadata1289"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1175"
id="namedview1287"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.82573726"
inkscape:cx="438.92362"
inkscape:cy="320.87266"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1285"
showguides="true"
inkscape:guide-bbox="true" />
<rect
style="opacity:1;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.14294769px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
id="rect1929"
width="1000"
height="286.64285"
x="0"
y="0" /><g
id="g929"
transform="translate(0,13.321425)"><g
transform="matrix(5.1207879,0,0,4.741146,45.483811,-7057.152)"
id="g1168">
<path
d="m 77.792,1533.05 c 0,0.32 -0.064,0.61 -0.192,0.88 -0.128,0.27 -0.3,0.5 -0.516,0.7 -0.216,0.19 -0.468,0.34 -0.756,0.45 -0.288,0.11 -0.596,0.16 -0.924,0.16 h -4.02 v -8.52 h 4.104 c 0.296,0 0.564,0.07 0.804,0.19 0.24,0.13 0.444,0.3 0.612,0.5 0.168,0.21 0.298,0.44 0.39,0.7 0.092,0.26 0.138,0.52 0.138,0.78 0,0.44 -0.108,0.83 -0.324,1.19 -0.216,0.35 -0.516,0.62 -0.9,0.8 0.488,0.14 0.874,0.41 1.158,0.8 0.284,0.39 0.426,0.85 0.426,1.37 z m -0.84,-0.15 c 0,-0.21 -0.036,-0.41 -0.108,-0.6 -0.072,-0.2 -0.174,-0.37 -0.306,-0.52 -0.132,-0.15 -0.288,-0.27 -0.468,-0.36 -0.18,-0.09 -0.374,-0.14 -0.582,-0.14 h -3.264 v 3.23 h 3.18 c 0.216,0 0.418,-0.04 0.606,-0.13 0.188,-0.09 0.352,-0.21 0.492,-0.35 0.14,-0.15 0.25,-0.33 0.33,-0.52 0.08,-0.2 0.12,-0.4 0.12,-0.61 z m -4.728,-5.45 v 3.15 h 2.928 c 0.208,0 0.402,-0.04 0.582,-0.13 0.18,-0.09 0.334,-0.21 0.462,-0.35 0.128,-0.14 0.228,-0.31 0.3,-0.5 0.072,-0.19 0.108,-0.38 0.108,-0.59 0,-0.22 -0.034,-0.42 -0.102,-0.62 -0.068,-0.19 -0.164,-0.35 -0.288,-0.49 -0.124,-0.14 -0.27,-0.26 -0.438,-0.34 -0.168,-0.08 -0.352,-0.13 -0.552,-0.13 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1162"
inkscape:connector-curvature="0" />
<path
d="m 88.436,1526.72 h 0.708 l 3.54,8.52 h -0.888 l -1.104,-2.66 h -3.828 l -1.092,2.66 h -0.9 z m 2.064,5.2 -1.716,-4.21 -1.74,4.21 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1164"
inkscape:connector-curvature="0" />
<path
d="m 105.716,1527.47 h -3.036 v 7.77 h -0.84 v -7.77 h -3.036 v -0.75 h 6.912 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1166"
inkscape:connector-curvature="0" />
</g><g
transform="translate(1.9578e-5)"
id="g6103"><g
id="g1172"
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
<path
inkscape:connector-curvature="0"
id="path1170"
style="fill:url(#_Linear1)"
d="m 4399.57,773.907 c 0,0 35.33,20.718 42.25,24.779 13.1,7.683 47.96,27.832 64.24,37.232 1.77,1.027 2.87,2.923 2.87,4.975 0.01,2.053 -1.08,3.952 -2.85,4.986 -27.1,15.803 -110.2,64.254 -128.26,74.788 -2.16,1.254 -4.82,1.237 -6.95,-0.046 -13.57,-8.147 -62.93,-37.791 -75.02,-44.875 -16.93,-9.911 -37.27,-21.84 -37.27,-21.84 z" />
</g><g
id="g1176"
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
<path
inkscape:connector-curvature="0"
id="path1174"
style="fill:#31369e"
d="m 4269.48,860.305 c -54.5,-31.918 -88.34,-51.732 -117.18,-68.621 -3.98,-2.335 -6.43,-6.608 -6.44,-11.228 0,-4.619 2.45,-8.893 6.44,-11.229 l 319.41,-187.171 c 2.02,-1.186 4.52,-1.198 6.56,-0.032 2.03,1.166 3.29,3.333 3.29,5.678 0,29.472 0,107.932 0,138.732 0,7.842 -4.16,15.094 -10.94,19.049 -13.32,7.783 -54.43,31.465 -67.73,39.233 0,0 -133.3,75.654 -133.41,75.589 z" />
</g><g
id="g1180"
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
<path
inkscape:connector-curvature="0"
id="path1178"
style="fill:#1d2167"
d="m 4604.42,705.593 85.54,34.367 v -63.802 c 0,-2.628 -1.37,-5.066 -3.62,-6.431 -2.24,-1.365 -5.04,-1.459 -7.37,-0.247 -5.93,3.078 -74.55,36.113 -74.55,36.113 z" />
</g><g
id="g1184"
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
<path
inkscape:connector-curvature="0"
id="path1182"
style="fill:url(#_Linear2)"
d="m 4976.91,704.019 c 0,0 -8.53,-4.983 -8.56,-5 -79.92,-46.83 -170.16,-99.71 -199.6,-116.963 -2.02,-1.186 -4.52,-1.198 -6.56,-0.032 -2.04,1.166 -3.29,3.333 -3.29,5.678 0,29.472 0,107.932 0,138.732 0,7.842 4.16,15.094 10.93,19.049 13.33,7.783 68.33,39.913 68.33,39.913 z" />
</g><g
id="g1188"
transform="matrix(0.31374232,0,0,0.31374232,-949.56013,-170.6326)">
<path
inkscape:connector-curvature="0"
id="path1186"
style="fill:url(#_Linear3)"
d="m 4968.44,699.073 c 0,0 -235.66,138.235 -263.83,154.762 -3.01,1.764 -6.73,1.783 -9.76,0.05 -3.02,-1.733 -4.89,-4.953 -4.89,-8.44 V 731.796 c 0,0 -111.16,-50.383 -128.47,-59.371 -2.33,-1.212 -4.9781,-0.84921 -7.37,0.247 -1.9592,0.89788 -3.62,3.803 -3.62,6.431 v 166.342 c 0,3.487 0.43,15.045 -12.02,22.226 -2.41,1.392 -130.21,75.278 -130.21,75.278 l 211.99,122.751 c 0,0 377.71,-221.201 467.9,-274.016 3.98,-2.335 6.43,-6.608 6.43,-11.228 0,-4.619 -2.45,-8.893 -6.43,-11.229 -24.64,-14.438 -119.72,-70.154 -119.72,-70.154"
sodipodi:nodetypes="cccsccsssccccscc" />
</g></g><g
transform="matrix(0.18627124,0,0,0.22786575,340.43532,-286.36087)"
id="g1262">
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1192">
<path
d="m 374.487,2270.67 h 4.788 l 23.94,57.61 h -6.006 l -7.465,-18.01 h -25.887 l -7.385,18.01 h -6.086 z m 13.958,35.14 -11.604,-28.49 -11.767,28.49 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1190"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1196">
<path
d="m 421.293,2307.02 c 0,-2.97 0.514,-5.78 1.542,-8.44 1.028,-2.65 2.475,-4.96 4.342,-6.94 1.866,-1.97 4.098,-3.52 6.695,-4.66 2.596,-1.14 5.464,-1.7 8.602,-1.7 4.003,0 7.492,0.9 10.468,2.71 2.975,1.82 5.221,4.26 6.735,7.35 l -5.356,1.7 c -1.19,-2.16 -2.853,-3.85 -4.99,-5.07 -2.137,-1.22 -4.504,-1.83 -7.101,-1.83 -2.164,0 -4.179,0.44 -6.046,1.3 -1.866,0.87 -3.489,2.05 -4.869,3.53 -1.379,1.49 -2.461,3.26 -3.246,5.32 -0.784,2.05 -1.176,4.3 -1.176,6.73 0,2.38 0.405,4.63 1.217,6.74 0.811,2.11 1.92,3.94 3.327,5.48 1.407,1.54 3.043,2.76 4.91,3.65 1.866,0.89 3.854,1.34 5.964,1.34 1.353,0 2.692,-0.19 4.017,-0.57 1.326,-0.38 2.556,-0.91 3.692,-1.58 1.137,-0.68 2.11,-1.45 2.922,-2.32 0.811,-0.86 1.379,-1.78 1.704,-2.75 l 5.437,1.62 c -0.595,1.51 -1.461,2.91 -2.597,4.18 -1.136,1.27 -2.475,2.38 -4.017,3.32 -1.541,0.95 -3.246,1.68 -5.112,2.2 -1.867,0.51 -3.801,0.77 -5.802,0.77 -3.084,0 -5.924,-0.59 -8.521,-1.75 -2.597,-1.16 -4.842,-2.76 -6.736,-4.79 -1.893,-2.03 -3.367,-4.36 -4.422,-7.02 -1.055,-2.65 -1.583,-5.49 -1.583,-8.52 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1194"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1200">
<path
d="m 476.962,2329.1 c -2.001,0 -3.854,-0.34 -5.558,-1.02 -1.705,-0.67 -3.192,-1.61 -4.464,-2.8 -1.271,-1.19 -2.258,-2.58 -2.962,-4.18 -0.703,-1.59 -1.055,-3.31 -1.055,-5.15 0,-1.84 0.433,-3.54 1.299,-5.11 0.865,-1.57 2.083,-2.92 3.652,-4.06 1.568,-1.14 3.435,-2.02 5.599,-2.64 2.164,-0.62 4.544,-0.93 7.141,-0.93 2.164,0 4.355,0.19 6.573,0.57 2.218,0.38 4.193,0.92 5.924,1.62 v -3.81 c 0,-3.74 -1.055,-6.7 -3.165,-8.89 -2.11,-2.19 -5.031,-3.29 -8.764,-3.29 -2.164,0 -4.382,0.44 -6.654,1.3 -2.272,0.87 -4.572,2.11 -6.898,3.74 l -1.948,-3.66 c 5.465,-3.67 10.766,-5.51 15.906,-5.51 5.302,0 9.467,1.48 12.497,4.46 3.03,2.97 4.544,7.09 4.544,12.33 v 19.07 c 0,1.52 0.677,2.28 2.029,2.28 v 4.86 c -0.919,0.17 -1.623,0.25 -2.11,0.25 -1.406,0 -2.502,-0.35 -3.286,-1.06 -0.785,-0.7 -1.204,-1.67 -1.258,-2.92 l -0.162,-3.33 c -1.948,2.55 -4.396,4.5 -7.345,5.85 -2.948,1.35 -6.126,2.03 -9.535,2.03 z m 1.299,-4.22 c 2.867,0 5.504,-0.54 7.912,-1.63 2.407,-1.08 4.233,-2.51 5.478,-4.3 0.486,-0.48 0.852,-1.01 1.095,-1.58 0.244,-0.57 0.365,-1.09 0.365,-1.58 v -6.9 c -1.839,-0.7 -3.746,-1.24 -5.721,-1.62 -1.975,-0.38 -3.99,-0.57 -6.046,-0.57 -3.895,0 -7.06,0.81 -9.494,2.43 -2.435,1.63 -3.652,3.76 -3.652,6.41 0,1.3 0.257,2.52 0.771,3.66 0.514,1.13 1.217,2.12 2.11,2.96 0.893,0.84 1.961,1.5 3.205,1.99 1.245,0.48 2.57,0.73 3.977,0.73 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1198"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1204">
<path
d="m 528.158,2326.26 c -0.325,0.16 -0.798,0.38 -1.42,0.65 -0.622,0.27 -1.339,0.54 -2.151,0.81 -0.811,0.27 -1.731,0.51 -2.759,0.73 -1.028,0.21 -2.11,0.32 -3.246,0.32 -1.19,0 -2.326,-0.16 -3.408,-0.49 -1.082,-0.32 -2.029,-0.82 -2.84,-1.5 -0.812,-0.67 -1.461,-1.52 -1.948,-2.55 -0.487,-1.03 -0.73,-2.22 -0.73,-3.57 v -30.27 h -5.843 v -4.38 h 5.843 v -14.29 h 5.518 v 14.29 h 9.738 v 4.38 h -9.738 v 28.73 c 0.108,1.56 0.663,2.71 1.664,3.44 1,0.73 2.15,1.1 3.448,1.1 1.569,0 2.949,-0.26 4.139,-0.77 1.19,-0.52 1.948,-0.88 2.272,-1.1 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1202"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1208">
<path
d="m 547.959,2307.02 c 0,-2.97 0.514,-5.78 1.542,-8.44 1.027,-2.65 2.475,-4.96 4.341,-6.94 1.866,-1.97 4.098,-3.52 6.695,-4.66 2.597,-1.14 5.464,-1.7 8.602,-1.7 4.003,0 7.493,0.9 10.468,2.71 2.976,1.82 5.221,4.26 6.736,7.35 l -5.356,1.7 c -1.19,-2.16 -2.854,-3.85 -4.991,-5.07 -2.137,-1.22 -4.504,-1.83 -7.101,-1.83 -2.164,0 -4.179,0.44 -6.045,1.3 -1.867,0.87 -3.49,2.05 -4.869,3.53 -1.38,1.49 -2.462,3.26 -3.246,5.32 -0.785,2.05 -1.177,4.3 -1.177,6.73 0,2.38 0.406,4.63 1.217,6.74 0.812,2.11 1.921,3.94 3.327,5.48 1.407,1.54 3.044,2.76 4.91,3.65 1.866,0.89 3.855,1.34 5.965,1.34 1.352,0 2.691,-0.19 4.016,-0.57 1.326,-0.38 2.557,-0.91 3.693,-1.58 1.136,-0.68 2.11,-1.45 2.921,-2.32 0.812,-0.86 1.38,-1.78 1.704,-2.75 l 5.437,1.62 c -0.595,1.51 -1.46,2.91 -2.596,4.18 -1.136,1.27 -2.475,2.38 -4.017,3.32 -1.542,0.95 -3.246,1.68 -5.113,2.2 -1.866,0.51 -3.8,0.77 -5.802,0.77 -3.084,0 -5.924,-0.59 -8.521,-1.75 -2.597,-1.16 -4.842,-2.76 -6.735,-4.79 -1.894,-2.03 -3.368,-4.36 -4.423,-7.02 -1.055,-2.65 -1.582,-5.49 -1.582,-8.52 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1206"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1212">
<path
d="m 593.24,2269.05 h 5.519 v 49.66 c 0,1.57 0.432,2.8 1.298,3.69 0.866,0.89 2.083,1.34 3.652,1.34 0.595,0 1.298,-0.08 2.11,-0.24 0.811,-0.16 1.569,-0.38 2.272,-0.65 l 0.974,4.46 c -1.028,0.43 -2.286,0.79 -3.774,1.06 -1.487,0.27 -2.772,0.4 -3.854,0.4 -2.543,0 -4.545,-0.72 -6.005,-2.15 -1.461,-1.43 -2.192,-3.45 -2.192,-6.04 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1210"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1216">
<path
d="m 630.651,2329.1 c -3.084,0 -5.897,-0.59 -8.44,-1.75 -2.543,-1.16 -4.747,-2.74 -6.614,-4.75 -1.866,-2 -3.313,-4.32 -4.341,-6.97 -1.028,-2.66 -1.542,-5.44 -1.542,-8.36 0,-2.98 0.527,-5.79 1.582,-8.44 1.055,-2.65 2.516,-4.98 4.383,-6.98 1.866,-2 4.071,-3.6 6.613,-4.79 2.543,-1.19 5.329,-1.78 8.359,-1.78 3.029,0 5.829,0.59 8.399,1.78 2.57,1.19 4.788,2.79 6.654,4.79 1.867,2 3.327,4.33 4.382,6.98 1.055,2.65 1.583,5.46 1.583,8.44 0,2.92 -0.514,5.7 -1.542,8.36 -1.028,2.65 -2.475,4.97 -4.342,6.97 -1.866,2.01 -4.084,3.59 -6.654,4.75 -2.57,1.16 -5.397,1.75 -8.48,1.75 z m -15.338,-21.75 c 0,2.38 0.406,4.58 1.218,6.61 0.811,2.03 1.907,3.82 3.286,5.36 1.38,1.54 3.003,2.74 4.869,3.61 1.867,0.86 3.855,1.3 5.965,1.3 2.11,0 4.098,-0.45 5.964,-1.34 1.867,-0.89 3.503,-2.11 4.91,-3.65 1.406,-1.54 2.516,-3.34 3.327,-5.4 0.812,-2.06 1.217,-4.27 1.217,-6.65 0,-2.33 -0.405,-4.53 -1.217,-6.62 -0.811,-2.08 -1.921,-3.89 -3.327,-5.43 -1.407,-1.55 -3.043,-2.76 -4.91,-3.66 -1.866,-0.89 -3.854,-1.34 -5.964,-1.34 -2.11,0 -4.085,0.45 -5.924,1.34 -1.84,0.9 -3.463,2.13 -4.869,3.7 -1.407,1.56 -2.516,3.39 -3.327,5.47 -0.812,2.09 -1.218,4.32 -1.218,6.7 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1214"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1220">
<path
d="m 694.029,2328.28 h -5.518 v -23.61 c 0,-5.03 -0.744,-8.68 -2.232,-10.95 -1.488,-2.28 -3.773,-3.41 -6.857,-3.41 -1.623,0 -3.246,0.29 -4.869,0.89 -1.623,0.59 -3.124,1.43 -4.504,2.52 -1.379,1.08 -2.61,2.36 -3.692,3.85 -1.082,1.49 -1.867,3.1 -2.354,4.83 v 25.88 h -5.518 v -42.27 h 5.032 v 9.57 c 1.731,-3.08 4.206,-5.57 7.425,-7.46 3.219,-1.9 6.722,-2.84 10.509,-2.84 2.326,0 4.301,0.43 5.924,1.29 1.623,0.87 2.921,2.09 3.895,3.65 0.974,1.57 1.677,3.5 2.11,5.77 0.433,2.27 0.649,4.79 0.649,7.54 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1218"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1224">
<path
d="m 721.62,2329.1 c -3.084,0 -5.91,-0.59 -8.48,-1.75 -2.57,-1.16 -4.801,-2.76 -6.695,-4.79 -1.893,-2.03 -3.368,-4.36 -4.423,-7.02 -1.055,-2.65 -1.582,-5.49 -1.582,-8.52 0,-2.97 0.527,-5.77 1.582,-8.4 1.055,-2.62 2.516,-4.92 4.382,-6.89 1.867,-1.98 4.099,-3.55 6.695,-4.71 2.597,-1.16 5.41,-1.74 8.44,-1.74 3.084,0 5.91,0.58 8.48,1.74 2.57,1.16 4.775,2.74 6.614,4.75 1.839,2 3.273,4.3 4.301,6.89 1.028,2.6 1.542,5.36 1.542,8.28 0,0.44 0,0.87 0,1.3 0,0.43 -0.027,0.73 -0.081,0.89 h -36.193 c 0.162,2.28 0.689,4.37 1.582,6.29 0.893,1.92 2.042,3.59 3.449,4.99 1.407,1.41 3.016,2.5 4.828,3.29 1.813,0.78 3.747,1.18 5.803,1.18 1.352,0 2.705,-0.19 4.057,-0.57 1.353,-0.38 2.597,-0.89 3.733,-1.54 1.136,-0.65 2.164,-1.45 3.084,-2.4 0.919,-0.94 1.623,-1.99 2.11,-3.12 l 4.787,1.3 c -0.649,1.57 -1.568,2.99 -2.759,4.26 -1.19,1.27 -2.569,2.38 -4.138,3.32 -1.569,0.95 -3.3,1.68 -5.194,2.2 -1.893,0.51 -3.868,0.77 -5.924,0.77 z m 15.581,-24.19 c -0.162,-2.27 -0.69,-4.34 -1.582,-6.21 -0.893,-1.86 -2.029,-3.47 -3.409,-4.82 -1.379,-1.35 -2.975,-2.41 -4.788,-3.17 -1.812,-0.76 -3.746,-1.13 -5.802,-1.13 -2.056,0 -4.003,0.37 -5.843,1.13 -1.839,0.76 -3.449,1.82 -4.828,3.17 -1.38,1.35 -2.489,2.97 -3.327,4.87 -0.839,1.89 -1.339,3.95 -1.502,6.16 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1222"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1228">
<path
d="m 818.344,2286.01 h 5.437 l -18.178,42.27 h -4.544 l -9.089,-21.58 -9.008,21.58 h -4.544 l -18.178,-42.27 h 5.356 l 15.418,36.59 8.034,-19.31 -7.222,-17.2 h 4.626 l 5.518,13.79 5.518,-13.79 h 4.707 l -7.223,17.2 8.034,19.31 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1226"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1232">
<path
d="m 828.65,2328.28 v -42.27 h 5.518 v 42.27 z m 0,-51.12 v -8.11 h 5.518 v 8.11 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1230"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1236">
<path
d="m 864.193,2326.26 c -0.324,0.16 -0.798,0.38 -1.42,0.65 -0.622,0.27 -1.339,0.54 -2.15,0.81 -0.812,0.27 -1.731,0.51 -2.759,0.73 -1.028,0.21 -2.11,0.32 -3.246,0.32 -1.19,0 -2.327,-0.16 -3.409,-0.49 -1.082,-0.32 -2.028,-0.82 -2.84,-1.5 -0.811,-0.67 -1.461,-1.52 -1.947,-2.55 -0.487,-1.03 -0.731,-2.22 -0.731,-3.57 v -30.27 h -5.843 v -4.38 h 5.843 v -14.29 h 5.518 v 14.29 h 9.738 v 4.38 h -9.738 v 28.73 c 0.109,1.56 0.663,2.71 1.664,3.44 1.001,0.73 2.15,1.1 3.449,1.1 1.569,0 2.948,-0.26 4.139,-0.77 1.19,-0.52 1.947,-0.88 2.272,-1.1 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1234"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1240">
<path
d="m 904.201,2328.28 h -5.519 v -23.61 c 0,-4.81 -0.825,-8.41 -2.475,-10.79 -1.65,-2.38 -4.071,-3.57 -7.263,-3.57 -1.569,0 -3.124,0.31 -4.666,0.93 -1.542,0.62 -2.989,1.47 -4.341,2.56 -1.353,1.08 -2.53,2.35 -3.53,3.81 -1.001,1.46 -1.745,3.06 -2.232,4.79 v 25.88 h -5.518 v -59.23 h 5.518 v 26.53 c 1.677,-3.19 4.003,-5.71 6.979,-7.55 2.975,-1.83 6.194,-2.75 9.657,-2.75 2.434,0 4.49,0.44 6.167,1.33 1.677,0.9 3.057,2.14 4.139,3.74 1.082,1.59 1.866,3.51 2.353,5.76 0.487,2.24 0.731,4.72 0.731,7.42 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1238"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1244">
<path
d="m 983.314,2286.01 h 5.437 l -18.177,42.27 h -4.545 l -9.088,-21.58 -9.008,21.58 h -4.545 l -18.177,-42.27 h 5.356 l 15.418,36.59 8.034,-19.31 -7.222,-17.2 h 4.625 l 5.519,13.79 5.518,-13.79 h 4.707 l -7.223,17.2 8.034,19.31 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1242"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1248">
<path
d="m 993.62,2328.28 v -42.27 h 5.519 v 42.27 z m 0,-51.12 v -8.11 h 5.519 v 8.11 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1246"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1252">
<path
d="m 1044.42,2328.28 h -5.52 v -23.61 c 0,-5.03 -0.74,-8.68 -2.23,-10.95 -1.49,-2.28 -3.77,-3.41 -6.86,-3.41 -1.62,0 -3.24,0.29 -4.87,0.89 -1.62,0.59 -3.12,1.43 -4.5,2.52 -1.38,1.08 -2.61,2.36 -3.69,3.85 -1.08,1.49 -1.87,3.1 -2.36,4.83 v 25.88 h -5.51 v -42.27 h 5.03 v 9.57 c 1.73,-3.08 4.2,-5.57 7.42,-7.46 3.22,-1.9 6.73,-2.84 10.51,-2.84 2.33,0 4.3,0.43 5.93,1.29 1.62,0.87 2.92,2.09 3.89,3.65 0.97,1.57 1.68,3.5 2.11,5.77 0.43,2.27 0.65,4.79 0.65,7.54 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1250"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1256">
<path
d="m 1070.71,2328.85 c -2.92,0 -5.58,-0.61 -7.99,-1.82 -2.41,-1.22 -4.49,-2.83 -6.25,-4.83 -1.76,-2 -3.12,-4.3 -4.1,-6.9 -0.97,-2.6 -1.46,-5.27 -1.46,-8.03 0,-2.92 0.48,-5.72 1.42,-8.4 0.95,-2.68 2.29,-5.02 4.02,-7.02 1.73,-2 3.8,-3.6 6.21,-4.79 2.4,-1.19 5.07,-1.78 7.99,-1.78 3.63,0 6.76,0.9 9.41,2.71 2.66,1.82 4.93,4.1 6.82,6.86 v -8.84 h 4.95 v 42.44 c 0,2.92 -0.55,5.5 -1.66,7.75 -1.11,2.24 -2.6,4.12 -4.47,5.64 -1.86,1.51 -4.05,2.65 -6.57,3.4 -2.51,0.76 -5.18,1.14 -7.99,1.14 -4.87,0 -8.79,-0.86 -11.77,-2.6 -2.97,-1.73 -5.38,-4.05 -7.22,-6.97 l 3.41,-2.68 c 1.67,2.7 3.89,4.69 6.65,5.96 2.76,1.27 5.74,1.91 8.93,1.91 2.05,0 4,-0.28 5.84,-0.85 1.84,-0.57 3.45,-1.41 4.83,-2.52 1.38,-1.11 2.47,-2.51 3.29,-4.22 0.81,-1.7 1.21,-3.69 1.21,-5.96 v -8.36 c -1.62,2.7 -3.84,4.84 -6.65,6.41 -2.81,1.57 -5.76,2.35 -8.85,2.35 z m 1.55,-4.62 c 1.62,0 3.21,-0.3 4.78,-0.89 1.57,-0.6 2.99,-1.4 4.26,-2.4 1.28,-1 2.34,-2.12 3.21,-3.37 0.86,-1.24 1.43,-2.51 1.7,-3.81 v -13.07 c -0.59,-1.51 -1.4,-2.92 -2.43,-4.22 -1.03,-1.29 -2.19,-2.4 -3.49,-3.32 -1.3,-0.92 -2.69,-1.65 -4.18,-2.19 -1.49,-0.55 -2.99,-0.82 -4.5,-0.82 -2.39,0 -4.51,0.5 -6.37,1.5 -1.87,1.01 -3.45,2.32 -4.75,3.94 -1.3,1.62 -2.29,3.46 -2.96,5.52 -0.68,2.06 -1.02,4.14 -1.02,6.25 0,2.27 0.41,4.43 1.22,6.49 0.81,2.06 1.93,3.86 3.37,5.4 1.43,1.54 3.09,2.76 4.99,3.65 1.89,0.89 3.95,1.34 6.17,1.34 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1254"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.28,0,0,1,-97.8353,0)"
id="g1260">
<path
d="m 1115.51,2329.1 c -3.3,0 -6.52,-0.55 -9.66,-1.63 -3.14,-1.08 -5.84,-2.65 -8.11,-4.7 l 2.51,-3.74 c 2.38,1.95 4.8,3.41 7.27,4.39 2.46,0.97 5.09,1.46 7.91,1.46 3.41,0 6.12,-0.69 8.15,-2.07 2.03,-1.38 3.05,-3.34 3.05,-5.89 0,-1.19 -0.27,-2.17 -0.82,-2.96 -0.54,-0.78 -1.33,-1.47 -2.39,-2.07 -1.05,-0.59 -2.38,-1.12 -3.98,-1.58 -1.59,-0.46 -3.44,-0.93 -5.56,-1.42 -2.43,-0.59 -4.54,-1.19 -6.32,-1.78 -1.79,-0.6 -3.26,-1.28 -4.43,-2.03 -1.16,-0.76 -2.03,-1.69 -2.59,-2.8 -0.57,-1.11 -0.86,-2.51 -0.86,-4.18 0,-2.11 0.42,-3.98 1.26,-5.6 0.84,-1.63 1.98,-2.96 3.41,-4.02 1.43,-1.05 3.11,-1.85 5.03,-2.39 1.92,-0.54 3.96,-0.81 6.13,-0.81 3.24,0 6.19,0.52 8.84,1.58 2.65,1.05 4.79,2.45 6.41,4.18 l -2.67,3.24 c -1.57,-1.62 -3.48,-2.84 -5.72,-3.65 -2.25,-0.81 -4.59,-1.22 -7.02,-1.22 -1.47,0 -2.82,0.15 -4.06,0.45 -1.25,0.3 -2.34,0.77 -3.29,1.42 -0.94,0.65 -1.69,1.47 -2.23,2.48 -0.54,1 -0.81,2.17 -0.81,3.52 0,1.14 0.19,2.06 0.57,2.76 0.37,0.71 1,1.32 1.86,1.83 0.87,0.51 1.96,0.97 3.29,1.38 1.33,0.41 2.94,0.83 4.83,1.26 2.7,0.65 5.08,1.3 7.14,1.94 2.05,0.66 3.77,1.41 5.15,2.28 1.38,0.86 2.42,1.92 3.13,3.16 0.7,1.25 1.05,2.76 1.05,4.55 0,3.89 -1.49,6.98 -4.46,9.25 -2.98,2.27 -6.98,3.41 -12.01,3.41 z"
style="fill:#1d2167;fill-rule:nonzero"
id="path1258"
inkscape:connector-curvature="0" />
</g>
</g></g>
<defs
id="defs1283"><linearGradient
id="_Linear1"
x1="0"
y1="0"
x2="1"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-158.501,-265.604,265.604,-158.501,4436.06,964.047)"><stop
offset="0"
style="stop-color:rgb(49,54,158);stop-opacity:1"
id="stop1266" /><stop
offset="0.52"
style="stop-color:rgb(38,42,122);stop-opacity:1"
id="stop1268" /><stop
offset="1"
style="stop-color:black;stop-opacity:1"
id="stop1270" /></linearGradient><linearGradient
id="_Linear2"
x1="0"
y1="0"
x2="1"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(160.563,96.0376,-96.0376,160.563,4771.78,656.669)"><stop
offset="0"
style="stop-color:rgb(49,54,158);stop-opacity:1"
id="stop1273" /><stop
offset="1"
style="stop-color:rgb(29,33,103);stop-opacity:1"
id="stop1275" /></linearGradient><linearGradient
id="_Linear3"
x1="0"
y1="0"
x2="1"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(76.53,136.554,-136.554,76.53,4737.26,847.244)"><stop
offset="0"
style="stop-color:rgb(49,54,158);stop-opacity:1"
id="stop1278" /><stop
offset="1"
style="stop-color:rgb(29,33,103);stop-opacity:1"
id="stop1280" /></linearGradient></defs>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

+488
View File
@@ -0,0 +1,488 @@
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 console::Term;
#[cfg(windows)]
use ansi_term;
use assets::BAT_THEME_DEFAULT;
use errors::*;
use line_range::LineRange;
use style::{OutputComponent, OutputComponents, OutputWrap};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PagingMode {
Always,
QuitIfOneScreen,
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
pub files: Vec<InputFile<'a>>,
/// The explicitly configured language, if any
pub language: Option<&'a str>,
/// The character width of the terminal
pub term_width: usize,
/// The width of tab characters.
/// Currently, a value of 0 will cause tabs to be passed through without expanding them.
pub tab_width: usize,
/// Whether or not to simply loop through all input (`cat` mode)
pub loop_through: bool,
/// Whether or not the output should be colorized
pub colored_output: bool,
/// Whether or not the output terminal supports true color
pub true_color: bool,
/// Style elements (grid, line numbers, ...)
pub output_components: OutputComponents,
/// Text wrapping mode
pub output_wrap: OutputWrap,
/// Pager or STDOUT
pub paging_mode: PagingMode,
/// The range lines that should be printed, if specified
pub line_range: Option<LineRange>,
/// The syntax highlighting theme
pub theme: String,
}
fn is_truecolor_terminal() -> bool {
env::var("COLORTERM")
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
.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 {
#[cfg(windows)]
let _ = ansi_term::enable_ansi_support();
let interactive_output = atty::is(Stream::Stdout);
App {
matches: Self::matches(interactive_output),
interactive_output,
}
}
fn matches(interactive_output: bool) -> ArgMatches<'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::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()
}
pub fn config(&self) -> Result<Config> {
let files = self.files();
let output_components = self.output_components()?;
let paging_mode = match self.matches.value_of("paging") {
Some("always") => PagingMode::Always,
Some("never") => PagingMode::Never,
Some("auto") | _ => if files.contains(&InputFile::StdIn) {
// If we are reading from stdin, only enable paging if we write to an
// interactive terminal and if we do not *read* from an interactive
// terminal.
if self.interactive_output && !atty::is(Stream::Stdin) {
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
} else {
if self.interactive_output {
PagingMode::QuitIfOneScreen
} else {
PagingMode::Never
}
},
};
Ok(Config {
true_color: is_truecolor_terminal(),
language: self.matches.value_of("language"),
output_wrap: if !self.interactive_output {
// We don't have the tty width when piping to another program.
// There's no point in wrapping when this is the case.
OutputWrap::None
} else {
match self.matches.value_of("wrap") {
Some("character") => OutputWrap::Character,
Some("never") => OutputWrap::None,
Some("auto") | _ => if output_components.plain() {
OutputWrap::None
} else {
OutputWrap::Character
},
}
},
colored_output: match self.matches.value_of("color") {
Some("always") => true,
Some("never") => false,
Some("auto") | _ => self.interactive_output,
},
paging_mode,
term_width: self
.matches
.value_of("terminal-width")
.and_then(|w| w.parse().ok())
.unwrap_or(Term::stdout().size().1 as usize),
loop_through: !(self.interactive_output
|| self.matches.value_of("color") == Some("always")
|| self.matches.value_of("decorations") == Some("always")),
files,
tab_width: self
.matches
.value_of("tabs")
.map(String::from)
.or_else(|| env::var("BAT_TABS").ok())
.and_then(|t| t.parse().ok())
.unwrap_or(
if output_components.plain() && paging_mode == PagingMode::Never {
0
} else {
8
},
),
theme: self
.matches
.value_of("theme")
.map(String::from)
.or_else(|| env::var("BAT_THEME").ok())
.unwrap_or(String::from(BAT_THEME_DEFAULT)),
line_range: transpose(self.matches.value_of("line-range").map(LineRange::from))?,
output_components,
})
}
fn files(&self) -> Vec<InputFile> {
self.matches
.values_of("FILE")
.map(|values| {
values
.map(|filename| {
if filename == "-" {
InputFile::StdIn
} else {
InputFile::Ordinary(filename)
}
}).collect()
}).unwrap_or_else(|| vec![InputFile::StdIn])
}
fn output_components(&self) -> Result<OutputComponents> {
let matches = &self.matches;
Ok(OutputComponents(
if matches.value_of("decorations") == Some("never") {
HashSet::new()
} else if matches.is_present("number") {
[OutputComponent::Numbers].iter().cloned().collect()
} else if matches.is_present("plain") {
[OutputComponent::Plain].iter().cloned().collect()
} else {
let env_style_components: Option<Vec<OutputComponent>> =
transpose(env::var("BAT_STYLE").ok().map(|style_str| {
style_str
.split(",")
.map(|x| OutputComponent::from_str(&x))
.collect::<Result<Vec<OutputComponent>>>()
}))?;
values_t!(matches.values_of("style"), OutputComponent)
.ok()
.or(env_style_components)
.unwrap_or(vec![OutputComponent::Full])
.into_iter()
.map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| {
acc.extend(components.iter().cloned());
acc
})
},
))
}
}
+234
View File
@@ -0,0 +1,234 @@
use directories::ProjectDirs;
use errors::*;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fs::{self, File};
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};
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;
use app::InputFile;
lazy_static! {
static ref PROJECT_DIRS: ProjectDirs =
ProjectDirs::from("", "", crate_name!()).expect("Could not get home directory");
}
pub const BAT_THEME_DEFAULT: &str = "Monokai Extended";
pub struct HighlightingAssets {
pub syntax_set: SyntaxSet,
pub theme_set: ThemeSet,
}
impl HighlightingAssets {
pub fn new() -> Self {
Self::from_cache().unwrap_or_else(|_| Self::from_binary())
}
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()
} else {
Self::from_binary_unlinked()
};
let theme_dir = source_dir.join("themes");
let res = extend_theme_set(&mut assets.theme_set, &theme_dir);
if !res.is_ok() {
println!(
"No themes were found in '{}', using the default set",
theme_dir.to_string_lossy()
);
}
let syntax_dir = source_dir.join("syntaxes");
if syntax_dir.exists() {
assets.syntax_set.load_syntaxes(syntax_dir, true)?;
} else {
println!(
"No syntaxes were found in '{}', using the default set.",
syntax_dir.to_string_lossy()
);
}
Ok(assets)
}
fn from_cache() -> Result<Self> {
let theme_set_path = theme_set_path();
let syntax_set_file = File::open(&syntax_set_path()).chain_err(|| {
format!(
"Could not load cached syntax set '{}'",
syntax_set_path().to_string_lossy()
)
})?;
let mut syntax_set: SyntaxSet =
from_reader(syntax_set_file).chain_err(|| "Could not parse cached syntax set")?;
syntax_set.link_syntaxes();
let theme_set_file = File::open(&theme_set_path).chain_err(|| {
format!(
"Could not load cached theme set '{}'",
theme_set_path.to_string_lossy()
)
})?;
let theme_set: ThemeSet =
from_reader(theme_set_file).chain_err(|| "Could not parse cached theme set")?;
Ok(HighlightingAssets {
syntax_set,
theme_set,
})
}
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"));
HighlightingAssets {
syntax_set,
theme_set,
}
}
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 theme_set_path = target_dir.join("themes.bin");
let syntax_set_path = target_dir.join("syntaxes.bin");
print!(
"Writing theme set to {} ... ",
theme_set_path.to_string_lossy()
);
dump_to_file(&self.theme_set, &theme_set_path).chain_err(|| {
format!(
"Could not save theme set to {}",
theme_set_path.to_string_lossy()
)
})?;
println!("okay");
print!(
"Writing syntax set to {} ... ",
syntax_set_path.to_string_lossy()
);
dump_to_file(&self.syntax_set, &syntax_set_path).chain_err(|| {
format!(
"Could not save syntax set to {}",
syntax_set_path.to_string_lossy()
)
})?;
println!("okay");
Ok(())
}
pub fn get_theme(&self, theme: &str) -> &Theme {
match self.theme_set.themes.get(theme) {
Some(theme) => theme,
None => {
use ansi_term::Colour::Yellow;
eprintln!(
"{}: Unknown theme '{}', using default.",
Yellow.paint("[bat warning]"),
theme
);
&self.theme_set.themes[BAT_THEME_DEFAULT]
}
}
}
pub fn get_syntax(&self, language: Option<&str>, filename: InputFile) -> &SyntaxDefinition {
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;
// 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);
if may_read_from_file {
self.syntax_set
.find_syntax_for_file(filename)
.unwrap_or(None)
} else {
None
}
}
(None, InputFile::StdIn) => None,
(_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"),
};
syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
}
}
// 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")
}
fn syntax_set_path() -> PathBuf {
PROJECT_DIRS.cache_dir().join("syntaxes.bin")
}
pub fn config_dir() -> Cow<'static, str> {
PROJECT_DIRS.config_dir().to_string_lossy()
}
pub fn clear_assets() {
print!("Clearing theme set cache ... ");
fs::remove_file(theme_set_path()).ok();
println!("okay");
print!("Clearing syntax set cache ... ");
fs::remove_file(syntax_set_path()).ok();
println!("okay");
}
+112
View File
@@ -0,0 +1,112 @@
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
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");
pub struct Controller<'a> {
config: &'a Config<'a>,
assets: &'a HighlightingAssets,
}
impl<'b> Controller<'b> {
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
Controller { config, assets }
}
pub fn run(&self) -> Result<bool> {
let mut output_type = OutputType::from_mode(self.config.paging_mode);
let writer = output_type.handle()?;
let mut no_errors: bool = true;
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)
};
if let Err(error) = result {
handle_error(&error);
no_errors = false;
}
}
Ok(no_errors)
}
fn print_file<'a, P: Printer>(
&self,
printer: &mut P,
writer: &mut Write,
filename: 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)?;
}
Ok(())
}
fn print_file_ranges<'a, P: Printer>(
&self,
printer: &mut P,
writer: &mut Write,
mut reader: Box<BufRead + 'a>,
line_ranges: &Option<LineRange>,
) -> 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)?;
}
}
line_number += 1;
}
line_buffer.clear();
}
Ok(())
}
}
+154
View File
@@ -0,0 +1,154 @@
use ansi_term::Style;
use diff::LineChange;
use printer::{Colors, InteractivePrinter};
#[derive(Clone)]
pub struct DecorationText {
pub width: usize,
pub text: String,
}
pub trait Decoration {
fn generate(
&self,
line_number: usize,
continuation: bool,
printer: &InteractivePrinter,
) -> DecorationText;
fn width(&self) -> usize;
}
pub struct LineNumberDecoration {
color: Style,
cached_wrap: DecorationText,
cached_wrap_invalid_at: usize,
}
impl LineNumberDecoration {
pub fn new(colors: &Colors) -> Self {
LineNumberDecoration {
color: colors.line_number,
cached_wrap_invalid_at: 10000,
cached_wrap: DecorationText {
text: colors.line_number.paint(" ".repeat(4)).to_string(),
width: 4,
},
}
}
}
impl Decoration for LineNumberDecoration {
fn generate(
&self,
line_number: usize,
continuation: bool,
_printer: &InteractivePrinter,
) -> DecorationText {
if continuation {
if line_number > self.cached_wrap_invalid_at {
let new_width = self.cached_wrap.width + 1;
return DecorationText {
text: self.color.paint(" ".repeat(new_width)).to_string(),
width: new_width,
};
}
self.cached_wrap.clone()
} else {
let plain: String = format!("{:4}", line_number);
DecorationText {
width: plain.len(),
text: self.color.paint(plain).to_string(),
}
}
}
fn width(&self) -> usize {
4
}
}
pub struct LineChangesDecoration {
cached_none: DecorationText,
cached_added: DecorationText,
cached_removed_above: DecorationText,
cached_removed_below: DecorationText,
cached_modified: DecorationText,
}
impl LineChangesDecoration {
#[inline]
fn generate_cached(style: Style, text: &str) -> DecorationText {
DecorationText {
text: style.paint(text).to_string(),
width: text.chars().count(),
}
}
pub fn new(colors: &Colors) -> Self {
LineChangesDecoration {
cached_none: Self::generate_cached(Style::default(), " "),
cached_added: Self::generate_cached(colors.git_added, "+"),
cached_removed_above: Self::generate_cached(colors.git_removed, ""),
cached_removed_below: Self::generate_cached(colors.git_removed, "_"),
cached_modified: Self::generate_cached(colors.git_modified, "~"),
}
}
}
impl Decoration for LineChangesDecoration {
fn generate(
&self,
line_number: usize,
continuation: bool,
printer: &InteractivePrinter,
) -> DecorationText {
if !continuation {
if let Some(ref changes) = printer.line_changes {
return match changes.get(&(line_number as u32)) {
Some(&LineChange::Added) => self.cached_added.clone(),
Some(&LineChange::RemovedAbove) => self.cached_removed_above.clone(),
Some(&LineChange::RemovedBelow) => self.cached_removed_below.clone(),
Some(&LineChange::Modified) => self.cached_modified.clone(),
_ => self.cached_none.clone(),
};
}
}
self.cached_none.clone()
}
fn width(&self) -> usize {
self.cached_none.width
}
}
pub struct GridBorderDecoration {
cached: DecorationText,
}
impl GridBorderDecoration {
pub fn new(colors: &Colors) -> Self {
GridBorderDecoration {
cached: DecorationText {
text: colors.grid.paint("").to_string(),
width: 1,
},
}
}
}
impl Decoration for GridBorderDecoration {
fn generate(
&self,
_line_number: usize,
_continuation: bool,
_printer: &InteractivePrinter,
) -> DecorationText {
self.cached.clone()
}
fn width(&self) -> usize {
self.cached.width
}
}
+80
View File
@@ -0,0 +1,80 @@
use git2::{DiffOptions, IntoCString, Repository};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
#[derive(Copy, Clone, Debug)]
pub enum LineChange {
Added,
RemovedAbove,
RemovedBelow,
Modified,
}
pub type LineChanges = HashMap<u32, LineChange>;
pub fn get_git_diff(filename: &str) -> Option<LineChanges> {
let repo = Repository::discover(&filename).ok()?;
let repo_path_absolute = fs::canonicalize(repo.workdir()?).ok()?;
let filepath_absolute = fs::canonicalize(&filename).ok()?;
let filepath_relative_to_repo = filepath_absolute.strip_prefix(&repo_path_absolute).ok()?;
let mut diff_options = DiffOptions::new();
let pathspec = filepath_relative_to_repo.into_c_string().ok()?;
diff_options.pathspec(pathspec);
diff_options.context_lines(0);
let diff = repo
.diff_index_to_workdir(None, Some(&mut diff_options))
.ok()?;
let mut line_changes: LineChanges = HashMap::new();
let mark_section =
|line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
for line in start..(end + 1) as u32 {
line_changes.insert(line, change);
}
};
let _ = diff.foreach(
&mut |_, _| true,
None,
Some(&mut |delta, hunk| {
let path = delta.new_file().path().unwrap_or_else(|| Path::new(""));
if filepath_relative_to_repo != path {
return false;
}
let old_lines = hunk.old_lines();
let new_start = hunk.new_start();
let new_lines = hunk.new_lines();
let new_end = (new_start + new_lines) as i32 - 1;
if old_lines == 0 && new_lines > 0 {
mark_section(&mut line_changes, new_start, new_end, LineChange::Added);
} else if new_lines == 0 && old_lines > 0 {
if new_start == 0 {
mark_section(&mut line_changes, 1, 1, LineChange::RemovedAbove);
} else {
mark_section(
&mut line_changes,
new_start,
new_start as i32,
LineChange::RemovedBelow,
);
}
} else {
mark_section(&mut line_changes, new_start, new_end, LineChange::Modified);
}
true
}),
None,
);
Some(line_changes)
}
+74
View File
@@ -0,0 +1,74 @@
use errors::*;
#[derive(Clone)]
pub struct LineRange {
pub lower: usize,
pub upper: usize,
}
impl LineRange {
pub fn from(range_raw: &str) -> Result<LineRange> {
LineRange::parse_range(range_raw)
}
pub fn new() -> LineRange {
LineRange {
lower: usize::min_value(),
upper: usize::max_value(),
}
}
pub fn parse_range(range_raw: &str) -> Result<LineRange> {
let mut new_range = LineRange::new();
if range_raw.bytes().nth(0).ok_or("Empty line range")? == b':' {
new_range.upper = range_raw[1..].parse()?;
return Ok(new_range);
} else if range_raw.bytes().last().ok_or("Empty line range")? == b':' {
new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
return Ok(new_range);
}
let line_numbers: Vec<&str> = range_raw.split(':').collect();
if line_numbers.len() == 2 {
new_range.lower = line_numbers[0].parse()?;
new_range.upper = line_numbers[1].parse()?;
return Ok(new_range);
}
Err("expected single ':' character".into())
}
}
#[test]
fn test_parse_full() {
let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
assert_eq!(40, range.lower);
assert_eq!(50, range.upper);
}
#[test]
fn test_parse_partial_min() {
let range = LineRange::from(":50").expect("Shouldn't fail on test!");
assert_eq!(usize::min_value(), range.lower);
assert_eq!(50, range.upper);
}
#[test]
fn test_parse_partial_max() {
let range = LineRange::from("40:").expect("Shouldn't fail on test!");
assert_eq!(40, range.lower);
assert_eq!(usize::max_value(), range.upper);
}
#[test]
fn test_parse_fail() {
let range = LineRange::from("40:50:80");
assert!(range.is_err());
let range = LineRange::from("40::80");
assert!(range.is_err());
let range = LineRange::from(":40:");
assert!(range.is_err());
let range = LineRange::from("40");
assert!(range.is_err());
}
+177 -345
View File
@@ -17,391 +17,223 @@ extern crate directories;
extern crate git2; extern crate git2;
extern crate syntect; extern crate syntect;
mod app;
mod assets;
mod controller;
mod decorations;
mod diff;
mod line_range;
mod output;
mod preprocessor;
mod printer;
mod style;
mod terminal; mod terminal;
use std::collections::HashMap; use std::collections::HashSet;
use std::env; use std::io;
use std::fs::{self, File}; use std::io::Write;
use std::io::{self, BufRead, StdoutLock, Write};
use std::path::Path; use std::path::Path;
use std::process; use std::process;
use ansi_term::Colour::{Fixed, Green, Red, White, Yellow}; use ansi_term::Colour::Green;
use ansi_term::Style; use ansi_term::Style;
use atty::Stream;
use clap::{App, AppSettings, Arg, SubCommand};
use console::Term;
use directories::ProjectDirs;
use git2::{DiffOptions, IntoCString, Repository};
use syntect::dumps::{dump_to_file, from_binary, from_reader}; use app::{App, Config, InputFile};
use syntect::easy::HighlightFile; use assets::{clear_assets, config_dir, HighlightingAssets};
use syntect::highlighting::{Theme, ThemeSet}; use controller::Controller;
use syntect::parsing::SyntaxSet; use style::{OutputComponent, OutputComponents};
use terminal::as_terminal_escaped;
lazy_static! {
static ref PROJECT_DIRS: ProjectDirs = ProjectDirs::from("", "", crate_name!());
}
mod errors { mod errors {
error_chain!{ error_chain! {
foreign_links { foreign_links {
Clap(::clap::Error);
Io(::std::io::Error); Io(::std::io::Error);
SyntectError(::syntect::LoadingError);
ParseIntError(::std::num::ParseIntError);
} }
} }
pub fn handle_error(error: &Error) {
match error {
&Error(ErrorKind::Io(ref io_error), _)
if io_error.kind() == super::io::ErrorKind::BrokenPipe =>
{
super::process::exit(0);
}
_ => {
use ansi_term::Colour::Red;
eprintln!("{}: {}", Red.paint("[bat error]"), error);
}
};
}
} }
use errors::*; use errors::*;
struct Options { fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
true_color: bool, if matches.is_present("init") {
} let source_dir = matches.value_of("source").map(Path::new);
let target_dir = matches.value_of("target").map(Path::new);
#[derive(Copy, Clone, Debug)] let blank = matches.is_present("blank");
enum LineChange {
Added,
RemovedAbove,
RemovedBelow,
Modified,
}
type LineChanges = HashMap<u32, LineChange>; let assets = HighlightingAssets::from_files(source_dir, blank)?;
assets.save(target_dir)?;
const PANEL_WIDTH: usize = 7; } else if matches.is_present("clear") {
const GRID_COLOR: u8 = 238; clear_assets();
} else if matches.is_present("config-dir") {
fn print_horizontal_line( writeln!(io::stdout(), "{}", config_dir())?;
handle: &mut StdoutLock, }
grid_char: char,
term_width: usize,
) -> Result<()> {
let hline = "".repeat(term_width - (PANEL_WIDTH + 1));
let hline = format!("{}{}{}", "".repeat(PANEL_WIDTH), grid_char, hline);
writeln!(handle, "{}", Fixed(GRID_COLOR).paint(hline))?;
Ok(()) Ok(())
} }
fn print_file<P: AsRef<Path>>( pub fn list_languages(config: &Config) -> Result<()> {
options: &Options, let assets = HighlightingAssets::new();
theme: &Theme, let mut languages = assets
syntax_set: &SyntaxSet, .syntax_set
filename: P, .syntaxes()
line_changes: &Option<LineChanges>, .iter()
) -> Result<()> { .filter(|syntax| !syntax.hidden && !syntax.file_extensions.is_empty())
let mut highlighter = HighlightFile::new(filename.as_ref(), syntax_set, theme)?; .collect::<Vec<_>>();
languages.sort_by_key(|lang| lang.name.to_uppercase());
let longest = languages
.iter()
.map(|syntax| syntax.name.len())
.max()
.unwrap_or(32); // Fallback width if they have no language definitions.
let comma_separator = ", ";
let separator = " ";
// Line-wrapping for the possible file extension overflow.
let desired_width = config.term_width - longest - separator.len();
let stdout = io::stdout(); let stdout = io::stdout();
let mut handle = stdout.lock(); let mut stdout = stdout.lock();
let term = Term::stdout(); let style = if config.colored_output {
let (_, term_width) = term.size(); Green.normal()
let term_width = term_width as usize;
print_horizontal_line(&mut handle, '┬', term_width)?;
writeln!(
handle,
"{}{} File {}",
" ".repeat(PANEL_WIDTH),
Fixed(GRID_COLOR).paint(""),
White.bold().paint(filename.as_ref().to_string_lossy())
)?;
print_horizontal_line(&mut handle, '┼', term_width)?;
for (idx, maybe_line) in highlighter.reader.lines().enumerate() {
let line_nr = idx + 1;
let line = maybe_line.unwrap_or_else(|_| "<INVALID UTF-8>".into());
let regions = highlighter.highlight_lines.highlight(&line);
let line_change = if let Some(ref changes) = *line_changes {
match changes.get(&(line_nr as u32)) {
Some(&LineChange::Added) => Green.paint("+"),
Some(&LineChange::RemovedAbove) => Red.paint(""),
Some(&LineChange::RemovedBelow) => Red.paint("_"),
Some(&LineChange::Modified) => Yellow.paint("~"),
_ => Style::default().paint(" "),
}
} else {
Style::default().paint(" ")
};
writeln!(
handle,
"{} {} {} {}",
Fixed(244).paint(format!("{:4}", line_nr)),
line_change,
Fixed(GRID_COLOR).paint(""),
as_terminal_escaped(&regions, options.true_color)
)?;
}
print_horizontal_line(&mut handle, '┴', term_width)?;
Ok(())
}
fn get_git_diff(filename: &str) -> Option<LineChanges> {
let repo = Repository::open_from_env().ok()?;
let workdir = repo.workdir()?;
let current_dir = env::current_dir().ok()?;
let filepath = current_dir.join(Path::new(&filename));
let mut diff_options = DiffOptions::new();
let pathspec = format!("*{}", filename).into_c_string().ok()?;
diff_options.pathspec(pathspec);
diff_options.context_lines(0);
let diff = repo.diff_index_to_workdir(None, Some(&mut diff_options))
.ok()?;
let mut line_changes: LineChanges = HashMap::new();
let mark_section =
|line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
for line in start..(end + 1) as u32 {
line_changes.insert(line, change);
}
};
let _ = diff.foreach(
&mut |_, _| true,
None,
Some(&mut |delta, hunk| {
let path = delta.new_file().path().unwrap_or_else(|| Path::new(""));
if filepath != workdir.join(path) {
return false;
}
let old_lines = hunk.old_lines();
let new_start = hunk.new_start();
let new_lines = hunk.new_lines();
let new_end = (new_start + new_lines) as i32 - 1;
if old_lines == 0 && new_lines > 0 {
mark_section(&mut line_changes, new_start, new_end, LineChange::Added);
} else if new_lines == 0 && old_lines > 0 {
if new_start == 0 {
mark_section(&mut line_changes, 1, 1, LineChange::RemovedAbove);
} else {
mark_section(
&mut line_changes,
new_start,
new_start as i32,
LineChange::RemovedBelow,
);
}
} else {
mark_section(&mut line_changes, new_start, new_end, LineChange::Modified);
}
true
}),
None,
);
Some(line_changes)
}
fn is_truecolor_terminal() -> bool {
env::var("COLORTERM")
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
.unwrap_or(false)
}
struct HighlightingAssets {
pub syntax_set: SyntaxSet,
pub theme_set: ThemeSet,
}
impl HighlightingAssets {
fn from_files() -> Result<Self> {
let config_dir = PROJECT_DIRS.config_dir();
let theme_dir = config_dir.join("themes");
let theme_set = ThemeSet::load_from_folder(&theme_dir).map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!(
"Could not load themes from '{}'",
theme_dir.to_string_lossy()
),
)
})?;
let mut syntax_set = SyntaxSet::new();
let syntax_dir = config_dir.join("syntax");
let _ = syntax_set.load_syntaxes(syntax_dir, false);
syntax_set.load_plain_text_syntax();
Ok(HighlightingAssets {
syntax_set,
theme_set,
})
}
fn save(&self) -> Result<()> {
let cache_dir = PROJECT_DIRS.cache_dir();
let theme_set_path = cache_dir.join("theme_set");
let syntax_set_path = cache_dir.join("syntax_set");
let _ = fs::create_dir(cache_dir);
dump_to_file(&self.theme_set, &theme_set_path).map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!(
"Could not save theme set to {}",
theme_set_path.to_string_lossy()
),
)
})?;
println!("Wrote theme set to {}", theme_set_path.to_string_lossy());
dump_to_file(&self.syntax_set, &syntax_set_path).map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!(
"Could not save syntax set to {}",
syntax_set_path.to_string_lossy()
),
)
})?;
println!("Wrote syntax set to {}", syntax_set_path.to_string_lossy());
Ok(())
}
fn from_cache() -> Result<Self> {
let cache_dir = PROJECT_DIRS.cache_dir();
let theme_set_path = cache_dir.join("theme_set");
let syntax_set_path = cache_dir.join("syntax_set");
let syntax_set_file = File::open(&syntax_set_path).chain_err(|| {
format!(
"Could not load cached syntax set '{}'",
syntax_set_path.to_string_lossy()
)
})?;
let mut syntax_set: SyntaxSet = from_reader(syntax_set_file).map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!("Could not parse cached syntax set"),
)
})?;
syntax_set.link_syntaxes();
let theme_set_file = File::open(&theme_set_path).chain_err(|| {
format!(
"Could not load cached theme set '{}'",
theme_set_path.to_string_lossy()
)
})?;
let theme_set: ThemeSet = from_reader(theme_set_file).map_err(|_| {
io::Error::new(
io::ErrorKind::Other,
format!("Could not parse cached theme set"),
)
})?;
Ok(HighlightingAssets {
syntax_set,
theme_set,
})
}
fn from_binary() -> Self {
let mut syntax_set: SyntaxSet = from_binary(include_bytes!("../assets/syntax_set"));
syntax_set.link_syntaxes();
let theme_set: ThemeSet = from_binary(include_bytes!("../assets/theme_set"));
HighlightingAssets {
syntax_set,
theme_set,
}
}
}
fn run() -> Result<()> {
let clap_color_setting = if atty::is(Stream::Stdout) {
AppSettings::ColoredHelp
} else { } else {
AppSettings::ColorNever Style::default()
}; };
let app_matches = App::new(crate_name!()) for lang in languages {
.version(crate_version!()) write!(stdout, "{:width$}{}", lang.name, separator, width = longest)?;
.setting(clap_color_setting)
.setting(AppSettings::DeriveDisplayOrder)
.setting(AppSettings::UnifiedHelpMessage)
.setting(AppSettings::NextLineHelp)
.setting(AppSettings::DisableVersion)
.max_term_width(90)
.about(crate_description!())
.arg(
Arg::with_name("FILE")
.help("File(s) to print")
.multiple(true)
.empty_values(false),
)
.subcommand(
SubCommand::with_name("init-cache")
.about("Load syntax definitions and themes into cache"),
)
.help_message("Print this help message.")
.version_message("Show version information.")
.get_matches();
match app_matches.subcommand() { // Number of characters on this line so far, wrap before `desired_width`
("init-cache", Some(_)) => { let mut num_chars = 0;
let assets = HighlightingAssets::from_files()?;
assets.save()?;
}
_ => {
let options = Options {
true_color: is_truecolor_terminal(),
};
let assets = let mut extension = lang.file_extensions.iter().peekable();
HighlightingAssets::from_cache().unwrap_or(HighlightingAssets::from_binary()); while let Some(word) = extension.next() {
// If we can't fit this word in, then create a line break and align it in.
let theme = assets.theme_set.themes.get("Default").ok_or_else(|| { let new_chars = word.len() + comma_separator.len();
io::Error::new( if num_chars + new_chars >= desired_width {
io::ErrorKind::Other, num_chars = 0;
format!("Could not find 'Default' theme"), write!(stdout, "\n{:width$}{}", "", separator, width = longest)?;
)
})?;
if let Some(files) = app_matches.values_of("FILE") {
for file in files {
let line_changes = get_git_diff(&file.to_string());
print_file(&options, theme, &assets.syntax_set, file, &line_changes)?;
}
} }
num_chars += new_chars;
write!(stdout, "{}", style.paint(&word[..]))?;
if extension.peek().is_some() {
write!(stdout, "{}", comma_separator)?;
}
}
writeln!(stdout)?;
}
Ok(())
}
pub fn list_themes(cfg: &Config) -> Result<()> {
let assets = HighlightingAssets::new();
let themes = &assets.theme_set.themes;
let mut config = cfg.clone();
let mut style = HashSet::new();
style.insert(OutputComponent::Plain);
config.files = vec![InputFile::ThemePreviewFile];
config.output_components = OutputComponents(style);
let stdout = io::stdout();
let mut stdout = stdout.lock();
if config.colored_output {
for (theme, _) in themes.iter() {
writeln!(
stdout,
"Theme: {}\n",
Style::new().bold().paint(theme.to_string())
)?;
config.theme = theme.to_string();
let _controller = Controller::new(&config, &assets).run();
writeln!(stdout)?;
}
} else {
for (theme, _) in themes.iter() {
writeln!(stdout, "{}", theme)?;
} }
} }
Ok(()) Ok(())
} }
fn run_controller(config: &Config) -> Result<bool> {
let assets = HighlightingAssets::new();
let controller = Controller::new(&config, &assets);
controller.run()
}
/// Returns `Err(..)` upon fatal errors. Otherwise, returns `Some(true)` on full success and
/// `Some(false)` if any intermediate errors occurred (were printed).
fn run() -> Result<bool> {
let app = App::new();
match app.matches.subcommand() {
("cache", Some(cache_matches)) => {
// If there is a file named 'cache' in the current working directory,
// arguments for subcommand 'cache' are not mandatory.
// If there are non-zero arguments, execute the subcommand cache, else, open the file cache.
if !cache_matches.args.is_empty() {
run_cache_subcommand(cache_matches)?;
Ok(true)
} else {
let mut config = app.config()?;
config.files = vec![InputFile::Ordinary(&"cache")];
run_controller(&config)
}
}
_ => {
let config = app.config()?;
if app.matches.is_present("list-languages") {
list_languages(&config)?;
Ok(true)
} else if app.matches.is_present("list-themes") {
list_themes(&config)?;
Ok(true)
} else {
run_controller(&config)
}
}
}
}
fn main() { fn main() {
let result = run(); let result = run();
if let Err(error) = result { match result {
match error { Err(error) => {
Error(ErrorKind::Io(ref io_error), _) handle_error(&error);
if io_error.kind() == io::ErrorKind::BrokenPipe => {} process::exit(1);
_ => { }
eprintln!("{}: {}", Red.paint("[bat error]"), error); Ok(false) => {
process::exit(1);
process::exit(1); }
} Ok(true) => {
}; process::exit(0);
}
} }
} }
+75
View File
@@ -0,0 +1,75 @@
use std::env;
use std::ffi::OsString;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{Child, Command, Stdio};
use app::PagingMode;
use errors::*;
pub enum OutputType {
Pager(Child),
Stdout(io::Stdout),
}
impl OutputType {
pub fn from_mode(mode: PagingMode) -> Self {
use self::PagingMode::*;
match mode {
Always => OutputType::try_pager(false),
QuitIfOneScreen => OutputType::try_pager(true),
_ => OutputType::stdout(),
}
}
/// Try to launch the pager. Fall back to stdout in case of errors.
fn try_pager(quit_if_one_screen: bool) -> Self {
let pager = env::var("BAT_PAGER")
.or_else(|_| env::var("PAGER"))
.unwrap_or(String::from("less"));
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 mut p = Command::new(&less_path);
p.args(&args).env("LESSCHARSET", "UTF-8");
p
} else {
Command::new(pager)
};
process
.stdin(Stdio::piped())
.spawn()
.map(OutputType::Pager)
.unwrap_or_else(|_| OutputType::stdout())
}
fn stdout() -> Self {
OutputType::Stdout(io::stdout())
}
pub fn handle(&mut self) -> Result<&mut Write> {
Ok(match *self {
OutputType::Pager(ref mut command) => command
.stdin
.as_mut()
.chain_err(|| "Could not open stdin for pager")?,
OutputType::Stdout(ref mut handle) => handle,
})
}
}
impl Drop for OutputType {
fn drop(&mut self) {
if let OutputType::Pager(ref mut command) = *self {
let _ = command.wait();
}
}
}
+34
View File
@@ -0,0 +1,34 @@
use console::AnsiCodeIterator;
/// Expand tabs like an ANSI-enabled expand(1).
pub fn expand(line: &str, width: usize, cursor: &mut usize) -> String {
let mut buffer = String::with_capacity(line.len() * 2);
for chunk in AnsiCodeIterator::new(line) {
match chunk {
(text, true) => buffer.push_str(text),
(mut text, false) => {
while let Some(index) = text.find('\t') {
// Add previous text.
if index > 0 {
*cursor += index;
buffer.push_str(&text[0..index]);
}
// Add tab.
let spaces = width - (*cursor % width);
*cursor += spaces;
buffer.push_str(&*" ".repeat(spaces));
// Next.
text = &text[index + 1..text.len()];
}
*cursor += text.len();
buffer.push_str(text);
}
}
}
buffer
}
+398
View File
@@ -0,0 +1,398 @@
use std::boxed::Box;
use std::io::Write;
use std::vec::Vec;
use ansi_term::Colour::{Fixed, Green, Red, Yellow};
use ansi_term::Style;
use console::AnsiCodeIterator;
use syntect::easy::HighlightLines;
use syntect::highlighting::Theme;
use 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};
pub trait Printer {
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()>;
fn print_footer(&mut self, handle: &mut Write) -> Result<()>;
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
line_number: usize,
line_buffer: &[u8],
) -> Result<()>;
}
pub struct SimplePrinter;
impl SimplePrinter {
pub fn new() -> Self {
SimplePrinter {}
}
}
impl Printer for SimplePrinter {
fn print_header(&mut self, _handle: &mut Write, _file: InputFile) -> Result<()> {
Ok(())
}
fn print_footer(&mut self, _handle: &mut Write) -> Result<()> {
Ok(())
}
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
_line_number: usize,
line_buffer: &[u8],
) -> Result<()> {
if !out_of_range {
handle.write(line_buffer)?;
}
Ok(())
}
}
pub struct InteractivePrinter<'a> {
colors: Colors,
config: &'a Config<'a>,
decorations: Vec<Box<Decoration>>,
panel_width: usize,
ansi_prefix_sgr: String,
pub line_changes: Option<LineChanges>,
highlighter: HighlightLines<'a>,
}
impl<'a> InteractivePrinter<'a> {
pub fn new(config: &'a Config, assets: &'a HighlightingAssets, file: InputFile) -> Self {
let theme = assets.get_theme(&config.theme);
let colors = if config.colored_output {
Colors::colored(theme, config.true_color)
} else {
Colors::plain()
};
// Create decorations.
let mut decorations: Vec<Box<Decoration>> = Vec::new();
if config.output_components.numbers() {
decorations.push(Box::new(LineNumberDecoration::new(&colors)));
}
if config.output_components.changes() {
decorations.push(Box::new(LineChangesDecoration::new(&colors)));
}
let mut panel_width: usize =
decorations.len() + decorations.iter().fold(0, |a, x| a + x.width());
// The grid border decoration isn't added until after the panel_width calculation, since the
// print_horizontal_line, print_header, and print_footer functions all assume the panel
// width is without the grid border.
if config.output_components.grid() && !decorations.is_empty() {
decorations.push(Box::new(GridBorderDecoration::new(&colors)));
}
// Disable the panel if the terminal is too small (i.e. can't fit 5 characters with the
// panel showing).
if config.term_width
< (decorations.len() + decorations.iter().fold(0, |a, x| a + x.width())) + 5
{
decorations.clear();
panel_width = 0;
}
// Get the Git modifications
let 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);
let highlighter = HighlightLines::new(syntax, theme);
InteractivePrinter {
panel_width,
colors,
config,
decorations,
ansi_prefix_sgr: String::new(),
line_changes,
highlighter,
}
}
fn print_horizontal_line(&mut self, handle: &mut Write, grid_char: char) -> Result<()> {
if self.panel_width == 0 {
writeln!(
handle,
"{}",
self.colors.grid.paint("".repeat(self.config.term_width))
)?;
} else {
let hline = "".repeat(self.config.term_width - (self.panel_width + 1));
let hline = format!("{}{}{}", "".repeat(self.panel_width), grid_char, hline);
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
}
Ok(())
}
fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
if self.config.tab_width > 0 {
expand(text, self.config.tab_width, cursor)
} else {
text.to_string()
}
}
}
impl<'a> Printer for InteractivePrinter<'a> {
fn print_header(&mut self, handle: &mut Write, file: InputFile) -> Result<()> {
if !self.config.output_components.header() {
return Ok(());
}
if self.config.output_components.grid() {
self.print_horizontal_line(handle, '┬')?;
write!(
handle,
"{}{}",
" ".repeat(self.panel_width),
self.colors
.grid
.paint(if self.panel_width > 0 { "" } else { "" }),
)?;
} else {
write!(handle, "{}", " ".repeat(self.panel_width))?;
}
let (prefix, name) = match file {
InputFile::Ordinary(filename) => ("File: ", filename),
_ => ("", "STDIN"),
};
writeln!(handle, "{}{}", prefix, self.colors.filename.paint(name))?;
if self.config.output_components.grid() {
self.print_horizontal_line(handle, '┼')?;
}
Ok(())
}
fn print_footer(&mut self, handle: &mut Write) -> Result<()> {
if self.config.output_components.grid() {
self.print_horizontal_line(handle, '┴')
} else {
Ok(())
}
}
fn print_line(
&mut self,
out_of_range: bool,
handle: &mut Write,
line_number: usize,
line_buffer: &[u8],
) -> Result<()> {
let line = String::from_utf8_lossy(&line_buffer).to_string();
let regions = self.highlighter.highlight(line.as_ref());
if out_of_range {
return Ok(());
}
let mut cursor: usize = 0;
let mut cursor_max: usize = self.config.term_width;
let mut cursor_total: usize = 0;
let mut panel_wrap: Option<String> = None;
// Line decorations.
if self.panel_width > 0 {
let decorations = self
.decorations
.iter()
.map(|ref d| d.generate(line_number, false, self))
.collect::<Vec<_>>();
for deco in decorations {
write!(handle, "{} ", deco.text)?;
cursor_max -= deco.width + 1;
}
}
// Line contents.
if self.config.output_wrap == OutputWrap::None {
let true_color = self.config.true_color;
let colored_output = self.config.colored_output;
for &(style, region) in regions.iter() {
let text = &*self.preprocess(region, &mut cursor_total);
write!(
handle,
"{}",
as_terminal_escaped(style, &*text, true_color, colored_output,)
)?;
}
if line.bytes().next_back() != Some(b'\n') {
write!(handle, "\n")?;
}
} else {
for &(style, region) in regions.iter() {
let mut ansi_iterator = AnsiCodeIterator::new(region);
let mut ansi_prefix: String = String::new();
for chunk in ansi_iterator {
match chunk {
// ANSI escape passthrough.
(text, true) => {
if text.chars().last().map_or(false, |c| c == 'm') {
ansi_prefix.push_str(text);
if text == "\x1B[0m" {
self.ansi_prefix_sgr = "\x1B[0m".to_owned();
} else {
self.ansi_prefix_sgr.push_str(text);
}
} else {
ansi_prefix.push_str(text);
}
}
// Regular text.
(text, false) => {
let text = self.preprocess(
text.trim_right_matches(|c| c == '\r' || c == '\n'),
&mut cursor_total,
);
let mut chars = text.chars();
let mut remaining = text.chars().count();
while remaining > 0 {
let available = cursor_max - cursor;
// It fits.
if remaining <= available {
let text = chars.by_ref().take(remaining).collect::<String>();
cursor += remaining;
write!(
handle,
"{}",
as_terminal_escaped(
style,
&*format!(
"{}{}{}",
self.ansi_prefix_sgr, ansi_prefix, text
),
self.config.true_color,
self.config.colored_output,
)
)?;
break;
}
// Generate wrap padding if not already generated.
if panel_wrap.is_none() {
panel_wrap = if self.panel_width > 0 {
Some(format!(
"{} ",
self.decorations
.iter()
.map(|ref d| d
.generate(line_number, true, self)
.text).collect::<Vec<String>>()
.join(" ")
))
} else {
Some("".to_string())
}
}
// It wraps.
let text = chars.by_ref().take(available).collect::<String>();
cursor = 0;
remaining -= available;
write!(
handle,
"{}\n{}",
as_terminal_escaped(
style,
&*format!(
"{}{}{}",
self.ansi_prefix_sgr, ansi_prefix, text
),
self.config.true_color,
self.config.colored_output,
),
panel_wrap.clone().unwrap()
)?;
}
// Clear the ANSI prefix buffer.
ansi_prefix.clear();
}
}
}
}
write!(handle, "\n")?;
}
Ok(())
}
}
const DEFAULT_GUTTER_COLOR: u8 = 238;
#[derive(Default)]
pub struct Colors {
pub grid: Style,
pub filename: Style,
pub git_added: Style,
pub git_removed: Style,
pub git_modified: Style,
pub line_number: Style,
}
impl Colors {
fn plain() -> Self {
Colors::default()
}
fn colored(theme: &Theme, true_color: bool) -> Self {
let gutter_color = theme
.settings
.gutter_foreground
.map(|c| to_ansi_color(c, true_color))
.unwrap_or(Fixed(DEFAULT_GUTTER_COLOR));
Colors {
grid: gutter_color.normal(),
filename: Style::new().bold(),
git_added: Green.normal(),
git_removed: Red.normal(),
git_modified: Yellow.normal(),
line_number: gutter_color.normal(),
}
}
}
+86
View File
@@ -0,0 +1,86 @@
use std::collections::HashSet;
use std::str::FromStr;
use errors::*;
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum OutputComponent {
Auto,
Changes,
Grid,
Header,
Numbers,
Full,
Plain,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum OutputWrap {
Character,
None,
}
impl OutputComponent {
pub fn components(&self, interactive_terminal: bool) -> &'static [OutputComponent] {
match *self {
OutputComponent::Auto => if interactive_terminal {
OutputComponent::Full.components(interactive_terminal)
} else {
OutputComponent::Plain.components(interactive_terminal)
},
OutputComponent::Changes => &[OutputComponent::Changes],
OutputComponent::Grid => &[OutputComponent::Grid],
OutputComponent::Header => &[OutputComponent::Header],
OutputComponent::Numbers => &[OutputComponent::Numbers],
OutputComponent::Full => &[
OutputComponent::Changes,
OutputComponent::Grid,
OutputComponent::Header,
OutputComponent::Numbers,
],
OutputComponent::Plain => &[],
}
}
}
impl FromStr for OutputComponent {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"auto" => Ok(OutputComponent::Auto),
"changes" => Ok(OutputComponent::Changes),
"grid" => Ok(OutputComponent::Grid),
"header" => Ok(OutputComponent::Header),
"numbers" => Ok(OutputComponent::Numbers),
"full" => Ok(OutputComponent::Full),
"plain" => Ok(OutputComponent::Plain),
_ => Err(format!("Unknown style '{}'", s).into()),
}
}
}
#[derive(Clone)]
pub struct OutputComponents(pub HashSet<OutputComponent>);
impl OutputComponents {
pub fn changes(&self) -> bool {
self.0.contains(&OutputComponent::Changes)
}
pub fn grid(&self) -> bool {
self.0.contains(&OutputComponent::Grid)
}
pub fn header(&self) -> bool {
self.0.contains(&OutputComponent::Header)
}
pub fn numbers(&self) -> bool {
self.0.contains(&OutputComponent::Numbers)
}
pub fn plain(&self) -> bool {
self.0.is_empty()
}
}
+35 -21
View File
@@ -1,7 +1,7 @@
use std::fmt::Write;
use ansi_term::Colour::{Fixed, RGB}; use ansi_term::Colour::{Fixed, RGB};
use syntect::highlighting; use ansi_term::{self, Style};
use syntect::highlighting::{self, FontStyle};
/// Approximate a 24 bit color value by a 8 bit ANSI code /// Approximate a 24 bit color value by a 8 bit ANSI code
fn rgb2ansi(r: u8, g: u8, b: u8) -> u8 { fn rgb2ansi(r: u8, g: u8, b: u8) -> u8 {
@@ -14,31 +14,45 @@ fn rgb2ansi(r: u8, g: u8, b: u8) -> u8 {
} else if r > 248 { } else if r > 248 {
WHITE WHITE
} else { } else {
let fr = f32::from(r); ((r - 8) as u16 * 24 / 247) as u8 + 232
(((fr - 8.) / 247.) * 24.) as u8 + 232
} }
} else { } else {
let fr = f32::from(r); 36 * (r / 51) + 6 * (g / 51) + (b / 51) + 16
let fg = f32::from(g);
let fb = f32::from(b);
16 + (36 * (fr / 255. * 5.) as u8) + (6 * (fg / 255. * 5.) as u8) + (fb / 255. * 5.) as u8
} }
} }
pub fn as_terminal_escaped(v: &[(highlighting::Style, &str)], true_color: bool) -> String { pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> ansi_term::Colour {
let mut s: String = String::new(); if true_color {
for &(ref style, text) in v.iter() { RGB(color.r, color.g, color.b)
let style = if true_color { } else {
RGB(style.foreground.r, style.foreground.g, style.foreground.b) let ansi_code = rgb2ansi(color.r, color.g, color.b);
} else { Fixed(ansi_code)
let ansi = rgb2ansi(style.foreground.r, style.foreground.g, style.foreground.b);
Fixed(ansi)
};
write!(s, "{}", style.paint(text)).unwrap();
} }
}
s pub fn as_terminal_escaped(
style: highlighting::Style,
text: &str,
true_color: bool,
colored: bool,
) -> String {
let style = if !colored {
Style::default()
} else {
let color = to_ansi_color(style.foreground, true_color);
if style.font_style.contains(FontStyle::BOLD) {
color.bold()
} else if style.font_style.contains(FontStyle::UNDERLINE) {
color.underline()
} else if style.font_style.contains(FontStyle::ITALIC) {
color.italic()
} else {
color.normal()
}
};
style.paint(text).to_string()
} }
#[test] #[test]
+1
View File
@@ -0,0 +1 @@
test-src/* linguist-vendored
+1
View File
@@ -0,0 +1 @@
test-src/*
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
if ! which hyperfine > /dev/null 2>&1; then
echo "'hyperfine' does not seem to be installed."
echo "You can get it here: https://github.com/sharkdp/hyperfine"
exit 1
fi
SRC="test-src/jquery-3.3.1.js"
cmd_bat="bat --style=full --color=always --paging=never '$SRC'"
cmd_pygmentize="pygmentize -g '$SRC'"
cmd_highlight="highlight -O truecolor '$SRC'"
cmd_ccat="ccat --color=always '$SRC'"
cmd_source_highlight="source-highlight --failsafe --infer-lang -f esc -i '$SRC'"
cmd_hicat="hicat '$SRC'"
cmd_coderay="coderay '$SRC'"
cmd_rouge="rougify '$SRC'"
hyperfine --warmup 3 \
"$cmd_bat" \
"$cmd_pygmentize" \
"$cmd_highlight" \
"$cmd_ccat" \
"$cmd_source_highlight" \
"$cmd_hicat" \
"$cmd_coderay" \
"$cmd_rouge" \
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
if ! which hyperfine > /dev/null 2>&1; then
echo "'hyperfine' does not seem to be installed."
echo "You can get it here: https://github.com/sharkdp/hyperfine"
exit 1
fi
echo "### Startup time"
echo
hyperfine --warmup 3 bat
echo
echo "### Plain text"
echo
hyperfine --warmup 3 "bat --language txt --paging=never 'test-src/jquery-3.3.1.js'"
echo
echo "### Time to syntax-highlight large files"
echo
for SRC in test-src/*; do
hyperfine --warmup 3 "bat --style=full --color=always --paging=never '$SRC'"
done
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+602
View File
@@ -0,0 +1,602 @@
/**************************************************************************
*
* Copyright 2013-2014 RAD Game Tools and Valve Software
* Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**************************************************************************/
#include "miniz.h"
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
#ifdef __cplusplus
extern "C" {
#endif
/* ------------------- zlib-style API's */
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
{
mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
size_t block_len = buf_len % 5552;
if (!ptr)
return MZ_ADLER32_INIT;
while (buf_len)
{
for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
{
s1 += ptr[0], s2 += s1;
s1 += ptr[1], s2 += s1;
s1 += ptr[2], s2 += s1;
s1 += ptr[3], s2 += s1;
s1 += ptr[4], s2 += s1;
s1 += ptr[5], s2 += s1;
s1 += ptr[6], s2 += s1;
s1 += ptr[7], s2 += s1;
}
for (; i < block_len; ++i)
s1 += *ptr++, s2 += s1;
s1 %= 65521U, s2 %= 65521U;
buf_len -= block_len;
block_len = 5552;
}
return (s2 << 16) + s1;
}
/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
#if 0
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
{
static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
mz_uint32 crcu32 = (mz_uint32)crc;
if (!ptr)
return MZ_CRC32_INIT;
crcu32 = ~crcu32;
while (buf_len--)
{
mz_uint8 b = *ptr++;
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
}
return ~crcu32;
}
#else
/* Faster, but larger CPU cache footprint.
*/
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
{
static const mz_uint32 s_crc_table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
while (buf_len >= 4)
{
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
pByte_buf += 4;
buf_len -= 4;
}
while (buf_len)
{
crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
++pByte_buf;
--buf_len;
}
return ~crc32;
}
#endif
void mz_free(void *p)
{
MZ_FREE(p);
}
void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
{
(void)opaque, (void)items, (void)size;
return MZ_MALLOC(items * size);
}
void miniz_def_free_func(void *opaque, void *address)
{
(void)opaque, (void)address;
MZ_FREE(address);
}
void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
{
(void)opaque, (void)address, (void)items, (void)size;
return MZ_REALLOC(address, items * size);
}
const char *mz_version(void)
{
return MZ_VERSION;
}
#ifndef MINIZ_NO_ZLIB_APIS
int mz_deflateInit(mz_streamp pStream, int level)
{
return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
}
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
{
tdefl_compressor *pComp;
mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
if (!pStream)
return MZ_STREAM_ERROR;
if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
return MZ_PARAM_ERROR;
pStream->data_type = 0;
pStream->adler = MZ_ADLER32_INIT;
pStream->msg = NULL;
pStream->reserved = 0;
pStream->total_in = 0;
pStream->total_out = 0;
if (!pStream->zalloc)
pStream->zalloc = miniz_def_alloc_func;
if (!pStream->zfree)
pStream->zfree = miniz_def_free_func;
pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
if (!pComp)
return MZ_MEM_ERROR;
pStream->state = (struct mz_internal_state *)pComp;
if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
{
mz_deflateEnd(pStream);
return MZ_PARAM_ERROR;
}
return MZ_OK;
}
int mz_deflateReset(mz_streamp pStream)
{
if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
return MZ_STREAM_ERROR;
pStream->total_in = pStream->total_out = 0;
tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
return MZ_OK;
}
int mz_deflate(mz_streamp pStream, int flush)
{
size_t in_bytes, out_bytes;
mz_ulong orig_total_in, orig_total_out;
int mz_status = MZ_OK;
if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
return MZ_STREAM_ERROR;
if (!pStream->avail_out)
return MZ_BUF_ERROR;
if (flush == MZ_PARTIAL_FLUSH)
flush = MZ_SYNC_FLUSH;
if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
orig_total_in = pStream->total_in;
orig_total_out = pStream->total_out;
for (;;)
{
tdefl_status defl_status;
in_bytes = pStream->avail_in;
out_bytes = pStream->avail_out;
defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
pStream->next_in += (mz_uint)in_bytes;
pStream->avail_in -= (mz_uint)in_bytes;
pStream->total_in += (mz_uint)in_bytes;
pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
pStream->next_out += (mz_uint)out_bytes;
pStream->avail_out -= (mz_uint)out_bytes;
pStream->total_out += (mz_uint)out_bytes;
if (defl_status < 0)
{
mz_status = MZ_STREAM_ERROR;
break;
}
else if (defl_status == TDEFL_STATUS_DONE)
{
mz_status = MZ_STREAM_END;
break;
}
else if (!pStream->avail_out)
break;
else if ((!pStream->avail_in) && (flush != MZ_FINISH))
{
if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
break;
return MZ_BUF_ERROR; /* Can't make forward progress without some input.
*/
}
}
return mz_status;
}
int mz_deflateEnd(mz_streamp pStream)
{
if (!pStream)
return MZ_STREAM_ERROR;
if (pStream->state)
{
pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL;
}
return MZ_OK;
}
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
{
(void)pStream;
/* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
}
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
{
int status;
mz_stream stream;
memset(&stream, 0, sizeof(stream));
/* In case mz_ulong is 64-bits (argh I hate longs). */
if ((source_len | *pDest_len) > 0xFFFFFFFFU)
return MZ_PARAM_ERROR;
stream.next_in = pSource;
stream.avail_in = (mz_uint32)source_len;
stream.next_out = pDest;
stream.avail_out = (mz_uint32)*pDest_len;
status = mz_deflateInit(&stream, level);
if (status != MZ_OK)
return status;
status = mz_deflate(&stream, MZ_FINISH);
if (status != MZ_STREAM_END)
{
mz_deflateEnd(&stream);
return (status == MZ_OK) ? MZ_BUF_ERROR : status;
}
*pDest_len = stream.total_out;
return mz_deflateEnd(&stream);
}
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
{
return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
}
mz_ulong mz_compressBound(mz_ulong source_len)
{
return mz_deflateBound(NULL, source_len);
}
typedef struct
{
tinfl_decompressor m_decomp;
mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
int m_window_bits;
mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
tinfl_status m_last_status;
} inflate_state;
int mz_inflateInit2(mz_streamp pStream, int window_bits)
{
inflate_state *pDecomp;
if (!pStream)
return MZ_STREAM_ERROR;
if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
return MZ_PARAM_ERROR;
pStream->data_type = 0;
pStream->adler = 0;
pStream->msg = NULL;
pStream->total_in = 0;
pStream->total_out = 0;
pStream->reserved = 0;
if (!pStream->zalloc)
pStream->zalloc = miniz_def_alloc_func;
if (!pStream->zfree)
pStream->zfree = miniz_def_free_func;
pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
if (!pDecomp)
return MZ_MEM_ERROR;
pStream->state = (struct mz_internal_state *)pDecomp;
tinfl_init(&pDecomp->m_decomp);
pDecomp->m_dict_ofs = 0;
pDecomp->m_dict_avail = 0;
pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
pDecomp->m_first_call = 1;
pDecomp->m_has_flushed = 0;
pDecomp->m_window_bits = window_bits;
return MZ_OK;
}
int mz_inflateInit(mz_streamp pStream)
{
return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
}
int mz_inflate(mz_streamp pStream, int flush)
{
inflate_state *pState;
mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
size_t in_bytes, out_bytes, orig_avail_in;
tinfl_status status;
if ((!pStream) || (!pStream->state))
return MZ_STREAM_ERROR;
if (flush == MZ_PARTIAL_FLUSH)
flush = MZ_SYNC_FLUSH;
if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
return MZ_STREAM_ERROR;
pState = (inflate_state *)pStream->state;
if (pState->m_window_bits > 0)
decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
orig_avail_in = pStream->avail_in;
first_call = pState->m_first_call;
pState->m_first_call = 0;
if (pState->m_last_status < 0)
return MZ_DATA_ERROR;
if (pState->m_has_flushed && (flush != MZ_FINISH))
return MZ_STREAM_ERROR;
pState->m_has_flushed |= (flush == MZ_FINISH);
if ((flush == MZ_FINISH) && (first_call))
{
/* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
in_bytes = pStream->avail_in;
out_bytes = pStream->avail_out;
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
pState->m_last_status = status;
pStream->next_in += (mz_uint)in_bytes;
pStream->avail_in -= (mz_uint)in_bytes;
pStream->total_in += (mz_uint)in_bytes;
pStream->adler = tinfl_get_adler32(&pState->m_decomp);
pStream->next_out += (mz_uint)out_bytes;
pStream->avail_out -= (mz_uint)out_bytes;
pStream->total_out += (mz_uint)out_bytes;
if (status < 0)
return MZ_DATA_ERROR;
else if (status != TINFL_STATUS_DONE)
{
pState->m_last_status = TINFL_STATUS_FAILED;
return MZ_BUF_ERROR;
}
return MZ_STREAM_END;
}
/* flush != MZ_FINISH then we must assume there's more input. */
if (flush != MZ_FINISH)
decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
if (pState->m_dict_avail)
{
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
pStream->next_out += n;
pStream->avail_out -= n;
pStream->total_out += n;
pState->m_dict_avail -= n;
pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
}
for (;;)
{
in_bytes = pStream->avail_in;
out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
pState->m_last_status = status;
pStream->next_in += (mz_uint)in_bytes;
pStream->avail_in -= (mz_uint)in_bytes;
pStream->total_in += (mz_uint)in_bytes;
pStream->adler = tinfl_get_adler32(&pState->m_decomp);
pState->m_dict_avail = (mz_uint)out_bytes;
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
pStream->next_out += n;
pStream->avail_out -= n;
pStream->total_out += n;
pState->m_dict_avail -= n;
pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
if (status < 0)
return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
else if (flush == MZ_FINISH)
{
/* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
if (status == TINFL_STATUS_DONE)
return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
/* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
else if (!pStream->avail_out)
return MZ_BUF_ERROR;
}
else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
break;
}
return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
}
int mz_inflateEnd(mz_streamp pStream)
{
if (!pStream)
return MZ_STREAM_ERROR;
if (pStream->state)
{
pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL;
}
return MZ_OK;
}
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
{
mz_stream stream;
int status;
memset(&stream, 0, sizeof(stream));
/* In case mz_ulong is 64-bits (argh I hate longs). */
if ((source_len | *pDest_len) > 0xFFFFFFFFU)
return MZ_PARAM_ERROR;
stream.next_in = pSource;
stream.avail_in = (mz_uint32)source_len;
stream.next_out = pDest;
stream.avail_out = (mz_uint32)*pDest_len;
status = mz_inflateInit(&stream);
if (status != MZ_OK)
return status;
status = mz_inflate(&stream, MZ_FINISH);
if (status != MZ_STREAM_END)
{
mz_inflateEnd(&stream);
return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
}
*pDest_len = stream.total_out;
return mz_inflateEnd(&stream);
}
const char *mz_error(int err)
{
static struct
{
int m_err;
const char *m_pDesc;
} s_error_descs[] =
{
{ MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
};
mz_uint i;
for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
if (s_error_descs[i].m_err == err)
return s_error_descs[i].m_pDesc;
return NULL;
}
#endif /*MINIZ_NO_ZLIB_APIS */
#ifdef __cplusplus
}
#endif
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import itertools
import subprocess
import pathlib
import shutil
def generate_snapshots():
single_styles = ["changes", "grid", "header", "numbers"]
collective_styles = ["full", "plain"]
for num in range(len(single_styles)):
for grouped in itertools.combinations(single_styles, num + 1):
generate_style_snapshot(",".join(grouped))
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))
def generate_snapshot(name, arguments):
command = "cargo run -- --paging=never --color=never --decorations=always "
command += "{args} sample.rs > output/{name}.snapshot.txt".format(
name=name,
args=arguments
)
print("generating snapshot for {}".format(name))
subprocess.call(command, shell=True)
def build_bat():
print("building bat")
subprocess.call("cargo build", cwd="../..", shell=True)
def prepare_output_dir():
shutil.rmtree("output", ignore_errors=True)
pathlib.Path("output").mkdir()
def modify_sample_file():
print("modifying sample.rs to show changes")
shutil.copyfile("sample.modified.rs", "sample.rs")
def undo_sample_file_modification():
print("undoing sample.rs modifications")
subprocess.call("git checkout -- sample.rs", shell=True)
build_bat()
prepare_output_dir()
modify_sample_file()
generate_snapshots()
undo_sample_file_modification()
@@ -0,0 +1,36 @@
struct Rectangle {
width: u32,
height: u32,
}
_ fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
~ "The perimeter of the rectangle is {} pixels.",
~ perimeter(&rect1)
);
+ println!(r#"This line contains invalid utf8: ""#;
}
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 ?
~ */
@@ -0,0 +1,37 @@
│ struct Rectangle {
│ width: u32,
│ height: u32,
│ }
_ │ fn main() {
│ let rect1 = Rectangle { width: 30, height: 50 };
│ println!(
~ │ "The perimeter of the rectangle is {} pixels.",
~ │ perimeter(&rect1)
│ );
+ │ println!(r#"This line contains invalid utf8: ""#;
│ }
│ 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 ?
~ │ */
──┴─────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,40 @@
──┬─────────────────────────────────────────────────────────────────────────────
│ File: sample.rs
──┼─────────────────────────────────────────────────────────────────────────────
│ struct Rectangle {
│ width: u32,
│ height: u32,
│ }
_ │ fn main() {
│ let rect1 = Rectangle { width: 30, height: 50 };
│ println!(
~ │ "The perimeter of the rectangle is {} pixels.",
~ │ perimeter(&rect1)
│ );
+ │ println!(r#"This line contains invalid utf8: ""#;
│ }
│ 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 ?
~ │ */
──┴─────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,40 @@
───────┬────────────────────────────────────────────────────────────────────────
│ File: sample.rs
───────┼────────────────────────────────────────────────────────────────────────
1 │ struct Rectangle {
2 │ width: u32,
3 │ height: u32,
4 │ }
5 │
6 _ │ fn main() {
7 │ let rect1 = Rectangle { width: 30, height: 50 };
8 │
9 │ println!(
10 ~ │ "The perimeter of the rectangle is {} pixels.",
11 ~ │ perimeter(&rect1)
12 │ );
13 + │ println!(r#"This line contains invalid utf8: ""#;
14 │ }
15 │
16 │ fn area(rectangle: &Rectangle) -> u32 {
17 │ rectangle.width * rectangle.height
18 │ }
19 │
20 + │ fn perimeter(rectangle: &Rectangle) -> u32 {
21 + │ (rectangle.width + rectangle.height) * 2
22 + │ }
23 + │
24 │ // Tab alignment:
25 │ /*
26 │ Indent
27 │ 1 2 3 4
28 │ 1 ?
29 │ 22 ?
30 │ 333 ?
31 │ 4444 ?
32 │ 55555 ?
33 │ 666666 ?
34 │ 7777777 ?
35 │ 88888888 ?
36 ~ │ */
───────┴────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,37 @@
1 │ struct Rectangle {
2 │ width: u32,
3 │ height: u32,
4 │ }
5 │
6 _ │ fn main() {
7 │ let rect1 = Rectangle { width: 30, height: 50 };
8 │
9 │ println!(
10 ~ │ "The perimeter of the rectangle is {} pixels.",
11 ~ │ perimeter(&rect1)
12 │ );
13 + │ println!(r#"This line contains invalid utf8: ""#;
14 │ }
15 │
16 │ fn area(rectangle: &Rectangle) -> u32 {
17 │ rectangle.width * rectangle.height
18 │ }
19 │
20 + │ fn perimeter(rectangle: &Rectangle) -> u32 {
21 + │ (rectangle.width + rectangle.height) * 2
22 + │ }
23 + │
24 │ // Tab alignment:
25 │ /*
26 │ Indent
27 │ 1 2 3 4
28 │ 1 ?
29 │ 22 ?
30 │ 333 ?
31 │ 4444 ?
32 │ 55555 ?
33 │ 666666 ?
34 │ 7777777 ?
35 │ 88888888 ?
36 ~ │ */
───────┴────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,37 @@
File: sample.rs
struct Rectangle {
width: u32,
height: u32,
}
_ fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
~ "The perimeter of the rectangle is {} pixels.",
~ perimeter(&rect1)
);
+ println!(r#"This line contains invalid utf8: ""#;
}
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 ?
~ */
@@ -0,0 +1,37 @@
File: sample.rs
1 struct Rectangle {
2 width: u32,
3 height: u32,
4 }
5
6 _ fn main() {
7 let rect1 = Rectangle { width: 30, height: 50 };
8
9 println!(
10 ~ "The perimeter of the rectangle is {} pixels.",
11 ~ perimeter(&rect1)
12 );
13 + println!(r#"This line contains invalid utf8: ""#;
14 }
15
16 fn area(rectangle: &Rectangle) -> u32 {
17 rectangle.width * rectangle.height
18 }
19
20 + fn perimeter(rectangle: &Rectangle) -> u32 {
21 + (rectangle.width + rectangle.height) * 2
22 + }
23 +
24 // Tab alignment:
25 /*
26 Indent
27 1 2 3 4
28 1 ?
29 22 ?
30 333 ?
31 4444 ?
32 55555 ?
33 666666 ?
34 7777777 ?
35 88888888 ?
36 ~ */
@@ -0,0 +1,36 @@
1 struct Rectangle {
2 width: u32,
3 height: u32,
4 }
5
6 _ fn main() {
7 let rect1 = Rectangle { width: 30, height: 50 };
8
9 println!(
10 ~ "The perimeter of the rectangle is {} pixels.",
11 ~ perimeter(&rect1)
12 );
13 + println!(r#"This line contains invalid utf8: ""#;
14 }
15
16 fn area(rectangle: &Rectangle) -> u32 {
17 rectangle.width * rectangle.height
18 }
19
20 + fn perimeter(rectangle: &Rectangle) -> u32 {
21 + (rectangle.width + rectangle.height) * 2
22 + }
23 +
24 // Tab alignment:
25 /*
26 Indent
27 1 2 3 4
28 1 ?
29 22 ?
30 333 ?
31 4444 ?
32 55555 ?
33 666666 ?
34 7777777 ?
35 88888888 ?
36 ~ */
+40
View File
@@ -0,0 +1,40 @@
───────┬────────────────────────────────────────────────────────────────────────
│ File: sample.rs
───────┼────────────────────────────────────────────────────────────────────────
1 │ struct Rectangle {
2 │ width: u32,
3 │ height: u32,
4 │ }
5 │
6 _ │ fn main() {
7 │ let rect1 = Rectangle { width: 30, height: 50 };
8 │
9 │ println!(
10 ~ │ "The perimeter of the rectangle is {} pixels.",
11 ~ │ perimeter(&rect1)
12 │ );
13 + │ println!(r#"This line contains invalid utf8: ""#;
14 │ }
15 │
16 │ fn area(rectangle: &Rectangle) -> u32 {
17 │ rectangle.width * rectangle.height
18 │ }
19 │
20 + │ fn perimeter(rectangle: &Rectangle) -> u32 {
21 + │ (rectangle.width + rectangle.height) * 2
22 + │ }
23 + │
24 │ // Tab alignment:
25 │ /*
26 │ Indent
27 │ 1 2 3 4
28 │ 1 ?
29 │ 22 ?
30 │ 333 ?
31 │ 4444 ?
32 │ 55555 ?
33 │ 666666 ?
34 │ 7777777 ?
35 │ 88888888 ?
36 ~ │ */
───────┴────────────────────────────────────────────────────────────────────────
+37
View File
@@ -0,0 +1,37 @@
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The perimeter of the rectangle is {} pixels.",
perimeter(&rect1)
);
println!(r#"This line contains invalid utf8: ""#;
}
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 ?
*/
────────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,40 @@
────────────────────────────────────────────────────────────────────────────────
File: sample.rs
────────────────────────────────────────────────────────────────────────────────
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The perimeter of the rectangle is {} pixels.",
perimeter(&rect1)
);
println!(r#"This line contains invalid utf8: ""#;
}
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 ?
*/
────────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,40 @@
─────┬──────────────────────────────────────────────────────────────────────────
│ File: sample.rs
─────┼──────────────────────────────────────────────────────────────────────────
1 │ struct Rectangle {
2 │ width: u32,
3 │ height: u32,
4 │ }
5 │
6 │ fn main() {
7 │ let rect1 = Rectangle { width: 30, height: 50 };
8 │
9 │ println!(
10 │ "The perimeter of the rectangle is {} pixels.",
11 │ perimeter(&rect1)
12 │ );
13 │ println!(r#"This line contains invalid utf8: ""#;
14 │ }
15 │
16 │ fn area(rectangle: &Rectangle) -> u32 {
17 │ rectangle.width * rectangle.height
18 │ }
19 │
20 │ fn perimeter(rectangle: &Rectangle) -> u32 {
21 │ (rectangle.width + rectangle.height) * 2
22 │ }
23 │
24 │ // Tab alignment:
25 │ /*
26 │ Indent
27 │ 1 2 3 4
28 │ 1 ?
29 │ 22 ?
30 │ 333 ?
31 │ 4444 ?
32 │ 55555 ?
33 │ 666666 ?
34 │ 7777777 ?
35 │ 88888888 ?
36 │ */
─────┴──────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,37 @@
1 │ struct Rectangle {
2 │ width: u32,
3 │ height: u32,
4 │ }
5 │
6 │ fn main() {
7 │ let rect1 = Rectangle { width: 30, height: 50 };
8 │
9 │ println!(
10 │ "The perimeter of the rectangle is {} pixels.",
11 │ perimeter(&rect1)
12 │ );
13 │ println!(r#"This line contains invalid utf8: ""#;
14 │ }
15 │
16 │ fn area(rectangle: &Rectangle) -> u32 {
17 │ rectangle.width * rectangle.height
18 │ }
19 │
20 │ fn perimeter(rectangle: &Rectangle) -> u32 {
21 │ (rectangle.width + rectangle.height) * 2
22 │ }
23 │
24 │ // Tab alignment:
25 │ /*
26 │ Indent
27 │ 1 2 3 4
28 │ 1 ?
29 │ 22 ?
30 │ 333 ?
31 │ 4444 ?
32 │ 55555 ?
33 │ 666666 ?
34 │ 7777777 ?
35 │ 88888888 ?
36 │ */
─────┴──────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,37 @@
File: sample.rs
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The perimeter of the rectangle is {} pixels.",
perimeter(&rect1)
);
println!(r#"This line contains invalid utf8: ""#;
}
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