Repository: sharkdp/bat Branch: master Commit: 4a38eab3eaa1 Files: 885 Total size: 6.0 MB Directory structure: gitextract_65sk4665/ ├── .cargo/ │ └── audit.toml ├── .envrc ├── .github/ │ ├── .codecov.yml │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yml │ │ ├── feature_request.md │ │ ├── question.md │ │ └── syntax_request.md │ ├── dependabot.yml │ └── workflows/ │ ├── CICD.yml │ └── require-changelog-for-PRs.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── NOTICE ├── README.md ├── SECURITY.md ├── assets/ │ ├── .gitattributes │ ├── .ignore │ ├── completions/ │ │ ├── _bat.ps1.in │ │ ├── bat.bash.in │ │ ├── bat.fish.in │ │ └── bat.zsh.in │ ├── create.sh │ ├── manual/ │ │ └── bat.1.in │ ├── patches/ │ │ ├── 1337.tmTheme.patch │ │ ├── C#.sublime-syntax.patch │ │ ├── Groff.sublime-syntax.patch │ │ ├── JavaDoc.sublime-syntax.patch │ │ ├── JavaScript.sublime-syntax.patch │ │ ├── Lisp.sublime-syntax.patch │ │ ├── Makefile.sublime-syntax.patch │ │ ├── Markdown.sublime-syntax.patch │ │ ├── MediaWiki.sublime-syntax.patch │ │ ├── Monokai-Extended.tmTheme.patch │ │ ├── OneHalfDark.tmTheme.patch │ │ ├── Python.sublime-syntax.patch │ │ ├── Rust.sublime-syntax.patch │ │ ├── ShellScript.sublime-syntax.patch │ │ ├── TodoTxt.sublime-syntax.patch │ │ ├── TwoDark.tmTheme.patch │ │ └── XML.sublime-syntax.patch │ ├── syntaxes/ │ │ └── 02_Extra/ │ │ ├── Apache.sublime-syntax │ │ ├── AsciiDoc.sublime-syntax │ │ ├── Assembly (ARM).sublime-syntax │ │ ├── Assembly (x86_64).sublime-syntax │ │ ├── CSV/ │ │ │ ├── CSV-comma.sublime-syntax │ │ │ ├── CSV-pipe.sublime-syntax │ │ │ ├── CSV-semi-colon.sublime-syntax │ │ │ ├── CSV.sublime-syntax │ │ │ └── TSV.sublime-syntax │ │ ├── Cabal.sublime-syntax │ │ ├── CoffeeScript.sublime-syntax │ │ ├── CpuInfo.sublime-syntax │ │ ├── Crystal.sublime-syntax │ │ ├── Dart.sublime-syntax │ │ ├── DotENV.sublime-syntax │ │ ├── Fstab.sublime-syntax │ │ ├── Group.sublime-syntax │ │ ├── HTML (Twig).sublime-syntax │ │ ├── INI.sublime-syntax │ │ ├── JavaScript (Babel).sublime-syntax │ │ ├── Kotlin.sublime-syntax │ │ ├── Lean.sublime-syntax │ │ ├── LiveScript.sublime-syntax │ │ ├── Manpage.sublime-syntax │ │ ├── MemInfo.sublime-syntax │ │ ├── Nim.sublime-syntax │ │ ├── Ninja.sublime-syntax │ │ ├── Nix.sublime-syntax │ │ ├── Org mode.sublime-syntax │ │ ├── Passwd.sublime-syntax │ │ ├── PowerShell.sublime-syntax │ │ ├── QML.sublime-syntax │ │ ├── Racket.sublime-syntax │ │ ├── Rego.sublime-syntax │ │ ├── Requirementstxt.sublime-syntax │ │ ├── Resolv.sublime-syntax │ │ ├── Robot.sublime-syntax │ │ ├── SML.sublime-syntax │ │ ├── Slim.sublime-syntax │ │ ├── Stylus.sublime-syntax │ │ ├── Swift.sublime-syntax │ │ ├── TypeScript.sublime-syntax │ │ ├── TypsecriptReact.sublime-syntax │ │ ├── Verilog.sublime-syntax │ │ ├── VimHelp.sublime-syntax │ │ ├── apt-source-list.sublime-syntax │ │ ├── gnuplot.sublime-syntax │ │ ├── log.sublime-syntax │ │ ├── show-nonprintable.sublime-syntax │ │ ├── syntax_test_csv.csv │ │ ├── syntax_test_helphelp.txt │ │ ├── syntax_test_man.man │ │ ├── syntax_test_requirements.txt │ │ ├── syntax_test_tsv.tsv │ │ ├── syslog.sublime-syntax │ │ └── wgsl.sublime-syntax │ ├── theme_preview.rs │ └── themes/ │ ├── ansi.tmTheme │ ├── base16-256.tmTheme │ └── base16.tmTheme ├── build/ │ ├── application.rs │ ├── main.rs │ ├── syntax_mapping.rs │ └── util.rs ├── diagnostics/ │ ├── .gitattributes │ └── info.sh ├── doc/ │ ├── README-ja.md │ ├── README-ko.md │ ├── README-ru.md │ ├── README-zh.md │ ├── alternatives.md │ ├── assets.md │ ├── long-help.txt │ ├── release-checklist.md │ ├── short-help.txt │ └── sponsors.md ├── examples/ │ ├── advanced.rs │ ├── buffer.rs │ ├── cat.rs │ ├── inputs.rs │ ├── list_syntaxes_and_themes.rs │ ├── simple.rs │ └── yaml.rs ├── flake.nix ├── rustfmt.toml ├── src/ │ ├── assets/ │ │ ├── assets_metadata.rs │ │ ├── build_assets/ │ │ │ └── acknowledgements.rs │ │ ├── build_assets.rs │ │ ├── lazy_theme_set.rs │ │ └── serialized_syntax_set.rs │ ├── assets.rs │ ├── bin/ │ │ └── bat/ │ │ ├── app.rs │ │ ├── assets.rs │ │ ├── clap_app.rs │ │ ├── completions.rs │ │ ├── config.rs │ │ ├── directories.rs │ │ ├── input.rs │ │ └── main.rs │ ├── config.rs │ ├── controller.rs │ ├── decorations.rs │ ├── diff.rs │ ├── error.rs │ ├── input.rs │ ├── less.rs │ ├── lessopen.rs │ ├── lib.rs │ ├── line_range.rs │ ├── macros.rs │ ├── nonprintable_notation.rs │ ├── output.rs │ ├── pager.rs │ ├── paging.rs │ ├── preprocessor.rs │ ├── pretty_printer.rs │ ├── printer.rs │ ├── style.rs │ ├── syntax_mapping/ │ │ ├── builtin.rs │ │ ├── builtins/ │ │ │ ├── README.md │ │ │ ├── bsd-family/ │ │ │ │ ├── .gitkeep │ │ │ │ └── 50-os-release.toml │ │ │ ├── common/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── 50-apache.toml │ │ │ │ ├── 50-aws-credentials.toml │ │ │ │ ├── 50-bat.toml │ │ │ │ ├── 50-citation.toml │ │ │ │ ├── 50-container.toml │ │ │ │ ├── 50-cpp.toml │ │ │ │ ├── 50-diff.toml │ │ │ │ ├── 50-dotnet-xml.toml │ │ │ │ ├── 50-f-sharp.toml │ │ │ │ ├── 50-gcloud-cli-config.toml │ │ │ │ ├── 50-git.toml │ │ │ │ ├── 50-json.toml │ │ │ │ ├── 50-markdown.toml │ │ │ │ ├── 50-mill.toml │ │ │ │ ├── 50-nginx.toml │ │ │ │ ├── 50-nix.toml │ │ │ │ ├── 50-nmap.toml │ │ │ │ ├── 50-proxy-auto-config.toml │ │ │ │ ├── 50-ron.toml │ │ │ │ ├── 50-sarif.toml │ │ │ │ ├── 50-ssh.toml │ │ │ │ ├── 90-ignore-files.toml │ │ │ │ ├── 99-unset-ambiguous-extensions.toml │ │ │ │ ├── 99-unset-ambiguous-filenames.toml │ │ │ │ └── xonsh.toml │ │ │ ├── linux/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── 50-containers.toml │ │ │ │ ├── 50-flatpak.toml │ │ │ │ ├── 50-kubernetes.toml │ │ │ │ ├── 50-os-release.toml │ │ │ │ ├── 50-pacman.toml │ │ │ │ ├── 50-paru.toml │ │ │ │ ├── 50-podman-quadlet.toml │ │ │ │ └── 50-systemd.toml │ │ │ ├── macos/ │ │ │ │ └── .gitkeep │ │ │ ├── unix-family/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── 50-apache.toml │ │ │ │ ├── 50-certbot.toml │ │ │ │ ├── 50-fish-shell.toml │ │ │ │ ├── 50-korn-shell.toml │ │ │ │ ├── 50-mail-spool.toml │ │ │ │ ├── 50-nginx.toml │ │ │ │ ├── 50-shell.toml │ │ │ │ ├── 50-syslog.toml │ │ │ │ └── 50-wireguard.toml │ │ │ └── windows/ │ │ │ └── .gitkeep │ │ └── ignored_suffixes.rs │ ├── syntax_mapping.rs │ ├── terminal.rs │ ├── theme.rs │ ├── vscreen.rs │ └── wrapping.rs └── tests/ ├── .gitattributes ├── assets.rs ├── benchmarks/ │ ├── .gitignore │ ├── .ignore │ ├── highlighting-speed-src/ │ │ ├── grep-output-ansi-sequences.txt │ │ ├── jquery.js │ │ ├── miniz.c │ │ └── numpy_test_multiarray.py │ ├── many-small-files/ │ │ ├── small-file-0.txt │ │ ├── small-file-1.txt │ │ ├── small-file-10.txt │ │ ├── small-file-100.txt │ │ ├── small-file-11.txt │ │ ├── small-file-12.txt │ │ ├── small-file-13.txt │ │ ├── small-file-14.txt │ │ ├── small-file-15.txt │ │ ├── small-file-16.txt │ │ ├── small-file-17.txt │ │ ├── small-file-18.txt │ │ ├── small-file-19.txt │ │ ├── small-file-2.txt │ │ ├── small-file-20.txt │ │ ├── small-file-21.txt │ │ ├── small-file-22.txt │ │ ├── small-file-23.txt │ │ ├── small-file-24.txt │ │ ├── small-file-25.txt │ │ ├── small-file-26.txt │ │ ├── small-file-27.txt │ │ ├── small-file-28.txt │ │ ├── small-file-29.txt │ │ ├── small-file-3.txt │ │ ├── small-file-30.txt │ │ ├── small-file-31.txt │ │ ├── small-file-32.txt │ │ ├── small-file-33.txt │ │ ├── small-file-34.txt │ │ ├── small-file-35.txt │ │ ├── small-file-36.txt │ │ ├── small-file-37.txt │ │ ├── small-file-38.txt │ │ ├── small-file-39.txt │ │ ├── small-file-4.txt │ │ ├── small-file-40.txt │ │ ├── small-file-41.txt │ │ ├── small-file-42.txt │ │ ├── small-file-43.txt │ │ ├── small-file-44.txt │ │ ├── small-file-45.txt │ │ ├── small-file-46.txt │ │ ├── small-file-47.txt │ │ ├── small-file-48.txt │ │ ├── small-file-49.txt │ │ ├── small-file-5.txt │ │ ├── small-file-50.txt │ │ ├── small-file-51.txt │ │ ├── small-file-52.txt │ │ ├── small-file-53.txt │ │ ├── small-file-54.txt │ │ ├── small-file-55.txt │ │ ├── small-file-56.txt │ │ ├── small-file-57.txt │ │ ├── small-file-58.txt │ │ ├── small-file-59.txt │ │ ├── small-file-6.txt │ │ ├── small-file-60.txt │ │ ├── small-file-61.txt │ │ ├── small-file-62.txt │ │ ├── small-file-63.txt │ │ ├── small-file-64.txt │ │ ├── small-file-65.txt │ │ ├── small-file-66.txt │ │ ├── small-file-67.txt │ │ ├── small-file-68.txt │ │ ├── small-file-69.txt │ │ ├── small-file-7.txt │ │ ├── small-file-70.txt │ │ ├── small-file-71.txt │ │ ├── small-file-72.txt │ │ ├── small-file-73.txt │ │ ├── small-file-74.txt │ │ ├── small-file-75.txt │ │ ├── small-file-76.txt │ │ ├── small-file-77.txt │ │ ├── small-file-78.txt │ │ ├── small-file-79.txt │ │ ├── small-file-8.txt │ │ ├── small-file-80.txt │ │ ├── small-file-81.txt │ │ ├── small-file-82.txt │ │ ├── small-file-83.txt │ │ ├── small-file-84.txt │ │ ├── small-file-85.txt │ │ ├── small-file-86.txt │ │ ├── small-file-87.txt │ │ ├── small-file-88.txt │ │ ├── small-file-89.txt │ │ ├── small-file-9.txt │ │ ├── small-file-90.txt │ │ ├── small-file-91.txt │ │ ├── small-file-92.txt │ │ ├── small-file-93.txt │ │ ├── small-file-94.txt │ │ ├── small-file-95.txt │ │ ├── small-file-96.txt │ │ ├── small-file-97.txt │ │ ├── small-file-98.txt │ │ └── small-file-99.txt │ ├── run-benchmarks.sh │ └── startup-time-src/ │ ├── Containerfile │ ├── mystery-file │ ├── small-CpuInfo-file.cpuinfo │ └── small-Markdown-file.md ├── examples/ │ ├── bat-tabs.conf │ ├── bat-theme.conf │ ├── bat-windows.conf │ ├── bat.conf │ ├── cache │ ├── cache.c │ ├── cache_source/ │ │ ├── syntaxes/ │ │ │ └── c.sublime-syntax │ │ └── themes/ │ │ └── example.tmTheme │ ├── control_characters.txt │ ├── empty.txt │ ├── empty_lines.txt │ ├── git/ │ │ ├── .config/ │ │ │ └── git/ │ │ │ └── config │ │ └── .gitconfig │ ├── git-commit.man │ ├── long-single-line.txt │ ├── longline.json │ ├── map-syntax_case.Config │ ├── multiline.txt │ ├── nonprintable.txt │ ├── overstrike.txt │ ├── regression_tests/ │ │ ├── first_line_fallback.invalid-syntax │ │ ├── issue_190.md │ │ ├── issue_2541.txt │ │ ├── issue_28.md │ │ ├── issue_314.hs │ │ ├── issue_914.rb │ │ ├── issue_915.vue │ │ └── issue_985.js │ ├── single-line.txt │ ├── sub_directory/ │ │ └── dummy.txt │ ├── system_config/ │ │ └── bat/ │ │ └── config │ ├── tabs.txt │ ├── test.A—B가 │ ├── test.binary │ ├── test.demo.foo.suffix │ ├── test.demo.suffix │ ├── test.json.suffix │ ├── test.json~ │ ├── test.txt │ ├── test_BOM.txt │ ├── test_UTF-16BE-complicated.txt │ ├── test_UTF-16BE.txt │ ├── test_UTF-16LE-complicated.txt │ ├── test_UTF-16LE.txt │ ├── this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt │ ├── unicode-wrap.txt │ └── word-wrap.txt ├── github-actions.rs ├── integration_tests.rs ├── mocked-pagers/ │ ├── echo.bat │ ├── more │ ├── more.bat │ ├── most │ └── most.bat ├── no_duplicate_extensions.rs ├── scripts/ │ ├── find-slow-to-highlight-files.py │ └── license-checks.sh ├── snapshot_tests.rs ├── snapshots/ │ ├── generate_snapshots.py │ ├── output/ │ │ ├── changes.snapshot.txt │ │ ├── changes_grid.snapshot.txt │ │ ├── changes_grid_header.snapshot.txt │ │ ├── changes_grid_header_numbers.snapshot.txt │ │ ├── changes_grid_header_numbers_rule.snapshot.txt │ │ ├── changes_grid_header_rule.snapshot.txt │ │ ├── changes_grid_numbers.snapshot.txt │ │ ├── changes_grid_numbers_rule.snapshot.txt │ │ ├── changes_grid_rule.snapshot.txt │ │ ├── changes_header.snapshot.txt │ │ ├── changes_header_numbers.snapshot.txt │ │ ├── changes_header_numbers_rule.snapshot.txt │ │ ├── changes_header_rule.snapshot.txt │ │ ├── changes_numbers.snapshot.txt │ │ ├── changes_numbers_rule.snapshot.txt │ │ ├── changes_rule.snapshot.txt │ │ ├── full.snapshot.txt │ │ ├── grid.snapshot.txt │ │ ├── grid_header.snapshot.txt │ │ ├── grid_header_numbers.snapshot.txt │ │ ├── grid_header_numbers_rule.snapshot.txt │ │ ├── grid_header_rule.snapshot.txt │ │ ├── grid_numbers.snapshot.txt │ │ ├── grid_numbers_rule.snapshot.txt │ │ ├── grid_rule.snapshot.txt │ │ ├── header.snapshot.txt │ │ ├── header_numbers.snapshot.txt │ │ ├── header_numbers_rule.snapshot.txt │ │ ├── header_rule.snapshot.txt │ │ ├── numbers.snapshot.txt │ │ ├── numbers_rule.snapshot.txt │ │ ├── plain.snapshot.txt │ │ └── rule.snapshot.txt │ ├── sample.modified.rs │ └── sample.rs ├── syntax-tests/ │ ├── BatTestCustomAssets.sublime-syntax │ ├── compare_highlighted_versions.py │ ├── create_highlighted_versions.py │ ├── highlighted/ │ │ ├── ARM Assembly/ │ │ │ └── test.S │ │ ├── ASP/ │ │ │ └── test.asp │ │ ├── AWK/ │ │ │ └── quicksort.awk │ │ ├── ActionScript/ │ │ │ └── test.as │ │ ├── Ada/ │ │ │ ├── click.adb │ │ │ ├── click.ads │ │ │ └── click.gpr │ │ ├── Apache/ │ │ │ └── httpd.conf │ │ ├── AppleScript/ │ │ │ └── test.applescript │ │ ├── AsciiDoc/ │ │ │ └── test.adoc │ │ ├── Assembly (x86_64)/ │ │ │ └── test.nasm │ │ ├── Bash/ │ │ │ ├── batgrep.sh │ │ │ ├── korn_shell.wrong_ext │ │ │ └── simple.sh │ │ ├── BatTestCustomAssets/ │ │ │ └── NoColorsUnlessCustomAssetsAreUsed.battestcustomassets │ │ ├── Batch/ │ │ │ └── build.bat │ │ ├── BibTeX/ │ │ │ └── test.bib │ │ ├── C/ │ │ │ └── test.c │ │ ├── C-Sharp/ │ │ │ └── Stack.cs │ │ ├── CFML/ │ │ │ └── test.cfml │ │ ├── CMake/ │ │ │ └── CMakeLists.txt │ │ ├── COBOL/ │ │ │ ├── payroll.cbl │ │ │ └── test.cbl │ │ ├── CSS/ │ │ │ └── style.css │ │ ├── CSV/ │ │ │ ├── comma-delimited.csv │ │ │ ├── comma_in_quotes.csv │ │ │ ├── decimals_comma_decimal_point_pipe_delimited.csv │ │ │ ├── decimals_comma_decimal_point_semicolon_delimited.csv │ │ │ └── simple.tsv │ │ ├── Cabal/ │ │ │ └── semantic.cabal │ │ ├── Clojure/ │ │ │ └── test.clj │ │ ├── CoffeeScript/ │ │ │ └── coffeescript.coffee │ │ ├── Cpp/ │ │ │ └── test.cpp │ │ ├── CpuInfo/ │ │ │ └── test.cpuinfo │ │ ├── Crontab/ │ │ │ └── crontab.tab │ │ ├── Crystal/ │ │ │ └── test.cr │ │ ├── D/ │ │ │ └── test.d │ │ ├── Dart/ │ │ │ ├── inner_comment.dart │ │ │ └── test.dart │ │ ├── Diff/ │ │ │ └── 82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff │ │ ├── Dockerfile/ │ │ │ └── Dockerfile │ │ ├── Elixir/ │ │ │ └── command.ex │ │ ├── Elm/ │ │ │ └── test.elm │ │ ├── Email/ │ │ │ └── test.eml │ │ ├── Erlang/ │ │ │ └── bat_erlang.erl │ │ ├── EtcGroup/ │ │ │ └── test.group │ │ ├── F#/ │ │ │ └── string.fs │ │ ├── Fish/ │ │ │ └── test.fish │ │ ├── Fortran (Fixed Form)/ │ │ │ └── quicksort_real_F77.F │ │ ├── Fortran (Modern)/ │ │ │ └── test_savetxt.f90 │ │ ├── Fortran Namelist/ │ │ │ └── test.namelist │ │ ├── Fstab/ │ │ │ └── fstab │ │ ├── GDScript/ │ │ │ └── test.gd │ │ ├── GLSL/ │ │ │ └── test.glsl │ │ ├── Git Attributes/ │ │ │ └── example.gitattributes │ │ ├── Git Config/ │ │ │ └── text.gitconfig │ │ ├── Git Ignore/ │ │ │ └── test.gitignore │ │ ├── Go/ │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ └── main.go │ │ ├── GraphQL/ │ │ │ └── test.graphql │ │ ├── Graphviz DOT/ │ │ │ ├── test_digraph.dot │ │ │ └── test_graph.dot │ │ ├── Groff/ │ │ │ └── rustdoc.1 │ │ ├── Groovy/ │ │ │ └── test.groovy │ │ ├── HTML/ │ │ │ └── test.html │ │ ├── Haskell/ │ │ │ └── test.hs │ │ ├── Hosts/ │ │ │ └── hosts │ │ ├── INI/ │ │ │ ├── test.inf │ │ │ └── test.ini │ │ ├── Idris2/ │ │ │ └── test.idr │ │ ├── Ignored suffixes/ │ │ │ ├── test.rs.bak │ │ │ ├── test.rs.dpkg-dist │ │ │ ├── test.rs.dpkg-old │ │ │ ├── test.rs.in │ │ │ ├── test.rs.in.in │ │ │ ├── test.rs.old │ │ │ ├── test.rs.orig │ │ │ ├── test.rs.orig~ │ │ │ ├── test.rs.rpmnew │ │ │ ├── test.rs.rpmorig │ │ │ ├── test.rs.rpmsave │ │ │ ├── test.rs.ucf-dist │ │ │ ├── test.rs.ucf-new │ │ │ ├── test.rs.ucf-old │ │ │ ├── test.rs~ │ │ │ └── test.unknown~ │ │ ├── JQ/ │ │ │ └── sample.jq │ │ ├── JSON/ │ │ │ ├── example.ndjson │ │ │ └── test.json │ │ ├── Java/ │ │ │ └── test.java │ │ ├── Java Server Page (JSP)/ │ │ │ └── sessionDetail.jsp │ │ ├── JavaScript/ │ │ │ └── test.js │ │ ├── Jinja2/ │ │ │ └── template.jinja2 │ │ ├── Julia/ │ │ │ └── test.jl │ │ ├── Kotlin/ │ │ │ └── test.kt │ │ ├── LLVM/ │ │ │ └── test.ll │ │ ├── Lean/ │ │ │ └── test.lean │ │ ├── Less/ │ │ │ └── example.less │ │ ├── Lisp/ │ │ │ └── utils.lisp │ │ ├── Literate Haskell/ │ │ │ └── Main.lhs │ │ ├── LiveScript/ │ │ │ └── livescript-demo.ls │ │ ├── Log/ │ │ │ └── example.log │ │ ├── Lua/ │ │ │ └── test.lua │ │ ├── MATLAB/ │ │ │ └── test.matlab │ │ ├── Makefile/ │ │ │ └── Makefile │ │ ├── Manpage/ │ │ │ ├── bat-0.16.man │ │ │ ├── fzf-0.33.0.man │ │ │ ├── select-2.man │ │ │ ├── sway.5.man │ │ │ └── uwsm-0.26.3.man │ │ ├── Markdown/ │ │ │ ├── example.md │ │ │ └── typescript.md │ │ ├── MediaWiki/ │ │ │ └── test.mediawiki │ │ ├── MemInfo/ │ │ │ └── test.meminfo │ │ ├── NAnt Build File/ │ │ │ └── Default.build │ │ ├── NSE/ │ │ │ └── test.nse │ │ ├── NSIS/ │ │ │ └── test.nsi │ │ ├── Ninja/ │ │ │ └── test.ninja │ │ ├── OCaml/ │ │ │ └── syntax-test.ml │ │ ├── Objective-C/ │ │ │ └── test.m │ │ ├── Objective-C++/ │ │ │ └── test.mm │ │ ├── Odin/ │ │ │ └── test.odin │ │ ├── PHP/ │ │ │ └── test.php │ │ ├── Pascal/ │ │ │ └── test.pas │ │ ├── Passwd/ │ │ │ └── passwd │ │ ├── Perl/ │ │ │ └── test.pl │ │ ├── Plaintext/ │ │ │ └── plaintext.txt │ │ ├── PowerShell/ │ │ │ └── test.ps1 │ │ ├── Protocol Buffer/ │ │ │ └── vyconf.proto │ │ ├── Puppet/ │ │ │ └── manifest_large_exported_classes_node.pp │ │ ├── PureScript/ │ │ │ └── test.purs │ │ ├── Python/ │ │ │ └── battest.py │ │ ├── QML/ │ │ │ └── BatSyntaxTest.qml │ │ ├── R/ │ │ │ └── test.r │ │ ├── Racket/ │ │ │ └── test.rkt │ │ ├── Rego/ │ │ │ └── src_test.rego │ │ ├── Regular Expression/ │ │ │ └── test.re │ │ ├── Requirements.txt/ │ │ │ └── requirements.txt │ │ ├── Robot Framework/ │ │ │ └── recipe141_aws_simple_storage_service.robot │ │ ├── Ruby/ │ │ │ └── output.rb │ │ ├── Ruby Haml/ │ │ │ └── test.html.haml │ │ ├── Ruby On Rails/ │ │ │ └── test.rb │ │ ├── Rust/ │ │ │ └── output.rs │ │ ├── SCSS/ │ │ │ └── example.scss │ │ ├── SLS/ │ │ │ └── test.sls │ │ ├── SML/ │ │ │ └── sample.sml │ │ ├── SQL/ │ │ │ └── ims.sql │ │ ├── SSH Config/ │ │ │ └── ssh_config │ │ ├── SSHD Config/ │ │ │ └── sshd_config │ │ ├── Sass/ │ │ │ └── example.sass │ │ ├── Scala/ │ │ │ └── ConcurrentEffectLaws.scala │ │ ├── Slim/ │ │ │ └── test.slim │ │ ├── Solidity/ │ │ │ └── ERC721.sol │ │ ├── Strace/ │ │ │ └── ls.strace │ │ ├── Stylus/ │ │ │ └── gradients.styl │ │ ├── Svelte/ │ │ │ └── App.svelte │ │ ├── Swift/ │ │ │ └── test.swift │ │ ├── Syslog/ │ │ │ └── example.syslog │ │ ├── SystemVerilog/ │ │ │ └── output.sv │ │ ├── TOML/ │ │ │ └── Cargo.toml │ │ ├── Tcl/ │ │ │ └── test.tcl │ │ ├── TeX/ │ │ │ └── main.tex │ │ ├── Terraform/ │ │ │ └── main.tf │ │ ├── Textile/ │ │ │ └── test.textile │ │ ├── Todo.txt/ │ │ │ └── todo.txt │ │ ├── TypeScript/ │ │ │ ├── example.cts │ │ │ └── example.ts │ │ ├── TypeScriptReact/ │ │ │ └── app.tsx │ │ ├── Typst/ │ │ │ └── test.typ │ │ ├── VHDL/ │ │ │ └── test.vhdl │ │ ├── Verilog/ │ │ │ └── div_pipelined.v │ │ ├── VimHelp/ │ │ │ └── helphelp.txt │ │ ├── VimL/ │ │ │ └── source.vim │ │ ├── Vue/ │ │ │ └── example.vue │ │ ├── Vyper/ │ │ │ └── crowdsale.vy │ │ ├── WGSL/ │ │ │ └── test.wgsl │ │ ├── XAML/ │ │ │ └── ItemPage.xaml │ │ ├── XML/ │ │ │ ├── Directory.Build.props │ │ │ ├── console.csproj │ │ │ ├── example.xml │ │ │ └── projectname.targets │ │ ├── YAML/ │ │ │ └── example.yaml │ │ ├── Zig/ │ │ │ └── example.zig │ │ ├── cmd-help/ │ │ │ └── test.cmd-help │ │ ├── dash/ │ │ │ └── shfm │ │ ├── debsources/ │ │ │ └── sources.list │ │ ├── fish_history/ │ │ │ └── fish_history │ │ ├── gnuplot/ │ │ │ └── test.gp │ │ ├── http-request-response/ │ │ │ └── example.http │ │ ├── jsonnet/ │ │ │ └── stdlib.jsonnet │ │ ├── nginx/ │ │ │ └── nginx.conf │ │ ├── nim/ │ │ │ ├── main.nim │ │ │ └── test.nimble │ │ ├── nix/ │ │ │ └── test.nix │ │ ├── orgmode/ │ │ │ └── test.org │ │ ├── reStructuredText/ │ │ │ └── reference.rst │ │ ├── resolv.conf/ │ │ │ └── resolv.conf │ │ └── varlink/ │ │ └── org.varlink.certification.varlink │ ├── regression_test.sh │ ├── source/ │ │ ├── ARM Assembly/ │ │ │ └── test.S │ │ ├── ASP/ │ │ │ └── test.asp │ │ ├── AWK/ │ │ │ └── quicksort.awk │ │ ├── ActionScript/ │ │ │ └── test.as │ │ ├── Ada/ │ │ │ ├── LICENSE.md │ │ │ ├── click.adb │ │ │ ├── click.ads │ │ │ └── click.gpr │ │ ├── Apache/ │ │ │ └── httpd.conf │ │ ├── AppleScript/ │ │ │ └── test.applescript │ │ ├── AsciiDoc/ │ │ │ └── test.adoc │ │ ├── Assembly (x86_64)/ │ │ │ └── test.nasm │ │ ├── Bash/ │ │ │ ├── batgrep.sh │ │ │ ├── korn_shell.wrong_ext │ │ │ └── simple.sh │ │ ├── BatTestCustomAssets/ │ │ │ └── NoColorsUnlessCustomAssetsAreUsed.battestcustomassets │ │ ├── Batch/ │ │ │ ├── LICENSE.md │ │ │ └── build.bat │ │ ├── BibTeX/ │ │ │ └── test.bib │ │ ├── C/ │ │ │ └── test.c │ │ ├── C-Sharp/ │ │ │ └── Stack.cs │ │ ├── CFML/ │ │ │ └── test.cfml │ │ ├── CMake/ │ │ │ └── CMakeLists.txt │ │ ├── COBOL/ │ │ │ ├── payroll.cbl │ │ │ └── test.cbl │ │ ├── CSS/ │ │ │ └── style.css │ │ ├── CSV/ │ │ │ ├── LICENSE.md │ │ │ ├── comma-delimited.csv │ │ │ ├── comma_in_quotes.csv │ │ │ ├── decimals_comma_decimal_point_pipe_delimited.csv │ │ │ ├── decimals_comma_decimal_point_semicolon_delimited.csv │ │ │ └── simple.tsv │ │ ├── Cabal/ │ │ │ ├── LICENSE.md │ │ │ └── semantic.cabal │ │ ├── Clojure/ │ │ │ └── test.clj │ │ ├── CoffeeScript/ │ │ │ ├── LICENSE.md │ │ │ └── coffeescript.coffee │ │ ├── Cpp/ │ │ │ └── test.cpp │ │ ├── CpuInfo/ │ │ │ └── test.cpuinfo │ │ ├── Crontab/ │ │ │ └── crontab.tab │ │ ├── Crystal/ │ │ │ └── test.cr │ │ ├── D/ │ │ │ └── test.d │ │ ├── Dart/ │ │ │ ├── inner_comment.dart │ │ │ └── test.dart │ │ ├── Diff/ │ │ │ └── 82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff │ │ ├── Dockerfile/ │ │ │ └── Dockerfile │ │ ├── DotENV/ │ │ │ └── LICENSE.md │ │ ├── Elixir/ │ │ │ ├── LICENSE.md │ │ │ └── command.ex │ │ ├── Elm/ │ │ │ ├── LICENSE.md │ │ │ └── test.elm │ │ ├── Email/ │ │ │ └── test.eml │ │ ├── Erlang/ │ │ │ └── bat_erlang.erl │ │ ├── EtcGroup/ │ │ │ └── test.group │ │ ├── F#/ │ │ │ ├── LICENSE.md │ │ │ └── string.fs │ │ ├── Fish/ │ │ │ └── test.fish │ │ ├── Fortran (Fixed Form)/ │ │ │ ├── LICENSE.md │ │ │ └── quicksort_real_F77.F │ │ ├── Fortran (Modern)/ │ │ │ ├── LICENSE.md │ │ │ └── test_savetxt.f90 │ │ ├── Fortran Namelist/ │ │ │ └── test.namelist │ │ ├── Fstab/ │ │ │ └── fstab │ │ ├── GDScript/ │ │ │ └── test.gd │ │ ├── GLSL/ │ │ │ └── test.glsl │ │ ├── Git Attributes/ │ │ │ └── example.gitattributes │ │ ├── Git Config/ │ │ │ ├── LICENSE.md │ │ │ └── text.gitconfig │ │ ├── Git Ignore/ │ │ │ ├── LICENSE.md │ │ │ └── test.gitignore │ │ ├── Go/ │ │ │ ├── LICENSE.md │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ └── main.go │ │ ├── GraphQL/ │ │ │ └── test.graphql │ │ ├── Graphviz DOT/ │ │ │ ├── LICENSE.md │ │ │ ├── test_digraph.dot │ │ │ └── test_graph.dot │ │ ├── Groff/ │ │ │ ├── LICENSE.md │ │ │ └── rustdoc.1 │ │ ├── Groovy/ │ │ │ └── test.groovy │ │ ├── HTML/ │ │ │ └── test.html │ │ ├── Haskell/ │ │ │ └── test.hs │ │ ├── Hosts/ │ │ │ └── hosts │ │ ├── INI/ │ │ │ ├── test.inf │ │ │ └── test.ini │ │ ├── Idris2/ │ │ │ ├── LICENSE.md │ │ │ └── test.idr │ │ ├── Ignored suffixes/ │ │ │ ├── test.rs.bak │ │ │ ├── test.rs.dpkg-dist │ │ │ ├── test.rs.dpkg-old │ │ │ ├── test.rs.in │ │ │ ├── test.rs.in.in │ │ │ ├── test.rs.old │ │ │ ├── test.rs.orig │ │ │ ├── test.rs.orig~ │ │ │ ├── test.rs.rpmnew │ │ │ ├── test.rs.rpmorig │ │ │ ├── test.rs.rpmsave │ │ │ ├── test.rs.ucf-dist │ │ │ ├── test.rs.ucf-new │ │ │ ├── test.rs.ucf-old │ │ │ ├── test.rs~ │ │ │ └── test.unknown~ │ │ ├── JQ/ │ │ │ ├── LICENSE.md │ │ │ └── sample.jq │ │ ├── JSON/ │ │ │ ├── example.ndjson │ │ │ └── test.json │ │ ├── Java/ │ │ │ └── test.java │ │ ├── Java Server Page (JSP)/ │ │ │ ├── LICENSE.md │ │ │ ├── NOTICE │ │ │ └── sessionDetail.jsp │ │ ├── JavaScript/ │ │ │ └── test.js │ │ ├── Jinja2/ │ │ │ └── template.jinja2 │ │ ├── Julia/ │ │ │ └── test.jl │ │ ├── Kotlin/ │ │ │ └── test.kt │ │ ├── LLVM/ │ │ │ └── test.ll │ │ ├── Lean/ │ │ │ ├── LICENSE.md │ │ │ └── test.lean │ │ ├── Less/ │ │ │ └── example.less │ │ ├── Lisp/ │ │ │ ├── LICENSE.md │ │ │ └── utils.lisp │ │ ├── Literate Haskell/ │ │ │ └── Main.lhs │ │ ├── LiveScript/ │ │ │ ├── LICENSE.md │ │ │ └── livescript-demo.ls │ │ ├── Log/ │ │ │ └── example.log │ │ ├── Lua/ │ │ │ └── test.lua │ │ ├── MATLAB/ │ │ │ ├── LICENSE.md │ │ │ └── test.matlab │ │ ├── Makefile/ │ │ │ ├── LICENSE.md │ │ │ └── Makefile │ │ ├── Manpage/ │ │ │ ├── bat-0.16.man │ │ │ ├── fzf-0.33.0.man │ │ │ ├── select-2.man │ │ │ ├── sway.5.man │ │ │ └── uwsm-0.26.3.man │ │ ├── Markdown/ │ │ │ ├── example.md │ │ │ └── typescript.md │ │ ├── MediaWiki/ │ │ │ └── test.mediawiki │ │ ├── MemInfo/ │ │ │ └── test.meminfo │ │ ├── NAnt Build File/ │ │ │ ├── Default.build │ │ │ └── LICENSE.md │ │ ├── NSE/ │ │ │ └── test.nse │ │ ├── NSIS/ │ │ │ └── test.nsi │ │ ├── Ninja/ │ │ │ ├── LICENSE.md │ │ │ └── test.ninja │ │ ├── OCaml/ │ │ │ └── syntax-test.ml │ │ ├── Objective-C/ │ │ │ └── test.m │ │ ├── Objective-C++/ │ │ │ └── test.mm │ │ ├── Odin/ │ │ │ └── test.odin │ │ ├── PHP/ │ │ │ └── test.php │ │ ├── Pascal/ │ │ │ └── test.pas │ │ ├── Passwd/ │ │ │ └── passwd │ │ ├── Perl/ │ │ │ └── test.pl │ │ ├── Plaintext/ │ │ │ ├── README.md │ │ │ ├── bat_options │ │ │ └── plaintext.txt │ │ ├── PowerShell/ │ │ │ └── test.ps1 │ │ ├── Protocol Buffer/ │ │ │ └── vyconf.proto │ │ ├── Puppet/ │ │ │ ├── LICENSE.md │ │ │ └── manifest_large_exported_classes_node.pp │ │ ├── PureScript/ │ │ │ └── test.purs │ │ ├── Python/ │ │ │ └── battest.py │ │ ├── QML/ │ │ │ └── BatSyntaxTest.qml │ │ ├── R/ │ │ │ └── test.r │ │ ├── Racket/ │ │ │ └── test.rkt │ │ ├── Rego/ │ │ │ ├── LICENSE.md │ │ │ └── src_test.rego │ │ ├── Regular Expression/ │ │ │ └── test.re │ │ ├── Requirements.txt/ │ │ │ └── requirements.txt │ │ ├── Robot Framework/ │ │ │ ├── LICENSE.md │ │ │ └── recipe141_aws_simple_storage_service.robot │ │ ├── Ruby/ │ │ │ └── output.rb │ │ ├── Ruby Haml/ │ │ │ └── test.html.haml │ │ ├── Ruby On Rails/ │ │ │ └── test.rb │ │ ├── Rust/ │ │ │ └── output.rs │ │ ├── SCSS/ │ │ │ └── example.scss │ │ ├── SLS/ │ │ │ └── test.sls │ │ ├── SML/ │ │ │ └── sample.sml │ │ ├── SQL/ │ │ │ └── ims.sql │ │ ├── SSH Config/ │ │ │ └── ssh_config │ │ ├── SSHD Config/ │ │ │ └── sshd_config │ │ ├── Sass/ │ │ │ └── example.sass │ │ ├── Scala/ │ │ │ ├── ConcurrentEffectLaws.scala │ │ │ └── LICENSE.md │ │ ├── Slim/ │ │ │ └── test.slim │ │ ├── Solidity/ │ │ │ ├── ERC721.sol │ │ │ └── LICENSE.md │ │ ├── Strace/ │ │ │ └── ls.strace │ │ ├── Stylus/ │ │ │ ├── LICENSE.md │ │ │ └── gradients.styl │ │ ├── Svelte/ │ │ │ ├── App.svelte │ │ │ └── LICENSE.md │ │ ├── Swift/ │ │ │ └── test.swift │ │ ├── Syslog/ │ │ │ └── example.syslog │ │ ├── SystemVerilog/ │ │ │ └── output.sv │ │ ├── TOML/ │ │ │ └── Cargo.toml │ │ ├── Tcl/ │ │ │ └── test.tcl │ │ ├── TeX/ │ │ │ └── main.tex │ │ ├── Terraform/ │ │ │ └── main.tf │ │ ├── Textile/ │ │ │ └── test.textile │ │ ├── Todo.txt/ │ │ │ └── todo.txt │ │ ├── TypeScript/ │ │ │ ├── LICENSE.md │ │ │ ├── example.cts │ │ │ └── example.ts │ │ ├── TypeScriptReact/ │ │ │ ├── LICENSE.md │ │ │ └── app.tsx │ │ ├── Typst/ │ │ │ └── test.typ │ │ ├── VHDL/ │ │ │ └── test.vhdl │ │ ├── Verilog/ │ │ │ ├── LICENSE.md │ │ │ └── div_pipelined.v │ │ ├── VimHelp/ │ │ │ └── helphelp.txt │ │ ├── VimL/ │ │ │ └── source.vim │ │ ├── Vue/ │ │ │ └── example.vue │ │ ├── Vyper/ │ │ │ ├── LICENSE.md │ │ │ └── crowdsale.vy │ │ ├── WGSL/ │ │ │ ├── LICENSE.md │ │ │ └── test.wgsl │ │ ├── XAML/ │ │ │ ├── ItemPage.xaml │ │ │ └── LICENSE.md │ │ ├── XML/ │ │ │ ├── Directory.Build.props │ │ │ ├── console.csproj │ │ │ ├── example.xml │ │ │ └── projectname.targets │ │ ├── YAML/ │ │ │ └── example.yaml │ │ ├── Zig/ │ │ │ └── example.zig │ │ ├── cmd-help/ │ │ │ └── test.cmd-help │ │ ├── dash/ │ │ │ ├── LICENSE.md │ │ │ └── shfm │ │ ├── debsources/ │ │ │ └── sources.list │ │ ├── fish_history/ │ │ │ └── fish_history │ │ ├── gnuplot/ │ │ │ └── test.gp │ │ ├── http-request-response/ │ │ │ └── example.http │ │ ├── jsonnet/ │ │ │ ├── LICENSE.md │ │ │ └── stdlib.jsonnet │ │ ├── nginx/ │ │ │ └── nginx.conf │ │ ├── nim/ │ │ │ ├── main.nim │ │ │ └── test.nimble │ │ ├── nix/ │ │ │ └── test.nix │ │ ├── orgmode/ │ │ │ └── test.org │ │ ├── reStructuredText/ │ │ │ └── reference.rst │ │ ├── resolv.conf/ │ │ │ └── resolv.conf │ │ └── varlink/ │ │ ├── LICENSE.md │ │ └── org.varlink.certification.varlink │ ├── test_custom_assets.sh │ └── update.sh ├── system_wide_config.rs ├── test_pretty_printer.rs ├── tester/ │ └── mod.rs └── utils/ ├── command.rs ├── mocked_pagers.rs └── mod.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cargo/audit.toml ================================================ [advisories] ignore = ["RUSTSEC-2024-0320", "RUSTSEC-2024-0421"] ================================================ FILE: .envrc ================================================ use flake ================================================ FILE: .github/.codecov.yml ================================================ comment: false ================================================ FILE: .github/FUNDING.yml ================================================ github: [sharkdp, keith-hall, Enselic] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug Report about: Report a bug. title: "" labels: bug assignees: '' --- **What steps will reproduce the bug?** 1. step 1 2. step 2 3. ... **What happens?** ... **What did you expect to happen instead?** ... **How did you install `bat`?** --- **bat version and environment** ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: true ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature Request about: Suggest an idea for this project. title: '' labels: feature-request assignees: '' --- ================================================ FILE: .github/ISSUE_TEMPLATE/question.md ================================================ --- name: Question about: Ask a question about 'bat'. title: '' labels: question assignees: '' --- ================================================ FILE: .github/ISSUE_TEMPLATE/syntax_request.md ================================================ --- name: Syntax Request about: Request adding a new syntax to bat. title: "" labels: syntax-request assignees: '' --- **Syntax:** [Name or description of the syntax/language here] **Guideline Criteria:** [packagecontrol.io link here] ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: cargo directory: "/" schedule: interval: monthly time: "04:00" timezone: Europe/Berlin ignore: - dependency-name: git2 versions: - 0.13.17 - package-ecosystem: gitsubmodule directory: "/" schedule: interval: monthly time: "04:00" timezone: Europe/Berlin - package-ecosystem: "github-actions" directory: "/" schedule: interval: monthly time: "04:00" timezone: Europe/Berlin ================================================ FILE: .github/workflows/CICD.yml ================================================ name: CICD env: CICD_INTERMEDIATES_DIR: "_cicd-intermediates" MSRV_FEATURES: --no-default-features --features minimal-application,bugreport,build-assets on: workflow_dispatch: pull_request: push: branches: - master tags: - '*' jobs: all-jobs: if: always() # Otherwise this job is skipped if the matrix job fails name: all-jobs runs-on: ubuntu-latest needs: - crate_metadata - lint - min_version - license_checks - test_with_new_syntaxes_and_themes - test_with_system_config - documentation - cargo-audit - build steps: - run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' crate_metadata: name: Extract crate metadata runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Extract crate information id: crate_metadata run: | cargo metadata --no-deps --format-version 1 | jq -r '"name=" + .packages[0].name' | tee -a $GITHUB_OUTPUT cargo metadata --no-deps --format-version 1 | jq -r '"version=" + .packages[0].version' | tee -a $GITHUB_OUTPUT cargo metadata --no-deps --format-version 1 | jq -r '"maintainer=" + .packages[0].authors[0]' | tee -a $GITHUB_OUTPUT cargo metadata --no-deps --format-version 1 | jq -r '"homepage=" + .packages[0].homepage' | tee -a $GITHUB_OUTPUT cargo metadata --no-deps --format-version 1 | jq -r '"msrv=" + .packages[0].rust_version' | tee -a $GITHUB_OUTPUT outputs: name: ${{ steps.crate_metadata.outputs.name }} version: ${{ steps.crate_metadata.outputs.version }} maintainer: ${{ steps.crate_metadata.outputs.maintainer }} homepage: ${{ steps.crate_metadata.outputs.homepage }} msrv: ${{ steps.crate_metadata.outputs.msrv }} lint: name: Ensure code quality runs-on: ubuntu-latest steps: - uses: dtolnay/rust-toolchain@stable with: components: rustfmt,clippy - uses: actions/checkout@v6 - run: cargo fmt -- --check - run: cargo clippy --locked --all-targets --all-features -- -D warnings min_version: name: Minimum supported rust version runs-on: ubuntu-latest needs: crate_metadata steps: - name: Checkout source code uses: actions/checkout@v6 - name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }}) uses: dtolnay/rust-toolchain@master with: toolchain: ${{ needs.crate_metadata.outputs.msrv }} - name: Run tests run: cargo test --locked ${{ env.MSRV_FEATURES }} license_checks: name: License checks runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: submodules: true # we especially want to perform license checks on submodules - run: tests/scripts/license-checks.sh test_with_new_syntaxes_and_themes: name: Run tests with updated syntaxes and themes runs-on: ubuntu-latest steps: - name: Git checkout uses: actions/checkout@v6 with: submodules: true # we need all syntax and theme submodules - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Build and install bat run: cargo install --locked --path . - name: Rebuild binary assets (syntaxes and themes) run: bash assets/create.sh - name: Build and install bat with updated assets run: cargo install --locked --path . - name: Run unit tests with new syntaxes and themes run: cargo test --locked --release - name: Run ignored-by-default unit tests with new syntaxes and themes run: cargo test --locked --release --test assets -- --ignored - name: Syntax highlighting regression test run: tests/syntax-tests/regression_test.sh - name: List of languages run: bat --list-languages - name: List of themes run: bat --list-themes - name: Test custom assets run: tests/syntax-tests/test_custom_assets.sh test_with_system_config: name: Run tests with system wide configuration runs-on: ubuntu-latest steps: - name: Git checkout uses: actions/checkout@v6 - name: Prepare environment variables run: | echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Build and install bat run: cargo install --locked --path . - name: Run unit tests run: cargo test --locked --test system_wide_config -- --ignored documentation: name: Documentation runs-on: ubuntu-latest steps: - name: Git checkout uses: actions/checkout@v6 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Check documentation env: RUSTDOCFLAGS: -D warnings run: cargo doc --locked --no-deps --document-private-items --all-features - name: Show man page run: man $(find . -name bat.1) cargo-audit: name: cargo audit runs-on: ubuntu-latest steps: - run: cargo install cargo-audit --locked - uses: actions/checkout@v6 - run: cargo audit build: name: ${{ matrix.job.target }} (${{ matrix.job.os }}) runs-on: ${{ matrix.job.os }} needs: crate_metadata strategy: fail-fast: false matrix: job: - { target: aarch64-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: arm64, use-cross: true } - { target: aarch64-unknown-linux-gnu , os: ubuntu-latest , dpkg_arch: arm64, use-cross: true } - { target: arm-unknown-linux-gnueabihf , os: ubuntu-latest , dpkg_arch: armhf, use-cross: true } - { target: arm-unknown-linux-musleabihf, os: ubuntu-latest , dpkg_arch: musl-linux-armhf, use-cross: true } - { target: i686-pc-windows-msvc , os: windows-2025 , } - { target: i686-unknown-linux-gnu , os: ubuntu-latest , dpkg_arch: i686, use-cross: true } - { target: i686-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: musl-linux-i686, use-cross: true } - { target: x86_64-apple-darwin , os: macos-15-intel, } - { target: aarch64-apple-darwin , os: macos-latest , } - { target: x86_64-pc-windows-msvc , os: windows-2025 , } - { target: aarch64-pc-windows-msvc , os: windows-11-arm, } - { target: x86_64-unknown-linux-gnu , os: ubuntu-latest , dpkg_arch: amd64, use-cross: true } - { target: x86_64-unknown-linux-musl , os: ubuntu-latest , dpkg_arch: musl-linux-amd64, use-cross: true } env: BUILD_CMD: cargo steps: - name: Checkout source code uses: actions/checkout@v6 - name: Install prerequisites shell: bash run: | case ${{ matrix.job.target }} in arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; esac - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.job.target }} - name: Install cross if: matrix.job.use-cross uses: taiki-e/install-action@v2 with: tool: cross - name: Overwrite build command env variable if: matrix.job.use-cross shell: bash run: echo "BUILD_CMD=cross" >> $GITHUB_ENV - name: Show version information (Rust, cargo, GCC) shell: bash run: | gcc --version || true rustup -V rustup toolchain list rustup default cargo -V rustc -V - name: Build shell: bash run: $BUILD_CMD build --locked --release --target=${{ matrix.job.target }} - name: Set binary name & path id: bin shell: bash run: | # Figure out suffix of binary EXE_suffix="" case ${{ matrix.job.target }} in *-pc-windows-*) EXE_suffix=".exe" ;; esac; # Setup paths BIN_NAME="${{ needs.crate_metadata.outputs.name }}${EXE_suffix}" BIN_PATH="target/${{ matrix.job.target }}/release/${BIN_NAME}" # Let subsequent steps know where to find the binary echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT - name: Set testing options id: test-options shell: bash run: | # test only library unit tests and binary for arm-type targets unset CARGO_TEST_OPTIONS unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${{ needs.crate_metadata.outputs.name }}" ;; esac; echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT - name: Run tests shell: bash run: | if [[ ${{ matrix.job.os }} = windows-* ]] then powershell.exe -command "$BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}" else $BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}} fi - name: Run bat shell: bash run: $BUILD_CMD run --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs - name: Show diagnostics (bat --diagnostic) shell: bash run: $BUILD_CMD run --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs --diagnostic - name: "Feature check: regex-onig" shell: bash run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig - name: "Feature check: regex-onig,git" shell: bash run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git - name: "Feature check: regex-onig,paging" shell: bash run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,paging - name: "Feature check: regex-onig,git,paging" shell: bash run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git,paging - name: "Feature check: minimal-application" shell: bash run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --no-default-features --features minimal-application - name: Create tarball id: package shell: bash run: | PKG_suffix=".tar.gz" ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac; PKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-v${{ needs.crate_metadata.outputs.version }}-${{ matrix.job.target }} PKG_NAME=${PKG_BASENAME}${PKG_suffix} echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package" ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/" mkdir -p "${ARCHIVE_DIR}" mkdir -p "${ARCHIVE_DIR}/autocomplete" # Binary cp "${{ steps.bin.outputs.BIN_PATH }}" "$ARCHIVE_DIR" # README, LICENSE and CHANGELOG files cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$ARCHIVE_DIR" # Man page cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/manual/bat.1 "$ARCHIVE_DIR" # Autocompletion files cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.bash "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.bash" cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.fish "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.fish" cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/_bat.ps1 "$ARCHIVE_DIR/autocomplete/_${{ needs.crate_metadata.outputs.name }}.ps1" cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.zsh "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.zsh" # base compressed package pushd "${PKG_STAGING}/" >/dev/null case ${{ matrix.job.target }} in *-pc-windows-*) 7z -y a "${PKG_NAME}" "${PKG_BASENAME}"/* | tail -2 ;; *) tar czf "${PKG_NAME}" "${PKG_BASENAME}"/* ;; esac; popd >/dev/null # Let subsequent steps know where to find the compressed package echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT - name: Create Debian package id: debian-package shell: bash if: startsWith(matrix.job.os, 'ubuntu') run: | COPYRIGHT_YEARS="2018 - "$(date "+%Y") DPKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/debian-package" DPKG_DIR="${DPKG_STAGING}/dpkg" mkdir -p "${DPKG_DIR}" DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }} DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}-musl case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl ; DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }} ;; esac; DPKG_VERSION=${{ needs.crate_metadata.outputs.version }} DPKG_ARCH="${{ matrix.job.dpkg_arch }}" DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb" echo "DPKG_NAME=${DPKG_NAME}" >> $GITHUB_OUTPUT # Binary install -Dm755 "${{ steps.bin.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.bin.outputs.BIN_NAME }}" # Man page install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/manual/bat.1 "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1" gzip -n --best "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1" # Autocompletion files install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.bash "${DPKG_DIR}/usr/share/bash-completion/completions/${{ needs.crate_metadata.outputs.name }}" install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.fish "${DPKG_DIR}/usr/share/fish/vendor_completions.d/${{ needs.crate_metadata.outputs.name }}.fish" install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.zsh "${DPKG_DIR}/usr/share/zsh/vendor-completions/_${{ needs.crate_metadata.outputs.name }}" # README and LICENSE install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md" install -Dm644 "LICENSE-MIT" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-MIT" install -Dm644 "LICENSE-APACHE" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-APACHE" install -Dm644 "CHANGELOG.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/changelog" gzip -n --best "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/changelog" cat > "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright" < "${DPKG_DIR}/DEBIAN/control" <> $GITHUB_OUTPUT # build dpkg fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}" - name: "Artifact upload: tarball" uses: actions/upload-artifact@master with: name: ${{ steps.package.outputs.PKG_NAME }} path: ${{ steps.package.outputs.PKG_PATH }} - name: "Artifact upload: Debian package" uses: actions/upload-artifact@master if: steps.debian-package.outputs.DPKG_NAME with: name: ${{ steps.debian-package.outputs.DPKG_NAME }} path: ${{ steps.debian-package.outputs.DPKG_PATH }} - name: Check for release id: is-release shell: bash run: | unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT - name: Publish archives and packages uses: softprops/action-gh-release@v2 if: steps.is-release.outputs.IS_RELEASE with: files: | ${{ steps.package.outputs.PKG_PATH }} ${{ steps.debian-package.outputs.DPKG_PATH }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} winget: name: Publish to Winget runs-on: ubuntu-latest needs: build if: startsWith(github.ref, 'refs/tags/v') steps: - uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f with: identifier: sharkdp.bat installers-regex: '-pc-windows-msvc\.zip$' token: ${{ secrets.WINGET_TOKEN }} ================================================ FILE: .github/workflows/require-changelog-for-PRs.yml ================================================ name: Changelog on: pull_request: jobs: check-changelog: name: Check for changelog entry runs-on: ubuntu-latest # dependabot PRs are automerged if CI passes; we shouldn't block these if: github.actor != 'dependabot[bot]' env: PR_NUMBER: ${{ github.event.number }} PR_BASE: ${{ github.base_ref }} steps: - uses: actions/checkout@v6 - name: Fetch PR base run: git fetch --no-tags --prune --depth=1 origin # cannot use `github.actor`: the triggering commit may be authored by a maintainer - name: Get PR submitter id: get-submitter run: curl -sSfL https://api.github.com/repos/sharkdp/bat/pulls/${PR_NUMBER} | jq -r '"submitter=" + .user.login' | tee -a $GITHUB_OUTPUT - name: Search for added line in changelog env: PR_SUBMITTER: ${{ steps.get-submitter.outputs.submitter }} run: | ADDED=$(git diff -U0 "origin/${PR_BASE}" HEAD -- CHANGELOG.md | grep -P '^\+[^\+].+$') echo "Added lines in CHANGELOG.md:" echo "$ADDED" echo "Grepping for PR info (see CONTRIBUTING.md):" grep "#${PR_NUMBER}\\b.*${PR_SUBMITTER}\\b" <<< "$ADDED" ================================================ FILE: .gitignore ================================================ .direnv/ /target/ **/*.rs.bk # Editors .idea/ .vscode/ # Generated files /assets/completions/_bat.ps1 /assets/completions/bat.bash /assets/completions/bat.fish /assets/completions/bat.zsh /assets/manual/bat.1 /assets/metadata.yaml ================================================ FILE: .gitmodules ================================================ [submodule "assets/syntaxes/Elixir"] path = assets/syntaxes/02_Extra/Elixir url = https://github.com/princemaple/elixir-sublime-syntax/ [submodule "assets/syntaxes/Packages"] path = assets/syntaxes/01_Packages url = https://github.com/sublimehq/Packages/ [submodule "assets/syntaxes/TOML"] path = assets/syntaxes/02_Extra/TOML url = https://github.com/jasonwilliams/sublime_toml_highlighting [submodule "assets/syntaxes/Julia"] path = assets/syntaxes/02_Extra/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/02_Extra/Docker url = https://github.com/asbjornenge/Docker.tmbundle [submodule "assets/syntaxes/VimL"] path = assets/syntaxes/02_Extra/VimL url = https://github.com/SalGnt/Sublime-VimL [submodule "assets/syntaxes/INI"] path = assets/syntaxes/02_Extra/INI url = https://github.com/clintberry/sublime-text-2-ini [submodule "assets/syntaxes/CMake"] path = assets/syntaxes/02_Extra/CMake url = https://github.com/zyxar/Sublime-CMakeLists [submodule "assets/syntaxes/LESS"] path = assets/syntaxes/02_Extra/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/02_Extra/AWK url = https://github.com/JohnNilsson/awk-sublime [submodule "assets/syntaxes/Nix"] path = assets/syntaxes/02_Extra/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/02_Extra/Kotlin url = https://github.com/vkostyukov/kotlin-sublime-package [submodule "assets/syntaxes/Elm"] path = assets/syntaxes/02_Extra/Elm url = https://github.com/elm-community/SublimeElmLanguageSupport [submodule "assets/syntaxes/TypeScript"] path = assets/syntaxes/02_Extra/TypeScript url = https://github.com/Microsoft/TypeScript-Sublime-Plugin [submodule "assets/syntaxes/Puppet"] path = assets/syntaxes/02_Extra/Puppet url = https://github.com/russCloak/SublimePuppet [submodule "assets/themes/onehalf"] path = assets/themes/onehalf url = https://github.com/sonph/onehalf [submodule "assets/syntaxes/JavaScript (Babel)"] path = assets/syntaxes/02_Extra/JavaScript_(Babel) url = https://github.com/babel/babel-sublime [submodule "assets/syntaxes/FSharp"] path = assets/syntaxes/02_Extra/FSharp url = https://github.com/hoest/sublimetext-fsharp [submodule "assets/syntaxes/PureScript"] path = assets/syntaxes/02_Extra/PureScript url = https://github.com/tellnobody1/sublime-purescript-syntax [submodule "assets/syntaxes/Swift"] path = assets/syntaxes/02_Extra/Swift url = https://github.com/quiqueg/Swift-Sublime-Package [submodule "assets/syntaxes/Crystal"] path = assets/syntaxes/02_Extra/Crystal url = https://github.com/crystal-lang-tools/sublime-crystal.git [submodule "assets/syntaxes/PowerShell"] path = assets/syntaxes/02_Extra/PowerShell url = https://github.com/PowerShell/EditorSyntax [submodule "assets/syntaxes/Robot"] path = assets/syntaxes/02_Extra/Robot url = https://github.com/andriyko/sublime-robot-framework-assistant.git [submodule "assets/themes/sublime-snazzy"] path = assets/themes/sublime-snazzy url = https://github.com/greggb/sublime-snazzy [submodule "assets/syntaxes/Assembly (ARM)"] path = assets/syntaxes/02_Extra/Assembly_(ARM) url = https://github.com/tvi/Sublime-ARM-Assembly [submodule "assets/syntaxes/protobuf-syntax-highlighting"] path = assets/syntaxes/02_Extra/Protobuf url = https://github.com/VcamX/protobuf-syntax-highlighting.git branch = master [submodule "assets/syntaxes/Terraform"] path = assets/syntaxes/02_Extra/Terraform url = https://github.com/alexlouden/Terraform.tmLanguage.git [submodule "assets/syntaxes/Jsonnet"] path = assets/syntaxes/02_Extra/Jsonnet url = https://github.com/gburiola/sublime-jsonnet-syntax.git [submodule "assets/syntaxes/varlink"] path = assets/syntaxes/02_Extra/varlink url = https://github.com/varlink/syntax-highlight-varlink.git [submodule "assets/syntaxes/sublime-fish"] path = assets/syntaxes/02_Extra/Fish url = https://github.com/Phidica/sublime-fish.git [submodule "assets/syntaxes/Org mode"] path = assets/syntaxes/02_Extra/Org_mode url = https://github.com/jezcope/Org.tmbundle.git [submodule "assets/syntaxes/DotENV"] path = assets/syntaxes/02_Extra/DotENV url = https://github.com/zaynali53/DotENV [submodule "assets/syntaxes/ssh-config"] path = assets/syntaxes/02_Extra/ssh-config url = https://github.com/robballou/sublimetext-sshconfig.git [submodule "assets/syntaxes/GraphQL"] path = assets/syntaxes/02_Extra/GraphQL url = https://github.com/dncrews/GraphQL-SublimeText3.git [submodule "assets/syntaxes/Verilog"] path = assets/syntaxes/02_Extra/Verilog url = https://github.com/pro711/sublime-verilog [submodule "assets/syntaxes/SCSS_Sass"] path = assets/syntaxes/02_Extra/SCSS_Sass url = https://github.com/braver/SublimeSass [submodule "assets/syntaxes/Strace"] path = assets/syntaxes/02_Extra/Strace url = https://github.com/djuretic/SublimeStrace [submodule "assets/syntaxes/Jinja2"] path = assets/syntaxes/02_Extra/Jinja2 url = https://github.com/ltrzesniewski/sublime-jinja2.git [submodule "assets/syntaxes/SLS"] path = assets/syntaxes/02_Extra/SLS url = https://github.com/saltstack/sublime-text branch = master [submodule "assets/themes/dracula-sublime"] path = assets/themes/dracula-sublime url = https://github.com/dracula/sublime.git [submodule "assets/syntaxes/HTML (Twig)"] path = assets/syntaxes/02_Extra/HTML_(Twig) url = https://github.com/Anomareh/PHP-Twig.tmbundle.git [submodule "assets/themes/Nord-sublime"] path = assets/themes/Nord-sublime url = https://github.com/crabique/Nord-plist.git [submodule "assets/syntaxes/Vue"] path = assets/syntaxes/02_Extra/Vue url = https://github.com/vuejs/vue-syntax-highlight.git branch = new [submodule "assets/syntaxes/CoffeeScript"] path = assets/syntaxes/02_Extra/CoffeeScript url = https://github.com/sustained/CoffeeScript-Sublime-Plugin [submodule "assets/syntaxes/02_Extra/Stylus"] path = assets/syntaxes/02_Extra/Stylus url = https://github.com/billymoon/Stylus [submodule "assets/themes/Solarized"] path = assets/themes/Solarized url = https://github.com/braver/Solarized [submodule "assets/syntaxes/02_Extra/Fortran"] path = assets/syntaxes/02_Extra/Fortran url = https://github.com/315234/SublimeFortran [submodule "assets/syntaxes/02_Extra/Email"] path = assets/syntaxes/02_Extra/Email url = https://github.com/mariozaizar/email.sublime-syntax.git [submodule "assets/syntaxes/02_Extra/QML"] path = assets/syntaxes/02_Extra/QML url = https://github.com/skozlovf/Sublime-QML [submodule "assets/syntaxes/02_Extra/AsciiDoc"] path = assets/syntaxes/02_Extra/AsciiDoc url = https://github.com/asciidoctor/sublimetext-asciidoc.git [submodule "assets/syntaxes/02_Extra/GLSL"] path = assets/syntaxes/02_Extra/GLSL url = https://github.com/euler0/sublime-glsl [submodule "assets/syntaxes/02_Extra/Nginx"] path = assets/syntaxes/02_Extra/Nginx url = https://github.com/SublimeText/nginx [submodule "assets/syntaxes/02_Extra/Apache"] path = assets/syntaxes/02_Extra/Apache url = https://github.com/colinta/ApacheConf.tmLanguage [submodule "assets/syntaxes/02_Extra/Ninja"] path = assets/syntaxes/02_Extra/Ninja url = https://github.com/pope/SublimeNinja.git [submodule "assets/syntaxes/02_Extra/Svelte"] path = assets/syntaxes/02_Extra/Svelte url = https://github.com/corneliusio/svelte-sublime [submodule "assets/themes/Coldark"] path = assets/themes/Coldark url = https://github.com/ArmandPhilippot/coldark-bat.git [submodule "assets/themes/gruvbox"] path = assets/themes/gruvbox url = https://github.com/subnut/gruvbox-tmTheme.git branch = bat-source [submodule "assets/syntaxes/02_Extra/Lean"] path = assets/syntaxes/02_Extra/Lean url = https://github.com/leanprover/vscode-lean4.git [submodule "assets/syntaxes/02_Extra/Zig"] path = assets/syntaxes/02_Extra/Zig url = https://codeberg.org/ziglang/sublime-zig-language.git [submodule "assets/syntaxes/02_Extra/gnuplot"] path = assets/syntaxes/02_Extra/gnuplot url = https://github.com/hesstobi/sublime_gnuplot [submodule "assets/syntaxes/02_Extra/SystemVerilog"] path = assets/syntaxes/02_Extra/SystemVerilog url = https://github.com/TheClams/SystemVerilog.git [submodule "assets/syntaxes/02_Extra/SublimeEthereum"] path = assets/syntaxes/02_Extra/SublimeEthereum url = https://github.com/davidhq/SublimeEthereum.git [submodule "assets/syntaxes/02_Extra/Groff"] path = assets/syntaxes/02_Extra/Groff url = https://github.com/carsonoid/sublime_man_page_support [submodule "assets/syntaxes/02_Extra/http-request-response"] path = assets/syntaxes/02_Extra/http-request-response url = https://github.com/keith-hall/http-request-response-syntax.git [submodule "assets/syntaxes/02_Extra/LLVM"] path = assets/syntaxes/02_Extra/LLVM url = https://github.com/ioncodes/LLVM.tmBundle [submodule "assets/syntaxes/02_Extra/Slim"] path = assets/syntaxes/02_Extra/Slim url = https://github.com/slim-template/ruby-slim.tmbundle.git [submodule "assets/syntaxes/02_Extra/Racket"] path = assets/syntaxes/02_Extra/Racket url = https://github.com/follesoe/sublime-racket.git [submodule "assets/syntaxes/02_Extra/MediaWiki"] path = assets/syntaxes/02_Extra/MediaWiki url = https://github.com/tosher/Mediawiker.git [submodule "assets/syntaxes/02_Extra/Dart"] path = assets/syntaxes/02_Extra/Dart url = https://github.com/elMuso/Dartlight.git [submodule "assets/syntaxes/02_Extra/SublimeJQ"] path = assets/syntaxes/02_Extra/SublimeJQ url = https://github.com/zogwarg/SublimeJQ.git [submodule "assets/syntaxes/02_Extra/cmd-help"] path = assets/syntaxes/02_Extra/cmd-help url = https://github.com/victor-gp/cmd-help-sublime-syntax.git branch = main shallow = true [submodule "assets/syntaxes/02_Extra/TodoTxt"] path = assets/syntaxes/02_Extra/TodoTxt url = https://github.com/dertuxmalwieder/SublimeTodoTxt [submodule "assets/syntaxes/02_Extra/Ada"] path = assets/syntaxes/02_Extra/Ada url = https://github.com/AldanTanneo/ada-sublime-syntax [submodule "assets/syntaxes/02_Extra/Crontab"] path = assets/syntaxes/02_Extra/Crontab url = https://github.com/michaelblyons/SublimeSyntax-Crontab [submodule "assets/syntaxes/02_Extra/NSIS"] path = assets/syntaxes/02_Extra/NSIS url = https://github.com/SublimeText/NSIS [submodule "assets/syntaxes/02_Extra/vscode-wgsl"] path = assets/syntaxes/02_Extra/vscode-wgsl url = https://github.com/PolyMeilex/vscode-wgsl.git [submodule "assets/syntaxes/02_Extra/CFML"] path = assets/syntaxes/02_Extra/CFML url = https://github.com/jcberquist/sublimetext-cfml.git [submodule "assets/syntaxes/02_Extra/Idris2"] path = assets/syntaxes/02_Extra/Idris2 url = https://github.com/buzden/sublime-syntax-idris2 [submodule "assets/syntaxes/02_Extra/GDScript-sublime"] path = assets/syntaxes/02_Extra/GDScript-sublime url = https://github.com/beefsack/GDScript-sublime [submodule "assets/syntaxes/02_Extra/sublime-odin"] path = assets/syntaxes/02_Extra/sublime-odin url = https://github.com/odin-lang/sublime-odin [submodule "assets/syntaxes/02_Extra/typst-syntax-highlight"] path = assets/syntaxes/02_Extra/typst-syntax-highlight url = https://github.com/hyrious/typst-syntax-highlight [submodule "assets/themes/Catppuccin"] path = assets/themes/Catppuccin url = https://github.com/SchweGELBin/catppuccin-bat-sub.git [submodule "assets/syntaxes/02_Extra/SmartVHDL"] path = assets/syntaxes/02_Extra/SmartVHDL url = https://github.com/TheClams/SmartVHDL [submodule "assets/syntaxes/02_Extra/hosts"] path = assets/syntaxes/02_Extra/hosts url = https://github.com/tijn/hosts.tmLanguage [submodule "assets/syntaxes/02_Extra/Gomod"] path = assets/syntaxes/02_Extra/Gomod url = https://github.com/mitranim/sublime-gomod [submodule "assets/syntaxes/02_Extra/COBOL"] path = assets/syntaxes/02_Extra/COBOL url = https://github.com/adukhan99/sublime_cobol.git ================================================ FILE: CHANGELOG.md ================================================ # unreleased - Fixed bug caused by using `--plain` and `--terminal-width=N` flags simultaneously, see #3529 (@H4k1l) - Fixed syntax tests path, see #3610 (@foxfromworld) ## Features - Added support for `hidden_file_extensions` from `.sublime-syntax` files, see #3613 (@Matei02355) - Add word wrapping mode via `--wrap=word`, see #3597 (@veeceey) - Implement `--unbuffered` mode for streaming input, allowing partial lines to display immediately (e.g. `tail -f | bat -u`). Closes #3555, see #3583 (@mainnebula) - Added an initial `flake.nix` for a ready made development environment; see #3578 (@vorburger) - Add `--quiet-empty` (`-E`) flag to suppress output when input is empty. Closes #1936, see #3563 (@NORMAL-EX) - Improve native man pages and command help syntax highlighting by stripping overstriking, see #3517 (@akirk) - Add `--fallback-syntax`/`--fallback-language` to apply syntax highlighting only when auto-detection fails, see #1341 (@Xavrir) ## Bugfixes - Fix `BAT_CONFIG_DIR` pointing at system config directory causing duplicate flag errors. Closes #3589, see #3620 (@Xavrir) - Fix syntax highlighting for symlinked files when the symlink name has no extension but the target does. Closes #1001, see #3621 (@Xavrir) - Report error when pager is missing instead of silently falling back, see #3588 (@IMaloney) - Fix `--wrap=never` and `-S` flags being ignored when piping to pager, see #3592 (@IMaloney) - Fix crash with BusyBox `less` on Windows, see #3527 (@Anchal-T) - Fix `bat cache --help` failing with 'unexpected argument' error, see #3580 and #3560 (@NORMAL-EX) - `--help` now correctly honors `--pager=builtin`. See #3516 (@keith-hall) - `--help` now correctly honors custom themes. See #3524 (@keith-hall) - Fixed test compatibility with future Cargo build directory changes, see #3550 (@nmacl) ## Other - Bump MSRV to 1.88, update `time` crate to 0.3.47 to fix RUSTSEC-2026-0009, see #3581 (@NORMAL-EX) ## Syntaxes - Change the URL of Zig submodule from GitHub to Codeberg, see #3519 (@sorairolake) - Don't color strings inside CSV files, to make it easier to tell which column they belong to, see #3521 (@keith-hall) - Add syntax highlighting support for COBOL, see #3584 (@adukhan99) - Fixed manpage syntax so that ANSI escape codes don't get incorrectly highlighted and thus broken, see #3586 (@BlueElectivire) - Map several Google Cloud CLI config files to their appropriate syntax #3635 (@victor-gp) - Map all ignore dotfiles to Git Ignore syntax #3636 (@victor-gp) ## Themes - Remove the Visual Studio Dark+ theme, see #3552 (@CosmicHorrorDev) ## `bat` as a library # v0.26.1 ## Features - Add paging to '-h' and '--help' see PR #3478 (@MuntasirSZN) ## Bugfixes - Fix hang when using `--list-themes` with an explicit pager, see #3457 (@abhinavcool42) - Fix negative values of N not being parsed in line ranges without `=` flag value separator, see #3442 (@lmmx) - Fix broken Docker syntax preventing use of custom assets, see #3476 (@keith-hall) - Fix decorations being applied unexpectedly when piping. Now only line numbers explicitly required on the command line should be applied in auto decorations mode for `cat` compatibility. See #3496 (@keith-hall) - Fix diagnostics attempting to find the version of an executable named builtin when builtin pager is used. See #3498 (@keith-hall) - `--help` now correctly reads the config file for theme information etc. See #3507 (@keith-hall) ## Other - Improve README documentation on pager options passed to less, see #3443 (@injust) - Make PowerShell completions compatible with PowerShell v5.1, see #3495 (@keith-hall) - Use more robust approach to escaping in Bash completions, see #3448 (@akinomyoga) ## Syntaxes - Update quadlet syntax mapping to include *.{build,pod} files #3484 (@cyqsimon) - Fix inconsistencies in Ada syntax, see #3481 (@AldanTanneo) - Add syntax mapping for podman's `artifact` quadlet files, see #3497 (@xduugu) - Highlight Korn Shell scripts (i.e. with a shebang of ...`ksh`) using Bash syntax, see #3509 (@keith-hall) ## Themes ## `bat` as a library # v0.26.0 ## Features - Add build for windows/ARM64 platform. #3190 (@alcroito) - Add paging to `--list-themes`, see PR #3239 (@einfachIrgendwer0815) - Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow) - Support context in line ranges, e.g. `bat -r 30::5` / `bat -r 30:40:5`, see #3345 (@cavanaug) - Add built-in 'minus' pager, e.g. `bat --pager=builtin` see PR #3402 (@academician) ## Bugfixes - Fix UTF-8 BOM not being stripped for syntax detection, see #3314 (@krikera) - Fix `BAT_THEME_DARK` and `BAT_THEME_LIGHT` being ignored, see issue #3171 and PR #3168 (@bash) - Prevent `--list-themes` from outputting default theme info to stdout when it is piped, see #3189 (@einfachIrgendwer0815) - Rename some submodules to fix Dependabot submodule updates, see issue #3198 and PR #3201 (@victor-gp) - Make highlight tests fail when new syntaxes don't have fixtures PR #3255 (@dan-hipschman) - Fix crash for multibyte characters in file path, see issue #3230 and PR #3245 (@HSM95) - Add missing mappings for various bash/zsh files, see PR #3262 (@AdamGaskins) - Send all bat errors to stderr by default, see #3336 (@JerryImMouse) - Make --map-syntax target case insensitive to match --language, see #3206 (@keith-hall) - Correctly determine the end of the line in UTF16LE/BE input #3369 (@keith-hall) - `--style=changes` no longer prints a two-space indent when the file is unmodified, see issue #2710 and PR #3406 (@jyn514) - Add missing shell completions, see #3411 (@keith-hall) - Execute help/version/diagnostic commands even with invalid config/arguments present, see #3414 (@keith-hall) - Fixed line numbers (`-n`) and style components not printing when piping output, see issue #2935 and PR #3438 (@lmmx) ## Other - Update base16 README links to community driven base16 work #2871 (@JamyGolden) - Work around build failures when building `bat` from vendored sources #3179 (@dtolnay) - CICD: Stop building for x86_64-pc-windows-gnu which fails #3261 (Enselic) - CICD: replace windows-2019 runners with windows-2025 #3339 (@cyqsimon) - Build script: replace string-based codegen with quote-based codegen #3340 (@cyqsimon) - Improve code coverage of `--list-languages` parameter #2942 (@sblondon) - Only start offload worker thread when there's more than 1 core #2956 (@cyqsimon) - Update terminal-colorsaurus (the library used for dark/light detection) to 1.0, see #3347 (@bash) - Update console dependency to 0.16, see #3351 (@musicinmybrain) - Fixed some typos #3244 (@ssbarnea) - Update onig_sys dependency to 69.9.1 to fix a gcc build failure #3400 (@CosmicHorrorDev) - Add a cargo feature (`vendored-libgit2`) to build with vendored libgit2 version without depending on the system's one #3426 (@0x61nas) - Update syntect dependency to v5.3.0 to fix a few minor bugs, see #3410 (@keith-hall) ## Syntaxes - Add syntax mapping for `paru` configuration files #3182 (@cyqsimon) - Add support for [Idris 2 programming language](https://www.idris-lang.org/) #3150 (@buzden) - Add syntax mapping for `nix`'s '`flake.lock` lockfiles #3196 (@odilf) - Improvements to CSV/TSV highlighting, with autodetection of delimiter and support for TSV files, see #3186 (@keith- - Improve (Sys)log error highlighting, see #3205 (@keith-hall) - Map `ndjson` extension to JSON syntax, see #3209 (@keith-hall) - Map files with `csproj`, `vbproj`, `props` and `targets` extensions to XML syntax, see #3213 (@keith-hall) - Add debsources syntax to highlight `/etc/apt/sources.list` files, see #3215 (@keith-hall) - Add syntax definition and test file for GDScript highlighting, see #3236 (@chetanjangir0) - Add syntax test file for Odin highlighting, see #3241 (@chetanjangir0) - Update quadlet syntax mapping rules to cover quadlets in subdirectories #3299 (@cyqsimon) - Add syntax Typst #3300 (@cskeeters) - Map `.mill` files to Scala syntax for Mill build tool configuration files #3311 (@krikera) - Add syntax highlighting for VHDL, see #3337 (@JerryImMouse) - Add syntax mapping for certbot certificate configuration #3338 (@cyqsimon) - Update Lean syntax from Lean 3 to Lean 4 #3322 (@YDX-2147483647) - Map `.flatpakref` and `.flatpakrepo` files to INI syntax #3353 (@Ferenc-) - Update hosts syntax #3368 (@keith-hall) - Map `.kshrc` files to Bash syntax #3364 (@ritoban23) - Map `/var/log/dmesg` files to Syslog syntax #3412 (@keith-hall) - Add syntax definition and test file for Go modules(`go.mod` and `go.sum`) highlighting, see #3424 (@DarkMatter-999) - Syntax highlighting for typescript code blocks within Markdown files, see #3435 (@MuntasirSZN) ## Themes - Add Catppuccin, see #3317 (@SchweGELBin) - Updated Catppuccin, see #3333 (@SchweGELBin) - Updated gruvbox, see #3372 (@Nicholas42) - Updated GitHub theme, see #3382 (@CosmicHorrorDev) - Updated ANSI theme to highlight JSON object keys differently from values, see #3413 (@keith-hall) # v0.25.0 ## Features - Set terminal title to file names when Paging is not Paging::Never #2807 (@Oliver-Looney) - `bat --squeeze-blank`/`bat -s` will now squeeze consecutive empty lines, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815) - `bat --squeeze-limit` to set the maximum number of empty consecutive when using `--squeeze-blank`, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815) - `PrettyPrinter::squeeze_empty_lines` to support line squeezing for bat as a library, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815) - Syntax highlighting for JavaScript files that start with `#!/usr/bin/env bun` #2913 (@sharunkumar) - `bat --strip-ansi={never,always,auto}` to remove ANSI escape sequences from bat's input, see #2999 (@eth-p) - Add or remove individual style components without replacing all styles #2929 (@eth-p) - Automatically choose theme based on the terminal's color scheme, see #2896 (@bash) - Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815) - Make shell completions available via `--completion `, see issue #2057 and PR #3126 (@einfachIrgendwer0815) - Syntax highlighting for puppet code blocks within Markdown files, see #3152 (@liliwilson) ## Bugfixes - Fix long file name wrapping in header, see #2835 (@FilipRazek) - Fix `NO_COLOR` support, see #2767 (@acuteenvy) - Fix handling of inputs with OSC ANSI escape sequences, see #2541 and #2544 (@eth-p) - Fix handling of inputs with combined ANSI color and attribute sequences, see #2185 and #2856 (@eth-p) - Fix panel width when line 10000 wraps, see #2854 (@eth-p) - Fix compile issue of `time` dependency caused by standard library regression #3045 (@cyqsimon) - Fix override behavior of --plain and --paging, see issue #2731 and PR #3108 (@einfachIrgendwer0815) - Fix bugs in `$LESSOPEN` support, see #2805 (@Anomalocaridid) ## Other - Upgrade to Rust 2021 edition #2748 (@cyqsimon) - Refactor and cleanup build script #2756 (@cyqsimon) - Checks changelog has been written to for PRs in CI #2766 (@cyqsimon) - Use GitHub API to get correct PR submitter #2791 (@cyqsimon) - Minor benchmark script improvements #2768 (@cyqsimon) - Update Arch Linux package URL in README files #2779 (@brunobell) - Update and improve `zsh` completion, see #2772 (@okapia) - More extensible syntax mapping mechanism #2755 (@cyqsimon) - Use proper Architecture for Debian packages built for musl, see #2811 (@Enselic) - Pull in fix for unsafe-libyaml security advisory, see #2812 (@dtolnay) - Update git-version dependency to use Syn v2, see #2816 (@dtolnay) - Update git2 dependency to v0.18.2, see #2852 (@eth-p) - Improve performance when color output disabled, see #2397 and #2857 (@eth-p) - Relax syntax mapping rule restrictions to allow brace expansion #2865 (@cyqsimon) - Apply clippy fixes #2864 (@cyqsimon) - Faster startup by offloading glob matcher building to a worker thread #2868 (@cyqsimon) - Display which theme is the default one in basic output (no colors), see #2937 (@sblondon) - Display which theme is the default one in colored output, see #2838 (@sblondon) - Add aarch64-apple-darwin ("Apple Silicon") binary tarballs to releases, see #2967 (@someposer) - Update the Lisp syntax, see #2970 (@ccqpein) - Use bat's ANSI iterator during tab expansion, see #2998 (@eth-p) - Support 'statically linked binary' for aarch64 in 'Release' page, see #2992 (@tzq0301) - Update options in shell completions and the man page of `bat`, see #2995 (@akinomyoga) - Update nix dev-dependency to v0.29.0, see #3112 (@decathorpe) - Bump MSRV to [1.74](https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html), see #3154 (@keith-hall) - Update clircle dependency to remove winapi transitive dependency, see #3113 (@niklasmohrin) ## Syntaxes - `cmd-help`: scope subcommands followed by other terms, and other misc improvements, see #2819 (@victor-gp) - Upgrade JQ syntax, see #2820 (@dependabot[bot]) - Add syntax mapping for quadman quadlets #2866 (@cyqsimon) - Map containers .conf files to TOML syntax #2867 (@cyqsimon) - Associate `.xsh` files with `xonsh` syntax that is Python, see #2840 (@anki-code) - Associate JSON with Comments `.jsonc` with `json` syntax, see #2795 (@mxaddict) - Associate JSON-LD `.jsonld` files with `json` syntax, see #3037 (@vorburger) - Associate `.textproto` files with `ProtoBuf` syntax, see #3038 (@vorburger) - Associate GeoJSON `.geojson` files with `json` syntax, see #3084 (@mvaaltola) - Associate `.aws/{config,credentials}`, see #2795 (@mxaddict) - Associate Wireguard config `/etc/wireguard/*.conf`, see #2874 (@cyqsimon) - Add support for [CFML](https://www.adobe.com/products/coldfusion-family.html), see #3031 (@brenton-at-pieces) - Map `*.mkd` files to `Markdown` syntax, see issue #3060 and PR #3061 (@einfachIrgendwer0815) - Add syntax mapping for CITATION.cff, see #3103 (@Ugzuzg) - Add syntax mapping for kubernetes config files #3049 (@cyqsimon) - Adds support for pipe delimiter for CSV #3115 (@pratik-m) - Add syntax mapping for `/etc/pacman.conf` #2961 (@cyqsimon) - Associate `uv.lock` with `TOML` syntax, see #3132 (@fepegar) ## Themes - Patched/improved themes for better Manpage syntax highlighting support, see #2994 (@keith-hall). ## `bat` as a library - Changes to `syntax_mapping::SyntaxMapping` #2755 (@cyqsimon) - `SyntaxMapping::get_syntax_for` is now correctly public - [BREAKING] `SyntaxMapping::{empty,builtin}` are removed; use `SyntaxMapping::new` instead - [BREAKING] `SyntaxMapping::mappings` is replaced by `SyntaxMapping::{builtin,custom,all}_mappings` - Make `Controller::run_with_error_handler`'s error handler `FnMut`, see #2831 (@rhysd) - Improve compile time by 20%, see #2815 (@dtolnay) - Add `theme::theme` for choosing an appropriate theme based on the terminal's color scheme, see #2896 (@bash) - [BREAKING] Remove `HighlightingAssets::default_theme`. Use `theme::default_theme` instead. - Add `PrettyPrinter::print_with_writer` for custom output destinations, see #3070 (@kojix2) # v0.24.0 ## Features - Add environment variable `BAT_PAGING`, see #2629 (@einfachIrgendwer0815) - Add opt-in (`--features lessopen`) support for `LESSOPEN` and `LESSCLOSE`. See #1597, #1739, #2444, #2602, and #2662 (@Anomalocaridid) ## Bugfixes - Fix `more` not being found on Windows when provided via `BAT_PAGER`, see #2570, #2580, and #2651 (@mataha) - Switched default behavior of `--map-syntax` to be case insensitive #2520 - Updated version of `serde_yaml` to `0.9`. See #2627 (@Raghav-Bell) - Fix arithmetic overflow in `LineRange::from` and `LineRange::parse_range`, see #2674, #2698 (@skoriop) - Fix paging not happening when stdout is interactive but stdin is not, see #2574 (@Nigecat) - Make `-pp` override `--paging` and vice versa when passed as a later argument, see #2660 (@J-Kappes) ## Other - Output directory for generated assets (completion, manual) can be customized, see #2515 (@tranzystorek-io) - Use the `is-terminal` crate instead of `atty`, see #2530 (@nickelc) - Add Winget Releaser workflow, see #2519 (@sitiom) - Bump MSRV to 1.70, see #2651 (@mataha) ## Syntaxes - Associate `os-release` with `bash` syntax, see #2587 (@cyqsimon) - Associate `Containerfile` with `Dockerfile` syntax, see #2606 (@einfachIrgendwer0815) - Replaced quotes with double quotes so fzf integration example script works on windows and linux. see #2095 (@johnmatthiggins) - Associate `ksh` files with `bash` syntax, see #2633 (@johnmatthiggins) - Associate `sarif` files with `JSON` syntax, see #2695 (@rhysd) - Associate `ron` files with `rust` syntax, see #2427 (@YeungOnion) - Add support for [WebGPU Shader Language](https://www.w3.org/TR/WGSL/), see #2692 (@rhysd) - Add `.dpkg-new` and `.dpkg-tmp` to ignored suffixe, see #2595 (@scop) - fix: Add syntax mapping `*.jsonl` => `json`, see #2539 (@WinterCore) - Update `Julia` syntax, see #2553 (@dependabot) - add `NSIS` support, see #2577 (@idleberg) - Update `ssh-config`, see #2697 (@mrmeszaros) - Add syntax mapping `*.debdiff` => `diff`, see #2947 (@jacg) ## `bat` as a library - Add optional output_buffer arg to `Controller::run()` and `Controller::run_with_error_handler()`, see #2618 (@Piturnah) # v0.23.0 ## Features - Implemented `-S` and `--chop-long-lines` flags as aliases for `--wrap=never`. See #2309 (@johnmatthiggins) - Breaking change: Environment variables can now override config file settings (but command-line arguments still have the highest precedence), see #1152, #1281, and #2381 (@aaronkollasch) - Implemented `--nonprintable-notation=caret` to support showing non-printable characters using caret notation. See #2429 (@einfachIrgendwer0815) ## Bugfixes - Fix `bat cache --clear` not clearing the `--target` dir if specified. See #2393 (@miles170) ## Other - Various bash completion improvements, see #2310 (@scop) - Disable completion of `cache` subcommand, see #2399 (@cyqsimon) - Signifigantly improve startup performance on macOS, see #2442 (@BlackHoleFox) - Bump MSRV to 1.62, see #2496 (@Enselic) ## Syntaxes - Added support for Ada, see #1300 and #2316 (@dkm) - Added `todo.txt` syntax, see #2375 (@BANOnotIT) - Improve Manpage.sublime-syntax. See #2364 (@Freed-Wu) and #2461 (@keith-hall) - Added a new `requirements.txt` syntax, see #2361 (@Freed-Wu) - Added a new VimHelp syntax, see #2366 (@Freed-Wu) - Associate `pdm.lock` with `TOML` syntax, see #2410 - `Todo.txt`: Fix highlighting of contexts and projects at beginning of done.txt, see #2411 - `cmd-help`: overhaul scope names (colors) to improve theme support; misc syntax improvements. See #2419 (@victor-gp) - Added support for Crontab, see #2509 (@keith-hall) ## Themes ## `bat` as a library - `PrettyPrinter::header` correctly displays a header with the filename, see #2378 and #2406 (@cstyles) # v0.22.1 ## Bugfixes - Bring back pre-processing of ANSI escape characters to so that some common `bat` use cases starts working again. See #2308 (@Enselic) # v0.22.0 ## Features - Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic) - Support for separate system and user config files. See #668 (@patrickpichler) ## Bugfixes - Prevent fork nightmare with `PAGER=batcat`. See #2235 (@johnmatthiggins) - Make `--no-paging`/`-P` override `--paging=...` if passed as a later arg, see #2201 (@themkat) - `--map-syntax` and `--ignored-suffix` now works together, see #2093 (@czzrr) - Strips byte order mark from output when in non-loop-through mode. See #1922 (@dag-h) ## Other - Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp) - Improved fish completions. See #2275 (@zgracem) - Stop pre-processing ANSI escape characters. Syntax highlighting on ANSI escaped input is not supported. See #2185 and #2189 (@Enselic) ## Syntaxes - NSE (Nmap Scripting Engine) is mapped to Lua, see #2151 (@Cre3per) - Correctly color `fstab` dump and pass fields, see #2246 (@yuvalmo) - Update `Command Help` syntax, see #2255 - `Julia`: Fix syntax highlighting for function name starting with `struct`, see #2230 - Minor update to `LiveScript`, see #2291 - Associate `.mts` and `.cts` files with the `TypeScript` syntax. See #2236 (@kidonng) - Fish history is mapped to YAML. See #2237 (@kidonng) ## `bat` as a library - Make `bat::PrettyPrinter::syntaxes()` iterate over new `bat::Syntax` struct instead of `&syntect::parsing::SyntaxReference`. See #2222 (@Enselic) - Clear highlights after printing, see #1919 and #1920 (@rhysd) # v0.21.0 ## Features - Correctly render tab stops in `--show-all`, see #2038 (@Synthetica9) - Add a `--style=default` option and make it the default. It is less verbose than `full`, see #2061 (@IsaacHorvath) - Enable BusyBox `less` as pager, see #2162 (@nfisher1226) - File extensions are now matched case-insensitively. See #1854, #2181 (@Enselic) ## Bugfixes - Bump `regex` dependency from 1.5.4 to 1.5.5 to fix [CVE-2022-24713](https://blog.rust-lang.org/2022/03/08/cve-2022-24713.html), see #2145, #2139 (@Enselic) - `bat` no longer crashes when encountering files that references missing syntaxes. See #915, #2181 (@Enselic) ## Performance - Skip syntax highlighting on long lines (> 16384 chars) to help improve performance. See #2165 (@keith-hall) - Vastly improve startup time by lazy-loading syntaxes via syntect 5.0.0. This makes bat display small files ~75% faster than before. See #951, #2181 (@Enselic) ## Other - Include info about custom assets in `--diagnostics` if used. See #2107, #2144 (@Enselic) ## Syntaxes - Mapped clang-format config file (.clang-format) to YAML syntax (@TruncatedDinosour) - log syntax: improved handling of escape characters in double quoted strings. See #2123 (@keith-hall) - Associate `/var/spool/mail/*` and `/var/mail/*` with the `Email` syntax. See #2156 (@cyqsimon) - Added cmd-help syntax to scope --help messages. See #2148 (@victor-gp) - Slightly adjust Zig syntax. See #2136 (@Enselic) - Associate `.inf` files with the `INI` syntax. See #2190 (@Enselic) ## `bat` as a library - Allow configuration of `show_nonprintable` with `PrettyPrinter`, see #2142 - The binary format of syntaxes.bin has been changed due to syntaxes now being lazy-loaded via syntect 5.0.0. See #2181 (@Enselic) - Mark `bat::error::Error` enum as `#[non_exhaustive]` to allow adding new variants without future semver breakage. See #2181 (@Enselic) - Change `Error::SyntectError(syntect::LoadingError)` to `Error::SyntectError(syntect::Error)`. See #2181 (@Enselic) - Add `Error::SyntectLoadingError(syntect::LoadingError)` enum variant. See #2181 (@Enselic) # v0.20.0 ## Features - New style component `header-filesize` to show size of the displayed file in the header. See #1988 (@mdibaiee) - Use underline for line highlighting on ANSI, see #1730 (@mdibaiee) ## Bugfixes - Fix bash completion on bash 3.x and bash-completion 1.x. See #2066 (@joshpencheon) ## Syntaxes - `GraphQL`: Add support for interfaces implementing interfaces and consider ampersand an operator. See #2000 - Associate `_vimrc` and `_gvimrc` files with the `VimL` syntax. See #2002 - Associate `poetry.lock` files with the `TOML` syntax. See #2049 - Associate `.mesh`, `.task`, `.rgen`, `.rint`, `.rahit`, `.rchit`, `.rmiss`, and `.rcall` with the `GLSL` syntax. See #2050 - Added support for `JQ` syntax, see #2072 - Properly associate global git config files rooted in `$XDG_CONFIG_HOME/git/` or `$HOME/.config/git/`. See #2067 (@cyqsimon) ## `bat` as a library - Exposed `get_syntax_set` and `get_theme` methods on `HighlightingAssets`. See #2030 (@dandavison) - Added `HeaderFilename` and `HeaderFilesize` to `StyleComponent` enum, and mark it `#[non_exhaustive]`. See #1988 (@mdibaiee) # v0.19.0 ## Performance - Reduce startup time in loop-through mode (e.g. when redirecting output) by 90%. See #1747 (@Enselic) - Load themes lazily to make bat start 25% faster when disregarding syntax load time. See #1969 (@Enselic) - Python syntax highlighting no longer suffers from abysmal performance in specific scenarios. See #1688 (@keith-hall) - Fix for poor performance when ANSI escape sequences are piped to `bat`, see #1596 (@eth-p) - Fix for incorrect handling of ANSI escape sequences when using `--wrap=never`, see #1596 (@eth-p) - Load custom assets as fast as integrated assets, see #1753 (@Enselic) ## Features - Support for `x:-delta` (minus) syntax in line ranges (e.g. `20:-10`). See #1901 (@bojan88) - Support for `--ignored-suffix` argument. See #1892 (@bojan88) - `$BAT_CONFIG_DIR` is now a recognized environment variable. It has precedence over `$XDG_CONFIG_HOME`, see #1727 (@billrisher) - Support for `x:+delta` syntax in line ranges (e.g. `20:+10`). See #1810 (@bojan88) - Add new `--acknowledgements` option that gives credit to theme and syntax definition authors. See #1971 (@Enselic) - Include git hash in `bat -V` and `bat --version` output if present. See #1921 (@Enselic) ## Bugfixes - First line not shown in diff context. See #1891 (@divagant-martian) - Do not ignore syntaxes that handle file names with a `*.conf` extension. See #1703 (@cbolgiano) ## Other - Add PowerShell completion, see #1826 (@rashil2000) - Minimum supported Rust version (MSRV) bumped to 1.51, see #1994 (@mdibaiee) ## Syntaxes - Groff, see #1685 (@scop) - HTTP Requests and Responses, see #1748 (@keith-hall) - LLVM, see #1777 (@ioncodes) - Highlight for `vimrc` and `gvimrc` files, see #1763 (@SuperSandro2000) - Syslog highlighting improvements, see #1793 (@scop) - Added support for `slim` syntax, see #1693 (@mfinelli) - Racket, see #1884 (@jubnzv) - LiveScript, see #1915 (@Enselic) - MediaWiki, see #1925 (@sorairolake) - The `requirements.txt` syntax has been removed due to incompatible license requirements. - Dart, new highlighter, see #1959 (@Ersikan) - SCSS and Sass syntaxes updated, see #1766 (@Enselic) - PowerShell syntax updated, see #1935 (@Enselic) - TypeScript syntax updated, see #1834 (@Enselic) ## `bat` as a library - Deprecate `HighlightingAssets::syntaxes()` and `HighlightingAssets::syntax_for_file_name()`. Use `HighlightingAssets::get_syntaxes()` and `HighlightingAssets::get_syntax_for_path()` instead. They return a `Result` which is needed for upcoming lazy-loading work to improve startup performance. They also return which `SyntaxSet` the returned `SyntaxReference` belongs to. See #1747, #1755, #1776, #1862 (@Enselic) - Remove `HighlightingAssets::from_files` and `HighlightingAssets::save_to_cache`. Instead of calling the former and then the latter you now make a single call to `bat::assets::build`. See #1802, #1971 (@Enselic) - Replace the `error::Error(error::ErrorKind, _)` struct and enum with an `error::Error` enum. `Error(ErrorKind::UnknownSyntax, _)` becomes `Error::UnknownSyntax`, etc. Also remove the `error::ResultExt` trait. These changes stem from replacing `error-chain` with `thiserror`. See #1820 (@Enselic) - Add new `MappingTarget` enum variant `MapExtensionToUnknown`. Refer to its documentation for more information. Also mark `MappingTarget` as `#[non_exhaustive]` since more enum variants might be added in the future. See #1703 (@cbolgiano), #2012 (@Enselic) # v0.18.3 ## Bugfixes - Bump `git2` dependency to fix build with Rust 1.54, see #1761 # v0.18.2 ## Features - Ignore known backup/template filename suffixes when selecting the syntax, see #1687 (@scop) ## Bugfixes - Fix for a security vulnerability on Windows. Prior to this release, `bat` would execute programs called `less`/`less.exe` from the current working directory (instead of the one from `PATH`) with priority. An attacker might be able to use this by placing a malicious program in a shared directory where the user would execute `bat`. `bat` users on Windows are advised to upgrade to this version. See #1724 and #1472 (@Ry0taK). ## Other - Add bash completion, see #1678 (@scop) - Fix Clippy lints, see #1661 (@mohamed-abdelnour) - Add syntax highlighting test files, see #1213 and #1668 (@mohamed-abdelnour) ## Syntaxes - Upgraded Julia syntax to fix a highlighting bug, see #1692 - Added support for `dash` syntax, see #1654 (@mohamed-abdelnour) - Added support for `XAML` syntax, see #1590 and #1655 (@mohamed-abdelnour) - Apply `DotENV` syntax also for `.env.default` and `.env.defaults` files, see #1669 # v0.18.1 ## Bugfixes - Mouse support and screen clearing broken for `less` versions with minor version number (581.2), see #1629 and #1639 (@aswild) ## Other - `Input::ordinary_file` and `Input::with_name` now accept `Path` rather than `OsStr` see #1571 (@matklad) - The `LESS` environment variable is now included in `bat --diagnostic`, see #1589 (@Enselic) - Increased min. required Rust version to 1.45 ## Syntaxes - Improved the Syslog syntax highlighting, see #1606 (@keith-hall) - Replaced "Advanced CSV" with a custom CSV syntax definition written especially for `bat`; see #1574 (@keith-hall) - Added SystemVerilog file syntax, see #1580 (@SeanMcLoughlin) - Added Solidity and Vyper syntax, see #1602 (@Ersikan) ## New themes - Dark+ VS Code theme, see #1588 and #1598 (@PatriotRossii) # v0.18.0 ## Features - Use a pager when `bat --list-languages` is called, see #1394 (@stku1985) ## Bugfixes - If the last line doesn't end with a newline character, don't add it if `--style=plain`, see #1438 (@Enselic) - Only print themes hint in interactive mode (`bat --list-themes`), see #1439 (@rsteube) - Make ./tests/syntax-tests/regression_test.sh work on recent versions of macOS, see #1443 (@Enselic) - VimL syntax highlighting fix, see #1450 (@esensar) - Print an 'Invalid syntax theme settings' error message if a custom theme is broken, see #614 (@Enselic) - If plain mode is set and wrap is not explicitly opted in, long lines will no be truncated, see #1426 - If `PAGER` (but not `BAT_PAGER` or `--pager`) is `more` or `most`, silently use `less` instead to ensure support for colors, see #1063 (@Enselic) - If `PAGER` is `bat`, silently use `less` to prevent recursion. For `BAT_PAGER` or `--pager`, exit with error, see #1413 (@Enselic) - Manpage highlighting fix, see #1511 (@keith-hall) - `BAT_CONFIG_PATH` ignored by `bat` if non-existent, see #1550 (@sharkdp) ## Other - Performance improvements, see #1421 (@LovecraftianHorror) - Added a new `--diagnostic` option to collect information for bug reports, see #1459 (@sharkdp) - Modified default theme colors to differentiate between a JSON key and a string value, see #1400 (@keith-hall) - Upped min required Rust version to 1.42 ## Syntaxes - Added Zig syntax, see #1470 (@paulsmith) - Added Lean syntax, see #1446 (@Julian) - Added `.resource` extension for Robot Framework files, see #1386 - Added `gnuplot` syntax, see #1431 (@sharkdp) - Highlight *.pac (Proxy auto-config) files as JavaScript, see #1515 (@sharkdp) ## New themes - `ansi` replaces `ansi-dark` and `ansi-light`, see #1104 and #1412 (@mk12). **Breaking change:** users that were previously using one of the `ansi-*` themes should switch to `ansi`. - The Gruvbox theme has been updated, see #1291 (@j0hnmeow). **Breaking change:** users that were previously using `gruvbox` or `gruvbox-white` should update and use `gruvbox-dark`/`gruvbox-light` instead. ## `bat` as a library - The following `PrettyPrinter` methods have been removed (they were previously deprecated): - `input_stdin_with_name` - `input_from_bytes_with_name` - `input_from_reader_with_name` - `vcs_modification_markers` (if the `git` feature is not enabled) # v0.17.1 ## Bugfixes - Running `bat` without arguments fails ("output file is also an input"), see #1396 # v0.17.0 ## Features - Added a new `--style` value, `rule`, which adds a simple horizontal ruled line between files, see #1276 (@tommilligan) - Pass `-S` ("chop long lines") to `less` if `--wrap=never` is set in `bat`, see #1255 (@gahag) ## Bugfixes - Detect infinite loop when input and output are the same, see #1193 and #1197 (@niklasmohrin) - Throw an error when `bat` is being used as `pager`, see #1343 (@adrian-rivera) - Bash syntax highlighting not selected for `*.ebuild` and `*.eclass` files, see #1292 (@sharkdp) - Fix `zsh` completion when using `-p`, see #1320 (@xzfc) ## Other - Add note to refer to see detailed help with `--help` (and vice versa with `-h`), see #1215 (@henil) - Add a `Contributors` section to `README`, see #1348 (@adrian-rivera) ## Syntaxes - Manpage syntax highlighting has been improved, see #1315 (@keith-hall) - Add Svelte file syntax, see #1285 (@kjmph) ## New themes - Coldark, see #1329 (@armandphilippot) # v0.16.0 ## Features - Added support for the `NO_COLOR` environment variable, see #1021 and #1031 (@eth-p) - Added `-P` short flag to disable paging, see #1075 and #1082 (@LordFlashmeow) - Added `--force-colorization`/`-f` flag to provide an alias for forced color and decoration output, see #1141 (@alexanderkarlis) ## Bugfixes - Fixed non-printable characters display for redirected output, see #1061 (@gsomix) - Handle file extension conflicts in `--list-languages`, see #1076 and #1135 (@Kienyew) ## Other - Switched to "·" (U+00B7) Middle Dot from "•" (U+2022) Bullet for non-printing spaces, see #1056 and #1100 (@LordFlashmeow) - Added zsh shell completion script, see #1136 (@Kienyew) - Improved `--help` text (@sharkdp) - Added custom languages/themes sections to manpage (@eth-p) ## Syntaxes - Update AsciiDoc syntax, see #1034 (@rxt1077) - GLSL (@caioalonso) - Add Nginx and Apache config file syntax, see #1137 (@kjmph, @niklasmohrin) - Use `fstab` syntax for `crypttab` files, see #1073 (@sharkdp) - Support syntax highlighting for files in `$XDG_CONFIG_HOME/git/`, see #1191 (@ahmedelgabri) ## New themes - Gruvbox, see #1069 (@kyleondy) - base16-256 for [base16-shell](https://github.com/chriskempson/base16-shell) users, see #1111 (@mk12) ## `bat` as a library - Add APIs to provide `Input` descriptions with `InputDescription` (@eth-p) - Add function to directly provide `Input`s to `PrettyPrinter` (@eth-p) - **Breaking:** `Input::theme_preview_file` is no longer available. (@eth-p) ## Packaging - Removed build dependency on `liquid` (@sharkdp). # v0.15.4 ## Bugfixes - Added missing Solarized themes, see #1027 - Fixed highlighting bug in Haskell source files, see #1026 # v0.15.3 ## Bugfixes - Cannot run `bat` with relative paths, see #1022 - bat mishighlights Users that start with digits in SSH config, see #984 ## New syntaxes - SML, see #1005 (@kopecs) ## Other - Some syntaxes and themes have been updated to the latest version # v0.15.2 ## Bugfixes - Fix syntax detection for files called 'rails', see #1008 - Fix potential errors with syntax detection for symlinked files, see #1001 - `--map-syntax` doesn't work with names provided through `--file-name` (@eth-p) ## Other - Add padding above headers when not using a grid, see #968 and #981 (@pt2121) - bat now prints an error if an invalid syntax is specified via `-l` or `--map-syntax`, see #1004 (@eth-p) ## `bat` as a library - `PrettyPrinter::vcs_modification_markers` has been marked deprecated when building without the `git` feature, see #997 and #1020 (@eth-p, @sharkdp) ## Packaging - Compilation problems with `onig_sys` on various platforms have been resolved by upgrading to `syntect 4.2`, which includes a new `onig` version that allows to build `onig_sys` without the `bindgen` dependency. This removes the need for `libclang(-dev)` to be installed to compile `bat`. Package maintainers might want to remove `clang` as a build dependency. See #650 for more details. # v0.15.1 ## Bugfixes - Fix highlighting of Markdown files, see #963 and #977 - Fix `base16` theme (was broken since in v0.14), see #972, #934 and #979 (@mk12). Users suffering from #865 ("no color for bat in ssh from a Windows client") can use the `ansi-dark` and `ansi-light` themes from now on. ## New syntaxes - Fortran, see #957 - Email (@mariozaizar) - QML, see #962 (@pylipp) # v0.15.0 ## Features - Add a new `--diff`/`-d` option that can be used to only show lines surrounding Git changes, i.e. added, removed or modified lines. The amount of additional context can be controlled with `--diff-context=N`. See #23 and #940 ## Bugfixes - Error message printed in the middle of the output for another file, see #946 - Performance improvements when using custom caches (via `bat cache --build`): the `bat` startup time should now be twice as fast (@lzutao). ## Themes - Updated version of the Solarized dark/light themes, see #941 ## `bat` as a library - There are a few changes in the "low level" API (the `Config` struct has changed and the error handler needs a new `&mut dyn Write` argument). The high-level API is not affected. # v0.14.0 ## Features - Added a new `--file-name …` option to overwrite the displayed filename(s) in the header. This is useful when piping input into `bat`. See #654 and #892 (@neuronull). - Added a new `--generate-config-file` option to create an initial configuration file at the right place. See #870 (@jmick414) ## Bugfixes - Performance problems with C# source code have been fixed, see #677 (@keith-hall) - Performance problems with Makefiles have been fixed, see #750 (@keith-hall) - Fix bug when highlighting Ruby files with unindented heredocs, see #914 (@keith-hall) - A highlighting problem with Rust source code has been fixed, see #924 (@keith-hall) - Windows: short files that do not require paging are displayed and then lost, see #887 - `--highlight-line` did not work correctly in combination with `--tabs=0` and `--wrap=never`, see #937 ## Other - When saving/reading user-provided syntaxes or themes, `bat` will now maintain a `metadata.yaml` file which includes information about the `bat` version which was used to create the cached files. When loading cached files, we now print an error if they have been created with an incompatible version. See #882 - Updated `liquid` dependency to 0.20, see #880 (@ignatenkobrain) ## `bat` as a library - A completely new "high level" API has been added that is much more convenient to use. See the `examples` folder for the updated code. The older "low level" API is still available (basically everything that is not in the root `bat` module), but has been refactored quite a bit. It is recommended to only use the new "high level" API, if possible. This will be much easier to keep stable. Note that this should still be considered a "beta" release of `bat`-as-a-library. For more details and some screenshots of the example programs, see #936. - Stripped out a lot of binary-only dependencies, see #895 and #899 (@dtolnay) This introduces a `features = ["application"]` which is enabled by default and pulls in everything required by `bat` the application. When depending on bat as a library, downstream `Cargo.toml` should disable this feature to cut out inapplicable heavy dependencies: ``` toml [dependencies] bat = { version = "0.14", default-features = false } ``` Other optional functionality has also been put behind features: `paging` and `git` support. - Allow using the library with older syntect, see #896 and #898 (@dtolnay) ## New syntaxes - Rego, see #872 (@patrick-east) - Stylo, see #917 # v0.13.0 ## `bat` as a library Beginning with this release, `bat` can be used as a library (#423). This was a huge effort and I want to thank all people who made this possible: @DrSensor, @mitsuhiko, @mre, @eth-p! - Initial attempt in #469 (@mitsuhiko) - Second attempt, complete restructuring of the `bat` crate, see #679 (@DrSensor) - Updates to example, public API, error handling, further refactoring: #693 #873 #875 (@sharkdp) I want to stress that this is the very first release of the library. Things are very likely to change. A lot of things are still missing (including the documentation). That being said, you can start using it! See the example programs in [`examples/`](https://github.com/sharkdp/bat/tree/master/examples). You can see the API documentation here: https://docs.rs/bat/ ## Features - (**Breaking change**) Glob-based syntax mapping, see #877 and #592. With this change, users need to update their bat config files (`bat --config-file`), if they have any `--map-syntax` settings present. The option now works like this: ```bash --map-syntax : ``` For more information, see the `--help` text, the man page or the README. This new feature allows us to properly highlight files like: * `/etc/profile` * `~/.ssh/config` - `--highlight-line` now accepts line ranges, see #809 (@lkalir) - Proper wrapping support for output with wide Unicode characters, see #811 #787 and #815 (@Kogia-sima) - A lot of updates to existing syntaxes via #644 (@benwaffle, @keith-hall) - `BAT_CACHE_PATH` can be used to place cached `bat` assets in a non-standard path, see #829 (@neuronull) - Support combination of multiple styles at the same time, see #857 (@aslpavel) ## Bugfixes - Do not pass '--no-init' on newer less versions, see #749 and #786 (@sharkdp) - 'bat cache' still takes precedence over existing files, see #666 (@sharkdp) - `.sc` files should be treated as scala files, see #443 (@benwaffle) - Allow underscores and dashes in page names, see #670 (@LunarLambda) - Keep empty lines empty, see #601 (@mbarbar) - Wrapping does not work when piping, see #758 (@fusillicode, @allevo, @gildo) - Allow for non-unicode filenames, see #225 (@sharkdp) - Empty file without header produces incomplete grid, see #798 (@eth-p) - Files named `build` don't respect shebang lines, see #685 (@sharkdp) ## Other - Parametrizable names for man page and shell completion files, see #659 #673 #656 (@eth-p) - Enabled LTO, making `bat` about 10% faster, see #719 (@bolinfest, @sharkdp) - Suggestions non how to configure `bat` for MacOS dark mode, see README (@jerguslejko) - Extended ["Integration with other tools"](https://github.com/sharkdp/bat#integration-with-other-tools) section (@eth-p) - Updated [instrutions on how to use `bat` as a `man`-pager](https://github.com/sharkdp/bat#man), see #652, see #667 (@sharkdp) - Add section concerning file encodings, see #688 and #568 (@sharkdp) - Updated sort order of command-line options in `--help` text and manpage, see #653 and #700 (@hrlmartins) - Updates to the man page syntax, see #718 (@sharkdp) - Japanese documentation updates, see #863 (@k-ta-yamada, @sorairolake and @wt-l00) - Accept "default" as a theme, see #757 (@fvictorio) - Updated Windows installation instructions, see #852 (@sorenbug) - Updated man page, see #573 (@sharkdp) ## New syntaxes - Jinja2, see #648 (@Martin819) - SaltStack SLS, see #658 (@Martin819) - `/etc/fstab`, see #696 (@flopp and @eth-p) - `/etc/group` and `/etc/passwd`, see #698 (@argentite) - `/proc/cpuinfo` and `/proc/meminfo`, see #593 (@sharkdp) - Nim, see #542 (@sharkdp) - Vue, see #826 (@chaaaaarlotte) - CoffeScript, see #833 (@sharkdp) ## New themes - Dracula, see #687 (@clarfon) - Nord, see #760 (@crabique) - Solarized light and dark, see #768 (@hakamadare) ## Packaging - `bat` is now in the official Ubuntu and Debian repositories, see #323 and #705 (@MarcoFalke) - `bat` can now be installed via MacPorts, see #675 (@bn3t) - Install fish completions into 'vendor_completions.d', see #651 (@sharkdp) ## Thanks - To @eth-p for joining me as a maintainer! I'm very grateful for all the work you put into managing and responding to issues, improving our deployment, adding PR/issue templates (#837) as well as fixing bugs and implementing new features. # v0.12.1 ## Bugfixes - Fixes a bug for older Windows versions (*"The procedure entry point `CreateFile2` could not be located"*), see #643 (@rivy) # v0.12.0 ## Features - Binary file content can now be viewed with `bat -A`, see #623, #640 (@pjsier and @sharkdp) - `bat` can now be used as a man pager. Take a look at the README and #523 for more details. - Add new style component to separate multiple `--line-range`s, see #570 (@eth-p) - Added `-L` as an alias for `--list-languages` ## Bugfixes - Output looks unbalanced when using '--style=grid,numbers' without 'header', see #571 (@eth-p) - issues with filenames starting with "cache", see #584 - Can't build cache with new theme without creating cache dir, see #576 (@frm) - `--terminal-width -10` is parsed incorrectly, see #611 ## Other - Added fish completions to DEB package, see #554 ## New syntaxes - Emacs Org mode, see #36 (@bricewge) - `requirements.txt` - DotENV `.env` - SSH config syntax (`-l ssh_config`), see #582 (@issmirnov) - `/etc/hosts`, see #583 (@issmirnov) - GraphQL, see #625 (@dandavison) - Verilog, see #616 - SCSS and Sass, see #637 - `strace` syntax, see #599 ## Packaging - `bat` is now in the official Gentoo repositories, see #588 (@toku-sa-n) - `bat` is now in the official Alpine Linux repositories, see #586 (@5paceToast) - `bat` is in the official Fedora repositories, see #610 (@ignatenkobrain) # v0.11.0 ## Features - Three new special color themes are available: `ansi-light`, `ansi-dark` and `base16`. These are useful for people that often switch from dark to light themes in their terminal emulator or for people that want the colors to match their terminal theme colors. For more details, see #543 and #490 (@mk12, implementation idea by @trishume) - Hand-written auto completion script for Fish shell, see #524 and #555 (@ev-dev and @eth-p) - The `-p`/`--plain` option can now be used twice (typically `-pp`). The first `-p` switches the `--style` to "plain". The second `-p` disables the pager. See #560 and #552 (@eth-p) ## Bugfixes - Do not replace arguments to `less` when using `--pager`, see #509 - Binary files will now be indicated by a warning in interactive mode, see #530 #466 #550 (@maxfilov) - Empty files are (once again) printed with a single header line, see #504 and #566 (@reidwagner and @sharkdp) - `--terminal-width=0` is now disallowed, see #559 (@eth-p) - Accidental printing of files named `cache`, see #557 ## Other - New integration tests, see #500 and #502 (@reidwagner and @sharkdp) - New ["Integration with other tools"](https://github.com/sharkdp/bat#integration-with-other-tools) section in the README. - Migrated to Rust 2018 (@expobrain) ## New syntaxes - F# syntax has been updated, see #531 (@stroborobo) - Fish shell, see #548 (@sanga) ## Packaging - `bat` is now available on Chocolatey, see #541 (@rasmuskriest) # v0.10.0 ## Features - Added new `--highlight-line ` option, see #453, #346 and #175 (@tskinn and @sharkdp) ## Changes - **Change the default configuration directory on macOS** to `~/.config/bat`, see #442 (@lavifb). If you are on macOS, you need to copy your configuration directory from the previous place (`~/Library/Preferences/bat`) to the new place (`~/.config/bat`). - Completely disabled the generation of shell completion files, see #372 - Properly set arguments to `less` if `PAGER` environment variable contains something like `less -F` (which is missing the `-R` option), see #430 (@majecty) - Report the name of missing files, see #444 (@ufuji1984) - Don't start pager if file doesn't exist, see #387 - Rename `bat cache --init` to `bat cache --build`, see #498 - Move the `--config-dir` and `--cache-dir` options from `bat cache` to `bat` and hide them from the help text. ## Bugfixes - Blank line at the end of output when using `--style=plain`, see #379 - EOF must be sent twice on stdin if no other input is sent, see #477 (@reidwagner) ## New syntaxes - Twig (@ahmedelgabri) - `.desktop` files (@jleclanche) - AsciiDoc (@markusthoemmes) - Assembly (x86_64 and ARM) - Log files (@caos21) - Protobuf and ProtobufText (@caos21) - Terraform (@caos21) - Jsonnet (@hfm) - Varlink (@haraldh) ## Other - Added Japanese version of README (@sh-tech and @object1037) - Code improvements (@barskern) # v0.9.0 ## Features - A new `-A`/`--show-all` option has been added to show and highlight non-printable characters (in analogy to GNU `cat`s option): ![](https://camo.githubusercontent.com/c3e769482ef3184f6be6adaa34bdc8d19c378254/68747470733a2f2f692e696d6775722e636f6d2f324b54486859542e706e67) see #395 and #381 for more details. - Added `--pager` option (to configure the pager from the configuration file), see #362 (@majecty) - Added `BAT_CONFIG_PATH` environment variable to set a non-default path for `bat`s configuration file, see #375 (@deg4uss3r) - Allow for multiple occurrences of `--style` to allow for the configuration of styles from the config file, see #367 (@sindreij) - Allow for multiple `--line-range` arguments, see #23 - The `--terminal-width` option can now also accept offsets, see #376 ## Changes - Use of italics is now *disabled by default* (see #389 for details). They can be re-enabled by adding `--italic-text=always` to your configuration file. - The default tab-width has been set to 4. - Added new "Sublime Snazzy" theme. - Shell completions are currently *not* shipped anymore, see #372 for details. ## Bugfixes - Avoid endless recursion when `PAGER="bat"`, see #383 (@rodorgas) ## Other - `bat` is now available on openSUSE, see #405 (@dmarcoux) - Added section about the new configuration file in the README (@deg4uss3r) - Chinese translation of README (@chinanf-boy) - Re-written tests for `--tabs` (@choznerol) - Speed up integration tests, see #394 # v0.8.0 ## Features - Support for a configuration file with the following simple format: ```bash --tabs=4 --theme="Sublime Snazzy" # A line-comment --map-syntax .ignore:.gitignore --map-syntax PKGBUILD:bash --map-syntax Podfile:ruby # Flags and options can also be on a single line: --wrap=never --paging=never ``` The configuration file path can be accessed via `bat --config-file`. On Linux, it is stored in `~/.config/bat/config`. - Support for the `BAT_OPTS` environment variable with the same format as specified above (in a single line). This takes precedence over the configuration file. See also #310. - Support for custom syntax mappings via the `-m`/`--max-syntax` option. This allows users to (re)map certain file extensions or file names to an existing syntax: ``` bash bat --map-syntax .config:json ... ``` The option can be use multiple times. Note that you can easily make these mappings permanent by using bats new configuration file. See #169 - Support pager command-line arguments in `PAGER` and `BAT_PAGER`, see #352 (@Foxboron) - Add support for wildcards in Windows CMD, see #309 (@zxey) - First-line syntax detection for all input types, see #205 - Encoding support for UTF-16LE and UTF-16BE, see #285 - New syntaxes: Robot framework (@sanga) ## Changes - Binary files are now detected and not displayed when the output goes to an interactive terminal, see #205 ## Bugfixes - JavaDoc comments break syntax highlighting in .java files, see #81 - Bat Panics on Haskell Source Code, see #314 ## Other - Better `-h` and `--help` texts. - Updated documentation on how to configure `bat`s pager - Updated documentation for light backgrounds, see #328 (@russtaylor) - Generate shell completions during build, see #115 (@davideGiovannini) - A lot of new tests have been written - `bat` is now available via [Termux](https://termux.com/), see #341 (@fornwall) - `bat` is now available via [nix](https://nixos.org/nix), see #344 (@mgttlinger) - `bat` is now available via [Docker](https://hub.docker.com/r/danlynn/bat/), see #331 (@danlynn) # v0.7.1 ## Features - Use the `ansi_colours` package by @mina86 for better true-color approximation on 8 bit color terminals, see #319 and #202. ## Bugfixes - Bat Panics on Haskell Source Code, see #314 - Disable wrapping when `--style=plain`/`-p` is used, see #289 ## Other - Added Ansible install instructions (@aeimer) - Added section about Cygwin to the README (@eth-p) # v0.7.0 ## Features - Tabs are now (optionally) expanded to spaces. This can be controlled with the new `--tabs` command-line option or the `BAT_TABS` environment variable. The new feature also closes two bugs #166 and #184. For more information, see #302 (@eth-p). - Added support for the `BAT_STYLE` environment variable, see #208 (@ms2300) - Added `OneHalf` theme for terminals with a light-gray background, see #256 - Added new syntaxes for CSV, JSX in JavaScript and TypeScript, Cabal, Dart, F#, PureScript, Swift, Crystal, PowerShell (Many Thanks to @tobenna and @mimadrid) ## Changes - Query `git diff` only when needed, see #303 (@ShikChen) - Disable wrapping when `--plain` is used, see #289 (@eth-p) ## Bugfixes - Can read files named `cache`, see #275 (@BK1603) - A lot of bugfixes for Windows, see #252, #264 - Detect `less` reliably and in a portable way, see #271 and #290 (@Aankhen) - last decoration line is not formatted properly with `--wrap never`, see #299 (@Rogach) - Do not show file header for directories, see #292 ## Other - Enabled a new `aarch64` build target, see #258 (@rachitchokshi) - Provide Debian packages for `armhf`, see #280 (@rachitchokshi) - Added README section about "`bat` on Windows" (@Aankhen) - Windows installation via scoop (@meltinglava) # v0.6.1 ## Bugfixes - Fixed panic when running `bat --list-languages | head`, see #232 (@mchlrhw) - Respect `--color` settings for `--list-themes` and `--list-languages`, see #233 - Git modifications now work on Windows ## Other - There will be auto-generated Windows releases, starting with this version (@anykao) # v0.6.0 ## Features - The `--list-themes` option now shows a preview for each highlighting theme (@ms2300) - Added `-p`/`--plain` as an alias for `--style=plain`, see #212 (@ms2300) - Major refactorings, enabling some progress on #150. In non-interactive mode, `bat` will now copy input bytes 1:1. - New languages: Elm, Kotlin, Puppet, TypeScript, see #215 #216 #217 #218 - New syntax highlighting theme: zenburn (@colindean) ## Changes - New themes in `$BAT_CONFIG_DIR/themes` are now loaded *in addition* to the default themes (they may also override), see #172 - The `Default.tmTheme` symlink is not necessary anymore. ## Bugfixes * Using `bat cache --init` leads to duplicated syntaxes, see #206 ## Other * Extended and cleaned-up `--help` text. * Added initial version of a man page, see #52 * New README sections: *Development* and *Troubleshooting*, see #220 # v0.5.0 ## Features - Added `--line-range n:m` option to print a range of lines, see #159 (@tskinn) - The syntax highlighting theme can now be controlled by the `BAT_THEME` environment variable, see [README](https://github.com/sharkdp/bat#highlighting-theme) and #177 (@mandx) - The `PAGER` and `BAT_PAGER` environment variables can be used to control the pager that `bat` uses, see #158 and the [new README section](https://github.com/sharkdp/bat#using-a-different-pager) - Added syntax highlighting for Nix, see #180 - Added syntax highlighting for AWK (Gert Hulselmans) ## Changes - The customization of syntax sets and theme sets is now separated. Syntax definitions are now loaded *in addition* to the ones that are stored in the `bat` binary by default. Please refer to these new sections in the README: [Adding new syntaxes](https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions), [Adding new themes](https://github.com/sharkdp/bat#adding-new-themes), also see #172 - The color for the filename is now the default foreground color. The colors for the grid and the line numbers is now determined from the syntax highlighting theme, which now also works for light backgrounds, see #178. ## Bugfixes - Escape Sequences get partially stripped, see #182 (@eth-p) - Use separate Git repository for snapshot testing, see #165 and #161 - Markdown breaking on JavaScript, see #183 ## Other - Binaries for armv7 are now provided, see #196 - `bat` is now in the official [Arch package repositories](https://www.archlinux.org/packages/community/x86_64/bat/). - Optimizations in the RGB => 8-bit conversion (@mina86) # v0.4.1 (this is just a small bugfix release, see 0.4.0 for all features and changes) ## Bugfixes - Fix problem with `cargo test` when `bat` is not checked out in a Git repository, see #161 # v0.4.0 ## Features * Support for line-wrapping, see #54 and #102 (@eth-p) * New and updated `--style` parameter, see #74 and README (@pitkley) * Added `--theme` and `--list-themes` options, see #89 (@rleungx) * Added syntax highlighting for: Julia (@iamed2), Dockerfiles, VimL, CMake, INI, Less * Added a few popular Sublime Text highlighting themes, see #133 * Support for bold, italic and underline font styles, see #96 * Support for 32bit systems is now available, see #84 * Added `-u` and `-n` options, see #134 * ANSI color support on Windows 10 ## Changes * The customization folder for own syntaxes has been renamed from `syntax` to `syntaxes`, see README. * Changed Markdown syntax to the default Sublime Text syntax, see #157 * Sorted language listing (@rleungx) * Command line arguments like `--theme` or `--color` can now override themselves. * Improved `--help` text. ## Bugfixes - Fixed crash for (really) small terminal sizes, see #117 (@eth-p) - Syntax detection for `.bashrc`, `CMakeLists.txt` etc., see #100 - Properly handle lines with invalid UTF-8, see #7 (@BrainMaestro) - Better error handling, see #17 (@rleungx and @sharkdp) - Proper handling of UTF-8 characters in `less`, see #98 (@ghuls) - Build fix on nightly, see #148 (@tathanhdinh) ## Other - [Comparison with alternative projects](https://github.com/sharkdp/bat/blob/master/doc/alternatives.md). - New "bat" logo in the README, see #119 (@jraulhernandezi) - Output test cases (@BrainMaestro) - Lots of great refactoring work (@BrainMaestro) # v0.3.0 ## Features * Automatic paging by integrating with `less`, see #29 (@BrainMaestro) * Added support for reading from standard input, see #2 * Added support for writing to non-interactive terminals (pipes, files, ..); new `--color=auto/always/never` option, see #26 (@BrainMaestro) * Added `--list-languages` option to print all available syntaxes, see #69 (@connorkuehl) * New option to specify the syntax via `-l`/`--language`, see #19 (@BrainMaestro) * New option to control the output style (`--style`), see #5 (@nakulcg) * Added syntax highlighting support for TOML files, see #37 ## Changes * The `init-cache` sub-command has been removed. The cache can now be controlled via `bat cache`. See `bat cache -h` for all available commands. ## Bug fixes * Get git repository from file path instead of current directory, see #22 (@nakulcg) * Process substitution can now be used with bat (`bat <(echo a) <(echo b)`), see #80 ## Thanks I'd like to say a big THANK YOU to all contributors and everyone that has given us some form of feedback. Special thanks go to @BrainMaestro for his huge support with new features, bug reports and code reviews! # v0.2.3 - Added a new statically linked version of bat (`..-musl-..`) # v0.2.2 - Remove openssl dependency completely, see #30. # v0.2.1 - Added Elixir syntax, see #25. - Use libcurl-openssl instead of libcurl-gnutls, see #30. # v0.2.0 - Support for custom syntaxes, add 'Markdown extended' theme - Bugfix: Git modifications not shown from child folder # v0.1.0 Initial release ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Thank you for considering to contribute to `bat`! ## Add an entry to the changelog Keeping the [`CHANGELOG.md`](CHANGELOG.md) file up-to-date makes the release process much easier and therefore helps to get your changes into a new `bat` release faster. However, not every change to the repository requires a changelog entry. Below are a few examples of that. Please update the changelog if your contribution contains changes regarding any of the following: - the behavior of `bat` - syntax mappings - syntax definitions - themes - the build system, linting, or CI workflows A changelog entry is not necessary when: - updating documentation - fixing typos >[!NOTE] > For PRs, a CI workflow verifies that a suitable changelog entry is > added. If such an entry is missing, the workflow will fail. If your > changes do not need an entry to the changelog (see above), that > workflow failure can be disregarded. ### Changelog entry format The top of the `CHANGELOG` contains a *"unreleased"* section with a few subsections (Features, Bugfixes, …). Please add your entry to the subsection that best describes your change. Entries must follow this format: ``` - Short description of what has been changed, see #123 (@user) ``` Please replace `#123` with the number of your pull request (not issue) and `@user` by your GitHub username. ## Development Please check out the [Development](https://github.com/sharkdp/bat#development) section in the README. ## Adding a new feature Please consider opening a [feature request ticket](https://github.com/sharkdp/bat/issues/new?assignees=&labels=feature-request&template=feature_request.md) first in order to give us a chance to discuss the details and specifics of the potential new feature before you go and build it. ## Adding new syntaxes/languages or themes Before you make a pull request that adds a new syntax or theme, please read the [Customization](https://github.com/sharkdp/bat#customization) section in the README first. If you really think that a particular syntax should be added for all users, please read the corresponding [documentation](https://github.com/sharkdp/bat/blob/master/doc/assets.md) first. To map a file name pattern to an existing syntax, read [the documentation here](https://github.com/sharkdp/bat/blob/master/src/syntax_mapping/builtins/README.md). Note: We are currently not accepting new default themes. ## Regression tests You are **strongly encouraged** to add regression tests. Regression tests are great, not least because they: * ensure that your contribution will never completely stop working. * makes code reviews easier, because it becomes very clear what the code is supposed to do. For functional changes, you most likely want to add a test to [`tests/integration_tests.rs`](https://github.com/sharkdp/bat/blob/master/tests/integration_tests.rs). Look at existing tests to know how to write a new test. In short, you will invoke the `bat` binary with a certain set of arguments, and then assert on stdout/stderr. To learn how to write regression tests for theme and syntax changes, read the [Syntax tests](https://github.com/sharkdp/bat/blob/master/doc/assets.md#syntax-tests) section in `assets.md`. ### Ensuring bat is available for Syntax tests The syntax test script (`tests/syntax-tests/update.sh`) calls `bat` from your PATH and regenerates the highlighted output files under `tests/syntax-tests/highlighted/`. These files are used to verify that syntax highlighting works as expected. - If you only built the binaries with: ```bash cargo build --bins ``` you need to add the debug build to your PATH from the bat project root before running the tests. See also step 5 in [Syntax tests](https://github.com/sharkdp/bat/blob/master/doc/assets.md#syntax-tests) for related instructions. ```bash export PATH="$PATH:$(pwd)/target/debug" ``` Otherwise, you will see: ```bash Error: Could not execute 'bat'. Please make sure that the executable is available on the PATH. ``` - If you installed bat with: ```bash cargo install --path . --locked ``` then bat will be available in ~/.cargo/bin (usually already in PATH), and the tests will run without issues. ================================================ FILE: Cargo.toml ================================================ [package] authors = ["David Peter "] categories = ["command-line-utilities"] description = "A cat(1) clone with wings." homepage = "https://github.com/sharkdp/bat" license = "MIT OR Apache-2.0" name = "bat" repository = "https://github.com/sharkdp/bat" version = "0.26.1" exclude = ["assets/syntaxes/*", "assets/themes/*"] build = "build/main.rs" edition = '2021' # You are free to bump MSRV as soon as a reason for bumping emerges. rust-version = "1.88" [features] default = ["application", "git"] # Feature required for bat the application. Should be disabled when depending on # bat as a library. application = [ "bugreport", "build-assets", "minimal-application", ] # Mainly for developers that want to iterate quickly # Be aware that the included features might change in the future minimal-application = [ "clap", "etcetera", "paging", "regex-onig", "wild", ] git = ["git2"] # Support indicating git modifications vendored-libgit2 = ["git2/vendored-libgit2"] paging = [ "shell-words", "grep-cli", "minus"] # Support applying a pager on the output lessopen = ["execute"] # Support $LESSOPEN preprocessor build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"] # You need to use one of these if you depend on bat as a library: regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine [dependencies] nu-ansi-term = "0.50.3" ansi_colours = "^1.2" bincode = "1.0" console = "0.16.2" flate2 = "1.1" once_cell = "1.20" thiserror = "2.0" wild = { version = "2.2", optional = true } content_inspector = "0.2.4" shell-words = { version = "1.1.1", optional = true } minus = { version = "5.6", optional = true, features = [ "dynamic_output", "search", ] } unicode-width = "0.2.1" globset = "0.4" serde = "1.0" serde_derive = "1.0" serde_yaml = "0.9.28" semver = "1.0" path_abs = { version = "0.5", default-features = false } clircle = { version = "0.6.1", default-features = false } bugreport = { version = "0.5.0", optional = true } etcetera = { version = "0.11.0", optional = true } grep-cli = { version = "0.1.12", optional = true } regex = { version = "1.12.2", optional = true } walkdir = { version = "2.5", optional = true } bytesize = { version = "2.3.1" } encoding_rs = "0.8.35" execute = { version = "0.2.15", optional = true } terminal-colorsaurus = "1.0" unicode-segmentation = "1.12.0" itertools = "0.14.0" [dependencies.git2] version = "0.20" optional = true default-features = false [dependencies.syntect] version = "5.3.0" default-features = false features = ["parsing"] [dependencies.clap] version = "4.5.60" optional = true features = ["wrap_help", "cargo"] [target.'cfg(target_os = "macos")'.dependencies] plist = "1.7.0" [dev-dependencies] assert_cmd = "2.0.16" expect-test = "1.5.0" serial_test = { version = "2.0.0", default-features = false } predicates = "3.1.3" wait-timeout = "0.2.1" tempfile = "3.23.0" serde = { version = "1.0", features = ["derive"] } [target.'cfg(unix)'.dev-dependencies] nix = { version = "0.31", default-features = false, features = ["term"] } [build-dependencies] anyhow = "1.0.97" indexmap = { version = "2.13.0", features = ["serde"] } itertools = "0.14.0" once_cell = "1.20" prettyplease = "0.2.37" proc-macro2 = "1.0.106" quote = "1.0.40" regex = "1.12.2" serde = "1.0" serde_derive = "1.0" serde_with = { version = "3.17.0", default-features = false, features = ["macros"] } syn = { version = "2.0.104", features = ["full"] } toml = { version = "0.9.8", features = ["preserve_order"] } walkdir = "2.5" [build-dependencies.clap] version = "4.5.60" optional = true features = ["wrap_help", "cargo"] [profile.release] lto = true strip = true codegen-units = 1 ================================================ FILE: LICENSE-APACHE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: LICENSE-MIT ================================================ Copyright (c) 2018-2023 bat-developers (https://github.com/sharkdp/bat). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights 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. ================================================ FILE: NOTICE ================================================ Copyright (c) 2018-2021 bat-developers (https://github.com/sharkdp/bat). bat is made available under the terms of either the MIT License or the Apache License 2.0, at your option. See the LICENSE-APACHE and LICENSE-MIT files for license details. ================================================ FILE: README.md ================================================

bat - a cat clone with wings
Build Status license Version info
A cat(1) clone with syntax highlighting and Git integration.

Key FeaturesHow To UseInstallationCustomizationProject goals, alternatives
[English] [中文] [日本語] [한국어] [Русский]

### Sponsors A special *thank you* goes to our biggest sponsors:

Warp
Warp, the intelligent terminal
Available on MacOS, Linux, Windows

### Syntax highlighting `bat` supports syntax highlighting for a large number of programming and markup languages: ![Syntax highlighting example](https://imgur.com/rGsdnDe.png) ### Git integration `bat` communicates with `git` to show modifications with respect to the index (see left sidebar): ![Git integration example](https://i.imgur.com/2lSW4RE.png) ### Show non-printable characters You can use the `-A`/`--show-all` option to show and highlight non-printable characters: ![Non-printable character example](https://i.imgur.com/WndGp9H.png) ### Automatic paging By default, `bat` pipes its own output to a pager (e.g. `less`) if the output is too large for one screen. If you would rather `bat` work like `cat` all the time (never page output), you can set `--paging=never` as an option, either on the command line or in your configuration file. If you intend to alias `cat` to `bat` in your shell configuration, you can use `alias cat='bat --paging=never'` to preserve the default behavior. #### File concatenation Even with a pager set, you can still use `bat` to concatenate files :wink:. Whenever `bat` detects a non-interactive terminal (i.e. when you pipe into another process or into a file), `bat` will act as a drop-in replacement for `cat` and fall back to printing the plain file contents, regardless of the `--pager` option's value. ## How to use Display a single file on the terminal ```bash bat README.md ``` Display multiple files at once ```bash bat src/*.rs ``` Read from stdin, determine the syntax automatically (note, highlighting will only work if the syntax can be determined from the first line of the file, usually through a shebang such as `#!/bin/sh`) ```bash curl -s https://sh.rustup.rs | bat ``` Read from stdin, specify the language explicitly ```bash yaml2json .travis.yml | json_pp | bat -l json ``` Show and highlight non-printable characters: ```bash bat -A /etc/hosts ``` Use it as a `cat` replacement: ```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'. ``` ### Integration with other tools #### `fzf` You can use `bat` as a previewer for [`fzf`](https://github.com/junegunn/fzf). To do this, use `bat`'s `--color=always` option to force colorized output. You can also use `--line-range` option to restrict the load times for long files: ```bash fzf --preview "bat --color=always --style=numbers --line-range=:500 {}" ``` For more information, see [`fzf`'s `README`](https://github.com/junegunn/fzf#preview-window). #### `find` or `fd` You can use the `-exec` option of `find` to preview all search results with `bat`: ```bash find … -exec bat {} + ``` If you happen to use [`fd`](https://github.com/sharkdp/fd), you can use the `-X`/`--exec-batch` option to do the same: ```bash fd … -X bat ``` #### `ripgrep` With [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md), `bat` can be used as the printer for [`ripgrep`](https://github.com/BurntSushi/ripgrep) search results. ```bash batgrep needle src/ ``` #### `tail -f` `bat` can be combined with `tail -f` to continuously monitor a given file with syntax highlighting. ```bash tail -f /var/log/pacman.log | bat --paging=never -l log ``` Note that we have to switch off paging in order for this to work. We have also specified the syntax explicitly (`-l log`), as it can not be auto-detected in this case. #### `git` You can combine `bat` with `git show` to view an older version of a given file with proper syntax highlighting: ```bash git show v0.6.0:src/main.rs | bat -l rs ``` #### `git diff` You can combine `bat` with `git diff` to view lines around code changes with proper syntax highlighting: ```bash batdiff() { git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff } ``` If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras). If you are looking for more support for git and diff operations, check out [`delta`](https://github.com/dandavison/delta). #### `xclip` The line numbers and Git modification markers in the output of `bat` can make it hard to copy the contents of a file. To prevent this, you can call `bat` with the `-p`/`--plain` option or simply pipe the output into `xclip`: ```bash bat main.cpp | xclip ``` `bat` will detect that the output is being redirected and print the plain file contents. #### `man` `bat` can be used as a colorizing pager for `man`, by setting the `MANPAGER` environment variable: ```bash export MANPAGER="bat -plman" man 2 select ``` (on some older Debian or Ubuntu releases, the executable is named `batcat` instead of `bat`) If you prefer to have this bundled in a new command, you can also use [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md). Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax) is developed in this repository and still needs some work. #### `prettier` / `shfmt` / `rustfmt` The [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) script is a wrapper that will format code and print it with `bat`. #### `Warp` Warp #### Highlighting `--help` messages You can use `bat` to colorize help text: `$ cp --help | bat -plhelp` You can also use a wrapper around this: ```bash # in your .bashrc/.zshrc/*rc alias bathelp='bat --plain --language=help' help() { "$@" --help 2>&1 | bathelp } ``` Then you can do `$ help cp` or `$ help git commit`. When you are using `zsh`, you can also use global aliases to override `-h` and `--help` entirely: ```bash alias -g -- -h='-h 2>&1 | bat --language=help --style=plain' alias -g -- --help='--help 2>&1 | bat --language=help --style=plain' ``` For `fish`, you can use abbreviations: ```fish abbr -a --position anywhere -- --help '--help | bat -plhelp' abbr -a --position anywhere -- -h '-h | bat -plhelp' ``` This way, you can keep on using `cp --help`, but get colorized help pages. Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`). In cases where you need to use `-h` as a command argument you can prepend `\` to the argument (eg. `ls \-h`) to escape the aliasing defined above. Please report any issues with the help syntax in [this repository](https://github.com/victor-gp/cmd-help-sublime-syntax). ## Installation [![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg?columns=3&exclude_unsupported=1)](https://repology.org/project/bat-cat/versions) ### On Ubuntu (using `apt`) *... and other Debian-based Linux distributions.* `bat` is available on [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) and [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). If your Ubuntu/Debian installation is new enough you can simply run: ```bash sudo apt install bat ``` **Important**: On some older Ubuntu/Debian releases, the executable is installed as `batcat` instead of `bat` (due to [a name clash with another package](https://github.com/sharkdp/bat/issues/982)). On newer releases, the executable is available as `bat`. If `bat --version` does not work after installation, try `batcat --version` instead. You can set up a `bat -> batcat` symlink or alias to prevent any issues that may come up because of this and to be consistent with other distributions: ``` bash mkdir -p ~/.local/bin ln -s /usr/bin/batcat ~/.local/bin/bat ``` an example alias for `batcat` as `bat`: ```bash alias bat="batcat" ``` ### On Ubuntu (using most recent `.deb` packages) *... and other Debian-based Linux distributions.* If the package has not yet been promoted to your Ubuntu/Debian installation, or you want the most recent release of `bat`, 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.18.3_amd64.deb # adapt version number and architecture ``` ### On Alpine Linux You can install [the `bat` package](https://pkgs.alpinelinux.org/packages?name=bat) from the official sources, provided you have the appropriate repository enabled: ```bash apk add bat ``` ### On Arch Linux You can install [the `bat` package](https://www.archlinux.org/packages/extra/x86_64/bat/) from the official sources: ```bash pacman -S bat ``` ### On Fedora You can install [the `bat` package](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) from the official [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/) repository. ```bash dnf install bat ``` ### On Gentoo Linux You can install [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat) from the official sources: ```bash emerge sys-apps/bat ``` ### On 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 OpenBSD You can install `bat` package using [`pkg_add(1)`](https://man.openbsd.org/pkg_add.1): ```bash pkg_add bat ``` ### Via nix You can install `bat` using the [nix package manager](https://nixos.org/nix): ```bash nix-env -i bat ``` ### On openSUSE You can install `bat` with zypper: ```bash zypper install bat ``` ### Via snap package There is currently no recommended snap package available. Existing packages may be available, but are not officially supported and may contain [issues](https://github.com/sharkdp/bat/issues/1519). ### On macOS (or Linux) via Homebrew You can install `bat` with [Homebrew](https://formulae.brew.sh/formula/bat): ```bash brew install bat ``` ### On macOS via MacPorts Or install `bat` with [MacPorts](https://ports.macports.org/port/bat/summary): ```bash port install bat ``` ### On Windows There are a few options to install `bat` on Windows. Once you have installed `bat`, take a look at the ["Using `bat` on Windows"](#using-bat-on-windows) section. #### Prerequisites You will need to install the [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version) #### With WinGet You can install `bat` via [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget): ```bash winget install sharkdp.bat ``` #### With Chocolatey You can install `bat` via [Chocolatey](https://chocolatey.org/packages/Bat): ```bash choco install bat ``` #### With Scoop You can install `bat` via [scoop](https://scoop.sh/): ```bash scoop install bat ``` #### From prebuilt binaries: You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases), You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package. ### From binaries Check out the [Release page](https://github.com/sharkdp/bat/releases) for prebuilt versions of `bat` for many different architectures. Statically-linked binaries are also available: look for archives with `musl` in the file name. ### From source If you want to build `bat` from source, you need Rust 1.79.0 or higher. You can then use `cargo` to build everything: #### From local source ```bash cargo install --path . --locked ``` > [!NOTE] > The `--path .` above specifies the directory of the source code and NOT where `bat` will be installed. > For more information see the docs for [`cargo install`](https://doc.rust-lang.org/cargo/commands/cargo-install.html). #### From `crates.io` ```bash cargo install --locked bat ``` Note that additional files like the man page or shell completion files can not be installed automatically in both these ways. If installing from a local source, they will be generated by `cargo` and should be available in the cargo target folder under `build`. Furthermore, shell completions are also available by running: ```bash bat --completion # see --help for supported shells ``` ## Customization ### Highlighting theme Use `bat --list-themes` to get a list of all available themes for syntax highlighting. By default, `bat` uses `Monokai Extended` or `Monokai Extended Light` for dark and light themes respectively. To select the `TwoDark` theme, call `bat` with the `--theme=TwoDark` option or set the `BAT_THEME` environment variable to `TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to make the change permanent. Alternatively, use `bat`'s [configuration file](#configuration-file). If you want to preview the different themes on a custom file, you can use the following command (you need [`fzf`](https://github.com/junegunn/fzf) for this): ```bash bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" ``` `bat` automatically picks a fitting theme depending on your terminal's background color. You can use the `--theme-dark` / `--theme-light` options or the `BAT_THEME_DARK` / `BAT_THEME_LIGHT` environment variables to customize the themes used. This is especially useful if you frequently switch between dark and light mode. You can also use a custom theme by following the ['Adding new themes' section below](#adding-new-themes). ### 8-bit themes `bat` has three themes that always use [8-bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors), even when truecolor support is available: - `ansi` looks decent on any terminal. It uses 3-bit colors: black, red, green, yellow, blue, magenta, cyan, and white. - `base16` is designed for [base16](https://github.com/tinted-theming/home) terminal themes. It uses 4-bit colors (3-bit colors plus bright variants) in accordance with the [base16 styling guidelines](https://github.com/tinted-theming/home/blob/main/styling.md). - `base16-256` is designed for [tinted-shell](https://github.com/tinted-theming/tinted-shell). It replaces certain bright colors with 8-bit colors from 16 to 21. **Do not** use this simply because you have a 256-color terminal but are not using tinted-shell. Although these themes are more restricted, they have three advantages over truecolor themes. They: - Enjoy maximum compatibility. Some terminal utilities do not support more than 3-bit colors. - Adapt to terminal theme changes. Even for already printed output. - Visually harmonize better with other terminal software. ### Output style You can use the `--style` option to control the appearance of `bat`'s output. You can use `--style=numbers,changes`, for example, to show only Git changes and line numbers but no grid and no file header. Set the `BAT_STYLE` environment variable to make these changes permanent or use `bat`'s [configuration file](#configuration-file). >[!tip] > If you specify a default style in `bat`'s config file, you can change which components > are displayed during a single run of `bat` using the `--style` command-line argument. > By prefixing a component with `+` or `-`, it can be added or removed from the current style. > > For example, if your config contains `--style=full,-snip`, you can run bat with > `--style=-grid,+snip` to remove the grid and add back the `snip` component. > Or, if you want to override the styles completely, you use `--style=numbers` to > only show the line numbers. ### Decorations By default, `bat` only shows decorations (such as line numbers, file headers, grid borders, etc.) when outputting to an interactive terminal. You can control this behavior with the `--decorations` option. Use `--decorations=always` to show decorations even when piping output to another command, or `--decorations=never` to disable them entirely. Possible values are `auto` (default), `never`, and `always`. There is also the `--force-colorization` option, which is an alias for `--decorations=always --color=always`. This is useful if you want to keep colorization and decorations when piping `bat`'s output to another program. ### Adding new syntaxes / language definitions Should you find that a particular syntax is not available within `bat`, you can follow these instructions to easily add new syntaxes to your current `bat` installation. `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. A good resource for finding Sublime Syntax packages is [Package Control](https://packagecontrol.io/). Once you found a syntax: 1. Create a folder with syntax definition files: ```bash mkdir -p "$(bat --config-dir)/syntaxes" cd "$(bat --config-dir)/syntaxes" # Put new '.sublime-syntax' language definition files # in this folder (or its subdirectories), for example: git clone https://github.com/tellnobody1/sublime-purescript-syntax ``` 2. Now use the following command to parse these files into a binary cache: ```bash bat cache --build ``` 3. Finally, use `bat --list-languages` to check if the new languages are available. If you ever want to go back to the default settings, call: ```bash bat cache --clear ``` 4. If you think that a specific syntax should be included in `bat` by default, please consider opening a "syntax request" ticket after reading the policies and instructions [here](doc/assets.md): [Open Syntax Request](https://github.com/sharkdp/bat/issues/new?labels=syntax-request&template=syntax_request.md). ### Adding new themes This works very similar to how we add new syntax definitions. > [!NOTE] > Custom themes must be stored in [`.tmTheme` files](https://www.sublimetext.com/docs/color_schemes_tmtheme.html). > Newer `.sublime-color-scheme` files are currently not supported. First, create a folder with the new syntax highlighting themes: ```bash mkdir -p "$(bat --config-dir)/themes" cd "$(bat --config-dir)/themes" # Download a theme in '.tmTheme' format, for example: git clone https://github.com/greggb/sublime-snazzy # Update the binary cache bat cache --build ``` Finally, use `bat --list-themes` to check if the new themes are available. > [!NOTE] > `bat` uses the name of the `.tmTheme` file for the theme's name. ### Adding or changing file type associations You can add new (or change existing) file name patterns using the `--map-syntax` command line option. The option takes an argument of the form `pattern:syntax` where `pattern` is a glob pattern that is matched against the file name and the absolute file path. The `syntax` part is the full name of a supported language (use `bat --list-languages` for an overview). **Note:** You probably want to use this option as [an entry in `bat`'s configuration file](#configuration-file) for persistence instead of passing it on the command line as a one-off. Generally you'd just use `-l` if you want to manually specify a language for a file. Example: To use "INI" syntax highlighting for all files with a `.conf` file extension, use ```bash --map-syntax='*.conf:INI' ``` Example: To open all files called `.ignore` (exact match) with the "Git Ignore" syntax, use: ```bash --map-syntax='.ignore:Git Ignore' ``` Example: To open all `.conf` files in subfolders of `/etc/apache2` with the "Apache Conf" syntax, use (this mapping is already built in): ```bash --map-syntax='/etc/apache2/**/*.conf:Apache Conf' ``` ### 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. You can also use bat's built-in pager with `--pager=builtin` or by setting the `BAT_PAGER` environment variable to "builtin". 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`. >[!NOTE] > If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors. If you want to pass command-line arguments to the pager, you can also set them via the `PAGER`/`BAT_PAGER` variables: ```bash export BAT_PAGER="less -RFK" ``` Instead of using environment variables, you can also use `bat`'s [configuration file](#configuration-file) to configure the pager (`--pager` option). ### Using `less` as a pager When using `less` as a pager, `bat` will automatically pass extra options along to `less` to improve the experience. Specifically, `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen`, `-K`/`--quit-on-intr` and under certain conditions, `-X`/`--no-init` and/or `-S`/`--chop-long-lines`. >[!IMPORTANT] > These options will not be added if: > - The pager is not named `less`. > - The `--pager` argument contains any command-line arguments (e.g. `--pager="less -R"`). > - The `BAT_PAGER` environment variable contains any command-line arguments (e.g. `export BAT_PAGER="less -R"`) > > The `--quit-if-one-screen` option will not be added when: > - The `--paging=always` argument is used. > - The `BAT_PAGING` environment is set to `always`. The `-R`/`--RAW-CONTROL-CHARS` option is needed to interpret ANSI colors correctly. The `-F`/`--quit-if-one-screen` option instructs `less` to exit immediately if the output size is smaller than the vertical size of the terminal. This is convenient for small files because you do not have to press `q` to quit the pager. The `-K`/`--quit-on-intr` option instructs `less` to exit immediately when an interrupt signal is received. This is useful to ensure that `less` quits together with `bat` on SIGINT. The `-X`/`--no-init` option is added to versions of `less` older than version 530 (older than 558 on Windows) to fix a bug with the `-F`/`--quit-if-one-screen` feature. Unfortunately, it also breaks mouse-wheel support in `less`. If you want to enable mouse-wheel scrolling on older versions of `less` and do not mind losing the quit-if-one-screen feature, you can set the pager (via `--pager` or `BAT_PAGER`) to `less -R`. For `less` 530 or newer, it should work out of the box. The `-S`/`--chop-long-lines` option is added when `bat`'s `-S`/`--chop-long-lines` option is used. This tells `less` to truncate any lines larger than the terminal width. ### Indentation `bat` expands tabs to 4 spaces by itself, not relying on the pager. To change this, simply add the `--tabs` argument with the number of spaces you want to be displayed. **Note**: Defining tab stops for the pager (via the `--pager` argument by `bat`, or via the `LESS` environment variable for `less`) won't be taken into account because the pager will already get expanded spaces instead of tabs. This behaviour is added to avoid indentation issues caused by the sidebar. Calling `bat` with `--tabs=0` will override it and let tabs be consumed by the pager. ### Dark mode If you make use of the dark mode feature in **macOS**, you might want to configure `bat` to use a different theme based on the OS theme. The following snippet uses the `default` theme when in the _dark mode_ and the `GitHub` theme when in the _light mode_. ```bash alias cat="bat --theme auto:system --theme-dark default --theme-light GitHub" ``` The same dark mode feature is now available in **GNOME** and affects the `org.gnome.desktop.interface color-scheme` setting. The following code converts the above to use said setting. ```bash # .bashrc sys_color_scheme_is_dark() { condition=$(gsettings get org.gnome.desktop.interface color-scheme) condition=$(echo "$condition" | tr -d "[:space:]'") if [ $condition == "prefer-dark" ]; then return 0 else return 1 fi } bat_alias_wrapper() { #get color scheme sys_color_scheme_is_dark if [[ $? -eq 0 ]]; then # bat command with dark color scheme bat --theme=default "$@" else # bat command with light color scheme bat --theme=GitHub "$@" fi } alias cat='bat_alias_wrapper' ``` ## Configuration file `bat` can also be customized with a configuration file. The location of the file is dependent on your operating system. To get the default path for your system, call ```bash bat --config-file ``` Alternatively, you can use `BAT_CONFIG_PATH` or `BAT_CONFIG_DIR` environment variables to point `bat` to a non-default location of the configuration file or the configuration directory respectively: ```bash export BAT_CONFIG_PATH="/path/to/bat/bat.conf" export BAT_CONFIG_DIR="/path/to/bat" ``` A default configuration file can be created with the `--generate-config-file` option. ```bash bat --generate-config-file ``` There is also now a systemwide configuration file, which is located under `/etc/bat/config` on Linux and Mac OS and `C:\ProgramData\bat\config` on windows. If the system wide configuration file is present, the content of the user configuration will simply be appended to it. ### Format The configuration file is a simple list of command line arguments. Use `bat --help` to see a full list of possible options and values. In addition, you can add comments by prepending a line with the `#` character. Example configuration file: ```bash # Set the theme to "TwoDark" --theme="TwoDark" # Show line numbers, Git modifications and file header (but no grid) --style="numbers,changes,header" # Use italic text on the terminal (not supported on all terminals) --italic-text=always # Use C++ syntax for Arduino .ino files --map-syntax "*.ino:C++" ``` ## Using `bat` on Windows `bat` mostly works out-of-the-box on Windows, but a few features may need extra configuration. ### Prerequisites You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package. ### Paging 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). The [Chocolatey package](#on-windows) installs `less` automatically. ### Colors Windows 10 natively supports colors in both `conhost.exe` (Command Prompt) and PowerShell since [v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)), as well as in newer versions of bash. On earlier versions of Windows, you can use [Cmder](http://cmder.app/), which includes [ConEmu](https://conemu.github.io/). **Note:** Old versions of `less` do not correctly interpret colors on Windows. To fix this, you can add the optional Unix tools to your PATH when installing Git. If you don’t have any other pagers installed, you can disable paging entirely by passing `--paging=never` or by setting `BAT_PAGER` to an empty string. ### Cygwin `bat` on Windows does not natively support Cygwin's unix-style paths (`/cygdrive/*`). When passed an absolute cygwin path as an argument, `bat` will encounter the following error: `The system cannot find the path specified. (os error 3)` This can be solved by creating a wrapper or adding the following function to your `.bash_profile` file: ```bash bat() { local index local args=("$@") for index in $(seq 0 ${#args[@]}) ; do case "${args[index]}" in -*) continue;; *) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";; esac done command bat "${args[@]}" } ``` ## Troubleshooting ### Garbled output If an input file contains color codes or other ANSI escape sequences or control characters, `bat` will have problems performing syntax highlighting and text wrapping, and thus the output can become garbled. If your version of `bat` supports the `--strip-ansi=auto` option, it can be used to remove such sequences before syntax highlighting. Alternatively, you may disable both syntax highlighting and wrapping by passing the `--color=never --wrap=never` options to `bat`. > [!NOTE] > The `auto` option of `--strip-ansi` avoids removing escape sequences when the syntax is plain text. ### Terminals & colors `bat` handles terminals *with* and *without* truecolor support. However, the colors in most syntax highlighting themes are not optimized for 8-bit colors. It is therefore strongly recommended that you use a terminal with 24-bit truecolor support (`terminator`, `konsole`, `iTerm2`, ...), or use one of the basic [8-bit themes](#8-bit-themes) designed for a restricted set of colors. 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. ### File encodings `bat` natively supports UTF-8 as well as UTF-16. For every other file encoding, you may need to convert to UTF-8 first because the encodings can typically not be auto-detected. You can `iconv` to do so. Example: if you have a PHP file in Latin-1 (ISO-8859-1) encoding, you can call: ``` bash iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat ``` Note: you might have to use the `-l`/`--language` option if the syntax can not be auto-detected by `bat`. ## Development ```bash # Recursive clone to retrieve all submodules git clone --recursive https://github.com/sharkdp/bat # Build (debug version) cd bat cargo build --bins # Run unit tests and integration tests cargo test # Install (release version) cargo install --path . --locked # Build a bat binary with modified syntaxes and themes bash assets/create.sh cargo install --path . --locked --force ``` If you want to build an application that uses `bat`'s pretty-printing features as a library, check out the [the API documentation](https://docs.rs/bat/). Note that you have to use either `regex-onig` or `regex-fancy` as a feature when you depend on `bat` as a library. ## Contributing Take a look at the [`CONTRIBUTING.md`](CONTRIBUTING.md) guide. ## Maintainers - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) - [keith-hall](https://github.com/keith-hall) - [Enselic](https://github.com/Enselic) ## Security vulnerabilities See [`SECURITY.md`](SECURITY.md). ## 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. ## License Copyright (c) 2018-2025 [bat-developers](https://github.com/sharkdp/bat). `bat` is made available under the terms of either the MIT License or the Apache License 2.0, at your option. See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files for license details. ================================================ FILE: SECURITY.md ================================================ # Security Vulnerabilities To report a security vulnerability, please contact [David Peter](https://david-peter.de/) via email. ================================================ FILE: assets/.gitattributes ================================================ * linguist-vendored ================================================ FILE: assets/.ignore ================================================ syntaxes/* themes/* ================================================ FILE: assets/completions/_bat.ps1.in ================================================ using namespace System.Management.Automation using namespace System.Management.Automation.Language Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -ScriptBlock { param($wordToComplete, $commandAst, $cursorPosition) $ArrayStyle = @('default', 'auto', 'full', 'plain', 'changes', 'header', 'header-filename', 'header-filesize', 'grid', 'rule', 'numbers', 'snip') $ArrayCompletion = @('bash', 'fish', 'zsh', 'ps1') $ArrayWhen = @('auto', 'never', 'always') $ArrayYesNo = @('never', 'always') $ArrayWrap = @('always', 'never', 'character', 'word') $ArrayBinary = @('no-printing', 'as-text') $ArrayPrint = @('unicode', 'caret') function Get-MyThemes(){ $themes = {{PROJECT_EXECUTABLE}} --list-themes | ForEach-Object {$_ -replace "^(.*)$", '''$1'''} | select-object return $themes } function Get-MyLanguages(){ $themes = {{PROJECT_EXECUTABLE}} --list-languages | ForEach-Object{[pscustomobject]@{MyParameter=$_.Substring(0,$_.IndexOf(":")).Trim();MyDescription=$_.Substring($_.IndexOf(":")+1)}} | select-object return $themes } $commandElements = $commandAst.CommandElements $command = @( '{{PROJECT_EXECUTABLE}}' for ($i = 1; $i -lt $commandElements.Count; $i++) { $element = $commandElements[$i] if ($element -isnot [StringConstantExpressionAst] -or $element.StringConstantType -ne [StringConstantType]::BareWord -or #$element.Value.StartsWith('-') -or $element.Value -eq $wordToComplete) { break } $element.Value }) -join ';' $completions = @(switch -Wildcard ($command) { '*;--help' { break } '*;--version' { break } '*;--acknowledgements' { break } '*;--language' { Get-MyLanguages | ForEach-Object { $desc = if ($null -eq $_.MyDescription) { '_no value_' } else { $_.MyDescription } [CompletionResult]::new(($_.MyParameter -replace "^(.*)$", '''$1'''), $_.MyParameter, [CompletionResultType]::ParameterName, $desc) } break } '*;--theme' { Get-MyThemes | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterName, $_)} break } '*;--binary' { $ArrayBinary | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--style' { $ArrayStyle | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--wrap' { $ArrayWrap | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--color' { $ArrayWhen | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--italic-text' { $ArrayYesNo | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--paging' { $ArrayWhen | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--decorations' { $ArrayWhen | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--completion' { $ArrayCompletion | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--strip-ansi' { $ArrayWhen | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--nonprintable-notation' { $ArrayPrint | ForEach-Object {[System.Management.Automation.CompletionResult]::new($_, $_, [CompletionResultType]::ParameterValue, $_)} break } '*;--generate-config-file' { break } '{{PROJECT_EXECUTABLE}};cache' { [CompletionResult]::new('--source' , 'source' , [CompletionResultType]::ParameterName, 'Use a different directory to load syntaxes and themes from.') [CompletionResult]::new('--target' , 'target' , [CompletionResultType]::ParameterName, 'Use a different directory to store the cached syntax and theme set.') # [CompletionResult]::new('-b' , 'b' , [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.') [CompletionResult]::new('--build' , 'build' , [CompletionResultType]::ParameterName, 'Initialize (or update) the syntax/theme cache.') # [CompletionResult]::new('-c' , 'c' , [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.') [CompletionResult]::new('--clear' , 'clear' , [CompletionResultType]::ParameterName, 'Remove the cached syntax definitions and themes.') [CompletionResult]::new('--blank' , 'blank' , [CompletionResultType]::ParameterName, 'Create completely new syntax and theme sets (instead of appending to the default sets).') # [CompletionResult]::new('-h' , 'h' , [CompletionResultType]::ParameterName, 'Prints help information') [CompletionResult]::new('--help' , 'help' , [CompletionResultType]::ParameterName, 'Prints help information') # [CompletionResult]::new('-V' , 'V' , [CompletionResultType]::ParameterName, 'Prints version information') # [CompletionResult]::new('--version' , 'version' , [CompletionResultType]::ParameterName, 'Prints version information') break } default { # [CompletionResult]::new('-l' , 'l' , [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.') [CompletionResult]::new('--language' , 'language' , [CompletionResultType]::ParameterName, 'Set the language for syntax highlighting.') # [CompletionResult]::new('-H' , 'H' , [CompletionResultType]::ParameterName, 'Highlight lines N through M.') [CompletionResult]::new('--highlight-line' , 'highlight-line' , [CompletionResultType]::ParameterName, 'Highlight lines N through M.') [CompletionResult]::new('--file-name' , 'file-name' , [CompletionResultType]::ParameterName, 'Specify the name to display for a file.') [CompletionResult]::new('--diff-context' , 'diff-context' , [CompletionResultType]::ParameterName, 'diff-context') [CompletionResult]::new('--tabs' , 'tabs' , [CompletionResultType]::ParameterName, 'Set the tab width to T spaces.') [CompletionResult]::new('--wrap' , 'wrap' , [CompletionResultType]::ParameterName, 'Specify the text-wrapping mode (*auto*, never, character, word).') [CompletionResult]::new('--terminal-width' , 'terminal-width' , [CompletionResultType]::ParameterName, 'Explicitly set the width of the terminal instead of determining it automatically. If prefixed with ''+'' or ''-'', the value will be treated as an offset to the actual terminal width. See also: ''--wrap''.') [CompletionResult]::new('--color' , 'color' , [CompletionResultType]::ParameterName, 'When to use colors (*auto*, never, always).') [CompletionResult]::new('--italic-text' , 'italic-text' , [CompletionResultType]::ParameterName, 'Use italics in output (always, *never*)') [CompletionResult]::new('--decorations' , 'decorations' , [CompletionResultType]::ParameterName, 'When to show the decorations (*auto*, never, always).') [CompletionResult]::new('--paging' , 'paging' , [CompletionResultType]::ParameterName, 'Specify when to use the pager, or use ''-P'' to disable (*auto*, never, always).') [CompletionResult]::new('--pager' , 'pager' , [CompletionResultType]::ParameterName, 'Determine which pager to use.') # [CompletionResult]::new('-m' , 'm' , [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').') [CompletionResult]::new('--map-syntax' , 'map-syntax' , [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').') [CompletionResult]::new('--theme' , 'theme' , [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.') [CompletionResult]::new('--theme-dark' , 'themedark' , [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for dark backgrounds.') [CompletionResult]::new('--theme-light' , 'themelight' , [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for light backgrounds.') [CompletionResult]::new('--style' , 'style' , [CompletionResultType]::ParameterName, 'Comma-separated list of style elements to display (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).') # [CompletionResult]::new('-r' , 'r' , [CompletionResultType]::ParameterName, 'Only print the lines from N to M.') [CompletionResult]::new('--line-range' , 'line-range' , [CompletionResultType]::ParameterName, 'Only print the lines from N to M.') # [CompletionResult]::new('-A' , 'A' , [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).') [CompletionResult]::new('--show-all' , 'show-all' , [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).') [CompletionResult]::new('--nonprintable-notation' , 'nonprintable-notation' , [CompletionResultType]::ParameterName, 'Set notation for non-printable characters. (unicode, caret)') [CompletionResult]::new('--chop-long-lines' , 'chop-long-lines' , [CompletionResultType]::ParameterName, 'Truncate all lines longer than screen width. Alias for ''--wrap=never''.') [CompletionResult]::new('--binary' , 'binary' , [CompletionResultType]::ParameterName, 'How to treat binary content. (*no-printing*, as-text)') [CompletionResult]::new('--ignored-suffix' , 'ignored-suffix' , [CompletionResultType]::ParameterName, 'Ignore extension. For example: ''bat --ignored-suffix ".dev" my_file.json.dev'' will use JSON syntax, and ignore ''.dev''') [CompletionResult]::new('--squeeze-blank' , 'squeeze-blank' , [CompletionResultType]::ParameterName, 'Squeeze consecutive empty lines into a single empty line.') [CompletionResult]::new('--squeeze-limit' , 'squeeze-limit' , [CompletionResultType]::ParameterName, 'Set the maximum number of consecutive empty lines to be printed.') [CompletionResult]::new('--strip-ansi' , 'strip-ansi' , [CompletionResultType]::ParameterName, 'Specify when to strip ANSI escape sequences from the input. The automatic mode will remove escape sequences unless the syntax highlighting language is plain text. (auto, always, *never*).') # [CompletionResult]::new('-p' , 'p' , [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').') [CompletionResult]::new('--plain' , 'plain' , [CompletionResultType]::ParameterName, 'Show plain style (alias for ''--style=plain'').') # [CompletionResult]::new('-d' , 'd' , [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.') [CompletionResult]::new('--diff' , 'diff' , [CompletionResultType]::ParameterName, 'Only show lines that have been added/removed/modified.') # [CompletionResult]::new('-n' , 'n' , [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').') [CompletionResult]::new('--number' , 'number' , [CompletionResultType]::ParameterName, 'Show line numbers (alias for ''--style=numbers'').') # [CompletionResult]::new('-f' , 'f' , [CompletionResultType]::ParameterName, 'f') [CompletionResult]::new('--force-colorization' , 'force-colorization' , [CompletionResultType]::ParameterName, 'force-colorization') # [CompletionResult]::new('-P' , 'P' , [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''') [CompletionResult]::new('--no-paging' , 'no-paging' , [CompletionResultType]::ParameterName, 'Alias for ''--paging=never''') [CompletionResult]::new('--list-themes' , 'list-themes' , [CompletionResultType]::ParameterName, 'Display all supported highlighting themes.') # [CompletionResult]::new('-L' , 'L' , [CompletionResultType]::ParameterName, 'Display all supported languages.') [CompletionResult]::new('--list-languages' , 'list-languages' , [CompletionResultType]::ParameterName, 'Display all supported languages.') # [CompletionResult]::new('-u' , 'u' , [CompletionResultType]::ParameterName, 'u') [CompletionResult]::new('--unbuffered' , 'unbuffered' , [CompletionResultType]::ParameterName, 'Enable unbuffered input reading for streaming use cases') [CompletionResult]::new('--completion' , 'completion' , [CompletionResultType]::ParameterName, 'Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]') [CompletionResult]::new('--no-config' , 'no-config' , [CompletionResultType]::ParameterName, 'Do not use the configuration file') [CompletionResult]::new('--no-custom-assets' , 'no-custom-assets' , [CompletionResultType]::ParameterName, 'Do not load custom assets') [CompletionResult]::new('--lessopen' , 'lessopen' , [CompletionResultType]::ParameterName, 'Enable the $LESSOPEN preprocessor') [CompletionResult]::new('--no-lessopen' , 'no-lessopen' , [CompletionResultType]::ParameterName, 'Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)') [CompletionResult]::new('--config-file' , 'config-file' , [CompletionResultType]::ParameterName, 'Show path to the configuration file.') [CompletionResult]::new('--generate-config-file' , 'generate-config-file' , [CompletionResultType]::ParameterName, 'Generates a default configuration file.') [CompletionResult]::new('--config-dir' , 'config-dir' , [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.') [CompletionResult]::new('--cache-dir' , 'cache-dir' , [CompletionResultType]::ParameterName, 'Show bat''s cache directory.') [CompletionResult]::new('--acknowledgements' , 'acknowledgements' , [CompletionResultType]::ParameterName, 'Show acknowledgements.') [CompletionResult]::new('--set-terminal-title' , 'set-terminal-title' , [CompletionResultType]::ParameterName, 'Sets terminal title to filenames when using a pager.') [CompletionResult]::new('--diagnostic' , 'diagnostic' , [CompletionResultType]::ParameterName, 'Show diagnostic information for bug reports.') [CompletionResult]::new('--quiet-empty' , 'quiet-empty' , [CompletionResultType]::ParameterName, 'Do not produce any output when the input is empty.') # [CompletionResult]::new('-h' , 'h' , [CompletionResultType]::ParameterName, 'Print this help message.') [CompletionResult]::new('--help' , 'help' , [CompletionResultType]::ParameterName, 'Print this help message.') # [CompletionResult]::new('-V' , 'V' , [CompletionResultType]::ParameterName, 'Show version information.') [CompletionResult]::new('--version' , 'version' , [CompletionResultType]::ParameterName, 'Show version information.') break } }) $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | Sort-Object -Property CompletionText } ================================================ FILE: assets/completions/bat.bash.in ================================================ # shellcheck disable=SC2207 # Requires https://github.com/scop/bash-completion # Macs have bash3 for which the bash-completion package doesn't include # _init_completion. This is a minimal version of that function. __bat_init_completion() { COMPREPLY=() _get_comp_words_by_ref "$@" cur prev words cword } __bat_escape_completions() { # Do not escape if completing a quoted value. [[ $cur == [\"\']* ]] && return 0 if (( BASH_VERSINFO[0] > 5 || \ BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3 )); then # bash >= 5.3 has "compopt -o fullquote", which exactly does # what this function tries to do. compopt -o fullquote elif (( BASH_VERSINFO[0] > 4 || \ BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] > 0 )); then # printf -v to an array index is available in bash >= 4.1. # Use it if available, as -o filenames is semantically # incorrect if we are not actually completing filenames, and it # has side effects (e.g. adds trailing slash to candidates # matching present dirs). local i for i in ${!COMPREPLY[*]}; do printf -v "COMPREPLY[i]" %q "${COMPREPLY[i]}" done # We can use "compopt -o noquote" available in bash >= 4.3 to # prevent further quoting by the shell, which would be # unexpectedly applied when a quoted result matches a filename. if (( BASH_VERSINFO[0] > 4 || \ BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3 )); then compopt -o noquote fi else compopt -o filenames fi } _bat() { local cur prev words split=false if declare -F _init_completion >/dev/null 2>&1; then _init_completion -s || return 0 else __bat_init_completion -n "=" || return 0 _split_longopt && split=true fi if [[ ${words[1]-} == cache ]]; then case $prev in --source | --target) _filedir -d return 0 ;; esac COMPREPLY=($(compgen -W " --build --clear --source --target --blank --help " -- "$cur")) return 0 fi case $prev in -l | --language) local IFS=$'\n' COMPREPLY=($(compgen -W "$( "$1" --list-languages | while IFS=: read -r lang _; do printf "%s\n" "$lang" done )" -- "$cur")) __bat_escape_completions return 0 ;; -H | --highlight-line | \ --diff-context | \ --tabs | \ --terminal-width | \ -m | --map-syntax | \ --ignored-suffix | \ --list-themes | \ --squeeze-limit | \ --line-range | \ -L | --list-languages | \ --lessopen | \ --no-paging | \ --diagnostic | \ --quiet-empty | \ --acknowledgements | \ -h | --help | \ -V | --version | \ --cache-dir | \ --config-dir | \ --config-file | \ --generate-config-file) # argument required but no completion available, or option # causes an exit return 0 ;; --file-name) _filedir return 0 ;; --wrap) COMPREPLY=($(compgen -W "auto never character word" -- "$cur")) return 0 ;; --binary) COMPREPLY=($(compgen -W "no-printing as-text" -- "$cur")) return 0 ;; --nonprintable-notation) COMPREPLY=($(compgen -W "unicode caret" -- "$cur")) return 0 ;; --strip-ansi) COMPREPLY=($(compgen -W "auto never always" -- "$cur")) return 0 ;; --completion) COMPREPLY=($(compgen -W "bash fish zsh ps1" -- "$cur")) return 0 ;; --color | --decorations | --paging) COMPREPLY=($(compgen -W "auto never always" -- "$cur")) return 0 ;; --italic-text) COMPREPLY=($(compgen -W "always never" -- "$cur")) return 0 ;; --pager) COMPREPLY=($(compgen -c -- "$cur")) return 0 ;; --theme) local IFS=$'\n' COMPREPLY=($(compgen -W "auto${IFS}auto:always${IFS}auto:system${IFS}dark${IFS}light${IFS}$("$1" --list-themes)" -- "$cur")) __bat_escape_completions return 0 ;; --theme-dark | \ --theme-light) local IFS=$'\n' COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur")) __bat_escape_completions return 0 ;; --style) # shellcheck disable=SC2034 local -a styles=( default full auto plain changes header header-filename header-filesize grid rule numbers snip ) # shellcheck disable=SC2016 if declare -F _comp_delimited >/dev/null 2>&1; then # bash-completion > 2.11 _comp_delimited , -W '"${styles[@]}"' else COMPREPLY=($(compgen -W '${styles[@]}' -- "$cur")) fi return 0 esac $split && return 0 if [[ $cur == -* ]]; then COMPREPLY=($(compgen -W " --unbuffered --show-all --nonprintable-notation --binary --plain --language --highlight-line --file-name --diff --diff-context --tabs --wrap --chop-long-lines --terminal-width --number --color --italic-text --decorations --force-colorization --paging --no-paging --pager --map-syntax --ignored-suffix --theme --theme-dark --theme-light --list-themes --squeeze-blank --squeeze-limit --strip-ansi --style --line-range --list-languages --lessopen --completion --diagnostic --quiet-empty --acknowledgements --set-terminal-title --help --version --cache-dir --config-dir --config-file --generate-config-file --no-config --no-custom-assets --no-lessopen " -- "$cur")) return 0 fi _filedir ## Completion of the 'cache' command itself is removed for better UX ## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802 } && complete -F _bat {{PROJECT_EXECUTABLE}} ================================================ FILE: assets/completions/bat.fish.in ================================================ # Fish Shell Completions # Copy or symlink to $XDG_CONFIG_HOME/fish/completions/{{PROJECT_EXECUTABLE}}.fish # ($XDG_CONFIG_HOME is usually set to ~/.config) # `bat` is `batcat` on Debian and Ubuntu set bat {{PROJECT_EXECUTABLE}} # Helper functions: function __bat_complete_files -a token # Cheat to complete files by calling `complete -C` on a fake command name, # like `__fish_complete_directories` does. set -l fake_command aaabccccdeeeeefffffffffgghhhhhhiiiii complete -C"$fake_command $token" end function __bat_complete_one_language -a comp command $bat --list-languages | string split -f1 : | string match -e "$comp" end function __bat_complete_list_languages for spec in (command $bat --list-languages) set -l name (string split -f1 : $spec) for ext in (string split -f2 : $spec | string split ,) test -n "$ext"; or continue string match -rq '[/*]' $ext; and continue printf "%s\t%s\n" $ext $name end printf "%s\t\n" $name end end function __bat_complete_map_syntax set -l token (commandline -ct) if string match -qr '(?.+):(?.*)' -- $token # If token ends with a colon, complete with the list of language names. set -f comps $glob:(__bat_complete_one_language $syntax) else if string match -qr '\*' -- $token # If token contains a globbing character (`*`), complete only possible # globs in the current directory set -f comps (__bat_complete_files $token | string match -er '[*]'): else # Complete files (and globs). set -f comps (__bat_complete_files $token | string match -erv '/$'): end if set -q comps[1] printf "%s\t\n" $comps end end function __bat_cache_subcommand __fish_seen_subcommand_from cache end # Returns true if no exclusive arguments seen. function __bat_no_excl_args not __bat_cache_subcommand; and not __fish_seen_argument \ -s h -l help \ -s V -l version \ -l acknowledgements \ -l config-dir -l config-file \ -l diagnostic -l quiet-empty \ -l list-languages -l list-themes end # Returns true if the 'cache' subcommand is seen without any exclusive arguments. function __bat_cache_no_excl __bat_cache_subcommand; and not __fish_seen_argument \ -s h -l help \ -l acknowledgements -l build -l clear end function __bat_style_opts set -l style_opts \ "default,recommended components" \ "auto,same as 'default' unless piped" \ "full,all components" \ "plain,no components" \ "changes,Git change markers" \ "header,alias for header-filename" \ "header-filename,filename above content" \ "header-filesize,filesize above content" \ "grid,lines b/w sidebar/header/content" \ "numbers,line numbers in sidebar" \ "rule,separate files" \ "snip,separate ranges" string replace , \t $style_opts end # Use option argument descriptions to indicate which is the default, saving # horizontal space and making sure the option description isn't truncated. set -l color_opts ' auto\tdefault never\t always\t ' set -l decorations_opts $color_opts set -l paging_opts $color_opts # Include some examples so we can indicate the default. set -l pager_opts ' less\tdefault less\ -FR\t more\t vimpager\t builtin\t ' set -l italic_text_opts ' always\t never\tdefault ' set -l wrap_opts ' auto\tdefault never\t character\t word\t ' # While --tabs theoretically takes any number, most people should be OK with these. # Specifying a list lets us explain what 0 does. set -l tabs_opts ' 0\tpass\ tabs\ through\ directly 1\t 2\t 4\t 8\t ' set -l special_themes ' auto\tdefault,\ Choose\ a\ theme\ based\ on\ dark\ or\ light\ mode auto:always\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode auto:system\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode dark\tUse\ the\ theme\ specified\ by\ --theme-dark light\tUse\ the\ theme\ specified\ by\ --theme-light ' # Completions: complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg complete -c $bat -l binary -x -a "no-printing as-text" -d "How to treat binary content" -n __bat_no_excl_args complete -c $bat -l cache-dir -f -d "Show bat's cache directory" -n __fish_is_first_arg complete -c $bat -s c -l chop-long-lines -d "Truncate all lines longer than screen width" -n __bat_no_excl_args complete -c $bat -l color -x -a "$color_opts" -d "When to use colored output" -n __bat_no_excl_args complete -c $bat -l completion -x -a "bash fish zsh ps1" -d "Show shell completion for a certain shell" -n __fish_is_first_arg complete -c $bat -l config-dir -f -d "Display location of configuration directory" -n __fish_is_first_arg complete -c $bat -l config-file -f -d "Display location of configuration file" -n __fish_is_first_arg complete -c $bat -l decorations -x -a "$decorations_opts" -d "When to use --style decorations" -n __bat_no_excl_args complete -c $bat -l diagnostic -d "Print diagnostic info for bug reports" -n __fish_is_first_arg complete -c $bat -l quiet-empty -d "Do not produce any output when the input is empty" -n __fish_is_first_arg complete -c $bat -s d -l diff -d "Only show lines with Git changes" -n __bat_no_excl_args complete -c $bat -l diff-context -x -d "Show N context lines around Git changes" -n "__fish_seen_argument -s d -l diff" complete -c $bat -l generate-config-file -f -d "Generates a default configuration file" -n __fish_is_first_arg complete -c $bat -l file-name -x -d "Specify the display name" -n __bat_no_excl_args complete -c $bat -s f -l force-colorization -d "Force color and decorations" -n __bat_no_excl_args complete -c $bat -s h -d "Print a concise overview" -n __fish_is_first_arg complete -c $bat -l help -f -d "Print all help information" -n __fish_is_first_arg complete -c $bat -s H -l highlight-line -x -d "Highlight line(s) N[:M]" -n __bat_no_excl_args complete -c $bat -l ignored-suffix -x -d "Ignore extension" -n __bat_no_excl_args complete -c $bat -l italic-text -x -a "$italic_text_opts" -d "When to use italic text in the output" -n __bat_no_excl_args complete -c $bat -s l -l language -x -k -a "(__bat_complete_list_languages)" -d "Set the syntax highlighting language" -n __bat_no_excl_args complete -c $bat -l lessopen -d "Enable the $LESSOPEN preprocessor" -n __fish_is_first_arg complete -c $bat -s r -l line-range -x -d "Only print lines [M]:[N] (either optional)" -n __bat_no_excl_args complete -c $bat -l list-languages -f -d "List syntax highlighting languages" -n __fish_is_first_arg complete -c $bat -l list-themes -f -d "List syntax highlighting themes" -n __fish_is_first_arg complete -c $bat -s m -l map-syntax -x -a "(__bat_complete_map_syntax)" -d "Map :" -n __bat_no_excl_args complete -c $bat -l no-config -d "Do not use the configuration file" complete -c $bat -l no-custom-assets -d "Do not load custom assets" complete -c $bat -l no-lessopen -d "Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)" complete -c $bat -l nonprintable-notation -x -a "unicode caret" -d "Set notation for non-printable characters" -n __bat_no_excl_args complete -c $bat -s n -l number -d "Only show line numbers, no other decorations" -n __bat_no_excl_args complete -c $bat -l no-paging -d "Alias for --paging=never" -n __bat_no_excl_args complete -c $bat -l pager -x -a "$pager_opts" -d "Which pager to use" -n __bat_no_excl_args complete -c $bat -l paging -x -a "$paging_opts" -d "When to use the pager" -n __bat_no_excl_args complete -c $bat -s p -l plain -d "Show plain style" -n __bat_no_excl_args complete -c $bat -l set-terminal-title -d "Sets terminal title to filenames when using a pager" -n __bat_no_excl_args complete -c $bat -s A -l show-all -d "Show non-printable characters" -n __bat_no_excl_args complete -c $bat -s s -l squeeze-blank -d "Squeeze consecutive empty lines into a single empty line" -n __bat_no_excl_args complete -c $bat -l squeeze-limit -x -d "Set the maximum number of consecutive empty lines to be printed" -n __bat_no_excl_args complete -c $bat -l strip-ansi -x -a "auto never always" -d "Specify when to strip ANSI escape sequences from the input" -n __bat_no_excl_args complete -c $bat -s p -l plain -d "Disable decorations" -n __bat_no_excl_args complete -c $bat -o pp -d "Disable decorations and paging" -n __bat_no_excl_args complete -c $bat -s P -d "Disable paging" -n __bat_no_excl_args complete -c $bat -l style -x -k -a "(__fish_complete_list , __bat_style_opts)" -d "Specify which non-content elements to display" -n __bat_no_excl_args complete -c $bat -l tabs -x -a "$tabs_opts" -d "Set tab width" -n __bat_no_excl_args complete -c $bat -l terminal-width -x -d "Set terminal , +, or -" -n __bat_no_excl_args complete -c $bat -l theme -x -a "$special_themes(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args complete -c $bat -l theme-dark -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for dark backgrounds" -n __bat_no_excl_args complete -c $bat -l theme-light -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for light backgrounds" -n __bat_no_excl_args complete -c $bat -s u -l unbuffered -d "Enable unbuffered input reading for streaming use cases" -n __bat_no_excl_args complete -c $bat -s V -l version -f -d "Show version information" -n __fish_is_first_arg complete -c $bat -l wrap -x -a "$wrap_opts" -d "Text-wrapping mode" -n __bat_no_excl_args # Sub-command 'cache' completions ## Completion of the 'cache' command itself is removed for better UX ## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802 complete -c $bat -l build -f -d "Parse new definitions into cache" -n __bat_cache_no_excl complete -c $bat -l clear -f -d "Reset definitions to defaults" -n __bat_cache_no_excl complete -c $bat -l blank -f -d "Create new data instead of appending" -n "__bat_cache_subcommand; and not __fish_seen_argument -l clear" complete -c $bat -l source -x -a "(__fish_complete_directories)" -d "Load syntaxes and themes from DIR" -n "__bat_cache_subcommand; and not __fish_seen_argument -l clear" complete -c $bat -l target -x -a "(__fish_complete_directories)" -d "Store cache in DIR" -n __bat_cache_subcommand complete -c $bat -l acknowledgements -d "Build acknowledgements.bin" -n __bat_cache_no_excl complete -c $bat -s h -d "Print a concise overview of $bat-cache help" -n __bat_cache_no_excl complete -c $bat -l help -f -d "Print all $bat-cache help" -n __bat_cache_no_excl # vim:ft=fish ================================================ FILE: assets/completions/bat.zsh.in ================================================ #compdef {{PROJECT_EXECUTABLE}} local curcontext="$curcontext" ret=1 local -a state state_descr line typeset -A opt_args (( $+functions[_{{PROJECT_EXECUTABLE}}_cache_subcommand] )) || _{{PROJECT_EXECUTABLE}}_cache_subcommand() { local -a args args=( '(-b --build -c --clear)'{-b,--build}'[initialize or update the syntax/theme cache]' '(-b --build -c --clear)'{-c,--clear}'[remove the cached syntax definitions and themes]' --source='[specify directory to load syntaxes and themes from]:directory:_files -/' --target='[specify directory to store the cached syntax and theme set in]:directory:_files -/' --blank'[create completely new syntax and theme sets]' --acknowledgements'[build acknowledgements.bin]' '(: -)'{-h,--help}'[show help information]' ) _arguments -S -s $args } (( $+functions[_{{PROJECT_EXECUTABLE}}_main] )) || _{{PROJECT_EXECUTABLE}}_main() { local -a args args=( '(-A --show-all)'{-A,--show-all}'[show non-printable characters (space, tab, newline, ..)]' --nonprintable-notation='[specify how to display non-printable characters when using --show-all]:notation:(caret unicode)' --binary='[specify how to treat binary content]:behavior:(no-printing as-text)' \*{-p,--plain}'[show plain style (alias for `--style=plain`), repeat twice to disable automatic paging (alias for `--paging=never`)]' '(-l --language)'{-l+,--language=}'[set the language for syntax highlighting]:language:->languages' \*{-H+,--highlight-line=}'[highlight specified block of lines]:start\:end' \*--file-name='[specify the name to display for a file]:name:_files' '(-d --diff)'--diff'[only show lines that have been added/removed/modified]' --diff-context='[specify lines of context around added/removed/modified lines when using `--diff`]:lines' --tabs='[set the tab width]:tab width [4]' --wrap='[specify the text-wrapping mode]:mode [auto]:(auto never character word)' '!(--wrap)'{-S,--chop-long-lines} --terminal-width='[explicitly set the width of the terminal instead of determining it automatically]:width' '(-n --number --diff --diff-context)'{-n,--number}'[show line numbers]' --color='[specify when to use colors]:when:(auto never always)' --italic-text='[use italics in output]:when:(always never)' --decorations='[specify when to show the decorations]:when:(auto never always)' '(-f --force-colorization)'--force-colorization'[force colorization and decorations]' --paging='[specify when to use the pager]:when:(auto never always)' '(-P --no-paging)'--no-paging'[alias for --paging=never]' --pager='[determine which pager to use]:command:' '(-m --map-syntax)'{-m+,--map-syntax=}'[map a glob pattern to an existing syntax name]: :->syntax-maps' --ignored-suffix='[ignore extension]:suffix:' '(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->theme_preferences' '(--theme-dark)'--theme-dark='[set the color theme for syntax highlighting for dark backgrounds]:theme:->themes' '(--theme-light)'--theme-light='[set the color theme for syntax highlighting for light backgrounds]:theme:->themes' '(: --list-themes --list-languages -L)'--list-themes'[show all supported highlighting themes]' --squeeze-blank'[squeeze consecutive empty lines into a single empty line]' --squeeze-limit='[set the maximum number of consecutive empty lines]:limit:' --strip-ansi='[specify when to strip ANSI escape sequences]:when:(auto never always)' --style='[comma-separated list of style elements to display]: : _values "style [default]" default auto full plain changes header header-filename header-filesize grid rule numbers snip' \*{-r+,--line-range=}'[only print the specified line range]:start\:end' '(* -)'{-L,--list-languages}'[display all supported languages]' '(-u --unbuffered)'--unbuffered'[enable unbuffered input reading for streaming use cases]' --completion='[show shell completion for a certain shell]:shell:(bash fish zsh ps1)' --set-terminal-title'[sets terminal title to filenames when using a pager]' --diagnostic'[show diagnostic information for bug reports]' --quiet-empty'[do not produce any output when the input is empty]' -P'[disable paging]' "--no-config[don't use the configuration file]" "--no-custom-assets[don't load custom assets]" '(--no-lessopen)'--lessopen'[enable the $LESSOPEN preprocessor]' '(--lessopen)'--no-lessopen'[disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)]' '(* -)'--config-dir"[show bat's configuration directory]" '(* -)'--config-file'[show path to the configuration file]' '(* -)'--generate-config-file'[generate a default configuration file]' '(* -)'--cache-dir"[show bat's cache directory]" '(* -)'{-h,--help}'[show help information]' '(* -)'{-V,--version}'[show version information]' '*: :{ _files || compadd cache }' ) _arguments -S -s $args && ret=0 case "$state" in syntax-maps) if ! compset -P '*:'; then _message -e patterns 'glob pattern:language' return fi ;& # fall-through languages) local IFS=$'\n' local -a languages languages=( $({{PROJECT_EXECUTABLE}} --list-languages | awk -F':|,' '{ for (i = 1; i <= NF; ++i) printf("%s:%s\n", $i, $1) }') ) _describe 'language' languages && ret=0 ;; themes) local -a themes expl themes=(${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} ) _wanted themes expl 'theme' compadd -a themes && ret=0 ;; theme_preferences) local -a themes expl themes=(auto dark light auto:always auto:system ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} ) _wanted themes expl 'theme' compadd -a themes && ret=0 ;; esac return ret } case $words[2] in cache) ## Completion of the 'cache' command itself is removed for better UX ## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802 shift words (( CURRENT-- )) curcontext="${curcontext%:*}-${words[1]}:" _{{PROJECT_EXECUTABLE}}_cache_subcommand ;; *) _{{PROJECT_EXECUTABLE}}_main ;; esac ================================================ FILE: assets/create.sh ================================================ #!/usr/bin/env bash set -euo pipefail ASSET_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" REPO_DIR="$ASSET_DIR/.." # Ensure submodules are initialized. update_submodules() { local submodule local submodule_prompt=unspecified local submodule_path { while { read -r submodule && read -r submodule_path; } <&3; do if ! [[ -d "${REPO_DIR}/.git/modules/${submodule}" ]] && [[ -d "${REPO_DIR}/${submodule_path}" ]]; then if [[ "$submodule_prompt" = "unspecified" ]]; then echo "One or more submodules were found to be uninitialized." printf "Initialize and update them? [Y/n] " read -r submodule_prompt fi case "$submodule_prompt" in y|yes|'') { git -C "$REPO_DIR" submodule update --init "$submodule_path" };; n|no) { return };; *) { echo "Unknown answer. Not updating submodules." };; esac fi done } 3< <(git config --file "${REPO_DIR}/.gitmodules" --null --get-regexp path | xargs -0 printf "%s\n" | sed 's/^submodule.//;s/.path$//') } if [ -t 0 ]; then update_submodules fi # Always remove the local cache to avoid any confusion bat cache --clear # TODO: # - Remove the JavaDoc patch once https://github.com/trishume/syntect/issues/222 has been fixed # - Remove the C# patch once https://github.com/sublimehq/Packages/pull/2331 has been merged # Apply patches ( cd "$ASSET_DIR" for patch in patches/*.patch; do patch --strip=0 < "$patch" done ) reverse_patches() { ( cd "$ASSET_DIR" for patch in patches/*.patch; do patch --strip=0 --reverse <"$patch" done ) } # Make sure to always reverse patches, even if the `bat cache` command fails or aborts trap reverse_patches EXIT bat cache --build --blank --acknowledgements --source="$ASSET_DIR" --target="$ASSET_DIR" ================================================ FILE: assets/manual/bat.1.in ================================================ .TH {{PROJECT_EXECUTABLE_UPPERCASE}} "1" .SH NAME {{PROJECT_EXECUTABLE}} \- a cat(1) clone with syntax highlighting and Git integration. .SH "USAGE" .IP "{{PROJECT_EXECUTABLE}} [OPTIONS] [FILE]..." .IP "{{PROJECT_EXECUTABLE}} cache [CACHE-OPTIONS] [--build|--clear] .SH DESCRIPTION {{PROJECT_EXECUTABLE}} prints the syntax-highlighted content of a collection of FILEs to the terminal. If no FILE is specified, or when FILE is '-', it reads from standard input. {{PROJECT_EXECUTABLE}} supports a large number of programming and markup languages. It also communicates with git(1) to show modifications with respect to the git index. {{PROJECT_EXECUTABLE}} automatically pipes its output through a pager (by default: less). Whenever the output of {{PROJECT_EXECUTABLE}} goes to a non-interactive terminal, i.e. when the output is piped into another process or into a file, {{PROJECT_EXECUTABLE}} will act as a drop-in replacement for cat(1) and fall back to printing the plain file contents, unless an explicit style is requested. .SH "OPTIONS" General remarks: Command-line options like '-l'/'--language' that take values can be specified as either '--language value', '--language=value', '-l value' or '-lvalue'. .HP \fB\-A\fR, \fB\-\-show\-all\fR .IP Show non\-printable characters like space, tab or newline. Use '\-\-tabs' to control the width of the tab\-placeholders. .HP \fB\-\-nonprintable\-notation\fR .IP Specify how to display non-printable characters when using \-\-show\-all. Possible values: .RS .IP "caret" Use character sequences like ^G, ^J, ^@, .. to identify non-printable characters .IP "unicode" Use special Unicode code points to identify non-printable characters .RE .HP \fB\-\-binary\fR .IP How to treat binary content. Possible values: .RS .IP "no\-printing" Do not print any binary content (default) .IP "as\-text" Treat binary content as normal text .RE .HP \fB\-\-completion\fR .IP Show shell completion for a certain shell. Possible values: bash, fish, zsh, ps1 .HP \fB\-p\fR, \fB\-\-plain\fR .IP Only show plain style, no decorations. This is an alias for \&'\-\-style=plain'. When '\-p' is used twice ('\-pp'), it also disables automatic paging (alias for '\-\-style=plain \fB\-\-paging\fR=\fI\,never\/\fR'). .HP \fB\-l\fR, \fB\-\-language\fR .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\-H\fR, \fB\-\-highlight\-line\fR ... .IP Highlight the specified line ranges with a different background color. For example: .RS .IP "\-\-highlight\-line 40" highlights line 40 .IP "\-\-highlight\-line 30:40" highlights lines 30 to 40 .IP "\-\-highlight\-line :40" highlights lines 1 to 40 .IP "\-\-highlight\-line 40:" highlights lines 40 to the end of the file .IP "\-\-highlight\-line 30:+10" highlights lines 30 to 40 .RE .HP \fB\-\-file\-name\fR ... .IP Specify the name to display for a file. Useful when piping data to {{PROJECT_EXECUTABLE}} from STDIN when {{PROJECT_EXECUTABLE}} does not otherwise know the filename. Note that the provided file name is also used for syntax detection. .HP \fB\-d\fR, \fB\-\-diff\fR .IP Only show lines that have been added/removed/modified with respect to the Git index. Use '\-\-diff\-context=N' to control how much context you want to see. .HP \fB\-\-diff\-context\fR ... .IP Include N lines of context around added/removed/modified lines when using '\-\-diff'. .HP \fB\-\-tabs\fR .IP Set the tab width to T spaces. Use a width of 0 to pass tabs through directly .HP \fB\-\-wrap\fR .IP Specify the text\-wrapping mode (*auto*, never, character, word). The '\-\-terminal\-width' option can be used in addition to control the output width. In \fBword\fR mode, lines are broken at whitespace boundaries. If a single word exceeds the terminal width, it falls back to character wrapping. .HP \fB\-S\fR, \fB\-\-chop\-long\-lines\fR .IP Truncate all lines longer than screen width. Alias for '\-\-wrap=never'. .HP \fB\-\-terminal\-width\fR .IP Explicitly set the width of the terminal instead of determining it automatically. If prefixed with '+' or '\-', the value will be treated as an offset to the actual terminal width. See also: '\-\-wrap'. .HP \fB\-n\fR, \fB\-\-number\fR .IP Only show line numbers, no other decorations. This is an alias for '\-\-style=numbers' .HP \fB\-\-color\fR .IP Specify when to use colored output. The automatic mode only enables colors if an interactive terminal is detected. Possible values: *auto*, never, always. .HP \fB\-\-italic\-text\fR .IP Specify when to use ANSI sequences for italic text in the output. Possible values: always, *never*. .HP \fB\-\-decorations\fR .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. The always mode will show decorations even when piping output. Possible values: *auto*, never, always. .HP \fB\-f\fR, \fB\-\-force\-colorization\fR .IP Alias for '--decorations=always --color=always'. This is useful \ if the output of {{PROJECT_EXECUTABLE}} is piped to another program, but you want \ to keep the colorization/decorations. .HP \fB\-\-paging\fR .IP Specify when to use the pager. To disable the pager, use \&'\-\-paging=never' or its alias, \fB-P\fR. To disable the pager permanently, set BAT_PAGER to an empty string. To control which pager is used, see the '\-\-pager' option. Possible values: *auto*, never, always. .HP \fB\-\-pager\fR .IP Determine which pager is used. This option will override the PAGER and BAT_PAGER environment variables. The default pager is 'less'. If you provide '\-\-pager=builtin', use the built-in 'minus' pager. To control when the pager is used, see the '\-\-paging' option. Example: '\-\-pager "less \fB\-RF\fR"'. Note: By default, if the pager is set to 'less' (and no command-line options are specified), 'bat' will pass the following command line options to the pager: '-R'/'--RAW-CONTROL-CHARS', '-F'/'--quit-if-one-screen' and '-X'/'--no-init'. The last option ('-X') is only used for 'less' versions older than 530. The '-R' option is needed to interpret ANSI colors correctly. The second option ('-F') instructs less to exit immediately if the output size is smaller than the vertical size of the terminal. This is convenient for small files because you do not have to press 'q' to quit the pager. The third option ('-X') is needed to fix a bug with the '--quit-if-one-screen' feature in old versions of 'less'. Unfortunately, it also breaks mouse-wheel support in 'less'. If you want to enable mouse-wheel scrolling on older versions of 'less', you can pass just '-R' (as in the example above, this will disable the quit-if-one-screen feature). For less 530 or newer, it should work out of the box. .HP \fB\-m\fR, \fB\-\-map\-syntax\fR ... .IP Map a glob pattern to an existing syntax name. The glob pattern is matched on the full path and the filename. For example, to highlight *.build files with the Python syntax, use -m '*.build:Python'. To highlight files named '.myignore' with the Git Ignore syntax, use -m '.myignore:Git Ignore'. Note that the right-hand side is the *name* of the syntax, not a file extension. .HP \fB\-\-ignored\-suffix\fR .IP Ignore extension. For example: 'bat \-\-ignored-suffix ".dev" my_file.json.dev' will use JSON syntax, and ignore '.dev' .HP \fB\-\-theme\fR .IP Set the theme for syntax highlighting. Use \fB\-\-list\-themes\fP to see all available themes. To set a default theme, add the \fB\-\-theme="..."\fP option to the configuration file or export the \fBBAT_THEME\fP environment variable (e.g.: \fBexport BAT_THEME="..."\fP). Special values: .RS .IP "auto (\fIdefault\fR)" Picks a dark or light theme depending on the terminal's colors. Use \fB-\-theme\-light\fR and \fB-\-theme\-dark\fR to customize the selected theme. .IP "auto:always" Variation of \fBauto\fR where where the terminal's colors are detected even when the output is redirected. .IP "auto:system (macOS only)" Variation of \fBauto\fR where the color scheme is detected from the system-wide preference instead. .IP "dark" Use the dark theme specified by \fB-\-theme-dark\fR. .IP "light" Use the light theme specified by \fB-\-theme-light\fR. .RE .HP \fB\-\-theme\-dark\fR .IP Sets the theme name for syntax highlighting used when the terminal uses a dark background. To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or export the \fBBAT_THEME_DARK\fP environment variable (e.g. \fBexport BAT_THEME_DARK="..."\fP). This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBdark\fR. .HP \fB\-\-theme\-light\fR .IP Sets the theme name for syntax highlighting used when the terminal uses a light background. To set a default theme, add the \fB\-\-theme-light="..."\fP option to the configuration file or export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP). This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR. .HP \fB\-\-list\-themes\fR .IP Display a list of supported themes for syntax highlighting. .HP \fB\-s\fR, \fB\-\-squeeze\-blank\fR .IP Squeeze consecutive empty lines into a single empty line. .HP \fB\-\-squeeze\-limit\fR .IP Set the maximum number of consecutive empty lines to be printed. .HP \fB\-\-strip\-ansi\fR .IP Specify when to strip ANSI escape sequences from the input. The automatic mode will remove escape sequences unless the syntax highlighting language is plain text. Possible values: auto, always, *never*. .HP \fB\-\-style\fR .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 style, add the '\-\-style=".."' option to the configuration file or export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). .IP When styles are specified in multiple places, the "nearest" set of styles take precedence. The command\-line arguments are the highest priority, followed by the BAT_STYLE environment variable, and then the configuration file. If any set of styles consists entirely of components prefixed with "+" or "\-", it will modify the previous set of styles instead of replacing them. .IP By default, the following components are enabled: changes, grid, header\-filename, numbers, snip .IP Possible values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip. .HP \fB\-r\fR, \fB\-\-line\-range\fR ... .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 .IP "\-\-line\-range 30:+10" prints lines 30 to 40 .RE .HP \fB\-L\fR, \fB\-\-list\-languages\fR .IP Display a list of supported languages for syntax highlighting. .HP \fB\-u\fR, \fB\-\-unbuffered\fR .IP Enable unbuffered input reading. When this flag is set, bat will display data as soon as it is available, without waiting for a complete line. This is useful for streaming use cases like \&'tail \-f logfile | bat \-u \-\-paging=never'. Note that line numbers are automatically disabled in unbuffered mode, and syntax highlighting may be imperfect on partial lines. .HP \fB\-\-no\-custom\-assets\fR .IP Do not load custom assets. .HP \fB\-\-config\-dir\fR .IP Show bat's configuration directory. .HP \fB\-\-cache\-dir\fR .IP Show bat's cache directory. .HP \fB\-\-diagnostic\fR .IP Show diagnostic information for bug reports. .HP \fB\-\-quiet\-empty\fR .IP Do not produce any output when the input is empty (e.g. an empty file or empty stdin). This is useful in scripts where silent behavior is preferred for empty input. .HP \fB\-\-acknowledgements\fR .IP Show acknowledgements. .HP \fB\-\-set\-terminal\-title\fR .IP Sets terminal title to filenames when using a pager. .HP \fB\-h\fR, \fB\-\-help\fR .IP Print this help message. .HP \fB\-V\fR, \fB\-\-version\fR .IP Show version information. .SH "POSITIONAL ARGUMENTS" .HP \fB...\fR .IP Files to print and concatenate. Use a dash ('\-') or no argument at all to read from standard input. .SH "SUBCOMMANDS" .HP \fBcache\fR - Modify the syntax\-definition and theme cache. .SH "FILES" {{PROJECT_EXECUTABLE}} can also be customized with a configuration file. The location of the file is dependent on your operating system. To get the default path for your system, call: \fB{{PROJECT_EXECUTABLE}} --config-file\fR Alternatively, you can use the BAT_CONFIG_PATH environment variable to point {{PROJECT_EXECUTABLE}} to a non-default location of the configuration file. To generate a default configuration file, call: \fB{{PROJECT_EXECUTABLE}} --generate-config-file\fR These are related options: .HP \fB\-\-config\-file\fR .IP Show path to the configuration file. .HP \fB\-\-generate-config\-file\fR .IP Generates a default configuration file. .HP \fB\-\-no\-config\fR .IP Do not use the configuration file. .SH "ADDING CUSTOM LANGUAGES" {{PROJECT_EXECUTABLE}} supports Sublime Text \fB.sublime-syntax\fR language files, and can be customized to add additional languages to your local installation. To do this, add the \fB.sublime-syntax\fR language files to `\fB$({{PROJECT_EXECUTABLE}} --config-dir)/syntaxes\fR` and run `\fB{{PROJECT_EXECUTABLE}} cache --build\fR`. \fBExample:\fR .RS 0.5i mkdir -p "$({{PROJECT_EXECUTABLE}} --config-dir)/syntaxes" .br cd "$({{PROJECT_EXECUTABLE}} --config-dir)/syntaxes" # Put new '.sublime-syntax' language definition files .br # in this folder (or its subdirectories), for example: .br git clone https://github.com/tellnobody1/sublime-purescript-syntax # And then build the cache. .br {{PROJECT_EXECUTABLE}} cache --build .RE Once the cache is built, the new language will be visible in `\fB{{PROJECT_EXECUTABLE}} --list-languages\fR`. .br If you ever want to remove the custom languages, you can clear the cache with `\fB{{PROJECT_EXECUTABLE}} cache --clear\fR`. .SH "ADDING CUSTOM THEMES" Similarly to custom languages, {{PROJECT_EXECUTABLE}} supports Sublime Text \fB.tmTheme\fR themes. These can be installed to `\fB$({{PROJECT_EXECUTABLE}} --config-dir)/themes\fR`, and are added to the cache with `\fB{{PROJECT_EXECUTABLE}} cache --build`. .SH "INPUT PREPROCESSOR" Much like less(1) does, {{PROJECT_EXECUTABLE}} supports input preprocessors via the LESSOPEN and LESSCLOSE environment variables. In addition, {{PROJECT_EXECUTABLE}} attempts to be as compatible with less's preprocessor implementation as possible. To use the preprocessor, call: \fB{{PROJECT_EXECUTABLE}} --lessopen\fR Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file. To temporarily disable the preprocessor if it is enabled by default, call: \fB{{PROJECT_EXECUTABLE}} --no-lessopen\fR These are related options: .HP \fB\-\-lessopen\fR .IP Enable the $LESSOPEN preprocessor. .HP \fB\-\-no\-lessopen\fR .IP Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen) .PP For more information, see the "INPUT PREPROCESSOR" section of less(1). .SH "MORE INFORMATION" For more information and up-to-date documentation, visit the {{PROJECT_EXECUTABLE}} repo: .br \fBhttps://github.com/sharkdp/bat\fR ================================================ FILE: assets/patches/1337.tmTheme.patch ================================================ diff --git themes/1337-Scheme/1337.tmTheme themes/1337-Scheme/1337.tmTheme index fdff5bf..8cfc888 100644 --- themes/1337-Scheme/1337.tmTheme +++ themes/1337-Scheme/1337.tmTheme @@ -280,7 +280,7 @@ SOFTWARE. name PHP Namespaces scope - support.other.namespace, entity.name.type.namespace + support.other.namespace, entity.name.type.namespace, entity.name settings foreground @@ -561,7 +561,7 @@ SOFTWARE. name diff.header scope - meta.diff, meta.diff.header + meta.diff, meta.diff.header, markup.heading settings foreground ================================================ FILE: assets/patches/C#.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/C#/C#.sublime-syntax syntaxes/01_Packages/C#/C#.sublime-syntax index ed494f8b..01b710e8 100644 --- syntaxes/01_Packages/C#/C#.sublime-syntax +++ syntaxes/01_Packages/C#/C#.sublime-syntax @@ -1312,7 +1312,7 @@ contexts: 2: punctuation.separator.cs 3: punctuation.section.brackets.end.cs 4: keyword.operator.pointer.cs - - match: \((?=(?:[^,)(]*|\([^\)]*\))*,) + - match: \((?=(?:[^,)(]|\([^\)]*\))*,) scope: punctuation.section.group.begin.cs push: - meta_scope: meta.group.tuple.cs ================================================ FILE: assets/patches/Groff.sublime-syntax.patch ================================================ diff --git syntaxes/02_Extra/Groff/Man Page/Man Page.sublime-syntax syntaxes/02_Extra/Groff/Man Page/Man Page.sublime-syntax index 57834af..6648664 100644 --- syntaxes/02_Extra/Groff/Man Page/Man Page.sublime-syntax +++ syntaxes/02_Extra/Groff/Man Page/Man Page.sublime-syntax @@ -4,9 +4,9 @@ # - man-pages(7) # - groff(7) --- -name: Man Page (groff/troff) +name: Groff/troff scope: text.groff -file_extensions: [man, groff, troff, '1', '2', '3', '4', '5', '6', '7'] +file_extensions: [groff, troff, '1', '2', '3', '4', '5', '6', '7', '8', '9'] contexts: main: ================================================ FILE: assets/patches/JavaDoc.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Java/JavaDoc.sublime-syntax syntaxes/01_Packages/Java/JavaDoc.sublime-syntax index 422a6a9..40a741e 100644 --- syntaxes/01_Packages/Java/JavaDoc.sublime-syntax +++ syntaxes/01_Packages/Java/JavaDoc.sublime-syntax @@ -13,7 +13,7 @@ variables: contexts: prototype: # https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#leadingasterisks - - match: ^\s*(\*)\s*(?!\s*@) + - match: ^\s*(\*)(?!/)\s*(?!\s*@) captures: 1: punctuation.definition.comment.javadoc ================================================ FILE: assets/patches/JavaScript.sublime-syntax.patch ================================================ Submodule assets/syntaxes/01_Packages contains modified content diff --git syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax index 05a4fed6..78a7bf55 100644 --- syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax +++ syntaxes/01_Packages/JavaScript/JavaScript.sublime-syntax @@ -5,7 +5,7 @@ name: JavaScript file_extensions: - js - htc -first_line_match: ^#!\s*/.*\b(node|js)\b +first_line_match: ^#!\s*/.*\b(node|bun|js)\b scope: source.js variables: bin_digit: '[01_]' ================================================ FILE: assets/patches/Lisp.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Lisp/Lisp.sublime-syntax syntaxes/01_Packages/Lisp/Lisp.sublime-syntax index 50e5dad3..44a9795d 100644 --- syntaxes/01_Packages/Lisp/Lisp.sublime-syntax +++ syntaxes/01_Packages/Lisp/Lisp.sublime-syntax @@ -1,11 +1,14 @@ %YAML 1.2 --- -# http://www.sublimetext.com/docs/3/syntax.html +# https://www.sublimetext.com/docs/syntax.html # # `Common Lisp` Language Reference: -# http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/index.html -# +# https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/index.html +# https://www.lispworks.com/documentation/lw70/CLHS/Front/Contents.htm name: Lisp +scope: source.lisp +version: 2 + file_extensions: - lisp - cl @@ -17,108 +20,2268 @@ file_extensions: - ss - lsp - fasl # Scheme dialect of Lisp -scope: source.lisp + - sld # Scheme r7rs library + +first_line_match: |- + (?xi: + ^ \s* ; .*? -\*- .*? \blisp\b .*? -\*- # editorconfig + ) + +############################################################################### + contexts: main: - - include: comments + - include: statements + + statements: - include: parens + - include: expressions + - match: \) + scope: invalid.illegal.stray-bracket-end.lisp expressions: - include: comments - include: numbers - - include: constants - include: strings - - include: variables + - include: annotations + - include: keywords + - include: quotes + - include: macros + - include: modifiers + - include: identifiers + +###[ COMMENTS ]################################################################ + + comments: + - include: line-comments + - include: block-comments + - match: \|# + scope: invalid.illegal.stray-comment-end.lisp + + block-comments: + - match: '#\|' + scope: punctuation.definition.comment.begin.lisp + push: block-comment-body + + block-comment-body: + - meta_scope: comment.block.lisp + - match: '\|#' + scope: punctuation.definition.comment.end.lisp + pop: 1 + - include: block-comments + + line-comments: + - match: ;+ + scope: punctuation.definition.comment.lisp + push: line-comment-body + + line-comment-body: + - meta_scope: comment.line.semicolon.lisp + - match: $\n? + pop: 1 + +###[ PARENTHESES ]############################################################# + + parens: + - match: \( + scope: punctuation.section.parens.begin.lisp + push: + - paren-body + - paren-begin + + paren-begin: + - include: class-declaration + - include: function-declaration + - include: macro-declaration + - include: struct-declaration + - include: type-declaration + - include: variable-declaration + - include: other-declaration + - include: declare - include: control - - include: functions - - include: operators + - include: loop + - include: operator + - include: quote + - include: namespaces + - include: builtin-function + - include: other-function + - include: comments + - include: else-pop - variables: - - match: (\*)(?i:trace-output|terminal-io|suppress-series-warnings|standard-output|standard-input|readtable|read-suppress|read-eval|read-default-float-format|read-base|random-state|query-io|print-right-margin|print-readably|print-radix|print-pretty|print-pprint-dispatch|print-miser-width|print-lines|print-level|print-length|print-gensym|print-escape|print-circle|print-case|print-base|print-array|package|modules|macroexpand-hook|load-verbose|load-truename|load-print|load-pathname|gensym-counter|features|evalhook|error-output|default-pathname-defaults|debugger-hook|debug-io|compile-verbose|compile-print|compile-file-truename|compile-file-pathname|break-on-warnings|break-on-signals|applyhook)(\*) - scope: variable.language.lisp + paren-body: + - meta_scope: meta.parens.lisp + - include: paren-end + - include: parens + - include: expressions + + paren-end: + - meta_include_prototype: false + - meta_scope: meta.parens.lisp + - match: \) + scope: punctuation.section.parens.end.lisp + pop: 1 + +###[ LISTS ]################################################################### + + expect-list: + # a list expression + # skips function-like parentheses on next level + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: paren-body + - include: comments + - include: else-pop + + expect-lists-list: + # a list of list expressions + # skips function-like parentheses on next 2 levels + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: lists-list-body + - include: comments + - include: else-pop + + lists-list-body: + - meta_scope: meta.parens.lisp + - include: paren-end + - include: lists + - include: expressions + + lists: + - match: \( + scope: punctuation.section.parens.begin.lisp + push: paren-body + +###[ QUOTED EXPRESSIONS ]###################################################### + + quotes: + # abbreviation of (quote ...) function + - match: \' + scope: punctuation.definition.quoted.lisp + push: quoted-content + + quoted-content: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: quoted-paren-body + # A quoted symbol evaluates to the symbol. + - match: '{{identifier}}' + scope: constant.other.symbol.lisp captures: - 1: punctuation.definition.variable.begin.lisp - 2: punctuation.definition.variable.end.lisp - - match: (\*)(\S*)(\*) - scope: variable.other.global.lisp + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: immediately-pop + + quoted-parens: + - match: \( + scope: punctuation.section.parens.begin.lisp + push: quoted-paren-body + + quoted-paren-body: + - meta_scope: meta.parens.lisp + - include: paren-end + - include: quoted-parens + - include: expressions + +###[ CLASS DECLARATIONS ]###################################################### + + class-declaration: + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_defcla.htm + - match: (?i:defclass|define-class){{break}} + scope: meta.class.lisp keyword.declaration.class.lisp + set: + - class-declaration-slots + - class-declaration-parent-list + - class-declaration-name + + class-declaration-name: + - match: '{{identifier}}' + scope: entity.name.class.lisp captures: - 1: punctuation.definition.variable.begin.lisp - 3: punctuation.definition.variable.end.lisp + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + class-declaration-parent-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: class-declaration-parent-list-body + - include: comments + - include: else-pop + + class-declaration-parent-list-body: + - meta_scope: meta.parens.lisp + - include: namespaces + - match: '{{identifier}}' + scope: entity.other.inherited-class.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + - include: comments + - include: paren-end + + class-declaration-slots: + - meta_content_scope: meta.class.lisp + - include: paren-pop + - include: lists + - include: expressions + +###[ FUNCTION DECLARATIONS ]################################################### + + function-declaration: + # https://www.lispworks.com/documentation/HyperSpec/Body/s_lambda.htm + - match: (?i:lambda){{break}} + scope: meta.function.lisp keyword.declaration.function.inline.lisp + set: + - function-body + - function-parameter-list + # https://www.lispworks.com/documentation/HyperSpec/Body/m_defun.htm + - match: (?i:def(?:[a-z]+f)?un|defgeneric|define-(?:command(?:-global)?|parenscript)){{break}} + scope: meta.function.lisp keyword.declaration.function.lisp + set: + - function-body + - function-parameter-list + - function-declaration-name + # https://www.lispworks.com/documentation/HyperSpec/Body/m_defmet.htm + - match: (?i:defmethod){{break}} + scope: meta.function.lisp keyword.declaration.function.lisp + set: + - function-body + - function-parameter-list + - method-qualifier + - function-declaration-name + # https://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm + - match: (?i:flet|labels){{break}} + scope: keyword.declaration.function.lisp + set: function-declaration-list + + function-declaration-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: function-declaration-list-body + - include: comments + - include: else-pop + + function-declaration-list-body: + - meta_scope: meta.parens.lisp + - match: \( + scope: punctuation.section.parens.begin.lisp + push: + - paren-end + - function-body + - function-parameter-list + - function-declaration-name + - include: comments + - include: paren-end + + function-declaration-name: + - include: namespaces + - match: '{{identifier}}' + scope: entity.name.function.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + method-qualifier: + # qualifiers may be anything but lists + - include: expressions + - include: else-pop + + function-parameter-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parameters.begin.lisp + set: function-parameter-list-body + - include: comments + - include: else-pop + + function-parameter-list-body: + - clear_scopes: 1 + - meta_scope: meta.function.parameters.lisp + - match: \) + scope: punctuation.section.parameters.end.lisp + pop: 1 + - include: comments + - include: annotations + - include: keywords + - include: modifiers + - include: parameters + + function-body: + - meta_content_scope: meta.function.lisp + - include: paren-pop + - include: parens + - include: expressions + +###[ MACRO DECLARATIONS ]###################################################### + + macro-declaration: + # https://www.lispworks.com/documentation/HyperSpec/Body/m_defmac.htm + - match: (?i:defmacro){{break}} + scope: meta.macro.lisp keyword.declaration.macro.lisp + set: + - macro-body + - macro-parameter-list + - macro-declaration-name + # https://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm + - match: (?i:macrolet){{break}} + scope: keyword.declaration.macro.lisp + set: macro-declaration-list + + macro-declaration-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: macro-declaration-list-body + - include: comments + - include: else-pop + + macro-declaration-list-body: + - meta_scope: meta.parens.lisp + - match: \( + scope: punctuation.section.parens.begin.lisp + push: + - paren-end + - macro-body + - macro-parameter-list + - macro-declaration-name + - include: comments + - include: paren-end + + macro-declaration-name: + - include: namespaces + - match: '{{identifier}}' + scope: entity.name.macro.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + macro-parameter-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parameters.begin.lisp + set: macro-parameter-list-body + - include: comments + - include: else-pop + + macro-parameter-list-body: + - clear_scopes: 1 + - meta_scope: meta.macro.parameters.lisp + - match: \) + scope: punctuation.section.parameters.end.lisp + pop: 1 + - include: comments + - include: annotations + - include: keywords + - include: modifiers + - include: parameters + + macro-body: + - meta_content_scope: meta.macro.lisp + - include: paren-pop + - include: parens + - include: expressions + +###[ STRUCT DECLARATIONS ]##################################################### + + struct-declaration: + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_defstr.htm + - match: (?i:defstruct|define-struct){{break}} + scope: meta.struct.lisp keyword.declaration.struct.lisp + set: + - struct-declaration-body + - struct-declaration-name + + struct-declaration-name: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: + - paren-body + - struct-declaration-qualified-name + - include: struct-declaration-qualified-name + + struct-declaration-qualified-name: + - include: namespaces + - match: '{{identifier}}' + scope: entity.name.struct.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + struct-declaration-body: + - meta_content_scope: meta.struct.lisp + - include: paren-pop + - include: lists + - include: expressions + +###[ TYPE DECLARATIONS ]####################################################### + + type-declaration: + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_deftp.htm + - match: (?i:deftype|define-type){{break}} + scope: meta.type.lisp keyword.declaration.type.lisp + set: + - type-body + - type-parameter-list + - type-declaration-name + + type-declaration-name: + - include: namespaces + - match: '{{identifier}}' + scope: entity.name.type.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + type-parameter-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parameters.begin.lisp + set: type-parameter-list-body + - include: comments + - include: else-pop + + type-parameter-list-body: + - clear_scopes: 1 + - meta_scope: meta.type.parameters.lisp + - match: \) + scope: punctuation.section.parameters.end.lisp + pop: 1 + - include: comments + - include: annotations + - include: keywords + - include: modifiers + - include: parameters + + type-body: + - meta_content_scope: meta.type.lisp + - include: paren-pop + - include: parens + - include: expressions + +###[ VARIABLE DECLARATIONS ]################################################### + + variable-declaration: + # https://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm + - match: (?i:let\*?){{break}} + scope: keyword.declaration.variable.lisp + set: variable-declaration-list + # https://www.lispworks.com/documentation/lw445/CLHS/Body/m_defcon.htm + - match: (?i:defconstant){{break}} + scope: meta.declaration.lisp keyword.declaration.constant.lisp + set: constant-declaration-name + # https://www.lispworks.com/documentation/HyperSpec/Body/m_defpar.htm + - match: (?i:defparameter|defvar){{break}} + scope: meta.declaration.lisp keyword.declaration.variable.lisp + set: variable-declaration-name + + variable-declaration-list: + - meta_include_prototype: false + - match: \( + scope: punctuation.section.parens.begin.lisp + set: variable-declaration-list-body + - include: comments + - include: else-pop + + variable-declaration-list-body: + - meta_scope: meta.parens.lisp + - match: \( + scope: punctuation.section.parens.begin.lisp + push: + - paren-body + - variable-declaration-name + - match: '{{identifier}}' + scope: meta.declaration.lisp variable.other.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + - include: comments + - include: paren-end + + constant-declaration-name: + - meta_content_scope: meta.declaration.lisp + - match: '{{identifier}}' + scope: meta.declaration.lisp constant.other.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + variable-declaration-name: + - meta_content_scope: meta.declaration.lisp + - match: '{{identifier}}' + scope: meta.declaration.lisp variable.other.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + +###[ OTHER DECLARATIONS ]###################################################### + + other-declaration: + - match: '{{declaration_keywords}}' + scope: keyword.declaration.lisp + pop: 1 + +###[ DECLARE STATEMENTS ]###################################################### + + declare: + # https://www.lispworks.com/documentation/HyperSpec/Body/s_declar.htm + - match: (?i:declare){{break}} + scope: keyword.declaration.declare.lisp + set: declare-specifier-list + + declare-specifier-list: + - match: \( + scope: punctuation.section.parens.begin.lisp + push: + - paren-body + - declare-identifier + - include: comments + - include: else-pop + + declare-identifier: + - match: '{{declaration_identifiers}}' + scope: storage.modifier.lisp + pop: 1 + - include: comments + - include: else-pop + +###[ CONTROL FLOW STATEMENTS ]################################################# control: - - match: \b(?i:with|while|when|unless|typecase|to|thereis|then|return-from name|return|repeat|prog*|prog|never|named|maplist|mapl|mapcon|mapcar|mapcan|mapc|loop|let|initially|if|from|for|finally|etypecase|else|dotimes|dolist|doing|do*|do|ctypecase|cond|case|block|as|always)\b + # Conditional + - match: (?i:if|case|cond|otherwise|unless|when|[ce]?typecase){{break}} + scope: keyword.control.conditional.lisp + pop: 1 + # Flow + - match: (?i:return(?:-from)?){{break}} + scope: keyword.control.flow.return.lisp + pop: 1 + # Loop + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_dolist.htm + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_dotime.htm + - match: (?i:dolist|dotimes){{break}} + scope: keyword.control.loop.lisp + set: expect-list + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_do_do.htm + - match: (?i:do\*?|do-(?:all-|external-)?symbols|iterate){{break}} + scope: keyword.control.loop.lisp + set: expect-lists-list + # Other + - match: (?xi:block|map(?:can|car|con|c|list|l)){{break}} scope: keyword.control.lisp + pop: 1 + +###[ LOOP STATEMENTS ]######################################################### + + loop: + # https://www.lispworks.com/documentation/lw70/CLHS/Body/06_a.htm + # https://www.lispworks.com/documentation/lw70/CLHS/Body/m_loop.htm + - match: (?i:loop){{break}} + scope: keyword.control.loop.lisp + set: loop-body + + loop-body: + - meta_scope: meta.loop.lisp + - include: paren-pop + + # declaration keywords + - match: (?i:named){{break}} + scope: keyword.declaration.name.lisp + push: loop-name + - match: (?i:with){{break}} + scope: keyword.declaration.variable.lisp + + # loop termination test keywords + - match: (?i:always|as|do|doing|for|never|repeat|thereis|until|while){{break}} + scope: keyword.control.loop.lisp + # conditional keywords + - match: (?i:end|else|if|then|unless|when){{break}} + scope: keyword.control.conditional.lisp + # control flow keywords + - match: (?i:finally|initially){{break}} + scope: keyword.control.flow.lisp + - match: (?i:return(?:-from)?){{break}} + scope: keyword.control.flow.return.lisp - functions: - - match: \b(?i:(defun|defmethod|defmacro))\b\s+([\w\-!?<>]*) - scope: meta.function.lisp + # operator keywords + - match: ={{break}} # can be both, assignment and comparison + scope: keyword.operator.lisp + - match: (?i:into){{break}} + scope: keyword.operator.assignment.lisp + - match: (?i:and){{break}} + scope: keyword.operator.logical.lisp + - match: |- + (?xi: across | above | being | below | by | each | in | of | on | the + | (?:down|up)?to | (?:up)?from | using ){{break}} + scope: keyword.other.loop.lisp + + # expressions + - include: comments + - include: parens + - include: numbers + - include: strings + - include: annotations + - include: keywords + - include: quotes + - include: macros + - include: modifiers + - match: (?={{identifier}}) + push: loop-identifier + + loop-identifier: + - include: builtin-function + - include: identifier + + loop-name: + - match: '{{identifier}}' + scope: entity.name.loop.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + +###[ QUOTE STATEMENTS ]######################################################## + + quote: + - match: (?i:quote){{break}} + scope: meta.function-call.lisp support.function.lisp + set: quote-args + + quote-args: + - include: paren-pop + - include: quoted-parens + - include: expressions + +###[ FUNCTIONS ]############################################################### + + builtin-function: + - match: '{{builtin_functions}}' + scope: meta.function-call.lisp support.function.lisp + pop: 1 + + other-function: + # functions starting with `make-` are most likely used as constructors + - match: make-{{identifier}} + scope: meta.function-call.lisp variable.function.constructor.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + # mutating functions changing data in-place end with ! + - match: (?![+*#`'&]\S){{identifier}}\!{{break}} + scope: meta.function-call.lisp variable.function.mutating.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + # predicate functions returning boolean values end with ? or -p + - match: (?![+*#`'&]\S){{identifier}}(?:\?|-p){{break}} + scope: meta.function-call.lisp variable.function.predicate.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + # anything not looking like global variable, constant or macro + - match: (?![+*#`'&]\S|{{builtin_constants}}|{{builtin_types}}){{identifier}} + scope: meta.function-call.lisp variable.function.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + +###[ MACROS ]################################################################## + + macros: + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node191.html + - include: macro-arrays + - include: macro-characters + - include: macro-conditionals + - include: macro-functions + - include: macro-numbers + - include: macro-pathnames + - include: macro-structures + - include: macro-throw-exceptions + - include: macro-variables + - include: macro-vectors + + macro-conditionals: + # Feature-flags + - match: (#[-+])({{identifier}})? + captures: + 1: keyword.control.conditional.lisp + 2: constant.other.feature.lisp + 3: punctuation.definition.symbol.begin.lisp + 4: punctuation.definition.symbol.end.lisp + + macro-arrays: + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node29.html + - match: (#\d*[aA])(\() + captures: + 1: punctuation.definition.array.lisp + 2: meta.parens.lisp punctuation.section.parens.begin.lisp + push: macro-array-body + - match: (#\d*[aA])({{identifier}}) + captures: + 1: punctuation.definition.array.lisp + 2: variable.other.lisp + 3: punctuation.definition.symbol.begin.lisp + 4: punctuation.definition.symbol.end.lisp + + macro-array-body: + - meta_scope: meta.array.lisp + - meta_content_scope: meta.parens.lisp + - match: \) + scope: meta.parens.lisp punctuation.section.parens.end.lisp + pop: 1 + - include: parens + - include: expressions + + macro-characters: + # Standard Characters + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node22.html + # Non-Standard Characters + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node24.html + # Character Attributes + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node25.html + - match: (#(\d*)\\){{char_attributes}}?(?i:Space|NewLine){{break}} + scope: constant.character.standard.lisp + captures: + 1: punctuation.definition.constant.lisp + 2: storage.modifier.attributes.lisp + - match: (#(\d*)\\){{char_attributes}}?(?i:Backspace|Tab|Linefeed|Page|Return|RubOut){{break}} + scope: constant.character.semi-standard.lisp + captures: + 1: punctuation.definition.constant.lisp + 2: storage.modifier.attributes.lisp + - match: (#(\d*)\\){{char_attributes}}?{{standard_char}}{{break}} + scope: constant.character.standard.lisp captures: - 1: storage.type.function-type.lisp - 2: entity.name.function.lisp - - match: \b(?i:zerop|yes-or-no-p|y-or-n-p|write-to-string|write-string|write-char|write-byte|write|with-standard-io-syntax|with-slots|with-simple-restart|with-package-iterator|with-output-to-string|with-open-stream|with-open-file|with-input-from-string|with-hash-table-iterator|with-condition-restarts|with-compilation-unit|with-accessors|wild-pathname-p|warn|vectorp|vector-push-extend|vector-push|vector-pop|vector|variable-information|values-list|values|user-homedir-pathname|use-value|use-package|upper-case-p|upgraded-complex-part-type|upgraded-array-element-type|update-instance-for-redefined-class|update-instance-for-different-class|unuse-package|untrace|until-if|until|unread-char|union|unintern|unexport|typep|type-of|type-error-expected-type|type-error-datum|two-way-stream-output-stream|two-way-stream-input-stream|truncate|truename|tree-equal|translate-pathname|translate-logical-pathname|trace|to-alter|time|third|terpri|terminate-producing|tenth|tanh|tan|tailp|synonym-stream-symbol|symbolp|symbol-value|symbol-plist|symbol-package|symbol-name|symbol-function|sxhash|svref|summing|sum|subtypep|substitute-if-not|substitute-if|substitute|subst-if-not|subst-if|subst|subsetp|subseries|subseq|sublis|stringp|string>=|string>|string=|string<=|string<|string/=|string-upcase|string-trim|string-right-trim|string-not-lessp|string-not-greaterp|string-not-equal|string-lessp|string-left-trim|string-greaterp|string-equal|string-downcase|string-char-p|string-capitalize|string|streamp|stream-external-format|stream-error-stream|stream-element-type|store-value|step|standard-char-p|stable-sort|sqrt|split-if|split|special-form-p|sort|some|software-version|software-type|slot-value|slot-unbound|slot-missing|slot-makunbound|slot-exists-p|slot-boundp|sleep|sixth|sinh|sin|simple-vector-p|simple-string-p|simple-condition-format-string|simple-condition-format-arguments|simple-bit-vector-p|signum|signal|short-site-name|shiftf|shared-initialize|shadowing-import|shadow|seventh|setq|setf|set-syntax-from-char|set-pprint-dispatch|set-macro-character|set-exclusive-or|set-dispatch-macro-character|set-difference|set-char-bit|set|series|second|search|schar|scan-symbols|scan-sublists|scan-range|scan-plist|scan-multiple|scan-lists-of-lists-fringe|scan-lists-of-lists|scan-hash|scan-fn-inclusive|scan-fn|scan-file|scan-alist|scan|scale-float|sbit|rplacd|rplaca|row-major-aref|round|rotatef|room|reverse|revappend|result-of|restart-name|restart-case|restart-bind|rest|require|replace|rename-package|rename-file|remprop|remove-method|remove-duplicates|remove|remhash|remf|reinitialize-instance|reduce|realpart|realp|readtablep|readtable-case|read-preserving-whitespace|read-line|read-from-string|read-delimited-list|read-char-no-hang|read-char|read-byte|read|rationalp|rationalize|rational|rassoc-if-not|rassoc-if|rassoc|random-state-p|random|quote|pushnew|push|psetq|psetf|provide|progn|prog2|prog1|producing|proclaim|probe-file|print-unreadable-object|print-object|print|prin1|previous|pprint-tabular|pprint-tab|pprint-pop|pprint-newline|pprint-logical-block|pprint-linear|pprint-indent|pprint-fill|pprint-exit-if-list-exhausted|pprint-dispatch|positions|position-if-not|position-if|position|pop|plusp|phase|peek-char|pathnamep|pathname-version|pathname-type|pathname-name|pathname-match-p|pathname-host|pathname-directory|pathname-device|pathname|parse-namestring|parse-macro|parse-integer|pairlis|packagep|package-used-by-list|package-use-list|package-shadowing-symbols|package-nicknames|package-name|package-error-package|output-stream-p|open-stream-p|open|oddp|nunion|numerator|numberp|nthcdr|nth-value|nth|nsubstitute-if-not|nsubstitute-if|nsubstitute|nsubst-if-not|nsubst-if|nsubst|nsublis|nstring-upcase|nstring-downcase|nstring-capitalize|nset-exclusive-or|nset-difference|nreverse|nreconc|notevery|notany|no-next-method|no-applicable-method|ninth|nintersection|next-out|next-method-p|next-in|nconcing|nconc|nbutlast|namestring|name-char|multiple-value-setq|multiple-value-list|multiple-value-bind|muffle-warning|mismatch|minusp|minimizing|minimize|mingle|method-qualifiers|method-combination-error|merge-pathnames|merge|memberp|member-if-not|member-if|member|maximizing|maximize|mask-field|mask|mapping|maphash|map-into|map-fn|map|makunbound|make-two-way-stream|make-synonym-stream|make-symbol|make-string-output-stream|make-string-input-stream|make-string|make-sequence|make-random-state|make-pathname|make-package|make-load-form-saving-slots|make-load-form|make-list|make-instances-obsolete|make-instance|make-hash-table|make-echo-stream|make-dispatch-macro-character|make-condition|make-concatenated-stream|make-char|make-broadcast-stream|make-array|macroexpand-1|macroexpand|macro-function|machine-version|machine-type|machine-instance|lower-case-p|loop-finish|long-site-name|logtest|logorc2|logorc1|lognot|lognand|logical-pathname-translations|logical-pathname|logcount|logbitp|logandc2|logandc1|log|locally|load-logical-pathname-translations|load|listp|listen|list-length|list-all-packages|list*|list|lisp-implementation-version|lisp-implementation-type|length|ldiff|ldb-test|ldb|lcm|latch|last|lambda|keywordp|iterate|isqrt|invoke-restart|invoke-debugger|invalid-method-error|intersection|intern|interactive-stream-p|integerp|integer-length|integer-decode-float|int-char|inspect|input-stream-p|initialize-instance|in-package|import|imagpart|ignore-errors|identity|host-namestring|hash-table-test|hash-table-size|hash-table-rehash-threshold|hash-table-rehash-size|hash-table-p|hash-table-count|handler-case|handler-bind|graphic-char-p|gethash|getf|get-universal-time|get-setf-method-multiple-value|get-setf-method|get-properties|get-output-stream-string|get-internal-run-time|get-internal-real-time|get-decoded-time|get|gentemp|gensym|generic-function|generator|gcd|gathering|gatherer|functionp|function-lambda-expression|function-keywords|function-information|funcall|fourth|formatter|format|floor|floatp|float-sign|float-radix|float-precision|float-digits|float|first|finish-output|find-symbol|find-restart|find-package|find-method|find-if-not|find-if|find-class|find-all-symbols|find|fill-pointer|fill|file-write-date|file-string-length|file-position|file-namestring|file-length|file-error-pathname|file-author|fifth|ffloor|fdefinition|fboundp|f|expt|export|expand|exp|every|evenp|evalhook|eval|error|ensure-generic-function|enough-namestring|endp|encode-universal-time|enclose|encapsulated|elt|eighth|ed|echo-stream-output-stream|echo-stream-input-stream|ecase|dribble|dpb|documentation|do-symbols|do-external-symbols|do-all-symbols|disassemble|directory-namestring|directory|digit-char-p|digit-char|destructuring-bind|describe-object|describe|deposit-field|denominator|delete-package|delete-if-not|delete-if|delete-file|delete-duplicates|delete|defvar|deftype|defstruct|defpackage|define-setf-method|define-modify-macro|define-method-combination|define-declaration|define-condition|define-compiler-macro|defgeneric|defclass|decode-universal-time|decode-float|declaration-information|declaim|counting|count-if-not|count-if|count|cotruncate|cosh|cos|copy-tree|copy-symbol|copy-seq|copy-readtable|copy-pprint-dispatch|copy-list|copy-alist|continue|constantp|consp|cons|conjugate|concatenated-stream-streams|concatenate|compute-restarts|compute-applicable-methods|complexp|complex|complement|compiler-macroexpand-1|compiler-macroexpand|compiler-macro-function|compiler-let|compiled-function-p|compile-file-pathname|compile-file|compile|commonp|collecting-fn|collecting|collect-sum|collect-plist|collect-or|collect-nth|collect-nconc|collect-min|collect-max|collect-length|collect-last|collect-hash|collect-fn|collect-first|collect-file|collect-append|collect-and|collect-alist|collect|coerce|code-char|clrhash|close|clear-input|class-of|class-name|cis|chunk|choose-if|choose|check-type|characterp|character|char>=|char>|char=|char<=|char<|char/=|char-upcase|char-not-lessp|char-not-greaterp|char-not-equal|char-name|char-lessp|char-int|char-greaterp|char-font|char-equal|char-downcase|char-code|char-bits|char-bit|char|change-class|cerror|cell-error-name|ceiling|cdr|cddr|cdddr|cddddr|cdddar|cddar|cddadr|cddaar|cdar|cdadr|cdaddr|cdadar|cdaar|cdaadr|cdaaar|ccase|catenate|car|call-next-method|call-method|cadr|caddr|cadddr|caddar|cadar|cadadr|cadaar|caar|caadr|caaddr|caadar|caaar|caaadr|caaaar|byte-size|byte-position|byte|butlast|broadcast-stream-streams|break|boundp|both-case-p|boole|bit-xor|bit-vector-p|bit-orc2|bit-orc1|bit-not|bit-nor|bit-nand|bit-ior|bit-eqv|bit-andc2|bit-andc1|bit-and|bit|augment-environment|atom|atanh|atan|assoc-if-not|assoc-if|assoc|assert|asinh|asin|ash|arrayp|array-total-size|array-row-major-index|array-rank|array-in-bounds-p|array-has-fill-pointer-p|array-element-type|array-dimensions|array-dimension|arithmetic-error-operation|arithmetic-error-operands|aref|apropos-list|apropos|applyhook|apply|appending|append|alter|alphanumericp|alpha-char-p|adjustable-array-p|adjust-array|adjoin|add-method|acosh|acos|acons|abs|abort)\b - scope: support.function.lisp + 1: punctuation.definition.constant.lisp + 2: storage.modifier.attributes.lisp + - match: (#(\d*)\\){{char_attributes}}?{{identifier_char}}+{{break}} + scope: constant.character.non-standard.lisp + captures: + 1: punctuation.definition.constant.lisp + 2: storage.modifier.attributes.lisp + + macro-functions: + # Function reference + - match: \#[Mm'] + scope: punctuation.definition.function.lisp + push: macro-function-name + + macro-function-name: + - include: namespaces + - include: operator + - include: builtin-function + - include: other-function + - include: immediately-pop + + macro-numbers: + # binary rational numbers + - match: |- + (?xi) + ( \#(?: b | 2r ) ) + ( [-+]? ) + ( [01]+ (/) [01]+ ) + {{break}} + scope: meta.number.rational.binary.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: keyword.operator.arithmetic.lisp + # binary integer numbers + - match: |- + (?xi) + ( \#(?: b | 2r ) ) + ( [-+]? ) + ( [01]+ (?: (\.)(?![01]) | {{break}} ) ) + scope: meta.number.integer.binary.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: punctuation.separator.decimal.lisp + # octal rational numbers + - match: |- + (?xi) + ( \#(?: o | 8r ) ) + ( [-+]? ) + ( [0-7]+ (/) [0-7]+ ) + {{break}} + scope: meta.number.rational.octal.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: keyword.operator.arithmetic.lisp + # octal integer numbers + - match: |- + (?xi) + ( \#(?: o | 8r ) ) + ( [-+]? ) + ( [0-7]+ (?: (\.)(?![0-7]) | {{break}} ) ) + scope: meta.number.integer.octal.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: punctuation.separator.decimal.lisp + # hexadecimal rational numbers + - match: |- + (?xi) + ( \#(?: x | 16r ) ) + ( [-+]? ) + ( \h+ (/) \h+ ) + {{break}} + scope: meta.number.rational.hexadecimal.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: keyword.operator.arithmetic.lisp + # hexadecimal integer numbers + - match: |- + (?xi) + ( \#(?: x | 16r ) ) + ( [-+]? ) + ( \h+ (?: (\.)(?!\h) | {{break}} ) ) + scope: meta.number.integer.hexadecimal.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: punctuation.separator.decimal.lisp + # radix rational numbers + - match: |- + (?xi) + ( \#\d+r ) + ( [-+]? ) + ( [[:alnum:]]+ (/) [[:alnum:]]+ ) + {{break}} + scope: meta.number.rational.other.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: keyword.operator.arithmetic.lisp + # radix integer numbers + - match: |- + (?xi) + ( \#\d+r ) + ( [-+]? ) + ( [[:alnum:]]+ (?: (\.)(?![[:alnum:]]) | {{break}} ) ) + scope: meta.number.integer.other.lisp + captures: + 1: constant.numeric.base.lisp + 2: keyword.operator.arithmetic.lisp + 3: constant.numeric.value.lisp + 4: punctuation.separator.decimal.lisp + # complex numbers + - match: (#[cC])(\() + captures: + 1: punctuation.definition.complex.lisp + 2: meta.parens.lisp punctuation.section.parens.begin.lisp + push: macro-numbers-complex-body + + macro-numbers-complex-body: + - meta_scope: meta.number.complex.lisp + - meta_content_scope: meta.parens.lisp + - match: \) + scope: meta.parens.lisp punctuation.section.parens.end.lisp + pop: 1 + - include: parens + - include: expressions - operators: - - match: '\/\=|\>\=|\<\=|\=|\>|\<|\b(?i:max|min|eq|neq|eql|equalp|equal)\b' + macro-pathnames: + - match: (#\d*[pP])(\") + captures: + 1: punctuation.definition.pathname.lisp + 2: string.quoted.double.lisp punctuation.definition.string.begin.lisp + push: macro-pathname-body + + macro-pathname-body: + - meta_scope: meta.path.lisp + - meta_content_scope: string.quoted.double.lisp + - match: \" + scope: string.quoted.double.lisp punctuation.definition.string.end.lisp + pop: 1 + - match: \\. + scope: constant.character.escape.lisp + + macro-structures: + # Structures + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node39.html + - match: (#\d*[sS])(\() + captures: + 1: punctuation.definition.struct.lisp + 2: meta.parens.lisp punctuation.section.parens.begin.lisp + push: + - macro-struct-body + - macro-struct-name + + macro-struct-name: + - match: '{{identifier}}' + scope: entity.name.struct.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: else-pop + + macro-struct-body: + - meta_scope: meta.struct.lisp + - meta_content_scope: meta.parens.lisp + - match: \) + scope: meta.parens.lisp punctuation.section.parens.end.lisp + pop: 1 + - include: lists + - include: expressions + + macro-vectors: + # Vector + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node30.html + - match: (#\d*)(\() + captures: + 1: punctuation.definition.vector.lisp + 2: meta.parens.lisp punctuation.section.parens.begin.lisp + push: macro-vector-body + # Bit vector + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node32.html + - match: (#\d*\*)([01]*){{break}} + scope: meta.vector.lisp + captures: + 1: punctuation.definition.vector.lisp + 2: meta.number.integer.binary constant.numeric.value.lisp + + macro-vector-body: + - meta_scope: meta.vector.lisp + - meta_content_scope: meta.parens.lisp + - match: \) + scope: meta.parens.lisp punctuation.section.parens.end.lisp + pop: 1 + - include: parens + - include: expressions + + macro-throw-exceptions: + - match: '#[ \t\n\r)<]' + scope: keyword.control.exception.throw.lisp + + macro-variables: + # Inline runtime/loadtime eval + - match: \#[.,:] + scope: punctuation.definition.variable.lisp + # Local assignment + - match: ((#)\d+)\s*(=) + captures: + 1: variable.other.local.lisp + 2: punctuation.definition.variable.lisp + 3: keyword.operator.assignment.lisp + - match: (#)(\d+)(#) + scope: variable.other.lisp + captures: + 1: punctuation.definition.variable.begin.lisp + 2: variable.other.local.lisp + 3: punctuation.definition.variable.end.lisp + +###[ OPERATORS ]############################################################### + + modifiers: + # https://www.lispworks.com/documentation/lw70/CLHS/Body/02_df.htm + - match: '[`'']' + scope: punctuation.definition.quoted.lisp + - match: ',@?' + scope: punctuation.definition.variable.lisp + + operator: + # Contains 'Standardized Compound Type Specifier Names' + # https://www.lispworks.com/documentation/lw70/CLHS/Body/04_bc.htm + - match: (?:(?:/=|>=|<=|=|>|<)|(?i:max|min|eq|neq|eql|equalp|equal)){{break}} scope: keyword.operator.comparison.lisp - - match: '\+|\-|\*|\/|\b(?i:mod|rem|incf|decf)\b' + pop: 1 + - match: ={{break}} + scope: keyword.operator.assignment.lisp + pop: 1 + - match: (?:[-+*/]|(?i:mod|rem|incf|decf)){{break}} scope: keyword.operator.arithmetic.lisp - - match: \b(?i:and|or|not)\b + pop: 1 + - match: (?i:and|or|not|satisfies){{break}} scope: keyword.operator.logical.lisp - - match: \b(?i:logand|logior|logxor|lognor|logeqv)\b + pop: 1 + - match: (?i:logand|logior|logxor|lognor|logeqv){{break}} scope: keyword.operator.bitwise.lisp + pop: 1 - parens: - - match: '\(' - scope: punctuation.definition.group.begin.lisp - push: - - meta_scope: meta.group.lisp - - match: '\)' - scope: punctuation.definition.group.end.lisp - pop: true - - include: expressions - - include: parens - - match: '\)' - scope: invalid.illegal.stray-bracket-end.lisp - - constants: - - match: \b(?i:null|t|single-float-negative-epsilon|single-float-epsilon|short-float-negative-epsilon|short-float-epsilon|pi|nil|multiple-values-limit|most-positive-single-float|most-positive-short-float|most-positive-long-float|most-positive-fixnum|most-positive-double-float|most-negative-single-float|most-negative-short-float|most-negative-long-float|most-negative-fixnum|most-negative-double-float|long-float-negative-epsilon|long-float-epsilon|least-positive-single-float|least-positive-short-float|least-positive-normalized-single-float|least-positive-normalized-short-float|least-positive-normalized-long-float|least-positive-normalized-double-float|least-positive-long-float|least-positive-double-float|least-negative-single-float|least-negative-short-float|least-negative-normalized-single-float|least-negative-normalized-short-float|least-negative-normalized-long-float|least-negative-normalized-double-float|least-negative-long-float|least-negative-double-float|lambda-parameters-limit|lambda-list-keywords|internal-time-units-per-second|double-float-negative-epsilon|double-float-epsilon|char-super-bit|char-meta-bit|char-hyper-bit|char-font-limit|char-control-bit|char-code-limit|char-bits-limit|call-arguments-limit|array-total-size-limit|array-rank-limit|array-dimension-limit)\b - scope: constant.language.lisp - - match: '(#)(\w|[\\+-=<>''"&#])+' - scope: constant.character.lisp - captures: - 1: punctuation.definition.constant.lisp +###[ LITERALS ]################################################################ numbers: - - match: '\b((0(x|X)\h*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(?i:l|ul|u|f|ll|ull)?\b' - scope: constant.numeric.lisp + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node16.html + # https://www.lispworks.com/documentation/lw70/CLHS/Body/02_ca.htm + # decimal floating point + - match: |- + (?x) + ( [-+]? ) + ( \d* (?: (\.) \d+ ) {{exponent}}? + | \d+ (?: (\.) \d* )? {{exponent}}) + {{break}} + scope: meta.number.float.decimal.lisp + captures: + 1: keyword.operator.arithmetic.lisp + 2: constant.numeric.value.lisp + 3: punctuation.separator.decimal.lisp + 4: punctuation.separator.decimal.lisp + # decimal rational numbers + - match: |- + (?x) + ( [-+]? ) + ( \d+ (/) \d+ ) + {{break}} + scope: meta.number.rational.decimal.lisp + captures: + 1: keyword.operator.arithmetic.lisp + 2: constant.numeric.value.lisp + 3: keyword.operator.arithmetic.lisp + # decimal integer numbers + - match: |- + (?x) + ( [-+]? ) + ( \d+ (?: (\.)(?!\d) | {{break}} ) ) + scope: meta.number.integer.decimal.lisp + captures: + 1: keyword.operator.arithmetic.lisp + 2: constant.numeric.value.lisp + 3: punctuation.separator.decimal.lisp strings: - - match: '"' + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node31.html + - match: \" scope: punctuation.definition.string.begin.lisp + push: string-body + + string-body: + - meta_include_prototype: false + - meta_scope: meta.string.lisp string.quoted.double.lisp + - match: \" + scope: punctuation.definition.string.end.lisp + pop: 1 + - match: \\. + scope: constant.character.escape.lisp + - include: string-format-mini-language + + string-format-mini-language: + # https://www.hexstreamsoft.com/articles/common-lisp-format-reference/clhs-summary/#subsections-summary-table + - match: (~)(\d*)[%&|~] + scope: constant.character.escape.lisp + captures: + 1: punctuation.definition.placeholder.lisp + # 2: constant.numeric.integer.decimal.lisp + - match: (~):?@?[CR] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + # ~R + - match: |- + (?x: + (~) + (?:(\d*) # Radix + (?:(,)\d* # mincol + (?:(,)(?:'.)? # padchar + (?:(,)(?:'.)? # comma-char + (?:(,)\d*)? # comma-interval + )?)?)?) + ):?@?[rR] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.definition.numeric.base.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + 5: punctuation.separator.sequence.lisp + 6: punctuation.separator.sequence.lisp + # ~b, ~o, ~d, ~x + - match: |- + (?x: + (~) + (?:\d* # mincol + (?:(,)(?:'.)? # padchar + (?:(,)(?:'.)? # comma-char + (?:(,)\d*)? # comma-interval + )?)?)? + ):?@?[bBoOdDxX] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.separator.sequence.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + # ~f + - match: |- + (?x: + (~) + (?:\d* # width + (?:(,)\d* # decimals + (?:(,)\d* # scale + (?:(,)(?:'.)? # overflowchar + (?:(,)(?:'.)? # padchar + )?)?)?)?)? + )@?[fF] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.separator.sequence.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + 5: punctuation.separator.sequence.lisp + # ~e, ~g + - match: |- + (?x: + (~) + (?:\d* # width + (?:(,)\d* # decimals + (?:(,)\d* # exponent-width + (?:(,)\d* # scale + (?:(,)(?:'.)? # overflowchar + (?:(,)(?:'.)? # padchar + (?:(,)(?:'.)? # exponentchar + )?)?)?)?)?)?)? + )@?[eEgG] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.separator.sequence.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + 5: punctuation.separator.sequence.lisp + 6: punctuation.separator.sequence.lisp + 7: punctuation.separator.sequence.lisp + # ~$ + - match: |- + (?x: + (~) + (?:\d* # decimals + (?:(,)\d* # min-units + (?:(,)\d* # min-width + (?:(,)(?:'.)? # padchar + )?)?)?)? + ):?@?\$ + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.separator.sequence.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + # ~a, ~s + - match: |- + (?x: + (~) + (?:\d* # min-col + (?:(,)\d* # col-inc + (?:(,)\d* # min-pad + (?:(,)(?:'.)? # padchar + )?)?)?)? + ):?@?[aAsS] + scope: constant.other.placeholder.lisp + captures: + 1: punctuation.definition.placeholder.lisp + 2: punctuation.separator.sequence.lisp + 3: punctuation.separator.sequence.lisp + 4: punctuation.separator.sequence.lisp + +###[ SYMBOLS ]################################################################# + + annotations: + - match: (&){{identifier}} + scope: variable.annotation.lisp + captures: + 1: punctuation.definition.annotation.lisp + 2: punctuation.definition.symbol.begin.lisp + 3: punctuation.definition.symbol.end.lisp + + keywords: + # The colon : is a package marker. + # If the package name is missing, the symbol is in the KEYWORD package. + - match: (::?)({{identifier}}) + captures: + 1: punctuation.accessor.lisp + 2: keyword.other.symbol.lisp + 3: punctuation.definition.symbol.begin.lisp + 4: punctuation.definition.symbol.end.lisp + - match: \.{{break}} + scope: keyword.control.lisp + + identifiers: + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node27.html + # Pushing a dedicated context reduces syntax cache size + # and increases parsing performance, significantly. + - match: (?={{identifier}}) + push: identifier + + identifier: + - include: namespaces + # types + - match: '{{builtin_types}}' + scope: storage.type.lisp + pop: 1 + # constants + - match: (?i:true|false){{break}} + scope: constant.language.boolean.lisp + pop: 1 + - match: (?i:nil|null){{break}} + scope: constant.language.null.lisp + pop: 1 + - match: '{{builtin_constants}}' + scope: constant.language.lisp + pop: 1 + - match: \+\S+\+{{break}} + scope: constant.other.lisp + pop: 1 + # variables + - match: '{{builtin_variables}}' + scope: variable.language.lisp + pop: 1 + - match: '{{identifier}}' + scope: variable.other.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: immediately-pop + + parameters: + # parameter with initial value + - match: \( + scope: punctuation.section.parens.begin.lisp push: - - meta_scope: string.quoted.double.lisp - - match: '"' - scope: punctuation.definition.string.end.lisp - pop: true - - match: \\. - scope: constant.character.escape.lisp - - block-comment: - - match: '#\|' - scope: punctuation.definition.comment.begin.lisp - push: - - meta_scope: comment.block.lisp - - include: block-comment - - match: '\|#' - scope: punctuation.definition.comment.end.lisp - pop: true + - paren-body + - parameter-name + # parameter without initial value + - match: '{{identifier}}' + scope: variable.parameter.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp - comments: - - include: block-comment - - match: '\|#' - scope: invalid.illegal.stray-comment-end.lisp - - match: (;).*$\n? - scope: comment.line.semicolon.lisp + parameter-name: + - include: annotations + - include: keywords + - include: modifiers + - match: '{{identifier}}' + scope: variable.parameter.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + pop: 1 + - include: comments + - include: else-pop + + namespaces: + # built-in namespace indicating keyword symbols + # note: accessor is consumed by `keywords` context + - match: (\|?)keyword(\|?)(?=:) + scope: variable.namespace.lisp + captures: + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + # normal namespaces but not an escaped char #\: + - match: ((?!#\\?){{identifier}})(::?) + captures: + 1: variable.namespace.lisp + 2: punctuation.definition.symbol.begin.lisp + 3: punctuation.definition.symbol.end.lisp + 4: punctuation.accessor.lisp + + variables: + # Symbols evaluate to their values + # https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node27.html + - match: '{{identifier}}' + scope: variable.other.lisp captures: - 1: punctuation.definition.comment.lisp + 1: punctuation.definition.symbol.begin.lisp + 2: punctuation.definition.symbol.end.lisp + +###[ PROTOTYPES ]############################################################## + + else-pop: + - match: (?=\S) + pop: 1 + + immediately-pop: + - match: '' + pop: 1 + + paren-pop: + - match: (?=\)) + pop: 1 + +############################################################################### + +variables: + + # variables / keyword-symbols + identifier: (?:{{identifier_char}}*{{identifier_must_have}}{{identifier_char}}*|{{quoted_identifier}}) + identifier_char: (?:\\.|[^{{break_char}}]) + identifier_must_have: (?:\\.|[^\d.{{break_char}}]) # May not be only digits or periods + quoted_identifier: (\|)(?:\\.|[^|])*(\|) + + break: (?={{break_char}}|$) + break_char: '[\s()"'',:;|]' + + # caracters + standard_char: '[0-9A-Za-z!"#$%&''()*+,\-./:;<=>?@\\\[\]^_`{|}~]' + char_attributes: (?:(?:[[:alnum:]_]+-)+\\?) + + # numbers + exponent: (?:[esfdlESFDL][-+]?\d+) + + declaration_keywords: |- + (?xi: + declaim + | define-(?: compiler-macro | condition | declaration | method-combination | modify-macro | setf-method ) + | def(?: class | constant | generic | macro | method | package | parameter | setf | struct | type | un | var ) + | generic-(?: flet | function | labels ) + | flet + | labels + | let\*? + | locally + | macrolet + | multiple-value-bind + | proclaim + | prog\*? + | with-(?: accessors | added-methods | condition-restarts | input-from-string | open-file | open-stream | output-to-string | standard-io-syntax ) + ){{break}} + + declaration_identifiers: |- + (?xi: + dynamic-extent + | ftype + | ignorable + | ignore + | inline + | notinline + | optimize + | special + | type + ){{break}} + + builtin_constants: |- + (?xi: + t | true | false | null | nil | pi + | array-(?: rank | dimension | total-size )-limit + | call-arguments-limit + | char-(?: (?: super | hyper | meta | control )-bit | (?: font | code | bits )-limit ) + | internal-time-units-per-second + | lambda-(?: parameters-limit | list-keywords ) + | least-(?: positive | negative )-normalized-(?: single | short | long | double )-float + | most-(?: positive | negative )-fixnum + | (?: most | least )-(?: positive | negative )-(?: single | short | long | double )-float + | multiple-values-limit + | (?: single | short | long | double )-float-(?: negative- )?epsilon + ){{break}} + + builtin_functions: |- + (?xi: + abort + | abs + | acons + | acos + | acosh + | add-method + | adjoin + | adjust-array + | adjustable-array-p + | alpha-char-p + | alphanumericp + | alter + | append + | appending + | apply + | applyhook + | apropos + | apropos-list + | aref + | arithmetic-error-operands + | arithmetic-error-operation + | array-dimension + | array-dimensions + | array-element-type + | array-has-fill-pointer-p + | array-in-bounds-p + | array-rank + | array-row-major-index + | array-total-size + | arrayp + | ash + | asin + | asinh + | assert + | assoc + | assoc-if + | assoc-if-not + | atan + | atanh + | atom + | augment-environment + | bit + | bit-and + | bit-andc1 + | bit-andc2 + | bit-eqv + | bit-ior + | bit-nand + | bit-nor + | bit-not + | bit-orc1 + | bit-orc2 + | bit-vector-p + | bit-xor + | boole + | both-case-p + | boundp + | break + | broadcast-stream-streams + | butlast + | byte + | byte-position + | byte-size + | caaaar + | caaadr + | caaar + | caadar + | caaddr + | caadr + | caar + | cadaar + | cadadr + | cadar + | caddar + | cadddr + | caddr + | cadr + | call-method + | call-next-method + | car + | catenate + | ccase + | cdaaar + | cdaadr + | cdaar + | cdadar + | cdaddr + | cdadr + | cdar + | cddaar + | cddadr + | cddar + | cdddar + | cddddr + | cdddr + | cddr + | cdr + | ceiling + | cell-error-name + | cerror + | change-class + | char + | char-bit + | char-bits + | char-code + | char-downcase + | char-equal + | char-font + | char-greaterp + | char-int + | char-lessp + | char-name + | char-not-equal + | char-not-greaterp + | char-not-lessp + | char-upcase + | char/= + | char< + | char<= + | char= + | char> + | char>= + | character + | characterp + | check-type + | choose + | choose-if + | chunk + | cis + | class-name + | class-of + | clear-input + | close + | clrhash + | code-char + | coerce + | collect + | collect-alist + | collect-and + | collect-append + | collect-file + | collect-first + | collect-fn + | collect-hash + | collect-last + | collect-length + | collect-max + | collect-min + | collect-nconc + | collect-nth + | collect-or + | collect-plist + | collect-sum + | collecting + | collecting-fn + | commonp + | compile + | compile-file + | compile-file-pathname + | compiled-function-p + | compiler-let + | compiler-macro-function + | compiler-macroexpand + | compiler-macroexpand-1 + | complement + | complex + | complexp + | compute-applicable-methods + | compute-restarts + | concatenate + | concatenated-stream-streams + | conjugate + | cons + | consp + | constantp + | continue + | copy-alist + | copy-list + | copy-pprint-dispatch + | copy-readtable + | copy-seq + | copy-symbol + | copy-tree + | cos + | cosh + | cotruncate + | count + | count-if + | count-if-not + | counting + | declaim + | declaration-information + | decode-float + | decode-universal-time + | delete + | delete-duplicates + | delete-file + | delete-if + | delete-if-not + | delete-package + | denominator + | deposit-field + | describe + | describe-object + | destructuring-bind + | digit-char + | digit-char-p + | directory + | directory-namestring + | disassemble + | do-all-keyword-symbols + | do-external-keyword-symbols + | do-keyword-symbols + | documentation + | dolist + | dpb + | dribble + | ecase + | echo-stream-input-stream + | echo-stream-output-stream + | ed + | eighth + | elt + | encapsulated + | enclose + | encode-universal-time + | endp + | enough-namestring + | ensure-generic-function + | error + | eval + | evalhook + | evenp + | every + | exp + | expand + | export + | expt + | f + | fboundp + | fdefinition + | ffloor + | fifth + | file-author + | file-error-pathname + | file-length + | file-namestring + | file-position + | file-string-length + | file-write-date + | fill + | fill-pointer + | find + | find-all-keyword-symbols + | find-class + | find-if + | find-if-not + | find-method + | find-package + | find-restart + | find-symbol + | finish-output + | first + | float + | float-digits + | float-precision + | float-radix + | float-sign + | floatp + | floor + | format + | formatter + | fourth + | funcall + | function-information + | function-keywords + | function-lambda-expression + | functionp + | gatherer + | gathering + | gcd + | generator + | generic-function + | gensym + | gentemp + | get + | get-decoded-time + | get-internal-real-time + | get-internal-run-time + | get-output-stream-string + | get-properties + | get-setf-method + | get-setf-method-multiple-value + | get-universal-time + | getf + | gethash + | graphic-char-p + | handler-bind + | handler-case + | hash-table-count + | hash-table-p + | hash-table-rehash-size + | hash-table-rehash-threshold + | hash-table-size + | hash-table-test + | host-namestring + | identity + | ignore-errors + | imagpart + | import + | in-package + | initialize-instance + | input-stream-p + | inspect + | int-char + | integer-decode-float + | integer-length + | integerp + | interactive-stream-p + | intern + | intersection + | invalid-method-error + | invoke-debugger + | invoke-restart + | isqrt + | iterate + | keywordp + | last + | latch + | lcm + | ldb + | ldb-test + | ldiff + | length + | lisp-implementation-type + | lisp-implementation-version + | list + | list-all-packages + | list-length + | list\* + | listen + | listp + | load + | load-logical-pathname-translations + | locally + | log + | logandc1 + | logandc2 + | logbitp + | logcount + | logical-pathname + | logical-pathname-translations + | lognand + | lognot + | logorc1 + | logorc2 + | logtest + | long-site-name + | loop-finish + | lower-case-p + | machine-instance + | machine-type + | machine-version + | macro-function + | macroexpand + | macroexpand-1 + | make-array + | make-broadcast-stream + | make-char + | make-concatenated-stream + | make-condition + | make-dispatch-macro-character + | make-echo-stream + | make-hash-table + | make-instance + | make-instances-obsolete + | make-list + | make-load-form + | make-load-form-saving-slots + | make-package + | make-pathname + | make-random-state + | make-sequence + | make-string + | make-string-input-stream + | make-string-output-stream + | make-symbol + | make-synonym-stream + | make-two-way-stream + | makunbound + | map + | map-fn + | map-into + | maphash + | mapping + | mask + | mask-field + | maximize + | maximizing + | member + | member-if + | member-if-not + | memberp + | merge + | merge-pathnames + | method-combination-error + | method-qualifiers + | mingle + | minimize + | minimizing + | minusp + | mismatch + | muffle-warning + | multiple-value-bind + | multiple-value-list + | multiple-value-setq + | name-char + | namestring + | nbutlast + | nconc + | nconcing + | next-in + | next-method-p + | next-out + | nintersection + | ninth + | no-applicable-method + | no-next-method + | notany + | notevery + | nreconc + | nreverse + | nset-difference + | nset-exclusive-or + | nstring-capitalize + | nstring-downcase + | nstring-upcase + | nsublis + | nsubst + | nsubst-if + | nsubst-if-not + | nsubstitute + | nsubstitute-if + | nsubstitute-if-not + | nth + | nth-value + | nthcdr + | numberp + | numerator + | nunion + | oddp + | open + | open-stream-p + | output-stream-p + | package-error-package + | package-name + | package-nicknames + | package-shadowing-keyword-symbols + | package-use-list + | package-used-by-list + | packagep + | pairlis + | parse-integer + | parse-macro + | parse-namestring + | pathname + | pathname-device + | pathname-directory + | pathname-host + | pathname-match-p + | pathname-name + | pathname-type + | pathname-version + | pathnamep + | peek-char + | phase + | plusp + | pop + | position + | position-if + | position-if-not + | positions + | pprint-dispatch + | pprint-exit-if-list-exhausted + | pprint-fill + | pprint-indent + | pprint-linear + | pprint-logical-block + | pprint-newline + | pprint-pop + | pprint-tab + | pprint-tabular + | previous + | prin1 + | print + | print-object + | print-unreadable-object + | probe-file + | producing + | prog1 + | prog2 + | progn + | provide + | psetf + | psetq + | push + | pushnew + | quote + | random + | random-state-p + | rassoc + | rassoc-if + | rassoc-if-not + | rational + | rationalize + | rationalp + | read + | read-byte + | read-char + | read-char-no-hang + | read-delimited-list + | read-from-string + | read-line + | read-preserving-whitespace + | readtable-case + | readtablep + | realp + | realpart + | reduce + | reinitialize-instance + | remf + | remhash + | remove + | remove-duplicates + | remove-method + | remprop + | rename-file + | rename-package + | replace + | require + | rest + | restart-bind + | restart-case + | restart-name + | result-of + | revappend + | reverse + | room + | rotatef + | round + | row-major-aref + | rplaca + | rplacd + | sbit + | scale-float + | scan + | scan-alist + | scan-file + | scan-fn + | scan-fn-inclusive + | scan-hash + | scan-lists-of-lists + | scan-lists-of-lists-fringe + | scan-multiple + | scan-plist + | scan-range + | scan-sublists + | scan-symbols + | schar + | search + | second + | series + | set + | set-char-bit + | set-difference + | set-dispatch-macro-character + | set-exclusive-or + | set-macro-character + | set-pprint-dispatch + | set-syntax-from-char + | setf + | setq + | seventh + | shadow + | shadowing-import + | shared-initialize + | shiftf + | short-site-name + | signal + | signum + | simple-bit-vector-p + | simple-condition-format-arguments + | simple-condition-format-string + | simple-string-p + | simple-vector-p + | sin + | sinh + | sixth + | sleep + | slot-boundp + | slot-exists-p + | slot-makunbound + | slot-missing + | slot-unbound + | slot-value + | software-type + | software-version + | some + | sort + | special-form-p + | split + | split-if + | sqrt + | stable-sort + | standard-char-p + | step + | store-value + | stream-element-type + | stream-error-stream + | stream-external-format + | streamp + | string + | string-capitalize + | string-downcase + | string-equal + | string-greaterp + | string-left-trim + | string-lessp + | string-not-equal + | string-not-greaterp + | string-not-lessp + | string-right-trim + | string-trim + | string-upcase + | string/= + | string< + | string<= + | string= + | string> + | string>= + | stringp + | sublis + | subseq + | subseries + | subsetp + | subst + | subst-if + | subst-if-not + | substitute + | substitute-if + | substitute-if-not + | subtypep + | sum + | summing + | svref + | sxhash + | symbol-function + | symbol-name + | symbol-package + | symbol-plist + | symbol-value + | symbolp + | synonym-stream-symbol + | tailp + | tan + | tanh + | tenth + | terminate-producing + | terpri + | third + | time + | to-alter + | trace + | translate-logical-pathname + | translate-pathname + | tree-equal + | truename + | truncate + | two-way-stream-input-stream + | two-way-stream-output-stream + | type-error-datum + | type-error-expected-type + | type-of + | typep + | unexport + | unintern + | union + | unread-char + | untrace + | unuse-package + | update-instance-for-different-class + | update-instance-for-redefined-class + | upgraded-array-element-type + | upgraded-complex-part-type + | upper-case-p + | use-package + | use-value + | user-homedir-pathname + | values + | values-list + | variable-information + | vector + | vector-pop + | vector-push + | vector-push-extend + | vectorp + | warn + | wild-pathname-p + | with-compilation-unit + | with-hash-table-iterator + | with-package-iterator + | with-simple-restart + | with-standard-io-syntax + | write + | write-byte + | write-char + | write-string + | write-to-string + | y-or-n-p + | yes-or-no-p + | zerop + ){{break}} + + # Built-in atomic type specifiers + # https://www.lispworks.com/documentation/lw70/CLHS/Body/04_bc.htm + # Note: Some of them are scoped function when appearing as first list item. + builtin_types: |- + (?xi: + arithmetic-error + | array + | atom + | base-char + | base-string + | bignum + | bit + | bit-vector + | broadcast-stream + | built-in-class + | cell-error + | character + | class + | compiled-function + | complex + | concatenated-stream + | condition + | cons + | control-error + | division-by-zero + | double-float + | echo-stream + | end-of-file + | error + | extended-char + | file-error + | file-stream + | fixnum + | float + | floating-point-inexact + | floating-point-invalid-operation + | floating-point-overflow + | floating-point-underflow + | function + | generic-function + | hash-table + | integer + | keyword + | list + | logical-pathname + | long-float + | method + | method-combination + | number + | package + | package-error + | parse-error + | pathname + | print-not-readable + | program-error + | random-state + | ratio + | rational + | reader-error + | readtable + | real + | restart + | sequence + | serious-condition + | short-float + | signed-byte + | simple-array + | simple-base-string + | simple-bit-vector + | simple-condition + | simple-error + | simple-string + | simple-type-error + | simple-vector + | simple-warning + | single-float + | standard-char + | standard-class + | standard-generic-function + | standard-method + | standard-object + | storage-condition + | stream + | stream-error + | string + | string-stream + | structure-class + | structure-object + | style-warning + | symbol + | synonym-stream + | two-way-stream + | type-error + | unbound-slot + | unbound-variable + | undefined-function + | unsigned-byte + | vector + | warning + ){{break}} + + builtin_variables: |- + \*(?xi: + applyhook + | break-on-signals + | break-on-warnings + | compile-file-pathname + | compile-file-truename + | compile-print + | compile-verbose + | debug-io + | debugger-hook + | default-pathname-defaults + | error-output + | evalhook + | features + | gensym-counter + | load-pathname + | load-print + | load-truename + | load-verbose + | macroexpand-hook + | modules + | package + | print-array + | print-base + | print-case + | print-circle + | print-escape + | print-gensym + | print-length + | print-level + | print-lines + | print-miser-width + | print-pprint-dispatch + | print-pretty + | print-radix + | print-readably + | print-right-margin + | query-io + | random-state + | read-base + | read-default-float-format + | read-eval + | read-suppress + | readtable + | standard-input + | standard-output + | suppress-series-warnings + | terminal-io + | trace-output + )\*{{break}} ================================================ FILE: assets/patches/Makefile.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Makefile/Makefile.sublime-syntax syntaxes/01_Packages/Makefile/Makefile.sublime-syntax index 3cc3a97e..0c7a3f24 100644 --- syntaxes/01_Packages/Makefile/Makefile.sublime-syntax +++ syntaxes/01_Packages/Makefile/Makefile.sublime-syntax @@ -44,64 +44,50 @@ variables: # variable substitutions anywhere. We try to remedy this by hacking in a # regex that matches up to four levels of nested parentheses, and ignores # whatever's inside the parentheses. - nps: '[^()]*' - open: '(?:\(' - close: '\))?' # ignore this invalid.illegal + nps_unnested: '[^()]*' + nps: '[^()]*(?=[()])' + open: '(?:{{nps}}\(' + close: '\){{nps_unnested}})?' # ignore this invalid.illegal just_eat: | # WARNING: INSANITY FOLLOWS! - (?x) # ignore whitespace in this regex - {{nps}} # level 0 + (?x)(?: # ignore whitespace in this regex {{open}} # start level 1 __ - {{nps}} # level 1 _______ /*_>-< {{open}} # start level 2 ___/ _____ \__/ / - {{nps}} # level 2 <____/ \____/ {{open}} # start level 3 is like snek... (by Valerie Haecky) - {{nps}} # level 3 {{open}} # start level 4 {{nps}} # level 4 {{close}} # end level 4 - {{nps}} # level 3 {{close}} # end level 3 - {{nps}} # level 2 {{open}} # start level 3 - {{nps}} # level 3 {{open}} # start level 4 {{nps}} # level 4 {{close}} # end level 4 - {{nps}} # level 3 {{close}} # end level 3 - {{nps}} # level 2 + {{nps}} {{close}} # end level 2 - {{nps}} # level 1 {{open}} # start level 2 - {{nps}} # level 2 {{open}} # start level 3 - {{nps}} # level 3 {{open}} # start level 4 {{nps}} # level 4 {{close}} # end level 4 - {{nps}} # level 3 + {{nps}} {{close}} # end level 3 - {{nps}} # level 2 {{open}} # start level 3 - {{nps}} # level 3 {{open}} # start level 4 {{nps}} # level 4 {{close}} # end level 4 - {{nps}} # level 3 + {{nps}} {{close}} # end level 3 - {{nps}} # level 2 {{open}} # start level 3 - {{nps}} # level 3 {{open}} # start level 4 {{nps}} # level 4 {{close}} # end level 4 - {{nps}} # level 3 + {{nps}} {{close}} # end level 3 - {{nps}} # level 2 + {{nps}} {{close}} # end level 2 - {{nps}} # level 1 + {{nps}} {{close}} # end level 1 - {{nps}} # level 0 + |{{nps_unnested}}) rule_lookahead: '{{just_eat}}{{ruleassign}}{{just_eat}}' var_lookahead_base: '{{just_eat}}({{varassign}}|{{shellassign}}){{just_eat}}' ================================================ FILE: assets/patches/Markdown.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Markdown/Markdown.sublime-syntax syntaxes/01_Packages/Markdown/Markdown.sublime-syntax index 19dc685d..3a45ea05 100644 --- syntaxes/01_Packages/Markdown/Markdown.sublime-syntax +++ syntaxes/01_Packages/Markdown/Markdown.sublime-syntax @@ -24,7 +24,6 @@ variables: ) [ \t]*$ # followed by any number of tabs or spaces, followed by the end of the line ) - setext_escape: ^(?=\s{0,3}(?:---+|===+)\s*$) block_quote: (?:[ ]{,3}>(?:.|$)) # between 0 and 3 spaces, followed by a greater than sign, followed by any character or the end of the line atx_heading: (?:[#]{1,6}\s*) # between 1 and 6 hashes, followed by any amount of whitespace indented_code_block: (?:[ ]{4}|\t) # 4 spaces or a tab @@ -277,69 +276,40 @@ contexts: 8: markup.underline.link.markdown push: [link-ref-def, after-link-title, link-title] - match: '^(?=\S)(?![=-]{3,}\s*$)' - branch_point: heading2-branch - branch: - - not-heading2 - - heading2 - - not-paragraph: - - match: |- - (?x) # pop out of this context when one of the following conditions are met: - ^(?: - \s*$ # the line is blank (or only contains whitespace) - | (?= - {{block_quote}} # a block quote begins the line - | [ ]{,3}[*+-][ ] # an unordered list item begins the line - | [ ]{,3}1[.][ ] # an ordered list item with number "1" begins the line - | \# # an ATX heading begins the line - | [ ]{,3}<( # all types of HTML blocks except type 7 may interrupt a paragraph - {{html_tag_block_end_at_close_tag}} # 1 - | !-- # 2 - | \? # 3 - | ![A-Z] # 4 - | !\[CDATA\[ # 5 - | {{html_tag_block_end_at_blank_line}} # 6 + push: + - meta_scope: meta.paragraph.markdown + - match: |- + (?x) # pop out of this context when one of the following conditions are met: + ^(?: + \s*$ # the line is blank (or only contains whitespace) + | (?= + {{block_quote}} # a block quote begins the line + | [ ]{,3}[*+-][ ] # an unordered list item begins the line + | [ ]{,3}1[.][ ] # an ordered list item with number "1" begins the line + | \# # an ATX heading begins the line + | [ ]{,3}<( # all types of HTML blocks except type 7 may interrupt a paragraph + {{html_tag_block_end_at_close_tag}} # 1 + | !-- # 2 + | \? # 3 + | ![A-Z] # 4 + | !\[CDATA\[ # 5 + | {{html_tag_block_end_at_blank_line}} # 6 + ) ) ) - ) - pop: true - - not-heading2: - - include: not-paragraph - - match: (?=\S) - branch_point: heading1-branch - branch: - - paragraph - - heading1 - - match: '' - pop: true - - paragraph: - - meta_scope: meta.paragraph.markdown - - match: ^\s{0,3}===+\s*$ - fail: heading1-branch - - match: ^\s{0,3}---+\s*$ - fail: heading2-branch - - include: not-paragraph - - include: inline-bold-italic-linebreak - - include: scope:text.html.basic - - heading1: - - meta_scope: markup.heading.1.markdown - - include: inline-bold-italic-linebreak - - match: '^[ \t]{0,3}(={3,})(?=[ \t]*$)' - captures: - 1: markup.heading.1.setext.markdown punctuation.definition.heading.setext.markdown - pop: true - - heading2: - - meta_scope: markup.heading.2.markdown - - include: inline-bold-italic-linebreak - - match: '^[ \t]{0,3}(-{3,})(?=[ \t]*$)' - captures: - 1: markup.heading.2.setext.markdown punctuation.definition.heading.setext.markdown - pop: true - + pop: true + - include: inline-bold-italic-linebreak + - include: scope:text.html.basic + - match: '^(={3,})(?=[ \t]*$)' + scope: markup.heading.1.setext.markdown + captures: + 1: punctuation.definition.heading.setext.markdown + pop: true + - match: '^(-{3,})(?=[ \t]*$)' + scope: markup.heading.2.setext.markdown + captures: + 1: punctuation.definition.heading.setext.markdown + pop: true link-ref-def: - meta_scope: meta.link.reference.def.markdown - match: '' @@ -430,8 +400,6 @@ contexts: push: - meta_scope: markup.bold.markdown - meta_content_scope: markup.italic.markdown - - match: '{{setext_escape}}' - pop: true - match: |- (?x) [ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic @@ -446,8 +414,6 @@ contexts: scope: punctuation.definition.bold.end.markdown set: - meta_content_scope: markup.italic.markdown - - match: '{{setext_escape}}' - pop: true - match: |- (?x) [ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic @@ -463,8 +429,6 @@ contexts: scope: punctuation.definition.italic.end.markdown set: - meta_content_scope: markup.bold.markdown - - match: '{{setext_escape}}' - pop: true - match: |- (?x) [ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic @@ -727,8 +691,6 @@ contexts: scope: punctuation.definition.italic.begin.markdown push: - meta_scope: markup.italic.markdown - - match: '{{setext_escape}}' - pop: true - match: |- (?x) [ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic @@ -745,8 +707,6 @@ contexts: scope: punctuation.definition.italic.begin.markdown push: - meta_scope: markup.italic.markdown - - match: '{{setext_escape}}' - pop: true - match: |- (?x) [ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic @@ -773,8 +733,6 @@ contexts: - include: bold-italic-trailing bold-italic-trailing: - include: scope:text.html.basic - - match: '{{setext_escape}}' - pop: true - match: ^\s*$\n? scope: invalid.illegal.non-terminated.bold-italic.markdown pop: true @@ -1073,6 +1031,36 @@ contexts: escape: '{{code_fence_escape}}' escape_captures: 0: meta.code-fence.definition.end.python.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:puppet)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.puppet.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.puppet + embed_scope: markup.raw.code-fence.puppet.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.puppet.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:typescript|ts)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.typescript.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ts + embed_scope: markup.raw.code-fence.typescript.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.typescript.markdown-gfm 1: punctuation.definition.raw.code-fence.end.markdown - match: |- (?x) @@ -1152,7 +1155,7 @@ contexts: - match: |- (?x) {{fenced_code_block_start}} - ((?i:rust)) + ((?i:rust|rs)) {{fenced_code_block_trailing_infostring_characters}} captures: 0: meta.code-fence.definition.begin.rust.markdown-gfm ================================================ FILE: assets/patches/MediaWiki.sublime-syntax.patch ================================================ diff --git syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax index f542c9e..8eaf020 100644 --- syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax +++ syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax @@ -1,7 +1,7 @@ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html -name: Mediawiki NG +name: MediaWiki file_extensions: [mediawiki, wikipedia, wiki] scope: text.html.mediawiki ================================================ FILE: assets/patches/Monokai-Extended.tmTheme.patch ================================================ diff --git themes/sublime-monokai-extended/Monokai\ Extended.tmTheme themes/sublime-monokai-extended/Monokai\ Extended.tmTheme index 9c2aa3e..180cbbf 100644 --- themes/sublime-monokai-extended/Monokai Extended.tmTheme +++ themes/sublime-monokai-extended/Monokai Extended.tmTheme @@ -810,11 +810,11 @@ name JSON String scope - meta.structure.dictionary.json string.quoted.double.json + meta.mapping.key.json string.quoted.double.json, punctuation.separator.sequence.csv settings foreground - #cfcfc2 + #fd971f @@ -1027,7 +1027,7 @@ name Invalid scope - invalid + invalid, meta.annotation.error-line settings background @@ -1038,11 +1038,22 @@ #f8f8f0 + + name + Error + scope + markup.error + settings + + foreground + #dd2020 + + name Invalid deprecated scope - invalid.deprecated + invalid.deprecated, markup.warning settings background ================================================ FILE: assets/patches/OneHalfDark.tmTheme.patch ================================================ diff --git themes/onehalf/sublimetext/OneHalfDark.tmTheme themes/onehalf/sublimetext/OneHalfDark.tmTheme index b16050c..b021071 100644 --- themes/onehalf/sublimetext/OneHalfDark.tmTheme +++ themes/onehalf/sublimetext/OneHalfDark.tmTheme @@ -28,7 +28,7 @@ name - OneHalfLight + OneHalfDark semanticClass theme.dark.one_half_dark uuid @@ -155,7 +155,7 @@ name Classes scope - support.class, entity.name.class, entity.name.type.class + support.class, entity.name.class, entity.name.type.class, entity.name settings foreground @@ -188,7 +188,7 @@ name Storage scope - storage + storage, meta.mapping.key string settings foreground @@ -309,7 +309,7 @@ name Markdown: Headings scope - markup.heading punctuation.definition.heading, entity.name.section + markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle @@ -660,4 +660,4 @@ - \ No newline at end of file + ================================================ FILE: assets/patches/Python.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Python/Python.sublime-syntax syntaxes/01_Packages/Python/Python.sublime-syntax index 2acd86d8..86257f7b 100644 --- syntaxes/01_Packages/Python/Python.sublime-syntax +++ syntaxes/01_Packages/Python/Python.sublime-syntax @@ -988,10 +988,6 @@ contexts: - match: \} scope: punctuation.section.mapping-or-set.end.python set: after-expression - - match: (?={{simple_expression}}:|\s*\*\*) - set: inside-dictionary - - match: (?={{simple_expression}}[,}]|\s*\*) - set: inside-set - match: ',' scope: punctuation.separator.set.python set: inside-set ================================================ FILE: assets/patches/Rust.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/Rust/Rust.sublime-syntax syntaxes/01_Packages/Rust/Rust.sublime-syntax index 3c354486..24727a4e 100644 --- syntaxes/01_Packages/Rust/Rust.sublime-syntax +++ syntaxes/01_Packages/Rust/Rust.sublime-syntax @@ -907,6 +907,8 @@ contexts: - include: type-any-identifier - match: ':' scope: punctuation.separator.rust + - match: (?=;) + pop: true fn-body: - meta_scope: meta.function.rust ================================================ FILE: assets/patches/ShellScript.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/ShellScript/Bash.sublime-syntax syntaxes/01_Packages/ShellScript/Bash.sublime-syntax index e973e319..07c170a7 100644 --- syntaxes/01_Packages/ShellScript/Bash.sublime-syntax +++ syntaxes/01_Packages/ShellScript/Bash.sublime-syntax @@ -30,12 +30,12 @@ file_extensions: - .zshenv - .zshrc - PKGBUILD # https://jlk.fjfi.cvut.cz/arch/manpages/man/PKGBUILD.5 - - .ebuild - - .eclass + - ebuild + - eclass first_line_match: | (?x) - ^\#! .* \b(bash|zsh|sh|tcsh|ash)\b + ^\#! .* \b(bash|zsh|sh|tcsh|ash|dash|ksh)\b | ^\# \s* -\*- [^*]* mode: \s* shell-script [^*]* -\*- #------------------------------------------------------------------------------- ================================================ FILE: assets/patches/TodoTxt.sublime-syntax.patch ================================================ diff --git syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax index 6c75dbb..0115978 100644 --- syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax +++ syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax @@ -68,7 +68,7 @@ contexts: - match: (\s+[^\s:]+:[^\s:]+)+\s*$ comment: Custom attributes - scope: variable.annotation.todotxt.attribute + scope: variable.other.todotxt.attribute comments: # Comments begin with a '//' and finish at the end of the line. ================================================ FILE: assets/patches/TwoDark.tmTheme.patch ================================================ diff --git themes/TwoDark/TwoDark.tmTheme themes/TwoDark/TwoDark.tmTheme index 87fd358..56376d3 100644 --- themes/TwoDark/TwoDark.tmTheme +++ themes/TwoDark/TwoDark.tmTheme @@ -125,7 +125,7 @@ name Classes scope - support.class, entity.name.class, entity.name.type.class + support.class, entity.name.class, entity.name.type.class, entity.name settings foreground @@ -290,7 +290,7 @@ name Headings scope - markup.heading punctuation.definition.heading, entity.name.section + markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle @@ -533,7 +533,7 @@ name Json key scope - source.json meta.structure.dictionary.json string.quoted.double.json + source.json meta.mapping.key.json string.quoted.double.json settings foreground @@ -875,4 +875,4 @@ comment Work in progress - \ No newline at end of file + ================================================ FILE: assets/patches/XML.sublime-syntax.patch ================================================ diff --git syntaxes/01_Packages/XML/XML.sublime-syntax syntaxes/01_Packages/XML/XML.sublime-syntax index ad7d9c87..af4a00f0 100644 --- syntaxes/01_Packages/XML/XML.sublime-syntax +++ syntaxes/01_Packages/XML/XML.sublime-syntax @@ -12,6 +12,7 @@ file_extensions: - rss - opml - svg + - xaml first_line_match: |- (?x: ^(?: ================================================ FILE: assets/syntaxes/02_Extra/Apache.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Apache Conf file_extensions: - envvars - htaccess - HTACCESS - htgroups - HTGROUPS - htpasswd - HTPASSWD - .htaccess - .HTACCESS - .htgroups - .HTGROUPS - .htpasswd - .HTPASSWD scope: source.apacheconf contexts: main: - match: ^(\s)*(#).*$\n? scope: comment.line.hash.ini captures: 1: punctuation.definition.comment.apacheconf - match: (<)(Proxy|ProxyMatch|IfVersion|Directory|DirectoryMatch|Files|FilesMatch|IfDefine|IfModule|Limit|LimitExcept|Location|LocationMatch|VirtualHost|Macro|If|Else|ElseIf)(\s(.+?))?(>) captures: 1: punctuation.definition.tag.apacheconf 2: entity.tag.apacheconf 4: string.value.apacheconf 5: punctuation.definition.tag.apacheconf - match: () captures: 1: punctuation.definition.tag.apacheconf 2: entity.tag.apacheconf 3: punctuation.definition.tag.apacheconf - match: (?<=(Rewrite(Rule|Cond)))\s+(.+?)\s+(.+?)($|\s) captures: 3: string.regexp.apacheconf 4: string.replacement.apacheconf - match: (?<=RedirectMatch)(\s+(\d\d\d|permanent|temp|seeother|gone))?\s+(.+?)\s+((.+?)($|\s))? captures: 2: entity.status.apacheconf 3: string.regexp.apacheconf 5: string.path.apacheconf - match: (?<=Redirect)(\s+(\d\d\d|permanent|temp|seeother|gone))?\s+(.+?)\s+((.+?)($|\s))? captures: 2: entity.status.apacheconf 3: string.path.apacheconf 5: string.path.apacheconf - match: (?<=ScriptAliasMatch|AliasMatch)\s+(.+?)\s+((.+?)\s)? captures: 1: string.regexp.apacheconf 3: string.path.apacheconf - match: (?<=RedirectPermanent|RedirectTemp|ScriptAlias|Alias)\s+(.+?)\s+((.+?)($|\s))? captures: 1: string.path.apacheconf 3: string.path.apacheconf - match: \b(AcceptPathInfo|AccessFileName|AddDefaultCharset|AddOutputFilterByType|AllowEncodedSlashes|AllowOverride|AuthName|AuthType|CGIMapExtension|ContentDigest|DefaultType|Define|DocumentRoot|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|FileETag|ForceType|HostnameLookups|IdentityCheck|Include(Optional)?|KeepAlive|KeepAliveTimeout|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|LogLevel|MaxKeepAliveRequests|Mutex|NameVirtualHost|Options|Require|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScriptInterpreterSource|ServerAdmin|ServerAlias|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetHandler|SetInputFilter|SetOutputFilter|Time(O|o)ut|TraceEnable|UseCanonicalName|Use|ErrorLogFormat|GlobalLog|PHPIniDir|SSLHonorCipherOrder|SSLCompression|SSLUseStapling|SSLStapling\w+|SSLCARevocationCheck|SSLSRPVerifierFile|SSLSessionTickets|RequestReadTimeout|ProxyHTML\w+|MaxRanges)\b captures: 1: keyword.core.apacheconf - match: \b(AcceptMutex|AssignUserID|BS2000Account|ChildPerUserID|CoreDumpDirectory|EnableExceptionHook|Group|Listen|ListenBacklog|LockFile|MaxClients|MaxConnectionsPerChild|MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxRequestWorkers|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MinSpareServers|MinSpareThreads|NumServers|PidFile|ReceiveBufferSize|ScoreBoardFile|SendBufferSize|ServerLimit|StartServers|StartThreads|ThreadLimit|ThreadsPerChild|ThreadStackSize|User|Win32DisableAcceptEx)\b captures: 1: keyword.mpm.apacheconf - match: \b(Allow|Deny|Order)\b captures: 1: keyword.access.apacheconf - match: \b(Action|Script)\b captures: 1: keyword.actions.apacheconf - match: \b(Alias|AliasMatch|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ScriptAlias|ScriptAliasMatch)\b captures: 1: keyword.alias.apacheconf - match: \b(AuthAuthoritative|AuthGroupFile|AuthUserFile|AuthBasicProvider|AuthBasicFake|AuthBasicAuthoritative|AuthBasicUseDigestAlgorithm)\b captures: 1: keyword.auth.apacheconf - match: \b(Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail)\b captures: 1: keyword.auth_anon.apacheconf - match: \b(AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile)\b captures: 1: keyword.auth_dbm.apacheconf - match: \b(AuthDigestAlgorithm|AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize|AuthDigestProvider)\b captures: 1: keyword.auth_digest.apacheconf - match: \b(AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl)\b captures: 1: keyword.auth_ldap.apacheconf - match: \b(AddAlt|AddAltByEncoding|AddAltByType|AddDescription|AddIcon|AddIconByEncoding|AddIconByType|DefaultIcon|HeaderName|IndexIgnore|IndexOptions|IndexOrderDefault|IndexStyleSheet|IndexHeadInsert|ReadmeName)\b captures: 1: keyword.autoindex.apacheconf - match: \b(BalancerMember|BalancerGrowth|BalancerPersist|BalancerInherit)\b captures: 1: keyword.filter.apacheconf - match: \b(CacheDefaultExpire|CacheDisable|CacheEnable|CacheForceCompletion|CacheIgnoreCacheControl|CacheIgnoreHeaders|CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire)\b captures: 1: keyword.cache.apacheconf - match: \b(MetaDir|MetaFiles|MetaSuffix)\b captures: 1: keyword.cern_meta.apacheconf - match: \b(ScriptLog|ScriptLogBuffer|ScriptLogLength)\b captures: 1: keyword.cgi.apacheconf - match: \b(ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock)\b captures: 1: keyword.cgid.apacheconf - match: \b(CharsetDefault|CharsetOptions|CharsetSourceEnc)\b captures: 1: keyword.charset_lite.apacheconf - match: \b(Dav|DavDepthInfinity|DavMinTimeout|DavLockDB)\b captures: 1: keyword.dav.apacheconf - match: \b(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize)\b captures: 1: keyword.deflate.apacheconf - match: \b(DirectoryIndex|DirectorySlash|FallbackResource)\b captures: 1: keyword.dir.apacheconf - match: \b(CacheDirLength|CacheDirLevels|CacheExpiryCheck|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheMaxFileSize|CacheMinFileSize|CacheRoot|CacheSize|CacheTimeMargin)\b captures: 1: keyword.disk_cache.apacheconf - match: \b(DumpIOInput|DumpIOOutput)\b captures: 1: keyword.dumpio.apacheconf - match: \b(PassEnv|SetEnv|UnsetEnv)\b captures: 1: keyword.env.apacheconf - match: \b(ExpiresActive|ExpiresByType|ExpiresDefault)\b captures: 1: keyword.expires.apacheconf - match: \b(ExtFilterDefine|ExtFilterOptions)\b captures: 1: keyword.ext_filter.apacheconf - match: \b(CacheFile|MMapFile)\b captures: 1: keyword.file_cache.apacheconf - match: \b(AddOutputFilterByType|FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace)\b captures: 1: keyword.filter.apacheconf - match: \b(Header|RequestHeader)\b captures: 1: keyword.headers.apacheconf - match: \b(ImapBase|ImapDefault|ImapMenu)\b captures: 1: keyword.imap.apacheconf - match: \b(SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|XBitHack)\b captures: 1: keyword.include.apacheconf - match: \b(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer)\b captures: 1: keyword.isapi.apacheconf - match: \b(LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTrustedCA|LDAPTrustedCAType)\b captures: 1: keyword.ldap.apacheconf - match: \b(BufferedLogs|CookieLog|CustomLog|LogFormat|TransferLog|ForensicLog)\b captures: 1: keyword.log.apacheconf - match: \b(MCacheMaxObjectCount|MCacheMaxObjectSize|MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize)\b captures: 1: keyword.mem_cache.apacheconf - match: \b(AddCharset|AddEncoding|AddHandler|AddInputFilter|AddLanguage|AddOutputFilter|AddType|DefaultLanguage|ModMimeUsePathInfo|MultiviewsMatch|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|TypesConfig)\b captures: 1: keyword.mime.apacheconf - match: \b(ProtocolEcho|Example|AddModuleInfo|MimeMagicFile|CheckSpelling|ExtendedStatus|SuexecUserGroup|UserDir)\b captures: 1: keyword.misc.apacheconf - match: \b(CacheNegotiatedDocs|ForceLanguagePriority|LanguagePriority)\b captures: 1: keyword.negotiation.apacheconf - match: \b(NWSSLTrustedCerts|NWSSLUpgradeable|SecureListen)\b captures: 1: keyword.nw_ssl.apacheconf - match: \b(AllowCONNECT|NoProxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyFtpDirCharset|ProxyIOBufferSize|ProxyMaxForwards|ProxyPass|ProxyPassMatch|ProxyPassReverse|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia)\b captures: 1: keyword.proxy.apacheconf - match: \b(RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule)\b captures: 1: keyword.rewrite.apacheconf - match: \b(BrowserMatch|BrowserMatchNoCase|SetEnvIf|SetEnvIfNoCase)\b captures: 1: keyword.setenvif.apacheconf - match: \b(LoadFile|LoadModule)\b captures: 1: keyword.so.apacheconf - match: \b(SSLCACertificateFile|SSLCACertificatePath|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth|SSLInsecureRenegotiation|SSLOpenSSLConfCmd)\b captures: 1: keyword.ssl.apacheconf - match: \b(Substitute|SubstituteInheritBefore|SubstituteMaxLineLength)\b captures: 1: keyword.substitute.apacheconf - match: \b(CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking)\b captures: 1: keyword.usertrack.apacheconf - match: \b(VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP)\b captures: 1: keyword.vhost_alias.apacheconf - match: \b(php_value|php_flag|php_admin_value|php_admin_flag)\b(\s+(.+?)(\s+(".+?"|.+?))?)?\s captures: 1: keyword.php.apacheconf 3: entity.property.apacheconf 5: string.value.apacheconf - match: '(%\{)((HTTP_USER_AGENT|HTTP_REFERER|HTTP_COOKIE|HTTP_FORWARDED|HTTP_HOST|HTTP_PROXY_CONNECTION|HTTP_ACCEPT|REMOTE_ADDR|REMOTE_HOST|REMOTE_PORT|REMOTE_USER|REMOTE_IDENT|REQUEST_METHOD|SCRIPT_FILENAME|PATH_INFO|QUERY_STRING|AUTH_TYPE|DOCUMENT_ROOT|SERVER_ADMIN|SERVER_NAME|SERVER_ADDR|SERVER_PORT|SERVER_PROTOCOL|SERVER_SOFTWARE|TIME_YEAR|TIME_MON|TIME_DAY|TIME_HOUR|TIME_MIN|TIME_SEC|TIME_WDAY|TIME|API_VERSION|THE_REQUEST|REQUEST_URI|REQUEST_FILENAME|IS_SUBREQ|HTTPS)|(.*?))(\})' captures: 1: punctuation.variable.apacheconf 3: variable.env.apacheconf 4: variable.misc.apacheconf 5: punctuation.variable.apacheconf - match: \b((text|image|application|video|audio)/.+?)\s captures: 1: entity.mime-type.apacheconf - match: \b(?i)(export|from|unset|set|on|off)\b captures: 1: entity.helper.apacheconf - match: \b(\d+)\b captures: 1: constant.numeric.integer.decimal.apacheconf - match: '\s(\[)(.*?)(\])\s' captures: 1: punctuation.definition.flag.apacheconf 2: string.flag.apacheconf 3: punctuation.definition.flag.apacheconf ================================================ FILE: assets/syntaxes/02_Extra/AsciiDoc.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: AsciiDoc (Asciidoctor) file_extensions: - adoc - ad - asciidoc scope: text.asciidoc contexts: main: - include: lists - include: blocks - include: section_titles - include: lines - include: inline - include: characters attribute_entry: - match: |- (?x) ^(:) # opening delimiter (!)? # bang symbol (unset attribute) ([A-Za-z0-9_][A-Za-z0-9_-]*) # attribute name (!)? # bang symbol (unset attribute) (:) # closing delimiter (?:\s+|(?=$)) comment: | An attribute entry. Examples: :my-attribute: value :sectnums!: :!sectnums: captures: 1: punctuation.definition.attributeentry.attrname.begin.asciidoc 2: punctuation.definition.attributeentry.unset.asciidoc 3: support.variable.attribute.asciidoc 4: punctuation.definition.attributeentry.unset.asciidoc 5: punctuation.definition.attributeentry.attrname.end.asciidoc push: - meta_scope: meta.attributeentry.asciidoc - meta_content_scope: meta.attributeentry.value.asciidoc - match: $\n? pop: true - include: characters attribute_list_line: - match: '^(\[)[^\[\]]*(\])\s*$\n?' comment: "Attribute list as paragraph: single brackets. No need for special treatment of escape; follows literal block, section template as being a more general regex." scope: support.variable.attributelist.asciidoc captures: 1: punctuation.definition.attributelistline.begin.asciidoc 2: punctuation.definition.attributelistline.end.asciidoc attribute_reference: - match: "({)([A-Za-z0-9_][A-Za-z0-9_-]*)(})" comment: | Examples: {my-attribute} scope: variable.other captures: 1: constant.character.attributes.reference.begin.asciidoc 2: support.variable.attribute.asciidoc 3: constant.character.attributes.reference.end.asciidoc biblio_anchor: - match: '(?)))\s+(?=\S) comment: | Marker of a callout list item. Examples: <1> a callout <42> another callout scope: markup.list.numbered.callout.asciidoc captures: 1: string.unquoted.list.callout.asciidoc 2: constant.numeric.callout.asciidoc 3: punctuation.definition.calloutlistnumber.begin.asciidoc 4: punctuation.definition.calloutlistnumber.end.asciidoc dlist_item_label: - match: '^\s*(?=.*:{2,4}(?:\s|$))' comment: | Label of a definition (labeled) list item. Examples: Label level 1:: lorem ipsum Label level 2::: dolor sit amet Label level 3:::: consectetur Label level 1:: lorem ipsum Another label :: lorem ipsum Last::label:: dolor sit amet Note: This rule is not strictly correct, because Asciidoctor allows double colon followed by a space inside a label, i.e. it matches the *last* double colon, not the first. I don't know how to do that *effectively. push: - meta_scope: markup.list.labeled.asciidoc - meta_content_scope: meta.list.label.asciidoc - match: '(:{2,4})(?:\s|$\n?)' captures: 1: constant.labeledlist.separator.asciidoc pop: true - include: inline - include: characters emphasis: - match: |- (?x) (\[[^\]]*?\])? # might be preceded by an attributes list (?<=^|\W)(?:])' comment: | List of special characters that may be escaped. Note: I do not really know if this is a good list, adopted wholesale from original bundle. scope: constant.character.escape.asciidoc indexterm_double: - match: '(?) comment: | Callout label Examples: <1> <42> scope: constant.other.callout.asciidoc captures: 1: punctuation.definition.callout.begin.asciidoc 2: punctuation.definition.callout.end.asciidoc inline_comment: - match: '^(//)([^/\n].*|)$\n?' comment: | Inline comment. Examples: // This is just a comment! scope: comment.line.double-slash.asciidoc captures: 1: punctuation.definition.comment.line.asciidoc 2: meta.line.comment.content.asciidoc lines: - include: inline_comment - include: list_continuation - include: inline_break - include: block_page_break - include: block_thematic_break - include: block_title - include: block_id - include: section_template - include: attribute_list_line - include: attribute_entry list_continuation: - match: ^\+\s*$\n? scope: constant.listcontinuation.asciidoc lists: - include: block_admonition_label - include: ulist_item_marker - include: olist_item_marker - include: dlist_item_label - include: colist_item_marker macro: - match: |- (?x) (?: ((?:https?|mailto|ftp|file) # specify separately so we can mark them as links that TextMate opens ?:{1} # inline only \S*) # (others such as image are partial URLs and/or TextMate cannot handle them) | (([a-zA-Z0-9][a-zA-Z0-9_]*) (:{1,2}) (\S*)) ) (?:(\[)([^\]]*)(\])) comment: | Note: There are other macro notations, but I match only those that end in square brackets. scope: meta.macro.asciidoc captures: 1: markup.underline.link.macro.asciidoc 3: keyword.control.name.macro.asciidoc 4: constant.character.separator.macro.asciidoc 5: markup.underline.target.macro.asciidoc 6: constant.character.attributes.macro.begin.asciidoc 7: variable.parameter.attributes.macro.asciidoc 8: constant.character.attributes.macro.end.asciidoc macro_pass: - match: |- (?x) (pass) (:{1,2}) (\S*) (\[)(?=[^\]]*\]) comment: | Passthrough macro Examples: pass:[Lorem ipsum] pass::[Lorem ipsum] captures: 1: keyword.control.name.macro.pass.asciidoc 2: constant.character.separator.macro.asciidoc 3: markup.underline.target.macro.asciidoc 4: constant.character.attributes.macro.begin.asciidoc push: - meta_scope: meta.macro.pass.asciidoc - meta_content_scope: variable.parameter.attributes.macro.pass.asciidoc - match: '\]' captures: 0: constant.character.attributes.macro.end.asciidoc pop: true - include: scope:text.xml mark: - match: |- (?x) (\[[^\]]*?\])? # might start with attribute list (darned well better or why are we here) (?<=^|\W)(? | <\- | => | <= ) scope: constant.character.replacement.asciidoc section_template: - match: |- (?x)^ (\[) # in square brackets (template\s*=\s*)?(")? # might start with template-equals and might have template name in quotes ( sect\d|abstract|preface|colophon|dedication|glossary|bibliography|synopsis|appendix|index # fixed list of known templates ) (".*(\])|(\])) # either close the quote (and perhaps go on) and close the bracket, or close the bracket immediately \s*$\n? comment: fixed list of known template names scope: variable.parameter.sectiontemplate.asciidoc captures: 1: punctuation.definition.sectiontemplate.begin.asciidoc 4: meta.tag.sectiontemplate.asciidoc 6: punctuation.definition.sectiontemplate.end.asciidoc 7: punctuation.definition.sectiontemplate.end.asciidoc section_titles: - include: title_level_5 - include: title_level_4 - include: title_level_3 - include: title_level_2 - include: title_level_1 - include: title_level_0 strong: - match: |- (?x) (\[[^\]]*?\])? # might start with an attributes list (?<=^|\W)(?>)(?!<)' comment: | Internal cross-reference Examples: <> <> scope: meta.xref.asciidoc captures: 1: constant.character.xref.begin.asciidoc 2: markup.underline.term.xref.asciidoc 5: variable.parameter.xref.asciidoc 6: constant.character.xref.end.asciidoc ================================================ FILE: assets/syntaxes/02_Extra/Assembly (ARM).sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: ARM Assembly file_extensions: - s - S scope: source.asm.arm contexts: main: - match: "@.*$" scope: comment.line - match: //.*$ scope: comment.line - match: ;.*$ scope: comment.line - match: ^\s*\#\s*if\s+0\b push: - meta_scope: comment.preprocessor - match: ^\s*\#\s*endif\b pop: true - match: /\* push: - meta_scope: comment.block - match: \*/ pop: true - match: |- (?x) ^\s*\#\s*(define)\s+ # define ((?[a-zA-Z_][a-zA-Z0-9_]*)) # macro name (?: # and optionally: (\() # an open parenthesis ( \s* \g \s* # first argument ((,) \s* \g \s*)* # additional arguments (?:\.\.\.)? # varargs ellipsis? ) (\)) # a close parenthesis )? captures: 1: keyword.control.import.define.c 2: entity.name.function.preprocessor.c 4: punctuation.definition.parameters.c 5: variable.parameter.preprocessor.c 7: punctuation.separator.parameters.c 8: punctuation.definition.parameters.c push: - meta_scope: meta.preprocessor.macro.c - match: (?=(?://|/\*))|$ pop: true - match: (?>\\\s*\n) scope: punctuation.separator.continuation.c - include: $top_level_main - match: ^\s*#\s*(error|warning)\b captures: 1: keyword.control.import.error.c push: - meta_scope: meta.preprocessor.diagnostic.c - match: $ captures: 1: keyword.control.import.error.c pop: true - match: (?>\\\s*\n) scope: punctuation.separator.continuation.c - match: ^\s*#\s*(include|import)\b\s+ captures: 1: keyword.control.import.include.c push: - meta_scope: meta.preprocessor.c.include - match: (?=(?://|/\*))|$ captures: 1: keyword.control.import.include.c pop: true - match: (?>\\\s*\n) scope: punctuation.separator.continuation.c - match: '"' captures: 0: punctuation.definition.string.begin.c push: - meta_scope: string.quoted.double.include.c - match: '"' captures: 0: punctuation.definition.string.end.c pop: true - match: < captures: 0: punctuation.definition.string.begin.c push: - meta_scope: string.quoted.other.lt-gt.include.c - match: ">" captures: 0: punctuation.definition.string.end.c pop: true - match: '((?i)([xw][0-9]|[xw]1[0-9]||[xw]2[0-9]|[wx]30|wzr|xzr|wsp|fpsr|fpcr|[rcp]1[0-5]|[rcp][0-9]|a[1-4]|v[1-8]|sl|sb|fp|ip|sp|lr|(c|s)psr(_c)?|pc|[sd]3[0-1]|[sd][12][0-9]|[sd][0-9]|fpsid|fpscr|fpexc|q3[0-1]|q2[0-9]|q1[0-9]|q[0-9]|APSR_nzcv|sy)!?(?-i))?\b' scope: storage.other.register - match: \.(?i)(globl|global|macro|endm|purgem|if|elseif|else|endif|section|text|arm|align|balign|irp|rept|endr|req|unreq|error|short|func|endfunc|hidden|type|fpu|arch|code|altmacro|object_arch|word|int|string)(?-i)\b scope: keyword.control.directive - match: armv(2a?|3m?|4t?|5t?e?6(j|t2|zk?|-m)?|7v?e?(-(a|r|m))?|8-a(\+crc)?) scope: keyword.control.arch.arm - match: ^\s*#\s*(define|defined|elif|else|if|ifdef|ifndef|line|pragma|undef|endif)\b captures: 1: keyword.control.import.c push: - meta_scope: meta.preprocessor.c - match: (?=(?://|/\*))|$ captures: 1: keyword.control.import.c pop: true - match: (?>\\\s*\n) scope: punctuation.separator.continuation.c - match: |- (?x)\b((?i) ( (bf(c|i)|(u|s)bfx|(u|s)xta?(h|b)?) | (v(add|cvt|sub|mov|trn|cmp|div|qdmulh|mrs|mul|ld1|qadd|qshrun|st[1234]|addw|mull|mlal|rshrn|swp|qmovun)|qmovun)(\.([isup]?8|[isupf]?16|[isuf]?32|[isu]?64))* | (and|m(rs|sr)|eor|sub|rsb|add|adc|sbc|rsc|tst|teq|cmp|cmn|orr|mov|bic|mvn | (neg) | (lsr|lsl|ror|asr) # shift ops either pseudo ops or actual shifts )s? | (mul|mla|mull|smlabb) | (mov(w|t)) | rev(8|16)? | (pld|adr|adrl|vswp) ) (ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b scope: support.function.mnemonic.arithmetic - match: |- (?x)\b((?i)( swi|svc|wfi| dmb | clrex | dsb | isb | v(ldr|str|push|pop) | (push|pop) | (st|ld)( p | r(ex|s?(h|b)|d)? | m( (f|e)(d|a) | (d|i)(b|a) )? ) | b(l|x|lx|lr|r)? | (i|e)?ret| b\.(eq|ne|hs|cs|lo|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|nv)+ | (c|t)?bn?z| )+(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))\b scope: support.function.mnemonic.memory - match: '\b((?i)(def(b|w|s)|equ|(include|get)(\s+([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*?)\.s)?)?(?-i))\b' scope: meta.preprocessor.c.include - match: \b((?i)(align)(?-i))?\b scope: storage.type.c.memaccess - match: \s+\".+\" scope: string - match: \b((?i)nop(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b scope: comment.nop - match: '\s\[' push: - meta_scope: storage.type.c.memaccess - match: '\]' pop: true - match: (?>\\\s*\n) scope: punctuation.separator.continuation.c - include: $top_level_main - match: (\b|\s+)\=\b scope: keyword.control.evaluation - match: '(\b|\s+)(\#)?-?(0x|&)[0-9a-fA-F_]+\b' scope: constant.numeric.hex - match: '(\b|\s+)\#-?[0-9a-zA-Z_]+\b' scope: constant.numeric.literal - match: '(\b|\s+)[0-9]+\b' scope: constant.numeric.dec - match: '\b([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*)\b' scope: meta.function.source.arm.label ================================================ FILE: assets/syntaxes/02_Extra/Assembly (x86_64).sublime-syntax ================================================ %YAML 1.2 --- name: x86_64 Assembly file_extensions: [yasm, nasm, asm, inc, mac] scope: source.asm.x86_64 variables: num_bin: '(?:[01][01_]*)' num_oct: '(?:[0-7][0-7_]*)' num_dec: '(?:[0-9][0-9_]*)' num_hex: '(?:[[:xdigit:]][[:xdigit:]_]*)' num_bin_exp: '(?:p[+-]?{{num_dec}})' num_dec_exp: '(?:e[+-]?{{num_dec}})' identifier_body: '(?:[[:alnum:]_$#@~.?]*)' valid_identifier: '(?:[[:alpha:]_?]{{identifier_body}})' contexts: prototype: - include: comments line-continuation: - match: '(\\)$\n' captures: 1: punctuation.separator.continuation.asm.x86_64 - match: '\\(\s+?)$' captures: 1: invalid.illegal.space-after-continuation.asm.x86_64 line-ending: - match: '$\n' pop: true pop: - match: '(?=.|$)' pop: true pop-if-not-whitespace: - match: '(?=\S)' set: pop main: - include: comments - include: prefixes - include: data-types - include: registers - include: mnemonics - include: strings - include: numbers - include: operators - include: support - include: directives - include: entities - include: structs - include: preprocessor - include: labels numbers: - include: floating-point - include: integers floating-point: # binary - match: '(?i)\b0[by]{{num_bin}}\.(?:{{num_bin}}?{{num_bin_exp}}?\b)?' scope: constant.numeric.binary.floating-point.asm.x86_64 - match: '(?i)\b0[by]{{num_bin}}{{num_bin_exp}}\b' scope: constant.numeric.binary.floating-point.asm.x86_64 # octal - match: '(?i)\b0[oq]{{num_oct}}\.(?:{{num_oct}}?{{num_bin_exp}}?\b)?' scope: constant.numeric.octal.floating-point.asm.x86_64 - match: '(?i)\b0[oq]{{num_oct}}{{num_bin_exp}}\b' scope: constant.numeric.octal.floating-point.asm.x86_64 # decimal - match: '(?i)\b(?:0[dt])?{{num_dec}}\.(?:{{num_dec}}?{{num_dec_exp}}?\b)?' scope: constant.numeric.decimal.floating-point.asm.x86_64 - match: '(?i)\b{{num_dec}}{{num_dec_exp}}\b' scope: constant.numeric.decimal.floating-point.asm.x86_64 #- match: '(?i)\.{{num_dec}}{{num_dec_exp}}?\b' # scope: invalid.illegal.constant.numeric.decimal.floating-point.asm.x86_64 - match: '(?i)\b{{num_dec}}p{{num_dec}}?\b' scope: constant.numeric.decimal.packed-bcd.asm.x86_64 # hex - match: '(?i)\b0[xh]{{num_hex}}\.(?:{{num_hex}}?{{num_bin_exp}}?\b)?' scope: constant.numeric.hex.floating-point.asm.x86_64 - match: '(?i)\b0[xh]{{num_hex}}{{num_bin_exp}}\b' scope: constant.numeric.hex.floating-point.asm.x86_64 - match: '(?i)\$[0-9]\_?{{num_hex}}?\.(?:{{num_hex}}?{{num_bin_exp}}?\b)?' scope: constant.numeric.hex.floating-point.asm.x86_64 - match: '(?i)\$[0-9]\_?{{num_hex}}{{num_bin_exp}}\b' scope: constant.numeric.hex.floating-point.asm.x86_64 integers: - match: '(?i)\b(?:(?:0[by]{{num_bin}})|(?:{{num_bin}}[by]))\b' scope: constant.numeric.binary.asm.x86_64 - match: '(?i)\b(?:(?:0[oq]{{num_oct}})|(?:{{num_oct}}[oq]))\b' scope: constant.numeric.octal.asm.x86_64 - match: '(?i)\b(?:(?:0[dt]{{num_dec}})|(?:{{num_dec}}[dt]?))\b' scope: constant.numeric.decimal.asm.x86_64 - match: '(?i)(?:\$[0-9]\_?{{num_hex}}?)\b' scope: constant.numeric.hex.asm.x86_64 - match: '(?i)\b(?:(?:0[xh]{{num_hex}})|(?:{{num_hex}}[hxHX]))\b' scope: constant.numeric.hex.asm.x86_64 labels: # http://www.nasm.us/doc/nasmdoc3.html#section-3.9 - match: '(\.\.@)({{valid_identifier}})(?:(\:)?|\b)' captures: 1: punctuation.separator.asm.x86_64 storage.modifier.asm.x86_64 2: entity.name.constant.special.asm.x86_64 3: punctuation.separator.asm.x86_64 - match: '(?:(\.)?|\b)({{valid_identifier}})(?:(\:)?|\b)' captures: 1: punctuation.separator.asm.x86_64 storage.modifier.asm.x86_64 2: entity.name.constant.asm.x86_64 3: punctuation.separator.asm.x86_64 - match: '(\.)([0-9]+{{identifier_body}})(?:(\:)?|\b)' captures: 1: punctuation.separator.asm.x86_64 storage.modifier.asm.x86_64 2: entity.name.constant.asm.x86_64 3: punctuation.separator.asm.x86_64 - match: '(?:(\.)?|\b)([0-9$@~]{{identifier_body}})(?:(\:)?|\b)' captures: 1: punctuation.separator.asm.x86_64 storage.modifier.asm.x86_64 2: invalid.illegal.entity.name.constant.asm.x86_64 3: punctuation.separator.asm.x86_64 - match: '((%)(\d+))' captures: 1: invalid.illegal.meta.preprocessor.asm.x86_64 #1: meta.preprocessor.asm.x86_64 2: punctuation.definition.variable.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 3: variable.other.preprocessor.asm.x86_64 - match: '((%%)({{valid_identifier}})(?:(\:)?|\b))' captures: 1: invalid.illegal.meta.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 3: entity.name.constant.special.asm.x86_64 4: punctuation.separator.asm.x86_64 data-types: # Initialized & uninitialized data: http://www.nasm.us/doc/nasmdoc3.html#section-3.2.1 - match: '(?i)\b(?:s?byte|(?:[doqtyz]|dq|s[dq]?)?word|(?:d|res)[bdoqtwyz]|ddq)\b' scope: storage.type.asm.x86_64 - match: '(?i)\b(?:incbin|equ|times)\b' scope: support.function.asm.x86_64 prefixes: - match: '(?i)\b(?:strict|nosplit|near|far|abs|rel)\b' scope: storage.modifier.asm.x86_64 - match: '(?i)\b(?:[ao](?:16|32|64))\b' scope: storage.modifier.prefix.asm.x86_64 - match: '(?i)\b(?:rep(?:n?[ez])?|lock|xacquire|xrelease|(?:no)?bnd)\b' scope: storage.modifier.prefix.asm.x86_64 - match: '{(vex[23]|evex)}' captures: 1: storage.modifier.prefix.vex.asm.x86_64 - match: '{(k[1-7])}' captures: 1: storage.modifier.opmask.asm.x86_64 - match: '{(1to(?:8|16))}' captures: 1: storage.modifier.precision.asm.x86_64 - match: '{(z|(?:r[nudz]-)?sae)}' captures: 1: storage.modifier.rounding.asm.x86_64 support: # http://www.nasm.us/doc/nasmdoc7.html#section-7.4.6 - match: '\.\.(?:start|imagebase|tlvp|got(?:pc(?:rel)?|(?:tp)?off)?|plt|sym|tlsie)\b' scope: support.constant.asm.x86_64 - match: '\b__(?:utf(?:(?:16|32)(?:[lb]e)?)|float(?:8|16|32|64|80[me]|128[lh])|Infinity|[QS]?NaN)__\b' scope: support.function.asm.x86_64 # http://www.nasm.us/doc/nasmdoc4.html#section-4.11 - match: '\b__NASM_(?:MAJOR|(?:SUB)?MINOR|SNAPSHOT|VER(?:SION_ID)?)__\b' scope: support.function.asm.x86_64 - match: '\b___NASM_PATCHLEVEL__\b' scope: support.function.asm.x86_64 - match: '\b__(?:FILE|LINE|BITS|OUTPUT_FORMAT)__\b' scope: support.function.asm.x86_64 - match: '\b__(?:(?:UTC_)?(?:DATE|TIME)(?:_NUM)?|POSIX_TIME)__\b' scope: support.function.asm.x86_64 - match: '\b__USE_(?:ALTREG|SMARTALIGN|FP|IFUNC)__\b' scope: support.function.asm.x86_64 - match: '\b__PASS__\b' scope: invalid.deprecated.support.constant.altreg.asm.x86_64 - match: '(?i)\balignmode\b' scope: support.function.smartalign.asm.x86_64 push: - include: line-continuation - include: line-ending - match: '\b(?:generic|nop|k7|k8|p6)\b' scope: support.constant.smartalign.asm.x86_64 pop: true - match: '\w+' scope: invalid.illegal.constant.smartalign.asm.x86_64 pop: true - match: '\b__ALIGNMODE__\b' scope: support.constant.smartalign.asm.x86_64 - match: '\b(?:Inf|[QS]?NaN)\b' scope: support.constant.fp.asm.x86_64 - match: '\b(?:float(?:8|16|32|64|80[me]|128[lh]))\b' scope: support.function.fp.asm.x86_64 - match: '(?i)\bilog2(?:[ewfc]|[fc]w)?\b' scope: support.function.ifunc.asm.x86_64 directives: - match: '(?i)\b(?:ideal|jumps|p[345]86|end)\b' scope: invalid.deprecated.tasm.asm.x86_64 - match: '(?i)\b(?:bits|use(?:16|32|64)|org|uppercase|safeseh|osabi)\b' scope: support.function.directive.asm.x86_64 - match: '(?i)\b(default)(?:\s+(rel|abs|(?:no)?bnd))?\b' captures: 1: support.function.directive.asm.x86_64 2: support.constant.directive.asm.x86_64 - match: '(?i)\b(?:section|segment)\b' scope: support.function.directive.asm.x86_64 push: [section-parameters, section-name] - match: '(?i)\bgroup\b' scope: support.function.directive.asm.x86_64 push: section-name - match: '\b(?:__SECT__|__NASMDEFSEG|_?_GLOBAL_OFFSET_TABLE_)\b' scope: support.constant.directive.asm.x86_64 - match: '(?i)\b(?:absolute|common)\b' scope: support.function.directive.asm.x86_64 - match: '(?i)\b(?:subsections_via_symbols|no_dead_strip)\b' scope: support.function.directive.macho.asm.x86_64 - match: '(?i)import\b' scope: support.function.directive.asm.x86_64 push: - match: '{{valid_identifier}}' scope: entity.name.function.asm.x86_64 set: - match: '{{valid_identifier}}' scope: meta.path.asm.x86_64 string.unquoted.asm.x86_64 set: - match: '{{valid_identifier}}' scope: variable.function.asm.x86_64 set: - include: comments - match: '{{valid_identifier}}' scope: invalid.illegal.asm.x86_64 - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - match: '(?i)export\b' scope: support.function.directive.asm.x86_64 push: - match: '{{valid_identifier}}' scope: entity.name.constant.asm.x86_64 set: - match: '{{valid_identifier}}' scope: variable.function.asm.x86_64 set: export-parameters - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - match: '(?i)global\b' scope: support.function.directive.asm.x86_64 push: - match: '(?<=\:)(?:function|data|export)\b' scope: storage.type.directive.asm.x86_64 - match: '\b(?:default|internal|hidden|protected|proc|data)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.asm.x86_64 - include: line-continuation - include: line-ending - include: preprocessor-macro-parameter - include: main - match: '(?i)extern\b' scope: support.function.directive.asm.x86_64 push: - match: '(?<=\:)(?:import)\b' scope: storage.type.directive.asm.x86_64 - match: '\b(?:proc|data)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.asm.x86_64 - include: line-continuation - include: line-ending - include: preprocessor-macro-parameter - include: main - match: '(?i)library\b' scope: support.function.directive.asm.x86_64 push: - match: '{{valid_identifier}}' scope: meta.path.asm.x86_64 string.unquoted.asm.x86_64 pop: true - include: line-continuation - include: line-ending - include: pop-if-not-whitespace - match: '(?i)module\b' scope: support.function.directive.asm.x86_64 push: - match: '\$?{{valid_identifier}}' scope: entity.name.namespace.asm.x86_64 pop: true - include: line-continuation - include: line-ending - include: pop-if-not-whitespace - match: '(?i)\bcpu\b' scope: support.function.directive.asm.x86_64 push: - match: '(?i)\b(?:(?:80|[1-6])86|pentium|ppro|p[234]|katmai|willamette|prescott|(?:x|ia)64)\b' scope: support.constant.directive.asm.x86_64 pop: true - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: main - match: '(?i)\bfloat\b' scope: support.function.directive.asm.x86_64 push: - match: '(?i)\b(?:(?:no)?daz|near|up|down|zero|default)\b' scope: support.constant.directive.asm.x86_64 pop: true - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: main - match: '(?i)(\[)\s*(warning)\b' captures: 2: support.function.directive.asm.x86_64 push: - match: '(?i)([+\-*])|(error)\s*(=)\s*' captures: 1: keyword.control.warning.asm.x86_64 2: support.constant.directive.warning.asm.x86_64 3: keyword.operator.assignment.asm.x86_64 push: - match: '(?i)\b(other|macro-(?:params|selfref|defaults)|orphan-labels|number-overflow|gnu-elf-extensions|float-(?:overflow|denorm|underflow|toolong)|user|lock|hle|bnd|zext-reloc|ptr|(?:bad|unknown|not-my)-pragma|unknown-warning|all)(?=\]|\s)' scope: support.constant.directive.warning.asm.x86_64 pop: true - match: '\S+(?=\])' scope: invalid.illegal.support.constant.directive.warning.asm.x86_64 pop: true - match: '\S+' scope: invalid.illegal.support.constant.directive.warning.asm.x86_64 pop: true - match: '(?i)\b(?:all|error)\b' scope: support.constant.directive.warning.asm.x86_64 - match: ']' pop: true - include: line-continuation - include: line-ending - match: '(?i)(\[)\s*(map)\b' captures: 2: support.function.directive.asm.x86_64 push: - match: '(?i)\b(?:all|brief|sections|segments|symbols)\b' scope: support.constant.directive.map.asm.x86_64 - match: '(?i)\b(?:std(?:out|err))\b' scope: meta.path.asm.x86_64 support.constant.directive.map.asm.x86_64 - match: '{{valid_identifier}}' scope: meta.path.asm.x86_64 string.unquoted.asm.x86_64 - match: ']' pop: true - include: line-continuation - include: line-ending section-parameters: - match: '=' scope: keyword.operator.assignment.asm.x86_64 - match: '(?i)\b(?:(?:v)?start|align|absolute)\b' scope: variable.parameter.directive.asm.x86_64 - match: '(?i)\b(?:(?:prog|no)bits|private|public|common|stack|code|text|data|bss|rdata|info)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.asm.x86_64 - match: '(?i)\b(?:mixed|zerofill|no_dead_strip|live_support|strip_static_syms)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.macho.asm.x86_64 - match: '(?i)\b(?:(?:no)?(?:alloc|exec|write)|tls)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.elf.asm.x86_64 - match: '(?i)\b(?:(?:v)?follows)\b' scope: variable.parameter.directive.asm.x86_64 push: - match: '=' scope: keyword.operator.assignment.asm.x86_64 set: [pop, section-name] - include: line-continuation - include: line-ending - match: '(?i)\b(?:class|overlay)\b' scope: variable.parameter.directive.asm.x86_64 push: - match: '=' scope: keyword.operator.assignment.asm.x86_64 - match: '{{valid_identifier}}' scope: entity.name.class.asm.x86_64 string.unquoted.asm.x86_64 pop: true - include: line-continuation - include: line-ending - include: line-continuation - include: line-ending - include: main section-name: - match: '(?:\.|\b)(?:text|bss|(?:[rpx]|ro)?data|code)\b' scope: entity.name.section.asm.x86_64 string.unquoted.asm.x86_64 support.constant.section.asm.x86_64 pop: true - match: '\b__(?:text|const|data|bss|TEXT|CONST|DATA|BSS)\b' scope: entity.name.section.asm.x86_64 string.unquoted.asm.x86_64 support.constant.section.macho.asm.x86_64 pop: true - match: '(?:\.)(?:[lt](?:data|bss)|lrodata|comment)\b' scope: entity.name.section.asm.x86_64 string.unquoted.asm.x86_64 support.constant.section.elf.asm.x86_64 pop: true - match: '(?:\.|\b){{valid_identifier}}\b' scope: entity.name.section.asm.x86_64 string.unquoted.asm.x86_64 pop: true - match: '(?=`|''|")' set: - meta_scope: entity.name.section.asm.x86_64 - include: strings - include: pop - include: line-continuation - include: pop-if-not-whitespace - include: line-ending export-parameters: - match: '=' scope: keyword.operator.assignment.asm.x86_64 - match: '(?i)\b(?:resident|nodata)\b' scope: storage.modifier.directive.asm.x86_64 variable.parameter.directive.asm.x86_64 - match: '(?i)\b(?:parm)\b' scope: variable.parameter.directive.asm.x86_64 - include: primitive-directive-end - include: line-continuation - include: line-ending - include: main operators: - match: '[+\-*/]' scope: keyword.operator.arithmetic.asm.x86_64 - match: '(%%|%)[[:space:]]' captures: 1: keyword.operator.arithmetic.asm.x86_64 - match: '[|&^~!]|<<|>>' scope: keyword.operator.bitwise.asm.x86_64 - match: '(?i)\b(seg|wrt)\b' scope: keyword.operator.word.asm.x86_64 - match: ',' scope: operator.separator.asm.x86_64 structs: - match: '(?i)\bstruc\b' scope: support.function.asm.x86_64 meta.struct.asm.x86_64 push: - meta_content_scope: meta.struct.asm.x86_64.1 - match: '{{valid_identifier}}' scope: entity.name.struct.asm.x86_64 set: - meta_scope: meta.struct.asm.x86_64 - match: '(?i)\bendstruc\b' scope: support.function.asm.x86_64 meta.struct.asm.x86_64 pop: true - include: main - match: '\w' scope: invalid.illegal.entity.name.struct.asm.x86_64 - match: '(?i)\bendstruc\b' scope: invalid.illegal.support.function.asm.x86_64 meta.struct.asm.x86_64 - match: '(?i)\bistruc\b' scope: support.function.asm.x86_64 meta.struct.asm.x86_64 push: - meta_content_scope: meta.struct.asm.x86_64.1 - match: '{{valid_identifier}}' scope: variable.other.asm.x86_64 set: - meta_scope: meta.struct.asm.x86_64 - match: '(?i)\bat\b' scope: support.function.asm.x86_64 meta.struct.asm.x86_64 - match: '(?i)\biend\b' scope: support.function.asm.x86_64 meta.struct.asm.x86_64 pop: true - include: main - match: '\w' scope: invalid.illegal.variable.struct.asm.x86_64 - match: '(?i)\biend\b' scope: invalid.illegal.support.function.asm.x86_64 meta.struct.asm.x86_64 - match: '(?i)\balignb?\b' scope: support.function.asm.x86_64 - match: '(?i)\b(sectalign)\s+(on|off)?' captures: 1: support.function.asm.x86_64 2: support.constant.asm.x86_64 entities: - match: '\$@feat\.00\b' scope: variable.language.sseh.asm.x86_64 - match: '(\$)(?:\w+)\b' scope: variable.other.asm.x86_64 captures: 1: punctuation.definition.variable.asm.x86_64 - match: '\${3,}' scope: invalid.illegal.variable.language.asm.x86_64 - match: '\$' scope: variable.language.asm.x86_64 comments: - match: (?:(;)|(?:^|\s)(#)\s).*$ scope: comment.line.asm.x86_64 captures: 1: punctuation.definition.comment.asm.x86_64 2: punctuation.definition.comment.asm.x86_64 - match: /\* scope: punctuation.definition.comment.asm.x86_64 push: - meta_scope: comment.block.asm.x86_64 - match: \*/ scope: punctuation.definition.comment.asm.x86_64 pop: true preprocessor: # http://www.nasm.us/doc/nasmdoc4.html - include: preprocessor-macro-multiline - include: preprocessor-macro-define - include: preprocessor-macro-indirection - include: preprocessor-conditions - include: preprocessor-other # single-line macro preprocessor-macro-define: - match: '^\s*((%)x?i?define)\b' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.import.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - match: '(?:{{valid_identifier}})(?=\()' scope: entity.name.function.preprocessor.asm.x86_64 set: - match: '\(' scope: punctuation.section.group.begin.asm.x86_64 set: preprocessor-macro-params - match: '{{valid_identifier}}' scope: entity.name.constant.preprocessor.asm.x86_64 set: preprocessor-macro-definition - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - match: '^\s*((%)(?:include|depend))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.import.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-macro-definition - match: '^\s*((%)use)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.import.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 string.unquoted.asm.x86_64 - include: strings - include: line-ending - include: preprocessor-macro-indirection - match: '^\s*((%)(?:assign|i?deftok|strcat|strlen|substr|pathsearch|push|pop|repl|line|clear))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-macro-indirection - include: preprocessor-conditions-constant - match: '^\s*((%)(?:arg|local))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - match: '({{valid_identifier}})(\:)(?=\w+)' captures: 1: meta.preprocessor.asm.x86_64 variable.parameter.macro.asm.x86_64 2: punctuation.separator.asm.x86_64 - match: '\,' scope: punctuation.separator.asm.x86_64 - include: data-types - match: '\w+\b' scope: invalid.illegal.storage.type.asm.x86_64 - include: line-continuation - include: line-ending - match: '^\s*((%)stacksize)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - match: '\b(flat(?:64)?|large|small)\b' scope: support.constant.macro.asm.x86_64 - match: '\w+\b' scope: invalid.illegal.storage.type.asm.x86_64 - include: line-continuation - include: line-ending - match: '^\s*((%)i?defstr)\s+(?:({{valid_identifier}})|(%%)({{valid_identifier}}))\b' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.import.preprocessor.assign.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: entity.name.constant.preprocessor.asm.x86_64 4: punctuation.definition.keyword.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 5: entity.name.constant.special.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 string.unquoted.asm.x86_64 - include: preprocessor-macro-indirection - include: line-ending - match: '^\s*((%)(?:warning|error|fatal|pragma))(?=\s|$)' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.preprocessor.assign.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: entity.name.constant.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 string.unquoted.asm.x86_64 - include: strings - include: preprocessor-macro-indirection - include: line-ending preprocessor-macro-params-illegal: - meta_scope: invalid.illegal.asm.x86_64 - include: preprocessor-macro-params preprocessor-macro-params: - meta_scope: meta.preprocessor.macro.parameters.asm.x86_64 meta.group.asm.x86_64 - match: '{{valid_identifier}}' scope: variable.parameter.asm.x86_64 - match: '\)' scope: punctuation.section.group.end.asm.x86_64 set: preprocessor-macro-definition - match: ',' scope: punctuation.separator.asm.x86_64 push: - match: '{{valid_identifier}}' scope: variable.parameter.asm.x86_64 pop: true - include: line-continuation - include: preprocessor-comments - match: '\.\.\.' scope: keyword.operator.variadic.asm.x86_64 - match: '(?=\))' pop: true - match: '(/\*).*(\*/)' scope: comment.block.asm.x86_64 captures: 1: punctuation.definition.comment.asm.x86_64 2: punctuation.definition.comment.asm.x86_64 - match: '\S+' scope: invalid.illegal.unexpected-character.asm.x86_64 - include: line-continuation - include: preprocessor-comments - match: '\.\.\.' scope: keyword.operator.variadic.asm.x86_64 - match: '(/\*).*(\*/)' scope: comment.block.asm.x86_64 captures: 1: punctuation.definition.comment.asm.x86_64 2: punctuation.definition.comment.asm.x86_64 - match: '$\n' scope: invalid.illegal.unexpected-end-of-line.asm.x86_64 preprocessor-macro-definition: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - include: line-continuation - include: line-ending - include: main preprocessor-macro-indirection: - match: '((%)(\[))' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: meta.brackets.asm.x86_64 punctuation.section.brackets.begin.asm.x86_64 push: - meta_scope: meta.brackets.asm.x86_64 meta.preprocessor.macro.asm.x86_64 - include: line-continuation - include: line-ending - include: main - match: '\]' scope: punctuation.section.brackets.end.asm.x86_64 keyword.control.preprocessor.asm.x86_64 pop: true - match: '((%)\+)\s+' captures: 1: meta.preprocessor.asm.x86_64 keyword.operator.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 - match: '((%)(\?\??))' captures: 1: meta.preprocessor.asm.x86_64 keyword.operator.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: variable.language.preprocessor.asm.x86_64 - match: '((%\$+)({{valid_identifier}})(?:(\:)?|\b))' captures: 1: meta.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 3: entity.name.constant.special.asm.x86_64 4: punctuation.separator.asm.x86_64 - match: '((%)(\!))' captures: 1: meta.preprocessor.asm.x86_64 keyword.operator.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: punctuation.definition.variable.asm.x86_64 push: - meta_content_scope: meta.preprocessor.asm.x86_64 keyword.operator.preprocessor.asm.x86_64 variable.parameter.preprocessor.environment.asm.x86_64 - match: '{{valid_identifier}}' scope: variable.parameter.preprocessor.environment.unquoted.asm.x86_64 pop: true - match: '(?=`|''|")' set: - meta_scope: variable.parameter.preprocessor.environment.quoted.asm.x86_64 - include: strings - include: pop - include: pop preprocessor-conditions: # also see preprocessor-macro-conditions-multiline - match: '^\s*((%)ifn?(?:idni?|id|num|str|token|empty|env)?)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-conditions-content-block - match: '^\s*((%)ifn?(?:def|ctx))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: [preprocessor-conditions-content-block, preprocessor-conditions-constant] - match: '^\s*((%)rep)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-conditions-content-block - match: '^\s*((%)ifn?macro)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: [preprocessor-conditions-content-block, preprocessor-macro-arguments-signature] - include: preprocessor-conditions-parity preprocessor-conditions-constant: - meta_content_scope: meta.preprocessor.asm.x86_64 - match: '(?:{{valid_identifier}})(?=\()' scope: entity.name.constant.preprocessor.asm.x86_64 set: - match: '\(' scope: punctuation.section.group.begin.asm.x86_64 set: preprocessor-macro-params-illegal - match: '{{valid_identifier}}\b' scope: meta.preprocessor.asm.x86_64 entity.name.constant.preprocessor.asm.x86_64 pop: true - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: main preprocessor-conditions-content-block: - meta_content_scope: meta.block.preprocessor.asm.x86_64 - include: preprocessor-conditions-content-block-common - include: main preprocessor-conditions-content-block-common: - match: '^\s*((%)(?:elifn?(?:idni?|id|num|str|token|empty|env)?|else|exitrep))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 - match: '^\s*((%)(?:elifn?(?:def|ctx)))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-conditions-constant - match: '^\s*((%)elifn?macro)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-macro-arguments-signature - match: '^\s*((%)(?:end(?:if|rep)))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 pop: true preprocessor-conditions-parity: - match: '^\s*((%)(?:elifn?(?:macro|def|ctx|idni?|id|num|str|token|empty|env)?|else|(?:end(?:if|rep))|exitrep))\b' captures: 1: invalid.illegal.meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 preprocessor-other: - include: preprocessor-macro-indirection - match: '^\s*((%)undef)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_scope: meta.preprocessor.asm.x86_64 - include: line-continuation - include: line-ending - include: preprocessor-comments - match: '{{valid_identifier}}' scope: entity.name.constant.preprocessor.asm.x86_64 pop: true - match: '^\s*((%)unmacro)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.import.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-macro-arguments-signature preprocessor-macro-arguments-signature: - meta_scope: meta.preprocessor.asm.x86_64 - include: preprocessor-comments - match: '({{valid_identifier}})(?:\s+(?:(\d+(?:(-)(?:\d+|\*))?)(\+)?(\.nolist\b)?))' captures: 1: entity.name.function.preprocessor.asm.x86_64 2: variable.parameter.preprocessor.asm.x86_64 3: keyword.operator.preprocessor.range.asm.x86_64 4: storage.modifier.preprocessor.greedy.asm.x86_64 5: storage.modifier.preprocessor.listing.asm.x86_64 pop: true - include: line-continuation - include: pop-if-not-whitespace - include: line-ending # multi-line macro preprocessor-macro-multiline: - match: '^\s*((%)i?macro)\b' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.import.define.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - match: '(?:{{valid_identifier}})(?=\()' scope: entity.name.constant.preprocessor.asm.x86_64 set: - meta_content_scope: invalid.illegal.asm.x86_64 - match: '\(' scope: punctuation.section.group.begin.asm.x86_64 set: preprocessor-macro-params-illegal - match: '({{valid_identifier}})(?:\s+(?:(\d+(?:(-)(?:\d+|\*))?)(\+)?(\.nolist\b)?))' captures: 1: entity.name.function.preprocessor.asm.x86_64 2: variable.parameter.preprocessor.asm.x86_64 3: keyword.operator.preprocessor.range.asm.x86_64 4: storage.modifier.preprocessor.greedy.asm.x86_64 5: storage.modifier.preprocessor.listing.asm.x86_64 set: preprocessor-macro-definition-multiline-with-parameters - match: '^\s*((%)endmacro)\b' captures: 1: invalid.illegal.meta.preprocessor.asm.x86_64 keyword.control.import.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 preprocessor-macro-parameter: - match: '((%)(\-?\d+))' captures: 1: meta.preprocessor.asm.x86_64 2: punctuation.definition.variable.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 3: variable.other.preprocessor.asm.x86_64 preprocessor-macro-definition-multiline-with-parameters: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - include: preprocessor-macro-parameter - include: preprocessor-macro-indirection - include: preprocessor-macro-conditions-multiline - include: preprocessor-macro-definition-multiline preprocessor-macro-definition-multiline: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - match: '^\s*((%)endmacro)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.import.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 pop: true - match: '((%%)({{valid_identifier}})(?:(\:)?|\b))' captures: 1: meta.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 3: entity.name.constant.special.asm.x86_64 4: punctuation.separator.asm.x86_64 - match: '((%)({))' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 3: meta.braces.asm.x86_64 punctuation.section.braces.begin.asm.x86_64 push: - meta_scope: meta.braces.asm.x86_64 meta.preprocessor.macro.asm.x86_64 - include: preprocessor-macro-indirection - match: ':' scope: punctuation.separator.asm.x86_64 - match: '}' scope: punctuation.section.braces.end.asm.x86_64 keyword.control.preprocessor.asm.x86_64 pop: true - match: '^\s*((%)(?:rotate))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.operator.word.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 - match: '^\s*((%)(?:include|depend))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.import.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 set: preprocessor-macro-definition-multiline-with-parameters - match: '^\s*((%)(?:pathsearch))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 set: [preprocessor-macro-definition-multiline-with-parameters, preprocessor-conditions-constant] - match: '^\s*((%)x?i?define)\b' captures: 1: meta.preprocessor.macro.asm.x86_64 keyword.control.import.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-comments - match: '(?:{{valid_identifier}})(?=\()' scope: entity.name.function.preprocessor.asm.x86_64 set: - match: '\(' scope: punctuation.section.group.begin.asm.x86_64 set: preprocessor-macro-params - match: '{{valid_identifier}}' scope: entity.name.constant.preprocessor.asm.x86_64 set: preprocessor-macro-definition-inside-multiline - include: line-continuation - include: pop-if-not-whitespace - include: line-ending - include: preprocessor-macro-indirection - include: preprocessor-conditions - include: main preprocessor-macro-conditions-multiline: # also see preprocessor-conditions - match: '^\s*((%)ifn?(?:idni?|id|num|str|token|empty|env)?)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-conditions-content-block-multiline - match: '^\s*((%)ifn?(?:def|ctx))\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: [preprocessor-conditions-content-block-multiline, preprocessor-conditions-constant] - match: '^\s*((%)rep)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: preprocessor-conditions-content-block-multiline - match: '^\s*((%)ifn?macro)\b' captures: 1: meta.preprocessor.asm.x86_64 keyword.control.preprocessor.asm.x86_64 2: punctuation.definition.keyword.preprocessor.asm.x86_64 push: [preprocessor-macro-arguments-signature, preprocessor-conditions-content-block-multiline] - include: preprocessor-conditions-parity preprocessor-conditions-content-block-multiline: - meta_content_scope: meta.block.preprocessor.asm.x86_64 - include: preprocessor-conditions-content-block-common - include: preprocessor-macro-definition-multiline-with-parameters preprocessor-macro-definition-inside-multiline: - meta_content_scope: meta.preprocessor.macro.asm.x86_64 - include: preprocessor-macro-parameter - include: preprocessor-macro-definition strings: # Character strings: http://www.nasm.us/doc/nasmdoc3.html#section-3.4.2 - match: '`' scope: punctuation.definition.string.begin.asm.x86_64 push: string-backquote - match: '''' scope: punctuation.definition.string.begin.asm.x86_64 push: string-single - match: '"' scope: punctuation.definition.string.begin.asm.x86_64 push: string-double string-content: - match: '\\u[[:xdigit:]]{4}' scope: constant.character.escape.asm.x86_64 - match: '\\U[[:xdigit:]]{8}' scope: constant.character.escape.asm.x86_64 - match: '\\x[[:xdigit:]]{1,2}' scope: constant.character.escape.asm.x86_64 - match: '\\[0-7]{1,3}' scope: constant.character.escape.asm.x86_64 - match: '\\[''"`\\?abtnvfre]' scope: constant.character.escape.asm.x86_64 - match: '\\.' scope: invalid.illegal.constant.character.escape.asm.x86_64 string-backquote: - meta_scope: string.quoted.other.asm.x86_64 - meta_include_prototype: false - include: string-content - match: '`' scope: punctuation.definition.string.end pop: true string-single: - meta_scope: string.quoted.single.asm.x86_64 - meta_include_prototype: false - match: '''' scope: punctuation.definition.string.end pop: true string-double: - meta_scope: string.quoted.double.asm.x86_64 - meta_include_prototype: false - match: '"' scope: punctuation.definition.string.end pop: true registers: - match: '(?i)\b(?:[abcd][hl]|[er]?[abcd]x|[er]?(?:di|si|bp|sp)|dil|sil|bpl|spl|r(?:8|9|1[0-5])[bdlw]?)\b' scope: constant.language.register.general-purpose.asm.x86_64 - match: '(?i)\b(?:[cdefgs]s)\b' scope: constant.language.register.segment.asm.x86_64 - match: '(?i)\b(?:[er]?flags)\b' scope: constant.language.register.flags.asm.x86_64 - match: '(?i)\b(?:[er]?ip)\b' scope: constant.language.register.instruction-pointer.asm.x86_64 - match: '(?i)\b(?:cr[02-4])\b' scope: constant.language.register.control.asm.x86_64 - match: '(?i)\b(?:(?:mm|st|fpr)[0-7])\b' scope: constant.language.register.mmx.asm.x86_64 - match: '(?i)\b(?:[xy]mm(?:[0-9]|1[0-5])|mxcsr)\b' scope: constant.language.register.sse_avx.asm.x86_64 - match: '(?i)\b(?:zmm(?:[12]?[0-9]|30|31))\b' scope: constant.language.register.avx512.asm.x86_64 - match: '(?i)\b(?:bnd(?:[0-3]|cfg[su]|status))\b' scope: constant.language.register.memory-protection.asm.x86_64 - match: '(?i)\b(?:(?:[gil]dt)r?|tr)\b' scope: constant.language.register.system-table-pointer.asm.x86_64 - match: '(?i)\b(?:dr[0-367])\b' scope: constant.language.register.debug.asm.x86_64 - match: '(?i)\b(?:cr8|dr(?:[89]|1[0-5])|efer|tpr|syscfg)\b' scope: constant.language.register.amd.asm.x86_64 - match: '(?i)\b(?:db[0-367]|t[67]|tr[3-7]|st)\b' scope: invalid.deprecated.constant.language.register.asm.x86_64 - match: '(?i)\b[xy]mm(?:1[6-9]|2[0-9]|3[01])\b' scope: invalid.deprecated.constant.language.register.asm.x86_64 mnemonics: # see valid.asm for references - include: mnemonics-general-purpose - include: mnemonics-fpu - include: mnemonics-mmx - include: mnemonics-sse - include: mnemonics-sse2 - include: mnemonics-sse3 - include: mnemonics-sse4 - include: mnemonics-aesni - include: mnemonics-avx - include: mnemonics-avx2 - include: mnemonics-tsx - include: mnemonics-system - include: mnemonics-64bit - include: mnemonics-vmx - include: mnemonics-smx - include: mnemonics-intel-isa-sgx - include: mnemonics-intel-isa-mpx - include: mnemonics-intel-isa-sha - include: mnemonics-supplemental-amd - include: mnemonics-supplemental-cyrix - include: mnemonics-supplemental-via - include: mnemonics-undocumented - include: mnemonics-future-intel - include: mnemonics-pseudo-ops #- include: mnemonics-invalid mnemonics-general-purpose: - match: '(?i)\b(?:mov(?:[sz]x)?|cmov(?:n?[abceglopsz]|n?[abgl]e|p[eo]))\b' scope: keyword.operator.word.mnemonic.general-purpose.data-transfer.mov - match: '(?i)\b(xchg|bswap|xadd|cmpxchg(8b)?)\b' scope: keyword.operator.word.mnemonic.general-purpose.data-transfer.xchg - match: '(?i)\b((push|pop)(ad?)?|cwde?|cdq|cbw)\b' scope: keyword.operator.word.mnemonic.general-purpose.data-transfer.other - match: '(?i)\b(adcx?|adox|add|sub|sbb|i?mul|i?div|inc|dec|neg|cmp)\b' scope: keyword.operator.word.mnemonic.general-purpose.binary-arithmetic - match: '(?i)\b(daa|das|aaa|aas|aam|aad)\b' scope: keyword.operator.word.mnemonic.general-purpose.decimal-arithmetic - match: '(?i)\b(and|x?or|not)\b' scope: keyword.operator.word.mnemonic.general-purpose.logical - match: '(?i)\b(s[ah][rl]|sh[rl]d|r[co][rl])\b' scope: keyword.operator.word.mnemonic.general-purpose.rotate - match: '(?i)\b(set(n?[abceglopsz]|n?[abgl]e|p[eo]))\b' scope: keyword.operator.word.mnemonic.general-purpose.bit-and-byte.set - match: '(?i)\b(bt[crs]?|bs[fr]|test|crc32|popcnt)\b' scope: keyword.operator.word.mnemonic.general-purpose.bit-and-byte.other - match: '(?i)\b(jmp|jn?[abceglopsz]|jn?[abgl]e|jp[eo]|j[er]?cxz)\b' scope: keyword.operator.word.mnemonic.general-purpose.control-transfer.jmp - match: '(?i)\b(loop(n?[ez])?|call|ret|iret[dq]?|into?|bound|enter|leave)\b' scope: keyword.operator.word.mnemonic.general-purpose.control-transfer.other - match: '(?i)\b((mov|cmp|sca|lod|sto)(s[bdw]?)|rep(n?[ez])?)\b' scope: keyword.operator.word.mnemonic.general-purpose.strings - match: '(?i)\b((in|out)(s[bdw]?)?)\b' scope: keyword.operator.word.mnemonic.general-purpose.io - match: '(?i)\b((st|cl)[cdi]|cmc|[ls]ahf|(push|pop)f[dq]?)\b' scope: keyword.operator.word.mnemonic.general-purpose.flag-control - match: '(?i)\b(l[defgs]s)\b' scope: keyword.operator.word.mnemonic.general-purpose.segment-registers - match: '(?i)\b(lea|nop|ud2|xlatb?|cpuid|movbe)\b' scope: keyword.operator.word.mnemonic.general-purpose.misc - match: '(?i)\b(rdrand|rdseed)\b' scope: keyword.operator.word.mnemonic.general-purpose.rng - match: '(?i)\b(andn|bextr|bls(i|r|msk)|bzhi|pdep|pext|[lt]zcnt|(mul|ror|sar|shl|shr)x)\b' scope: keyword.operator.word.mnemonic.general-purpose.bmi mnemonics-fpu: - match: '(?i)\b(fcmov(n?([beu]|be)))\b' scope: keyword.operator.word.mnemonic.fpu.data-transfer.mov - match: '(?i)\b(f(i?(ld|stp?)|b(ld|stp)|xch))\b' scope: keyword.operator.word.mnemonic.fpu.data-transfer.other - match: '(?i)\b(f((add|div|mul|sub)p?|i(add|div|mul|sub)|(div|sub)rp?|i(div|sub)r))\b' scope: keyword.operator.word.mnemonic.fpu.basic-arithmetic.basic - match: '(?i)\b(f(prem1?|abs|chs|rndint|scale|sqrt|xtract))\b' scope: keyword.operator.word.mnemonic.fpu.basic-arithmetic.other - match: '(?i)\b(f(u?com[ip]?p?|icomp?|tst|xam))\b' scope: keyword.operator.word.mnemonic.fpu.comparison - match: '(?i)\b(f(sin|cos|sincos|pa?tan|2xm1|yl2x(p1)?))\b' scope: keyword.operator.word.mnemonic.fpu.transcendental - match: '(?i)\b(fld(1|z|pi|l2[et]|l[ng]2))\b' scope: keyword.operator.word.mnemonic.fpu.load-constants - match: '(?i)\b(f((inc|dec)stp|free|n?(init|clex|st[cs]w|stenv|save)|ld(cw|env)|rstor|nop)|f?wait)\b' scope: keyword.operator.word.mnemonic.fpu.control-management - match: '(?i)\b(fx(save|rstor)(64)?)\b' scope: keyword.operator.word.mnemonic.fpu.state-management mnemonics-mmx: - match: '(?i)\b(mov[dq])\b' scope: keyword.operator.word.mnemonic.mmx.data-transfer - match: '(?i)\b(pack(ssdw|[su]swb)|punpck[hl](bw|dq|wd))\b' scope: keyword.operator.word.mnemonic.mmx.conversion - match: '(?i)\b(p(((add|sub)(d|(u?s)?[bw]))|maddwd|mul[lh]w))\b' scope: keyword.operator.word.mnemonic.mmx.packed-arithmetic - match: '(?i)\b(pcmp((eq|gt)[bdw]))\b' scope: keyword.operator.word.mnemonic.mmx.comparison - match: '(?i)\b(pandn?|px?or)\b' scope: keyword.operator.word.mnemonic.mmx.logical - match: '(?i)\b(ps([rl]l[dwq]|raw|rad))\b' scope: keyword.operator.word.mnemonic.mmx.shift-and-rotate - match: '(?i)\b(emms)\b' scope: keyword.operator.word.mnemonic.mmx.state-management mnemonics-sse: - match: '(?i)\b(mov(([ahlu]|hl|lh|msk)ps|ss))\b' scope: keyword.operator.word.mnemonic.sse.data-transfer - match: '(?i)\b((add|div|max|min|mul|rcp|r?sqrt|sub)[ps]s)\b' scope: keyword.operator.word.mnemonic.sse.packed-arithmetic - match: '(?i)\b(cmp[ps]s|u?comiss)\b' scope: keyword.operator.word.mnemonic.sse.comparison - match: '(?i)\b((andn?|x?or)ps)\b' scope: keyword.operator.word.mnemonic.sse.logical - match: '(?i)\b((shuf|unpck[hl])ps)\b' scope: keyword.operator.word.mnemonic.sse.shuffle-and-unpack - match: '(?i)\b(cvt(pi2ps|si2ss|ps2pi|tps2pi|ss2si|tss2si))\b' scope: keyword.operator.word.mnemonic.sse.conversion - match: '(?i)\b((ld|st)mxcsr)\b' scope: keyword.operator.word.mnemonic.sse.state-management - match: '(?i)\b(p(avg[bw]|extrw|insrw|(max|min)(sw|ub)|sadbw|shufw|mulhuw|movmskb))\b' scope: keyword.operator.word.mnemonic.sse.simd-integer - match: '(?i)\b(maskmovq|movntps|sfence)\b' scope: keyword.operator.word.mnemonic.sse.cacheability-control - match: '(?i)\b(prefetch(nta|t[0-2]|w(t1)?))\b' scope: keyword.operator.word.mnemonic.sse.prefetch mnemonics-sse2: - match: '(?i)\b(mov([auhl]|msk)pd)\b' scope: keyword.operator.word.mnemonic.sse2.data-transfer - match: '(?i)\b((add|div|max|min|mul|sub|sqrt)[ps]d)\b' scope: keyword.operator.word.mnemonic.sse2.packed-arithmetic - match: '(?i)\b((andn?|x?or)pd)\b' scope: keyword.operator.word.mnemonic.sse2.logical - match: '(?i)\b((cmpp|u?comis)d)\b' scope: keyword.operator.word.mnemonic.sse2.compare - match: '(?i)\b((shuf|unpck[hl])pd)\b' scope: keyword.operator.word.mnemonic.sse2.shuffle-and-unpack - match: '(?i)\b(cvt(dq2pd|pi2pd|ps2pd|pd2ps|si2sd|sd2ss|ss2sd|t?(pd2dq|pd2pi|sd2si)))\b' scope: keyword.operator.word.mnemonic.sse2.conversion - match: '(?i)\b(cvt(dq2ps|ps2dq|tps2dq))\b' scope: keyword.operator.word.mnemonic.sse2.packed-floating-point - match: '(?i)\b(mov(dq[au]|q2dq|dq2q))\b' scope: keyword.operator.word.mnemonic.sse2.simd-integer.mov - match: '(?i)\b(p((add|sub|(s[lr]l|mulu|unpck[hl]q)d)q|shuf(d|[hl]w)))\b' scope: keyword.operator.word.mnemonic.sse2.simd-integer.other - match: '(?i)\b(clflush|[lm]fence|pause|maskmovdqu|movnt(dq|i|pd))\b' scope: keyword.operator.word.mnemonic.sse2.cacheability-control mnemonics-sse3: - match: '(?i)\b(fisttp|lddqu|(addsub|h(add|sub))p[sd]|mov(sh|sl|d)dup|monitor|mwait)\b' scope: keyword.operator.word.mnemonic.sse3 - match: '(?i)\b(ph(add|sub)(s?w|d))\b' scope: keyword.operator.word.mnemonic.sse3.supplimental.horizontal-packed-arithmetic - match: '(?i)\b(p((abs|sign)[bdw]|maddubsw|mulhrsw|shufb|alignr))\b' scope: keyword.operator.word.mnemonic.sse3.supplimental.other mnemonics-sse4: - match: '(?i)\b(pmul(ld|dq)|dpp[ds])\b' scope: keyword.operator.word.mnemonic.sse4.1.arithmetic - match: '(?i)\b(movntdqa)\b' scope: keyword.operator.word.mnemonic.sse4.1.load-hint - match: '(?i)\b(blendv?p[ds]|pblend(vb|w))\b' scope: keyword.operator.word.mnemonic.sse4.1.packed-blending - match: '(?i)\b(p(min|max)(u[dw]|s[bd]))\b' scope: keyword.operator.word.mnemonic.sse4.1.packed-integer - match: '(?i)\b(round[ps][sd])\b' scope: keyword.operator.word.mnemonic.sse4.1.packed-floating-point - match: '(?i)\b((extract|insert)ps|p((ins|ext)(r[bdq])))\b' scope: keyword.operator.word.mnemonic.sse4.1.insertion-and-extraction - match: '(?i)\b(pmov([sz]x(b[dqw]|dq|wd|wq)))\b' scope: keyword.operator.word.mnemonic.sse4.1.conversion - match: '(?i)\b(mpsadbw|phminposuw|ptest|pcmpeqq|packusdw)\b' scope: keyword.operator.word.mnemonic.sse4.1.other - match: '(?i)\b(pcmp([ei]str[im]|gtq))\b' scope: keyword.operator.word.mnemonic.sse4.2 mnemonics-aesni: - match: '(?i)\b(aes((dec|enc)(last)?|imc|keygenassist)|pclmulqdq)\b' scope: keyword.operator.word.mnemonic.aesni mnemonics-avx: - match: '(?i)\b(v((test|permil|maskmov)p[ds]|zero(all|upper)|(perm2|insert|extract|broadcast)f128|broadcasts[ds]))\b' scope: keyword.operator.word.mnemonic.avx - match: '(?i)\b(vaes((dec|enc)(last)?|imc|keygenassist)|vpclmulqdq)\b' scope: keyword.operator.word.mnemonic.avx.promoted.aes - match: '(?i)\b(v((cmp[ps]|u?comis)[ds]|pcmp([ei]str[im]|(eq|gt)[bdqw])))\b' scope: keyword.operator.word.mnemonic.avx.promoted.comparison - match: '(?i)\b(v(cvt(dq2pd|dq2ps|pd2ps|ps2pd|sd2ss|si2sd|si2ss|ss2sd|t?(pd2dq|ps2dq|sd2si|ss2si))))\b' scope: keyword.operator.word.mnemonic.avx.promoted.conversion - match: '(?i)\b(vh((add|sub)p[ds])|vph((add|sub)([dw]|sw)|minposuw))\b' scope: keyword.operator.word.mnemonic.avx.promoted.horizontal-packed-arithmetic - match: '(?i)\b(v((andn?|x?or)p[ds]))\b' scope: keyword.operator.word.mnemonic.avx.promoted.logical - match: '(?i)\b(v(mov(([ahl]|msk|nt|u)p[ds]|(hl|lh)ps|s([ds]|[hl]dup)|q)))\b' scope: keyword.operator.word.mnemonic.avx.promoted.mov - match: '(?i)\b(v((add|div|mul|sub|max|min|round|sqrt)[ps][ds]|(addsub|dp)p[ds]|(rcp|rsqrt)[ps]s))\b' scope: keyword.operator.word.mnemonic.avx.promoted.packed-arithmetic - match: '(?i)\b(v(pack[su]s(dw|wb)|punpck[hl](bw|dq|wd|qdq)|unpck[hl]p[ds]))\b' scope: keyword.operator.word.mnemonic.avx.promoted.packed-conversion - match: '(?i)\b(vp(shuf([bd]|[hl]w))|vshufp[ds])\b' scope: keyword.operator.word.mnemonic.avx.promoted.packed-shuffle - match: '(?i)\b(vp((abs|sign|(max|min)[su])[bdw]|(add|sub)([bdqw]|u?s[bw])|avg[bw]|extr[bdqw]|madd(wd|ubsw)|mul(hu?w|hrsw|l[dw]|u?dq)|sadbw))\b' scope: keyword.operator.word.mnemonic.avx.promoted.supplemental.arithmetic - match: '(?i)\b(vp(andn?|x?or))\b' scope: keyword.operator.word.mnemonic.avx.promoted.supplemental.logical - match: '(?i)\b(vpblend(vb|w))\b' scope: keyword.operator.word.mnemonic.avx.promoted.supplemental.blending - match: '(?i)\b(vpmov(mskb|[sz]x(b[dqw]|w[dq]|dq)))\b' scope: keyword.operator.word.mnemonic.avx.promoted.supplemental.mov - match: '(?i)\b(vp(insr[bdqw]|sll(dq|[dqw])|srl(dq)))\b' scope: keyword.operator.word.mnemonic.avx.promoted.simd-integer - match: '(?i)\b(vp(sra[dwq]|srl[dqw]))\b' scope: keyword.operator.word.mnemonic.avx.promoted.shift-and-rotate - match: '(?i)\b(vblendv?p[ds])\b' scope: keyword.operator.word.mnemonic.avx.promoted.packed-blending - match: '(?i)\b(vp(test|alignr))\b' scope: keyword.operator.word.mnemonic.avx.promoted.packed-other - match: '(?i)\b(vmov(d(dup|qa|qu)?))\b' scope: keyword.operator.word.mnemonic.avx.promoted.simd-integer.mov - match: '(?i)\b(v((extract|insert)ps|lddqu|(ld|st)mxcsr|mpsadbw))\b' scope: keyword.operator.word.mnemonic.avx.promoted.other - match: '(?i)\b(v(maskmovdqu|movntdqa?))\b' scope: keyword.operator.word.mnemonic.avx.promoted.cacheability-control - match: '(?i)\b(vcvt(ph2ps|ps2ph))\b' scope: keyword.operator.word.mnemonic.16-bit-floating-point-conversion - match: '(?i)\b(vfn?m((add|sub)(132|213|231)[ps][ds])|vfm((addsub|subadd)(132|213|231)p[ds]))\b' scope: keyword.operator.word.mnemonic.fma mnemonics-avx2: - match: '(?i)\b(v((broadcast|extract|insert|perm2)i128|pmaskmov[dq]|perm([dsq]|p[sd])))\b' scope: keyword.operator.word.mnemonic.avx2.promoted.simd - match: '(?i)\b(vpbroadcast[bdqw])\b' scope: keyword.operator.word.mnemonic.avx2.promoted.packed - match: '(?i)\b(vp(blendd|s[lr]lv[dq]|sravd))\b' scope: keyword.operator.word.mnemonic.avx2.blend - match: '(?i)\b(vp?gather[dq][dq]|vgather([dq]|dq)p[ds])\b' scope: keyword.operator.word.mnemonic.avx2.gather mnemonics-tsx: - match: '(?i)\b(x(abort|acquire|release|begin|end|test))\b' scope: keyword.operator.word.mnemonic.tsx mnemonics-system: - match: '(?i)\b((cl|st)ac|[ls]([gli]dt|tr|msw)|clts|arpl|lar|lsl|ver[rw]|inv(d|lpg|pcid)|wbinvd)\b' scope: keyword.operator.word.mnemonic.system - match: '(?i)\b(lock|hlt|rsm|(rd|wr)(msr|pkru|[fg]sbase)|rd(pmc|tscp?)|sys(enter|exit))\b' scope: keyword.operator.word.mnemonic.system - match: '(?i)\b(x((save(c|opt|s)?|rstors?)(64)?|[gs]etbv))\b' scope: keyword.operator.word.mnemonic.system mnemonics-64bit: - match: '(?i)\b(cdqe|cqo|(cmp|lod|mov|sto)sq|cmpxchg16b|mov(ntq|sxd)|scasq|swapgs|sys(call|ret))\b' scope: keyword.operator.word.mnemonic.64-bit-mode mnemonics-vmx: - match: '(?i)\b(vm(ptr(ld|st)|clear|read|write|launch|resume|xo(ff|n)|call|func)|inv(ept|vpid))\b' scope: keyword.operator.word.mnemonic.vmx mnemonics-smx: - match: '(?i)\b(getsec)\b' scope: keyword.operator.word.mnemonic.smx.getsec - match: '(?i)\b(capabilities|enteraccs|exitac|senter|sexit|parameters|smctrl|wakeup)\b' scope: support.constant mnemonics-intel-isa-sgx: - match: '(?i)\be(add|block|create|dbg(rd|wr)|extend|init|ld[bu]|pa|remove|track|wb)\b' scope: keyword.operator.word.mnemonic.sgx1.supervisor - match: '(?i)\be(enter|exit|getkey|report|resume)\b' scope: keyword.operator.word.mnemonic.sgx1.user - match: '(?i)\be(aug|mod(pr|t))\b' scope: keyword.operator.word.mnemonic.sgx2.supervisor - match: '(?i)\be(accept(copy)?|modpe)\b' scope: keyword.operator.word.mnemonic.sgx2.user mnemonics-intel-isa-mpx: - match: '(?i)\b(bnd(mk|c[lnu]|mov|ldx|stx))\b' scope: keyword.operator.word.mnemonic.mpx mnemonics-intel-isa-sha: - match: '(?i)\b(sha(1rnds4|256rnds2|1nexte|(1|256)msg[12]))\b' scope: keyword.operator.word.mnemonic.sha mnemonics-supplemental-amd: - match: '(?i)\b(bl([cs](fill|ic?|msk)|cs)|t1mskc|tzmsk)\b' scope: keyword.operator.word.mnemonic.supplemental.amd.general-purpose - match: '(?i)\b(clgi|int3|invlpga|iretw|skinit|stgi|vm(load|mcall|run|save)|monitorx|mwaitx)\b' scope: keyword.operator.word.mnemonic.supplemental.amd.system - match: '(?i)\b([ls]lwpcb|lwp(ins|val))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.profiling - match: '(?i)\b(movnts[ds])\b' scope: keyword.operator.word.mnemonic.supplemental.amd.memory-management - match: '(?i)\b(prefetch|clzero)\b' scope: keyword.operator.word.mnemonic.supplemental.amd.cache-management - match: '(?i)\b((extr|insert)q)\b' scope: keyword.operator.word.mnemonic.supplemental.amd.sse4.a - match: '(?i)\b(vfn?m((add|sub)[ps][ds])|vfm((addsub|subadd)p[ds]))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.fma4 - match: '(?i)\b(vp(cmov|(comu?|rot|sh[al])[bdqw]|mac(s?s(d(d|q[hl])|w[dw]))|madcss?wd|perm))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.xop.simd - match: '(?i)\b(vph(addu?(b[dqw]|w[dq]|dq)|sub(bw|dq|wd)))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.xop.simd-horizontal - match: '(?i)\b(vfrcz[ps][ds]|vpermil2p[ds])\b' scope: keyword.operator.word.mnemonic.supplemental.amd.xop.other - match: '(?i)\b(femms)\b' scope: keyword.operator.word.mnemonic.supplemental.amd.3dnow - match: '(?i)\b(p(avgusb|(f2i|i2f)[dw]|mulhrw|swapd)|pf((p?n)?acc|add|max|min|mul|rcp(it[12])?|rsqit1|rsqrt|subr?))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.3dnow.simd - match: '(?i)\b(pfcmp(eq|ge|gt))\b' scope: keyword.operator.word.mnemonic.supplemental.amd.3dnow.comparison mnemonics-supplemental-cyrix: - match: '(?i)\b((sv|rs)dc|(wr|rd)shr|paddsiw)\b' scope: keyword.operator.word.mnemonic.supplemental.cyrix mnemonics-supplemental-via: - match: '(?i)\b(montmul)\b' scope: keyword.operator.word.mnemonic.supplemental.via - match: '(?i)\b(x(store(rng)?|crypt(ecb|cbc|ctr|cfb|ofb)|sha(1|256)))\b' scope: keyword.operator.word.mnemonic.supplemental.via.padlock mnemonics-undocumented: - match: '(?i)\b(ret[nf]|icebp|int1|int03|smi|ud1)\b' scope: keyword.operator.word.mnemonic.undocumented mnemonics-future-intel: - include: mnemonics-future-intel-avx512 - include: mnemonics-future-intel-opmask - include: mnemonics-future-intel-cet - include: mnemonics-future-intel-other mnemonics-future-intel-avx512: - match: '(?i)\b(vblendm(pd|ps)|vpblendm[bdqw])\b' scope: keyword.operator.word.mnemonic.avx512.blend - match: '(?i)\b(vbroadcast[fi](32x[248]|64x[24])|v(extract|insert)[fi](32x[48]|64x[24])|vshuf[fi](32x4|64x2)|vpbroadcastm(b2q|w2d))\b' scope: keyword.operator.word.mnemonic.avx512.bits-mov - match: '(?i)\b(v(compress|expand)p[ds]|vp(compress|expand|conflict)[dq])\b' scope: keyword.operator.word.mnemonic.avx512.compress - match: '(?i)\b(vcvt(t?p[sd]2(udq|u?qq)|(udq|u?qq)2p[ds]|t?s[ds]2usi|usi2s[ds]))\b' scope: keyword.operator.word.mnemonic.avx512.conversion - match: '(?i)\b(v(fixupimm|fpclass|get(exp|mant)|range|(rcp|rsqrt)(14|28)|reduce|rndscale|scalef)([ps][ds]))\b' scope: keyword.operator.word.mnemonic.avx512.math - match: '(?i)\b(v(exp2p[ds]|(scatter|(gather|scatter)pf[01])[dq]p[ds]))\b' scope: keyword.operator.word.mnemonic.avx512.math - match: '(?i)\b(vmovdq(a(32|64)|u(8|16|32|64)))\b' scope: keyword.operator.word.mnemonic.avx512.simd-integer - match: '(?i)\b(vp(andn?|x?or)[dq])\b' scope: keyword.operator.word.mnemonic.avx512.logical - match: '(?i)\b(vpcmpu?[dqw])\b' scope: keyword.operator.word.mnemonic.avx512.packed-comparison - match: '(?i)\b(vp(absq|(lzcnt|ternlog)[dq]|madd52[lh]uq|(max|min)[su]q|mullq))\b' scope: keyword.operator.word.mnemonic.avx512.packed-math - match: '(?i)\b(vpmov(m2[bdqw]|[bdqw]2m|(u?s)?([qd][bw]|qd|wb)))\b' scope: keyword.operator.word.mnemonic.avx512.packed-mov - match: '(?i)\b(vp(ro[rl]v?[dq]|scatter[dq][dq]))\b' scope: keyword.operator.word.mnemonic.avx512.packed-shift - match: '(?i)\b(vptestn?m[bdqw])\b' scope: keyword.operator.word.mnemonic.avx512.packed-test - match: '(?i)\b(vperm([bdw]|[it]2([bdwq]|p[ds])))\b' scope: keyword.operator.word.mnemonic.avx512.permutations - match: '(?i)\b(valign[dq]|vdbpsadbw|vpmultishiftqb|vpsrav[dqw])\b' scope: keyword.operator.word.mnemonic.avx512.other mnemonics-future-intel-opmask: - match: '(?i)\b(k(add|andn?|(xn?)?or|mov|not|(or)?test|shift[lr])[bdqw]|kunpck(bw|wd|dq))\b' scope: keyword.operator.word.mnemonic.opmask mnemonics-future-intel-cet: - match: '(?i)\b((inc|save|rstor)ssp|wru?ss|(set|clr)ssbsy|endbranch|endbr(32|64))\b' scope: keyword.operator.word.mnemonic.cet mnemonics-future-intel-other: - match: '(?i)\b(clflushopt|clwb|pcommit)\b' scope: keyword.operator.word.mnemonic.other mnemonics-pseudo-ops: - match: '(?i)\b(cmp(n?(eq|lt|le)|(un)?ord)[ps][ds])\b' scope: keyword.pseudo-mnemonic.sse2.compare - match: '(?i)\b(v?pclmul([hl]q[hl]q|[hl]qh)dq)\b' scope: keyword.pseudo-mnemonic.avx.promoted.aes - match: '(?i)\b(vcmp(eq(_(os|uq|us))?|neq(_(oq|os|us))?|[gl][et](_oq)?|n[gl][et](_uq)?|(un)?ord(_s)?|false(_os)?|true(_us)?)[ps][ds])\b' scope: keyword.pseudo-mnemonic.avx.promoted.comparison - match: '(?i)\b(vpcom(n?eq|[gl][et]|false|true)(b|uw))\b' scope: keyword.pseudo-mnemonic.supplemental.amd.xop.simd mnemonics-invalid: - include: mnemonics-invalid-amd-sse5 mnemonics-invalid-amd-sse5: - match: '(?i)\b(com[ps][ds]|pcomu?[bdqw])\b' scope: invalid.keyword.operator.word.mnemonic.sse5.comparison - match: '(?i)\b(cvtp(h2ps|s2ph)|frcz[ps][ds])\b' scope: invalid.keyword.operator.word.mnemonic.sse5.conversion - match: '(?i)\b(fn?m((add|sub)[ps][ds])|ph(addu?(b[dqw]|w[dq]|dq)|sub(bw|dq|wd))|pma(css?(d(d|q[hl])|w[dw])|dcss?wd))\b' scope: invalid.keyword.operator.word.mnemonic.sse5.packed-arithmetic - match: '(?i)\b(pcmov|permp[ds]|pperm|prot[bdqw]|psh[al][bdqw])\b' scope: invalid.keyword.operator.word.mnemonic.sse5.simd-integer ================================================ FILE: assets/syntaxes/02_Extra/CSV/CSV-comma.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: Comma Separated Values scope: text.csv.comma variables: field_separator: (?:,) record_separator: (?:$\n?) contexts: main: - match: '^' push: fields fields: - include: record_separator - match: '' push: - field_or_record_separator - field5 - field_or_record_separator - field4 - field_or_record_separator - field3 - field_or_record_separator - field2 - field_or_record_separator - field1 record_separator_pop: - match: (?={{record_separator}}) pop: true record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv pop: true field_or_record_separator: - meta_include_prototype: false - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true field_contents: - match: '"' scope: punctuation.definition.string.begin.csv push: scope:text.csv#double_quoted_string - include: record_separator_pop - match: (?={{field_separator}}) pop: true field1: - match: '' set: - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' set: - meta_content_scope: meta.field-2.csv support.function - include: field_contents field3: - match: '' set: - meta_content_scope: meta.field-3.csv constant.numeric - include: field_contents field4: - match: '' set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents field5: - match: '' set: - meta_content_scope: meta.field-5.csv string.unquoted - include: field_contents ================================================ FILE: assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: Pipe Separated Values scope: text.csv.pipe variables: field_separator: (?:\|) record_separator: (?:$\n?) contexts: main: - match: '^' push: fields fields: - include: record_separator - match: '' push: - field_or_record_separator - field5 - field_or_record_separator - field4 - field_or_record_separator - field3 - field_or_record_separator - field2 - field_or_record_separator - field1 record_separator_pop: - match: (?={{record_separator}}) pop: true record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv pop: true field_or_record_separator: - meta_include_prototype: false - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true field_contents: - match: '"' scope: punctuation.definition.string.begin.csv push: scope:text.csv#double_quoted_string - include: record_separator_pop - match: (?={{field_separator}}) pop: true field1: - match: '' set: - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' set: - meta_content_scope: meta.field-2.csv support.function - include: field_contents field3: - match: '' set: - meta_content_scope: meta.field-3.csv constant.numeric - include: field_contents field4: - match: '' set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents field5: - match: '' set: - meta_content_scope: meta.field-5.csv string.unquoted - include: field_contents ================================================ FILE: assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: Semi-Colon Separated Values scope: text.csv.semi-colon variables: field_separator: (?:;) record_separator: (?:$\n?) contexts: main: - match: '^' push: fields fields: - include: record_separator - match: '' push: - field_or_record_separator - field5 - field_or_record_separator - field4 - field_or_record_separator - field3 - field_or_record_separator - field2 - field_or_record_separator - field1 record_separator_pop: - match: (?={{record_separator}}) pop: true record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv pop: true field_or_record_separator: - meta_include_prototype: false - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true field_contents: - match: '"' scope: punctuation.definition.string.begin.csv push: scope:text.csv#double_quoted_string - include: record_separator_pop - match: (?={{field_separator}}) pop: true field1: - match: '' set: - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' set: - meta_content_scope: meta.field-2.csv support.function - include: field_contents field3: - match: '' set: - meta_content_scope: meta.field-3.csv constant.numeric - include: field_contents field4: - match: '' set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents field5: - match: '' set: - meta_content_scope: meta.field-5.csv string.unquoted - include: field_contents ================================================ FILE: assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: Separated Values file_extensions: - csv scope: text.csv variables: field_separator_chars: ',;\t|' field_separator: (?:[{{field_separator_chars}}]) record_separator: (?:$\n?) contexts: main: - meta_include_prototype: false - include: three_field_separators - include: single_separator_type_on_line - match: '^' push: unknown-separated-main three_field_separators: - match: ^(?=(?:[^,]*,){3}) set: scope:text.csv.comma - match: ^(?=(?:[^;]*;){3}) set: scope:text.csv.semi-colon - match: ^(?=(?:[^\t]*\t){3}) set: scope:text.csv.tab - match: ^(?=(?:[^|]*\|){3}) set: scope:text.csv.pipe single_separator_type_on_line: - match: ^(?=[^{{field_separator_chars}}]*,[^;\t|]*$) set: scope:text.csv.comma - match: ^(?=[^{{field_separator_chars}}]*;[^,\t|]*$) set: scope:text.csv.semi-colon - match: ^(?=[^{{field_separator_chars}}]*\t[^,;|]*$) set: scope:text.csv.tab - match: ^(?=[^{{field_separator_chars}}]*\|[^,;\t]*$) set: scope:text.csv.pipe unknown-separated-main: - include: record_separator - match: '' push: - field_or_record_separator - field5 - field_or_record_separator - field4 - field_or_record_separator - field3 - field_or_record_separator - field2 - field_or_record_separator - field1 record_separator_pop: - match: (?={{record_separator}}) pop: true record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv field_or_record_separator: - meta_include_prototype: false - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true field_contents: - match: '"' scope: punctuation.definition.string.begin.csv push: double_quoted_string - include: record_separator_pop - match: (?={{field_separator}}) pop: true double_quoted_string: - meta_include_prototype: false - meta_scope: meta.string.quoted.double.csv - match: '""' scope: constant.character.escape.csv - match: '"' scope: punctuation.definition.string.end.csv pop: true field1: - match: '' set: - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' set: - meta_content_scope: meta.field-2.csv support.function - include: field_contents field3: - match: '' set: - meta_content_scope: meta.field-3.csv constant.numeric - include: field_contents field4: - match: '' set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents field5: - match: '' set: - meta_content_scope: meta.field-5.csv string.unquoted - include: field_contents ================================================ FILE: assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html name: Tab Separated Values scope: text.csv.tab file_extensions: - tsv variables: field_separator: (?:\t) record_separator: (?:$\n?) contexts: main: - match: '^' push: fields fields: - include: record_separator - match: '' push: - field_or_record_separator - field5 - field_or_record_separator - field4 - field_or_record_separator - field3 - field_or_record_separator - field2 - field_or_record_separator - field1 record_separator_pop: - match: (?={{record_separator}}) pop: true record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv pop: true field_or_record_separator: - meta_include_prototype: false - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true field_contents: - match: '"' scope: punctuation.definition.string.begin.csv push: scope:text.csv#double_quoted_string - include: record_separator_pop - match: (?={{field_separator}}) pop: true field1: - match: '' set: - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' set: - meta_content_scope: meta.field-2.csv support.function - include: field_contents field3: - match: '' set: - meta_content_scope: meta.field-3.csv constant.numeric - include: field_contents field4: - match: '' set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents field5: - match: '' set: - meta_content_scope: meta.field-5.csv string.unquoted - include: field_contents ================================================ FILE: assets/syntaxes/02_Extra/Cabal.sublime-syntax ================================================ %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|custom-setup)\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: assets/syntaxes/02_Extra/CoffeeScript.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: CoffeeScript comment: "CoffeeScript Syntax: version 1" file_extensions: - coffee - Cakefile - coffee.erb - cson first_line_match: ^#!.*\bcoffee scope: source.coffee contexts: main: - match: '(\([^()]*?\))\s*([=-]>)' comment: "match stuff like: a -> …" scope: meta.inline.function.coffee captures: 1: variable.parameter.function.coffee 2: storage.type.function.coffee - match: (new)\s+(\w+(?:\.\w*)*) scope: meta.class.instance.constructor captures: 1: keyword.operator.new.coffee 2: support.class.coffee - match: "'''" captures: 0: punctuation.definition.string.begin.coffee push: - meta_scope: string.quoted.heredoc.coffee - match: "'''" captures: 0: punctuation.definition.string.end.coffee pop: true - match: '"""' captures: 0: punctuation.definition.string.begin.coffee push: - meta_scope: string.quoted.double.heredoc.coffee - match: '"""' captures: 0: punctuation.definition.string.end.coffee pop: true - match: \\. scope: constant.character.escape.coffee - include: interpolated_coffee - match: "`" captures: 0: punctuation.definition.string.begin.coffee push: - meta_scope: string.quoted.script.coffee - match: "`" captures: 0: punctuation.definition.string.end.coffee pop: true - match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)' scope: constant.character.escape.coffee - match: (?)|\+\+|\+|~|==|=(?!>)|!=|<=|>=|<<=|>>=| >>>=|<>|<|>|!|&&|\.\.(\.)?|\?|\||\|\||\:|\*=|(?)))' scope: variable.assignment.coffee captures: 1: variable.assignment.coffee 4: punctuation.separator.key-value 5: keyword.operator.coffee - match: '(?<=\s|^)([\[\{])(?=.*?[\]\}]\s+[:=])' captures: 0: keyword.operator.coffee push: - meta_scope: meta.variable.assignment.destructured.coffee - match: '([\]\}]\s*[:=])' captures: 0: keyword.operator.coffee pop: true - include: variable_name - include: instance_variable - include: single_quoted_string - include: double_quoted_string - include: numeric - match: |- (?x) (\s*) (?=[a-zA-Z\$_]) ( [a-zA-Z\$_](\w|\$|:|\.)*\s* (?=[:=](\s*\(.*\))?\s*([=-]>)) ) scope: meta.function.coffee captures: 2: entity.name.function.coffee 3: entity.name.function.coffee 4: variable.parameter.function.coffee 5: storage.type.function.coffee - match: ^\s*(describe|it|app\.(get|post|put|all|del|delete)) comment: Show well-known functions from Express and Mocha in Go To Symbol view push: - meta_scope: meta.function.symbols.coffee - match: $ pop: true - include: main - match: "[=-]>" scope: storage.type.function.coffee - match: '\b(?|_|\*|\$|\?|:|"|-[0adFiIlpv])' scope: variable.other.readwrite.global.pre-defined.crystal captures: 1: punctuation.definition.variable.crystal - match: '\b(ENV)\[' captures: 1: variable.other.constant.crystal push: - meta_scope: meta.environment-variable.crystal - match: '\]' pop: true - include: main - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*' scope: support.class.crystal - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*\b' scope: variable.other.constant.crystal - match: |- (?x) (?=def\b) # an optimization to help Oniguruma fail fast (?<=^|\s)(def)\s+ # the def keyword ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>\.|::))? # a method name prefix (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\](?:=|\?)?) ) # …or an operator method \s*(\() # the openning parenthesis for arguments comment: the method pattern comes from the symbol pattern, see there for a explaination captures: 1: keyword.control.def.crystal 2: entity.name.function.crystal 3: punctuation.definition.parameters.crystal push: - meta_scope: meta.function.method.with-arguments.crystal - meta_content_scope: variable.parameter.function.crystal - match: \) captures: 0: punctuation.definition.parameters.crystal pop: true - include: main - match: |- (?x) (?=def\b) # an optimization to help Oniguruma fail fast (?<=^|\s)(def)\s+ # the def keyword ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\](?:=|\?)?) ) # …or an operator method [ \t] # the space separating the arguments (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow comment: same as the previous rule, but without parentheses around the arguments captures: 1: keyword.control.def.crystal 2: entity.name.function.crystal push: - meta_scope: meta.function.method.with-arguments.crystal - meta_content_scope: variable.parameter.function.crystal - match: $ pop: true - include: main - match: |- (?x) (?=def\b) # an optimization to help Oniguruma fail fast (?<=^|\s)(def)\b # the def keyword ( \s+ # an optional group of whitespace followed by… ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\](?:=|\?)?) ) )? # …or an operator method comment: the optional name is just to catch the def also without a method-name scope: meta.function.method.without-arguments.crystal captures: 1: keyword.control.def.crystal 3: entity.name.function.crystal - match: '\b(0[xX]\h(?>_?\h)*|\d(?>_?\d)*(\.(?![^[:space:][:digit:]])(?>_?\d)*)?([eE][-+]?\d(?>_?\d)*)?|0[bB][01]+|0o[0-7]+)(_?(u8|u16|u32|u64|i8|i16|i32|i64|f32|f64))?\b' scope: constant.numeric.crystal - match: ":'" captures: 0: punctuation.definition.constant.crystal push: - meta_scope: constant.other.symbol.single-quoted.crystal - match: "'" captures: 0: punctuation.definition.constant.crystal pop: true - match: '\\[''\\]' scope: constant.character.escape.crystal - match: ':"' captures: 0: punctuation.definition.constant.crystal push: - meta_scope: constant.other.symbol.double-quoted.crystal - match: '"' captures: 0: punctuation.definition.constant.crystal pop: true - include: interpolated_crystal - include: escaped_char - match: /= comment: Needs higher precidence than regular expressions. scope: keyword.operator.assignment.augmented.crystal - match: "'" comment: single quoted string (does not allow interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.single.crystal - match: "'" captures: 0: punctuation.definition.string.end.crystal pop: true - match: \\'|\\\\ scope: constant.character.escape.crystal - match: '"' comment: double quoted string (allows for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.double.crystal - match: '"' captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - match: "`" comment: execute string (allows for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: "`" captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - match: '%x\{' comment: execute string (allow for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: '\}' captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_curly_i - match: '%x\[' comment: execute string (allow for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: '\]' captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_brackets_i - match: '%x\<' comment: execute string (allow for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: \> captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_ltgt_i - match: '%x\(' comment: execute string (allow for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: \) captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_parens_i - match: '%x([^\w])' comment: execute string (allow for interpolation) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.interpolated.crystal - match: \1 captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - match: |- (?x) (?: ^ # beginning of line | (?<= # or look-behind on: [=>~(?:\[,|&;] | [\s;]if\s # keywords | [\s;]elsif\s | [\s;]while\s | [\s;]unless\s | [\s;]when\s | [\s;]assert_match\s | [\s;]or\s # boolean opperators | [\s;]and\s | [\s;]not\s | [\s.]index\s # methods | [\s.]scan\s | [\s.]sub\s | [\s.]sub!\s | [\s.]gsub\s | [\s.]gsub!\s | [\s.]match\s ) | (?<= # or a look-behind with line anchor: ^when\s # duplication necessary due to limits of regex | ^if\s | ^elsif\s | ^while\s | ^unless\s ) ) \s*((/))(?![*+{}?]) comment: | regular expressions (normal) we only start a regexp if the character before it (excluding whitespace) is what we think is before a regexp captures: 1: string.regexp.classic.crystal 2: punctuation.definition.string.crystal push: - meta_content_scope: string.regexp.classic.crystal - match: "((/[eimnosux]*))" captures: 1: string.regexp.classic.crystal 2: punctuation.definition.string.crystal pop: true - include: regex_sub - match: '%r\{' comment: regular expressions (literal) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.regexp.mod-r.crystal - match: '\}[eimnosux]*' captures: 0: punctuation.definition.string.end.crystal pop: true - include: regex_sub - include: nest_curly_r - match: '%r\[' comment: regular expressions (literal) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.regexp.mod-r.crystal - match: '\][eimnosux]*' captures: 0: punctuation.definition.string.end.crystal pop: true - include: regex_sub - include: nest_brackets_r - match: '%r\(' comment: regular expressions (literal) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.regexp.mod-r.crystal - match: '\)[eimnosux]*' captures: 0: punctuation.definition.string.end.crystal pop: true - include: regex_sub - include: nest_parens_r - match: '%r\<' comment: regular expressions (literal) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.regexp.mod-r.crystal - match: '\>[eimnosux]*' captures: 0: punctuation.definition.string.end.crystal pop: true - include: regex_sub - include: nest_ltgt_r - match: '%r([^\w])' comment: regular expressions (literal) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.regexp.mod-r.crystal - match: '\1[eimnosux]*' captures: 0: punctuation.definition.string.end.crystal pop: true - include: regex_sub - match: '%[QWSR]?\(' comment: literal capable of interpolation () captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.upper.crystal - match: \) captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_parens_i - match: '%[QWSR]?\[' comment: "literal capable of interpolation []" captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.upper.crystal - match: '\]' captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_brackets_i - match: '%[QWSR]?\<' comment: literal capable of interpolation <> captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.upper.crystal - match: \> captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_ltgt_i - match: '%[QWSR]?\{' comment: "literal capable of interpolation -- {}" captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.double.crystal.mod - match: '\}' captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_curly_i - match: '%[QWSR]([^\w])' comment: literal capable of interpolation -- wildcard captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.upper.crystal - match: \1 captures: 0: punctuation.definition.string.end.crystal pop: true - include: interpolated_crystal - include: escaped_char - match: '%[qws]\(' comment: literal incapable of interpolation -- () captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.lower.crystal - match: \) captures: 0: punctuation.definition.string.end.crystal pop: true - match: \\\)|\\\\ scope: constant.character.escape.crystal - include: nest_parens - match: '%[qws]\<' comment: literal incapable of interpolation -- <> captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.lower.crystal - match: \> captures: 0: punctuation.definition.string.end.crystal pop: true - match: \\\>|\\\\ scope: constant.character.escape.crystal - include: nest_ltgt - match: '%[qws]\[' comment: "literal incapable of interpolation -- []" captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.lower.crystal - match: '\]' captures: 0: punctuation.definition.string.end.crystal pop: true - match: '\\\]|\\\\' scope: constant.character.escape.crystal - include: nest_brackets - match: '%[qws]\{' comment: "literal incapable of interpolation -- {}" captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.lower.crystal - match: '\}' captures: 0: punctuation.definition.string.end.crystal pop: true - match: '\\\}|\\\\' scope: constant.character.escape.crystal - include: nest_curly - match: '%[qws]([^\w])' comment: literal incapable of interpolation -- wildcard captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.quoted.other.literal.lower.crystal - match: \1 captures: 0: punctuation.definition.string.end.crystal pop: true - match: \\. comment: Cant be named because its not neccesarily an escape. - match: '(?[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?![>=]))?|===?|>[>=]?|<[<=]?|<=>|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\](?:=|\?)?|@@?[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*|!=?(?![?!]))' comment: symbols scope: constant.other.symbol.crystal captures: 1: punctuation.definition.constant.crystal - match: '(?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!])?)(:)(?!:)' comment: symbols scope: constant.other.symbol.crystal.19syntax captures: 1: punctuation.definition.constant.crystal - match: '(?:^[ \t]+)?(#).*$\n?' scope: comment.line.number-sign.crystal captures: 1: punctuation.definition.comment.crystal - match: ^__END__\n comment: __END__ marker captures: 0: string.unquoted.program-block.crystal push: - meta_content_scope: text.plain - match: (?=not)impossible captures: 0: string.unquoted.program-block.crystal pop: true - match: (?=<<-("?)((?:[_\w]+_|)HTML)\b\1)' comment: heredoc with embedded HTML and indented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.html.crystal - meta_content_scope: text.html.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:text.html.basic - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)SQL)\b\1)' comment: heredoc with embedded SQL and indented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.sql.crystal - meta_content_scope: text.sql.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.sql - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)CSS)\b\1)' comment: heredoc with embedded css and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.css.crystal - meta_content_scope: text.css.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.css - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)CPP)\b\1)' comment: heredoc with embedded c++ and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.cplusplus.crystal - meta_content_scope: text.c++.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.c++ - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)C)\b\1)' comment: heredoc with embedded c++ and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.c.crystal - meta_content_scope: text.c.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.c - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)(?:JS|JAVASCRIPT))\b\1)' comment: heredoc with embedded javascript and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.js.crystal - meta_content_scope: text.js.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:text.html.basic - include: scope:source.js - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)JQUERY)\b\1)' comment: heredoc with embedded javascript and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.js.crystal - meta_content_scope: text.js.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.js - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)(?:SH|SHELL))\b\1)' comment: heredoc with embedded shell and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.shell.crystal - meta_content_scope: text.shell.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.shell - include: interpolated_crystal - include: escaped_char - match: '(?><<-("?)((?:[_\w]+_|)RUBY)\b\1)' comment: heredoc with embedded crystal and intented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.embedded.crystal.crystal - meta_content_scope: text.crystal.embedded.crystal - match: \s*\2$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: scope:source.crystal - include: interpolated_crystal - include: escaped_char - match: (?>\=\s*<<(\w+)) captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.heredoc.crystal - match: ^\1$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: interpolated_crystal - include: escaped_char - match: (?><<-(\w+)) comment: heredoc with indented terminator captures: 0: punctuation.definition.string.begin.crystal push: - meta_scope: string.unquoted.heredoc.crystal - match: \s*\1$ captures: 0: punctuation.definition.string.end.crystal pop: true - include: heredoc - include: interpolated_crystal - include: escaped_char - match: '(?<=\{|do|\{\s|do\s)(\|)' captures: 1: punctuation.separator.variable.crystal push: - match: (\|) captures: 1: punctuation.separator.variable.crystal pop: true - match: "[_a-zA-Z][_a-zA-Z0-9]*" scope: variable.other.block.crystal - match: "," scope: punctuation.separator.variable.crystal - match: "=>" scope: punctuation.separator.key-value - match: '<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<' scope: keyword.operator.assignment.augmented.crystal - match: '<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \t])\?' scope: keyword.operator.comparison.crystal - match: '(?<=[ \t])!+|\bnot\b|&&|\band\b|\|\||\bor\b|\^' scope: keyword.operator.logical.crystal - match: '(\{\%|\%\}|\{\{|\}\})' scope: keyword.operator.macro.crystal - match: (%|&|\*\*|\*|\+|\-|/) scope: keyword.operator.arithmetic.crystal - match: "=" scope: keyword.operator.assignment.crystal - match: \||~|>> scope: keyword.operator.other.crystal - match: ":" scope: punctuation.separator.other.crystal - match: \; scope: punctuation.separator.statement.crystal - match: "," scope: punctuation.separator.object.crystal - match: '\.|::' scope: punctuation.separator.method.crystal - match: '\{|\}' scope: punctuation.section.scope.crystal - match: '\[|\]' scope: punctuation.section.array.crystal - match: \(|\) scope: punctuation.section.function.crystal escaped_char: - match: '\\(?:[0-7]{1,3}|x[\da-fA-F]{1,2}|.)' scope: constant.character.escape.crystal heredoc: - match: ^<<-?\w+ push: - match: $ pop: true - include: main interpolated_crystal: - match: '#\{(\})' scope: source.crystal.embedded.source captures: 0: punctuation.section.embedded.crystal 1: source.crystal.embedded.source.empty - match: '#\{' captures: 0: punctuation.section.embedded.crystal push: - meta_scope: source.crystal.embedded.source - match: '\}' captures: 0: punctuation.section.embedded.crystal pop: true - include: nest_curly_and_self - include: main - match: '(#@)[a-zA-Z_]\w*' scope: variable.other.readwrite.instance.crystal captures: 1: punctuation.definition.variable.crystal - match: '(#@@)[a-zA-Z_]\w*' scope: variable.other.readwrite.class.crystal captures: 1: punctuation.definition.variable.crystal - match: '(#\$)[a-zA-Z_]\w*' scope: variable.other.readwrite.global.crystal captures: 1: punctuation.definition.variable.crystal nest_brackets: - match: '\[' captures: 0: punctuation.section.scope.crystal push: - match: '\]' captures: 0: punctuation.section.scope.crystal pop: true - include: nest_brackets nest_brackets_i: - match: '\[' captures: 0: punctuation.section.scope.crystal push: - match: '\]' captures: 0: punctuation.section.scope.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_brackets_i nest_brackets_r: - match: '\[' captures: 0: punctuation.section.scope.crystal push: - match: '\]' captures: 0: punctuation.section.scope.crystal pop: true - include: regex_sub - include: nest_brackets_r nest_curly: - match: '\{' captures: 0: punctuation.section.scope.crystal push: - match: '\}' captures: 0: punctuation.section.scope.crystal pop: true - include: nest_curly nest_curly_and_self: - match: '\{' captures: 0: punctuation.section.scope.crystal push: - match: '\}' captures: 0: punctuation.section.scope.crystal pop: true - include: nest_curly_and_self - include: main nest_curly_i: - match: '\{' captures: 0: punctuation.section.scope.crystal push: - match: '\}' captures: 0: punctuation.section.scope.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_curly_i nest_curly_r: - match: '\{' captures: 0: punctuation.section.scope.crystal push: - match: '\}' captures: 0: punctuation.section.scope.crystal pop: true - include: regex_sub - include: nest_curly_r nest_ltgt: - match: \< captures: 0: punctuation.section.scope.crystal push: - match: \> captures: 0: punctuation.section.scope.crystal pop: true - include: nest_ltgt nest_ltgt_i: - match: \< captures: 0: punctuation.section.scope.crystal push: - match: \> captures: 0: punctuation.section.scope.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_ltgt_i nest_ltgt_r: - match: \< captures: 0: punctuation.section.scope.crystal push: - match: \> captures: 0: punctuation.section.scope.crystal pop: true - include: regex_sub - include: nest_ltgt_r nest_parens: - match: \( captures: 0: punctuation.section.scope.crystal push: - match: \) captures: 0: punctuation.section.scope.crystal pop: true - include: nest_parens nest_parens_i: - match: \( captures: 0: punctuation.section.scope.crystal push: - match: \) captures: 0: punctuation.section.scope.crystal pop: true - include: interpolated_crystal - include: escaped_char - include: nest_parens_i nest_parens_r: - match: \( captures: 0: punctuation.section.scope.crystal push: - match: \) captures: 0: punctuation.section.scope.crystal pop: true - include: regex_sub - include: nest_parens_r regex_sub: - include: interpolated_crystal - include: escaped_char - match: '(\{)\d+(,\d+)?(\})' scope: string.regexp.arbitrary-repitition.crystal captures: 1: punctuation.definition.arbitrary-repitition.crystal 3: punctuation.definition.arbitrary-repitition.crystal - match: '\[(?:\^?\])?' captures: 0: punctuation.definition.character-class.crystal push: - meta_scope: string.regexp.character-class.crystal - match: '\]' captures: 0: punctuation.definition.character-class.crystal pop: true - include: escaped_char - match: \( captures: 0: punctuation.definition.group.crystal push: - meta_scope: string.regexp.group.crystal - match: \) captures: 0: punctuation.definition.group.crystal pop: true - include: regex_sub - match: '(?<=^|\s)(#)\s[[a-zA-Z0-9,. \t?!-][^\x{00}-\x{7F}]]*$' comment: We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags. scope: comment.line.number-sign.crystal captures: 1: punctuation.definition.comment.crystal ================================================ FILE: assets/syntaxes/02_Extra/Dart.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html name: Dart file_extensions: - dart scope: source.dart contexts: main: - match: ^(#!.*)$ scope: meta.preprocessor.script.dart - match: ^\w*\b(library|import|part of|part|export)\b captures: 0: keyword.other.import.dart push: - meta_scope: meta.declaration.dart - match: ; captures: 0: punctuation.terminator.dart pop: true - include: strings - include: comments - match: \b(as|show|hide)\b scope: keyword.other.import.dart - include: comments - include: punctuation - include: annotations - include: keywords - include: constants-and-special-vars - include: strings annotations: - match: '@[a-zA-Z]+' scope: storage.type.annotation.dart comments: - match: /\*\*/ scope: comment.block.empty.dart captures: 0: punctuation.definition.comment.dart - include: comments-doc-oldschool - include: comments-doc - include: comments-inline comments-block: - match: /\* push: - meta_scope: comment.block.dart - match: \*/ pop: true - include: comments-block comments-doc: - match: /// push: - meta_scope: comment.block.documentation.dart - match: .* pop: true - include: dartdoc comments-doc-oldschool: - match: /\*\* push: - meta_scope: comment.block.documentation.dart - match: \*/ pop: true - include: comments-doc-oldschool - include: comments-block - include: dartdoc comments-inline: - include: comments-block - match: ((//).*)$ captures: 1: comment.line.double-slash.dart constants-and-special-vars: - match: (?)' captures: 1: entity.name.function.dart dartdoc: - match: '(\[.*?\])' captures: 0: variable.name.source.dart - match: '^ {4,}(?![ \*]).*' captures: 0: variable.name.source.dart - match: '```.*?$' push: - meta_content_scope: variable.other.source.dart - match: '```' pop: true - match: (`.*?`) captures: 0: variable.other.source.dart - match: (`.*?`) captures: 0: variable.other.source.dart - match: (\* (( ).*))$ captures: 2: variable.other.source.dart - match: (\* .*)$ keywords: - match: (?>>?|~|\^|\||&) scope: keyword.operator.bitwise.dart - match: ((&|\^|\||<<|>>>?)=) scope: keyword.operator.assignment.bitwise.dart - match: (=>) scope: keyword.operator.closure.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: (?]*>)' captures: 1: punctuation.definition.tag.html 2: entity.name.tag.html push: - meta_scope: meta.tag.any.html - match: (>(<)/)(\2)(>) captures: 1: punctuation.definition.tag.html 2: meta.scope.between-tag-pair.html 3: entity.name.tag.html 4: punctuation.definition.tag.html pop: true - include: tag-stuff - match: (<\?)(xml) captures: 1: punctuation.definition.tag.html 2: entity.name.tag.xml.html push: - meta_scope: meta.tag.preprocessor.xml.html - match: (\?>) captures: 1: punctuation.definition.tag.html 2: entity.name.tag.xml.html pop: true - include: tag-generic-attribute - include: string-double-quoted - include: string-single-quoted - match: ) scope: comment.block.html.js captures: 0: punctuation.definition.comment.js - match: (//).*$\n? scope: comment.line.double-slash.js captures: 1: punctuation.definition.comment.js - match: ^(#!).*$\n? scope: comment.line.shebang.js captures: 1: punctuation.definition.comment.js core: - include: literal-function-labels - include: literal-arrow-function-labels - include: literal-labels - include: literal-for - include: literal-switch - include: styled-components - include: graphql - include: expression - include: literal-punctuation curly-brackets: - match: "{" captures: 0: meta.brace.curly.begin.js push: - meta_scope: meta.group.braces.curly.js - match: "}" captures: 0: meta.brace.curly.end.js pop: true - include: main es7-decorators: - match: |- (?x) (@)([_$a-zA-Z][$\w]*)\b scope: tag.decorator.js captures: 1: punctuation.definition.tag.js 2: entity.name.tag.js expression: - include: merge-conflits - include: literal-regexp - include: literal-jsx - include: es7-decorators - include: support-class - include: support-other - include: literal-function - include: literal-arrow-function - include: literal-prototype - include: literal-keywords - include: literal-method - include: literal-module - include: literal-class - include: flowtype-declaration - include: literal-number - include: literal-template-string - include: literal-string - include: literal-language-constant - include: literal-language-variable - include: literal-constructor - include: literal-method-call - include: literal-function-call - include: comments - include: brackets - include: literal-operators - include: literal-variable flowtype-annotation: - match: (?:(\?)\s*)?(:) captures: 1: keyword.operator.flowtype.optional.js 2: keyword.operator.flowtype.annotation.js push: - meta_scope: meta.flowtype.annotation.js - include: flowtype-tokens - match: (?=\S) pop: true flowtype-brackets: - match: "{" captures: 0: punctuation.section.flowtype.begin.js push: - match: "}" captures: 0: punctuation.section.flowtype.end.js pop: true - include: flowtype-tokens flowtype-declaration: - match: (?" captures: 0: punctuation.section.flowtype.end.js pop: true - include: flowtype-tokens flowtype-tokens: - match: '(?<=[:?|&=])(?=\s*{)' push: - match: "(?<=})" pop: true - include: flowtype-brackets - match: '\s*([|&])\s*' scope: meta.flowtype.set.js captures: 1: keyword.operator.flowtype.other.js - match: '[*:?&|.]|\.\.\.|\b(typeof)\b' scope: keyword.operator.flowtype.other.js - match: < captures: 0: punctuation.section.flowtype.begin.js push: - match: ">" captures: 0: punctuation.section.flowtype.end.js pop: true - include: flowtype-tokens - match: '\[' captures: 0: punctuation.section.flowtype.begin.js push: - match: '\]' captures: 0: punctuation.section.flowtype.end.js pop: true - include: flowtype-tokens - match: \( captures: 0: punctuation.section.flowtype.begin.js push: - match: \) captures: 0: punctuation.section.flowtype.end.js pop: true - include: flowtype-tokens - match: "=>" captures: 0: keyword.operator.flowtype.js push: - meta_scope: meta.flowtype.function.js - match: "(?<=}|[_$a-zA-Z])" pop: true - include: flowtype-brackets - include: flowtype-identifier - include: comments - include: flowtype-identifier - include: literal-string - include: comments function-declaration-parameters: - match: \( captures: 0: punctuation.definition.parameters.begin.js push: - match: \) captures: 0: punctuation.definition.parameters.end.js pop: true - include: comments - include: flowtype-annotation - match: (?" captures: 0: meta.tag.jsx punctuation.definition.tag.end.jsx push: - match: (?=)|(/>) captures: 1: meta.tag.jsx punctuation.definition.tag.begin.jsx 2: meta.tag.jsx entity.name.tag.jsx 3: meta.tag.jsx punctuation.definition.tag.end.jsx 4: meta.tag.jsx punctuation.definition.tag.end.jsx pop: true - include: jsx-tag-end - include: jsx-attributes - match: < scope: invalid.illegal.tag.incomplete.jsx literal-arrow-function: - match: |- (?x) (?:([_$a-zA-Z][$\w]*)\s*(=)\s*)? (?:\b(async)\s+)? (?=(\((?>(?>[^()]+)|\g<-1>)*\))\s*(=>)) captures: 1: entity.name.function.js 2: keyword.operator.assignment.js 3: storage.type.js push: - meta_scope: meta.function.arrow.js - match: (?<=\))\s*(=>) captures: 1: storage.type.function.arrow.js pop: true - include: function-declaration-parameters - match: |- (?x) (?:([_$a-zA-Z][$\w]*)\s*(=)\s*)? (?:(async)\s+)? \b([_$a-zA-Z][$\w]*)\s*(=>) scope: meta.function.arrow.js captures: 1: entity.name.function.js 2: keyword.operator.assignment.js 3: storage.type.js 4: variable.parameter.function.js 5: storage.type.function.arrow.js - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)(prototype) (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(async)? \s*(?=(\((?>(?>[^()]+)|\g<-1>)*\))\s*(=>)) captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: variable.language.prototype.js 4: keyword.operator.accessor.js 5: entity.name.function.js 6: keyword.operator.assignment.js 7: storage.type.js push: - meta_scope: meta.prototype.function.arrow.js - match: (?<=\))\s*(=>) captures: 1: storage.type.function.arrow.js pop: true - include: function-declaration-parameters - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)(prototype) (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(async)? \s*\b([_$a-zA-Z][$\w]*)\s*(=>) scope: meta.prototype.function.arrow.js captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: variable.language.prototype.js 4: keyword.operator.accessor.js 5: entity.name.function.js 6: keyword.operator.assignment.js 7: storage.type.js 8: variable.parameter.function.js 9: storage.type.function.arrow.js - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(async)? \s*(?=(\((?>(?>[^()]+)|\g<-1>)*\))\s*(=>)) captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: entity.name.function.js 4: keyword.operator.assignment.js 5: storage.type.js push: - meta_scope: meta.function.static.arrow.js - match: (?<=\))\s*(=>) captures: 1: storage.type.function.arrow.js pop: true - include: function-declaration-parameters - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(async)? \s*\b([_$a-zA-Z][$\w]*)\s*(=>) scope: meta.function.static.arrow.js captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: entity.name.function.js 4: keyword.operator.assignment.js 5: storage.type.js 6: variable.parameter.function.js 7: storage.type.function.arrow.js literal-arrow-function-labels: - match: |- (?x) (?> ((')((?>[^'\\]|\\.)*)('))| ((")((?>[^"\\]|\\.)*)("))| (([_$a-zA-Z][$\w]*|\d+)) ) \s*(:) \s*(?:\b(async)\s+)? \s*(?=(\((?>(?>[^()]+)|\g<-1>)*\))\s*(=>)) captures: 1: string.quoted.js 2: punctuation.definition.string.begin.js 3: entity.name.function.js 4: punctuation.definition.string.end.js 5: string.quoted.js 6: punctuation.definition.string.begin.js 7: entity.name.function.js 8: punctuation.definition.string.end.js 9: string.unquoted.js 10: entity.name.function.js 11: punctuation.separator.key-value.js 12: storage.type.js push: - meta_scope: meta.function.json.arrow.js - match: (?<=\))\s*(=>) captures: 1: storage.type.function.arrow.js pop: true - include: function-declaration-parameters - match: |- (?x) (?> ((')((?>[^'\\]|\\.)*)('))| ((")((?>[^"\\]|\\.)*)("))| (([_$a-zA-Z][$\w]*|\d+)) ) \s*(:) \s*(?:\b(async)\s+)? \s*\b([_$a-zA-Z][$\w]*)\s*(=>) scope: meta.function.json.arrow.js captures: 1: string.quoted.js 2: punctuation.definition.string.begin.js 3: entity.name.function.js 4: punctuation.definition.string.end.js 5: string.quoted.js 6: punctuation.definition.string.begin.js 7: entity.name.function.js 8: punctuation.definition.string.end.js 9: string.unquoted.js 10: entity.name.function.js 11: punctuation.separator.key-value.js 12: storage.type.js 13: variable.parameter.function.js 14: storage.type.function.arrow.js literal-class: - match: (?\s*(\*)|(?=[\s(<])) \s*([_$a-zA-Z][$\w]*)? captures: 1: entity.name.function.js 2: keyword.operator.assignment.js 3: storage.type.js 4: storage.type.function.js 5: keyword.generator.asterisk.js 6: entity.name.function.js push: - meta_scope: meta.function.js - match: (?<=\)) pop: true - include: flowtype-polymorph - include: function-declaration-parameters - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)(prototype) (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(?:(async)\s+)? \s*(function)(?>\s*(\*)|(?=[\s(<])) \s*([_$a-zA-Z][$\w]*)?\s* captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: variable.language.prototype.js 4: keyword.operator.accessor.js 5: entity.name.function.js 6: keyword.operator.assignment.js 7: storage.type.js 8: storage.type.function.js 9: keyword.generator.asterisk.js 10: entity.name.function.js push: - meta_scope: meta.function.prototype.js - match: (?<=\)) pop: true - include: flowtype-polymorph - include: function-declaration-parameters - match: |- (?x) (\b_?[A-Z][$\w]*)? (\.)([_$a-zA-Z][$\w]*) \s*(=) \s*(?:(async)\s+)? \s*(function)(?>\s*(\*)|(?=[\s(<])) \s*([_$a-zA-Z][$\w]*)?\s* captures: 1: entity.name.class.js 2: keyword.operator.accessor.js 3: entity.name.function.js 4: keyword.operator.assignment.js 5: storage.type.js 6: storage.type.function.js 7: keyword.generator.asterisk.js 8: entity.name.function.js push: - meta_scope: meta.function.static.js - match: (?<=\)) pop: true - include: flowtype-polymorph - include: function-declaration-parameters literal-function-call: - match: '([_$a-zA-Z][$\w]*)\s*(\(\s*\))' scope: meta.function-call.without-arguments.js captures: 1: variable.function.js 2: meta.group.braces.round.function.arguments.js - match: '([_$a-zA-Z][$\w]*)\s*(?=\()' scope: meta.function-call.with-arguments.js captures: 1: variable.function.js - match: '([_$a-zA-Z][$\w]*)\s*(?=`)' scope: meta.function-call.tagged-template.js captures: 1: variable.function.js literal-function-labels: - match: |- (?x) (?> ((')((?>[^'\\]|\\.)*)('))| ((")((?>[^"\\]|\\.)*)("))| (([_$a-zA-Z][$\w]*|\d+)) ) \s*(:) \s*(?:\b(async)\s+)? \s*(function)(?>\s*(\*)|(?=[\s(<])) \s*([_$a-zA-Z][$\w]*)? captures: 1: string.quoted.js 2: punctuation.definition.string.begin.js 3: entity.name.function.js 4: punctuation.definition.string.end.js 5: string.quoted.js 6: punctuation.definition.string.begin.js 7: entity.name.function.js 8: punctuation.definition.string.end.js 9: string.unquoted.js 10: entity.name.function.js 11: punctuation.separator.key-value.js 12: storage.type.js 13: storage.type.function.js 14: keyword.generator.asterisk.js 15: entity.name.function.js push: - meta_scope: meta.function.json.js - match: (?<=\)) pop: true - include: flowtype-polymorph - include: function-declaration-parameters literal-jsx: - match: '(?<=\(|\{|\[|,|&&|\|\||\?|:|=|=>|\Wreturn|^return|\Wdefault|^)(?=\s*<[_$a-zA-Z])' push: - meta_content_scope: meta.jsx.js - match: (?<=/>|>) pop: true - include: jsx-tag-start literal-keyword-storage: - match: (?const|let|var)\b scope: storage.type.js literal-keywords: - include: literal-keyword-storage - match: (?await|yield))\b(?:\s*(\*))? captures: 1: keyword.control.flow.js 2: keyword.generator.asterisk.js - match: (?if|else)\b scope: keyword.control.conditional.js - match: (?catch|finally|throw|try)\b scope: keyword.control.trycatch.js - match: (?break|continue|do|goto|while|case|default)\b scope: keyword.control.loop.js - match: (?enum|module|public|package|private|interface|protected)\b scope: keyword.other.reserved.js - match: (? ((')((?>[^'\\]|\\.)*)('))| ((")((?>[^"\\]|\\.)*)("))| )\s*:) push: - match: ":" captures: 0: punctuation.separator.key-value.js pop: true - include: literal-string - match: '(? ((')((?>[^'\\]|\\.)*)('))| ((")((?>[^"\\]|\\.)*)("))| (([_$a-zA-Z][$\w]*|\d+)) ) (?=\s*(\((?>(?>[^()]+)|\g<-1>)*\))(?>\s|/\*.*\*/)*\{) captures: 1: storage.type.js 2: storage.type.js 3: keyword.generator.asterisk.js 4: string.quoted.js 5: punctuation.definition.string.begin.js 6: entity.name.function.js 7: punctuation.definition.string.end.js 8: string.quoted.js 9: punctuation.definition.string.begin.js 10: entity.name.function.js 11: punctuation.definition.string.end.js 12: string.unquoted.js 13: entity.name.function.js push: - meta_scope: meta.method.js - match: (?<=\)) pop: true - include: function-declaration-parameters - match: |- (?x) \b(?:(static)\s+)? (get|set)\s+ ([_$a-zA-Z][$\w]*|\d+)\s* (?=(\((?>(?>[^()]+)|\g<-1>)*\))(?>\s|/\*.*\*/)*\{) captures: 1: storage.type.js 2: storage.type.accessor.js 3: entity.name.accessor.js push: - meta_scope: meta.accessor.js - match: (?<=\)) pop: true - include: function-declaration-parameters literal-method-call: - match: |- (?x) (?:(?<=\.)|\b) ([A-Z][$\w]*)\s*(\.) ([_$a-zA-Z][$\w]*)\s* (\(\s*\)) scope: meta.function-call.static.without-arguments.js captures: 1: variable.other.class.js 2: keyword.operator.accessor.js 3: variable.function.js 4: meta.group.braces.round.function.arguments.js - match: |- (?x) (?:(?<=\.)|\b) ([A-Z][$\w]*)\s*(\.) ([_$a-zA-Z][$\w]*)\s* (?=\() scope: meta.function-call.static.with-arguments.js captures: 1: variable.other.class.js 2: keyword.operator.accessor.js 3: variable.function.js - match: |- (?x) (?<=\.) ([_$a-zA-Z][$\w]*)\s* (\(\s*\)) scope: meta.function-call.method.without-arguments.js captures: 1: variable.function.js 2: meta.group.braces.round.function.arguments.js - match: |- (?x) (?<=\.) ([_$a-zA-Z][$\w]*)\s* (?=\() scope: meta.function-call.method.with-arguments.js captures: 1: variable.function.js literal-module: - match: (?import|export|default|from|as)\b scope: keyword.operator.module.js literal-number: - match: '(?i)(?:\B[-+]|\b)0x[0-9a-f]*\.(\B|\b[0-9]+)' scope: invalid.illegal.numeric.hex.js - match: '(?:\B[-+]|\b)0[0-9]+\.(\B|\b[0-9]+)' scope: invalid.illegal.numeric.octal.js - match: |- (?xi) (?:\B[-+])? (?: \b0b[0-1]*| # binary \b0o[0-7]*| # octal \b0x[0-9a-f]*| # hex ( \B\.[0-9]+| # e.g. .999 \b[0-9]+(\.[0-9]*)? # e.g. 999.999, 999. or 999 )(e[-+]?[0-9]+)? # e.g. e+123, E-123 ) scope: constant.numeric.js - match: '(?:\B[-+]|\b)(Infinity)\b' scope: constant.language.infinity.js literal-operators: - match: (?delete|instanceof|in|new|of|typeof|void|with)\b scope: keyword.operator.js - match: |- (?x) !(?!=)| # logical-not right-to-left right && | # logical-and left-to-right both \|\| # logical-or left-to-right both scope: keyword.operator.logical.js - match: |- (?x) =(?!=) # assignment right-to-left both scope: keyword.operator.assignment.js - match: |- (?x) %= | # assignment right-to-left both &= | # assignment right-to-left both \*= | # assignment right-to-left both \+= | # assignment right-to-left both -= | # assignment right-to-left both /= | # assignment right-to-left both \^= | # assignment right-to-left both \|= | # assignment right-to-left both <<= | # assignment right-to-left both >>= | # assignment right-to-left both >>>= # assignment right-to-left both scope: keyword.operator.assignment.augmented.js - match: |- (?x) ~ | # bitwise-not right-to-left right << | # bitwise-shift left-to-right both >>> | # bitwise-shift left-to-right both >> | # bitwise-shift left-to-right both & | # bitwise-and left-to-right both \^ | # bitwise-xor left-to-right both \| # bitwise-or left-to-right both scope: keyword.operator.bitwise.js - match: |- (?x) <= | # relational left-to-right both >= | # relational left-to-right both < | # relational left-to-right both > # relational left-to-right both scope: keyword.operator.relational.js - match: |- (?x) === | # equality left-to-right both !== | # equality left-to-right both == | # equality left-to-right both != # equality left-to-right both scope: keyword.operator.comparison.js - match: |- (?x) -- | # decrement n/a right-or-left \+\+ | # increment n/a right-or-left / | # division left-to-right both % | # modulus left-to-right both \* | # multiplication left-to-right both \+ | # addition left-to-right both - # subtraction left-to-right both scope: keyword.operator.arithmetic.js - match: "[?:]" scope: keyword.operator.ternary.js - match: (?|<=|>=|==|!=|===|!==|\+|-|\*|%|\+\+|--|<<|>>|>>>|&|\||\^|!|~|&&|\|\||\?|:|=|\+=|-=|\*=|%=|<<=|>>=|>>>=|&=|\|=|\^=|/|/=| \Wnew|\Wdelete|\Wvoid|\Wtypeof|\Winstanceof|\Win|\Wdo|\Wreturn|\Wcase|\Wthrow|\Wyield| ^new|^delete|^void|^typeof|^instanceof|^in|^do|^return|^case|^throw|^yield|^ )\s* (/) (?!/|\*|$) captures: 1: punctuation.definition.string.begin.js push: - meta_scope: string.regexp.js - match: "(/)([gimy]*)" captures: 1: punctuation.definition.string.end.js 2: keyword.other.js pop: true - include: scope:source.regexp.js literal-string: - match: '(["''])' captures: 0: punctuation.definition.string.begin.js push: - meta_scope: string.quoted.js - match: (\1)|(\n) captures: 1: punctuation.definition.string.end.js 2: invalid.illegal.newline.js pop: true - include: string-content literal-switch: - match: (?]{7})\s(.+)$' captures: 1: invalid.illegal.conflict-marker.other-commit.js 2: invalid.illegal.string.js round-brackets: - match: \( captures: 0: meta.brace.round.begin.js push: - meta_scope: meta.group.braces.round.js - match: \) captures: 0: meta.brace.round.end.js pop: true - include: expression square-brackets: - match: '\[' captures: 0: meta.brace.square.begin.js push: - meta_scope: meta.group.braces.square.js - match: '\]' captures: 0: meta.brace.square.end.js pop: true - include: expression string-content: - match: \\\s*\n scope: constant.character.escape.newline.js - match: '\\([1-7][0-7]{0,2}|[0-7]{2,3}|[bfnrtv0''"\\]|x\h{2}|u\{\h+\}|u\h{4})' scope: constant.character.escape.js styled-components: - match: (?(?>[^()]+)|\g<-1>)*\))\s*`)' captures: 1: meta.function-call.with-arguments.js variable.function.js push: - meta_scope: meta.styled-components.js - match: (?<=`) captures: 1: meta.function-call.with-arguments.js variable.function.js pop: true - match: \( captures: 0: punctuation.definition.group.begin.js push: - meta_scope: meta.function-call.with-arguments.js meta.group.js - match: \) captures: 0: punctuation.definition.group.end.js pop: true - include: expression - match: "`" captures: 0: punctuation.definition.string.template.begin.js push: - meta_content_scope: source.css.embedded.js - match: "`" captures: 0: punctuation.definition.string.template.end.js pop: true - include: scope:source.js.css support-class: - match: (?Eval|Range|Reference|Syntax|Type|URI)?Error)\b scope: support.class.error.js - match: \b(?>Buffer)\b scope: support.class.node.js support-other: - match: (?document|window)\b scope: support.type.object.dom.js - match: (?global|GLOBAL|root|__dirname|__filename)\b scope: support.type.object.node.js - 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 ================================================ FILE: assets/syntaxes/02_Extra/Lean.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html name: Lean 4 file_extensions: - lean scope: source.lean4 contexts: main: - include: comments - match: \b(Prop|Type|Sort)\b scope: storage.type.lean4 - match: '\battribute\b\s*\[[^\]]*\]' scope: storage.modifier.lean4 - match: '@\[[^\]]*\]' scope: storage.modifier.lean4 - match: \b(?])' pop: true - include: comments - include: definitionName - match: ',' - match: \b(?\*? |<[~-]{1,2}!? |\(\s* (?= instanceof[\s)]|and[\s)]|or[\s)]|is[\s)]|isnt[\s)]|in[\s)]|import[\s)]|import\ all[\s)] |\.|[-+/*%^&<>=|][\b\s)\w$]|\*\*|\%\%) | (?<=[\s(]instanceof|[\s(]and|[\s(]or|[\s(]is|[\s(]isnt|[\s(]in|[\s(]import|[\s(]import\ all|[\s(]do|\.|\*\*|\%\%|[\b\s(\w$][-+/*%^&<>=|]) \s*\) scope: storage.type.function.livescript - match: \/\* captures: 0: punctuation.definition.comment.livescript push: - meta_scope: comment.block.livescript - match: \*\/ captures: 0: punctuation.definition.comment.livescript pop: true - match: '@\w*' scope: storage.type.annotation.livescriptscript - match: '(#)(?!\{).*$\n?' scope: comment.line.number-sign.livescript captures: 1: punctuation.definition.comment.livescript - match: '((?:!|~|!~|~!)?function\*?)\s+([$\w\-]*[$\w]+)' captures: 1: storage.type.function.livescript 2: entity.name.function.livescript - match: (new)\s+(\w+(?:\.\w*)*) captures: 1: keyword.operator.new.livescript 2: entity.name.type.instance.livescript - match: \b(package|private|protected|public|interface|enum|static)(?!-)\b scope: keyword.illegal.livescript - match: "'''" captures: 0: punctuation.definition.string.begin.livescript push: - meta_scope: string.quoted.heredoc.livescript - match: "'''" captures: 0: punctuation.definition.string.end.livescript pop: true - match: '"""' captures: 0: punctuation.definition.string.begin.livescript push: - meta_scope: string.quoted.double.heredoc.livescript - match: '"""' captures: 0: punctuation.definition.string.end.livescript pop: true - match: \\. scope: constant.character.escape.livescript - include: interpolated_livescript - match: "``" captures: 0: punctuation.definition.string.begin.livescript push: - meta_scope: string.quoted.script.livescript - match: "``" captures: 0: punctuation.definition.string.end.livescript pop: true - match: '\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)' scope: constant.character.escape.livescript - match: '<\[' push: - meta_scope: string.array-literal.livescript - match: '\]>' pop: true - match: '/{2}(?![\s=/*+{}?]).*?[^\\]/[igmy]{0,4}(?![a-zA-Z0-9])/{2}' scope: string.regexp.livescript - match: '/{2}\n' push: - meta_scope: string.regexp.livescript - match: "/{2}[imgy]{0,4}" pop: true - include: embedded_spaced_comment - include: interpolated_livescript - match: "/{2}" push: - meta_scope: string.regexp.livescript - match: "/{2}[imgy]{0,4}" pop: true - match: '\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)' scope: constant.character.escape.livescript - include: interpolated_livescript - match: '/(?![\s=/*+{}?]).*?[^\\]/[igmy]{0,4}(?![a-zA-Z0-9])' scope: string.regexp.livescript - match: |- (?x) \b(? scope: keyword.operator.livescript - match: "=>" scope: keyword.control.livescript - match: |- (?x) \b(?)|\+\+|\+| ~(?!~?>)|==|=|!=|<=|>=|<<=|>>=| >>>=|<>|<(?!\[)|(?|(?)|&&|\.\.(\.)?|\s\.\s|\?|\|\||\:|\*=|(?)))\s*(?!(\s*!?\s*\(.*\))?\s*(!?[~-]{1,2}>\*?))' captures: 1: variable.assignment.livescript 3: punctuation.separator.key-value, keyword.operator.livescript 4: keyword.operator.livescript - match: '(?<=\s|^)([\[\{])(?=.*?[\]\}]\s+[:=])' captures: 0: keyword.operator.livescript push: - meta_scope: meta.variable.assignment.destructured.livescript - match: '([\]\}]\s*[:=])' captures: 0: keyword.operator.livescript pop: true - include: variable_name - include: instance_variable - include: single_quoted_string - include: double_quoted_string - include: numeric - match: |- (?x) (\s*) (?=[a-zA-Z\$_]) ([a-zA-Z\$_]([\w$.:-])*)\s* (?=[:=](\s*!?\s*\(.*\))?\s*(!?[~-]{1,2}>\*?)) scope: meta.function.livescript captures: 2: entity.name.function.livescript 3: entity.name.function.livescript 4: variable.parameter.function.livescript 5: storage.type.function.livescript - match: \b(?][ =)]|[`}%*)]|/(?!.*?/)|&&|[.][^.]|=>|\/ +|\||\|\||\-\-|\+\+|\|>|<|\||$|\n|\#|/\*))' captures: 1: meta.function-call.livescript 2: keyword.operator.livescript - match: \| _ scope: keyword.control.livescript - match: '\|(?![.])' scope: keyword.control.livescript - match: \| scope: keyword.operator.livescript - match: ((?<=console\.)(debug|warn|info|log|error|time(End|-end)|assert))\b scope: support.function.console.livescript - match: |- (?x)\b( decodeURI(Component)?|encodeURI(Component)?|eval|parse(Float|Int)|require )\b scope: support.function.livescript - match: |- (?x)(?' scope: punctuation.definition.generic.end.man - match: '$|(?=[],]|{{command_line_option}})' pop: true c-code: - match: '^(?=\s+(?:#include\b|#define\b|/\*|struct\s+(\w+\s*)?\{))' embed: scope:source.c #embed_scope: source.c.embedded.man #escape: ^(?!#|\1|\s*(?:$|/\*|#include\b|#define\b)) escape: ^(?=\s*(?:\(.*\.\)\s*$|[A-Z](?![A-Z]))) synopsis: - include: c-code - match: \[ scope: punctuation.section.brackets.begin.man push: command-line-option-or-pipe - include: options command-line-option-or-pipe: - match: (\|)\s* captures: 1: keyword.operator.logical.man #- match: (?={{command_line_option}}) - match: \w+-\w+ - match: (?=-) push: - match: (?=\s*\|) pop: true - include: expect-command-line-option - match: \] scope: punctuation.section.brackets.end.man pop: true - match: \[ scope: punctuation.section.brackets.begin.man push: command-line-option-or-pipe commands-start: - match: (?=^[ ]{7}.*(?:[ ]<|[|])) push: commands commands: - match: '^[ ]{7}([a-z_\-]+)(?=[ ]|$)' captures: 1: entity.name.command.man push: expect-parameter - match: '^[ ]{7}(?=[\[<]|\w+[|\]])' push: expect-parameter environment-variables: - match: '^[ ]{7}([A-Z_]+)\b' captures: 1: support.constant.environment-variable.man ================================================ FILE: assets/syntaxes/02_Extra/MemInfo.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: MemInfo file_extensions: - meminfo scope: source.meminfo contexts: main: - match: '^([^:]+)\w*:\w*(.*)$' captures: 1: keyword.other.meminfo-key 2: string.other.meminfo-value ================================================ FILE: assets/syntaxes/02_Extra/Nim.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Nim file_extensions: - nim - nims - nimble scope: source.nim contexts: main: - match: '(\#\[\s*(TODO|todo)?)' comment: A multiline comment. captures: 1: punctuation.definition.multi-comment.nim 2: invalid.illegal.TODO.nim push: - meta_scope: comment.line.number-sign.multi-comment.nim - match: '(.*]\#)' captures: 1: punctuation.definition.multi-comment.nim 2: invalid.illegal.TODO.nim pop: true - match: (##\s*(TODO|todo)?).+$\n? comment: A documentation comment. scope: comment.line.number-sign.doc-comment.nim captures: 1: punctuation.definition.doc-comment.nim 2: invalid.illegal.TODO.nim - match: (##\s*)$\n? comment: An empty documentation comment. scope: comment.line.number-sign.doc-comment.empty.nim captures: 1: punctuation.definition.doc-comment.empty.nim - match: (#\s*(TODO|todo)?).*$\n? comment: A regular comment scope: comment.line.number-sign.comment.nim captures: 1: punctuation.definition.comment.nim 2: invalid.illegal.TODO.nim - match: '\{\.' comment: Pragmas push: - meta_scope: pragma - match: '\.?\}' pop: true - match: \" push: - meta_scope: string.something.nim - match: \" pop: true - match: '([\w\x{80}-\x{10FFFF}]+)' scope: entity.other.attribute-name.pragma.nim - match: discard \"\"\" comment: A discarded triple string literal comment push: - meta_scope: comment.line.discarded.nim - match: \"\"\" pop: true - match: '(?|@|\$|~|&|%|!|\?|\^|\.|:|\\)+) comment: Generic operators for expressions. scope: keyword.operator.nim - match: (for)\s+ comment: in keyword in a 'for' loop captures: 1: keyword.control.nim push: - meta_scope: meta.forloop.nim - match: (?=:) captures: 1: keyword.control.nim pop: true - match: '\ [\w\x{80}-\x{10FFFF},]+\s+(in)\s+' captures: 1: keyword.control.nim - include: scope:source.nim - match: '((import)\s+[\.|\w|\/]+,?)' comment: Import syntax captures: 2: keyword.control.nim - match: '(from)\s+[\/\w]+\s+(?=import)' captures: 1: keyword.control.nim - match: (var|let)\s*\( comment: Destructure syntax captures: 1: keyword.other.nim push: - match: \) captures: 1: keyword.other.nim pop: true - match: '((?\=|\>|&&|\|\||-\>|//|\?|\+\+|-|\*|/(?=([^*]|$))|\+)' 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: '(?" 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: subexpression - include: function - include: attribute - include: UsingDirective - include: type - include: hashtable - include: doubleQuotedString - include: scriptblock - include: doubleQuotedStringEscapes - match: '[''\x{2018}-\x{201B}]' captures: 0: punctuation.definition.string.begin.powershell push: - meta_scope: string.quoted.single.powershell - match: '[''\x{2018}-\x{201B}]{2}' scope: constant.character.escape.powershell - match: '[''\x{2018}-\x{201B}]' captures: 0: punctuation.definition.string.end.powershell pop: true - match: '(@["\x{201C}-\x{201E}])\s*$' captures: 1: punctuation.definition.string.begin.powershell push: - meta_scope: string.quoted.double.heredoc.powershell - match: '^["\x{201C}-\x{201E}]@' captures: 0: punctuation.definition.string.end.powershell pop: true - include: variableNoProperty - include: doubleQuotedStringEscapes - include: interpolation - match: '(@[''\x{2018}-\x{201B}])\s*$' captures: 1: punctuation.definition.string.begin.powershell push: - meta_scope: string.quoted.single.heredoc.powershell - match: '^[''\x{2018}-\x{201B}]@' captures: 0: punctuation.definition.string.end.powershell pop: true - 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: keyword.other.substatement.powershell 2: punctuation.definition.subexpression.powershell 3: 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: (?{1,5})}' scope: constant.character.escape.powershell - match: '`u(?:\{[0-9a-fA-F]{,6}.)?' scope: invalid.character.escape.powershell 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)\b)((?:\.(?:\p{L}|\d|_)+)*\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.variable.automatic.powershell 1: punctuation.definition.variable.powershell 3: variable.other.member.powershell - match: '(\$)(?i:(ConfirmPreference|DebugPreference|ErrorActionPreference|ErrorView|FormatEnumerationLimit|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|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|InformationPreference|LogCommandHealthEvent|LogCommandLifecycleEvent|LogEngineHealthEvent|LogEngineLifecycleEvent|LogProviderHealthEvent|LogProviderLifecycleEvent|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount|MaximumHistoryCount|MaximumVariableCount|OFS|OutputEncoding|PSCulture|PSDebugContext|PSDefaultParameterValues|PSEmailServer|PSItem|PSModuleAutoLoadingPreference|PSModuleAutoloadingPreference|PSSenderInfo|PSSessionApplicationName|PSSessionConfigurationName|PSSessionOption|ProgressPreference|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 ================================================ FILE: assets/syntaxes/02_Extra/QML.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: QML file_extensions: - qml - qmlproject scope: source.qml contexts: main: - match: /\*(?!/) comment: Block comment. push: - meta_scope: comment.block.documentation.qml - match: \*/ pop: true - match: //.*$ comment: Line comment. scope: comment.line.double-slash.qml - match: \b(import)\s+ comment: import statement. captures: 1: keyword.other.import.qml push: - meta_scope: meta.import.qml - match: $ pop: true - match: '([\w\d\.]+)\s+(\d+\.\d+)(?:\s+(as)\s+([A-Z][\w\d]*))?' comment: "import Namespace VersionMajor.VersionMinor [as SingletonTypeIdentifier]" scope: meta.import.namespace.qml captures: 1: entity.name.class.qml 2: constant.numeric.qml 3: keyword.other.import.qml 4: entity.name.class.qml - match: '(\"[^\"]+\")(?:\s+(as)\s+([A-Z][\w\d]*))?' comment: "import [as Script]" scope: meta.import.dirjs.qml captures: 1: string.quoted.double.qml 2: keyword.other.import.qml 3: entity.name.class.qml - match: '\b[A-Z]\w*\b' comment: Capitalized word (class or enum). scope: support.class.qml - match: '(((^|\{)\s*)|\b)on[A-Z]\w*\b' comment: onSomething - handler. scope: support.class.qml - match: '(?:^|\{)\s*(id)\s*\:\s*([^;\s]+)\b' comment: "id: " scope: meta.id.qml captures: 1: keyword.other.qml 2: storage.modifier.qml - match: '^\s*(?:(default|readonly)\s+)?(property)\s+(?:(alias)|([\w\<\>]+))\s+(\w+)' comment: property definition. scope: meta.propertydef.qml captures: 1: keyword.other.qml 2: keyword.other.qml 3: keyword.other.qml 4: storage.type.qml 5: entity.other.attribute-name.qml - match: \b(signal)\s+(\w+)\s* comment: "signal [([ [, ...]])]" captures: 1: keyword.other.qml 2: support.function.qml push: - meta_scope: meta.signal.qml - match: ;|(?=/)|$ pop: true - match: (\w+)\s+(\w+) scope: meta.signal.parameters.qml captures: 1: storage.type.qml 2: variable.parameter.qml - match: (?:\b|\s+)(?:(true|false|null|undefined)|(var|void)|(on|as|enum|connect|break|case|catch|continue|debugger|default|delete|do|else|finally|for|if|in|instanceof|new|return|switch|this|throw|try|typeof|while|with))\b comment: js keywords. scope: meta.keyword.qml captures: 1: constant.language.qml 2: storage.type.qml 3: keyword.control.qml - match: '\b(function)\s+([\w_]+)\s*(?=\()' comment: function definition. scope: meta.function.qml captures: 1: storage.type.qml 2: entity.name.function.untitled - match: '\b[\w_]+\s*(?=\()' comment: function call. scope: support.function.qml - match: '(?:^|\{|;)\s*[a-z][\w\.]*\s*(?=\:)' comment: "property (property: )." scope: entity.other.attribute-name.qml - match: (?<=\.)\b\w* comment: property of the variable (name.property). scope: entity.other.attribute-name.qml - match: '\b([a-z_]\w*)\b' comment: All non colored words are assumed to be variables. scope: variable.parameter - include: scope:source.js ================================================ FILE: assets/syntaxes/02_Extra/Racket.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Racket file_extensions: - rkt scope: source.racket contexts: main: - match: '[^\\](\"[^\"]*\")' captures: 1: string.quoted.double.source.racket - match: '\((define)\s+([a-zA-Z0-9_\-?\+^]+)\s*' scope: meta.variable.source.racket captures: 1: keyword.source.racket 2: entity.name.variable.source.racket - match: '\((define)\s+\(([a-zA-Z0-9_\-?\+^]+)\s*' scope: meta.function.source.racket captures: 1: keyword.source.racket 2: entity.name.function - match: '\((struct)\s+([a-zA-Z0-9_\-?\+^]+)\s+' scope: meta.struct.source.racket captures: 1: keyword.source.racket 2: entity.name.type - match: '[\s\(](if|lambda|cond|define|type-case|let|letrec|let!|\#lang|require|test|else|first|rest|define-type|define-type-alias|define-struct|not|local|error|lang)[\s\)]' scope: meta.keywords.source.racket captures: 1: keyword.source.racket - match: '[\s\(](true|false|empty|null)[\s\)]' captures: 1: constant.language.source.racket - match: '[\s\(\[\{](#t|#true|#f|#false)[\s\)\]\}]' captures: 1: constant.language.source.racket - match: '(#\\[a-zA-Z0-9_\-?\+\.\!\"]+)' captures: 1: constant.language.source.racket - match: '\b(0|([1-9][0-9_]*))\b' scope: constant.numeric.integer.source.racket - match: ; push: - meta_scope: comment.line.documentation.source.racket - match: $\n pop: true - match: '#\|' push: - meta_scope: comment.block.source.racket - match: '\|#' pop: true ================================================ FILE: assets/syntaxes/02_Extra/Rego.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Rego file_extensions: - rego scope: source.rego contexts: main: - include: comment - include: keyword - include: operator - include: head - include: term comment: - match: (#).*$\n? scope: comment.line.number-sign.rego captures: 1: punctuation.definition.comment.rego call: - match: '([a-zA-Z_][a-zA-Z0-9_]*)\(' scope: meta.function-call.rego captures: 1: support.function.any-method.rego constant: - match: \b(?:true|false|null)\b scope: constant.language.rego head: - match: "^([[:alpha:]_][[:alnum:]_]*)" captures: 1: entity.name.function.declaration push: - meta_scope: meta.function.rego - match: '(=|{|\n)' pop: true - include: term keyword: - match: (^|\s+)(?:(default|not|package|import|as|with|else|some))\s+ scope: keyword.other.rego number: - match: |- (?x: # turn on extended mode -? # an optional minus (?: 0 # a zero | # ...or... [1-9] # a 1-9 character \d* # followed by zero or more digits ) (?: (?: \. # a period \d+ # followed by one or more digits )? (?: [eE] # an e character [+-]? # followed by an option +/- \d+ # followed by one or more digits )? # make exponent optional )? # make decimal portion optional ) scope: constant.numeric.rego operator: - match: \=|\!\=|>|<|<\=|>\=|\+|-|\*|%|/|\||&|:\= scope: keyword.operator.comparison.rego string: - match: '"' captures: 0: punctuation.definition.string.begin.rego push: - meta_scope: string.quoted.double.rego - match: '"' captures: 0: punctuation.definition.string.end.rego pop: true - match: |- (?x: # turn on extended mode \\ # a literal backslash (?: # ...followed by... ["\\/bfnrt] # one of these characters | # ...or... u # a u [0-9a-fA-F]{4} # and four hex digits ) ) scope: constant.character.escape.rego - match: \\. scope: invalid.illegal.unrecognized-string-escape.rego term: - include: constant - include: string - include: number - include: call - include: variable variable: - match: '\b[[:alpha:]_][[:alnum:]_]*\b' scope: meta.identifier.rego ================================================ FILE: assets/syntaxes/02_Extra/Requirementstxt.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html name: Requirements.txt scope: source.requirements-txt # https://pip.pypa.io/en/stable/reference/requirements-file-format/ # https://github.com/raimon49/requirements.txt.vim/blob/f246bd10155fbc3b1a9e2fff6c95b21521b09116/ftdetect/requirements.vim file_extensions: - requirements.txt - requirements.in - pip # https://github.com/sublimehq/Packages/pull/2760/files first_line_match: |- (?xi: ^ \#! .* \bpip # shebang | ^ \s* \# .*? -\*- .*? \bpip-requirements\b .*? -\*- # editorconfig | ^ \s* \# (vim?|ex): .*? \brequirements\b # modeline ) # pip install -r # pip-compile variables: operator: '===?|<=?|>=?|~=|!=' contexts: main: - match: '(?i)\d+[\da-z\-_\.\*]*' scope: constant.other.version-control.requirements-txt - match: '(?i)^\[?--?[\da-z\-]*\]?' scope: entity.name.function.option.requirements-txt - match: '{{operator}}' scope: keyword.operator.logical.requirements-txt - match: '(\[)' captures: 1: punctuation.section.braces.begin.requirements-txt push: - meta_scope: variable.function.extra.requirements-txt - match: ',' scope: punctuation.separator.requirements-txt - match: '(\])' captures: 1: punctuation.section.braces.end.requirements-txt pop: true - match: '(git\+?|hg\+|svn\+|bzr\+).*://.\S+' scope: markup.underline.link.versioncontrols.requirements-txt - match: '(@\s)?(https?|ftp|gopher)://?[^\s/$.?#].\S*' scope: markup.underline.link.url.requirements-txt captures: 1: punctuation.definition.keyword.requirements-txt - match: '(?i)^[a-z\d_\-\.]*[a-z\d]' scope: variable.parameter.package-name.requirements-txt - match: '(;)' captures: 1: punctuation.definition.annotation.requirements-txt push: - meta_scope: meta.annotation.requirements-txt # https://pip.pypa.io/en/stable/reference/inspect-report/#example - match: |- (?x: implementation_name | implementation_version | os_name | platform_machine | platform_release | platform_system | platform_version | python_full_version | platform_python_implementation | python_version | sys_platform ) scope: variable.language.requirements-txt - match: '{{operator}}' scope: keyword.operator.logical.requirements-txt # https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples - match: '(")' captures: 1: punctuation.definition.string.begin.double.requirements-txt push: - meta_scope: string.quoted.double.requirements-txt - match: '\\"' scope: constant.character.escape.double.requirements-txt - match: '(")' captures: 1: punctuation.definition.string.end.double.requirements-txt pop: true - match: "(')" captures: 1: punctuation.definition.string.begin.single.requirements-txt push: - meta_scope: string.quoted.single.requirements-txt - match: '\\''' scope: constant.character.escape.single.requirements-txt - match: "(')" captures: 1: punctuation.definition.string.end.single.requirements-txt pop: true - match: '(.(?=#)|$)' pop: true - match: '(\$)(\{)' captures: 1: punctuation.definition.keyword.requirements-txt 2: punctuation.definition.begin.parameter.requirements-txt push: - meta_scope: variable.parameter.requirements-txt - match: '(\})' captures: 1: punctuation.definition.end.parameter.requirements-txt pop: true - match: '(#)' captures: 1: punctuation.definition.comment.requirements-txt push: - meta_scope: comment.line.requirements-txt - match: '(-*-) coding: .* (-*-)' captures: 1: punctuation.definition.begin.pep263.requirements-txt 2: punctuation.definition.end.pep263.requirements-txt - match: '$' pop: true ================================================ FILE: assets/syntaxes/02_Extra/Resolv.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: resolv file_extensions: - resolv.conf scope: source.resolv contexts: main: - scope: comment.line.number-sign match: \#.* comment: comment - comment: configuration match: "(nameserver|domain|search|sortlist|options)" scope: keyword.control - comment: options match: "(debug|ndots|timeout|attempts|rotate|no-check-names|inet6|ip6-bytestring|ip6-dotint|no-ip6-dotint|edns0|single-request|single-request-reopen|no-tld-query|use-vc|no-reload)" scope: entity.name ================================================ FILE: assets/syntaxes/02_Extra/Robot.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Robot Framework file_extensions: - robot - resource scope: source.robot contexts: main: - match: '\$\{(\d+|\d+\.\d*|0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+)\}' comment: "Robot Framework numbers, like ${1} or ${12.3}" scope: constant.numeric.robot - match: '(?i)(%\{[\w|\s]+\})' comment: "Robot Framework environment variable, like %{USER}" scope: variable.parameter.robot - match: '((?|::|\[\]|->|:>)' comment: Character scope: constant.character.sml ================================================ FILE: assets/syntaxes/02_Extra/Slim.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html name: Ruby Slim file_extensions: - slim - skim scope: text.slim contexts: main: - match: ^(\s*)(ruby):$ captures: 2: constant.language.name.ruby.filter.slim push: - meta_scope: text.ruby.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.ruby - match: ^(\s*)(javascript):$ captures: 2: constant.language.name.javascript.filter.slim push: - meta_scope: source.js.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.js - match: ^(---)\s*\n captures: 1: storage.frontmatter.slim push: - meta_scope: source.yaml.meta.slim - match: ^(---)\s*\n captures: 1: storage.frontmatter.slim pop: true - include: scope:source.yaml - match: ^(\s*)(coffee):$ captures: 2: constant.language.name.coffeescript.filter.slim push: - meta_scope: text.coffeescript.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.coffee - match: ^(\s*)(markdown):$ captures: 2: constant.language.name.markdown.filter.slim push: - meta_scope: text.markdown.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:text.html.markdown - match: ^(\s*)(css):$ captures: 2: constant.language.name.css.filter.slim push: - meta_scope: text.css.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.css - match: ^(\s*)(sass):$ captures: 2: constant.language.name.sass.filter.slim push: - meta_scope: text.sass.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.sass - match: ^(\s*)(scss):$ captures: 2: constant.language.name.scss.filter.slim push: - meta_scope: text.scss.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.scss - match: ^(\s*)(less):$ captures: 2: constant.language.name.less.filter.slim push: - meta_scope: text.less.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.less - match: ^(\s*)(erb):$ captures: 2: constant.language.name.erb.filter.slim push: - meta_scope: text.erb.filter.slim - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:source.erb - match: ^(! )($|\s.*) scope: meta.prolog.slim captures: 1: punctuation.definition.prolog.slim - match: ^(\s*)(/)\s*.*$ captures: 2: comment.line.slash.slim push: - meta_scope: comment.block.slim - match: ^(?!(\1\s)|\s*$) pop: true - match: ^\s*(?=-) push: - match: $ pop: true - include: rubyline - match: (?==+|~) push: - match: $ pop: true - include: rubyline - include: tag-attribute - include: embedded-ruby - match: ^(\s*)(\||')\s* comment: Verbatim text (can include HTML tags and copied lines) push: - match: ^(?!(\1\s)|\s*$) pop: true - include: scope:text.html.basic - include: embedded-ruby - match: '^\s*(\.|#|[-a-zA-Z0-9]+)([\w-]+)?' comment: '1 - dot OR hash OR any combination of word, number; 2 - OPTIONAL any combination of word, number, dash or underscore (following a . or' captures: 1: entity.name.tag.slim 2: entity.other.attribute-name.event.slim push: - meta_scope: meta.tag - match: '$|(?!\.|#|:|-|~|/|\}|\]|\*|\s?[\*\{])' captures: 1: entity.name.tag.slim 2: entity.other.attribute-name.event.slim pop: true - match: '(:[\w\d]+)+' comment: XML push: - meta_scope: entity.name.tag.slim - match: $|\s pop: true - match: '(:\s)(\.|#|[a-zA-Z0-9]+)([\w-]+)?' comment: Inline HTML / 1 - colon; 2 - dot OR hash OR any combination of word, number; 3 - OPTIONAL any combination of word, number, dash or underscore (following a . or captures: 1: punctuation.definition.tag.end.slim 2: entity.name.tag.slim 3: entity.other.attribute-name.event.slim push: - match: '$|(?!\.|#|=|-|~|/|\}|\]|\*|\s?[\*\{])' captures: 1: punctuation.definition.tag.end.slim 2: entity.name.tag.slim 3: entity.other.attribute-name.event.slim pop: true - include: root-class-id-tag - include: tag-attribute - match: '(\*\{)(?=.*\}|.*\|\s*$)' comment: Splat attributes captures: 1: punctuation.section.embedded.ruby push: - meta_scope: source.ruby.embedded.slim - match: '(\})|$|^(?!.*\|\s*$)' captures: 1: punctuation.section.embedded.ruby pop: true - include: embedded-ruby - include: root-class-id-tag - include: rubyline - match: / scope: punctuation.terminator.tag.slim - match: ^\s*(\\.) captures: 1: meta.escape.slim - match: ^\s*(?=\||') push: - match: $ pop: true - include: embedded-ruby - include: scope:text.html.basic - match: '(?=<[\w\d\:]+)' comment: Inline and root-level HTML tags push: - match: $|\/\> pop: true - include: scope:text.html.basic continuation: - match: '([\\,])\s*\n' captures: 1: punctuation.separator.continuation.slim delimited-ruby-a: - match: '=\(' push: - meta_scope: source.ruby.embedded.slim - match: \)(?=( \w|$)) pop: true - include: scope:source.ruby.rails delimited-ruby-b: - match: '=\[' push: - meta_scope: source.ruby.embedded.slim - match: '\](?=( \w|$))' pop: true - include: scope:source.ruby.rails delimited-ruby-c: - match: '=\{' push: - meta_scope: source.ruby.embedded.slim - match: '\}(?=( \w|$))' pop: true - include: scope:source.ruby.rails embedded-ruby: - match: '(?|><|<'|'<|<|>)?|- comment: Hack to thwart Sublime's Ruby highlighter. It thinks do without a variable continues the next line (this can be muted with a / at the end of the line). For things like yields, do is unnecessary without an argument, so this hack will suffice push: - meta_scope: meta.line.ruby.slim - meta_content_scope: source.ruby.embedded.slim - match: (do\s*\n$)|(?\[*\/] # symbols but they are valid for selector ) | ( \+\s*[\w$-]+\b\s* # are an identifier starting with $ (?!\() # and they can't have anything besides ) | ( # for animtions \d+(\.\d+)?%|(from|to)\b ) | ( # Placeholder selectors \$[\w$-]+\b\s* # are an identifier starting with $ (?=$|\{) # and they can't have anything besides ) | ( # CSS class \.[a-zA-Z0-9_-]+ ) | ( # CSS id \#[a-zA-Z0-9_-]+ ) | ( # Reference to parent ([\w\d_-]+)? # matching any word right before & (&) # & itself, escaped because of plist ([\w\d_-]+)? # matching any word right after & ) ) push: - meta_scope: meta.selector.stylus - match: |- |$|(?=\{\s*\}.*$)|(?=\{.*?[:;])|(?=\{)(?!.+\}.*$) pop: true - include: comma - match: \d+(\.\d+)?%|from|to scope: entity.other.animation-keyframe.stylus - include: selector-components - match: . scope: entity.other.attribute-name.stylus - match: |- (?x) # multi-line regex definition mode (?<=^|;|{)\s* # starts after beginning of line, '{' or ';'' (?= # lookahead for ( [a-zA-Z0-9_-] # then a letter | # or (\{(.*?)\}) # interpolation | # or (/\*.*?\*/) # comment )+ \s*[:\s]\s* # value is separated by colon or space (?!(\s*\{)) # if there are only spaces afterwards (?! [^}]*? # checking for an unclosed curly braces on this \{ # line because if one exists it means that [^}]* # this is a selector and not a property ($|\}) ) ) push: - match: '(?=\}|;)|(?|(?:=|:|\?|\+|-|\*|\/|%|<|>)?=|!=)|\b(?:in|is(?:nt)?|(?]" scope: keyword.operator.selector.stylus - match: |- (?x) # multi-line regex definition mode \b( altGlyph|altGlyphDef|altGlyphItem|animate|animateColor| animateMotion|animateTransform|circle|clipPath|color-profile| defs|desc|ellipse|feBlend|feColorMatrix| feComponentTransfer|feComposite|feConvolveMatrix| feDiffuseLighting|feDisplacementMap|feDistantLight|feFlood| feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge| feMergeNode|feMorphology|feOffset|fePointLight| feSpecularLighting|feSpotLight|feTile|feTurbulence|filter| font-face|font-face-format|font-face-name|font-face-src| font-face-uri|foreignObject|g|glyph|glyphRef|hkern|image|line| linearGradient|marker|mask|metadata|missing-glyph|mpath|path| pattern|polygon|polyline|radialGradient|rect|set|stop|svg| switch|symbol|text|textPath|tref|tspan|use|view|vkern| a|abbr|acronym|address|applet|area|article|aside|audio|b|base| basefont|bdi|bdo|bgsound|big|blink|blockquote|body|br|button| canvas|caption|center|cite|code|col|colgroup|content|data| datalist|dd|decorator|del|details|dfn|dir|div|dl|dt|element| em|embed|fieldset|figcaption|figure|font|footer|form|frame| frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe| img|input|ins|isindex|kbd|keygen|label|legend|li|link|listing| main|map|mark|marquee|menu|menuitem|meta|meter|nav|nobr| noframes|noscript|object|ol|optgroup|option|output|p|param| plaintext|pre|progress|q|rp|rt|ruby|s|samp|script|section| select|shadow|small|source|spacer|span|strike|strong|style| sub|summary|sup|table|tbody|td|template|textarea|tfoot|th| thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp )\b scope: entity.name.tag.stylus - match: '\.[a-zA-Z0-9_-]+' scope: entity.other.attribute-name.class.stylus - match: "#[a-zA-Z0-9_-]+" scope: entity.other.attribute-name.id.stylus - match: |- (?x) # multi-line regex definition mode ([\w\d_-]+)? # matching any word right before & (&) # & itself, escaped because of plist ([\w\d_-]+)? # matching any word right after & captures: 1: entity.other.attribute-name.stylus 2: variable.language.stylus 3: entity.other.attribute-name.stylus single-line-comment: - match: (\/\/).*$ scope: comment.line.stylus captures: 1: punctuation.definition.comment.stylus string-quoted: - match: "'[^']*'" scope: string.quoted.single.stylus - match: '"[^"]*"' scope: string.quoted.double.stylus url: - match: (url)\s*(\() captures: 1: entity.function-name.stylus 2: punctuation.definition.parameters.start.stylus push: - meta_scope: meta.function-call.stylus - match: (\)) captures: 1: punctuation.definition.parameters.end.stylus pop: true - include: string-quoted - include: language-constants - include: language-property-value-constants - include: property-reference - include: variable variable: - match: '([\w$-]+\b)' scope: variable.other.stylus ================================================ FILE: assets/syntaxes/02_Extra/Swift.sublime-syntax ================================================ %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)\]},;:\.])' 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: assets/syntaxes/02_Extra/TypeScript.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: TypeScript file_extensions: - ts - mts - cts scope: source.ts contexts: main: - include: directives - include: statements - include: shebang comment: - match: /\*\*(?!/) captures: 0: punctuation.definition.comment.ts push: - meta_scope: comment.block.documentation.ts - match: \*/ captures: 0: punctuation.definition.comment.ts pop: true - include: docblock - match: (/\*)(?:\s*((@)internal)(?=\s|(\*/)))? captures: 1: punctuation.definition.comment.ts 2: storage.type.internaldeclaration.ts 3: punctuation.decorator.internaldeclaration.ts push: - meta_scope: comment.block.ts - match: \*/ captures: 0: punctuation.definition.comment.ts pop: true - match: '(^[ \t]+)?((//)(?:\s*((@)internal)(?=\s|$))?)' captures: 1: punctuation.whitespace.comment.leading.ts 2: comment.line.double-slash.ts 3: punctuation.definition.comment.ts 4: storage.type.internaldeclaration.ts 5: punctuation.decorator.internaldeclaration.ts push: - meta_content_scope: comment.line.double-slash.ts - match: (?=$) pop: true access-modifier: - match: '(?]|^await|[^\._$[:alnum:]]await|^return|[^\._$[:alnum:]]return|^yield|[^\._$[:alnum:]]yield|^throw|[^\._$[:alnum:]]throw|^in|[^\._$[:alnum:]]in|^of|[^\._$[:alnum:]]of|^typeof|[^\._$[:alnum:]]typeof|&&|\|\||\*)\s*(\{)' captures: 1: punctuation.definition.block.ts push: - meta_scope: meta.objectliteral.ts - match: '\}' captures: 0: punctuation.definition.block.ts pop: true - include: object-member array-binding-pattern: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.ts 2: punctuation.definition.binding-pattern.array.ts push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.ts pop: true - include: binding-element - include: punctuation-comma array-binding-pattern-const: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.ts 2: punctuation.definition.binding-pattern.array.ts push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.ts pop: true - include: binding-element-const - include: punctuation-comma array-literal: - match: '\s*(\[)' captures: 1: meta.brace.square.ts push: - meta_scope: meta.array.literal.ts - match: '\]' captures: 0: meta.brace.square.ts pop: true - include: expression - include: punctuation-comma arrow-function: - match: '(?:(?)' scope: meta.arrow.ts captures: 1: storage.modifier.async.ts 2: variable.parameter.ts - match: |- (?x) (?: (? is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) ) ) captures: 1: storage.modifier.async.ts push: - meta_scope: meta.arrow.ts - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: comment - include: type-parameters - include: function-parameters - include: arrow-return-type - include: possibly-arrow-return-type - match: "=>" captures: 0: storage.type.function.arrow.ts push: - meta_scope: meta.arrow.ts - match: '((?<=\}|\S)(?)|((?!\{)(?=\S)))(?!\/[\/\*])' pop: true - include: single-line-comment-consuming-line-ending - include: decl-block - include: expression arrow-return-type: - match: (?<=\))\s*(:) captures: 1: keyword.operator.type.annotation.ts push: - meta_scope: meta.return.type.arrow.ts - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: arrow-return-type-body arrow-return-type-body: - match: '(?<=[:])(?=\s*\{)' push: - match: '(?<=\})' pop: true - include: type-object - include: type-predicate-operator - include: type async-modifier: - match: '(?) scope: cast.expr.ts captures: 1: meta.brace.angle.ts 2: storage.modifier.ts 3: meta.brace.angle.ts - match: '(?:(?*?\&\|\^]|[^_$[:alnum:]](?:\+\+|\-\-)|[^\+]\+|[^\-]\-))\s*(<)(?!) captures: 1: meta.brace.angle.ts pop: true - include: type - match: '(?:(?<=^))\s*(<)(?=[_$[:alpha:]][_$[:alnum:]]*\s*>)' captures: 1: meta.brace.angle.ts push: - meta_scope: cast.expr.ts - match: (\>) captures: 1: meta.brace.angle.ts pop: true - include: type class-declaration: - match: '(?\s*$)' captures: 1: punctuation.definition.comment.ts push: - meta_scope: comment.line.triple-slash.directive.ts - match: (?=$) pop: true - match: (<)(reference|amd-dependency|amd-module) captures: 1: punctuation.definition.tag.directive.ts 2: entity.name.tag.directive.ts push: - meta_scope: meta.tag.ts - match: /> captures: 0: punctuation.definition.tag.directive.ts pop: true - match: path|types|no-default-lib|lib|name scope: entity.other.attribute-name.directive.ts - match: "=" scope: keyword.operator.assignment.ts - include: string docblock: - match: |- (?x) ((@)(?:access|api)) \s+ (private|protected|public) \b captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: constant.language.access-type.jsdoc - match: |- (?x) ((@)author) \s+ ( [^@\s<>*/] (?:[^@<>*/]|\*[^/])* ) (?: \s* (<) ([^>\s]+) (>) )? captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc 4: punctuation.definition.bracket.angle.begin.jsdoc 5: constant.other.email.link.underline.jsdoc 6: punctuation.definition.bracket.angle.end.jsdoc - match: |- (?x) ((@)borrows) \s+ ((?:[^@\s*/]|\*[^/])+) # \s+ (as) \s+ # as ((?:[^@\s*/]|\*[^/])+) # captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc 4: keyword.operator.control.jsdoc 5: entity.name.type.instance.jsdoc - match: ((@)example)\s+ captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - meta_scope: meta.example.jsdoc - match: (?=@|\*/) pop: true - match: ^\s\*\s+ - match: \G(<)caption(>) captures: 0: entity.name.tag.inline.jsdoc 1: punctuation.definition.bracket.angle.begin.jsdoc 2: punctuation.definition.bracket.angle.end.jsdoc push: - meta_content_scope: constant.other.description.jsdoc - match: ()|(?=\*/) captures: 0: entity.name.tag.inline.jsdoc 1: punctuation.definition.bracket.angle.begin.jsdoc 2: punctuation.definition.bracket.angle.end.jsdoc pop: true - match: '[^\s@*](?:[^*]|\*[^/])*' captures: 0: source.embedded.ts - match: (?x) ((@)kind) \s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \b captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: constant.language.symbol-type.jsdoc - match: |- (?x) ((@)see) \s+ (?: # URL ( (?=https?://) (?:[^\s*]|\*[^/])+ ) | # JSDoc namepath ( (?! # Avoid matching bare URIs (also acceptable as links) https?:// | # Avoid matching {@inline tags}; we match those below (?:\[[^\[\]]*\])? # Possible description [preceding]{@tag} {@(?:link|linkcode|linkplain|tutorial)\b ) # Matched namepath (?:[^@\s*/]|\*[^/])+ ) ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.link.underline.jsdoc 4: entity.name.type.instance.jsdoc - match: |- (?x) ((@)template) \s+ # One or more valid identifiers ( [A-Za-z_$] # First character: non-numeric word character [\w$.\[\]]* # Rest of identifier (?: # Possible list of additional identifiers \s* , \s* [A-Za-z_$] [\w$.\[\]]* )* ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: |- (?x) ( (@) (?:arg|argument|const|constant|member|namespace|param|var) ) \s+ ( [A-Za-z_$] [\w$.\[\]]* ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: '((@)typedef)\s+(?={)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: '(?:[^@\s*/]|\*[^/])+' scope: entity.name.type.instance.jsdoc - match: '((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\s+(?={)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: '([A-Za-z_$][\w$.\[\]]*)' scope: variable.other.jsdoc - match: |- (?x) (\[)\s* [\w$]+ (?: (?:\[\])? # Foo[ ].bar properties within an array \. # Foo.Bar namespaced parameter [\w$]+ )* (?: \s* (=) # [foo=bar] Default parameter value \s* ( # The inner regexes are to stop the match early at */ and to not stop at escaped quotes (?> "(?:(?:\*(?!/))|(?:\\(?!"))|[^*\\])*?" | # [foo="bar"] Double-quoted '(?:(?:\*(?!/))|(?:\\(?!'))|[^*\\])*?' | # [foo='bar'] Single-quoted \[ (?:(?:\*(?!/))|[^*])*? \] | # [foo=[1,2]] Array literal (?:(?:\*(?!/))|\s(?!\s*\])|\[.*?(?:\]|(?=\*/))|[^*\s\[\]])* # Everything else )* ) )? \s*(?:(\])((?:[^*\s]|\*[^\s/])+)?|(?=\*/)) scope: variable.other.jsdoc captures: 1: punctuation.definition.optional-value.begin.bracket.square.jsdoc 2: keyword.operator.assignment.jsdoc 3: source.embedded.ts 4: punctuation.definition.optional-value.end.bracket.square.jsdoc 5: invalid.illegal.syntax.jsdoc - match: |- (?x) ( (@) (?:define|enum|exception|export|extends|lends|implements|modifies |namespace|private|protected|returns?|suppress|this|throws|type |yields?) ) \s+(?={) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: |- (?x) ( (@) (?:alias|augments|callback|constructs|emits|event|fires|exports? |extends|external|function|func|host|lends|listens|interface|memberof!? |method|module|mixes|mixin|name|requires|see|this|typedef|uses) ) \s+ ( (?: [^{}@\s*] | \*[^/] )+ ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc - match: '((@)(?:default(?:value)?|license|version))\s+(([''''"]))' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc 4: punctuation.definition.string.begin.jsdoc push: - meta_content_scope: variable.other.jsdoc - match: (\3)|(?=$|\*/) captures: 0: variable.other.jsdoc 1: punctuation.definition.string.end.jsdoc pop: true - match: '((@)(?:default(?:value)?|license|tutorial|variation|version))\s+([^\s*]+)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: '(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \b' scope: storage.type.class.jsdoc captures: 1: punctuation.definition.block.tag.jsdoc - include: inline-tags - match: '((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\s+)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc enum-declaration: - match: '(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: storage.modifier.ts 2: keyword.operator.rest.ts 3: entity.name.function.ts variable.language.this.ts 4: entity.name.function.ts 5: keyword.operator.optional.ts - match: '(?x)(?:(?]|\|\||\&\&|\!\=\=|$|((?>=|>>>=|\|= scope: keyword.operator.assignment.compound.bitwise.ts - match: "<<|>>>|>>" scope: keyword.operator.bitwise.shift.ts - match: "===|!==|==|!=" scope: keyword.operator.comparison.ts - match: <=|>=|<>|<|> scope: keyword.operator.relational.ts - match: '(?<=[_$[:alnum:]])(\!)\s*(?:(/=)|(?:(/)(?![/*])))' captures: 1: keyword.operator.logical.ts 2: keyword.operator.assignment.compound.ts 3: keyword.operator.arithmetic.ts - match: \!|&&|\|\||\?\? scope: keyword.operator.logical.ts - match: \&|~|\^|\| scope: keyword.operator.bitwise.ts - match: \= scope: keyword.operator.assignment.ts - match: "--" scope: keyword.operator.decrement.ts - match: \+\+ scope: keyword.operator.increment.ts - match: '%|\*|/|-|\+' scope: keyword.operator.arithmetic.ts - match: '(?<=[_$[:alnum:])\]])\s*(?=(\/\*([^\*]|(\*[^\/]))*\*\/\s*)+(?:(/=)|(?:(/)(?![/*]))))' push: - match: '(?:(/=)|(?:(/)(?!\*([^\*]|(\*[^\/]))*\*\/)))' captures: 1: keyword.operator.assignment.compound.ts 2: keyword.operator.arithmetic.ts pop: true - include: comment - match: '(?<=[_$[:alnum:])\]])\s*(?:(/=)|(?:(/)(?![/*])))' captures: 1: keyword.operator.assignment.compound.ts 2: keyword.operator.arithmetic.ts expressionPunctuations: - include: punctuation-comma - include: punctuation-accessor expressionWithoutIdentifiers: - include: string - include: regex - include: comment - include: function-expression - include: class-expression - include: arrow-function - include: paren-expression-possibly-arrow - include: cast - include: ternary-expression - include: new-expr - include: instanceof-expr - include: object-literal - include: expression-operators - include: function-call - include: literal - include: support-objects - include: paren-expression field-declaration: - match: |- (?x)(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.property.ts entity.name.function.ts 2: keyword.operator.optional.ts 3: keyword.operator.definiteassignment.ts - match: '\#?[_$[:alpha:]][_$[:alnum:]]*' scope: meta.definition.property.ts variable.object.property.ts - match: \? scope: keyword.operator.optional.ts - match: \! scope: keyword.operator.definiteassignment.ts for-loop: - match: '(?\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' push: - match: '(?<=\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))\s*(?:(\?\.\s*)|(\!))?((<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))' push: - meta_scope: meta.function-call.ts - match: '(?=\s*(?:(\?\.\s*)|(\!))?((<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' pop: true - include: function-call-target - include: comment - include: function-call-optionals - include: type-arguments - include: paren-expression - match: '(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))(<\s*[\{\[\(]\s*$))' push: - match: '(?<=\>)(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))(<\s*[\{\[\(]\s*$))' pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))' push: - meta_scope: meta.function-call.ts - match: '(?=(<\s*[\{\[\(]\s*$))' pop: true - include: function-call-target - include: comment - include: function-call-optionals - include: type-arguments function-call-optionals: - match: \?\. scope: meta.function-call.ts punctuation.accessor.optional.ts - match: \! scope: meta.function-call.ts keyword.operator.definiteassignment.ts function-call-target: - include: support-function-call-identifiers - match: '(\#?[_$[:alpha:]][_$[:alnum:]]*)' scope: entity.name.function.ts function-declaration: - match: '(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) captures: 1: punctuation.accessor.ts 2: punctuation.accessor.optional.ts 3: entity.name.function.ts - match: '(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(\#?[[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])' captures: 1: punctuation.accessor.ts 2: punctuation.accessor.optional.ts 3: variable.other.constant.property.ts - match: '(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(\#?[_$[:alpha:]][_$[:alnum:]]*)' captures: 1: punctuation.accessor.ts 2: punctuation.accessor.optional.ts 3: variable.other.property.ts - match: "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" scope: variable.other.constant.ts - match: "[_$[:alpha:]][_$[:alnum:]]*" scope: variable.other.readwrite.ts if-statement: - match: '(?]|\|\||\&\&|\!\=\=|$|(([\&\~\^\|]\s*)?[_$[:alpha:]][_$[:alnum:]]*\s+instanceof(?![_$[:alnum:]])(?:(?=\.\.\.)|(?!\.)))|((?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(])' captures: 1: storage.modifier.ts 2: storage.modifier.ts 3: storage.modifier.ts 4: storage.modifier.async.ts 5: keyword.operator.new.ts 6: keyword.generator.asterisk.ts push: - meta_scope: meta.method.declaration.ts - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: method-declaration-name - include: function-body - match: |- (?x)(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.ts 2: storage.modifier.ts 3: storage.modifier.ts 4: storage.modifier.async.ts 5: storage.type.property.ts 6: keyword.generator.asterisk.ts push: - meta_scope: meta.method.declaration.ts - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: method-declaration-name - include: function-body method-declaration-name: - match: |- (?x)(?=((\b(?]|\|\||\&\&|\!\=\=|$|((?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.async.ts 2: storage.type.property.ts 3: keyword.generator.asterisk.ts push: - meta_scope: meta.method.declaration.ts - match: '(?=\}|;|,)|(?<=\})' pop: true - include: method-declaration-name - include: function-body - match: |- (?x)(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.async.ts 2: storage.type.property.ts 3: keyword.generator.asterisk.ts push: - match: (?=\(|\<) pop: true - include: method-declaration-name object-member: - include: comment - include: object-literal-method-declaration - match: '(?=\[)' push: - meta_scope: meta.object.member.ts meta.object-literal.key.ts - match: '(?=:)|((?<=[\]])(?=\s*[\(\<]))' pop: true - include: comment - include: array-literal - match: '(?=[\''\"\`])' push: - meta_scope: meta.object.member.ts meta.object-literal.key.ts - match: '(?=:)|((?<=[\''\"\`])(?=((\s*[\(\<,}])|(\s+(as)\s+))))' pop: true - include: comment - include: string - match: |- (?x)(?=(\b(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) scope: meta.object.member.ts captures: 0: meta.object-literal.key.ts 1: entity.name.function.ts - match: '(?:[_$[:alpha:]][_$[:alnum:]]*)\s*(?=(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*:)' scope: meta.object.member.ts captures: 0: meta.object-literal.key.ts - match: \.\.\. captures: 0: keyword.operator.spread.ts push: - meta_scope: meta.object.member.ts - match: '(?=,|\})' pop: true - include: expression - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?=,|\}|$|\/\/|\/\*)' scope: meta.object.member.ts captures: 1: variable.other.readwrite.ts - match: '(?]|\|\||\&\&|\!\=\=|$|^|((?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)\(\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.ts push: - match: (?<=\)) pop: true - include: type-parameters - match: \( captures: 0: meta.brace.round.ts push: - match: \) captures: 0: meta.brace.round.ts pop: true - include: expression-inside-possibly-arrow-parens - match: '(?<=:)\s*(async)?\s*(\()(?=\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.ts 2: meta.brace.round.ts push: - match: \) captures: 0: meta.brace.round.ts pop: true - include: expression-inside-possibly-arrow-parens - match: (?<=:)\s*(async)?\s*(?=\<\s*$) captures: 1: storage.modifier.async.ts push: - match: (?<=\>) pop: true - include: type-parameters - match: '(?<=\>)\s*(\()(?=\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: meta.brace.round.ts push: - match: \) captures: 0: meta.brace.round.ts pop: true - include: expression-inside-possibly-arrow-parens - include: possibly-arrow-return-type - include: expression - include: punctuation-comma parameter-array-binding-pattern: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.ts 2: punctuation.definition.binding-pattern.array.ts push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.ts pop: true - include: parameter-binding-element - include: punctuation-comma parameter-binding-element: - include: comment - include: string - include: numeric-literal - include: regex - include: parameter-object-binding-pattern - include: parameter-array-binding-pattern - include: destructuring-parameter-rest - include: variable-initializer parameter-name: - match: '(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: storage.modifier.ts 2: keyword.operator.rest.ts 3: entity.name.function.ts variable.language.this.ts 4: entity.name.function.ts 5: keyword.operator.optional.ts - match: '(?x)(?:(?])" pop: true - include: type paren-expression: - match: \( captures: 0: meta.brace.round.ts push: - match: \) captures: 0: meta.brace.round.ts pop: true - include: expression paren-expression-possibly-arrow: - match: '(?<=[(=,])\s*(async)?(?=\s*((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?\(\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.ts push: - match: (?<=\)) pop: true - include: paren-expression-possibly-arrow-with-typeparameters - match: '(?<=[(=,]|=>|^return|[^\._$[:alnum:]]return)\s*(async)?(?=\s*((((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?\()|(<))\s*$)' captures: 1: storage.modifier.async.ts push: - match: (?<=\)) pop: true - include: paren-expression-possibly-arrow-with-typeparameters - include: possibly-arrow-return-type paren-expression-possibly-arrow-with-typeparameters: - include: type-parameters - match: \( captures: 0: meta.brace.round.ts push: - match: \) captures: 0: meta.brace.round.ts pop: true - include: expression-inside-possibly-arrow-parens possibly-arrow-return-type: - match: '(?<=\)|^)\s*(:)(?=\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*=>)' captures: 1: meta.arrow.ts meta.return.type.arrow.ts keyword.operator.type.annotation.ts push: - meta_content_scope: meta.arrow.ts meta.return.type.arrow.ts - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: arrow-return-type-body property-accessor: - match: '(?|&&|\|\||\*\/)\s*(\/)(?![\/*])(?=(?:[^\/\\\[\()]|\\.|\[([^\]\\]|\\.)+\]|\(([^\)\\]|\\.)+\))+\/([dgimsuy]+|(?![\/\*])|(?=\/\*))(?!\s*[a-zA-Z0-9_$]))' captures: 1: punctuation.definition.string.begin.ts push: - meta_scope: string.regexp.ts - match: "(/)([dgimsuy]*)" captures: 1: punctuation.definition.string.end.ts 2: keyword.other.ts pop: true - include: regexp - match: '((?' captures: 0: keyword.other.back-reference.regexp 1: variable.other.regexp - match: '[?+*]|\{(\d+,\d+|\d+,|,\d+|\d+)\}\??' scope: keyword.operator.quantifier.regexp - match: \| scope: keyword.operator.or.regexp - match: (\()((\?=)|(\?!)|(\?<=)|(\?))?' captures: 0: punctuation.definition.group.regexp 1: punctuation.definition.group.no-capture.regexp 2: variable.other.regexp push: - meta_scope: meta.group.regexp - match: \) captures: 0: punctuation.definition.group.regexp pop: true - include: regexp - match: '(\[)(\^)?' captures: 1: punctuation.definition.character-class.regexp 2: keyword.operator.negation.regexp push: - meta_scope: constant.other.character-class.set.regexp - match: '(\])' captures: 1: punctuation.definition.character-class.regexp pop: true - match: '(?:.|(\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\c[A-Z])|(\\.))\-(?:[^\]\\]|(\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\c[A-Z])|(\\.))' scope: constant.other.character-class.range.regexp captures: 1: constant.character.numeric.regexp 2: constant.character.control.regexp 3: constant.character.escape.backslash.regexp 4: constant.character.numeric.regexp 5: constant.character.control.regexp 6: constant.character.escape.backslash.regexp - include: regex-character-class - include: regex-character-class return-type: - match: (?<=\))\s*(:)(?=\s*\S) captures: 1: keyword.operator.type.annotation.ts push: - meta_scope: meta.return.type.ts - match: "(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?\()) | (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\b(?!\$))) captures: 1: punctuation.accessor.ts 2: punctuation.accessor.optional.ts 3: support.variable.property.ts 4: support.constant.ts - match: |- (?x) (?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?\() captures: 1: punctuation.accessor.ts 2: punctuation.accessor.optional.ts 3: support.constant.dom.ts 4: support.variable.property.dom.ts - match: |- (?x)(?\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?`)' push: - meta_scope: string.template.ts - match: (?=`) pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*\s*\??\.\s*)*|(\??\.\s*)?)([_$[:alpha:]][_$[:alnum:]]*))' push: - match: '(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?`)' pop: true - include: support-function-call-identifiers - match: "([_$[:alpha:]][_$[:alnum:]]*)" scope: entity.name.function.tagged-template.ts - include: type-arguments - match: '([_$[:alpha:]][_$[:alnum:]]*)?\s*(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)`)' captures: 1: entity.name.function.tagged-template.ts push: - meta_scope: string.template.ts - match: (?=`) pop: true - include: type-arguments template-substitution-element: - match: '\$\{' captures: 0: punctuation.definition.template-expression.begin.ts push: - meta_scope: meta.template.expression.ts - meta_content_scope: meta.embedded.line.ts - match: '\}' captures: 0: punctuation.definition.template-expression.end.ts pop: true - include: expression template-type: - include: template-call - match: "([_$[:alpha:]][_$[:alnum:]]*)?(`)" captures: 1: entity.name.function.tagged-template.ts 2: punctuation.definition.string.template.begin.ts push: - meta_scope: string.template.ts - match: "`" captures: 0: punctuation.definition.string.template.end.ts pop: true - include: template-type-substitution-element - include: string-character-escape template-type-substitution-element: - match: '\$\{' captures: 0: punctuation.definition.template-expression.begin.ts push: - meta_scope: meta.template.expression.ts - meta_content_scope: meta.embedded.line.ts - match: '\}' captures: 0: punctuation.definition.template-expression.end.ts pop: true - include: type ternary-expression: - match: '(?!\?\.\s*[^[:digit:]])(\?)(?!\?)' captures: 1: keyword.operator.ternary.ts push: - match: \s*(:) captures: 1: keyword.operator.ternary.ts pop: true - include: expression this-literal: - match: '(?])|((?<=[\}>\]\)]|[_$[:alpha:]])\s*(?=\{)))' pop: true - include: type - match: (:) captures: 1: keyword.operator.type.annotation.ts push: - meta_scope: meta.type.annotation.ts - match: '(?])|(?=^\s*$)|((?<=\S)(?=\s*$))|((?<=[\}>\]\)]|[_$[:alpha:]])\s*(?=\{)))' pop: true - include: type type-arguments: - match: \< captures: 0: punctuation.definition.typeparameters.begin.ts push: - meta_scope: meta.type.parameters.ts - match: \> captures: 0: punctuation.definition.typeparameters.end.ts pop: true - include: type-arguments-body type-arguments-body: - match: '(?) pop: true - include: comment - include: type-parameters - match: '(?) )) ) ) ) push: - meta_scope: meta.type.function.ts - match: (?<=\)) pop: true - include: function-parameters type-function-return-type: - match: (=>)(?=\s*\S) captures: 1: storage.type.function.arrow.ts push: - meta_scope: meta.type.function.return.ts - match: '(?)(?:\?]|//|$)' pop: true - include: type-function-return-type-core - match: "=>" captures: 0: storage.type.function.arrow.ts push: - meta_scope: meta.type.function.return.ts - match: '(?)(?]|//|^\s*$)|((?<=\S)(?=\s*$)))' pop: true - include: type-function-return-type-core type-function-return-type-core: - include: comment - match: '(?<==>)(?=\s*\{)' push: - match: '(?<=\})' pop: true - include: type-object - include: type-predicate-operator - include: type type-name: - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(<)' captures: 1: entity.name.type.module.ts 2: punctuation.accessor.ts 3: punctuation.accessor.optional.ts 4: meta.type.parameters.ts punctuation.definition.typeparameters.begin.ts push: - meta_content_scope: meta.type.parameters.ts - match: (>) captures: 1: meta.type.parameters.ts punctuation.definition.typeparameters.end.ts pop: true - include: type-arguments-body - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(<)' captures: 1: entity.name.type.ts 2: meta.type.parameters.ts punctuation.definition.typeparameters.begin.ts push: - meta_content_scope: meta.type.parameters.ts - match: (>) captures: 1: meta.type.parameters.ts punctuation.definition.typeparameters.end.ts pop: true - include: type-arguments-body - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?:(\.)|(\?\.(?!\s*[[:digit:]])))' captures: 1: entity.name.type.module.ts 2: punctuation.accessor.ts 3: punctuation.accessor.optional.ts - match: "[_$[:alpha:]][_$[:alnum:]]*" scope: entity.name.type.ts type-object: - match: '\{' captures: 0: punctuation.definition.block.ts push: - meta_scope: meta.object.type.ts - match: '\}' captures: 0: punctuation.definition.block.ts pop: true - include: comment - include: method-declaration - include: indexer-declaration - include: indexer-mapped-type-declaration - include: field-declaration - include: type-annotation - match: \.\.\. captures: 0: keyword.operator.spread.ts push: - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: type - include: punctuation-comma - include: punctuation-semicolon - include: type type-operators: - include: typeof-operator - match: '([&|])(?=\s*\{)' captures: 0: keyword.operator.type.ts push: - match: '(?<=\})' pop: true - include: type-object - match: "[&|]" captures: 0: keyword.operator.type.ts push: - match: (?=\S) pop: true - match: '(?) captures: 1: punctuation.definition.typeparameters.end.ts pop: true - include: comment - match: '(?) scope: keyword.operator.assignment.ts type-paren-or-function-parameters: - match: \( captures: 0: meta.brace.round.ts push: - meta_scope: meta.type.paren.cover.ts - match: \) captures: 0: meta.brace.round.ts pop: true - match: |- (?x)(?:(?) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))))) captures: 1: storage.modifier.ts 2: keyword.operator.rest.ts 3: entity.name.function.ts variable.language.this.ts 4: entity.name.function.ts 5: keyword.operator.optional.ts - match: '(?x)(?:(?:&|{\?]|$|;|^\s*$|(?:^\s*(?:abstract|async|class|const|declare|enum|export|function|import|interface|let|module|namespace|return|type|var)\b))' pop: true - include: expression undefined-literal: - match: '(?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.variable.ts variable.other.constant.ts entity.name.function.ts push: - meta_scope: meta.var-single-variable.expr.ts - match: '(?=$|^|[;,=}]|((?) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?[\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.variable.ts entity.name.function.ts 2: keyword.operator.definiteassignment.ts push: - meta_scope: meta.var-single-variable.expr.ts - match: '(?=$|^|[;,=}]|((?\s*$) captures: 1: keyword.operator.assignment.ts push: - match: '(?=$|^|[,);}\]]|((?]|^await|[^\._$[:alnum:]]await|^return|[^\._$[:alnum:]]return|^yield|[^\._$[:alnum:]]yield|^throw|[^\._$[:alnum:]]throw|^in|[^\._$[:alnum:]]in|^of|[^\._$[:alnum:]]of|^typeof|[^\._$[:alnum:]]typeof|&&|\|\||\*)\s*(\{)' captures: 1: punctuation.definition.block.tsx push: - meta_scope: meta.objectliteral.tsx - match: '\}' captures: 0: punctuation.definition.block.tsx pop: true - include: object-member array-binding-pattern: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.tsx 2: punctuation.definition.binding-pattern.array.tsx push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.tsx pop: true - include: binding-element - include: punctuation-comma array-binding-pattern-const: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.tsx 2: punctuation.definition.binding-pattern.array.tsx push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.tsx pop: true - include: binding-element-const - include: punctuation-comma array-literal: - match: '\s*(\[)' captures: 1: meta.brace.square.tsx push: - meta_scope: meta.array.literal.tsx - match: '\]' captures: 0: meta.brace.square.tsx pop: true - include: expression - include: punctuation-comma arrow-function: - match: '(?:(?)' scope: meta.arrow.tsx captures: 1: storage.modifier.async.tsx 2: variable.parameter.tsx - match: |- (?x) (?: (? is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) ) ) captures: 1: storage.modifier.async.tsx push: - meta_scope: meta.arrow.tsx - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: comment - include: type-parameters - include: function-parameters - include: arrow-return-type - include: possibly-arrow-return-type - match: "=>" captures: 0: storage.type.function.arrow.tsx push: - meta_scope: meta.arrow.tsx - match: '((?<=\}|\S)(?)|((?!\{)(?=\S)))(?!\/[\/\*])' pop: true - include: single-line-comment-consuming-line-ending - include: decl-block - include: expression arrow-return-type: - match: (?<=\))\s*(:) captures: 1: keyword.operator.type.annotation.tsx push: - meta_scope: meta.return.type.arrow.tsx - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: arrow-return-type-body arrow-return-type-body: - match: '(?<=[:])(?=\s*\{)' push: - match: '(?<=\})' pop: true - include: type-object - include: type-predicate-operator - include: type async-modifier: - match: '(?\s*$)' captures: 1: punctuation.definition.comment.tsx push: - meta_scope: comment.line.triple-slash.directive.tsx - match: (?=$) pop: true - match: (<)(reference|amd-dependency|amd-module) captures: 1: punctuation.definition.tag.directive.tsx 2: entity.name.tag.directive.tsx push: - meta_scope: meta.tag.tsx - match: /> captures: 0: punctuation.definition.tag.directive.tsx pop: true - match: path|types|no-default-lib|lib|name scope: entity.other.attribute-name.directive.tsx - match: "=" scope: keyword.operator.assignment.tsx - include: string docblock: - match: |- (?x) ((@)(?:access|api)) \s+ (private|protected|public) \b captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: constant.language.access-type.jsdoc - match: |- (?x) ((@)author) \s+ ( [^@\s<>*/] (?:[^@<>*/]|\*[^/])* ) (?: \s* (<) ([^>\s]+) (>) )? captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc 4: punctuation.definition.bracket.angle.begin.jsdoc 5: constant.other.email.link.underline.jsdoc 6: punctuation.definition.bracket.angle.end.jsdoc - match: |- (?x) ((@)borrows) \s+ ((?:[^@\s*/]|\*[^/])+) # \s+ (as) \s+ # as ((?:[^@\s*/]|\*[^/])+) # captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc 4: keyword.operator.control.jsdoc 5: entity.name.type.instance.jsdoc - match: ((@)example)\s+ captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - meta_scope: meta.example.jsdoc - match: (?=@|\*/) pop: true - match: ^\s\*\s+ - match: \G(<)caption(>) captures: 0: entity.name.tag.inline.jsdoc 1: punctuation.definition.bracket.angle.begin.jsdoc 2: punctuation.definition.bracket.angle.end.jsdoc push: - meta_content_scope: constant.other.description.jsdoc - match: ()|(?=\*/) captures: 0: entity.name.tag.inline.jsdoc 1: punctuation.definition.bracket.angle.begin.jsdoc 2: punctuation.definition.bracket.angle.end.jsdoc pop: true - match: '[^\s@*](?:[^*]|\*[^/])*' captures: 0: source.embedded.tsx - match: (?x) ((@)kind) \s+ (class|constant|event|external|file|function|member|mixin|module|namespace|typedef) \b captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: constant.language.symbol-type.jsdoc - match: |- (?x) ((@)see) \s+ (?: # URL ( (?=https?://) (?:[^\s*]|\*[^/])+ ) | # JSDoc namepath ( (?! # Avoid matching bare URIs (also acceptable as links) https?:// | # Avoid matching {@inline tags}; we match those below (?:\[[^\[\]]*\])? # Possible description [preceding]{@tag} {@(?:link|linkcode|linkplain|tutorial)\b ) # Matched namepath (?:[^@\s*/]|\*[^/])+ ) ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.link.underline.jsdoc 4: entity.name.type.instance.jsdoc - match: |- (?x) ((@)template) \s+ # One or more valid identifiers ( [A-Za-z_$] # First character: non-numeric word character [\w$.\[\]]* # Rest of identifier (?: # Possible list of additional identifiers \s* , \s* [A-Za-z_$] [\w$.\[\]]* )* ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: |- (?x) ( (@) (?:arg|argument|const|constant|member|namespace|param|var) ) \s+ ( [A-Za-z_$] [\w$.\[\]]* ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: '((@)typedef)\s+(?={)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: '(?:[^@\s*/]|\*[^/])+' scope: entity.name.type.instance.jsdoc - match: '((@)(?:arg|argument|const|constant|member|namespace|param|prop|property|var))\s+(?={)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: '([A-Za-z_$][\w$.\[\]]*)' scope: variable.other.jsdoc - match: |- (?x) (\[)\s* [\w$]+ (?: (?:\[\])? # Foo[ ].bar properties within an array \. # Foo.Bar namespaced parameter [\w$]+ )* (?: \s* (=) # [foo=bar] Default parameter value \s* ( # The inner regexes are to stop the match early at */ and to not stop at escaped quotes (?> "(?:(?:\*(?!/))|(?:\\(?!"))|[^*\\])*?" | # [foo="bar"] Double-quoted '(?:(?:\*(?!/))|(?:\\(?!'))|[^*\\])*?' | # [foo='bar'] Single-quoted \[ (?:(?:\*(?!/))|[^*])*? \] | # [foo=[1,2]] Array literal (?:(?:\*(?!/))|\s(?!\s*\])|\[.*?(?:\]|(?=\*/))|[^*\s\[\]])* # Everything else )* ) )? \s*(?:(\])((?:[^*\s]|\*[^\s/])+)?|(?=\*/)) scope: variable.other.jsdoc captures: 1: punctuation.definition.optional-value.begin.bracket.square.jsdoc 2: keyword.operator.assignment.jsdoc 3: source.embedded.tsx 4: punctuation.definition.optional-value.end.bracket.square.jsdoc 5: invalid.illegal.syntax.jsdoc - match: |- (?x) ( (@) (?:define|enum|exception|export|extends|lends|implements|modifies |namespace|private|protected|returns?|suppress|this|throws|type |yields?) ) \s+(?={) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc push: - match: '(?=\s|\*/|[^{}\[\]A-Za-z_$])' pop: true - include: jsdoctype - match: |- (?x) ( (@) (?:alias|augments|callback|constructs|emits|event|fires|exports? |extends|external|function|func|host|lends|listens|interface|memberof!? |method|module|mixes|mixin|name|requires|see|this|typedef|uses) ) \s+ ( (?: [^{}@\s*] | \*[^/] )+ ) captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: entity.name.type.instance.jsdoc - match: '((@)(?:default(?:value)?|license|version))\s+(([''''"]))' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc 4: punctuation.definition.string.begin.jsdoc push: - meta_content_scope: variable.other.jsdoc - match: (\3)|(?=$|\*/) captures: 0: variable.other.jsdoc 1: punctuation.definition.string.end.jsdoc pop: true - match: '((@)(?:default(?:value)?|license|tutorial|variation|version))\s+([^\s*]+)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc 3: variable.other.jsdoc - match: '(?x) (@) (?:abstract|access|alias|api|arg|argument|async|attribute|augments|author|beta|borrows|bubbles |callback|chainable|class|classdesc|code|config|const|constant|constructor|constructs|copyright |default|defaultvalue|define|deprecated|desc|description|dict|emits|enum|event|example|exception |exports?|extends|extension(?:_?for)?|external|externs|file|fileoverview|final|fires|for|func |function|generator|global|hideconstructor|host|ignore|implements|implicitCast|inherit[Dd]oc |inner|instance|interface|internal|kind|lends|license|listens|main|member|memberof!?|method |mixes|mixins?|modifies|module|name|namespace|noalias|nocollapse|nocompile|nosideeffects |override|overview|package|param|polymer(?:Behavior)?|preserve|private|prop|property|protected |public|read[Oo]nly|record|require[ds]|returns?|see|since|static|struct|submodule|summary |suppress|template|this|throws|todo|tutorial|type|typedef|unrestricted|uses|var|variation |version|virtual|writeOnce|yields?) \b' scope: storage.type.class.jsdoc captures: 1: punctuation.definition.block.tag.jsdoc - include: inline-tags - match: '((@)(?:[_$[:alpha:]][_$[:alnum:]]*))(?=\s+)' captures: 1: storage.type.class.jsdoc 2: punctuation.definition.block.tag.jsdoc enum-declaration: - match: '(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: storage.modifier.tsx 2: keyword.operator.rest.tsx 3: entity.name.function.tsx variable.language.this.tsx 4: entity.name.function.tsx 5: keyword.operator.optional.tsx - match: '(?x)(?:(?]|\|\||\&\&|\!\=\=|$|((?>=|>>>=|\|= scope: keyword.operator.assignment.compound.bitwise.tsx - match: "<<|>>>|>>" scope: keyword.operator.bitwise.shift.tsx - match: "===|!==|==|!=" scope: keyword.operator.comparison.tsx - match: <=|>=|<>|<|> scope: keyword.operator.relational.tsx - match: '(?<=[_$[:alnum:]])(\!)\s*(?:(/=)|(?:(/)(?![/*])))' captures: 1: keyword.operator.logical.tsx 2: keyword.operator.assignment.compound.tsx 3: keyword.operator.arithmetic.tsx - match: \!|&&|\|\||\?\? scope: keyword.operator.logical.tsx - match: \&|~|\^|\| scope: keyword.operator.bitwise.tsx - match: \= scope: keyword.operator.assignment.tsx - match: "--" scope: keyword.operator.decrement.tsx - match: \+\+ scope: keyword.operator.increment.tsx - match: '%|\*|/|-|\+' scope: keyword.operator.arithmetic.tsx - match: '(?<=[_$[:alnum:])\]])\s*(?=(\/\*([^\*]|(\*[^\/]))*\*\/\s*)+(?:(/=)|(?:(/)(?![/*]))))' push: - match: '(?:(/=)|(?:(/)(?!\*([^\*]|(\*[^\/]))*\*\/)))' captures: 1: keyword.operator.assignment.compound.tsx 2: keyword.operator.arithmetic.tsx pop: true - include: comment - match: '(?<=[_$[:alnum:])\]])\s*(?:(/=)|(?:(/)(?![/*])))' captures: 1: keyword.operator.assignment.compound.tsx 2: keyword.operator.arithmetic.tsx expressionPunctuations: - include: punctuation-comma - include: punctuation-accessor expressionWithoutIdentifiers: - include: jsx - include: string - include: regex - include: comment - include: function-expression - include: class-expression - include: arrow-function - include: paren-expression-possibly-arrow - include: cast - include: ternary-expression - include: new-expr - include: instanceof-expr - include: object-literal - include: expression-operators - include: function-call - include: literal - include: support-objects - include: paren-expression field-declaration: - match: |- (?x)(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.property.tsx entity.name.function.tsx 2: keyword.operator.optional.tsx 3: keyword.operator.definiteassignment.tsx - match: '\#?[_$[:alpha:]][_$[:alnum:]]*' scope: meta.definition.property.tsx variable.object.property.tsx - match: \? scope: keyword.operator.optional.tsx - match: \! scope: keyword.operator.definiteassignment.tsx for-loop: - match: '(?\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' push: - match: '(?<=\))(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))\s*(?:(\?\.\s*)|(\!))?((<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))' push: - meta_scope: meta.function-call.tsx - match: '(?=\s*(?:(\?\.\s*)|(\!))?((<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?\())' pop: true - include: function-call-target - include: comment - include: function-call-optionals - include: type-arguments - include: paren-expression - match: '(?=(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))(<\s*[\{\[\(]\s*$))' push: - match: '(?<=\>)(?!(((([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))|(?<=[\)]))(<\s*[\{\[\(]\s*$))' pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*)(\s*\??\.\s*(\#?[_$[:alpha:]][_$[:alnum:]]*))*)|(\??\.\s*\#?[_$[:alpha:]][_$[:alnum:]]*))' push: - meta_scope: meta.function-call.tsx - match: '(?=(<\s*[\{\[\(]\s*$))' pop: true - include: function-call-target - include: comment - include: function-call-optionals - include: type-arguments function-call-optionals: - match: \?\. scope: meta.function-call.tsx punctuation.accessor.optional.tsx - match: \! scope: meta.function-call.tsx keyword.operator.definiteassignment.tsx function-call-target: - include: support-function-call-identifiers - match: '(\#?[_$[:alpha:]][_$[:alnum:]]*)' scope: entity.name.function.tsx function-declaration: - match: '(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) captures: 1: punctuation.accessor.tsx 2: punctuation.accessor.optional.tsx 3: entity.name.function.tsx - match: '(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(\#?[[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])' captures: 1: punctuation.accessor.tsx 2: punctuation.accessor.optional.tsx 3: variable.other.constant.property.tsx - match: '(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(\#?[_$[:alpha:]][_$[:alnum:]]*)' captures: 1: punctuation.accessor.tsx 2: punctuation.accessor.optional.tsx 3: variable.other.property.tsx - match: "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" scope: variable.other.constant.tsx - match: "[_$[:alpha:]][_$[:alnum:]]*" scope: variable.other.readwrite.tsx if-statement: - match: '(?]|\|\||\&\&|\!\=\=|$|(([\&\~\^\|]\s*)?[_$[:alpha:]][_$[:alnum:]]*\s+instanceof(?![_$[:alnum:]])(?:(?=\.\.\.)|(?!\.)))|((?))' push: - meta_scope: meta.tag.tsx - match: '(/>)|(?:())' captures: 1: punctuation.definition.tag.end.tsx 2: punctuation.definition.tag.begin.tsx 3: entity.name.tag.namespace.tsx 4: punctuation.separator.namespace.tsx 5: entity.name.tag.tsx 6: support.class.component.tsx 7: punctuation.definition.tag.end.tsx pop: true - match: '(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?)' captures: 1: punctuation.definition.tag.begin.tsx 2: entity.name.tag.namespace.tsx 3: punctuation.separator.namespace.tsx 4: entity.name.tag.tsx 5: support.class.component.tsx push: - match: "(?=[/]?>)" pop: true - include: comment - include: type-arguments - include: jsx-tag-attributes - match: (>) captures: 1: punctuation.definition.tag.end.tsx push: - meta_content_scope: meta.jsx.children.tsx - match: (?=|/\*|//) captures: 1: entity.other.attribute-name.namespace.tsx 2: punctuation.separator.namespace.tsx 3: entity.other.attribute-name.tsx jsx-tag-attributes: - match: \s+ push: - meta_scope: meta.tag.attributes.tsx - match: "(?=[/]?>)" pop: true - include: comment - include: jsx-tag-attribute-name - include: jsx-tag-attribute-assignment - include: jsx-string-double-quoted - include: jsx-string-single-quoted - include: jsx-evaluated-code - include: jsx-tag-attributes-illegal jsx-tag-attributes-illegal: - match: \S+ scope: invalid.illegal.attribute.tsx jsx-tag-in-expression: - match: |- (?x) (?:*]|&&|\|\||\?|\*\/|^await|[^\._$[:alnum:]]await|^return|[^\._$[:alnum:]]return|^default|[^\._$[:alnum:]]default|^yield|[^\._$[:alnum:]]yield|^)\s* (?!<\s*[_$[:alpha:]][_$[:alnum:]]*((\s+extends\s+[^=>])|,)) # look ahead is not type parameter of arrow (?=(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?)) push: - match: '(?!(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))' pop: true - include: jsx-tag jsx-tag-without-attributes: - match: '(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?)' captures: 1: punctuation.definition.tag.begin.tsx 2: entity.name.tag.namespace.tsx 3: punctuation.separator.namespace.tsx 4: entity.name.tag.tsx 5: support.class.component.tsx 6: punctuation.definition.tag.end.tsx push: - meta_scope: meta.tag.without-attributes.tsx - meta_content_scope: meta.jsx.children.tsx - match: '()' captures: 1: punctuation.definition.tag.begin.tsx 2: entity.name.tag.namespace.tsx 3: punctuation.separator.namespace.tsx 4: entity.name.tag.tsx 5: support.class.component.tsx 6: punctuation.definition.tag.end.tsx pop: true - include: jsx-children jsx-tag-without-attributes-in-expression: - match: '(?:*]|&&|\|\||\?|\*\/|^await|[^\._$[:alnum:]]await|^return|[^\._$[:alnum:]]return|^default|[^\._$[:alnum:]]default|^yield|[^\._$[:alnum:]]yield|^)\s*(?=(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))' push: - match: '(?!(<)\s*(?:([_$[:alpha:]][-_$[:alnum:].]*)(?))' pop: true - include: jsx-tag-without-attributes label: - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(:)(?=\s*\{)' captures: 1: entity.name.label.tsx 2: punctuation.separator.label.tsx push: - match: '(?<=\})' pop: true - include: decl-block - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(:)' captures: 1: entity.name.label.tsx 2: punctuation.separator.label.tsx literal: - include: numeric-literal - include: boolean-literal - include: null-literal - include: undefined-literal - include: numericConstant-literal - include: array-literal - include: this-literal - include: super-literal method-declaration: - match: '(?x)(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(])' captures: 1: storage.modifier.tsx 2: storage.modifier.tsx 3: storage.modifier.tsx 4: storage.modifier.async.tsx 5: keyword.operator.new.tsx 6: keyword.generator.asterisk.tsx push: - meta_scope: meta.method.declaration.tsx - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: method-declaration-name - include: function-body - match: |- (?x)(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.tsx 2: storage.modifier.tsx 3: storage.modifier.tsx 4: storage.modifier.async.tsx 5: storage.type.property.tsx 6: keyword.generator.asterisk.tsx push: - meta_scope: meta.method.declaration.tsx - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: method-declaration-name - include: function-body method-declaration-name: - match: |- (?x)(?=((\b(?]|\|\||\&\&|\!\=\=|$|((?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.async.tsx 2: storage.type.property.tsx 3: keyword.generator.asterisk.tsx push: - meta_scope: meta.method.declaration.tsx - match: '(?=\}|;|,)|(?<=\})' pop: true - include: method-declaration-name - include: function-body - match: |- (?x)(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?[\(]) captures: 1: storage.modifier.async.tsx 2: storage.type.property.tsx 3: keyword.generator.asterisk.tsx push: - match: (?=\(|\<) pop: true - include: method-declaration-name object-member: - include: comment - include: object-literal-method-declaration - match: '(?=\[)' push: - meta_scope: meta.object.member.tsx meta.object-literal.key.tsx - match: '(?=:)|((?<=[\]])(?=\s*[\(\<]))' pop: true - include: comment - include: array-literal - match: '(?=[\''\"\`])' push: - meta_scope: meta.object.member.tsx meta.object-literal.key.tsx - match: '(?=:)|((?<=[\''\"\`])(?=((\s*[\(\<,}])|(\s+(as)\s+))))' pop: true - include: comment - include: string - match: |- (?x)(?=(\b(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) scope: meta.object.member.tsx captures: 0: meta.object-literal.key.tsx 1: entity.name.function.tsx - match: '(?:[_$[:alpha:]][_$[:alnum:]]*)\s*(?=(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*:)' scope: meta.object.member.tsx captures: 0: meta.object-literal.key.tsx - match: \.\.\. captures: 0: keyword.operator.spread.tsx push: - meta_scope: meta.object.member.tsx - match: '(?=,|\})' pop: true - include: expression - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?=,|\}|$|\/\/|\/\*)' scope: meta.object.member.tsx captures: 1: variable.other.readwrite.tsx - match: '(?]|\|\||\&\&|\!\=\=|$|^|((?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)\(\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.tsx push: - match: (?<=\)) pop: true - include: type-parameters - match: \( captures: 0: meta.brace.round.tsx push: - match: \) captures: 0: meta.brace.round.tsx pop: true - include: expression-inside-possibly-arrow-parens - match: '(?<=:)\s*(async)?\s*(\()(?=\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.tsx 2: meta.brace.round.tsx push: - match: \) captures: 0: meta.brace.round.tsx pop: true - include: expression-inside-possibly-arrow-parens - match: (?<=:)\s*(async)?\s*(?=\<\s*$) captures: 1: storage.modifier.async.tsx push: - match: (?<=\>) pop: true - include: type-parameters - match: '(?<=\>)\s*(\()(?=\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: meta.brace.round.tsx push: - match: \) captures: 0: meta.brace.round.tsx pop: true - include: expression-inside-possibly-arrow-parens - include: possibly-arrow-return-type - include: expression - include: punctuation-comma parameter-array-binding-pattern: - match: '(?:(\.\.\.)\s*)?(\[)' captures: 1: keyword.operator.rest.tsx 2: punctuation.definition.binding-pattern.array.tsx push: - match: '\]' captures: 0: punctuation.definition.binding-pattern.array.tsx pop: true - include: parameter-binding-element - include: punctuation-comma parameter-binding-element: - include: comment - include: string - include: numeric-literal - include: regex - include: parameter-object-binding-pattern - include: parameter-array-binding-pattern - include: destructuring-parameter-rest - include: variable-initializer parameter-name: - match: '(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: storage.modifier.tsx 2: keyword.operator.rest.tsx 3: entity.name.function.tsx variable.language.this.tsx 4: entity.name.function.tsx 5: keyword.operator.optional.tsx - match: '(?x)(?:(?])" pop: true - include: type paren-expression: - match: \( captures: 0: meta.brace.round.tsx push: - match: \) captures: 0: meta.brace.round.tsx pop: true - include: expression paren-expression-possibly-arrow: - match: '(?<=[(=,])\s*(async)?(?=\s*((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?\(\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))' captures: 1: storage.modifier.async.tsx push: - match: (?<=\)) pop: true - include: paren-expression-possibly-arrow-with-typeparameters - match: '(?<=[(=,]|=>|^return|[^\._$[:alnum:]]return)\s*(async)?(?=\s*((((<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*))?\()|(<))\s*$)' captures: 1: storage.modifier.async.tsx push: - match: (?<=\)) pop: true - include: paren-expression-possibly-arrow-with-typeparameters - include: possibly-arrow-return-type paren-expression-possibly-arrow-with-typeparameters: - include: type-parameters - match: \( captures: 0: meta.brace.round.tsx push: - match: \) captures: 0: meta.brace.round.tsx pop: true - include: expression-inside-possibly-arrow-parens possibly-arrow-return-type: - match: '(?<=\)|^)\s*(:)(?=\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*=>)' captures: 1: meta.arrow.tsx meta.return.type.arrow.tsx keyword.operator.type.annotation.tsx push: - meta_content_scope: meta.arrow.tsx meta.return.type.arrow.tsx - match: '(?==>|\{|(^\s*(export|function|class|interface|let|var|const|import|enum|namespace|module|type|abstract|declare)\s+))' pop: true - include: arrow-return-type-body property-accessor: - match: '(?|&&|\|\||\*\/)\s*(\/)(?![\/*])(?=(?:[^\/\\\[\()]|\\.|\[([^\]\\]|\\.)+\]|\(([^\)\\]|\\.)+\))+\/([dgimsuy]+|(?![\/\*])|(?=\/\*))(?!\s*[a-zA-Z0-9_$]))' captures: 1: punctuation.definition.string.begin.tsx push: - meta_scope: string.regexp.tsx - match: "(/)([dgimsuy]*)" captures: 1: punctuation.definition.string.end.tsx 2: keyword.other.tsx pop: true - include: regexp - match: '((?' captures: 0: keyword.other.back-reference.regexp 1: variable.other.regexp - match: '[?+*]|\{(\d+,\d+|\d+,|,\d+|\d+)\}\??' scope: keyword.operator.quantifier.regexp - match: \| scope: keyword.operator.or.regexp - match: (\()((\?=)|(\?!)|(\?<=)|(\?))?' captures: 0: punctuation.definition.group.regexp 1: punctuation.definition.group.no-capture.regexp 2: variable.other.regexp push: - meta_scope: meta.group.regexp - match: \) captures: 0: punctuation.definition.group.regexp pop: true - include: regexp - match: '(\[)(\^)?' captures: 1: punctuation.definition.character-class.regexp 2: keyword.operator.negation.regexp push: - meta_scope: constant.other.character-class.set.regexp - match: '(\])' captures: 1: punctuation.definition.character-class.regexp pop: true - match: '(?:.|(\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\c[A-Z])|(\\.))\-(?:[^\]\\]|(\\(?:[0-7]{3}|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}))|(\\c[A-Z])|(\\.))' scope: constant.other.character-class.range.regexp captures: 1: constant.character.numeric.regexp 2: constant.character.control.regexp 3: constant.character.escape.backslash.regexp 4: constant.character.numeric.regexp 5: constant.character.control.regexp 6: constant.character.escape.backslash.regexp - include: regex-character-class - include: regex-character-class return-type: - match: (?<=\))\s*(:)(?=\s*\S) captures: 1: keyword.operator.type.annotation.tsx push: - meta_scope: meta.return.type.tsx - match: "(?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?\()) | (?:(EPSILON|MAX_SAFE_INTEGER|MAX_VALUE|MIN_SAFE_INTEGER|MIN_VALUE|NEGATIVE_INFINITY|POSITIVE_INFINITY)\b(?!\$))) captures: 1: punctuation.accessor.tsx 2: punctuation.accessor.optional.tsx 3: support.variable.property.tsx 4: support.constant.tsx - match: |- (?x) (?]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)?\() captures: 1: punctuation.accessor.tsx 2: punctuation.accessor.optional.tsx 3: support.constant.dom.tsx 4: support.variable.property.dom.tsx - match: |- (?x)(?\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?`)' push: - meta_scope: string.template.tsx - match: (?=`) pop: true - match: '(?=(([_$[:alpha:]][_$[:alnum:]]*\s*\??\.\s*)*|(\??\.\s*)?)([_$[:alpha:]][_$[:alnum:]]*))' push: - match: '(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)?`)' pop: true - include: support-function-call-identifiers - match: "([_$[:alpha:]][_$[:alnum:]]*)" scope: entity.name.function.tagged-template.tsx - include: type-arguments - match: '([_$[:alpha:]][_$[:alnum:]]*)?\s*(?=(<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))(([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>|\<\s*(((keyof|infer|typeof|readonly)\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\''([^\''\\]|\\.)*\'')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))(?=\s*([\<\>\,\.\[]|=>|&(?!&)|\|(?!\|)))))([^<>\(]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(?<==)\>)*(?))*(?)*(?\s*)`)' captures: 1: entity.name.function.tagged-template.tsx push: - meta_scope: string.template.tsx - match: (?=`) pop: true - include: type-arguments template-substitution-element: - match: '\$\{' captures: 0: punctuation.definition.template-expression.begin.tsx push: - meta_scope: meta.template.expression.tsx - meta_content_scope: meta.embedded.line.tsx - match: '\}' captures: 0: punctuation.definition.template-expression.end.tsx pop: true - include: expression template-type: - include: template-call - match: "([_$[:alpha:]][_$[:alnum:]]*)?(`)" captures: 1: entity.name.function.tagged-template.tsx 2: punctuation.definition.string.template.begin.tsx push: - meta_scope: string.template.tsx - match: "`" captures: 0: punctuation.definition.string.template.end.tsx pop: true - include: template-type-substitution-element - include: string-character-escape template-type-substitution-element: - match: '\$\{' captures: 0: punctuation.definition.template-expression.begin.tsx push: - meta_scope: meta.template.expression.tsx - meta_content_scope: meta.embedded.line.tsx - match: '\}' captures: 0: punctuation.definition.template-expression.end.tsx pop: true - include: type ternary-expression: - match: '(?!\?\.\s*[^[:digit:]])(\?)(?!\?)' captures: 1: keyword.operator.ternary.tsx push: - match: \s*(:) captures: 1: keyword.operator.ternary.tsx pop: true - include: expression this-literal: - match: '(?])|((?<=[\}>\]\)]|[_$[:alpha:]])\s*(?=\{)))' pop: true - include: type - match: (:) captures: 1: keyword.operator.type.annotation.tsx push: - meta_scope: meta.type.annotation.tsx - match: '(?])|(?=^\s*$)|((?<=\S)(?=\s*$))|((?<=[\}>\]\)]|[_$[:alpha:]])\s*(?=\{)))' pop: true - include: type type-arguments: - match: \< captures: 0: punctuation.definition.typeparameters.begin.tsx push: - meta_scope: meta.type.parameters.tsx - match: \> captures: 0: punctuation.definition.typeparameters.end.tsx pop: true - include: type-arguments-body type-arguments-body: - match: '(?) pop: true - include: comment - include: type-parameters - match: '(?) )) ) ) ) push: - meta_scope: meta.type.function.tsx - match: (?<=\)) pop: true - include: function-parameters type-function-return-type: - match: (=>)(?=\s*\S) captures: 1: storage.type.function.arrow.tsx push: - meta_scope: meta.type.function.return.tsx - match: '(?)(?:\?]|//|$)' pop: true - include: type-function-return-type-core - match: "=>" captures: 0: storage.type.function.arrow.tsx push: - meta_scope: meta.type.function.return.tsx - match: '(?)(?]|//|^\s*$)|((?<=\S)(?=\s*$)))' pop: true - include: type-function-return-type-core type-function-return-type-core: - include: comment - match: '(?<==>)(?=\s*\{)' push: - match: '(?<=\})' pop: true - include: type-object - include: type-predicate-operator - include: type type-name: - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?:(\.)|(\?\.(?!\s*[[:digit:]])))\s*(<)' captures: 1: entity.name.type.module.tsx 2: punctuation.accessor.tsx 3: punctuation.accessor.optional.tsx 4: meta.type.parameters.tsx punctuation.definition.typeparameters.begin.tsx push: - meta_content_scope: meta.type.parameters.tsx - match: (>) captures: 1: meta.type.parameters.tsx punctuation.definition.typeparameters.end.tsx pop: true - include: type-arguments-body - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(<)' captures: 1: entity.name.type.tsx 2: meta.type.parameters.tsx punctuation.definition.typeparameters.begin.tsx push: - meta_content_scope: meta.type.parameters.tsx - match: (>) captures: 1: meta.type.parameters.tsx punctuation.definition.typeparameters.end.tsx pop: true - include: type-arguments-body - match: '([_$[:alpha:]][_$[:alnum:]]*)\s*(?:(\.)|(\?\.(?!\s*[[:digit:]])))' captures: 1: entity.name.type.module.tsx 2: punctuation.accessor.tsx 3: punctuation.accessor.optional.tsx - match: "[_$[:alpha:]][_$[:alnum:]]*" scope: entity.name.type.tsx type-object: - match: '\{' captures: 0: punctuation.definition.block.tsx push: - meta_scope: meta.object.type.tsx - match: '\}' captures: 0: punctuation.definition.block.tsx pop: true - include: comment - include: method-declaration - include: indexer-declaration - include: indexer-mapped-type-declaration - include: field-declaration - include: type-annotation - match: \.\.\. captures: 0: keyword.operator.spread.tsx push: - match: '(?=\}|;|,|$)|(?<=\})' pop: true - include: type - include: punctuation-comma - include: punctuation-semicolon - include: type type-operators: - include: typeof-operator - match: '([&|])(?=\s*\{)' captures: 0: keyword.operator.type.tsx push: - match: '(?<=\})' pop: true - include: type-object - match: "[&|]" captures: 0: keyword.operator.type.tsx push: - match: (?=\S) pop: true - match: '(?) captures: 1: punctuation.definition.typeparameters.end.tsx pop: true - include: comment - match: '(?) scope: keyword.operator.assignment.tsx type-paren-or-function-parameters: - match: \( captures: 0: meta.brace.round.tsx push: - meta_scope: meta.type.paren.cover.tsx - match: \) captures: 0: meta.brace.round.tsx pop: true - match: |- (?x)(?:(?) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))))) captures: 1: storage.modifier.tsx 2: keyword.operator.rest.tsx 3: entity.name.function.tsx variable.language.this.tsx 4: entity.name.function.tsx 5: keyword.operator.optional.tsx - match: '(?x)(?:(?:&|{\?]|$|;|^\s*$|(?:^\s*(?:abstract|async|class|const|declare|enum|export|function|import|interface|let|module|namespace|return|type|var)\b))' pop: true - include: expression undefined-literal: - match: '(?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.variable.tsx variable.other.constant.tsx entity.name.function.tsx push: - meta_scope: meta.var-single-variable.expr.tsx - match: '(?=$|^|[;,=}]|((?) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) )) | # typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) => (:\s*( (<) | ([(]\s*( ([)]) | (\.\.\.) | ([_$[:alnum:]]+\s*( ([:,?=])| ([)]\s*=>) )) )) )) | (:\s*(?\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*))))))) | (:\s*(=>|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(<[^<>]*>)|[^<>(),=])+=\s*( ((async\s+)?( (function\s*[(<*]) | (function\s+) | ([_$[:alpha:]][_$[:alnum:]]*\s*=>) )) | ((async\s*)?( ((<\s*$)|([\(]\s*((([\{\[]\s*)?$)|((\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})\s*((:\s*\{?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))|((\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])\s*((:\s*\[?$)|((\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+\s*)?=\s*)))))) | # sure shot arrow functions even if => is on new line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? [(]\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)* ( ([)]\s*:) | # (): ((\.\.\.\s*)?[_$[:alpha:]][_$[:alnum:]]*\s*:) # [(]param: | [(]...param: ) ) | ( [<]\s*[_$[:alpha:]][_$[:alnum:]]*\s+extends\s*[^=>] # < typeparam extends ) | # arrow function possible to detect only with => on same line ( (<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<]|\<\s*([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\]))([^=<>]|=[^<])*\>)*\>)*>\s*)? # typeparameters \(\s*(\/\*([^\*]|(\*[^\/]))*\*\/\s*)*(([_$[:alpha:]]|(\{([^\{\}]|(\{([^\{\}]|\{[^\{\}]*\})*\}))*\})|(\[([^\[\]]|(\[([^\[\]]|\[[^\[\]]*\])*\]))*\])|(\.\.\.\s*[_$[:alpha:]]))([^()\'\"\`]|(\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))|(\'([^\'\\]|\\.)*\')|(\"([^\"\\]|\\.)*\")|(\`([^\`\\]|\\.)*\`))*)?\) # parameters (\s*:\s*([^<>\(\)\{\}]|\<([^<>]|\<([^<>]|\<[^<>]+\>)+\>)+\>|\([^\(\)]+\)|\{[^\{\}]+\})+)? # return type \s*=> # arrow operator ) )) ))) captures: 1: meta.definition.variable.tsx entity.name.function.tsx 2: keyword.operator.definiteassignment.tsx push: - meta_scope: meta.var-single-variable.expr.tsx - match: '(?=$|^|[;,=}]|((?\s*$) captures: 1: keyword.operator.assignment.tsx push: - match: '(?=$|^|[,);}\]]|((?])' scope: meta.include.verilog captures: 1: meta.preprocessor.verilog 2: entity.name.type.include.verilog - match: '^\s*(`ifdef|`ifndef|`undef|`define)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b' scope: meta.preprocessor.ifdef.verilog captures: 1: meta.preprocessor.verilog 2: constant.other.define.verilog - match: '`(celldefine|default_nettype|define|else|elsif|endcelldefine|endif|ifdef|ifndef|include|line|nounconnected_drive|resetall|timescale|unconnected_drive|undef)\b' scope: meta.preprocessor.verilog - match: "[.][_a-zA-Z0-9]+" scope: meta.module.parameters.verilog - match: '`\b([a-zA-Z_][a-zA-Z0-9_]*)\b' scope: constant.other.define.verilog - include: comments - match: \b(endmodule|endfunction|endprimitive)\b scope: storage.type.verilog - match: '^\s*\b([a-zA-Z_][a-zA-Z0-9_]*)\b\s*(:)\s*' scope: meta.case.verilog captures: 1: entity.name.state.verilog 2: keyword.operator.bitwise.verilog - include: all-types - match: (==|===|!=|!==|<=|>=|<|>) scope: keyword.operator.comparison.verilog - match: (\-|\+|\*|\/|%) scope: keyword.operator.arithmetic.verilog - match: (!|&&|\|\|) scope: keyword.operator.logical.verilog - match: (&|\||\^|~|<<|>>|\?|:) scope: keyword.operator.bitwise.verilog - match: "({|})" scope: keyword.operator.parenthesis.curly.verilog - match: (\(|\)) scope: keyword.operator.parenthesis.round.verilog - match: '(\[|\])' scope: keyword.operator.parenthesis.square.verilog - match: "([;,])" scope: keyword.delimiter.verilog - match: (#|@|=) scope: keyword.other.verilog - match: '\b(output|input|inout|and|nand|nor|or|xor|xnor|buf|not|bufif[01]|notif[01]|r?[npc]mos|tran|r?tranif[01]|pullup|pulldown)\b' scope: support.type.verilog - match: '((\b\d+)?''s?([bB]\s*(([0-1_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[oO]\s*(([0-7_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[dD]\s*(([0-9_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*))|[hH]\s*(([0-9a-fA-F_xXzZ?]+)|(`[A-Z]+[_0-9a-zA-Z]*)))((e|E)(\+|-)?[0-9]+)?\b)|(\b\d+\b)' scope: constant.numeric.verilog - include: strings - match: '\$\b([a-zA-Z_][a-zA-Z0-9_]*)\b' scope: support.function.verilog all-types: - include: storage-type-verilog - include: storage-modifier-verilog comments: - match: /\* captures: 0: punctuation.definition.comment.verilog push: - meta_scope: comment.block.verilog - match: \*/ captures: 0: punctuation.definition.comment.verilog pop: true - match: (//).*$\n? scope: comment.line.double-slash.verilog captures: 1: punctuation.definition.comment.verilog storage-modifier-verilog: - match: '\b(signed|unsigned|small|medium|large|supply[01]|strong[01]|pull[01]|weak[01]|highz[01])\b' scope: storage.modifier.verilog storage-type-verilog: - match: '\b(wire|tri|tri[01]|supply[01]|wand|triand|wor|trior|trireg|reg|parameter|integer)\b' scope: storage.type.verilog strings: - match: '"' captures: 0: punctuation.definition.string.begin.verilog push: - meta_scope: string.quoted.double.verilog - match: '"' captures: 0: punctuation.definition.string.end.verilog pop: true - match: \\. scope: constant.character.escape.verilog - match: "'" captures: 0: punctuation.definition.string.begin.verilog push: - meta_scope: string.quoted.single.verilog - match: "'" captures: 0: punctuation.definition.string.end.verilog pop: true - match: \\. scope: constant.character.escape.verilog ================================================ FILE: assets/syntaxes/02_Extra/VimHelp.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html scope: source.vimhelp file_extensions: # shortname - vimhelp # $VIMRUNTIME/syntax/help.vim contexts: main: - match: '(?<=^\s*)(vim?|ex):\s*([a-z]+(=[^\s:]+)?(\s+|:))+' scope: comment.line.modeline.vimhelp - match: '^[-A-Z .][-A-Z0-9 .()_]*(?=\s+\*|$)' scope: markup.heading.headline.vimhelp - match: '^(===.*===)$' captures: 1: punctuation.definition.heading.1.setext.vimhelp push: - meta_scope: markup.heading.1.setext.vimhelp - match: '\t| ' pop: true - match: '^(---.*---)$' captures: 1: punctuation.definition.heading.2.setext.vimhelp push: - meta_scope: markup.heading.2.setext.vimhelp - match: '\t| ' pop: true - match: '(?:^| )(>)$' captures: 1: punctuation.definition.blockquote.begin.vimhelp push: - meta_scope: markup.quote.vimhelp - match: '^(<)' captures: 1: punctuation.definition.blockquote.end.vimhelp pop: true - match: '^(?=\S)' pop: true - match: '(?.,]+)(\})' captures: 1: punctuation.definition.constant.begin.vimhelp 2: constant.numeric.vimhelp 3: punctuation.definition.constant.end.vimhelp - match: '\[(range|line|count|offset|\+?cmd|(\+|-|)num|\+\+opt)\]' scope: constant.numeric.vimhelp - match: '\[(arg(uments)?|ident|addr|group)\]' scope: constant.numeric.vimhelp - match: '\[(readonly|fifo|socket|converted|crypted)\]' scope: constant.numeric.vimhelp - match: '<[-a-zA-Z0-9_]+>' scope: markup.underline.link.key.vimhelp - match: '<[SCM]-.>' scope: markup.underline.link.key.vimhelp - match: 'CTRL-((SHIFT-)?.|Break|PageUp|PageDown|Insert|Del|\{char\})' scope: markup.underline.link.key.vimhelp - match: '(META|ALT)-.' scope: markup.underline.link.key.vimhelp - match: '\b(((https?|ftp|gopher)://|(mailto|file|news):)[^'' <>"]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^'' <>"]+)[a-zA-Z0-9/]' scope: markup.underline.link.url.vimhelp ================================================ FILE: assets/syntaxes/02_Extra/apt-source-list.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/syntax.html name: debsources file_extensions: - sources.list scope: text.apt-source-list contexts: main: - include: comments - match: ^[\w-]+ scope: constant.language.apt-source-list - match: \w+://\S+ scope: markup.underline.link.apt-source-list push: distribution - match: \bmain\b scope: support.class.apt-source-list - match: \buniverse\b scope: support.constant.apt-source-list - match: \brestricted\b scope: storage.modifier.apt-source-list - match: \bmultiverse\b scope: keyword.other.apt-source-list - match: '[\w-]+' scope: constant.other.apt-source-list comments: - match: '#' scope: punctuation.definition.comment.apt-source-list push: line_comment line_comment: - meta_scope: comment.line.apt-source-list - match: $ pop: true distribution: - match: \S+ scope: support.type.apt-source-list pop: 1 - match: $ pop: 1 ================================================ FILE: assets/syntaxes/02_Extra/gnuplot.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: gnuplot file_extensions: - gp - gpl - gnuplot - gnu - plot - plt scope: source.gnuplot contexts: main: - include: number - include: string_single - include: string_double - match: '\b(for)\b\s*(\[)' comment: | gnuplot iteration statement. There are two forms: numeric [n = 1:2{:inc}] string based [str in "x y z"] but both can also iterate over lists etc, so this is kept loose. captures: 1: keyword.other.iteration.gnuplot 2: punctuation.definition.range.begin.gnuplot push: - meta_scope: meta.structure.iteration.gnuplot - match: '\]' captures: 0: punctuation.definition.range.end.gnuplot pop: true - include: number - include: operator - include: string_double - include: string_single - match: ":" scope: punctuation.separator.range.gnuplot - match: '\b([a-zA-Z]\w*)\b\s*(=|in)' scope: variable-assignment.range.gnuplot - match: '(?i:[^\s(pi|e)\]])' scope: invalid.illegal.expected-range-separator.gnuplot - match: '\[' comment: "gnuplot range statement [a:b]. Lots of things are legal, still more make no sense!" captures: 0: punctuation.definition.range.begin.gnuplot push: - meta_scope: meta.structure.range.gnuplot - match: '\]' captures: 0: punctuation.definition.range.end.gnuplot pop: true - include: number - include: operator - match: ":" scope: punctuation.separator.range.gnuplot - match: '(?i:[^\s(pi|e)\]])' scope: invalid.illegal.expected-range-separator.gnuplot - match: \\. scope: constant.character.escape.gnuplot - match: '(?|>=|<|<=|&|&&|:|\||\|\||\+|-|\*|\.\*|/|\./|\\|\.\\|\^|\.\^)\s* comment: Operator symbols scope: keyword.operator.symbols.matlab string_double: - match: '"' captures: 0: punctuation.definition.string.begin.gnuplot push: - meta_scope: string.quoted.double.gnuplot - match: '"' captures: 0: punctuation.definition.string.end.gnuplot pop: true - match: '\\[\$`"\\\n]' scope: constant.character.escape.gnuplot string_single: - match: "'" captures: 0: punctuation.definition.string.begin.gnuplot push: - meta_scope: string.quoted.single.gnuplot - match: "'" captures: 0: punctuation.definition.string.end.gnuplot pop: true ================================================ FILE: assets/syntaxes/02_Extra/log.sublime-syntax ================================================ %YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html file_extensions: - log scope: text.log variables: ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) hours_minutes_seconds: (?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d) error: \b(?i:fail(?:ure|ed)?|error|exception|fatal|critical)\b warning: \b(?i:warn(?:ing)?)\b info: \b(?i:info)\b debug: \b(?i:debug)\b contexts: main: - include: log_level_lines - include: main_without_log_level_line main_without_log_level_line: - match: (\w+)(=) captures: 1: variable.parameter.log 2: keyword.operator.assignment.log - match: (')([^']*)(') scope: string.quoted.single.log captures: 1: punctuation.definition.string.begin.log 3: punctuation.definition.string.end.log - match: \" captures: 1: punctuation.definition.string.begin.log push: double_quoted_string - include: dates - include: ip_addresses - include: numbers - include: log_levels #- include: scope:text.html.markdown#autolink-inet - match: \b\w+:/{2,3} scope: markup.underline.link.scheme.log push: url-host log_level_lines: - match: (?=.*{{error}}) push: - error_line_meta - main_pop_at_eol - match: (?=.*{{warning}}) push: - warning_line_meta - main_pop_at_eol - match: (?=.*{{info}}) push: - info_line_meta - main_pop_at_eol - match: (?=.*{{debug}}) push: - debug_line_meta - main_pop_at_eol log_levels: - match: '{{error}}' scope: markup.error.log - match: '{{warning}}' scope: markup.warning.log - match: '{{info}}' scope: markup.info.log - match: '{{debug}}' scope: markup.info.log error_line_meta: - meta_scope: meta.annotation.error-line.log - include: immediately_pop warning_line_meta: - meta_scope: meta.annotation.warning-line.log - include: immediately_pop info_line_meta: - meta_scope: meta.annotation.info-line.log - include: immediately_pop debug_line_meta: - meta_scope: meta.annotation.debug-line.log - include: immediately_pop immediately_pop: - match: '' pop: true pop_at_eol: - match: $ pop: true main_pop_at_eol: - include: main_without_log_level_line - include: pop_at_eol dates: - match: \b\d{4}-\d{2}-\d{2}(?=\b|T) scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log push: maybe_date_time_separator - match: \b\d{4}/\d{2}/\d{2}(?=\b|T) scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log push: maybe_date_time_separator - match: \b(?={{hours_minutes_seconds}}) push: time time: - match: (?:{{hours_minutes_seconds}})(?:(\.)\d{3})?\b scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log captures: 1: punctuation.separator.decimal.log - include: immediately_pop maybe_date_time_separator: - match: T(?={{hours_minutes_seconds}}) scope: meta.date.log meta.time.log keyword.other.log set: time - include: immediately_pop ip_addresses: - match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b) push: - meta_scope: meta.ipaddress.v4.log meta.number.integer.decimal.log - match: \d+ scope: constant.numeric.value.log - match: \. scope: punctuation.separator.sequence.log - include: immediately_pop - match: (?=(?:\h{0,4}:){2,6}\h{1,4}\b) push: - meta_scope: meta.ipaddress.v6.log meta.number.integer.hexadecimal.log - match: \h{1,4} scope: constant.numeric.value.log - match: ':' scope: punctuation.separator.sequence.log - include: immediately_pop numbers: - match: \b(0x)(\h+)(?:(\.)(\h+))?\b scope: meta.number.float.hexadecimal.log captures: 1: constant.numeric.base.log 2: constant.numeric.value.log 3: constant.numeric.value.log punctuation.separator.decimal.log 4: constant.numeric.value.log - match: \b\d+(\.)\d+\b scope: meta.number.float.log constant.numeric.value.log captures: 1: punctuation.separator.decimal.log - match: \b\d+\b scope: meta.number.integer.log constant.numeric.value.log url-host: - meta_content_scope: markup.underline.link.host.log - match: \[ scope: punctuation.section.brackets.begin.log push: - match: \] scope: punctuation.section.brackets.end.log pop: true - include: ip_addresses - match: '[^:/\s]+' - match: '' set: url-after-host url-after-host: - match: (:)(\d+) scope: markup.underline.link.port.log captures: 1: punctuation.separator.mapping.port.log 2: constant.numeric.value.log #- include: scope:text.html.markdown#url-escaped-chars - match: (%)\h{2} scope: markup.underline.link.path.log constant.character.escape.url.log captures: 1: punctuation.definition.escape.log # After a valid domain, zero or more non-space non-< characters may follow - match: (?=[?!.,:*_~]*[\s<]) # Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will not be considered part of the autolink, though they may be included in the interior of the link pop: true - match: \( # When an autolink ends in ), we scan the entire autolink for the total number of parentheses. If there is a greater number of closing parentheses than opening ones, we don’t consider the last character part of the autolink, in order to facilitate including an autolink inside a parenthesis push: - meta_scope: markup.underline.link.path.log - match: (?=[?!.,:*_~]*[\s<]) pop: true - match: \) pop: true - match: (?=\)[?!.,:*_~]*[\s<]) pop: true - match: '[^?!.,:*_~\s<&()%]+|\S' scope: markup.underline.link.path.log - include: immediately_pop double_quoted_string: - meta_scope: string.quoted.double.log - match: \\" scope: constant.character.escape.log - match: \\n scope: constant.character.escape.log - match: \" scope: punctuation.definition.string.end.log pop: true ================================================ FILE: assets/syntaxes/02_Extra/show-nonprintable.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: Highlight non-printables file_extensions: - show-nonprintable scope: whitespace contexts: main: - match: "·" scope: support.function.show-nonprintable.space - match: "├─*┤" scope: constant.character.escape.show-nonprintable.tab - match: "↹" scope: constant.character.escape.show-nonprintable.tab - match: "␊" scope: keyword.operator.show-nonprintable.line-feed - match: "␍" scope: string.show-nonprintable.carriage-return - match: "␀" scope: entity.other.attribute-name.show-nonprintable.null - match: "␇" scope: entity.other.attribute-name.show-nonprintable.bell - match: "␛" scope: entity.other.attribute-name.show-nonprintable.escape - match: "␈" scope: entity.other.attribute-name.show-nonprintable.backspace - match: "\\\\x[A-Z0-9][A-Z0-9]" scope: comment.block.show-nonprintable.backspace - match: "\\\\u\\{[a-z0-9]+\\}" scope: comment.block.show-nonprintable.backspace ================================================ FILE: assets/syntaxes/02_Extra/syntax_test_csv.csv ================================================ # SYNTAX TEST "CSV.sublime-syntax" Forename,Surname,House No.,Street,City,Postcode #^^^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^^^^^^^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^ meta.field-4 # ^ punctuation.separator.sequence # ^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 John,Doe,87,Logon Road,Citiville,TU43 6GH #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^^^^^ meta.field-4 # ^ punctuation.separator.sequence # ^^^^^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 Jane,Doe,22,"""Fun"" Street","The City, County",FA90 1XA #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^^^^^^^^^^^ meta.field-4 string.quoted.double # ^^ constant.character.escape # ^^ constant.character.escape # ^ punctuation.separator.sequence # ^ meta.field-1 string.quoted.double punctuation.definition.string.begin # ^^^^^^^^^^^^^^^^^ meta.field-1 string.quoted.double # ^ meta.field-1 string.quoted.double punctuation.definition.string.end # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 Fred,Bloggs,"19","Street #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^^ meta.field-3 string.quoted.double # ^ punctuation.separator.sequence # ^ meta.field-4 punctuation.definition.string.begin # ^^^^^^^^ meta.field-4 string.quoted.double Spanning Multiple "" #^^^^^^^^^^^^^^^^^^^^ meta.field-4 string.quoted.double # ^^ constant.character.escape Lines",Citee,P0stc0d3 #^^^^^ meta.field-4 string.quoted.double # ^ meta.field-4 punctuation.definition.string.end # ^ punctuation.separator.sequence # ^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 ================================================ FILE: assets/syntaxes/02_Extra/syntax_test_helphelp.txt ================================================ # SYNTAX TEST "VimHelp.sublime-syntax" *helphelp.txt* Nvim # <- punctuation.definition.constant.begin #^^^^^^^^^^^^ entity.name.reference.link # ^ punctuation.definition.constant.end VIM REFERENCE MANUAL by Bram Moolenaar # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variable.language Help on help files *helphelp* Type |gO| to see the table of contents. # ^ punctuation.definition.link.begin # ^^ markup.underline.link # ^ punctuation.definition.link.end ============================================================================== #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ punctuation.definition.heading.1.setext 1. Help commands *online-help* #^^^^^^^^^^^^^^^ markup.heading.1.setext *help* ** *:h* *:help* ** *i_* *i_* or #^^^^^ markup.underline.link.key :h[elp] Open a window and display the help file in read-only mode. If there is a help window open already, use that one. Otherwise, if the current window uses the full width of the screen or is at least 80 characters wide, the help window will appear just above the current window. Otherwise the new window is put at the very top. The 'helplang' option is used to select a language, if # ^ punctuation.definition.link.option.begin # ^^^^^^^^ markup.underline.link.option # ^ punctuation.definition.link.option.end the main help file is available in several languages. Type |gO| to see the table of contents. *{subject}* *E149* *E661* :h[elp] {subject} Like ":help", additionally jump to the tag {subject}. For example: > :help options < {subject} can include wildcards such as "*", "?" and # ^ punctuation.definition.constant.begin # ^^^^^^^ constant.numeric # ^ punctuation.definition.constant.end "[a-z]": :help z? jump to help for any "z" command :help z. jump to the help for "z." But when a tag exists it is taken literally: :help :? jump to help for ":?" If there is no full match for the pattern, or there are several matches, the "best" match will be used. A sophisticated algorithm is used to decide which match is better than another one. These items are considered in the computation: - A match with same case is much better than a match with different case. - A match that starts after a non-alphanumeric character is better than a match in the middle of a word. - A match at or near the beginning of the tag is better than a match further on. - The more alphanumeric characters match, the better. - The shorter the length of the match, the better. The 'helplang' option is used to select a language, if the {subject} is available in several languages. To find a tag in a specific language, append "@ab", where "ab" is the two-letter language code. See |help-translated|. Note that the longer the {subject} you give, the less matches will be found. You can get an idea how this all works by using commandline completion (type CTRL-D # ^^^^^^ markup.underline.link.key after ":help subject" |c_CTRL-D|). If there are several matches, you can have them listed by hitting CTRL-D. Example: > :help cont < Instead of typing ":help CTRL-V" to search for help for CTRL-V you can type: > :help ^V < This also works together with other characters, for example to find help for CTRL-V in Insert mode: > :help i^V < It is also possible to first do ":help" and then use ":tag {pattern}" in the help window. The ":tnext" command can then be used to jump to other matches, "tselect" to list matches and choose one. > :help index :tselect /.*mode < When there is no argument you will see matches for "help", to avoid listing all possible matches (that would be very slow). The number of matches displayed is limited to 300. The `:help` command can be followed by '|' and another command, but you don't need to escape the '|' inside a help command. So these both work: > :help | :help k| only < Note that a space before the '|' is seen as part of # ^^^^ constant.other.note the ":help" argument. You can also use or to separate the help command from a following command. You need to type CTRL-V first to insert the or . Example: > :help soonly < :h[elp]! [subject] Like ":help", but in non-English help files prefer to find a tag in a file with the same language as the current file. See |help-translated|. *:helpc* *:helpclose* :helpc[lose] Close one help window, if there is one. Vim will try to restore the window layout (including cursor position) to the same layout it was before opening the help window initially. This might cause triggering several autocommands. *:helpg* *:helpgrep* :helpg[rep] {pattern}[@xx] Search all help text files and make a list of lines in which {pattern} matches. Jumps to the first match. The optional [@xx] specifies that only matches in the "xx" language are to be found. You can navigate through the matches with the |quickfix| commands, e.g., |:cnext| to jump to the next one. Or use |:cwindow| to get the list of matches in the quickfix window. {pattern} is used as a Vim regexp |pattern|. 'ignorecase' is not used, add "\c" to ignore case. Example for case sensitive search: > :helpgrep Uganda < Example for case ignoring search: > :helpgrep uganda\c < Example for searching in French help: > :helpgrep backspace@fr < The pattern does not support line breaks, it must match within one line. You can use |:grep| instead, but then you need to get the list of help files in a complicated way. Cannot be followed by another command, everything is used as part of the pattern. But you can use |:execute| when needed. Compressed help files will not be searched (Fedora compresses the help files). *:lh* *:lhelpgrep* :lh[elpgrep] {pattern}[@xx] Same as ":helpgrep", except the location list is used instead of the quickfix list. If the help window is already opened, then the location list for that window is used. Otherwise, a new help window is opened and the location list for that window is set. The location list for the current window is not changed then. *:exu* *:exusage* :exu[sage] Show help on Ex commands. Added to simulate the Nvi command. *:viu* *:viusage* :viu[sage] Show help on Normal mode commands. Added to simulate the Nvi command. When no argument is given to |:help| the file given with the 'helpfile' option will be opened. Otherwise the specified tag is searched for in all "doc/tags" files in the directories specified in the 'runtimepath' option. If you would like to open the help in the current window, see this tip: |help-curwin|. The initial height of the help window can be set with the 'helpheight' option (default 20). *help-buffer-options* When the help buffer is created, several local options are set to make sure the help text is displayed as it was intended: 'iskeyword' nearly all ASCII chars except ' ', '*', '"' and '|' 'foldmethod' "manual" 'tabstop' 8 'arabic' off 'binary' off 'buflisted' off 'cursorbind' off 'diff' off 'foldenable' off 'list' off 'modifiable' off 'number' off 'relativenumber' off 'rightleft' off 'scrollbind' off 'spell' off Jump to specific subjects by using tags. This can be done in two ways: - Use the "CTRL-]" command while standing on the name of a command or option. This only works when the tag is a keyword. "" and "g" work just like "CTRL-]". - use the ":ta {subject}" command. This also works with non-keyword characters. Use CTRL-T or CTRL-O to jump back. Use ":q" to close the help window. If there are several matches for an item you are looking for, this is how you can jump to each one of them: 1. Open a help window 2. Use the ":tag" command with a slash prepended to the tag. E.g.: > :tag /min 3. Use ":tnext" to jump to the next matching tag. It is possible to add help files for plugins and other items. You don't need to change the distributed help files for that. See |add-local-help|. To write a local help file, see |write-local-help|. Note that the title lines from the local help files are automagically added to the "LOCAL ADDITIONS" section in the "help.txt" help file |local-additions|. This is done when viewing the file in Vim, the file itself is not changed. It is done by going through all help files and obtaining the first line of each file. The files in $VIMRUNTIME/doc are skipped. *help-xterm-window* If you want to have the help in another xterm window, you could use this command: > :!xterm -e vim +help & < *:helpt* *:helptags* *E150* *E151* *E152* *E153* *E154* *E670* *E856* :helpt[ags] [++t] {dir} Generate the help tags file(s) for directory {dir}. When {dir} is ALL then all "doc" directories in 'runtimepath' will be used. All "*.txt" and "*.??x" files in the directory and sub-directories are scanned for a help tag definition in between stars. The "*.??x" files are for translated docs, they generate the "tags-??" file, see |help-translated|. The generated tags files are sorted. When there are duplicates an error message is given. An existing tags file is silently overwritten. The optional "++t" argument forces adding the "help-tags" tag. This is also done when the {dir} is equal to $VIMRUNTIME/doc. To rebuild the help tags in the runtime directory (requires write permission there): > :helptags $VIMRUNTIME/doc < ============================================================================== 2. Translated help files *help-translated* It is possible to add translated help files, next to the original English help files. Vim will search for all help in "doc" directories in 'runtimepath'. At this moment translations are available for: Chinese - multiple authors French - translated by David Blanchet Italian - translated by Antonio Colombo Japanese - multiple authors Polish - translated by Mikolaj Machowski Russian - translated by Vassily Ragosin See the Vim website to find them: http://www.vim.org/translations.php A set of translated help files consists of these files: help.abx howto.abx ... tags-ab "ab" is the two-letter language code. Thus for Italian the names are: help.itx howto.itx ... tags-it The 'helplang' option can be set to the preferred language(s). The default is set according to the environment. Vim will first try to find a matching tag in the preferred language(s). English is used when it cannot be found. To find a tag in a specific language, append "@ab" to a tag, where "ab" is the two-letter language code. Example: > :he user-manual@it :he user-manual@en The first one finds the Italian user manual, even when 'helplang' is empty. The second one finds the English user manual, even when 'helplang' is set to "it". When using command-line completion for the ":help" command, the "@en" extension is only shown when a tag exists for multiple languages. When the tag only exists for English "@en" is omitted. When the first candidate has an "@ab" extension and it matches the first language in 'helplang' "@ab" is also omitted. When using |CTRL-]| or ":help!" in a non-English help file Vim will try to find the tag in the same language. If not found then 'helplang' will be used to select a language. Help files must use latin1 or utf-8 encoding. Vim assumes the encoding is utf-8 when finding non-ASCII characters in the first line. Thus you must translate the header with "For Vim version". The same encoding must be used for the help files of one language in one directory. You can use a different encoding for different languages and use a different encoding for help files of the same language but in a different directory. Hints for translators: - Do not translate the tags. This makes it possible to use 'helplang' to specify the preferred language. You may add new tags in your language. - When you do not translate a part of a file, add tags to the English version, using the "tag@en" notation. - Make a package with all the files and the tags file available for download. Users can drop it in one of the "doc" directories and start use it. Report this to Bram, so that he can add a link on www.vim.org. - Use the |:helptags| command to generate the tags files. It will find all languages in the specified directory. ============================================================================== 3. Writing help files *help-writing* For ease of use, a Vim help file for a plugin should follow the format of the standard Vim help files, except for the first line. If you are writing a new help file it's best to copy one of the existing files and use it as a template. The first line in a help file should have the following format: *plugin_name.txt* {short description of the plugin} The first field is a help tag where ":help plugin_name" will jump to. The remainder of the line, after a Tab, describes the plugin purpose in a short way. This will show up in the "LOCAL ADDITIONS" section of the main help file. Check there that it shows up properly: |local-additions|. If you want to add a version number or last modification date, put it in the second line, right aligned. At the bottom of the help file, place a Vim modeline to set the 'textwidth' and 'tabstop' options and the 'filetype' to "help". Never set a global option in such a modeline, that can have undesired consequences. TAGS To define a help tag, place the name between asterisks (*tag-name*). The tag-name should be different from all the Vim help tag names and ideally should begin with the name of the Vim plugin. The tag name is usually right aligned on a line. When referring to an existing help tag and to create a hot-link, place the name between two bars (|) eg. |help-writing|. When referring to a Vim command and to create a hot-link, place the name between two backticks, eg. inside `:filetype`. You will see this is highlighted as a command, like a code block (see below). When referring to a Vim option in the help file, place the option name between two single quotes, eg. 'statusline' When referring to any other technical term, such as a filename or function parameter, surround it in backticks, eg. `~/.path/to/init.vim`. HIGHLIGHTING To define a column heading, use a tilde character at the end of the line. This will highlight the column heading in a different color. E.g. Column heading~ #^^^^^^^^^^^^^ markup.heading.header # ^ punctuation.definition.keyword To separate sections in a help file, place a series of '=' characters in a line starting from the first column. The section separator line is highlighted differently. To quote a block of ex-commands verbatim, place a greater than (>) character at the end of the line before the block and a less than (<) character as the first non-blank on a line following the block. Any line starting in column 1 also implicitly stops the block of ex-commands before it. E.g. > function Example_Func() echo "Example" endfunction < The following are highlighted differently in a Vim help file: - a special key name expressed either in <> notation as in , or as a Ctrl character as in CTRL-X - anything between {braces}, e.g. {lhs} and {rhs} The word "Note", "Notes" and similar automagically receive distinctive highlighting. So do these: *Todo something to do *Error something wrong You can find the details in $VIMRUNTIME/syntax/help.vim vim:tw=78:ts=8:noet:ft=help:norl: #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.modeline ================================================ FILE: assets/syntaxes/02_Extra/syntax_test_man.man ================================================ # SYNTAX TEST "Manpage.sublime-syntax" SOMETHING(8) System Manager's Manual SOMETHING(8) # ^^^^^ meta.preprocessor # ^^^^^^^^^^^^^^^^^^^^^^^ markup.heading.title # ^^^^^^^ meta.preprocessor NAME #^^^ markup.heading.other example - do something useful SYNOPSIS example [options] [--home DIR] [--shell SHELL] [--no-create-home] # ^ punctuation.section.brackets.begin # ^^^^^^ entity.name.command-line-option # ^^^ variable.parameter # ^ punctuation.section.brackets.end # ^ punctuation.section.brackets.begin # ^^^^^^^ entity.name.command-line-option # ^^^^^ variable.parameter # ^ punctuation.section.brackets.end # ^ punctuation.section.brackets.begin # ^^^^^^^^^^^^^^^^ entity.name.command-line-option # ^ punctuation.section.brackets.end [-u | --set-upstream] [-o | --push-option=] # ^ punctuation.section.brackets.begin # ^^ entity.name.command-line-option # ^ keyword.operator.logical # ^^^^^^^^^^^^^^ entity.name.command-line-option # ^ punctuation.section.brackets.end # ^^^^^^^^^^^^^ entity.name.command-line-option [--force-with-lease[=[:]]] # ^ punctuation.section.brackets.begin # ^^^^^^^^^^^^^^^^^^ entity.name.command-line-option # ^ punctuation.section.brackets.begin # ^ keyword.operator # ^^^^^^^ variable.parameter # ^ punctuation.section.brackets.begin # ^^^^^^ variable.parameter # ^^^ punctuation.section.brackets.end example --system [options] # ^^^^^^^^ entity.name COMMON OPTIONS [--quiet] [--debug] [--help|-h] [--version] [--conf FILE] /* According to POSIX.1-2001, POSIX.1-2008 */ # ^^ source.c comment.block punctuation.definition.comment #include # ^^^^^^^^ source.c meta.preprocessor.include keyword.control.import.include struct timeval { # ^^^^^^ source.c storage.type time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; DESCRIPTION example does something useful in relation to the command line options and configuration information in /etc/example.conf. OPTIONS --conf FILE # ^^^^^^ entity.name.command-line-option #^^^^^^ - variable - entity - markup # ^^^^ variable.parameter Use FILE instead of /etc/example.conf. # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable - entity --disabled-login Do not run passwd to set the password. The user won't be able to use her account until the password is set. --disabled-password Like --disabled-login, but logins are still possible (for exam- # ^^^^^^^^^^^^^^^^ entity.name #^^^^^^^^^^^^^^^^^^ - entity - variable - markup # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - entity - variable - markup ple using SSH RSA keys) but not using password authentication. --help Display brief instructions. # ^^^^^^ entity.name.command-line-option # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable.parameter --home DIR # ^^^^^^ entity.name.command-line-option # ^^^ variable.parameter # ^ - variable - entity - markup Use DIR as the user's home directory, rather than the default specified by the configuration file. If the directory does not exist, it is created and skeleton files are copied. --[no-]signed, --signed=(true|false|if-asked) # ^^^^^^^^^^^^^ entity.name.command-line-option # ^ punctuation.separator # ^^^^^^^^ entity.name.command-line-option # ^ keyword.operator # ^ - variable # ^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^^^^^ variable.parameter # ^ - variable --no-recurse-submodules, --recurse-submodules=check|on-demand|only|no # ^^^^^^^^^^^^^^^^^^^^^^^ entity.name.command-line-option # ^ punctuation.separator # ^^^^^^^^^^^^^^^^^^^^ entity.name.command-line-option # ^ keyword.operator # ^^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^^^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^ variable.parameter # ^ keyword.operator.logical # ^^ variable.parameter May be used to make sure all submodule commits used by the -c, -C NUM, --context[=NUM] # ^^ entity.name.command-line-option # ^ punctuation.separator # ^^ entity.name.command-line-option # ^^^ variable.parameter # ^ punctuation.separator # ^^^^^^^^^ entity.name.command-line-option # ^^^^^^^ - entity.name # ^ keyword.operator # ^^^ variable.parameter # ^^ - variable output NUM (default 3) lines of copied context - This is not really a switch, but indicates that standard input # ^ entity.name.command-line-option.man # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - entity - variable is coming from a file or a pipe and not interactively from the command line. EXAMPLE #include # ^^^^^^^^ source.c meta.preprocessor.include keyword.control.import.include (This is not C code.) # ^^^^^^^^^^^^^^^^^^^^^^ - source.c struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; # ^ source.c punctuation.terminator The corresponding argument for pselect() has the following type: #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - source.c #define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) # ^ source.c meta.preprocessor.macro meta.group punctuation.section.group.end ENVIRONMENT $SYSTEMD_LOG_LEVEL # ^ punctuation.definition.variable # ^^^^^^^^^^^^^^^^^ constant.other systemd reads the log level from this environment variable. This can be overridden with --log-level=. ENVIRONMENT VARIABLES Various Git commands use the following environment variables: The Git Repository These environment variables apply to all core Git commands. Nb: it is worth noting that they may be used/overridden by SCMS sitting above Git so take care if using a foreign front-end. GIT_INDEX_FILE # ^^^^^^^^^^^^^^ support.constant.environment-variable This environment allows the specification of an alternate index file. If not specified, the default of $GIT_DIR/index is used. GIT_INDEX_VERSION # ^^^^^^^^^^^^^^^^^ support.constant.environment-variable This environment variable allows the specification of an index version for new repositories. It won’t affect existing index files. By default index file version 2 or 3 is used. See git-update- index(1) for more information. COMMANDS This section only lists general commands. For input and output com‐ mands, refer to sway-input(5) and sway-output(5). The following commands may only be used in the configuration file. bar [] # ^^^ entity.name.command # ^ punctuation.section.brackets.begin # ^ punctuation.definition.generic.begin # ^^^^^^ variable.parameter # ^ punctuation.definition.generic.end # ^ punctuation.section.brackets.end # ^ punctuation.definition.generic.begin # ^^^^^^^^^^^^^^^ variable.parameter # ^ punctuation.definition.generic.end For details on bar subcommands, see sway-bar(5). default_orientation horizontal|vertical|auto # ^^^^^^^^^^^^^^^^^^^ entity.name.command # ^^^^^^^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^^^^^ variable.parameter # ^ keyword.operator.logical # ^^^^ variable.parameter Sets the default container layout for tiled containers. include Includes another file from path. path can be either a full path or a path relative to the parent config, and expands shell syntax (see wordexp(3) for details). The same include file can only be included once; subsequent attempts will be ignored. The following commands cannot be used directly in the configuration # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable - entity file. They are expected to be used with bindsym or at runtime through # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable - entity swaymsg(1). border none|normal|csd|pixel [] Set border style for focused window. normal includes a border of thickness n and a title bar. pixel is a border without title bar n pixels thick. Default is normal with border thickness 2. csd is short for client-side-decorations, which allows the client to draw its own decorations. border toggle # ^^^^^^ entity.name.command Cycles through the available border styles. exit # ^^^^ entity.name.command Exit sway and end your Wayland session. floating enable|disable|toggle Make focused view floating, non-floating, or the opposite of what it is now. focus # ^ punctuation.definition.generic.begin # ^^^^^^^^ variable.parameter # ^ punctuation.definition.generic.end # ^^^^^ variable.parameter Moves focus to the container that matches the specified criteria. gaps inner|outer|horizontal|vertical|top|right|bottom|left all|current set|plus|minus|toggle # ^^^ variable.parameter # ^ keyword.operator.logical Changes the inner or outer gaps for either all workspaces or the current workspace. outer gaps can be altered per side with top, right, bottom, and left or per direction with horizontal and verti‐ cal. layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... # ^ punctuation.section.brackets.begin # ^^^^^ variable.parameter # ^ keyword.operator.logical Cycles the layout mode of the focused container through a list of layouts. SEE ALSO The systemd Homepage[11], systemd-system.conf(5), locale.conf(5) # ^^^^^^^^^^^^^^^^^^^ entity.name.function ================================================ FILE: assets/syntaxes/02_Extra/syntax_test_requirements.txt ================================================ # SYNTAX TEST "Requirementstxt.sublime-syntax" # Options # <- punctuation.definition.comment # ^^^^^^^ comment.line --allow-external #^^^^^^^^^^^^^^^ entity.name.function.option --allow-unverified # Freeze packages alabaster==0.7.6 Babel>=2.9.1 docutils==0.12 gevent_subprocess==0.1.2 gitpython==3.0.7 hg-diff==1.2.4 #^^^^^^ variable.parameter.package-name # ^^ keyword.operator.logical # ^^^^^ constant.other Jinja2>=2.8.1 MarkupSafe==0.23 Pygments==2.7.4 pytz==2015.7 six==1.10.0 snowballstemmer==1.2.0 Sphinx==1.3.3 sphinx-rtd-theme==0.1.9 svn==1.0.1 zope.interface==4.2.0 # Examples from PEP508 # c.f. https://www.python.org/dev/peps/pep-0508/ requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < "2.7" # Comment #^^^^^^^ variable.parameter.package-name # ^^^^^^^^^^^^^^^^ variable.function.extra # ^ punctuation.section.braces.begin # ^ punctuation.separator # ^ punctuation.section.braces.end # ^^ keyword.operator.logical # ^^^^^ constant.other # ^^ keyword.operator.logical # ^^^^^ constant.other # ^ punctuation.definition.annotation # ^^^^^^^^^^^^^^^^^^^^^^^^ meta.annotation # ^^^^^^^^^^^^^^ variable.language # ^ keyword.operator.logical # ^ punctuation.definition.string.begin.double # ^^^^^ string.quoted.double.requirements-txt # ^ punctuation.definition.string.end.double # ^^^^^^^^^ comment.line pip @ https://github.com/pypa/pip/archive/1.3.1.zip#sha1=da9234ee9982d4bbb3c72346a6de940a148ea686 # ^ punctuation.definition.keyword # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.url name @ gopher:/foo/com" foobar[quux]<2,>=3; os_name=='a' # VCS repositories -e git+git://git.myproject.org/MyProject#egg=MyProject # Git # <- entity.name.function.option #^ entity.name.function.option # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols # ^^^^^^^^^^^^^^^ - comment.line # ^^^^^ comment.line -e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols -e hg+https://hg.myproject.org/MyProject#egg=MyProject # Mercurial # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols # ^^^^^^^^^^^ comment.line -e hg+http://hg.myproject.org/MyProject@da39a3ee5e6b#egg=MyProject # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols -e svn+http://svn.myproject.org/svn/MyProject/trunk@2019#egg=MyProject # Subversion # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols # ^^^^^^^^^^^^ comment.line -e bzr+ssh://user@myproject.org/MyProject/trunk#egg=MyProject # Bazaar # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols # ^^^^^^^^ comment.line -e bzr+https://bzr.myproject.org/MyProject/trunk@2019#egg=MyProject # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols # Project or archive URL https://github.com/pallets/click/archive/7.0.zip#egg=click #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.url # ^^^^^^^^^^ - comment.line ================================================ FILE: assets/syntaxes/02_Extra/syntax_test_tsv.tsv ================================================ # SYNTAX TEST "CSV.sublime-syntax" Forename Surname House No. Street City Postcode #^^^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^^^^^^^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^ meta.field-4 # ^ punctuation.separator.sequence # ^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 John Doe 87 Logon Road Citiville TU43 6GH #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^^^^^ meta.field-4 # ^ punctuation.separator.sequence # ^^^^^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 Jane Doe 22 """Fun"" Street" "The City County" FA90 1XA #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^ meta.field-3 # ^ punctuation.separator.sequence # ^^^^^^^^^^^^^^^^ meta.field-4 string.quoted.double # ^^ constant.character.escape # ^^ constant.character.escape # ^ punctuation.separator.sequence # ^ meta.field-1 string.quoted.double punctuation.definition.string.begin # ^^^^^^^^^^^^^^^^^ meta.field-1 string.quoted.double # ^ meta.field-1 string.quoted.double punctuation.definition.string.end # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 Fred Bloggs "19" "Street #^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^ meta.field-2 # ^ punctuation.separator.sequence # ^^^ meta.field-3 string.quoted.double # ^ punctuation.separator.sequence # ^ meta.field-4 punctuation.definition.string.begin # ^^^^^^^^ meta.field-4 string.quoted.double Spanning Multiple "" #^^^^^^^^^^^^^^^^^^^^ meta.field-4 string.quoted.double # ^^ constant.character.escape Lines" Citee P0stc0d3 #^^^^^ meta.field-4 string.quoted.double # ^ meta.field-4 punctuation.definition.string.end # ^ punctuation.separator.sequence # ^^^^^ meta.field-1 # ^ punctuation.separator.sequence # ^^^^^^^^ meta.field-2 ================================================ FILE: assets/syntaxes/02_Extra/syslog.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: syslog file_extensions: - syslog scope: text.log.syslog contexts: main: - match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2}) scope: meta.datetime.syslog captures: 1: meta.date.syslog constant.numeric.syslog 2: meta.time.syslog constant.numeric.syslog push: loghost - match: ^ push: text loghost: - match: '[\w:.-]+' scope: entity.other.attribute-name.loghost.syslog set: process process: - match: ([\w.-]+)(?:(\[)(\d+)(\]))?([ :]) captures: 1: support.function.process.syslog 2: punctuation.separator.pid.begin.syslog 3: meta.pid.syslog meta.number.integer.syslog constant.numeric.value.syslog 4: punctuation.separator.pid.end.syslog 5: punctuation.separator.mapping.syslog set: structured-data structured-data: - match: '\[' scope: punctuation.section.mapping.begin.syslog push: structured-data-contents - match: (?=\S) set: text structured-data-contents: - match: \] scope: punctuation.section.mapping.end.syslog pop: true - match: \w+ scope: variable.parameter.syslog - match: = scope: keyword.operator.assignment.syslog push: structured-data-assignment structured-data-assignment: - match: '[^\s\]]+' scope: constant.other.syslog pop: true - match: (?=\]) pop: true text: - match: $ pop: true - match: '<\w+>' scope: constant.language.syslog - match: \b(CMD)\b\s+(\() captures: 1: entity.name.label.syslog 2: punctuation.section.block.begin.syslog embed: scope:source.shell.bash escape: \)$ escape_captures: 0: punctuation.section.block.end.syslog - include: scope:text.log ================================================ FILE: assets/syntaxes/02_Extra/wgsl.sublime-syntax ================================================ %YAML 1.2 --- # http://www.sublimetext.com/docs/syntax.html name: WGSL file_extensions: - wgsl scope: source.wgsl contexts: main: - include: line_comments - include: block_comments - include: keywords - include: attributes - include: functions - include: function_calls - include: constants - include: types - include: variables - include: punctuation attributes: - match: '(@)([A-Za-z_]+)' comment: attribute declaration scope: meta.attribute.wgsl captures: 1: keyword.operator.attribute.at 2: entity.name.attribute.wgsl block_comments: - match: /\*\*/ comment: empty block comments scope: comment.block.wgsl - match: /\*\* comment: block documentation comments push: - meta_scope: comment.block.documentation.wgsl - match: \*/ pop: true - include: block_comments - match: /\*(?!\*) comment: block comments push: - meta_scope: comment.block.wgsl - match: \*/ pop: true - include: block_comments constants: - match: '(-?\b[0-9][0-9]*\.[0-9][0-9]*)([eE][+-]?[0-9]+)?\b' comment: decimal float literal scope: constant.numeric.float.wgsl - match: '-?\b0x[0-9a-fA-F]+\b|\b0\b|-?\b[1-9][0-9]*\b' comment: int literal scope: constant.numeric.decimal.wgsl - match: '\b0x[0-9a-fA-F]+u\b|\b0u\b|\b[1-9][0-9]*u\b' comment: uint literal scope: constant.numeric.decimal.wgsl - match: \b(true|false)\b comment: boolean constant scope: constant.language.boolean.wgsl function_calls: - match: '([A-Za-z0-9_]+)(\()' comment: function/method calls captures: 1: entity.name.function.wgsl 2: punctuation.brackets.round.wgsl push: - meta_scope: meta.function.call.wgsl - match: \) captures: 0: punctuation.brackets.round.wgsl pop: true - include: line_comments - include: block_comments - include: keywords - include: attributes - include: function_calls - include: constants - include: types - include: variables - include: punctuation functions: - match: '\b(fn)\s+([A-Za-z0-9_]+)((\()|(<))' comment: function definition captures: 1: keyword.other.fn.wgsl 2: entity.name.function.wgsl 4: punctuation.brackets.round.wgsl push: - meta_scope: meta.function.definition.wgsl - match: '\{' captures: 0: punctuation.brackets.curly.wgsl pop: true - include: line_comments - include: block_comments - include: keywords - include: attributes - include: function_calls - include: constants - include: types - include: variables - include: punctuation keywords: - match: \b(bitcast|block|break|case|continue|continuing|default|discard|else|elseif|enable|fallthrough|for|function|if|loop|private|read|read_write|return|storage|switch|uniform|while|workgroup|write)\b comment: other keywords scope: keyword.control.wgsl - match: \b(asm|const|do|enum|handle|mat|premerge|regardless|typedef|unless|using|vec|void)\b comment: reserved keywords scope: keyword.control.wgsl - match: \b(let|var)\b comment: storage keywords scope: keyword.other.wgsl storage.type.wgsl - match: \b(type)\b comment: type keyword scope: keyword.declaration.type.wgsl storage.type.wgsl - match: \b(enum)\b comment: enum keyword scope: keyword.declaration.enum.wgsl storage.type.wgsl - match: \b(struct)\b comment: struct keyword scope: keyword.declaration.struct.wgsl storage.type.wgsl - match: \bfn\b comment: fn scope: keyword.other.fn.wgsl - match: (\^|\||\|\||&&|<<|>>|!)(?!=) comment: logical operators scope: keyword.operator.logical.wgsl - match: '&(?![&=])' comment: logical AND, borrow references scope: keyword.operator.borrow.and.wgsl - match: (\+=|-=|\*=|/=|%=|\^=|&=|\|=|<<=|>>=) comment: assignment operators scope: keyword.operator.assignment.wgsl - match: '(?])=(?!=|>)' comment: single equal scope: keyword.operator.assignment.equal.wgsl - match: (=(=)?(?!>)|!=|<=|(?=) comment: comparison operators scope: keyword.operator.comparison.wgsl - match: '(([+%]|(\*(?!\w)))(?!=))|(-(?!>))|(/(?!/))' comment: math operators scope: keyword.operator.math.wgsl - match: \.(?!\.) comment: dot access scope: keyword.operator.access.dot.wgsl - match: '->' comment: dashrocket, skinny arrow scope: keyword.operator.arrow.skinny.wgsl line_comments: - match: \s*//.* comment: single line comment scope: comment.line.double-slash.wgsl punctuation: - match: ',' comment: comma scope: punctuation.comma.wgsl - match: '[{}]' comment: curly braces scope: punctuation.brackets.curly.wgsl - match: '[()]' comment: parentheses, round brackets scope: punctuation.brackets.round.wgsl - match: ; comment: semicolon scope: punctuation.semi.wgsl - match: '[\[\]]' comment: square brackets scope: punctuation.brackets.square.wgsl - match: '(?]' comment: angle brackets scope: punctuation.brackets.angle.wgsl types: - match: \b(bool|i32|u32|f32)\b comment: scalar Types scope: storage.type.wgsl - match: \b(i64|u64|f64)\b comment: reserved scalar Types scope: storage.type.wgsl - match: \b(vec2i|vec3i|vec4i|vec2u|vec3u|vec4u|vec2f|vec3f|vec4f|vec2h|vec3h|vec4h)\b comment: vector type aliasses scope: storage.type.wgsl - match: \b(mat2x2f|mat2x3f|mat2x4f|mat3x2f|mat3x3f|mat3x4f|mat4x2f|mat4x3f|mat4x4f|mat2x2h|mat2x3h|mat2x4h|mat3x2h|mat3x3h|mat3x4h|mat4x2h|mat4x3h|mat4x4h)\b comment: matrix type aliasses scope: storage.type.wgsl - match: '\b(vec[2-4]|mat[2-4]x[2-4])\b' comment: vector/matrix types scope: storage.type.wgsl - match: \b(atomic)\b comment: atomic types scope: storage.type.wgsl - match: \b(array)\b comment: array types scope: storage.type.wgsl - match: '\b([A-Z][A-Za-z0-9]*)\b' comment: Custom type scope: entity.name.type.wgsl variables: - match: '\b(? author Template: Chris Kempson, Scheme: Mitchell Kember name ANSI colorSpaceName sRGB settings settings background #00000001 foreground #00000001 gutter #00000001 gutterForeground #00000001 name Comments scope comment, punctuation.definition.comment settings foreground #02000000 name Keywords scope keyword settings foreground #05000000 name Functions scope entity.name.function, meta.require, support.function.any-method settings foreground #04000000 name Labels scope entity.name.label, variable.parameter settings foreground #06000000 name Classes scope support.class, entity.name.class, entity.name.type.class, entity.name settings foreground #03000000 name Methods scope keyword.other.special-method settings foreground #04000000 name Storage scope storage settings foreground #05000000 name Support scope support.function settings foreground #06000000 name Strings, Inherited Class scope string, constant.other.symbol, entity.other.inherited-class settings foreground #02000000 name Integers scope constant.numeric settings foreground #03000000 name Floats scope none settings foreground #03000000 name Boolean scope none settings foreground #03000000 name Constants scope constant settings foreground #03000000 name Tags scope entity.name.tag settings foreground #01000000 name Attributes scope entity.other.attribute-name settings foreground #03000000 name Attribute IDs scope entity.other.attribute-name.id, punctuation.definition.entity settings foreground #04000000 name Selector scope meta.selector settings foreground #05000000 name Values scope none settings foreground #03000000 name Headings scope markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown, meta.mapping.key string.quoted.double settings fontStyle foreground #04000000 name Units scope keyword.other.unit settings foreground #03000000 name Bold scope markup.bold, punctuation.definition.bold settings fontStyle bold foreground #03000000 name Italic scope markup.italic, punctuation.definition.italic settings fontStyle italic foreground #05000000 name Code scope markup.raw.inline settings foreground #02000000 name Link Text scope string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown settings foreground #01000000 name Link Url scope meta.link settings foreground #03000000 name Quotes scope markup.quote settings foreground #03000000 name Inserted scope markup.inserted settings foreground #02000000 name Deleted scope markup.deleted settings foreground #01000000 name Changed scope markup.changed settings foreground #05000000 name Colors scope constant.other.color settings foreground #06000000 name Regular Expressions scope string.regexp settings foreground #06000000 name Escape Characters scope constant.character.escape settings foreground #06000000 name Embedded scope punctuation.section.embedded, variable.interpolation settings foreground #05000000 name Illegal scope invalid.illegal settings background #01000000 name Broken scope invalid.broken settings background #03000000 uuid uuid ================================================ FILE: assets/themes/base16-256.tmTheme ================================================ author Template: Chris Kempson, Scheme: Mitchell Kember name Base16 256 colorSpaceName sRGB settings settings background #00000000 caret #07000000 foreground #07000000 invisibles #08000000 lineHighlight #08000000 selection #13000000 gutter #12000000 gutterForeground #08000000 name Text scope variable.parameter.function settings foreground #07000000 name Comments scope comment, punctuation.definition.comment settings foreground #08000000 name Punctuation scope punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array settings foreground #07000000 name Delimiters scope none settings foreground #07000000 name Operators scope keyword.operator settings foreground #07000000 name Keywords scope keyword settings foreground #05000000 name Variables scope variable settings foreground #07000000 name Functions scope entity.name.function, meta.require, support.function.any-method settings foreground #04000000 name Labels scope entity.name.label settings foreground #11000000 name Classes scope support.class, entity.name.class, entity.name.type.class settings foreground #03000000 name Classes scope meta.class settings foreground #0f000000 name Methods scope keyword.other.special-method settings foreground #04000000 name Storage scope storage settings foreground #05000000 name Support scope support.function settings foreground #06000000 name Strings, Inherited Class scope string, constant.other.symbol, entity.other.inherited-class settings foreground #02000000 name Integers scope constant.numeric settings foreground #10000000 name Floats scope none settings foreground #10000000 name Boolean scope none settings foreground #10000000 name Constants scope constant settings foreground #10000000 name Tags scope entity.name.tag, entity.name settings foreground #01000000 name Attributes scope entity.other.attribute-name settings foreground #10000000 name Attribute IDs scope entity.other.attribute-name.id, punctuation.definition.entity settings foreground #04000000 name Selector scope meta.selector settings foreground #05000000 name Values scope none settings foreground #10000000 name Headings scope markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle foreground #04000000 name Units scope keyword.other.unit settings foreground #10000000 name Bold scope markup.bold, punctuation.definition.bold settings fontStyle bold foreground #03000000 name Italic scope markup.italic, punctuation.definition.italic settings fontStyle italic foreground #05000000 name Code scope markup.raw.inline settings foreground #02000000 name Link Text scope string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown settings foreground #01000000 name Link Url scope meta.link settings foreground #10000000 name Quotes scope markup.quote settings foreground #10000000 name Separator scope meta.separator settings background #13000000 foreground #07000000 name Inserted scope markup.inserted settings foreground #02000000 name Deleted scope markup.deleted settings foreground #01000000 name Changed scope markup.changed settings foreground #05000000 name Colors scope constant.other.color settings foreground #06000000 name Regular Expressions scope string.regexp settings foreground #06000000 name Escape Characters scope constant.character.escape settings foreground #06000000 name Embedded scope punctuation.section.embedded, variable.interpolation settings foreground #05000000 name Illegal scope invalid.illegal settings background #01000000 foreground #0f000000 name Broken scope invalid.broken settings background #10000000 foreground #00000000 name Deprecated scope invalid.deprecated settings background #11000000 foreground #0f000000 name Unimplemented scope invalid.unimplemented settings background #08000000 foreground #0f000000 uuid uuid ================================================ FILE: assets/themes/base16.tmTheme ================================================ author Template: Chris Kempson, Scheme: Mitchell Kember name Base16 colorSpaceName sRGB settings settings background #00000000 caret #07000000 foreground #07000000 invisibles #08000000 lineHighlight #08000000 selection #0b000000 gutter #0a000000 gutterForeground #08000000 name Text scope variable.parameter.function settings foreground #07000000 name Comments scope comment, punctuation.definition.comment settings foreground #08000000 name Punctuation scope punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array settings foreground #07000000 name Delimiters scope none settings foreground #07000000 name Operators scope keyword.operator settings foreground #07000000 name Keywords scope keyword settings foreground #05000000 name Variables scope variable settings foreground #07000000 name Functions scope entity.name.function, meta.require, support.function.any-method settings foreground #04000000 name Labels scope entity.name.label settings foreground #0e000000 name Classes scope support.class, entity.name.class, entity.name.type.class settings foreground #03000000 name Classes scope meta.class settings foreground #0f000000 name Methods scope keyword.other.special-method settings foreground #04000000 name Storage scope storage settings foreground #05000000 name Support scope support.function settings foreground #06000000 name Strings, Inherited Class scope string, constant.other.symbol, entity.other.inherited-class settings foreground #02000000 name Integers scope constant.numeric settings foreground #09000000 name Floats scope none settings foreground #09000000 name Boolean scope none settings foreground #09000000 name Constants scope constant settings foreground #09000000 name Tags scope entity.name.tag, entity.name settings foreground #01000000 name Attributes scope entity.other.attribute-name settings foreground #09000000 name Attribute IDs scope entity.other.attribute-name.id, punctuation.definition.entity settings foreground #04000000 name Selector scope meta.selector settings foreground #05000000 name Values scope none settings foreground #09000000 name Headings scope markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle foreground #04000000 name Units scope keyword.other.unit settings foreground #09000000 name Bold scope markup.bold, punctuation.definition.bold settings fontStyle bold foreground #03000000 name Italic scope markup.italic, punctuation.definition.italic settings fontStyle italic foreground #05000000 name Code scope markup.raw.inline settings foreground #02000000 name Link Text scope string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown settings foreground #01000000 name Link Url scope meta.link settings foreground #09000000 name Quotes scope markup.quote settings foreground #09000000 name Separator scope meta.separator settings background #0b000000 foreground #07000000 name Inserted scope markup.inserted settings foreground #02000000 name Deleted scope markup.deleted settings foreground #01000000 name Changed scope markup.changed settings foreground #05000000 name Colors scope constant.other.color settings foreground #06000000 name Regular Expressions scope string.regexp settings foreground #06000000 name Escape Characters scope constant.character.escape settings foreground #06000000 name Embedded scope punctuation.section.embedded, variable.interpolation settings foreground #05000000 name Illegal scope invalid.illegal settings background #01000000 foreground #0f000000 name Broken scope invalid.broken settings background #09000000 foreground #00000000 name Deprecated scope invalid.deprecated settings background #0e000000 foreground #0f000000 name Unimplemented scope invalid.unimplemented settings background #08000000 foreground #0f000000 uuid uuid ================================================ FILE: build/application.rs ================================================ use std::{env, fs, path::PathBuf}; use crate::util::render_template; /// Generate manpage and shell completions for the bat application. pub fn gen_man_and_comp() -> anyhow::Result<()> { println!("cargo:rerun-if-changed=assets/manual/"); println!("cargo:rerun-if-changed=assets/completions/"); println!("cargo:rerun-if-env-changed=PROJECT_NAME"); println!("cargo:rerun-if-env-changed=PROJECT_EXECUTABLE"); println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION"); println!("cargo:rerun-if-env-changed=BAT_ASSETS_GEN_DIR"); // Read environment variables. let project_name = env::var("PROJECT_NAME").unwrap_or("bat".into()); let executable_name = env::var("PROJECT_EXECUTABLE").unwrap_or(project_name.clone()); let executable_name_uppercase = executable_name.to_uppercase(); let project_version = env::var("CARGO_PKG_VERSION")?; let variables = [ ("PROJECT_NAME", project_name), ("PROJECT_EXECUTABLE", executable_name), ("PROJECT_EXECUTABLE_UPPERCASE", executable_name_uppercase), ("PROJECT_VERSION", project_version), ] .into_iter() .collect(); let Some(out_dir) = env::var_os("BAT_ASSETS_GEN_DIR") .or_else(|| env::var_os("OUT_DIR")) .map(PathBuf::from) else { anyhow::bail!("BAT_ASSETS_GEN_DIR or OUT_DIR should be set for build.rs"); }; fs::create_dir_all(out_dir.join("assets/manual")).unwrap(); fs::create_dir_all(out_dir.join("assets/completions")).unwrap(); render_template( &variables, "assets/manual/bat.1.in", out_dir.join("assets/manual/bat.1"), )?; render_template( &variables, "assets/completions/bat.bash.in", out_dir.join("assets/completions/bat.bash"), )?; render_template( &variables, "assets/completions/bat.fish.in", out_dir.join("assets/completions/bat.fish"), )?; render_template( &variables, "assets/completions/_bat.ps1.in", out_dir.join("assets/completions/_bat.ps1"), )?; render_template( &variables, "assets/completions/bat.zsh.in", out_dir.join("assets/completions/bat.zsh"), )?; println!( "cargo:rustc-env=BAT_GENERATED_COMPLETION_BASH={}", out_dir.join("assets/completions/bat.bash").display() ); println!( "cargo:rustc-env=BAT_GENERATED_COMPLETION_FISH={}", out_dir.join("assets/completions/bat.fish").display() ); println!( "cargo:rustc-env=BAT_GENERATED_COMPLETION_PS1={}", out_dir.join("assets/completions/_bat.ps1").display() ); println!( "cargo:rustc-env=BAT_GENERATED_COMPLETION_ZSH={}", out_dir.join("assets/completions/bat.zsh").display() ); Ok(()) } ================================================ FILE: build/main.rs ================================================ #[cfg(feature = "application")] mod application; mod syntax_mapping; mod util; fn main() -> anyhow::Result<()> { // only watch manually-designated files // see: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed println!("cargo:rerun-if-changed=build/"); syntax_mapping::build_static_mappings()?; #[cfg(feature = "application")] application::gen_man_and_comp()?; Ok(()) } ================================================ FILE: build/syntax_mapping.rs ================================================ use std::{ convert::Infallible, env, fs, path::{Path, PathBuf}, str::FromStr, }; use anyhow::{anyhow, bail}; use indexmap::IndexMap; use itertools::Itertools; use once_cell::sync::Lazy; use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; use regex::Regex; use serde_derive::Deserialize; use serde_with::DeserializeFromStr; use walkdir::WalkDir; /// Known mapping targets. /// /// Corresponds to `syntax_mapping::MappingTarget`. #[allow(clippy::enum_variant_names)] #[derive(Clone, Debug, Eq, PartialEq, Hash, DeserializeFromStr)] pub enum MappingTarget { MapTo(String), MapToUnknown, MapExtensionToUnknown, } impl FromStr for MappingTarget { type Err = Infallible; fn from_str(s: &str) -> Result { match s { "MappingTarget::MapToUnknown" => Ok(Self::MapToUnknown), "MappingTarget::MapExtensionToUnknown" => Ok(Self::MapExtensionToUnknown), syntax => Ok(Self::MapTo(syntax.into())), } } } impl ToTokens for MappingTarget { fn to_tokens(&self, tokens: &mut TokenStream) { let t = match self { Self::MapTo(syntax) => quote! { MappingTarget::MapTo(#syntax) }, Self::MapToUnknown => quote! { MappingTarget::MapToUnknown }, Self::MapExtensionToUnknown => quote! { MappingTarget::MapExtensionToUnknown }, }; tokens.append_all(t); } } #[derive(Clone, Debug, PartialEq, Eq, Hash, DeserializeFromStr)] /// A single matcher. /// /// Codegen converts this into a `Lazy>`. struct Matcher(Vec); /// Parse a matcher. /// /// Note that this implementation is rather strict: it will greedily interpret /// every valid environment variable replacement as such, then immediately /// hard-error if it finds a '$' anywhere in the remaining text segments. /// /// The reason for this strictness is I currently cannot think of a valid reason /// why you would ever need '$' as plaintext in a glob pattern. Therefore any /// such occurrences are likely human errors. /// /// If we later discover some edge cases, it's okay to make it more permissive. /// /// Revision history: /// - 2024-02-20: allow `{` and `}` (glob brace expansion) impl FromStr for Matcher { type Err = anyhow::Error; fn from_str(s: &str) -> Result { use MatcherSegment as Seg; static VAR_REGEX: Lazy = Lazy::new(|| Regex::new(r"\$\{([\w\d_]+)\}").unwrap()); let mut segments = vec![]; let mut text_start = 0; for capture in VAR_REGEX.captures_iter(s) { let match_0 = capture.get(0).unwrap(); // text before this var let text_end = match_0.start(); segments.push(Seg::Text(s[text_start..text_end].into())); text_start = match_0.end(); // this var segments.push(Seg::Env(capture.get(1).unwrap().as_str().into())); } // possible trailing text segments.push(Seg::Text(s[text_start..].into())); // cleanup empty text segments let non_empty_segments = segments .into_iter() .filter(|seg| seg.text().map(|t| !t.is_empty()).unwrap_or(true)) .collect_vec(); // sanity check if non_empty_segments .windows(2) .any(|segs| segs[0].is_text() && segs[1].is_text()) { unreachable!("Parsed into consecutive text segments: {non_empty_segments:?}"); } // guard empty case if non_empty_segments.is_empty() { bail!(r#"Parsed an empty matcher: "{s}""#); } // guard variable syntax leftover fragments if non_empty_segments .iter() .filter_map(Seg::text) .any(|t| t.contains('$')) { bail!(r#"Invalid matcher: "{s}""#); } Ok(Self(non_empty_segments)) } } impl ToTokens for Matcher { fn to_tokens(&self, tokens: &mut TokenStream) { let t = match self.0.as_slice() { [] => unreachable!("0-length matcher should never be created"), [MatcherSegment::Text(text)] => { quote! { Lazy::new(|| Some(build_matcher_fixed(#text))) } } // parser logic ensures that this case can only happen when there are dynamic segments segs @ [_, ..] => quote! { Lazy::new(|| build_matcher_dynamic(&[ #(#segs),* ])) }, }; tokens.append_all(t); } } /// A segment in a matcher. /// /// Corresponds to `syntax_mapping::MatcherSegment`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum MatcherSegment { Text(String), Env(String), } impl ToTokens for MatcherSegment { fn to_tokens(&self, tokens: &mut TokenStream) { let t = match self { Self::Text(text) => quote! { MatcherSegment::Text(#text) }, Self::Env(env) => quote! { MatcherSegment::Env(#env) }, }; tokens.append_all(t); } } #[allow(dead_code)] impl MatcherSegment { fn is_text(&self) -> bool { matches!(self, Self::Text(_)) } fn is_env(&self) -> bool { matches!(self, Self::Env(_)) } fn text(&self) -> Option<&str> { match self { Self::Text(t) => Some(t), Self::Env(_) => None, } } fn env(&self) -> Option<&str> { match self { Self::Text(_) => None, Self::Env(t) => Some(t), } } } /// A struct that models a single .toml file in /src/syntax_mapping/builtins/. #[derive(Clone, Debug, Deserialize)] struct MappingDefModel { mappings: IndexMap>, } impl MappingDefModel { fn into_mapping_list(self) -> MappingList { let list = self .mappings .into_iter() .flat_map(|(target, matchers)| { matchers .into_iter() .map(|matcher| (matcher, target.clone())) .collect::>() }) .collect(); MappingList(list) } } #[derive(Clone, Debug)] struct MappingList(Vec<(Matcher, MappingTarget)>); impl ToTokens for MappingList { fn to_tokens(&self, tokens: &mut TokenStream) { let len = self.0.len(); let array_items = self .0 .iter() .map(|(matcher, target)| quote! { (#matcher, #target) }); let t = quote! { /// Generated by build script from /src/syntax_mapping/builtins/. pub(crate) static BUILTIN_MAPPINGS: [(Lazy>, MappingTarget); #len] = [#(#array_items),*]; }; tokens.append_all(t); } } /// Get the list of paths to all mapping definition files that should be /// included for the current target platform. fn get_def_paths() -> anyhow::Result> { let source_subdirs = [ "common", #[cfg(target_family = "unix")] "unix-family", #[cfg(any( target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "macos" ))] "bsd-family", #[cfg(target_os = "linux")] "linux", #[cfg(target_os = "macos")] "macos", #[cfg(target_os = "windows")] "windows", ]; let mut toml_paths = vec![]; for subdir_name in source_subdirs { let subdir = Path::new("src/syntax_mapping/builtins").join(subdir_name); if !subdir.try_exists()? { // Directory might not exist due to this `cargo vendor` bug: // https://github.com/rust-lang/cargo/issues/15080 continue; } let wd = WalkDir::new(subdir); let paths = wd .into_iter() .filter_map_ok(|entry| { let path = entry.path(); (path.is_file() && path.extension().map(|ext| ext == "toml").unwrap_or(false)) .then(|| path.to_owned()) }) .collect::, _>>()?; toml_paths.extend(paths); } toml_paths.sort_by_key(|path| { path.file_name() .expect("file name should not terminate in ..") .to_owned() }); Ok(toml_paths) } fn read_all_mappings() -> anyhow::Result { let mut all_mappings = vec![]; for path in get_def_paths()? { let toml_string = fs::read_to_string(path)?; let mappings = toml::from_str::(&toml_string)?.into_mapping_list(); all_mappings.extend(mappings.0); } let duplicates = all_mappings .iter() .duplicates_by(|(matcher, _)| matcher) .collect_vec(); if !duplicates.is_empty() { bail!("Rules with duplicate matchers found: {duplicates:?}"); } Ok(MappingList(all_mappings)) } /// Build the static syntax mappings defined in /src/syntax_mapping/builtins/ /// into a .rs source file, which is to be inserted with `include!`. pub fn build_static_mappings() -> anyhow::Result<()> { println!("cargo:rerun-if-changed=src/syntax_mapping/builtins/"); let mappings = read_all_mappings()?; // IMPRV: parse + unparse is a bit cringe, but there seems to be no better // option given the limited APIs of `prettyplease` let rs_src = syn::parse_file(&mappings.to_token_stream().to_string())?; let rs_src_pretty = prettyplease::unparse(&rs_src); let codegen_path = Path::new(&env::var_os("OUT_DIR").ok_or(anyhow!("OUT_DIR is unset"))?) .join("codegen_static_syntax_mappings.rs"); fs::write(codegen_path, rs_src_pretty)?; Ok(()) } ================================================ FILE: build/util.rs ================================================ #![allow(dead_code)] use std::{collections::HashMap, fs, path::Path}; /// Generates a file from a template. pub fn render_template( variables: &HashMap<&str, String>, in_file: &str, out_file: impl AsRef, ) -> anyhow::Result<()> { let mut content = fs::read_to_string(in_file)?; for (variable_name, value) in variables { // Replace {{variable_name}} by the value let pattern = format!("{{{{{variable_name}}}}}"); content = content.replace(&pattern, value); } fs::write(out_file, content)?; Ok(()) } ================================================ FILE: diagnostics/.gitattributes ================================================ * linguist-vendored ================================================ FILE: diagnostics/info.sh ================================================ #!/usr/bin/env bash _modules=('system' 'bat' 'bat_config' 'bat_wrapper' 'bat_wrapper_function' 'tool') _modules_consented=() set -o pipefail export LC_ALL=C export LANG=C BAT="bat" if ! command -v bat &>/dev/null; then if command -v batcat &> /dev/null; then BAT="batcat" else tput setaf 1 printf "%s\n%s\n" \ "Unable to find a bat executable on your PATH." \ "Please ensure that 'bat' exists and is not named something else." tput sgr0 exit 1 fi fi # ----------------------------------------------------------------------------- # Modules: # ----------------------------------------------------------------------------- _bat_:description() { _collects "Version information for 'bat'." _collects "Custom syntaxes and themes for 'bat'." } _bat_config_:description() { _collects "The environment variables used by 'bat'." _collects "The 'bat' configuration file." } _bat_wrapper_:description() { _collects "Any wrapper script used by 'bat'." } _bat_wrapper_function_:description() { _collects "The wrapper function surrounding 'bat' (if applicable)." } _system_:description() { _collects "Operating system name." _collects "Operating system version." } _tool_:description() { _collects "Version information for 'less'." } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _bat_:run() { _out "$BAT" --version _out env | grep '^BAT_\|^PAGER=' local cache_dir cache_dir="$($BAT --cache-dir)" if [[ -f "${cache_dir}/syntaxes.bin" ]]; then _print_command "$BAT" "--list-languages" echo "Found custom syntax set." fi if [[ -f "${cache_dir}/themes.bin" ]]; then _print_command "$BAT" "--list-themes" echo "Found custom theme set." fi } _bat_config_:run() { if [[ -f "$("$BAT" --config-file)" ]]; then _out_fence cat "$("$BAT" --config-file)" fi } _bat_wrapper_:run() { _bat_wrapper_:detect_wrapper() { local bat="$1" if file "$(command -v "${bat}")" | grep "text executable" &> /dev/null; then _out_fence cat "$(command -v "${bat}")" return fi printf "\nNo wrapper script for '%s'.\n" "${bat}" } _bat_wrapper_:detect_wrapper bat if [[ "$BAT" != "bat" ]]; then _bat_wrapper_:detect_wrapper "$BAT" fi } _bat_wrapper_function_:run() { _bat_wrapper_function_:detect_wrapper() { local command="$1" case "$("$SHELL" --version | head -n 1)" in *fish*) if "$SHELL" --login -i -c "type ${command}" 2>&1 | grep 'function' &> /dev/null; then _out_fence "$SHELL" --login -i -c "functions ${command}" return fi ;; *bash* | *zsh*) local type type="$("$SHELL" --login -i -c "type ${command}" 2>&1)" if grep 'function' <<< "$type" &> /dev/null; then _out_fence "$SHELL" --login -i -c "declare -f ${command}" return elif grep 'alias' <<< "$type" &> /dev/null; then _out_fence "$SHELL" --login -i -c "type ${command}" return fi ;; *) echo "Unable to determine if a wrapper function for '${command}' is set." return ;; esac printf "\nNo wrapper function for '%s'.\n" "${command}" } _bat_wrapper_function_:detect_wrapper bat _bat_wrapper_function_:detect_wrapper cat if [[ "$BAT" != "bat" ]]; then _bat_wrapper_function_:detect_wrapper "$BAT" fi } _system_:run() { _out uname -srm if command -v "sw_vers" &> /dev/null; then _out sw_vers; fi if command -v "lsb_release" &> /dev/null; then _out lsb_release -a; fi } _tool_:run() { _out less --version | head -n1 } # ----------------------------------------------------------------------------- # Functions: # ----------------------------------------------------------------------------- _print_command() { printf '\n**$' 1>&2 printf ' %s' "$@" 1>&2 printf '**\n' 1>&2 } _out() { _print_command "$@" "$@" 2>&1 | sed 's/$/ /' } _out_fence() { _print_command "$@" printf '```\n' 1>&2 "$@" 2>&1 printf '```\n' 1>&2 } _tput() { tput "$@" 1>&2 2> /dev/null } _collects() { printf " - %s\n" "$1" 1>&2 } _ask_module() { _tput clear _tput cup 0 0 cat 1>&2 << EOF -------------------------------------------------------------------------------- This script runs some harmless commands to collect information about your system and bat configuration. It will give you a small preview of the commands that will be run, and ask consent before running them. Once completed, it will output a small report that you can review and copy into the issue description. -------------------------------------------------------------------------------- EOF # Print description. _tput setaf 3 printf "The following data will be collected:\n" 1>&2 _tput sgr0 "_$1_:description" _tput sgr0 # Print preview. _tput setaf 3 printf "\nThe following commands will be run:\n" 1>&2 _tput sgr0 declare -f "_$1_:run" \ | sed 's/^ *//; s/;$//' \ | grep '^_out[^ ]* ' \ | sed 's/^_out[^ ]* //' \ | sed "s/\"\$BAT\"/$BAT/" 1>&2 # Prompt printf "\n" 1>&2 local response while true; do _tput cup "$(($( tput lines || echo 22) - 2))" _tput el read -er -p "Collect $(sed 's/_/ /' <<< "$1") data? [Y/n] " response case "$response" in Y | y | yes | '') return 0 ;; N | n | no) return 1 ;; *) continue ;; esac done } _run_module() { local module="$1" printf "%s\n%s\n" "$module" "$(printf "%${#module}s" | tr ' ' '-')" "_$1_:run" } # ----------------------------------------------------------------------------- # Functions: # ----------------------------------------------------------------------------- # Tell the user if their executable isn't named "bat". if [[ "$BAT" != "bat" ]] && [[ "$1" != '-y' ]]; then trap '_tput rmcup; exit 1' INT _tput smcup _tput clear _tput cup 0 0 _tput setaf 1 printf "The %s executable on your system is named '%s'.\n%s\n" "bat" "$BAT" \ "If your issue is related to installation, please check that this isn't the issue." _tput sgr0 printf "Press any key to continue...\n" read -rsn1 _tput rmcup fi # Ask for consent. if [[ "$1" == '-y' ]]; then _modules_consented=("${_modules[@]}") else trap '_tput rmcup; exit 1' INT _tput smcup for _module in "${_modules[@]}"; do if _ask_module "$_module"; then _modules_consented+=("$_module") fi done _tput rmcup fi # Collect information. for _module in "${_modules_consented[@]}"; do _run_module "$_module" 2>&1 printf "\n" done ================================================ FILE: doc/README-ja.md ================================================

bat - a cat clone with wings
Build Status license Version info
シンタックスハイライトとGitとの連携機能付きの cat(1) クローン。

特徴使い方インストールカスタマイズプロジェクトの目標と既存の類似したOSS
[English] [中文] [日本語] [한국어] [Русский]

### シンタックスハイライト `bat` は多くのプログラミング言語やマークアップ言語の シンタックスハイライトに対応しています: ![Syntax highlighting example](https://imgur.com/rGsdnDe.png) ### Gitの統合 `bat` は `git` とも連携しており、差分を表現する記号が表示されます (図の左端): ![Git integration example](https://i.imgur.com/2lSW4RE.png) ### 印刷できない文字の表示 `-A`/`--show-all` オプションをつけることで 印刷できない文字を可視化できます: ![Non-printable character example](https://i.imgur.com/WndGp9H.png) ### 自動ページング 出力が1つの画面に対して大きすぎる場合、`bat` は自身の出力をページャー(例えば `less`) にパイプで繋げます。 ### ファイルの連結 あなたはさらにファイルを連結させるために使うことも可能です:wink:。 `bat` は非対話型のターミナルを検出すると(すなわち他のプロセスにパイプしたりファイル出力していると)、 `bat` は `cat` の完全互換として振る舞い、 プレーンなファイルを表示します。 ## 使い方 単一のファイルを表示させたい場合 ```bash > bat README.md ``` 複数のファイルを一度に表示させたい場合 ```bash > bat src/*.rs ``` 標準入力から自動的に構文を決定させたい場合(ハイライトされるのは、 たいていは `#!/bin/sh` のようなシバンを利用して、 ファイルの一行目から構文を決定できる場合のみです) ```bash > curl -s https://sh.rustup.rs | bat ``` 標準入力から明示的に言語を指定したい場合 ```bash > yaml2json .travis.yml | json_pp | bat -l json ``` 空白文字を可視化させたい場合: ```bash > bat -A /etc/hosts ``` `cat` の代わりに `bat` を使用する際の例: ```bash bat > note.md # quickly create a new file bat header.md content.md footer.md > document.md bat -n main.rs # show line numbers (only) bat f - g # output 'f', then stdin, then 'g'. ``` ### 他のツールとの統合 #### `fzf` [`fzf`](https://github.com/junegunn/fzf) のプレビューウィンドウに `bat` を使用できます。 その場合、`bat` の `--color=always` オプションを用いてカラー出力を強制しなければなりません。 また、`--line-range` オプションを用いることで巨大なファイルの読み込み時間を制限できます: ```bash fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' ``` 詳しくは [`fzf` の `README`](https://github.com/junegunn/fzf#preview-window) を参照してください。 #### `find` or `fd` `find` の `-exec` オプションを使用して、`bat` ですべての検索結果をプレビューできます: ```bash find … -exec bat {} + ``` [`fd`](https://github.com/sharkdp/fd) を使用している場合は、`-X` /`-exec-batch` オプションを使用して同じことを行うことができます: ```bash fd … -X bat ``` #### `ripgrep` [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md) では、[`ripgrep`](https://github.com/BurntSushi/ripgrep) 検索結果のプリンターとして `bat` を使用できます。 ```bash batgrep needle src/ ``` #### `tail -f` `bat` を `tail -f` と組み合わせて、構文強調表示を使用して特定のファイルを継続的に監視できます。 ```bash tail -f /var/log/pacman.log | bat --paging=never -l log ``` 注意事項:`tail -f`と組み合わせるには、ページングをオフにしなければなりません。また、この場合は構文が自動検出されないため、明示的に指定(`-l log`)しています。 #### `git` `bat` を `git show` と組み合わせて、 適切な構文強調表示を使用して特定のファイルの古いバージョンを表示できます: ```bash git show v0.6.0:src/main.rs | bat -l rs ``` 差分内の構文強調表示は現在サポートされていないことに注意してください。 これを探しているなら、[`delta`](https://github.com/dandavison/delta) をチェックしてください。 #### `xclip` `bat` の出力の行番号と Git 変更マーカーにより、ファイルの内容をコピーするのが難しくなる場合があります。 これを防ぐには、`-p` / `-plain` オプションを使用して `bat` を呼び出すか、 単に出力を `xclip` にパイプします: ```bash bat main.cpp | xclip ``` `bat` は出力がリダイレクトされていることを検出し、プレーンファイルの内容を出力します。 #### `man` `bat` は `MANPAGER` 環境変数を設定することにより、 `man` の色付けページャーとして使用できます: ```bash export MANPAGER="sh -c 'col -bx | bat -l man -p'" man 2 select ``` フォーマットの問題が発生した場合は `MANROFFOPT="-c"` を設定する必要もあります。 これを新しいコマンドにバンドルしたい場合は [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md) も使用できます。 [Manpage syntax](assets/syntaxes/Manpage.sublime-syntax) はこのリポジトリで開発されており、まだ作業が必要であることに注意してください。 #### `prettier` / `shfmt` / `rustfmt` [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) スクリプトは、コードをフォーマットし、`bat` で印刷するラッパーです。 ## インストール [![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg?columns=3&exclude_unsupported=1)](https://repology.org/project/bat-cat/versions) ### On Ubuntu (`apt` を使用) *... や他のDebianベースのLinuxディストリビューション* [20.04 ("Focal") 以降の Ubuntu](https://packages.ubuntu.com/search?keywords=bat&exact=1) または [2021 年 8 月以降の Debian (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat) では `bat` パッケージが利用できます。 ```bash apt install bat ``` `apt` を使用して `bat` をインストールした場合、実行可能ファイルの名前が `bat` ではなく `batcat` になることがあります([他のパッケージとの名前衝突のため](https://github.com/sharkdp/bat/issues/982))。`bat -> batcat` のシンボリックリンクまたはエイリアスを設定することで、実行可能ファイル名が異なることによる問題の発生を防ぎ、他のディストリビューションと一貫性を保てます。 ``` bash mkdir -p ~/.local/bin ln -s /usr/bin/batcat ~/.local/bin/bat ``` ### On Ubuntu (最新の `.deb` パッケージを使用) *... や他のDebianベースのLinuxディストリビューション batの最新リリースを実行する場合、または Ubuntu/Debian の古いバージョンを使用している場合は、[release page](https://github.com/sharkdp/bat/releases) から最新の `.deb` パッケージをダウンロードし、 次の方法でインストールします: ```bash sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture ``` ### On Alpine Linux 適切なリポジトリが有効になっている場合は、 公式のソースから [`bat` package](https://pkgs.alpinelinux.org/packages?name=bat) をインストールできます: ```bash apk add bat ``` ### On Arch Linux [Arch Linuxの公式リソース](https://www.archlinux.org/packages/extra/x86_64/bat/) からインストールできます。 ```bash pacman -S bat ``` ### On Fedora 公式の [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/) リポジトリから [the `bat` package](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) をインストールできます。 ```bash dnf install bat ``` ### On Gentoo Linux 公式ソースから [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat) をインストールできます。 ```bash emerge sys-apps/bat ``` ### On Void Linux xbps-install経由で `bat` をインストールできます。 ``` xbps-install -S bat ``` ### On FreeBSD pkg を使用してプリコンパイルされた [`bat` package](https://www.freshports.org/textproc/bat) をインストールできます: ```bash pkg install bat ``` または FreeBSD ポートから自分でビルドすることもできます: ```bash cd /usr/ports/textproc/bat make install ``` ### Via nix `bat` を [nix package manager](https://nixos.org/nix) 経由でインストールすることができます: ```bash nix-env -i bat ``` ### On openSUSE `bat` をzypperでインストールすることができます: ```bash zypper install bat ``` ### On macOS [Homebrew](http://braumeister.org/formula/bat)で `bat` をインストールできます: ```bash brew install bat ``` または [MacPorts](https://ports.macports.org/port/bat/summary) で `bat` をインストールします: ```bash port install bat ``` ### On Windows Windowsにbatをインストールするいくつかのオプションがあります。 batをインストールしたら [Windowsでのbatの使用](#windows-での-bat-の利用) セクションをご覧ください。 #### With Chocolatey [Chocolatey](https://chocolatey.org/packages/Bat) から `bat` をインストールできます: ```bash choco install bat ``` #### With Scoop [scoop](https://scoop.sh/) から `bat` をインストールできます: ```bash scoop install bat ``` [Visual C ++再頒布可能](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) パッケージをインストールする必要があります。 #### From prebuilt binaries: [リリースページ](https://github.com/sharkdp/bat/releases) からビルド済みのバイナリをダウンロードできます。 [Visual C ++再頒布可能](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) パッケージをインストールする必要があります。 ### Via Docker コンテナ内で `bat` を使いたい方のために [Docker image](https://hub.docker.com/r/danlynn/bat/) が用意されています: ```bash docker pull danlynn/bat alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat' ``` ### Via Ansible [Ansible](https://www.ansible.com/) でインストールすることができます: ```bash # Install role on local machine ansible-galaxy install aeimer.install_bat ``` ```yaml --- # Playbook to install bat - host: all roles: - aeimer.install_bat ``` - [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat) - [GitHub](https://github.com/aeimer/ansible-install-bat) これは以下のディストリビューションで動作するはずです: - Debian/Ubuntu - ARM (eg. Raspberry PI) - Arch Linux - Void Linux - FreeBSD - MacOS ### From binaries 多くの異なるアーキテクチャのためのプレビルドバージョンを[リリースページ](https://github.com/sharkdp/bat/releases)からチェックしてみてください。静的にリンクされている多くのバイナリも利用できます: ファイル名に `musl` を含むアーカイブを探してみてください。 ### From source `bat` をソースからビルドしたいならば、Rust 1.79.0 以上の環境が必要です。 `cargo` を使用してビルドすることができます: ```bash cargo install --locked bat ``` 一部のプラットフォームでは `llvm` および/または `libclang-dev` のインストールが必要になる場合があります。 ## カスタマイズ ### ハイライト テーマ `bat --list-themes` を使うと現在利用可能なシンタックスハイライトのテーマを入手できます。 `TwoDark` テーマを選ぶためには `--theme=TwoDark` オプションをつけるか `BAT_THEME` という環境変数に `TwoDark` を代入する必要があります。 シェルの起動ファイルに `export BAT_THEME="TwoDark"` と定義すればその設定が変わることはないでしょう。あるいは、 `bat` の [設定ファイル](#設定ファイル)を利用してください。 カスタムファイルでさまざまなテーマをプレビューする場合は、 次のコマンドを使用できます(これには [`fzf`](https://github.com/junegunn/fzf) が必要です)。 ``` bash bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" ``` `bat` はデフォルトだと黒い背景色のターミナルに適しています。 しかし、`GitHub` や `OneHalfLight` のような白い背景色のテーマでもいい感じにすることができます。 ['新しいテーマの追加' セクションに従って](#新しいテーマの追加) カスタムテーマを使用することもできます。 ### 出力のスタイル `--style` を使うことで `bat` の表示の見た目を変更することができます。 例えば、 `--style=numbers,changes` と入力します。 すると、Gitの差分と行番号だけが表示され、グリッド線とファイルヘッダーは表示されません。 環境変数に `BAT_STYLE` を定義するとこれらの設定を永続的に使用することができます。 [設定ファイル](#設定ファイル) を参考にしても良いでしょう。 ### 新しい構文の追加 / 言語の定義 `bat` はシンタックスハイライトのための [`syntect`](https://github.com/trishume/syntect/) という素晴らしいライブラリを使用しています。`syntect` は、 [Sublime Text の `.sublime-syntax` ファイル](https://www.sublimetext.com/docs/3/syntax.html) とテーマを読み取ることができます。新しい構文を定義するために以下の手順を行います。 構文定義ファイルを入れておくためのフォルダを作ります: ```bash mkdir -p "$(bat --config-dir)/syntaxes" cd "$(bat --config-dir)/syntaxes" # Put new '.sublime-syntax' language definition files # in this folder (or its subdirectories), for example: git clone https://github.com/tellnobody1/sublime-purescript-syntax ``` 次のコマンドを使用して、これらのファイルをバイナリキャッシュに解析します: ```bash bat cache --build ``` 最後に `bat --list-languages` と入力すると新しい言語が利用可能かどうかチェックします。 デフォルトの設定に戻したいときは以下のコマンドを実行します: ```bash bat cache --clear ``` ### 新しいテーマの追加 これは構文を新しく定義するやり方と非常に似ています。 まず、新しいシンタックスハイライトのテーマのフォルダを作ります: ```bash mkdir -p "$(bat --config-dir)/themes" cd "$(bat --config-dir)/themes" # Download a theme in '.tmTheme' format, for example: git clone https://github.com/greggb/sublime-snazzy # Update the binary cache bat cache --build ``` 最後に、 `bat --list-themes` で新しいテーマが利用可能かチェックします ### 異なるページャーの使用 `bat` は環境変数 `PAGER` に使用するページャーを明記します。 この環境変数が定義されていない場合、デフォルトで `less` が使用されます。 もし、異なるページャーを使用したい場合は、`PAGER` を修正してください。 または、`PAGER` を上書きする環境変数として `BAT_PAGER` を定義することも可能です。 もし、ページャーにコマンドライン引数を渡したい場合は、 `PAGER`/`BAT_PAGER` 環境変数を定義してください: ```bash export BAT_PAGER="less -RF" ``` 環境変数を利用する代わりに、 `bat` の [設定ファイル](#設定ファイル) を使用して設定も可能です(`--pager` オプション) **注意**: デフォルトにより、ページャーが `less` にセットされているならば `bat` はページャーの以下のコマンドラインオプション を受け付けるでしょう: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` そして `-X`/`--no-init`。 最後のオプション(-X)は、530 より古いバージョンにのみ使用されます。 `-R` オプションは、ANSIカラーを正しく解釈するために必要です。 2番目のオプション(`-F`)は、出力サイズが端末の垂直サイズよりも小さい場合、すぐに終了するようにlessに指示します。 これは、ページャーを終了するために `q` を押す必要がないため、小さなファイルに便利です。 3番目のオプション(`-X`)は、`less` の古いバージョンの `--quit-if-one-screen` 機能のバグを修正するために必要です。 残念ながら、`less` のマウスホイールのサポートも少なくなります。 `less` の古いバージョンでマウスホイールのスクロールを有効にしたい場合は、 `-R` だけを渡すことができます(上記の例のように、これは1画面終了機能を無効にします)。 530以下の場合は、そのまま使用できます。 ### Dark mode macOSでダークモード機能を使用する場合、OSテーマに基づいて異なるテーマを使用するように `bat` を構成することができます。 次のスニペットは、ライトモードの場合は `デフォルト` のテーマを使用し、 ダークモードの場合は `GitHub` テーマを使用します。 ```bash alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" ``` ## 設定ファイル `bat` は設定ファイルでカスタマイズすることが可能です。ファイルの場所はOSに依存します。 使用しているOSのデフォルトパスを調べるには以下のコマンドを実行してください: ``` bat --config-file ``` または、`BAT_CONFIG_PATH` 環境変数を使用して、`bat` が 構成ファイルのデフォルト以外の場所を指すようにすることができます: ```bash export BAT_CONFIG_PATH="/path/to/bat.conf" ``` ### フォーマット この設定ファイルはコマンドライン引数の単純なリストです。 `bat --help` を利用すると、利用可能なオプションとその値を閲覧することができます。さらに、`#` でコメント文を加えることができます。 設定ファイルの例: ```bash # Set the theme to "TwoDark" --theme="TwoDark" # Show line numbers, Git modifications and file header (but no grid) --style="numbers,changes,header" # Use italic text on the terminal (not supported on all terminals) --italic-text=always # Use C++ syntax for Arduino .ino files --map-syntax "*.ino:C++" # Use ".gitignore"-style highlighting for ".ignore" files --map-syntax ".ignore:Git Ignore" ``` ## Windows での `bat` の利用 Windows 上で `bat` はほとんど動作しますが、いくつかの機能は設定を必要をする場合があります。 ### ページング Windowsには、`more` 形式の非常に限られたページャーしか含まれていません。 `less` 用のWindowsバイナリは、[ホームページ](http://www.greenwoodsoftware.com/less/download.html) または [Chocolatey](https://chocolatey.org/packages/Less) からダウンロードできます。 これを使用するには、バイナリを `PATH` のディレクトリに配置するか、環境変数を定義します。[Chocolateyパッケージ](#on-windows) は `less` を自動的にインストールします。 ### 色 Windows 10では、`conhost.exe` (コマンドプロンプト)と [v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)) 以降の PowerShell の両方、 およびbashの新しいバージョンの色がネイティブにサポートされています。 以前のバージョンのWindowsでは、 [ConEmu](https://conemu.github.io/) を含む [Cmder](http://cmder.net/) を使用できます。 **注意:** Git と MSYS の `less` はWindows上で色を正しく解釈しません。 もし、あなたが他のページャーをインストールしていないのであれば、 `--paging=never` オプションを付け加えるか `BAT_PAGER` に空文字を設定することでページングを完全に無効にできます。 ### Cygwin Windows上の `bat` は Cygwin のunix風のpath(`/cygdrive/*`)をネイティブサポートしていません。絶対的なcygwinパスを引数として受けたときに、 `bat` は以下のエラーを返すでしょう: `The system cannot find the path specified. (os error 3)` wrapperを作成するか、以下の関数を `.bash_profile` に追記することで、この問題を解決することができます: ```bash bat() { local index local args=("$@") for index in $(seq 0 ${#args[@]}) ; do case "${args[index]}" in -*) continue;; *) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";; esac done command bat "${args[@]}" } ``` ## トラブルシューティング ### ターミナルと色 `bat` はターミナルがトゥルーカラーをサポートしている/していないに関係なくサポートします。 しかし、シンタックスハイライトのテーマの色が8-bitカラーに最適化されていない場合、 24-bitであるトゥルーカラーをサポートしているターミナルを使用することを強く推奨します(`terminator`, `konsole`, `iTerm2`, ...)。 この [記事](https://gist.github.com/XVilka/8346728) には 24-bitカラーがサポートされているターミナルの一覧が掲載されています。 本当の色をターミナルにセットするために、環境変数 `COLORTERM` に `truecolor` か `24bit` のどちらかを代入してください。さもなければ、`bat` はどの色を使うのか決定することができません。または、24-bit エスケープシーケンスがサポートされません (そして、8-bit colorに戻ります)。 ### 行番号とグリッド線がほとんど見えない 異なるテーマを試してみてください(`bat --list-themes` でテーマを閲覧できます)。 `OneHalfDark` と `OneHalfLight` テーマはグリッド線と線の色を明るくします。 ### ファイルエンコーディング `bat` は UTF-16 と同様に UTF-8 をネイティブにサポートします。 他のすべてのファイルエンコーディングでは、エンコーディングは通常自動検出できないため、最初に UTF-8 に変換する必要があります。 これを行うには `iconv` を使用できます。 例: Latin-1(ISO-8859-1)エンコーディングの PHP ファイルがある場合、次のように呼び出すことができます: ``` bash iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat ``` 注: `bat` が構文を自動検出できない場合は `-l` / `-language` オプションを使用する必要がある場合があります。 ## 開発 ```bash # Recursive clone to retrieve all submodules git clone --recursive https://github.com/sharkdp/bat # Build (debug version) cd bat cargo build --bins # Run unit tests and integration tests cargo test # Install (release version) cargo install --locked # Build a bat binary with modified syntaxes and themes bash assets/create.sh cargo install --locked --force ``` ## Maintainers - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) ## プロジェクトの目標と既存の類似したOSS `bat` は以下の目標を達成しようと試みています: - 美しく高度なシンタックスハイライトの提供 - ファイルの差分を表示するためのGitとの連携 - (POSIX) `cat` との完全互換 - ユーザーフレンドリーなコマンドラインインターフェースの提供 あなたが同様のプログラムを探しているなら、多くの選択肢があります。 比較については [このドキュメント](alternatives.md) を参照してください。 ## ライセンス Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). `bat` は MIT License 及び Apache License 2.0 の両方の条件の下で配布されています。 ライセンスの詳細については [LICENSE-APACHE](../LICENSE-APACHE) 及び [LICENSE-MIT](../LICENSE-MIT) ファイルを参照して下さい。 ================================================ FILE: doc/README-ko.md ================================================

bat - a cat clone with wings
Build Status license Version info
문법 강조와 Git 통합 기능의 cat(1) 클론

주요 기능들사용법설치사용자화프로젝트 목표와 대안들
[English] [中文] [日本語] [한국어] [Русский]

### 문법 강조 `bat`은 다양한 프로그래밍 및 마크업 언어의 문법 강조(syntax highlighting) 기능을 지원합니다: ![Syntax highlighting example](https://imgur.com/rGsdnDe.png) ### Git 통합 `bat`은 `git`을 통해 인덱스와 함께 변경분을 표시합니다 (왼쪽 사이드바를 확인하세요): ![Git integration example](https://i.imgur.com/2lSW4RE.png) ### 비인쇄 문자 처리 `-A`/`--show-all` 옵션을 사용하여 비인쇄 문자를 표시 및 강조할 수 있습니다: ![Non-printable character example](https://i.imgur.com/WndGp9H.png) ### 자동 페이징 `bat`은 기본적으로 한 화면에 비해 출력이 큰 경우 `less`와 같은 페이저(pager)로 출력을 연결(pipe)합니다. 만약 `bat`을 언제나 `cat`처럼 작동하게 하려면 (출력을 페이지하지 않기), `--paging=never` 옵션을 커맨드 라인이나 설정 파일에 넣을 수 있습니다. 셸(shell) 설정에서 `cat`을 `bat`의 alias로 사용하려면, `alias cat='bat --paging=never'`를 써서 기본 행동을 유지할 수 있습니다. ### 파일 연결(concatenation) 페이저(pager)를 사용하더라도 `bat`은 파일들을 연결(concatenate)할 수 있습니다 :wink:. `bat`이 비대화형(non-interactive) 터미널(예를 들어, 다른 프로세스나 파일에 연결(pipe)한 경우)을 감지하면, `bat`은 `--pager` 옵션의 값과 상관없이 `cat`과 동일하게 파일 내용을 그대로 출력합니다. ## 사용법 터미널에 하나의 파일 표시하기 ```bash > bat README.md ``` 여러 파일 한 번에 보여주기 ```bash > bat src/*.rs ``` stdin에서 읽고, 자동으로 맞는 문법 결정하기 (참고로, 문법 강조는 파일의 첫 줄만으로 문법이 결정될 수 있을 때만 작동합니다. 이는 보통 `#!/bin/sh`와 같은 셔뱅(shebang)으로 판단합니다.) ```bash > curl -s https://sh.rustup.rs | bat ``` stdin에서 읽고, 명시적으로 언어 지정하기 ```bash > yaml2json .travis.yml | json_pp | bat -l json ``` 비인쇄 문자 표시 및 강조하기 ```bash > bat -A /etc/hosts ``` `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'. ``` ### 다른 도구들과 통합하기 #### `fzf` `bat`을 [`fzf`](https://github.com/junegunn/fzf)의 프리뷰로 쓸 수 있습니다. 이를 위해서는 `bat`의 `--color=always` 옵션으로 항상 컬러 출력이 나오게 해야 합니다. 또한 `--line-range` 옵션으로 긴 파일의 로드 시간을 제한할 수 있습니다: ```bash fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' ``` 더 많은 정보는 [`fzf`의 `README`](https://github.com/junegunn/fzf#preview-window)를 참고하세요. #### `find`와 `fd` `find`의 `-exec` 옵션을 사용하여 모든 검색 결과를 `bat`로 미리 볼 수 있습니다: ```bash find … -exec bat {} + ``` [`fd`](https://github.com/sharkdp/fd)를 사용하는 경우, `-X`/`--exec-batch` 옵션을 이용하여 동일하게 사용할 수 있습니다: ```bash fd … -X bat ``` #### `ripgrep` [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md)을 통해 `bat`로 [`ripgrep`](https://github.com/BurntSushi/ripgrep)의 검색 결과를 출력할 수 있습니다. ```bash batgrep needle src/ ``` #### `tail -f` `bat`와 `tail -f`를 함께 사용하여 주어진 파일을 문법 강조하며 지속적으로 모니터할 수 있습니다. ```bash tail -f /var/log/pacman.log | bat --paging=never -l log ``` 참고로 이 작업을 하려면 페이징 기능을 꺼야 합니다. 또한 이 경우 문법을 자동 감지할 수 없기 때문에, 적용할 문법을 직접 지정해야 합니다 (`-l log`). #### `git` `bat`과 `git show`를 함께 사용하여 주어진 파일의 이전 버전을 올바른 문법 강조로 볼 수 있습니다: ```bash git show v0.6.0:src/main.rs | bat -l rs ``` #### `git diff` `bat`과 `git diff`를 함께 사용하여 수정된 코드 주위의 줄들을 올바른 문법 강조로 볼 수 있습니다: ```bash batdiff() { git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff } ``` 이것을 별도의 도구로 쓰고 싶다면 [`bat-extras`](https://github.com/eth-p/bat-extras)의 `batdiff`를 확인해 보세요. Git과 diff의 더 많은 지원을 원한다면 [`delta`](https://github.com/dandavison/delta)를 확인해 보세요. #### `xclip` `bat` 출력에 줄 번호와 Git 수정 내역이 포함되어서 파일의 내용을 복사하기 어려울 수 있습니다. 이 경우에는 `bat`의 `-p`/`--plain` 옵션을 사용하거나 간단히 `xclip`으로 출력을 연결(pipe)하면 됩니다: ```bash bat main.cpp | xclip ``` `bat`는 출력이 우회되고 있다는 것을 감지하여 파일 내용 그대로를 출력합니다. #### `man` `MANPAGER` 환경 변수 설정을 통해 `bat`을 `man`의 컬러 페이저(pager)로 쓸 수 있습니다. ```bash export MANPAGER="sh -c 'col -bx | bat -l man -p'" man 2 select ``` (Debian이나 Ubuntu를 사용한다면 `bat`을 `batcat`으로 치환하세요.) 포팻 문제가 발생한다면, `MANROFFOPT="-c"`을 써야 할 수 있습니다. 이 기능을 포함한 새로운 명령어를 선호한다면, [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md)을 쓸 수도 있습니다. 참고로 [Manpage 문법](../assets/syntaxes/Manpage.sublime-syntax)은 본 저장소에서 개발 중에 있으며, 아직 더 손봐야 합니다. 또한, 이는 Mandoc의 `man` 구현에서 [작동하지 않습니다](https://github.com/sharkdp/bat/issues/1145). #### `prettier` / `shfmt` / `rustfmt` [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) 스크립트는 코드를 포맷하고 `bat`으로 출력하는 래퍼(wrapper)입니다. ## 설치 [![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg?columns=3&exclude_unsupported=1)](https://repology.org/project/bat-cat/versions) ### Ubuntu에서 (`apt` 사용) *... 그리고 다른 Debian 기반의 Linux 배포판들에서.* `bat`은 [Ubuntu](https://packages.ubuntu.com/eoan/bat)와 [Debian](https://packages.debian.org/sid/bat) 패키지 배포 과정에 도입되는 중이며, Eoan 19.10 버전의 Ubuntu에서부터 제공됩니다. 현재 Debian에서는 불안정한 "Sid" 브랜치에서만 `bat`이 제공됩니다. 만약 충분히 최신 버전의 Ubuntu/Debian이 설치되어 있다면 간단히 다음을 실행하세요: ```bash apt install bat ``` **중요**: 만약 `bat`을 이와 같이 설치한다면, ([다른 패키지와의 이름 충돌](https://github.com/sharkdp/bat/issues/982)로 인하여) `bat` 대신에 `batcat`이라는 이름의 실행 파일로 설치될 수 있음을 참고하세요. 이에 따른 문제들과 다른 배포판들과의 일관성을 위하여 `bat -> batcat` symlink 혹은 alias를 설정할 수 있습니다: ``` bash mkdir -p ~/.local/bin ln -s /usr/bin/batcat ~/.local/bin/bat ``` ### Ubuntu에서 (가장 최신 `.deb` 패키지들 사용) *... 그리고 다른 Debian 기반의 Linux 배포판들에서.* 만약 여러분이 설치한 Ubuntu/Debian에 패키지가 배포되지 않거나 가장 최신 릴리즈된 `bat`을 원한다면, [릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 다음과 같이 `.deb` 패키지를 받아 설치하세요: ```bash sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture ``` ### Alpine Linux에서 적절한 저장소가 활성화되어 있다면, 공식 소스를 통해 [`bat` 패키지](https://pkgs.alpinelinux.org/packages?name=bat)를 설치할 수 있습니다: ```bash apk add bat ``` ### Arch Linux에서 공식 소스를 통해 [`bat` 패키지](https://www.archlinux.org/packages/extra/x86_64/bat/)를 설치할 수 있습니다: ```bash pacman -S bat ``` ### Fedora에서 공식 [Fedora 모듈](https://docs.fedoraproject.org/en-US/modularity/using-modules/) 저장소에서 [`bat` 패키지](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506)를 설치할 수 있습니다: ```bash dnf install bat ``` ### Funtoo Linux에서 dev-kit을 통해 [`bat` 패키지](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/bat)를 설치할 수 있습니다: ```bash emerge sys-apps/bat ``` ### Gentoo Linux에서 공식 소스를 통해 [`bat` 패키지](https://packages.gentoo.org/packages/sys-apps/bat)를 설치할 수 있습니다: ```bash emerge sys-apps/bat ``` ### Void Linux에서 xbps-install을 이용해 `bat`을 설치할 수 있습니다: ```bash xbps-install -S bat ``` ### Termux에서 pkg를 이용해 `bat`을 설치할 수 있습니다: ```bash pkg install bat ``` ### FreeBSD에서 pkg를 이용하여 미리 컴파일된 [`bat` 패키지](https://www.freshports.org/textproc/bat)를 설치할 수 있습니다: ```bash pkg install bat ``` 또는 FreeBSD 포트에서 직접 빌드할 수도 있습니다: ```bash cd /usr/ports/textproc/bat make install ``` ### nix를 써서 [nix package manager](https://nixos.org/nix)를 이용해 `bat`을 설치할 수 있습니다: ```bash nix-env -i bat ``` ### openSUSE에서 zypper를 이용해 `bat`을 설치할 수 있습니다: ```bash zypper install bat ``` ### snap 패키지를 써서 지금으로서는 추천하는 snap 패키지가 없습니다. 제공되는 패키지들이 존재할 수는 있지만, 공식적으로 지원되지 않으며 [문제](https://github.com/sharkdp/bat/issues/1519)가 있을 수 있습니다. ### macOS (또는 Linux)에서 Homebrew를 써서 [macOS의 Homebrew](https://formulae.brew.sh/formula/bat) 또는 [Linux의 Homebrew](https://formulae.brew.sh/formula-linux/bat)를 이용하여 `bat`을 설치할 수 있습니다. ```bash brew install bat ``` ### macOS에서 MacPorts를 써서 [MacPorts](https://ports.macports.org/port/bat/summary)를 이용하여 `bat`을 설치할 수 있습니다: ```bash port install bat ``` ### Windows에서 Windows에서 `bat`을 설치할 수 있는 몇 가지 옵션들이 있습니다. 먼저 `bat`을 설치한 후, ["Windows에서 `bat` 사용하기"](#windows에서-bat-사용하기) 섹션을 살펴보세요. #### 전제 조건 [Visual C++ 재배포 가능](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 패키지를 설치해야 합니다. #### Chocolatey를 써서 [Chocolatey](https://chocolatey.org/packages/Bat)를 이용해 `bat`을 설치할 수 있습니다: ```bash choco install bat ``` #### Scoop을 써서 [scoop](https://scoop.sh/)을 이용해 `bat`을 설치할 수 있습니다: ```bash scoop install bat ``` #### 사전 빌드된 바이너리들로 [릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 사전 빌드된 바이너리를 다운받을 수 있습니다. [Visual C++ 재배포 가능](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 패키지를 설치해야 합니다. ### 바이너리들로 [릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 다양한 아키텍처를 위해 사전 빌드된 버전들을 확인할 수 있습니다. 정적 링크 바이너리들은 파일 이름에 `musl` 이 포함된 아카이브들을 확인하세요. ### 소스에서 `bat`의 소스를 빌드하기 위해서는, Rust 1.79.0 이상이 필요합니다. `cargo`를 이용해 전부 빌드할 수 있습니다: ```bash cargo install --locked bat ``` 참고로 man 페이지나 셸 자동 완성 파일과 같은 부가 파일들은 이 방법으로 설치될 수 없습니다. 이것들은 `cargo`에 의해 생성이 되고 (`build` 밑의) cargo 타켓 폴더에서 찾을 수 있습니다. ## 사용자화 ### 문법 강조 테마 `bat --list-themes`을 사용하여 사용 가능한 문법 강조 테마들의 목록을 확인할 수 있습니다. `TwoDark` 테마를 선택하려면, `--theme=TwoDark` 옵션과 함께 `bat`을 사용하거나 `BAT_THEME` 환경 변수를 `TwoDark`로 설정하세요. 셸 시작 파일에 `export BAT_THEME="TwoDark"` 를 정의해 영구적으로 설정할 수 있습니다. 이 밖에 `bat`의 [설정 파일](#설정-파일)을 이용할 수 있습니다. 만약 다른 테마들을 사용하여 특정 파일을 보고 싶다면, 다음 명령어를 쓸 수 있습니다(이 경우 [`fzf`](https://github.com/junegunn/fzf)가 필요합니다.) ```bash bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" ``` `bat`은 기본적으로 어두운 배경에 적합합니다. 그러나 밝은 배경의 터미널을 사용한다면 `GitHub`이나 `OneHalfLight`과 같은 테마가 더 잘 어울립니다. 아래 [새로운 테마 추가하기](#새로운-테마-추가하기) 섹션에 따라 커스텀 테마를 사용할 수도 있습니다. ### 8비트 테마 `bat`은 트루컬러 지원이 되더라도 항상 [8비트 색상](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)을 사용하는 세 개의 테마가 있습니다. - `ansi`는 어떤 터미널에서도 무난하게 보입니다. 이는 3비트 색상을 사용합니다: 검정, 빨강, 녹색, 노랑, 파랑, 마젠타, 시안, 하양. - `base16`은 [base16](https://github.com/tinted-theming/home) 터미널 테마를 위해 디자인되었습니다. 이는 [base16 스타일 가이드라인](https://github.com/tinted-theming/home/blob/main/styling.md)에 따라 4비트 색상(3비트 색상에 밝은 변형 추가)을 사용합니다. - `base16-256`는 [base16-shell](https://github.com/tinted-theming/base16-shell)을 위해 디자인되었습니다. 이는 16부터 21의 일부 밝은 색상을 8비트 색상으로 대치합니다. 단지 256-색상 터미널을 쓰지만 base16-shell을 쓰지 않는다고 해서 이것을 사용하지 **마십시오**. 이들 테마는 더 제한적이지만, 트루컬러 테마에 비해 두 장점이 있습니다: - 이들은 3비트 혹은 4비트 색상을 쓰는 다른 터미널 소프트웨어와 더 잘 어울립니다. - 만약 터미널 테마를 바꾼다면, 이미 화면 상의 `bat`의 출력도 이에 맞추어 업데이트됩니다. ### 출력 스타일 `--style` 옵션을 이용하면 `bat`의 출력 모양을 조절할 수 있습니다. 예를 들어, `--style=numbers,changes`를 통해 Git 변경분과 줄 번호는 출력하지만 격자와 파일 헤더는 출력하지 않을 수 있습니다. `BAT_STYLE` 환경 변수를 정의하여 이러한 수정을 영구적으로 하거나 `bat`의 [설정 파일](#설정-파일)을 사용하세요. ### 새로운 문법 / 언어 정의 추가하기 만약 `bat`에서 특정 문법이 지원되지 않을 경우, 다음의 절차를 통해 현재 `bat` 설치본에 새로운 문법을 쉽게 추가할 수 있습니다. `bat`은 문법 강조를 위해 훌륭한 [`syntect`](https://github.com/trishume/syntect/) 라이브러리를 사용합니다. `syntect`는 임의의 [Sublime Text의 `.sublime-syntax` 파일](https://www.sublimetext.com/docs/3/syntax.html)과 테마를 읽을 수 있습니다. [Package Control](https://packagecontrol.io/)에 Sublime 문법 패키지를 찾는 방법이 잘 정리되어 있습니다. 일단 문법을 찾았다면: 1. 문법 정의 파일들을 넣을 폴더를 만듭니다: ```bash mkdir -p "$(bat --config-dir)/syntaxes" cd "$(bat --config-dir)/syntaxes" # Put new '.sublime-syntax' language definition files # in this folder (or its subdirectories), for example: git clone https://github.com/tellnobody1/sublime-purescript-syntax ``` 2. 이제 다음 명령어를 통해 파일들을 파싱(parse)하여 바이너리 캐시를 만듭니다. ```bash bat cache --build ``` 3. 마지막으로, `bat --list-languages`로 새로 추가한 언어가 사용 가능한지 확인합니다. 만약 기본 설정으로 돌아갈 일이 생긴다면, 다음 명령어를 이용합니다: ```bash bat cache --clear ``` 4. 만약 특정 문법이 `bat`에 기본적으로 포함되어 있어야 한다고 생각한다면, 방침과 절차를 [여기](../doc/assets.md)서 읽은 후 "문법 요청(syntax request)"을 열어 주세요: [문법 요청하기](https://github.com/sharkdp/bat/issues/new?labels=syntax-request&template=syntax_request.md). ### 새로운 테마 추가하기 이 과정은 새로운 문법 정의 추가 방식과 매우 비슷합니다. 먼저, 새로운 문법 강조 테마 폴더를 만듭니다. ```bash mkdir -p "$(bat --config-dir)/themes" cd "$(bat --config-dir)/themes" # Download a theme in '.tmTheme' format, for example: git clone https://github.com/greggb/sublime-snazzy # Update the binary cache bat cache --build ``` 마지막으로 `bat --list-themes`을 통해 새로 추가한 테마들이 사용 가능한지 확인합니다. ### 파일 타입 설정을 추가하거나 변경하기 새로운 파일 이름 패턴을 추가하려면 (혹은 이미 존재하는 것을 변경하려면) `--map-syntax` 커맨드 라인 옵션을 사용하세요. 이 옵션은 `pattern:syntax` 꼴의 인자를 받습니다. 이때 `pattern`은 파일 이름과 절대 파일 경로를 매치할 글로브(glob) 패턴입니다. `syntax` 부분은 지원되는 언어의 전체 이름입니다 (`bat --list-languages`를 통해 개요를 확인하세요). 참고: 이 옵션은 커맨드 라인에 넘겨 주는 것보다는 `bat`의 설정 파일에 넣는 것이 좋을 것입니다 (아래를 보세요). 예시: "INI" 문법 강조를 `.conf` 파일 확장자의 모든 파일에 적용하려면, 다음을 사용하세요: ```bash --map-syntax='*.conf:INI' ``` 예시: `.ignore`(완전 일치)이라는 이름의 모든 파일을 "Git Ignore" 문법으로 열려면, 다음을 사용하세요: ```bash --map-syntax='.ignore:Git Ignore' ``` 예시: `/etc/apache2`의 하위 폴더들에 있는 모든 `.conf` 파일들을 "Apache Conf" 문법으로 열려면, 다음을 사용하세요 (이 대응(mapping)은 이미 내장되어 있습니다): ```bash --map-syntax='/etc/apache2/**/*.conf:Apache Conf' ``` ### 다른 페이저 사용하기 `bat`은 환경 변수 `PAGER`에 명시된 페이저를 사용합니다. 이 변수가 정의되어 있지 않다면, `less`가 기본으로 사용됩니다. 만약 다른 페이저를 사용하고 싶다면, `PAGER` 변수를 수정하거나 `BAT_PAGER` 환경 변수를 설정하여 `PAGER`의 설정을 오버라이드(override)할 수 있습니다. 만약 커맨드라인 인수들을 페이저에게 넘겨 주려면, `PAGER`/`BAT_PAGER` 변수로 설정할 수 있습니다: ```bash export BAT_PAGER="less -RF" ``` 환경 변수를 사용하는 대신, `bat`의 [설정 파일](#설정-파일)로 페이저를 설정할 수도 있습니다 (`--pager` 옵션). **참고**: 기본적으로, 페이저가 `less`로 설정되어 있다면 (그리고 커맨드 라인 옵션이 지정되어 있지 않다면), `bat`은 다음 옵션들을 페이저로 넘겨줍니다: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` 그리고 `-X`/`--no-init`. 마지막 옵션(`-X`)은 530 이전 버전의 `less`에만 사용됩니다. `-R` 옵션은 ANSI 색상을 올바르게 해석하기 위해 필요합니다. 두 번째 옵션(`-F`)은 출력 크기가 터미널의 세로 크기보다 작을 경우 less가 즉시 종료되도록 합니다. 이는 작은 파일을 다룰 때 페이저를 종료하기 위해 `q`를 누를 필요 없어서 편리합니다. 세 번째 옵션(`-X`)는 예전 버전의 `less`에 있는 `--quit-if-one-screen` 기능의 버그를 고치기 위해 필요합니다. 안타깝게도, 이는 `less`의 마우스 휠 지원과 호환되지 않습니다. `less`의 예전 버전에서 마우스 휠 기능을 활성화하려면, `-R` 옵션을 넘겨주세요 (위의 예제처럼, 이 옵션은 quit-if-one-screen 기능을 비활성화합니다). less 530과 이후 버전에서는 그대로 사용할 수 있습니다. ### 들여쓰기 `bat`은 페이저에 의존하지 않고 탭을 4 스페이스로 확장합니다. 이를 변경하려면 간단히 `--tabs` 인자에 표시되기를 원하는 스페이스 개수를 추가하세요. **참고**: (`bat`의 `--pager` 인자 혹은 `less`의 `LESS` 환경 변수를 통해) 페이저의 탭 길이를 지정하는 것은 효과가 없을 것인데, 이는 페이저가 이미 스페이스로 확장된 탭을 받기 때문입니다. 이 기능은 사이드바에 의한 들여쓰기 문제를 회피하기 위해 추가되었습니다. `bat`을 `--tabs=0`과 함께 호출하면 이를 오버라이드하여 페이저가 탭을 처리하게 합니다. ### 다크 모드 macOS에서 다크 모드를 사용하고 있다면, `bat`가 OS 테마에 따라 다른 테마를 사용하도록 구성할 수 있습니다. 아래 스니펫은 _다크 모드_에서는 `default` 테마를, _라이트 모드_에서는 `GitHub` 테마를 사용하는 방법입니다. ```bash alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" ``` ## 설정 파일 `bat`는 설정 파일로도 사용자화 할 수 있습니다. 설정 파일의 위치는 운영 체제에 따라 다릅니다. 아래 커맨드를 통해 시스템의 기본 경로를 확인할 수 있습니다. ``` bat --config-file ``` 또는, `BAT_CONFIG_PATH` 환경 변수를 사용하여 `bat`가 설정 파일의 기본 경로 이외의 위치를 사용하도록 할 수 있습니다. ```bash export BAT_CONFIG_PATH="/path/to/bat.conf" ``` 기본 설정 파일은 `--generate-config-file` 옵션으로 생성할 수 있습니다. ```bash bat --generate-config-file ``` ### 포맷 설정 파일은 단순히 커맨드 라인 인자들의 리스트입니다. `bat --help`로 가능한 모든 옵션과 값들을 확인하세요. 추가적으로, 줄 앞에 `#` 문자를 추가해 주석을 넣을 수 있습니다. 설정 파일 예시: ```bash # "TwoDark" 테마 설정하기 --theme="TwoDark" # 줄 번호, Git 변경 내용, 파일 헤더 보이기 (격자 없이) --style="numbers,changes,header" # 터미널에서 이탤릭체 쓰기 (일부 터미널에서 미지원) --italic-text=always # Arduino .ino 파일에 C++ 문법 쓰기 --map-syntax "*.ino:C++" ``` ## Windows에서 `bat` 사용하기 `bat`는 대부분의 경우 Windows에서 기본적으로 잘 작동하지만, 일부 기능은 추가적인 구성이 필요할 수 있습니다. #### 전제 조건 [Visual C++ 재배포 가능](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 패키지를 설치해야 합니다. ### 페이징 Windows는 `more` 형식의 매우 제한된 페이저만 포함합니다. Windows용 `less` 바이너리는 [공식 홈페이지](http://www.greenwoodsoftware.com/less/download.html)나 [Chocolatey](https://chocolatey.org/packages/Less)를 통해 다운로드 받을 수 있습니다. 이를 사용하려면 디렉터리 안의 바이너리를 `PATH`에 넣거나 [환경 변수로 정의](#using-a-different-pager)하세요. [Chocolatey 패키지](#on-windows)는 `less`를 자동으로 설치합니다. ### 색상 Windows 10은 [v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update))부터 기본적으로 `conhost.exe`(Command Prompt)와 PowerShell에서 색상을 지원하며, 최신 버전의 bash에서도 색상을 지원합니다. 이전 버전의 Windows에서는, [ConEmu](https://conemu.github.io/)가 포함된 [Cmder](http://cmder.net/)를 사용할 수 있습니다. **참고:** Git과 MSYS 버전의 `less`는 Windows에서 색상을 올바르게 해석하지 않습니다. 다른 페이저가 설치되어 있지 않은 경우, `--paging=never`을 넘겨주거나 `BAT_PAGER`을 빈 문자열로 설정하여 페이징을 완전히 비활성화 할 수 있습니다. ### Cygwin Windows에서의 `bat`은 기본적으로 Cygwin의 unix 스타일 경로(`/cygdrive/*`)를 지원하지 않습니다. Cygwin 절대 경로를 인자로 받았을 때, `bat`은 다음과 같은 오류를 반환합니다: `The system cannot find the path specified. (os error 3)` 이는 wrapper를 만들거나 다음 함수를 `.bash_profile`에 추가하여 해결할 수 있습니다: ```bash bat() { local index local args=("$@") for index in $(seq 0 ${#args[@]}) ; do case "${args[index]}" in -*) continue;; *) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";; esac done command bat "${args[@]}" } ``` ## 문제 해결 ### 터미널과 색상 `bat`은 터미널의 트루컬러 지원 여부와 상관 없이 동작합니다. 그러나 대부분 문법 강조 테마의 색상은 8비트 색상에 최적화되어 있지 않습니다. 따라서 24비트 트루컬러 지원이 되는 터미널(`terminator`, `konsole`, `iTerm2`, ...)을 사용하는 것을 적극 권장합니다. 트루컬러를 지원하는 터미널들과 더 자세한 정보는 [이 글](https://gist.github.com/XVilka/8346728)에서 찾아보실 수 있습니다. 사용하고 있는 트루컬러 터미널에서 `COLORTERM` 변수를 `truecolor` 혹은 `24bit`로 설정되어 있는지 확인하세요. 그렇지 않을 경우, `bat`은 24비트 확장열(escape sequence)이 지원되는지 여부를 판단할 수 없습니다 (그리고 8비트 색상을 사용합니다). ### 줄 번호와 격자가 잘 보이지 않는 경우 다른 테마를 사용해 보세요 (`bat --list-themes`에서 목록을 볼 수 있습니다). `OneHalfDark`와 `OneHalfLight` 테마는 더 밝은 눈금과 선의 색상을 사용합니다. ### 파일 인코딩 `bat`은 기본적으로 UTF-8과 UTF-16을 지원합니다. 다른 모든 종류의 파일 인코딩에 대해서는, 일반적으로 인코딩을 자동으로 판별하는 방법이 없기 때문에 먼저 UTF-8으로 변환해야 할 수 있습니다. 이를 위해 `iconv`를 사용할 수 있습니다. 예시: Latin-1(ISO-8859-1)로 인코딩된 PHP 파일은 다음과 같이 처리할 수 있습니다: ``` bash iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat ``` 참고: `bat`으로 문법 자동 감지가 되지 않는 경우에는 `-l`/`--language` 옵션을 사용할 수 있습니다. ## 개발 ```bash # 모든 서브모듈을 받기 위해 재귀적으로 복제하기 git clone --recursive https://github.com/sharkdp/bat # (디버그 버전) 빌드 cd bat cargo build --bins # 단위 테스트와 통합 테스트 실행 cargo test # (배포 버전) 설치 cargo install --locked # 수정된 문법과 테마가 적용된 bat 바이너리 빌드 bash assets/create.sh cargo install --locked --force ``` `bat`의 pretty-printing 기능을 라이브러리로 사용하는 애플리케이션을 만들고 싶다면, [API 문서](https://docs.rs/bat/)를 살펴보세요. 참고로 `bat`에 라이브러리로써 의존한다면, `regex-onig`나 `regex-fancy`를 기능으로 사용해야 합니다. ## 기여하기 [`CONTRIBUTING.md`](../CONTRIBUTING.md) 가이드를 살펴보세요. ## 메인테이너들 - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) - [keith-hall](https://github.com/keith-hall) - [Enselic](https://github.com/Enselic) ## 보안 취약점 만약 `bat`의 취약점을 발견하였다면, [David Peter](https://david-peter.de/)에게 메일로 연락주시기 바랍니다. ## 프로젝트 목표와 대안들 `bat`은 다음과 같은 목표를 달성하려고 합니다: - 아름답고 발전된 문법 강조 기능 제공 - Git과의 연동을 통한 파일 변경 내용 확인 - (POSIX) `cat`의 대체제 - 사용자 친화적인 커맨드 라인 인터페이스 제공 비슷한 프로그램들을 찾고 있다면 많은 대안들이 있습니다. 비교는 [이 문서](../doc/alternatives.md)를 참조해 주세요. ## 라이센스 Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). `bat`는 여러분의 선택에 따라 MIT 라이센스 또는 Apache 라이센스 2.0의 조건에 따라 배포됩니다. 라이센스의 세부사항은 [LICENSE-APACHE](../LICENSE-APACHE)와 [LICENSE-MIT](../LICENSE-MIT)를 참조하세요. ================================================ FILE: doc/README-ru.md ================================================

bat - a cat clone with wings
Build Status license Version info
Клон утилиты cat(1) с поддержкой подсветки синтаксиса и Git

Ключевые возможностиИспользованиеУстановкаКастомизацияЦели и альтернативы
[English] [中文] [日本語] [한국어] [Русский]

### Подсветка синтаксиса `bat` поддерживает подсветку синтаксиса для огромного количества языков программирования и разметки: ![Пример подсветки синтаксиса](https://i.imgur.com/3FGy5tW.png) ### Интеграция с Git `bat` использует `git`, чтобы показать изменения в коде (смотрите на левый сайдбар): ![Пример интеграции с Git](https://i.imgur.com/azUAzdx.png) ### Показ непечатных символов Вы можете использовать флаг `-A` / `--show-all`, чтобы показать непечатные символы: ![Строка с неотображемыми символами](https://i.imgur.com/X0orYY9.png) ### Автоматический пейджинг терминала `bat` умеет перенаправлять вывод в пейджер терминала (например, в `less`), если вывод не помещается на экране полностью. Если вы хотите, чтобы `bat` работал как `cat` всё время, вы можете установить опцию `--paging=never` в командной строке или в конфигурационном файле. Если вы намерены использовать `bat` в качестве алиаса для `cat`, вы можете установить `alias cat='bat --paging=never'`, чтобы сохранить изначальное поведение. ### Объединение файлов О... Вы также можете объединять файлы :wink:. Когда `bat` обнаружит неинтерактивный терминал (например, когда вы перенаправляете вывод в файл или процесс), он будет работать как утилита `cat` и выведет содержимое файлов как обычный текст (без подсветки синтаксиса). ## Как использовать Вывести единственный файл в терминале ```bash > bat README.md ``` Отобразить сразу несколько файлов в терминале ```bash > bat src/*.rs ``` Читаем из stdin и определяем синтаксис автоматически (внимание: это делается по заглавной строке файла, например, `#!/bin/sh`) ```bash > curl -s https://sh.rustup.rs | bat ``` Прочитать из stdin с явным указанием языка ```bash > yaml2json .travis.yml | json_pp | bat -l json ``` Вывести и выделить неотображаемые символы ```bash > bat -A /etc/hosts ``` Использование в качестве замены `cat` ```bash bat > note.md # мгновенно создаем новый файл bat header.md content.md footer.md > document.md bat -n main.rs # показываем только количество строк bat f - g # выводит 'f', потом stdin, а потом 'g'. ``` ### Интеграция с другими утилитами #### `fzf` Вы можете использовать `bat` как просмотрщик для [`fzf`](https://github.com/junegunn/fzf). Чтобы это заработало, используйте опцию `--color=always`, чтобы вывод был всегда цветным. Вы можете также использовать опцию `--line-range`, чтобы уменьшить время загрузки для больших файлов: ```bash fzf --preview "bat --color=always --style=numbers --line-range=:500 {}" ``` Больше деталей смотрите в [`README` программы `fzf`](https://github.com/junegunn/fzf#preview-window). #### `find` или `fd` Вы можете использовать флаг `-exec` в `find`, чтобы посмотреть превью всех файлов в `bat` ```bash find … -exec bat {} + ``` Если вы используете [`fd`](https://github.com/sharkdp/fd), применяйте для этого флаг `-X`/`--exec-batch`: ```bash fd … -X bat ``` #### `ripgrep` С помощью [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md), `bat` может быть использован для вывода результата запроса [`ripgrep`](https://github.com/BurntSushi/ripgrep) ```bash batgrep needle src/ ``` #### `tail -f` `bat` может быть использован вместе с `tail -f`, чтобы выводить содержимое файла с подсветкой синтаксиса в реальном времени. ```bash tail -f /var/log/pacman.log | bat --paging=never -l log ``` Заметьте, что мы должны отключить пэйджинг, чтобы это заработало. Мы также явно указали синтаксис (`-l log`), так как он не может быть автоматически определен в данном случае. #### `git` Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с подсветкой синтаксиса: ```bash git show v0.6.0:src/main.rs | bat -l rs ``` #### `git diff` Вы можете использовать `bat` с `git diff` для просмотра строк кода вокруг изменений с подсветкой синтаксиса: ```bash batdiff() { git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff } ``` Если вы хотите использовать это как отдельную программу, посмотрите `batdiff` из [`bat-extras`](https://github.com/eth-p/bat-extras). Если вам это нужна более полная поддержка для операций с git и diff, посмотрите [`delta`](https://github.com/dandavison/delta). #### `xclip` Нумерация строк и отображение изменений затрудняет копирование содержимого файлов в буфер обмена. Чтобы справиться с этим, используйте флаг `-p`/`--plain` или просто перенаправьте стандартный вывод в `xclip`: ```bash bat main.cpp | xclip ``` `bat` обнаружит перенаправление вывода и выведет обычный текст без подсветки синтаксиса. #### `man` `bat` может быть использован для раскрашивания вывода `man`, для этого установите переменную окружения `MANPAGER`: ```bash export MANPAGER="sh -c 'col -bx | bat -l man -p'" man 2 select ``` (замените `bat` на `batcat`, если у вас Debian или Ubuntu) Возможно вам понадобится также установить `MANROFFOPT="-c"`, если у вас есть проблемы с форматированием. Если вы хотите сделать этой одной командой, вы можете использовать [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md). Обратите внимание, что [синтаксис manpage](assets/syntaxes/02_Extra/Manpage.sublime-syntax) разрабатывается в этом репозитории и все еще находится в разработке. Также заметьте, что это [не заработает](https://github.com/sharkdp/bat/issues/1145) с реализацией `man` через Mandocs. #### `prettier` / `shfmt` / `rustfmt` [`Prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) — скрипт, который форматирует код и выводит его с помощью `bat`. #### Подсветка сообщений `--help` Вы можете использовать `bat`, чтобы подсвечивать текст справки комманд: `$ cp --help | bat -plhelp` Вы можете сделать такую вспомогательную команду для этого: ```bash # in your .bashrc/.zshrc/*rc alias bathelp='bat --plain --language=help' help() { "$@" --help 2>&1 | bathelp } ``` В этом случае, вы можете просто писать `$ help cp` или `$ help git commit`. Если вы используете `zsh`, вы можете объявить глобальные алиасы для `-h` и `--help`: ```bash alias -g -- -h='-h 2>&1 | bat --language=help --style=plain' alias -g -- --help='--help 2>&1 | bat --language=help --style=plain' ``` В этом случае, вы можете продолжать использовать `cp --help`, но при этом получать подцвеченный вывод. Обратите внимание, что не всегда опция `-h` является краткой формы опции `--help` (например, у `ls`). Пожалуйста, сообщайте о проблемах с подсветкой справки в [этот репозиторий](https://github.com/victor-gp/cmd-help-sublime-syntax). ## Установка [![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg?columns=3&exclude_unsupported=1)](https://repology.org/project/bat-cat/versions) ### Ubuntu (с помощью `apt`) *... и другие дистрибутивы основанные на Debian.* `bat` доступен на [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) и [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). Если ваша версия Ubuntu/Debian достаточно новая, вы можете установить `bat` так: ```bash apt install bat ``` Если вы установили `bat` таким образом, то бинарный файл может быть установлен как `batcat` вместо `bat` (из-за [конфликта имени с другим пакетом](https://github.com/sharkdp/bat/issues/982)). Вы можете сделать симлинк или алиас `bat -> batcat`, чтобы предотвратить подобные проблемы и в других дистрибутивах. ``` bash mkdir -p ~/.local/bin ln -s /usr/bin/batcat ~/.local/bin/bat ``` ### Ubuntu (С помощью самого нового `.deb` пакета) *... и другие дистрибутивы Linux основанные на Debian* Если пакет еще недоступен в вашем Ubuntu/Debian дистрибутиве или вы хотите установить самую последнюю версию `bat`, то вы можете скачать самый последний `deb`-пакет отсюда: [release page](https://github.com/sharkdp/bat/releases) и установить так: ```bash sudo dpkg -i bat_0.18.3_amd64.deb # измените архитектуру и версию ``` ### Alpine Linux Вы можете установить [`bat`](https://pkgs.alpinelinux.org/packages?name=bat) из официальных источников: ```bash apk add bat ``` ### Arch Linux Вы можете установить [`bat`](https://www.archlinux.org/packages/extra/x86_64/bat/) из официального источника: ```bash pacman -S bat ``` ### Fedora Вы можете установить [`bat`](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) из официального репозитория [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/). ```bash dnf install bat ``` ### Gentoo Linux Вы можете установить [`bat`](https://packages.gentoo.org/packages/sys-apps/bat) из официальных источников: ```bash emerge sys-apps/bat ``` ### Void Linux Вы можете установить `bat` с помощью `xbps-install`: ```bash xbps-install -S bat ``` ### FreeBSD Вы можете установить [`bat`](https://www.freshports.org/textproc/bat) с помощью `pkg`: ```bash pkg install bat ``` или самому скомпилировать его: ```bash cd /usr/ports/textproc/bat make install ``` ### On OpenBSD Вы можете установить `bat` с помощью [`pkg_add(1)`](https://man.openbsd.org/pkg_add.1): ```bash pkg_add bat ``` ### С помощью nix Вы можете установить `bat`, используя [nix package manager](https://nixos.org/nix): ```bash nix-env -i bat ``` ### Через flox Вы можете установить `bat` используя [Flox](https://flox.dev) ```bash flox install bat ``` ### openSUSE Вы можете установить `bat` с помощью `zypper`: ```bash zypper install bat ``` ### На macOS (или Linux) через Homebrew Вы можете установить `bat` с помощью [Homebrew](http://braumeister.org/formula/bat): ```bash brew install bat ``` ### На macOS через MacPorts Или же установить его с помощью [MacPorts](https://ports.macports.org/port/bat/summary): ```bash port install bat ``` ### Windows Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#использование-bat-в-windows). #### Пререквитизы Вам нужно установить пакет [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). #### С помощью WinGet Вы можете установить `bat` через [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget): ```bash winget install sharkdp.bat ``` #### С помощью Chocolatey Вы можете установить `bat` с помощью [Chocolatey](https://chocolatey.org/packages/Bat): ```bash choco install bat ``` #### С помощью Scoop Вы можете установить `bat` с помощью [scoop](https://scoop.sh/): ```bash scoop install bat ``` #### Из заранее скомпилированных файлов: Их вы можете скачать на [странице релизов](https://github.com/sharkdp/bat/releases). ### Из скомпилированных файлов Перейдите на [страницу релизов](https://github.com/sharkdp/bat/releases) для скомпилированных файлов `bat` для различных платформ. Бинарные файлы со статической связкой так же доступны: выбирайте архив с `musl` в имени. ### Из исходников Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.79.0 или выше. После этого используйте `cargo`, чтобы всё скомпилировать: ```bash cargo install --locked bat ``` Заметьте, что дополнительные файлы, такие как документация man и подсказки командной строки, не могут быть установлены таким способом. Они будут сгенерированы командой `cargo` должны быть доступны в папке сборки (в `build`). Подсказки командной строки также доступны при таком запуске: ```bash bat --completion # see --help for supported shells ``` ## Кастомизация ### Темы для подсветки синтаксиса Используйте `bat --list-themes`, чтобы вывести список всех доступных тем. Для выбора темы `TwoDark` используйте `bat` с флагом `--theme=TwoDark` или выставьте переменную окружения `BAT_THEME` в `TwoDark`. Используйте `export BAT_THEME="TwoDark"` в конфигурационном файле вашей оболочки, чтобы изменить ее навсегда. Или же используйте [конфигурационный файл](https://github.com/sharkdp/bat#configuration-file) `bat`. Если вы хотите просто просмотреть темы, используйте следующую команду (для этого вам понадобится [`fzf`](https://github.com/junegunn/fzf)): ```bash bat --list-themes | fzf --preview="bat --theme={} --color=always /путь/к/файлу" ``` `bat` отлично смотрится на темном фоне. Однако если ваш терминал использует светлую тему, то такие темы как `GitHub` или `OneHalfLight` будут смотреться куда лучше! Вы также можете использовать новую тему, для этого перейдите [в раздел добавления тем](https://github.com/sharkdp/bat#добавление-новых-тем). ### Изменение внешнего вывода Вы можете использовать флаг `--style`, чтобы изменять внешний вид вывода в `bat`. Например, вы можете использовать `--style=numbers,changes`, чтобы показать только количество строк и изменений в Git. Установите переменную окружения `BAT_STYLE` чтобы изменить это навсегда, или используйте [конфиг файл](https://github.com/sharkdp/bat#configuration-file) `bat`. ### Добавление новых синтаксисов `bat` использует [`syntect`](https://github.com/trishume/syntect/) для подсветки синтаксиса. `syntect` может читать [файл `.sublime-syntax`](https://www.sublimetext.com/docs/3/syntax.html) и темы. Чтобы добавить новый синтаксис, сделайте следующее: Создайте каталог с синтаксисом: ```bash mkdir -p "$(bat --config-dir)/syntaxes" cd "$(bat --config-dir)/syntaxes" # Разместите файлы '.sublime-syntax' # в каталоге (или субкаталогах), например: git clone https://github.com/tellnobody1/sublime-purescript-syntax ``` Теперь используйте следующую команду, чтобы превратить эти файлы в бинарный кеш: ```bash bat cache --build ``` Теперь вы можете использовать `bat --list-languages`, чтобы проверить, доступны ли новые языки. Если когда-нибудь вы заходите вернуться к настройкам по умолчанию, введите ```bash bat cache --clear ``` ### Добавление новых тем Это работает похожим образом, так же как и добавление новых тем подсветки синтаксиса Во-первых, создайте каталог с новыми темами для синтаксиса: ```bash mkdir -p "$(bat --config-dir)/themes" cd "$(bat --config-dir)/themes" # Загрузите тему в формате '.tmTheme': git clone https://github.com/greggb/sublime-snazzy # Обновите кеш bat cache --build ``` Теперь используйте `bat --list-themes`, чтобы проверить доступность новых тем. ### Использование другого пейджера. `bat` использует пейджер, указанный в переменной окружения `PAGER`. Если она не задана, то используется `less`. Если вы желаете использовать другой пейджер, вы можете либо изменить переменную `PAGER`, либо `BAT_PAGER` чтобы перезаписать то, что указано в `PAGER`. Чтобы передать дополнительные аргументы вашему пейджеру, перечислите их в этой переменной: ```bash export BAT_PAGER="less -RF" ``` Так же вы можете использовать [файл конфигурации](https://github.com/sharkdp/bat#configuration-file) `bat` (флаг `--pager`). **Внимание**: По умолчанию пейджером является`less` (без каких-либо аргументов), `bat` задаст следующие флаги для пейджера: `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen` и `-X`/`--no-init`. Последний флаг(`-X`) используется только для `less`, чья версия раньше 530. Флаг `-R` нужен чтобы корректно воспроизвести ANSI цвета. Второй флаг (`-F`) говорит `less` чтобы тот сразу же завершился, если размер вывода меньше чем вертикальный размер терминала. Это удобно для небольших файлов, так как вам не надо каждый раз нажимать `q`, чтобы выйти из пейджера. Третий флаг (`-X`) нужен для того, чтобы исправить баг с `--quit-if-one-screen` в старых версиях `less`. К сожалению, это блокирует возможность использования колеса мышки. Если вы хотите все же его включить, вы можете добавить флаг `-R`. Для `less` новее чем 530 оно должно работать из коробки. ### Темная тема Если вы используете темный режим в macOS, возможно вы захотите чтобы `bat` использовал другую тему, основанную на теме вашей ОС. Следующий сниппет использует тему `default`, когда у вас включен темный режим, и тему `GitHub`, когда включен светлый. ```bash alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" ``` ## Файл конфигурации `bat` также может быть кастомизирован с помощью файла конфигурации. Его местоположение зависит от вашей ОС: чтобы посмотреть его путь, введите ``` bat --config-file ``` Также вы можете установить переменную окружения `BAT_CONFIG_PATH`, чтобы изменить путь к файлу конфигурации. ```bash export BAT_CONFIG_PATH="/path/to/bat.conf" ``` Файл конфигурации «по умолчанию» может быть создан с помощью флага `--generate-config-file`. ```bash bat --generate-config-file ``` ### Формат Файл конфигурации - это всего лишь набор аргументов. Введите `bat --help`, чтобы просмотреть список всех возможных флагов и аргументов. Также вы можете закомментировать строку с помощью `#`. Пример файла конфигурации: ```bash # Установить тему "TwoDark" --theme="TwoDark" # Показывать количество строк, изменений в Git и заголовок файла --style="numbers,changes,header" # Использовать курсив (поддерживается не всеми терминалами) --italic-text=always # Использовать синтаксис C++ для всех Arduino .ino файлов --map-syntax "*.ino:C++" # Использовать синтаксис Git Ignore для всех файлов .ignore --map-syntax ".ignore:Git Ignore" ``` ## Использование `bat` в Windows `bat` полностью работоспособен "из коробки", но для некоторых возможностей могут понадобиться дополнительные настройки. ### Пейджинг Windows поддерживает только очень простой пейджер `more`. Вы можете скачать установщик для `less` [с его сайта](http://www.greenwoodsoftware.com/less/download.html) или [через Chocolatey](https://chocolatey.org/packages/Less). Чтобы его использовать, скопируйте исполняемый файл в ваш `PATH` или [используйте переменную окружения](#Использование-другого-пейджера). [Пакет из Chocolatey](#windows) установит все автоматически. ### Цвета Windows 10 поддерживает цвета и в `conhost.exe` (Command Prompt), и в PowerShell начиная с версии Windows [v1511](https://ru.wikipedia.org/wiki/Windows_10#Обновления и поддержка), так же как и в bash. На ранних версиях Windows вы можете использовать [Cmder](http://cmder.net/), в котором есть [ConEmu](https://conemu.github.io/). **Внимание:** Версия `less` в Git и MSYS2 воспроизводит цвета некорректно. Если у вас нет других пейджеров, мы можете отключить использование пейджеров с помощью флага `--paging=never` или установить `BAT_PAGER` равным пустой строке. ### Cygwin Из коробки `bat` не поддерживает пути в стиле Unix (`/cygdrive/*`). Когда указан абсолютный путь cygwin, `bat` выдаст следующую ошибку: `The system cannot find the path specified. (os error 3)` Она может быть решена добавлением следующей функции в `.bash_profile`: ```bash bat() { local index local args=("$@") for index in $(seq 0 ${#args[@]}) ; do case "${args[index]}" in -*) continue;; *) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";; esac done command bat "${args[@]}" } ``` ## Проблемы и их решение ### Терминалы и цвета `bat` поддерживает терминалы *с* и *без* поддержки truecolor. Однако подсветка синтаксиса не оптимизирована для терминалов с 8-битными цветами, и рекомендуется использовать терминалы с поддержкой 24-битных цветов (`terminator`, `konsole`, `iTerm2`, ...). Смотрите [эту статью](https://gist.github.com/XVilka/8346728) для полного списка терминалов. Удостоверьтесь, что переменная `COLORTERM` равна `truecolor` или `24bit`. Иначе `bat` не сможет определить поддержку 24-битных цветов (и будет использовать 8-битные). ### Текст и номера строк плохо видны Используйте другую тему (`bat --list-themes` выведет список всех установленных тем). Темы `OneHalfDark` и `OneHalfLight` имеют более яркие номера строк и тексты. ### Кодировки файлов `bat` поддерживает UTF-8 и UTF-16. Файлы в других кодировках, возможно, придётся перекодировать, так как кодировка может быть распознана неверно. Используйте `iconv`. Пример: у вас есть PHP файл в кодировке Latin-1 (ISO-8859-1): ``` bash iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat ``` Внимание: вам может понадобиться флаг `-l`/`--language`, если `bat` не сможет автоматически определить синтаксис. ## Разработка ```bash # Рекурсивно клонирует все модули git clone --recursive https://github.com/sharkdp/bat # Компиляции в режиме разработки cd bat cargo build --bins # Запуск тестов cargo test # Установка (релизная версия) cargo install --locked # Компилирование исполняемого файла bat с другим синтаксисом и темами bash assets/create.sh cargo install --locked --force ``` ## Разработчики - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) ## Цели и альтернативы Цели проекта `bat`: - Красивая и продвинутая подсветка синтаксиса. - Интеграция с Git. - Полноценная замена `cat`. - Дружелюбный интерфейс и аргументы. Есть очень много альтернатив `bat`. Смотрите [этот документ](doc/alternatives.md) для сравнения. ## Лицензия Copyright (c) 2018-2024 [Разработчики bat](https://github.com/sharkdp/bat). `bat` распространяется под лицензиями MIT License и Apache License 2.0 (на выбор пользователя). Смотрите [LICENSE-APACHE](LICENSE-APACHE) и [LICENSE-MIT](LICENSE-MIT) для более подробного ознакомления. ================================================ FILE: doc/README-zh.md ================================================

bat - a cat clone with wings
Build Status license Version info
类似 cat(1),但带有 git 集成和语法高亮.

主要功能使用方法安装自定义项目目标和替代方案
[English] [中文] [日本語] [한국어] [Русский]

### 语法高亮 `bat` 对大部分编程语言和标记语言提供语法高亮: ![Syntax highlighting example](https://imgur.com/rGsdnDe.png) ### Git 集成 `bat` 能从 git 中获取文件的修改并展示在边栏(见下图): ![Git integration example](https://i.imgur.com/2lSW4RE.png) ### 不可打印(non-printable)字符可视化 添加`-A`/`--show-all`参数可以文件文件中的不可打印字符: ![Non-printable character example](https://i.imgur.com/WndGp9H.png) ### 自动分页 `bat`会在一般情况下将大于屏幕可显示范围的内容输出到分页器(pager, e.g. `less`)。 你可以在调用时添加`--paging=never`参数来使`bat`不使用分页器(就像`cat`一样)。如果你想要用为`cat`使用`bat`别名,可以在 shell 配置文件(shell configuration)中添加`alias cat='bat --paging=never'`。 #### 智能输出 `bat`能够在设置了分页器选项的同时进行管道:wink:。 当`bat`检测到当前环境为非可交互终端或管道时(例如使用`bat`并将内容用管道输出到文件),`bat`会像`cat`一样,一次输出文件内容为纯文本且无视`--paging`参数。 ## 如何使用 在终端中查看一个文件 ```bash > bat README.md ``` 一次性展示多个文件 ```bash > bat src/*.rs ``` 从`stdin`读入流,自动为内容添加语法高亮(前提是输入内容的语言可以被正确识别,通常根据内容第一行的 shebang 标记,形如`#!bin/sh`) ```bash > curl -s https://sh.rustup.rs | bat ``` 显式指定`stdin`输入的语言 ```bash > yaml2json .travis.yml | json_pp | bat -l json ``` 显示不可打印字符 ```bash > bat -A /etc/hosts ``` 与`cat`的兼容性 ```bash bat > note.md # 创建一个空文件 bat header.md content.md footer.md > document.md bat -n main.rs # 只显示行号 bat f - g # 输出 f,接着是标准输入流,最后 g ``` ### 第三方工具交互 #### `fzf` 你可以使用`bat`作为`fzf`的预览器。这需要在`bat`后添加`--color=always`选项,以及`--line-range` 选项来限制大文件的加载次数。 ```bash fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' ``` 更多信息请参阅[`fzf`的说明](https://github.com/junegunn/fzf#preview-window)。 #### `find` 或 `fd` 你可以使用`find`的`-exec`选项来用`bat`预览搜索结果: ```bash find … -exec bat {} + ``` 亦或者在用`fd`时添加`-X`/`--exec-batch`选项: ```bash fd … -X bat ``` #### `ripgrep` `bat`也能用`batgrep`来显示`ripgrep`的搜索结果。 ```bash batgrep needle src/ ``` #### `tail -f` 当与`tail -f`一起使用,`bat`可以持续监视文件内容并为其添加语法高亮。 ```bash tail -f /var/log/pacman.log | bat --paging=never -l log ``` 注意:这项功能需要在关闭分页时使用,同时要手动指定输入的内容语法(通过`-l log`)。 #### `git` `bat`也能直接接受来自`git show`的输出并为其添加语法高亮(当然也需要手动指定语法): ```bash git show v0.6.0:src/main.rs | bat -l rs ``` #### `git diff` `bat`也可以和`git diff`一起使用: ```bash batdiff() { git diff --name-only --relative --diff-filter=d -z | xargs -0 bat --diff } ``` 该功能也作为一个独立工具提供,你可以在[`bat-extras`](https://github.com/eth-p/bat-extras)中找到`batdiff`。 如果你想了解更多 git 和 diff 的信息,参阅[`delta`](https://github.com/dandavison/delta)。 #### `xclip` 当需要拷贝文件内容时,行号以及 git 标记会影响输出,此时可以使用`-p`/`--plain`参数来把纯文本传递给`xclip`。 ```bash bat main.cpp | xclip ``` `bat`会检测输出是否是管道重定向来决定是否使用纯文本输出。 #### `man` `bat` 可以通过设置 `MANPAGER` 环境变量,用作 `man` 的彩色分页器: ```bash export MANPAGER="sh -c 'awk '\''{ gsub(/\x1B\[[0-9;]*m/, \"\", \$0); gsub(/.\x08/, \"\", \$0); print }'\'' | bat -p -lman'" man 2 select ``` (如果你使用 Debian 或 Ubuntu,请将 `batcat` 替换为 `bat`) 如果你希望将其打包为一个新的命令,也可以使用 [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md)。 > [!WARNING] > 在使用 Mandoc 的 `man` 实现时,这[无法](https://github.com/sharkdp/bat/issues/1145)直接工作。 > > 请使用 `batman`,或将此 Shell 脚本包装为 [Shebang 可执行文件](https://en.wikipedia.org/wiki/Shebang_(Unix)),并将 `MANPAGER` 指向该文件。 注意,[Manpage 语法](assets/syntaxes/02_Extra/Manpage.sublime-syntax)是在此仓库中开发的,仍需一些改进。 #### `prettier` / `shfmt` / `rustfmt` `prettybat`脚本能够格式化代码并用`bat`输出。 ## 安装 [![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg?columns=3&exclude_unsupported=1)](https://repology.org/project/bat-cat/versions) ### Ubuntu (使用 `apt`) *... 以及其他基于 Debian的发行版.* `bat` 要求的版本: [Ubuntu 高于 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) 和 [Debian 高于 August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). 当你的发行版满足条件那么直接在终端运执行: ```bash sudo apt install bat ``` 重要:如果你通过这种方法安装`bat`,请留意你所安装的可执行文件是否为`batcat`(由[其他包的可执行文件名冲突](https://github.com/sharkdp/bat/issues/982)造成)。你可以创建一个`bat -> batcat`的符号链接(symlink)或别名来避免因为可执行文件不同带来的问题并与其他发行版保持一致性。 ```bash mkdir -p ~/.local/bin ln -s /usr/bin/batcat ~/.local/bin/bat ``` ### Ubuntu (使用`.deb`包) *... 以及其他基于 Debian的发行版.* 如果你无法使用上一种方法安装,或需要用最新版的`bat`,你可以从[release 页面](https://github.com/sharkdp/bat/releases)下载最新的`.deb`包并通过下述方法安装: ```bash sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture ``` ### Alpine Linux 你可以用下面下列命令从官方源中安装[`bat 包`](https://pkgs.alpinelinux.org/packages?name=bat): ```bash apk add bat ``` ### Arch Linux 你可以用下面下列命令从官方源中安装[`bat`包](https://www.archlinux.org/packages/extra/x86_64/bat/): ```bash pacman -S bat ``` ### Fedora 你可以使用下列命令从官方[Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/)仓库安装[`bat` 包](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506): ```bash dnf install bat ``` ### Funtoo Linux 你可以从 dev-kit 中安装[`bat` 包](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/bat): ```bash emerge sys-apps/bat ``` ### Gentoo Linux 你可以使用下列命令从官方源中安装 [`bat` 包](https://packages.gentoo.org/packages/sys-apps/bat): ```bash emerge sys-apps/bat ``` ### Void Linux 你可以用 xbps-install 安装`bat`: ```bash xbps-install -S bat ``` ### Termux: 你可以用 pkg 安装`bat: ```bash pkg install bat ``` ### FreeBSD 你可以用 pkg 来安装一份预编译的[`bat` 包](https://www.freshports.org/textproc/bat): ```bash pkg install bat ``` 或从 FreeBSD ports 自己编译一份: ```bash cd /usr/ports/textproc/bat make install ``` ### OpenBSD 你可以用`pkg——add`安装`bat`包 ```bash pkg_add bat ``` ### 通过 nix 你可以用[nix 包管理器](https://nixos.org/nix)安装`bat`: ```bash nix-env -i bat ``` ### openSUSE 你可以用 zypper 安装`bat`: ```bash zypper install bat ``` ### 通过 snap 目前还没有推荐的 snap 包可用。可以使用其他现存的包但不会受到官方支持且可能会遇到[问题](https://github.com/sharkdp/bat/issues/1519)。 ### macOS (或 Linux) 通过 Homebrew 你可以用 [Homebrew on MacOS](https://formulae.brew.sh/formula/bat) 或者 [Homebrew on Linux](https://formulae.brew.sh/formula-linux/bat) 安装`bat`: ```bash brew install bat ``` ### macOS 通过 MacPorts 或用 [MacPorts](https://ports.macports.org/port/bat/summary) 安装`bat`: ```bash port install bat ``` ### Windows 在 Windows 上具有多种安装`bat`的方法。若你已完成安装,记得看看 ["在 Windows 上使用`bat`"](#在-Windows-中使用-bat) 。 #### 前置条件 你必须已安装 [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 包。 #### 使用 Chocolatey 你可以用[Chocolatey](https://chocolatey.org/packages/Bat) 安装`bat`: ```bash choco install bat ``` #### 使用 Scoop 你可以用 [scoop](https://scoop.sh/) 安装`bat`: ```bash scoop install bat ``` #### 使用预编译二进制版本 直接从 [Release 发布页](https://github.com/sharkdp/bat/releases) 下载已经编译好的二进制包,前提是你安装了 [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 包。 ### 使用二进制版本 在 [Release 发布页](https://github.com/sharkdp/bat/releases) 中可以找到为多种架构构建的`bat`版本和静态编译的二进制文件(文件名带有`musl`)。 ### 从源码编译 如果你想要自己构建`bat`,那么你需要安装有高于1.74.0版本的 Rust。 使用以下命令编译。 ```bash cargo install --locked bat ``` 注意:man page或 shell 自动补全所需要的额外文件无法通过该方法安装。但你可以在`cargo`的生成目录找到这些文件(`build`目录下)。 ## 自定义 ### 语法高亮主题 使用 `bat --list-themes` 一份语法高亮主题的清单,然后用`--theme=TwoDark`来指定主题为`TwoDark`,也可以通过设置`BAT_THEME`环境变量来选定主题。把`export BAT_THEME="TwoDark"`添加到 shell 的启动脚本(shell startup file)来取得永久效果。或者使用`bat`的[配置文件](#c配置文件) 若想要查看所有主题在一个文件上的显示效果可以用一下命令(需要安装`fzf`): ```bash bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" ``` `bat`在默认情况下能够在黑色主题背景下获得较好的效果,如果你的终端使用亮色背景,可以试试`GitHub`或`OneHalfLight`。想要添加自定义主题可以参考[添加主题](#添加主题)。 ### 8-bit 主题 `bat` 自带三个 [8-bit 色彩](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 主题: - `ansi` 适应于大部分终端。它使用 3-bit 色彩:黑红绿黄蓝洋红靛青白。 - `base16`专为 [base16](https://github.com/tinted-theming/home) 终端设计。它使用 4-bit 色彩(带有亮度的 3-bit 色彩)。根据 [base16 styling guidelines](https://github.com/tinted-theming/home/blob/main/styling.md) 制作。 - `base16-25`专为 [base16-shell](https://github.com/tinted-theming/base16-shell) 设计。它把部分亮色替换为 8-bit 色彩。请不要直接使用该主题,除非你清楚你的256色终端是否使用 base16-shell。 尽管这些主题具有诸多限制,但具有一些 truecolor 主题不具有的三个优点: - 享有最佳兼容性。并不是所有终端工具都支持高于 3-bit 的色彩。 - 适应终端主题。 - 视觉上和其他的终端工具更协调。 ### 输出样式 你可以用`--style`参数来控制`bat`输出的样式。使用`--style=numbers,changes`可以只开启 Git 修改和行号显示而不添加其他内容。`BAT_STYLE`环境变量具有相同功能。 ### 添加新的语言和语法 当现有的`bat`不支持某个语言或语法时你可以自己添加。 `bat`使用`syntect`库来支持语法高亮,该库使用 [Sublime Text `.sublime-syntax` 语法文件](https://www.sublimetext.com/docs/3/syntax.html)和主题。而后者中的大部分可以在 [Package Control](https://packagecontrol.io/) 找到。 当你找到一份语法文件,按照下列方法: 1. 创建包含语法描述文件的目录: ```bash mkdir -p "$(bat --config-dir)/syntaxes" cd "$(bat --config-dir)/syntaxes" # Put new '.sublime-syntax' language definition files # in this folder (or its subdirectories), for example: git clone https://github.com/tellnobody1/sublime-purescript-syntax ``` 2. 调用下面指令把文件转换为二进制缓存: ```bash bat cache --build ``` 3. 最后用`bat --list-languages`来检查新的语法是否被成功导入。如果想要回滚到最初状态,执行: ```bash bat cache --clear ``` 4. 如果你觉得`bat`有必要自带该语法支持,请在阅读[指导](doc/assets.md)后向仓库提交 [Syntax Request](https://github.com/sharkdp/bat/issues/new?labels=syntax-request&template=syntax_request.md)。 ### 添加主题 类似添加语法支持,第一步也是创建一个带有语法高亮的目录 ```bash mkdir -p "$(bat --config-dir)/themes" cd "$(bat --config-dir)/themes" # 下载一个主题 git clone https://github.com/greggb/sublime-snazzy # 更新二进制缓存 bat cache --build ``` 然后用`bat --list-themes`检查添加是否成功。 ### 添加或修改文件关联 你可以用`--map-syntax`参数添加或修改文件名模板。它需要一个类似`pattern:syntax`的参数来指定,其中`pattern`是 glob 文件匹配模板,`syntax`则是支持的语法的完整名(使用`bat --list-languages`来查看获取一份清单)。 注意:方便起见,你可能需要把参数添加到配置文件,而不是每次都在命令行中传递该参数。 以下展示了把“INI”关联到具有`.conf`扩展名的文件 ```bash --map-syntax='*.conf:INI' ``` 把`.ignore`文件与“Git Ignore”关联 ```bash --map-syntax='.ignore:Git Ignore' ``` 把`/etc/apache2`内的`.conf`文件关联到“Apache Conf”语法(`bat`已默认绑定) ```bash --map-syntax='/etc/apache2/**/*.conf:Apache Conf' ``` ### 使用自定义分页器 `bat`默认使用`PAGER`环境变量定义的分页器,如果没有定义则使用`less`。`bat`提供了`BAT_PAGER`环境变量来专为`bat`选择分页器(优先级高于`PAGER`)。 注意:当`PAGER`设置为`more`或`most`时,`bat`会使用`less`来代替以确保能提供色彩支持。 ```bash export BAT_PAGER="less -RF" ``` 除了使用环境变量来改变`bat`使用的的分页器,也可以在配置文件中提供`--pager`参数。 注意:`bat`会把部分命令行参数直接传递给分页器:`-R`/`--RAW-CONTROL-CHARS`,`-F`/`--quit-if-one-screen`以及`-X`/`--no-init`(该参数仅适用于高于530版本的`less`)。其中`-R` 参数需要在解释 ANSI 标准颜色时起作用。`-F`则指示`less`在输出内容的垂直尺寸小于终端尺寸时立即退出。当文件内容可以在一个屏幕里完全显示时,就不需要按`q`键退出阅读模式,很方便就是了。`-X`则能修复`-F`在`less`的老版本中的一些bug(代价是不支持鼠标滚轮,但可以用`-R`来取消`quit-if-one-screen`功能。)。 ### 缩进 `bat` 使用四个空格宽的制表符,而不受分页器影响,同时也可以用`--tabs`参数来自定义。 注意:通过其他方法针对分页器的制表符设置不会生效(例如通过`bat`的`--pager`参数传递或`less`使用的`LESS`环境变量)。因为在输出提交给分页器之前,内容中的制表符就已经被`bat`替换为了特定长度的空格以避免由于边栏导致的缩进问题。你可以用给`bat`传递`--tabs=0`参数来取消该设定并让分页器自己处理制表符。 ### 暗色模式 如果你用的 macOS 处于暗色模式,你可以为`bat`启用基于系统主题的主题。如下所示操作会让`bat`在系统处于亮色模式时加载`GitHub`主题和暗色模式时加载`default`主题。 ```bash alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" ``` ## 配置文件 ```bash bat --config-file ``` 你也可以用`BAT_CONFIG_PATH`来为`bat`指定自定义位置的配置文件: ```bash export BAT_CONFIG_PATH="/path/to/bat.conf" ``` 使用`--generate-config-file`参数调用`bat`会在指定位置生成一份默认的`bat`配置文件: ```bash bat --generate-config-file ``` ### 格式 配置文件其实是一份按行分割的命令行参数列表。你可以用`bat --help`来查看所有可用的参数和适用的值。配置文件中`#`打头的行会被视为注释而不生效。 以下是一份示例: ```bash # 设置主题为 TwoDark --theme="TwoDark" # 显示行号和 Git 修改信息, 但没有边框 --style="numbers,changes,header" # 在终端中以斜体输出文本(不是所有终端都支持) --italic-text=always # 使用 C++ 语法来给 Arduino 的 .ino 文件提供高亮 --map-syntax "*.ino:C++" ``` ## 在 Windows 中使用 `bat` `bat` 在 Windows 上开箱即用,除了部分功能需要额外配置。 ### 前置条件 你需要先安装 [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) 包。 ### 分页 Windows 只有一个提供有限功能的分页器,你可以从[这里下载](http://www.greenwoodsoftware.com/less/download.html)或用 [Chocolatey 安装](https://chocolatey.org/packages/Less) Windows 版本的`less`。第一种方法需要你把它所在目录加入`PATH`环境变量或[定义分页器变量](#使用自定义分页器) ### 色彩 Windows 10 从 [v1511](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1511_(November_Update)) 开始 shell(`conhost.exe`,命令提示符或 Powershell)原生支持色彩。在早些版本的 Windows 中你可以用第三方终端如 [Cmder](http://cmder.net/) (使用[ConEmu](https://conemu.github.io/))。 注意:Git 和 MSYS 版本的 `less` 没法正确在 Windows 表达色彩。如果你没有安装其他分页器,你可以直接用`--paging=never`或设置`BAT_PAGER`为空字符串来关闭分页功能。 ### Cygwin Windows 上的`bat`原生不支持 Cygwin' unix-style 路径(`/cygdrive/*`)。当传递一个绝对 cygwin 路径作为参数值时,`bat`会产生`The system cannot find the path specified. (os error 3)`的错误。你可以`.bash_profile`文件中添加以下函数来解决这个问题。 ```bash bat() { local index local args=("$@") for index in $(seq 0 ${#args[@]}) ; do case "${args[index]}" in -*) continue;; *) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}")";; esac done command bat "${args[@]}" } ``` ## 疑难解答 ### 输出内容含糊不清 当输入文件包含颜色代码和其他 ANSI 转义符号时,`bat`会产生错误的语法高亮和文本,导致输出看起来令人无法理解。当你需要输出该文件时,请使用`--color=never --wrap=never`参数来关闭上色和文字包裹。 ### 终端与色彩 `bat`会区分支持 truecolor 和不支持 truecolor 的终端。但是大部分语法高亮主题都是用了没有为 8-bit 色彩支持的颜色,因此强烈推荐使用一个支持 24-bit 色彩的终端(`terminator`,`konsole`,`iTerm2`...),或使用一个 [8-bit 主题](#8-bit-主题)来限制一些颜色。查看[这篇文章使用自定义分页器](https://gist.github.com/XVilka/8346728)了解更多支持 truecolor 的终端。你需要定义`COLORTERM`变量为`truecolor`或`24bit`来确保`bat`能够识别终端的对颜色的支持,否则会使用 8 bit 模式。 ### 行号和边框很难看清 试试其他主题,说不定能有所改善(用`bat --list-themes`查看主题列表)。 ### 文件编码 `bat`原生支持 UTF-8 和 UTF-16。至于其他文件你可能需要在使用`bat`之前先把编码转换到UTF-8。 这里展示了使用`iconv`来把 Latin-1(ISO-8859-1) 编码的 PHP 文件转换到 UTF-8: ```bash iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat ``` 注意: 当`bat`无法识别语言时你可能会需要`-l`/`--language`参数。 ## 开发 ```bash # 递归 clone 以获取所有子模块 git clone --recursive https://github.com/sharkdp/bat # 构建(调试版本) cd bat cargo build --bins # 运行单元测试和集成测试 cargo test # 安装(发布版本) cargo install --path . --locked # 使用修改后的语法和主题构建一个 bat 二进制文件 bash assets/create.sh cargo install --path . --locked --force ``` 如果你想构建一个使用 `bat` 美化打印功能的应用程序,请查看 [API 文档](https://docs.rs/bat/)。请注意,当你依赖 `bat` 作为库时,必须使用 `regex-onig` 或 `regex-fancy` 作为特性。 ## 贡献指南 请查看 [`CONTRIBUTING.md`](CONTRIBUTING.md) 指南。 ## 维护者 - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) - [keith-hall](https://github.com/keith-hall) - [Enselic](https://github.com/Enselic) ## 安全漏洞 如果你想报告 `bat` 中的漏洞,请通过邮件联系 [David Peter](https://david-peter.de/)。 ## 项目目标和替代方案 `bat` 试图实现以下目标: - 提供美观的高级语法高亮 - 与 Git 集成以显示文件修改 - 成为 (POSIX) `cat` 的替代品 - 提供用户友好的命令行界面 如果你在寻找类似的程序,有很多替代方案。请参阅[本文档](doc/alternatives.md)进行比较。 ## 许可证 版权所有 (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat)。 `bat` 可根据 MIT 许可证或 Apache 许可证 2.0 的条款使用,任选其一。 有关许可证的详细信息,请参阅 [LICENSE-APACHE](LICENSE-APACHE) 和 [LICENSE-MIT](LICENSE-MIT) 文件。 ================================================ FILE: doc/alternatives.md ================================================ # 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) | [clp](https://github.com/jpe90/clp) | |----------------------------------------------|---------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------|------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------| | Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (✔️) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: | :x: | | Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: | :x: | | Languages (circa) | 150 | 300 | 200 | 7 | 80 | 130 | 30 | 130 | 150 | | Extensible (languages, themes) | :heavy_check_mark: | (✔️) | (✔️) | :x: | (✔️) | :x: | :x: | :x: | :heavy_check_mark: | | Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (✔️) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Execution time [ms] (`jquery-3.3.1.js`) | 422 | 455 | 299 | 39 | 208 | 287 | 128 | 740 | 22 | | Execution time [ms] (`miniz.c`) | 27 | 169 | 19 | 4 | 36 | 131 | 58 | 231 | 4 | | Execution time [ms] (957 kB XML file) | 215 | 296 | 236 | 165 | 83 | 412 | 135 | 386 | 127 | 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) - [vimpager](https://github.com/rkitover/vimpager) ## Benchmarks The benchmarks above have been created with this script: ```bash #!/usr/bin/env bash cd "$(dirname "${BASH_SOURCE[0]}")" || exit if ! command -v hyperfine > /dev/null 2>&1; then echo "'hyperfine' does not seem to be installed." echo "You can get it here: https://github.com/sharkdp/hyperfine" exit 1 fi SRC="test-src/jquery-3.3.1.js" cmd_bat="bat --style=full --color=always --paging=never '$SRC'" cmd_bat_simple="bat --plain --wrap=never --tabs=0 --color=always --paging=never '$SRC'" cmd_pygmentize="pygmentize -g '$SRC'" cmd_highlight="highlight -O truecolor '$SRC'" cmd_ccat="ccat --color=always '$SRC'" cmd_source_highlight="source-highlight --failsafe --infer-lang -f esc -i '$SRC'" cmd_hicat="hicat '$SRC'" cmd_coderay="coderay '$SRC'" cmd_rouge="rougify '$SRC'" cmd_clp="clp '$SRC'" hyperfine --warmup 3 \ "$cmd_bat" \ "$cmd_bat_simple" \ "$cmd_pygmentize" \ "$cmd_highlight" \ "$cmd_ccat" \ "$cmd_source_highlight" \ "$cmd_hicat" \ "$cmd_coderay" \ "$cmd_rouge" \ "$cmd_clp" \ ``` ================================================ FILE: doc/assets.md ================================================ ## Adding new builtin languages for syntax highlighting Should you find that a particular syntax is not available within `bat` and think it should be included in `bat` by default, you can follow the instructions outlined below. `bat` uses the excellent [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. **Important:** Before proceeding, verify that the syntax you wish to add meets the [criteria for inclusion](#Criteria-for-inclusion-of-new-syntaxes). 1. Find a Sublime Text syntax for the given language, preferably in a separate Git repository which can be included as a submodule (under `assets/syntaxes`) using `git submodule add ./assets/syntaxes/02_Extra/`, replacing the contents of the angle brackets as appropriate. 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. If only `.tmLanguage.json` or `.tmLanguage.yml` file is available, use [PackageDev](https://packagecontrol.io/packages/PackageDev) to convert it to `.tmLanguage.plist` format and then rename the converted file to `.tmLanguage` file. 3. Run the `assets/create.sh` script. It calls `bat cache --build` to parse all available `.sublime-syntax` files and serialize them to a `syntaxes.bin` file. 4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the `bat` binary. 5. Use `bat --list-languages` to check if the new languages are available. You may want to do something like ``export PATH="`pwd`/target/debug:$PATH"`` to ensure the locally compiled version is the one being used. 6. Add a syntax test for the new language. See [below](#Syntax-tests) for details. 7. If you send a pull request with your changes, please do *not* include the changed `syntaxes.bin` file. A new binary cache file will be created once before every new release of `bat`. This avoids bloating the repository size unnecessarily. ### Syntax tests `bat` has a set of syntax highlighting regression tests in `tests/syntax-tests`. The main idea is make sure that we do not run into issues we had in the past where either (1) syntax highlighting for some language is suddenly not working anymore or (2) `bat` suddenly crashes for some input (due to `regex` incompatibilities between `syntect` and Sublime Text). In order to add a new test file, please follow these steps (let's take "Ruby" as an example): 1. Make sure that you are running the **latest version of `bat`** and that `bat` is available on the path. If you are creating a syntax test for a new builtin syntax (see above), make sure that your version of `bat` already has the new syntax builtin. 2. Find an example Ruby source file or write one yourself. If possible, the file should aim to be "comprehensive" (i.e. include a lot of the possible syntax), but this is not strictly necessary. A simple file is better than none at all. Also, the files shouldn't be gigantic. 3. Save the file in `tests/syntax-tests/source/Ruby` (adapt for your language). The file name could be `test.rb` (adapt extension) but can also be adapted if that is necessary in order for `bat` to highlight it correctly (e.g. `Makefile`). 4. If you have copied the file from somewhere else, please make sure that the file *may* be copied under the respective license and that the license is compatible with `bat`s license. If it requires attribution, please add a `LICENSE.md` in the same folder with a text like this: ``` The `test.rb` file has been added from [enter source here] under the following license: [add license text here] ``` 5. Go to `tests/syntax-tests` and run the `update.sh` Bash script. A new file should be generated in the `highlighted` folder (e.g. `highlighted/Ruby/test.rb`). 6. Use `cat` or `bat --language=txt` to display the content of this file and make sure that the syntax highlighting looks correct. 7. `git add` the new files in the `source` folder as well as the autogenerated files in the `highlighted` folder. ### Troubleshooting Make sure that the local cache does not interfere with the internally stored syntaxes and themes (`bat cache --clear`). ## Criteria for inclusion of new syntaxes * More than 10,000 downloads at [Package Control](https://packagecontrol.io) ### Manual modifications The following files have been manually modified after converting from a `.tmLanguage` file: * `Apache.sublime_syntax`=> removed `conf` and `CONF` file types. * `Dart.sublime-syntax` => removed `#regex.dart` include. * `DotENV.sublime-syntax` => added `.env.template`, `env` and `env.*` file types ([upstream PR](https://github.com/zaynali53/DotENV/pull/17)). * `INI.sublime-syntax` => added `.coveragerc`, `.pylintrc`, `.gitlint`, `.hgrc`, `hgrc`, and `desktop` file types and support for comments after section headers. * `Org mode.sublime-syntax` => removed `task` file type. * `Robot.sublime_syntax` => changed name to "Robot Framework", added `.resource` extension. * `SML.sublime_syntax` => removed `ml` file type. * `wgsl.sublime-syntax` => added `wgsl` file extension. ### Non-submodule additions * `Assembly (x86_64)` has been manually added from https://github.com/13xforever/x86-assembly-textmate-bundle due to `git clone` recursion problems * `Nim.sublime-syntax` has been added manually from https://github.com/getzola/zola/blob/master/sublime_syntaxes/Nim.sublime-syntax as there was no suitable Git repository for it. The original syntax seems to originate from https://github.com/Varriount/NimLime * `Rego.sublime-syntax` has been added manually from https://github.com/open-policy-agent/opa/blob/master/misc/syntax/sublime/rego.sublime-syntax as it is not kept in a standalone repository. The file is generated from https://github.com/open-policy-agent/opa/blob/master/misc/syntax/textmate/Rego.tmLanguage * `SML.sublime_syntax` has been added manually from https://github.com/seanjames777/SML-Language-Definitiona as it is not kept in a standalone repository. The file generated is from https://github.com/seanjames777/SML-Language-Definition/blob/master/sml.tmLanguage * `Cabal.sublime_syntax` has been added manually from https://github.com/SublimeHaskell/SublimeHaskell/ - we don't want to include the whole submodule because it includes other syntaxes ("Haskell improved") as well. * `Lean.sublime-syntax` has been added manually from https://github.com/leanprover/vscode-lean4/blob/master/vscode-lean4/syntaxes/lean4.json via conversion. ================================================ FILE: doc/long-help.txt ================================================ A cat(1) clone with syntax highlighting and Git integration. Usage: bat [OPTIONS] [FILE]... bat Arguments: [FILE]... File(s) to print / concatenate. Use a dash ('-') or no argument at all to read from standard input. Options: -A, --show-all Show non-printable characters like space, tab or newline. This option can also be used to print binary files. Use '--tabs' to control the width of the tab-placeholders. --nonprintable-notation Set notation for non-printable characters. Possible values: * unicode (␇, ␊, ␀, ..) * caret (^G, ^J, ^@, ..) --binary How to treat binary content. (default: no-printing) Possible values: * no-printing: do not print any binary content * as-text: treat binary content as normal text -p, --plain... Only show plain style, no decorations. This is an alias for '--style=plain'. When '-p' is used twice ('-pp'), it also disables automatic paging (alias for '--style=plain --paging=never'). -l, --language 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. --fallback-syntax Set a fallback language for syntax highlighting when auto-detection fails. Unlike '--language', this is only used when no syntax could be detected from filename, custom syntax mappings, or first-line detection. [aliases: --fallback-language] -H, --highlight-line Highlight the specified line ranges with a different background color For example: '--highlight-line 40' highlights line 40 '--highlight-line 30:40' highlights lines 30 to 40 '--highlight-line :40' highlights lines 1 to 40 '--highlight-line 40:' highlights lines 40 to the end of the file '--highlight-line 30:+10' highlights lines 30 to 40 --file-name Specify the name to display for a file. Useful when piping data to bat from STDIN when bat does not otherwise know the filename. Note that the provided file name is also used for syntax detection. -d, --diff Only show lines that have been added/removed/modified with respect to the Git index. Use --diff-context=N to control how much context you want to see. --diff-context Include N lines of context around added/removed/modified lines when using '--diff'. --tabs Set the tab width to T spaces. Use a width of 0 to pass tabs through directly --wrap Specify the text-wrapping mode (*auto*, never, character, word). The '--terminal-width' option can be used in addition to control the output width. -S, --chop-long-lines Truncate all lines longer than screen width. Alias for '--wrap=never'. --terminal-width Explicitly set the width of the terminal instead of determining it automatically. If prefixed with '+' or '-', the value will be treated as an offset to the actual terminal width. See also: '--wrap'. -n, --number Only show line numbers, no other decorations. This is an alias for '--style=numbers' --color Specify when to use colored output. The automatic mode only enables colors if an interactive terminal is detected - colors are automatically disabled if the output goes to a pipe. Possible values: *auto*, never, always. --italic-text Specify when to use ANSI sequences for italic text in the output. Possible values: always, *never*. --decorations Specify when to use the decorations that have been specified via '--style'. The automatic mode only enables decorations if an interactive terminal is detected. The always mode will show decorations even when piping output. Possible values: *auto*, never, always. -f, --force-colorization Alias for '--decorations=always --color=always'. This is useful if the output of bat is piped to another program, but you want to keep the colorization/decorations. --paging Specify when to use the pager. To disable the pager, use '--paging=never' or its alias,'-P'. To disable the pager permanently, set BAT_PAGING to 'never'. To control which pager is used, see the '--pager' option. Possible values: *auto*, never, always. --pager Determine which pager is used. This option will override the PAGER and BAT_PAGER environment variables. The default pager is 'less'. If you provide '--pager=builtin', use the built-in 'minus' pager. To control when the pager is used, see the '--paging' option. Example: '--pager "less -RF"'. -m, --map-syntax Map a glob pattern to an existing syntax name. The glob pattern is matched on the full path and the filename. For example, to highlight *.build files with the Python syntax, use -m '*.build:Python'. To highlight files named '.myignore' with the Git Ignore syntax, use -m '.myignore:Git Ignore'. Note that the right-hand side is the *name* of the syntax, not a file extension. --ignored-suffix Ignore extension. For example: 'bat --ignored-suffix ".dev" my_file.json.dev' will use JSON syntax, and ignore '.dev' --theme Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To set a default theme, add the '--theme="..."' option to the configuration file or export the BAT_THEME environment variable (e.g.: export BAT_THEME="..."). Special values: * auto: Picks a dark or light theme depending on the terminal's colors (default). Use '--theme-light' and '--theme-dark' to customize the selected theme. * auto:always: Detect the terminal's colors even when the output is redirected. * auto:system: Detect the color scheme from the system-wide preference (macOS only). * dark: Use the dark theme specified by '--theme-dark'. * light: Use the light theme specified by '--theme-light'. --theme-light Sets the theme name for syntax highlighting used when the terminal uses a light background. Use '--list-themes' to see all available themes. To set a default theme, add the '--theme-light="..." option to the configuration file or export the BAT_THEME_LIGHT environment variable (e.g. export BAT_THEME_LIGHT="..."). --theme-dark Sets the theme name for syntax highlighting used when the terminal uses a dark background. Use '--list-themes' to see all available themes. To set a default theme, add the '--theme-dark="..." option to the configuration file or export the BAT_THEME_DARK environment variable (e.g. export BAT_THEME_DARK="..."). --list-themes Display a list of supported themes for syntax highlighting. -s, --squeeze-blank Squeeze consecutive empty lines into a single empty line. --squeeze-limit Set the maximum number of consecutive empty lines to be printed. --strip-ansi Specify when to strip ANSI escape sequences from the input. The automatic mode will remove escape sequences unless the syntax highlighting language is plain text. Possible values: auto, always, *never*. --style Configure which elements (line numbers, file headers, grid borders, Git modifications, ..) to display in addition to the file contents. The argument is a comma-separated list of components to display (e.g. 'numbers,changes,grid') or a pre-defined style ('full'). To set a default style, add the '--style=".."' option to the configuration file or export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). When styles are specified in multiple places, the "nearest" set of styles take precedence. The command-line arguments are the highest priority, followed by the BAT_STYLE environment variable, and then the configuration file. If any set of styles consists entirely of components prefixed with "+" or "-", it will modify the previous set of styles instead of replacing them. By default, the following components are enabled: changes, grid, header-filename, numbers, snip Possible values: * default: enables recommended style components (default). * full: enables all available components. * auto: same as 'default', unless the output is piped. * plain: disables all available components. * changes: show Git modification markers. * header: alias for 'header-filename'. * header-filename: show filenames before the content. * header-filesize: show file sizes before the content. * grid: vertical/horizontal lines to separate side bar and the header from the content. * rule: horizontal lines to delimit files. * numbers: show line numbers in the side bar. * snip: draw separation lines between distinct line ranges. -r, --line-range Only print the specified range of lines for each file. For example: '--line-range 30:40' prints lines 30 to 40 '--line-range :40' prints lines 1 to 40 '--line-range 40:' prints lines 40 to the end of the file '--line-range 40' only prints line 40 '--line-range -10:' prints the last 10 lines '--line-range 30:+10' prints lines 30 to 40 '--line-range 35::5' prints lines 30 to 40 (line 35 with 5 lines of context) '--line-range 30:40:2' prints lines 28 to 42 (range 30-40 with 2 lines of context) -L, --list-languages Display a list of supported languages for syntax highlighting. -u, --unbuffered Enable unbuffered input reading. When this flag is set, bat will display data as soon as it is available, without waiting for a complete line. This is useful for streaming use cases like 'tail -f logfile | bat -u --paging=never'. Note that line numbers are automatically disabled in unbuffered mode, and syntax highlighting may be imperfect on partial lines. --completion Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1] --diagnostic Show diagnostic information for bug reports. -E, --quiet-empty When this flag is set, bat will produce no output at all when the input is empty. This is useful when piping commands that may produce empty output, like 'git diff'. --acknowledgements Show acknowledgements. --set-terminal-title Sets terminal title to filenames when using a pager. -h, --help Print help (see a summary with '-h') -V, --version Print version ================================================ FILE: doc/release-checklist.md ================================================ # Release checklist ## Version bump - [ ] Update version in `Cargo.toml`. Run `cargo build` to update `Cargo.lock`. Make sure to `git add` the `Cargo.lock` changes as well. - [ ] Find the current min. supported Rust version by running `cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].rust_version'`. - [ ] Update the version and the min. supported Rust version in `README.md` and `doc/README-*.md`. Check with `git grep -i -e 'rust.*1\.' -e '1\..*rust' | grep README | grep -v tests/`. ## CHANGELOG.md updates - [ ] Go to https://github.com/sharkdp/bat/releases/new, click "Choose a tag", type the name of the tag that will be created later, click "Generate release notes". DO NOT ACTUALLY CREATE ANY RELEASE IN THIS STEP. - [ ] Compare current `CHANGELOG.md` with auto-generated release notes and add missing entries. Expect in particular dependabot PRs to not be in `CHANGELOG.md` since they are [auto-merged] if CI passes. - [ ] Introduce a section for the new release and perform final touch-ups. ## Update syntaxes and themes (build assets) - [ ] Install the latest master version (`cargo clean && cargo install --locked -f --path .`) and make sure that it is available on the `PATH` (`bat --version` should show the new version). - [ ] Run `assets/create.sh` and check in the binary asset files. ## Documentation - [ ] Review [`-h`](./short-help.txt), [`--help`](./long-help.txt), and the `man` page. The `man` page is shown in the output of the CI job called *Documentation*, so look there. The CI workflow corresponding to the tip of the master branch is a good place to look. ## Pre-release checks - [ ] Push all changes and wait for CI to succeed (before continuing with the next section). - [ ] Optional: manually test the new features and command-line options. To do this, install the latest `bat` version again (to include the new syntaxes and themes). - [ ] Run `cargo publish --dry-run` to make sure that it will succeed later (after creating the GitHub release). ## Release - [ ] Create a tag and push it: `git tag vX.Y.Z; git push origin tag vX.Y.Z`. This will trigger the deployment via GitHub Actions. REMINDER: If your `origin` is a fork, don't forget to push to e.g. `upstream` instead! - [ ] Go to https://github.com/sharkdp/bat/releases/new to create the new release. Select the new tag and also use it as the release title. For the release notes, copy the corresponding section from `CHANGELOG.md` and possibly add additional remarks for package maintainers. Publish the release. - [ ] Check if the binary deployment works (archives and Debian packages should appear when the CI run for the Git tag has finished). - [ ] Publish to crates.io by running `cargo publish` in a *clean* repository. The safest way to do this is to clone a fresh copy. ## Post-release - [ ] Prepare a new "unreleased" section at the top of `CHANGELOG.md`. Put this at the top: ``` # unreleased ## Features ## Bugfixes ## Other ## Syntaxes ## Themes ## `bat` as a library ``` [auto-merged]: https://github.com/sharkdp/bat/blob/master/.github/workflows/Auto-merge-dependabot-PRs.yml ================================================ FILE: doc/short-help.txt ================================================ A cat(1) clone with wings. Usage: bat [OPTIONS] [FILE]... bat Arguments: [FILE]... File(s) to print / concatenate. Use '-' for standard input. Options: -A, --show-all Show non-printable characters (space, tab, newline, ..). --nonprintable-notation Set notation for non-printable characters. --binary How to treat binary content. (default: no-printing) -p, --plain... Show plain style (alias for '--style=plain'). -l, --language Set the language for syntax highlighting. --fallback-syntax Set a fallback language for undetected syntaxes. [aliases: --fallback-language] -H, --highlight-line Highlight lines N through M. --file-name Specify the name to display for a file. -d, --diff Only show lines that have been added/removed/modified. --tabs Set the tab width to T spaces. --wrap Specify the text-wrapping mode (*auto*, never, character, word). -S, --chop-long-lines Truncate all lines longer than screen width. Alias for '--wrap=never'. -n, --number Show line numbers (alias for '--style=numbers'). --color When to use colors (*auto*, never, always). --italic-text Use italics in output (always, *never*) --decorations When to show the decorations (*auto*, never, always). --paging Specify when to use the pager, or use `-P` to disable (*auto*, never, always). -m, --map-syntax Use the specified syntax for files matching the glob pattern ('*.cpp:C++'). --theme Set the color theme for syntax highlighting. --theme-light Sets the color theme for syntax highlighting used for light backgrounds. --theme-dark Sets the color theme for syntax highlighting used for dark backgrounds. --list-themes Display all supported highlighting themes. -s, --squeeze-blank Squeeze consecutive empty lines. --style Comma-separated list of style elements to display (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip). -r, --line-range Only print the lines from N to M. -L, --list-languages Display all supported languages. -u, --unbuffered Enable unbuffered input reading for streaming use cases. --completion Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1] -E, --quiet-empty Produce no output when the input is empty. -h, --help Print help (see more with '--help') -V, --version Print version ================================================ FILE: doc/sponsors.md ================================================ ## Sponsors `bat` development is sponsored by many individuals and companies. Thank you very much! Please note, that being sponsored does not affect the individuality of the `bat` project or affect the maintainers' actions in any way. We remain impartial and continue to assess pull requests solely on merit - the features added, bugs solved, and effect on the overall complexity of the code. No issue will have a different priority based on sponsorship status of the reporter. Contributions from anybody are most welcomed, please see our [`CONTRIBUTING.md`](../CONTRIBUTING.md) guide. If you want to see our biggest sponsors, check the top of [`README.md`](../README.md#sponsors). ================================================ FILE: examples/advanced.rs ================================================ /// A program that prints its own source code using the bat library use bat::{PagingMode, PrettyPrinter, WrappingMode}; fn main() { PrettyPrinter::new() .header(true) .grid(true) .line_numbers(true) .use_italics(true) // The following line will be highlighted in the output: .highlight(line!() as usize) .theme("1337") .wrapping_mode(WrappingMode::Character) .paging_mode(PagingMode::QuitIfOneScreen) .input_file(file!()) .print() .unwrap(); } ================================================ FILE: examples/buffer.rs ================================================ use bat::{ assets::HighlightingAssets, config::Config, controller::Controller, output::OutputHandle, Input, }; fn main() { let mut buffer = String::new(); let config = Config { colored_output: true, ..Default::default() }; let assets = HighlightingAssets::from_binary(); let controller = Controller::new(&config, &assets); let input = Input::from_file(file!()); controller .run( vec![input.into()], Some(&mut OutputHandle::FmtWrite(&mut buffer)), ) .unwrap(); println!("{buffer}"); } ================================================ FILE: examples/cat.rs ================================================ /// A very simple colorized `cat` clone, using `bat` as a library. /// See `src/bin/bat` for the full `bat` application. use bat::PrettyPrinter; fn main() { PrettyPrinter::new() .header(true) .grid(true) .line_numbers(true) .input_files(std::env::args_os().skip(1)) .print() .unwrap(); } ================================================ FILE: examples/inputs.rs ================================================ /// A small demonstration of the Input API. /// This prints embedded bytes with a custom header and then reads from STDIN. use bat::{Input, PrettyPrinter}; fn main() { PrettyPrinter::new() .header(true) .grid(true) .line_numbers(true) .inputs(vec![ Input::from_bytes(b"echo 'Hello World!'") .name("embedded.sh") // Dummy name provided to detect the syntax. .kind("Embedded") .title("An embedded shell script."), Input::from_stdin().title("Standard Input").kind("FD"), ]) .print() .unwrap(); } ================================================ FILE: examples/list_syntaxes_and_themes.rs ================================================ /// A simple program that lists all supported syntaxes and themes. use bat::PrettyPrinter; fn main() { let printer = PrettyPrinter::new(); println!("Syntaxes:"); for syntax in printer.syntaxes() { println!("- {} ({})", syntax.name, syntax.file_extensions.join(", ")); } println!(); println!("Themes:"); for theme in printer.themes() { println!("- {theme}"); } } ================================================ FILE: examples/simple.rs ================================================ /// A simple program that prints its own source code using the bat library use bat::PrettyPrinter; fn main() { PrettyPrinter::new().input_file(file!()).print().unwrap(); } ================================================ FILE: examples/yaml.rs ================================================ /// A program that serializes a Rust structure to YAML and pretty-prints the result use bat::{Input, PrettyPrinter}; use serde::Serialize; #[derive(Serialize)] struct Person { name: String, height: f64, adult: bool, children: Vec, } fn main() { let person = Person { name: String::from("Anne Mustermann"), height: 1.76f64, adult: true, children: vec![Person { name: String::from("Max Mustermann"), height: 1.32f64, adult: false, children: vec![], }], }; let mut bytes = Vec::with_capacity(128); serde_yaml::to_writer(&mut bytes, &person).unwrap(); PrettyPrinter::new() .language("yaml") .line_numbers(true) .grid(true) .header(true) .input(Input::from_bytes(&bytes).name("person.yaml").kind("File")) .print() .unwrap(); } ================================================ FILE: flake.nix ================================================ { description = "bat"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { self, ... }@inputs: let supportedSystems = [ "x86_64-linux" # 64-bit Intel/AMD Linux "aarch64-linux" # 64-bit ARM Linux "aarch64-darwin" # 64-bit ARM macOS "x86_64-darwin" # 64-bit Intel macOS ]; forEachSupportedSystem = f: inputs.nixpkgs.lib.genAttrs supportedSystems ( system: f { inherit system; pkgs = import inputs.nixpkgs { inherit system; }; } ); in { devShells = forEachSupportedSystem ( { pkgs, system }: { default = pkgs.mkShellNoCC { packages = with pkgs; [ cargo ]; }; } ); }; } ================================================ FILE: rustfmt.toml ================================================ # Defaults are used ================================================ FILE: src/assets/assets_metadata.rs ================================================ use std::fs::File; use std::path::Path; use std::time::SystemTime; use semver::Version; use serde_derive::{Deserialize, Serialize}; use crate::error::*; #[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct AssetsMetadata { bat_version: Option, creation_time: Option, } const FILENAME: &str = "metadata.yaml"; impl AssetsMetadata { #[cfg(feature = "build-assets")] pub(crate) fn new(current_version: &str) -> AssetsMetadata { AssetsMetadata { bat_version: Some(current_version.to_owned()), creation_time: Some(SystemTime::now()), } } #[cfg(feature = "build-assets")] pub(crate) fn save_to_folder(&self, path: &Path) -> Result<()> { let file = File::create(path.join(FILENAME))?; serde_yaml::to_writer(file, self)?; Ok(()) } fn try_load_from_folder(path: &Path) -> Result { let file = File::open(path.join(FILENAME))?; Ok(serde_yaml::from_reader(file)?) } /// Load metadata about the stored cache file from the given folder. /// /// There are several possibilities: /// - We find a `metadata.yaml` file and are able to parse it /// - return the contained information /// - We find a `metadata.yaml` file, but are not able to parse it /// - return a [`Error::SerdeYamlError`] /// - We do not find a `metadata.yaml` file but a `syntaxes.bin` or `themes.bin` file /// - assume that these were created by an old version of bat and return /// [`AssetsMetadata::default()`] without version information /// - We do not find a `metadata.yaml` file and no cached assets /// - no user provided assets are available, return `None` pub fn load_from_folder(path: &Path) -> Result> { match Self::try_load_from_folder(path) { Ok(metadata) => Ok(Some(metadata)), Err(e) => { if let Error::SerdeYamlError(_) = e { Err(e) } else if path.join("syntaxes.bin").exists() || path.join("themes.bin").exists() { Ok(Some(Self::default())) } else { Ok(None) } } } } pub fn is_compatible_with(&self, current_version: &str) -> bool { let current_version = Version::parse(current_version).expect("bat follows semantic versioning"); let stored_version = self .bat_version .as_ref() .and_then(|ver| Version::parse(ver).ok()); if let Some(stored_version) = stored_version { current_version.major == stored_version.major && current_version.minor == stored_version.minor } else { false } } } ================================================ FILE: src/assets/build_assets/acknowledgements.rs ================================================ use std::fmt::Write; use std::fs::read_to_string; use std::path::{Path, PathBuf}; use walkdir::DirEntry; use crate::error::*; struct PathAndStem { path: PathBuf, stem: String, relative_path: String, } /// Looks for LICENSE and NOTICE files in `source_dir`, does some rudimentary /// analysis, and compiles them together in a single string that is meant to be /// used in the output to `--acknowledgements` pub fn build_acknowledgements( source_dir: &Path, include_acknowledgements: bool, ) -> Result> { if !include_acknowledgements { return Ok(None); } let mut acknowledgements = format!("{}\n\n", include_str!("../../../NOTICE")); // Sort entries so the order is stable over time let entries = walkdir::WalkDir::new(source_dir).sort_by(|a, b| a.path().cmp(b.path())); for path_and_stem in entries .into_iter() .flatten() .flat_map(|entry| to_path_and_stem(source_dir, entry)) { if let Some(license_text) = handle_file(&path_and_stem)? { append_to_acknowledgements( &mut acknowledgements, &path_and_stem.relative_path, &license_text, ) } } Ok(Some(acknowledgements)) } fn to_path_and_stem(source_dir: &Path, entry: DirEntry) -> Option { let path = entry.path(); Some(PathAndStem { path: path.to_owned(), stem: path.file_stem().map(|s| s.to_string_lossy().to_string())?, relative_path: path .strip_prefix(source_dir) .map(|p| p.to_string_lossy().to_string()) .ok()?, }) } fn handle_file(path_and_stem: &PathAndStem) -> Result> { if path_and_stem.stem == "NOTICE" { handle_notice(&path_and_stem.path) } else if path_and_stem.stem.eq_ignore_ascii_case("LICENSE") { handle_license(&path_and_stem.path) } else { Ok(None) } } fn handle_notice(path: &Path) -> Result> { // Assume NOTICE as defined by Apache License 2.0. These must be part of acknowledgements. Ok(Some(read_to_string(path)?)) } fn handle_license(path: &Path) -> Result> { let license_text = read_to_string(path)?; if include_license_in_acknowledgments(&license_text) { Ok(Some(license_text)) } else if license_not_needed_in_acknowledgements(&license_text) { Ok(None) } else { Err(format!("ERROR: License is of unknown type: {path:?}").into()) } } fn include_license_in_acknowledgments(license_text: &str) -> bool { let markers = vec![ // MIT "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", // BSD "Redistributions in binary form must reproduce the above copyright notice,", // Apache 2.0 "Apache License Version 2.0, January 2004 http://www.apache.org/licenses/", "Licensed under the Apache License, Version 2.0 (the \"License\");", // CC BY 4.0 "Creative Commons Attribution 4.0 International Public License", ]; license_contains_marker(license_text, &markers) } fn license_not_needed_in_acknowledgements(license_text: &str) -> bool { let markers = vec![ // Public domain "This is free and unencumbered software released into the public domain.", // Public domain with stronger wording than above "DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE", // Special license of assets/syntaxes/01_Packages/LICENSE "Permission to copy, use, modify, sell and distribute this software is granted. This software is provided \"as is\" without express or implied warranty, and with no claim as to its suitability for any purpose." ]; license_contains_marker(license_text, &markers) } fn license_contains_marker(license_text: &str, markers: &[&str]) -> bool { let normalized_license_text = normalize_license_text(license_text); markers.iter().any(|m| normalized_license_text.contains(m)) } fn append_to_acknowledgements( acknowledgements: &mut String, relative_path: &str, license_text: &str, ) { write!(acknowledgements, "## {relative_path}\n\n{license_text}").ok(); // Make sure the last char is a newline to not mess up formatting later if acknowledgements .chars() .last() .expect("acknowledgements is not the empty string") != '\n' { acknowledgements.push('\n'); } // Add two more newlines to make it easy to distinguish where this text ends // and the next starts acknowledgements.push_str("\n\n"); } /// Replaces newlines with a space character, and replaces multiple spaces with one space. /// This makes the text easier to analyze. fn normalize_license_text(license_text: &str) -> String { use regex::Regex; let whitespace_and_newlines = Regex::new(r"\s").unwrap(); let as_single_line = whitespace_and_newlines.replace_all(license_text, " "); let many_spaces = Regex::new(" +").unwrap(); many_spaces.replace_all(&as_single_line, " ").to_string() } #[cfg(test)] mod tests { #[cfg(test)] use super::*; #[test] fn test_normalize_license_text() { let license_text = "This is a license text with these terms: * Complicated multi-line term with indentation"; assert_eq!( "This is a license text with these terms: * Complicated multi-line term with indentation".to_owned(), normalize_license_text(license_text), ); } #[test] fn test_normalize_license_text_with_windows_line_endings() { let license_text = "This license text includes windows line endings\r and we need to handle that."; assert_eq!( "This license text includes windows line endings and we need to handle that." .to_owned(), normalize_license_text(license_text), ); } #[test] fn test_append_to_acknowledgements_adds_newline_if_missing() { let mut acknowledgements = "preamble\n\n\n".to_owned(); append_to_acknowledgements(&mut acknowledgements, "some/path", "line without newline"); assert_eq!( "preamble ## some/path line without newline ", acknowledgements ); append_to_acknowledgements(&mut acknowledgements, "another/path", "line with newline\n"); assert_eq!( "preamble ## some/path line without newline ## another/path line with newline ", acknowledgements ); } } ================================================ FILE: src/assets/build_assets.rs ================================================ use std::convert::TryInto; use std::path::Path; use syntect::highlighting::ThemeSet; use syntect::parsing::{SyntaxSet, SyntaxSetBuilder}; use crate::assets::*; use acknowledgements::build_acknowledgements; mod acknowledgements; pub fn build( source_dir: &Path, include_integrated_assets: bool, include_acknowledgements: bool, target_dir: &Path, current_version: &str, ) -> Result<()> { let theme_set = build_theme_set(source_dir, include_integrated_assets)?; let syntax_set_builder = build_syntax_set_builder(source_dir, include_integrated_assets)?; let syntax_set = syntax_set_builder.build(); let acknowledgements = build_acknowledgements(source_dir, include_acknowledgements)?; print_unlinked_contexts(&syntax_set); write_assets( &theme_set, &syntax_set, &acknowledgements, target_dir, current_version, ) } fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> Result { let mut theme_set = if include_integrated_assets { crate::assets::get_integrated_themeset().try_into()? } else { ThemeSet::new() }; let theme_dir = source_dir.join("themes"); if theme_dir.exists() { let res = theme_set.add_from_folder(&theme_dir); if let Err(err) = res { println!( "Failed to load one or more themes from '{}' (reason: '{err}')", theme_dir.to_string_lossy(), ); } } else { println!( "No themes were found in '{}', using the default set", theme_dir.to_string_lossy() ); } theme_set.try_into() } fn build_syntax_set_builder( source_dir: &Path, include_integrated_assets: bool, ) -> Result { let mut syntax_set_builder = if !include_integrated_assets { let mut builder = syntect::parsing::SyntaxSetBuilder::new(); builder.add_plain_text_syntax(); builder } else { from_binary::(get_serialized_integrated_syntaxset(), COMPRESS_SYNTAXES) .into_builder() }; let syntax_dir = source_dir.join("syntaxes"); if syntax_dir.exists() { syntax_set_builder.add_from_folder(syntax_dir, true)?; } else { println!( "No syntaxes were found in '{}', using the default set.", syntax_dir.to_string_lossy() ); } Ok(syntax_set_builder) } fn print_unlinked_contexts(syntax_set: &SyntaxSet) { let missing_contexts = syntax_set.find_unlinked_contexts(); if !missing_contexts.is_empty() { println!("Some referenced contexts could not be found!"); for context in missing_contexts { println!("- {context}"); } } } fn write_assets( theme_set: &LazyThemeSet, syntax_set: &SyntaxSet, acknowledgements: &Option, target_dir: &Path, current_version: &str, ) -> Result<()> { let _ = std::fs::create_dir_all(target_dir); asset_to_cache( theme_set, &target_dir.join("themes.bin"), "theme set", COMPRESS_THEMES, )?; asset_to_cache( syntax_set, &target_dir.join("syntaxes.bin"), "syntax set", COMPRESS_SYNTAXES, )?; if let Some(acknowledgements) = acknowledgements { asset_to_cache( acknowledgements, &target_dir.join("acknowledgements.bin"), "acknowledgements", COMPRESS_ACKNOWLEDGEMENTS, )?; } print!( "Writing metadata to folder {} ... ", target_dir.to_string_lossy() ); crate::assets_metadata::AssetsMetadata::new(current_version).save_to_folder(target_dir)?; println!("okay"); Ok(()) } pub(crate) fn asset_to_contents( asset: &T, description: &str, compressed: bool, ) -> Result> { let mut contents = vec![]; if compressed { bincode::serialize_into( flate2::write::ZlibEncoder::new(&mut contents, flate2::Compression::best()), asset, ) } else { bincode::serialize_into(&mut contents, asset) } .map_err(|_| format!("Could not serialize {description}"))?; Ok(contents) } fn asset_to_cache( asset: &T, path: &Path, description: &str, compressed: bool, ) -> Result<()> { print!("Writing {description} to {} ... ", path.to_string_lossy()); let contents = asset_to_contents(asset, description, compressed)?; std::fs::write(path, &contents[..]) .map_err(|_| format!("Could not save {description} to {}", path.to_string_lossy()))?; println!("okay"); Ok(()) } ================================================ FILE: src/assets/lazy_theme_set.rs ================================================ use super::*; use std::collections::BTreeMap; use std::convert::TryFrom; use serde_derive::{Deserialize, Serialize}; use once_cell::unsync::OnceCell; use syntect::highlighting::{Theme, ThemeSet}; /// Same structure as a [`syntect::highlighting::ThemeSet`] but with themes /// stored in raw serialized form, and deserialized on demand. #[derive(Debug, Default, Serialize, Deserialize)] pub struct LazyThemeSet { /// This is a [`BTreeMap`] because that's what [`syntect::highlighting::ThemeSet`] uses themes: BTreeMap, } /// Stores raw serialized data for a theme with methods to lazily deserialize /// (load) the theme. #[derive(Debug, Serialize, Deserialize)] struct LazyTheme { serialized: Vec, #[serde(skip, default = "OnceCell::new")] deserialized: OnceCell, } impl LazyThemeSet { /// Lazily load the given theme pub fn get(&self, name: &str) -> Option<&Theme> { self.themes.get(name).and_then(|lazy_theme| { lazy_theme .deserialized .get_or_try_init(|| lazy_theme.deserialize()) .ok() }) } /// Returns the name of all themes. pub fn themes(&self) -> impl Iterator { self.themes.keys().map(|name| name.as_ref()) } } impl LazyTheme { fn deserialize(&self) -> Result { asset_from_contents( &self.serialized[..], "lazy-loaded theme", COMPRESS_LAZY_THEMES, ) } } impl TryFrom for ThemeSet { type Error = Error; /// Since the user might want to add custom themes to bat, we need a way to /// convert from a `LazyThemeSet` to a regular [`ThemeSet`] so that more /// themes can be added. This function does that pretty straight-forward /// conversion. fn try_from(lazy_theme_set: LazyThemeSet) -> Result { let mut theme_set = ThemeSet::default(); for (name, lazy_theme) in lazy_theme_set.themes { theme_set.themes.insert(name, lazy_theme.deserialize()?); } Ok(theme_set) } } #[cfg(feature = "build-assets")] impl TryFrom for LazyThemeSet { type Error = Error; /// To collect themes, a [`ThemeSet`] is needed. Once all desired themes /// have been added, we need a way to convert that into [`LazyThemeSet`] so /// that themes can be lazy-loaded later. This function does that /// conversion. fn try_from(theme_set: ThemeSet) -> Result { let mut lazy_theme_set = LazyThemeSet::default(); for (name, theme) in theme_set.themes { // All we have to do is to serialize the theme let lazy_theme = LazyTheme { serialized: crate::assets::build_assets::asset_to_contents( &theme, &format!("theme {name}"), COMPRESS_LAZY_THEMES, )?, deserialized: OnceCell::new(), }; // Ok done, now we can add it lazy_theme_set.themes.insert(name, lazy_theme); } Ok(lazy_theme_set) } } ================================================ FILE: src/assets/serialized_syntax_set.rs ================================================ use std::path::PathBuf; use syntect::parsing::SyntaxSet; use super::*; /// A SyntaxSet in serialized form, i.e. bincoded and flate2 compressed. /// We keep it in this format since we want to load it lazily. #[derive(Debug)] pub enum SerializedSyntaxSet { /// The data comes from a user-generated cache file. FromFile(PathBuf), /// The data to use is embedded into the bat binary. FromBinary(&'static [u8]), } impl SerializedSyntaxSet { pub fn deserialize(&self) -> Result { match self { SerializedSyntaxSet::FromBinary(data) => Ok(from_binary(data, COMPRESS_SYNTAXES)), SerializedSyntaxSet::FromFile(ref path) => { asset_from_cache(path, "syntax set", COMPRESS_SYNTAXES) } } } } ================================================ FILE: src/assets.rs ================================================ use std::ffi::OsStr; use std::fs; use std::path::Path; use once_cell::unsync::OnceCell; use syntect::highlighting::Theme; use syntect::parsing::{SyntaxReference, SyntaxSet}; use path_abs::PathAbs; use crate::error::*; use crate::input::{InputReader, OpenedInput}; use crate::syntax_mapping::ignored_suffixes::IgnoredSuffixes; use crate::syntax_mapping::MappingTarget; use crate::theme::{default_theme, ColorScheme}; use crate::{bat_warning, SyntaxMapping}; use lazy_theme_set::LazyThemeSet; use serialized_syntax_set::*; #[cfg(feature = "build-assets")] pub use crate::assets::build_assets::*; pub(crate) mod assets_metadata; #[cfg(feature = "build-assets")] mod build_assets; mod lazy_theme_set; mod serialized_syntax_set; #[derive(Debug)] pub struct HighlightingAssets { syntax_set_cell: OnceCell, serialized_syntax_set: SerializedSyntaxSet, theme_set: LazyThemeSet, fallback_theme: Option<&'static str>, } #[derive(Debug)] pub struct SyntaxReferenceInSet<'a> { pub syntax: &'a SyntaxReference, pub syntax_set: &'a SyntaxSet, } /// Lazy-loaded syntaxes are already compressed, and we don't want to compress /// already compressed data. pub(crate) const COMPRESS_SYNTAXES: bool = false; /// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes /// within it are already compressed, and compressing another time just makes /// performance suffer pub(crate) const COMPRESS_THEMES: bool = false; /// Compress for size of ~40 kB instead of ~200 kB without much difference in /// performance due to lazy-loading pub(crate) const COMPRESS_LAZY_THEMES: bool = true; /// Compress for size of ~10 kB instead of ~120 kB pub(crate) const COMPRESS_ACKNOWLEDGEMENTS: bool = true; impl HighlightingAssets { fn new(serialized_syntax_set: SerializedSyntaxSet, theme_set: LazyThemeSet) -> Self { HighlightingAssets { syntax_set_cell: OnceCell::new(), serialized_syntax_set, theme_set, fallback_theme: None, } } pub fn from_cache(cache_path: &Path) -> Result { Ok(HighlightingAssets::new( SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")), asset_from_cache(&cache_path.join("themes.bin"), "theme set", COMPRESS_THEMES)?, )) } pub fn from_binary() -> Self { HighlightingAssets::new( SerializedSyntaxSet::FromBinary(get_serialized_integrated_syntaxset()), get_integrated_themeset(), ) } pub fn set_fallback_theme(&mut self, theme: &'static str) { self.fallback_theme = Some(theme); } /// Return the collection of syntect syntax definitions. pub fn get_syntax_set(&self) -> Result<&SyntaxSet> { self.syntax_set_cell .get_or_try_init(|| self.serialized_syntax_set.deserialize()) } /// Use [Self::get_syntaxes] instead #[deprecated] pub fn syntaxes(&self) -> &[SyntaxReference] { self.get_syntax_set() .expect(".syntaxes() is deprecated, use .get_syntaxes() instead") .syntaxes() } pub fn get_syntaxes(&self) -> Result<&[SyntaxReference]> { Ok(self.get_syntax_set()?.syntaxes()) } fn get_theme_set(&self) -> &LazyThemeSet { &self.theme_set } pub fn themes(&self) -> impl Iterator { self.get_theme_set().themes() } /// Use [Self::get_syntax_for_path] instead #[deprecated] pub fn syntax_for_file_name( &self, file_name: impl AsRef, mapping: &SyntaxMapping, ) -> Option<&SyntaxReference> { self.get_syntax_for_path(file_name, mapping) .ok() .map(|syntax_in_set| syntax_in_set.syntax) } /// Detect the syntax based on, in order: /// 1. Syntax mappings with [MappingTarget::MapTo] and [MappingTarget::MapToUnknown] /// (e.g. `/etc/profile` -> `Bourne Again Shell (bash)`) /// 2. The file name (e.g. `Dockerfile`) /// 3. Syntax mappings with [MappingTarget::MapExtensionToUnknown] /// (e.g. `*.conf`) /// 4. The file name extension (e.g. `.rs`) /// /// When detecting syntax based on syntax mappings, the full path is taken /// into account. When detecting syntax based on file name, no regard is /// taken to the path of the file. Only the file name itself matters. When /// detecting syntax based on file name extension, only the file name /// extension itself matters. /// /// Returns [Error::UndetectedSyntax] if it was not possible detect syntax /// based on path/file name/extension (or if the path was mapped to /// [MappingTarget::MapToUnknown] or [MappingTarget::MapExtensionToUnknown]). /// In this case it is appropriate to fall back to other methods to detect /// syntax. Such as using the contents of the first line of the file. /// /// Returns [Error::UnknownSyntax] if a syntax mapping exist, but the mapped /// syntax does not exist. pub fn get_syntax_for_path( &self, path: impl AsRef, mapping: &SyntaxMapping, ) -> Result> { let path = path.as_ref(); let syntax_match = mapping.get_syntax_for(path); if let Some(MappingTarget::MapToUnknown) = syntax_match { return Err(Error::UndetectedSyntax(path.to_string_lossy().into())); } if let Some(MappingTarget::MapTo(syntax_name)) = syntax_match { return self .find_syntax_by_token(syntax_name)? .ok_or_else(|| Error::UnknownSyntax(syntax_name.to_owned())); } let file_name = path.file_name().unwrap_or_default(); match ( self.get_syntax_for_file_name(file_name, &mapping.ignored_suffixes)?, syntax_match, ) { (Some(syntax), _) => Ok(syntax), (_, Some(MappingTarget::MapExtensionToUnknown)) => { Err(Error::UndetectedSyntax(path.to_string_lossy().into())) } _ => self .get_syntax_for_file_extension(file_name, &mapping.ignored_suffixes)? .ok_or_else(|| Error::UndetectedSyntax(path.to_string_lossy().into())), } } /// Look up a syntect theme by name. pub fn get_theme(&self, theme: &str) -> &Theme { match self.get_theme_set().get(theme) { Some(theme) => theme, None => { if theme == "ansi-light" || theme == "ansi-dark" { bat_warning!("Theme '{theme}' is deprecated, using 'ansi' instead."); return self.get_theme("ansi"); } if !theme.is_empty() { bat_warning!("Unknown theme '{theme}', using default.") } self.get_theme_set() .get( self.fallback_theme .unwrap_or_else(|| default_theme(ColorScheme::Dark)), ) .expect("something is very wrong if the default theme is missing") } } } pub(crate) fn get_syntax( &self, language: Option<&str>, fallback_syntax: Option<&str>, input: &mut OpenedInput, mapping: &SyntaxMapping, ) -> Result> { if let Some(language) = language { let syntax_set = self.get_syntax_set()?; return syntax_set .find_syntax_by_token(language) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }) .ok_or_else(|| Error::UnknownSyntax(language.to_owned())); } let path = input.path(); let absolute_path = path.and_then(|p| { PathAbs::new(p) .ok() .map(|abs| abs.as_path().to_path_buf()) .or_else(|| Some(p.to_owned())) }); let path_syntax = if let Some(ref path) = absolute_path { self.get_syntax_for_path(path, mapping).or_else(|e| { // If syntax detection failed on the given path, retry with the // canonicalized path (which resolves symlinks). This handles // cases like `Aliases/0install -> ../Formula/zero-install.rb` // where the symlink name has no extension but the target does. // See #1001. if matches!(e, Error::UndetectedSyntax(_)) { if let Ok(resolved) = fs::canonicalize(path) { if resolved != *path { return match self.get_syntax_for_path(&resolved, mapping) { Ok(syntax) => Ok(syntax), Err(Error::UndetectedSyntax(_)) => Err(e), Err(err) => Err(err), }; } } } Err(e) }) } else { Err(Error::UndetectedSyntax("[unknown]".into())) }; // If a path wasn't provided, or if path based syntax detection // above failed, we fall back to first-line syntax detection. match path_syntax { Err(Error::UndetectedSyntax(path)) => { if let Some(syntax_in_set) = self.get_first_line_syntax(&mut input.reader)? { Ok(syntax_in_set) } else if let Some(language) = fallback_syntax { self.find_syntax_by_token(language)? .ok_or_else(|| Error::UnknownSyntax(language.to_owned())) } else { Err(Error::UndetectedSyntax(path)) } } _ => path_syntax, } } pub(crate) fn find_syntax_by_name( &self, syntax_name: &str, ) -> Result>> { let syntax_set = self.get_syntax_set()?; Ok(syntax_set .find_syntax_by_name(syntax_name) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })) } fn find_syntax_by_extension( &self, e: Option<&OsStr>, ) -> Result>> { let syntax_set = self.get_syntax_set()?; let extension = e.and_then(|x| x.to_str()).unwrap_or_default(); Ok(syntax_set .find_syntax_by_extension(extension) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })) } fn find_syntax_by_hidden_file_name( &self, file_name: &OsStr, ) -> Result>> { let Some(hidden_file_extension) = file_name .to_str() .and_then(|name| name.strip_prefix('.')) .filter(|name| !name.is_empty()) else { return Ok(None); }; // syntect stores `hidden_file_extensions` in the same extension list as // regular file extensions, but dotfiles must be queried without the // leading period. self.find_syntax_by_extension(Some(OsStr::new(hidden_file_extension))) } fn find_syntax_by_token(&self, token: &str) -> Result>> { let syntax_set = self.get_syntax_set()?; Ok(syntax_set .find_syntax_by_token(token) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })) } fn get_syntax_for_file_name( &self, file_name: &OsStr, ignored_suffixes: &IgnoredSuffixes, ) -> Result>> { let mut syntax = self.find_syntax_by_extension(Some(file_name))?; if syntax.is_none() { syntax = self.find_syntax_by_hidden_file_name(file_name)?; } if syntax.is_none() { syntax = ignored_suffixes.try_with_stripped_suffix(file_name, |stripped_file_name| { // Note: recursion self.get_syntax_for_file_name(stripped_file_name, ignored_suffixes) })?; } Ok(syntax) } fn get_syntax_for_file_extension( &self, file_name: &OsStr, ignored_suffixes: &IgnoredSuffixes, ) -> Result>> { let mut syntax = self.find_syntax_by_extension(Path::new(file_name).extension())?; if syntax.is_none() { syntax = ignored_suffixes.try_with_stripped_suffix(file_name, |stripped_file_name| { // Note: recursion self.get_syntax_for_file_extension(stripped_file_name, ignored_suffixes) })?; } Ok(syntax) } fn get_first_line_syntax( &self, reader: &mut InputReader, ) -> Result>> { let syntax_set = self.get_syntax_set()?; Ok(String::from_utf8(reader.first_line.clone()) .ok() .and_then(|l| { // Strip UTF-8 BOM if present let line = l.strip_prefix('\u{feff}').unwrap_or(&l); syntax_set.find_syntax_by_first_line(line) }) .map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })) } } pub(crate) fn get_serialized_integrated_syntaxset() -> &'static [u8] { include_bytes!("../assets/syntaxes.bin") } pub(crate) fn get_integrated_themeset() -> LazyThemeSet { from_binary(include_bytes!("../assets/themes.bin"), COMPRESS_THEMES) } pub fn get_acknowledgements() -> String { from_binary( include_bytes!("../assets/acknowledgements.bin"), COMPRESS_ACKNOWLEDGEMENTS, ) } pub(crate) fn from_binary(v: &[u8], compressed: bool) -> T { asset_from_contents(v, "n/a", compressed) .expect("data integrated in binary is never faulty, but make sure `compressed` is in sync!") } fn asset_from_contents( contents: &[u8], description: &str, compressed: bool, ) -> Result { if compressed { bincode::deserialize_from(flate2::read::ZlibDecoder::new(contents)) } else { bincode::deserialize_from(contents) } .map_err(|_| format!("Could not parse {description}").into()) } fn asset_from_cache( path: &Path, description: &str, compressed: bool, ) -> Result { let contents = fs::read(path).map_err(|_| { format!( "Could not load cached {description} '{}'", path.to_string_lossy() ) })?; asset_from_contents(&contents[..], description, compressed) .map_err(|_| format!("Could not parse cached {description}").into()) } #[cfg(test)] mod tests { use super::*; use std::ffi::OsStr; use std::fs::File; use std::io::{BufReader, Write}; use tempfile::TempDir; use crate::input::Input; struct SyntaxDetectionTest<'a> { assets: HighlightingAssets, pub syntax_mapping: SyntaxMapping<'a>, pub temp_dir: TempDir, } impl SyntaxDetectionTest<'_> { fn new() -> Self { SyntaxDetectionTest { assets: HighlightingAssets::from_binary(), syntax_mapping: SyntaxMapping::new(), temp_dir: TempDir::new().expect("creation of temporary directory"), } } fn get_syntax_name( &self, language: Option<&str>, fallback_syntax: Option<&str>, input: &mut OpenedInput, mapping: &SyntaxMapping, ) -> String { self.assets .get_syntax(language, fallback_syntax, input, mapping) .map(|syntax_in_set| syntax_in_set.syntax.name.clone()) .unwrap_or_else(|_| "!no syntax!".to_owned()) } fn syntax_for_real_file_with_content_os( &self, file_name: &OsStr, first_line: &str, ) -> String { let file_path = self.temp_dir.path().join(file_name); { let mut temp_file = File::create(&file_path).unwrap(); writeln!(temp_file, "{first_line}").unwrap(); } let input = Input::ordinary_file(&file_path); let dummy_stdin: &[u8] = &[]; let mut opened_input = input.open(dummy_stdin, None).unwrap(); self.get_syntax_name(None, None, &mut opened_input, &self.syntax_mapping) } fn syntax_for_file_with_content_os(&self, file_name: &OsStr, first_line: &str) -> String { let file_path = self.temp_dir.path().join(file_name); let input = Input::from_reader(Box::new(BufReader::new(first_line.as_bytes()))) .with_name(Some(&file_path)); let dummy_stdin: &[u8] = &[]; let mut opened_input = input.open(dummy_stdin, None).unwrap(); self.get_syntax_name(None, None, &mut opened_input, &self.syntax_mapping) } #[cfg(unix)] fn syntax_for_file_os(&self, file_name: &OsStr) -> String { self.syntax_for_file_with_content_os(file_name, "") } fn syntax_for_file_with_content(&self, file_name: &str, first_line: &str) -> String { self.syntax_for_file_with_content_os(OsStr::new(file_name), first_line) } fn syntax_for_file(&self, file_name: &str) -> String { self.syntax_for_file_with_content(file_name, "") } fn syntax_for_stdin_with_content(&self, file_name: &str, content: &[u8]) -> String { let input = Input::stdin().with_name(Some(file_name)); let mut opened_input = input.open(content, None).unwrap(); self.get_syntax_name(None, None, &mut opened_input, &self.syntax_mapping) } fn syntax_is_same_for_inputkinds(&self, file_name: &str, content: &str) -> bool { let as_file = self.syntax_for_real_file_with_content_os(file_name.as_ref(), content); let as_reader = self.syntax_for_file_with_content_os(file_name.as_ref(), content); let consistent = as_file == as_reader; // TODO: Compare StdIn somehow? if !consistent { eprintln!( "Inconsistent syntax detection:\nFor File: {as_file}\nFor Reader: {as_reader}" ) } consistent } } #[test] fn syntax_detection_basic() { let test = SyntaxDetectionTest::new(); assert_eq!(test.syntax_for_file("test.rs"), "Rust"); assert_eq!(test.syntax_for_file("test.cpp"), "C++"); assert_eq!(test.syntax_for_file("test.build"), "NAnt Build File"); assert_eq!( test.syntax_for_file("PKGBUILD"), "Bourne Again Shell (bash)" ); assert_eq!(test.syntax_for_file(".bashrc"), "Bourne Again Shell (bash)"); assert_eq!(test.syntax_for_file("Makefile"), "Makefile"); } #[cfg(unix)] #[test] fn syntax_detection_invalid_utf8() { use std::os::unix::ffi::OsStrExt; let test = SyntaxDetectionTest::new(); assert_eq!( test.syntax_for_file_os(OsStr::from_bytes(b"invalid_\xFEutf8_filename.rs")), "Rust" ); } #[test] fn syntax_detection_same_for_inputkinds() { let mut test = SyntaxDetectionTest::new(); test.syntax_mapping .insert("*.myext", MappingTarget::MapTo("C")) .ok(); test.syntax_mapping .insert("MY_FILE", MappingTarget::MapTo("Markdown")) .ok(); assert!(test.syntax_is_same_for_inputkinds("Test.md", "")); assert!(test.syntax_is_same_for_inputkinds("Test.txt", "#!/bin/bash")); assert!(test.syntax_is_same_for_inputkinds(".bashrc", "")); assert!(test.syntax_is_same_for_inputkinds("test.h", "")); assert!(test.syntax_is_same_for_inputkinds("test.js", "#!/bin/bash")); assert!(test.syntax_is_same_for_inputkinds("test.myext", "")); assert!(test.syntax_is_same_for_inputkinds("MY_FILE", "")); assert!(test.syntax_is_same_for_inputkinds("MY_FILE", ""; assert_eq!( test.syntax_for_file_with_content("unknown_file", xml_with_bom), "XML" ); // Test the specific .csproj case mentioned in the issue // Even if .csproj has extension mapping, this tests first-line fallback let csproj_content_with_bom = "\u{feff}\n"; assert_eq!( test.syntax_for_file_with_content("test.csproj", csproj_content_with_bom), "XML" ); // Test that shell scripts are detected correctly even with UTF-8 BOM let script_with_bom = "\u{feff}#!/bin/bash"; assert_eq!( test.syntax_for_file_with_content("unknown_script", script_with_bom), "Bourne Again Shell (bash)" ); // Test that PHP files are detected correctly even with UTF-8 BOM let php_with_bom = "\u{feff} bool { env::var("COLORTERM") .map(|colorterm| colorterm == "truecolor" || colorterm == "24bit") .unwrap_or(false) } pub fn env_no_color() -> bool { env::var_os("NO_COLOR").is_some_and(|x| !x.is_empty()) } enum HelpType { Short, Long, } pub struct App { pub matches: ArgMatches, interactive_output: bool, /// True if -n / --number was passed on the command line /// (not from config file or environment variables). /// This is used to honor the flag when piping output, similar to `cat -n`. number_from_cli: bool, } impl App { pub fn new() -> Result { #[cfg(windows)] let _ = nu_ansi_term::enable_ansi_support(); let interactive_output = std::io::stdout().is_terminal(); // Check if the -n / --number option was passed on the command line // (before merging with config file and environment variables). // This is needed to honor the -n flag when piping output, similar to `cat -n`. // We need to handle both standalone (-n, --number) and combined short flags (-pn, -An, etc.) // Note: We only check if -n appears and is not overridden by -p in the same combined flag. // For combined flags like -np, -p comes after -n and overrides it, so we don't count it. // For combined flags like -pn, -n comes after -p and takes effect. let number_from_cli = wild::args_os().any(|arg| { let arg_str = arg.to_string_lossy(); if arg_str == "-n" || arg_str == "--number" { return true; } // Handle combined short flags // Only count -n if it's the LAST flag in the combined form (so -p doesn't override it) // or if -p is not present in the combined form if arg_str.starts_with('-') && !arg_str.starts_with("--") && arg_str.len() > 2 { let chars: Vec = arg_str.chars().skip(1).collect(); let n_pos = chars.iter().position(|&c| c == 'n'); let p_pos = chars.iter().position(|&c| c == 'p'); // -n is in the combined flag and either: // - -p is not present, OR // - -n comes after -p (so -n takes effect) if let Some(n) = n_pos { if p_pos.is_none() || n > p_pos.unwrap() { return true; } } } false }); let matches = Self::matches(interactive_output)?; if matches.get_flag("help") { let help_type = if wild::args_os().any(|arg| arg == "--help") { HelpType::Long } else { HelpType::Short }; let use_pager = match matches.get_one::("paging").map(|s| s.as_str()) { Some("never") => false, _ => !matches.get_flag("no-paging"), }; let use_color = match matches.get_one::("color").map(|s| s.as_str()) { Some("always") => true, Some("never") => false, _ => interactive_output, // auto: use color if interactive }; let pager = matches.get_one::("pager").map(|s| s.as_str()); let theme_options = Self::theme_options_from_matches(&matches); let use_custom_assets = !matches.get_flag("no-custom-assets"); Self::display_help( interactive_output, help_type, use_pager, use_color, pager, theme_options, use_custom_assets, )?; std::process::exit(0); } Ok(App { matches, interactive_output, number_from_cli, }) } fn display_help( interactive_output: bool, help_type: HelpType, use_pager: bool, use_color: bool, pager: Option<&str>, theme_options: ThemeOptions, use_custom_assets: bool, ) -> Result<()> { use crate::assets::assets_from_cache_or_binary; use crate::directories::PROJECT_DIRS; use bat::{ config::Config, controller::Controller, input::Input, style::{StyleComponent, StyleComponents}, theme::theme, PagingMode, }; let mut cmd = clap_app::build_app(interactive_output); let help_text = match help_type { HelpType::Short => cmd.render_help().to_string(), HelpType::Long => cmd.render_long_help().to_string(), }; let inputs: Vec = vec![Input::from_reader(Box::new(help_text.as_bytes()))]; let paging_mode = if use_pager { PagingMode::QuitIfOneScreen } else { PagingMode::Never }; let help_config = Config { style_components: StyleComponents::new(StyleComponent::Plain.components(false)), paging_mode, pager, colored_output: use_color, true_color: use_color, language: if use_color { Some("help") } else { None }, theme: theme(theme_options).to_string(), ..Default::default() }; let cache_dir = PROJECT_DIRS.cache_dir(); let assets = assets_from_cache_or_binary(use_custom_assets, cache_dir)?; Controller::new(&help_config, &assets) .run(inputs, None) .ok(); Ok(()) } /// Build argument list with env vars and CLI args (without config file) fn build_args_without_config() -> Vec { let mut cli_args = wild::args_os(); let mut args = get_args_from_env_vars(); // Put the zero-th CLI argument (program name) first args.insert(0, cli_args.next().unwrap()); // .. and the rest at the end cli_args.for_each(|a| args.push(a)); args } fn matches(interactive_output: bool) -> Result { // Check if we should skip config file processing for special arguments // that don't require full application setup (version, diagnostic) let should_skip_config = wild::args_os().any(|arg| { matches!( arg.to_str(), Some("-V" | "--version" | "--diagnostic" | "--diagnostics") ) }); // Check if help was requested - help should read the config file but be // forgiving of invalid arguments (so configured theme etc. can be used) let help_requested = wild::args_os().any(|arg| matches!(arg.to_str(), Some("-h" | "--help"))); if wild::args_os().nth(1) == Some("cache".into()) { // Skip the config file and env vars let args = wild::args_os().collect::>(); return Ok(clap_app::build_app(interactive_output).get_matches_from(args)); } if wild::args_os().any(|arg| arg == "--no-config") || should_skip_config { // Skip the arguments in bats config file when --no-config is present // or when user requests version or diagnostic information let args = Self::build_args_without_config(); return Ok(clap_app::build_app(interactive_output).get_matches_from(args)); } // Build arguments with config file let mut cli_args = wild::args_os(); // Read arguments from bats config file let config_args = match get_args_from_env_opts_var() { Some(result) => result, None => get_args_from_config_file(), }; // For help, ignore config file parse errors (use empty config instead) // For non-help, propagate the error let mut args = if help_requested { config_args.unwrap_or_default() } else { config_args.map_err(|_| "Could not parse configuration file")? }; // Selected env vars supersede config vars args.extend(get_args_from_env_vars()); // Put the zero-th CLI argument (program name) first args.insert(0, cli_args.next().unwrap()); // .. and the rest at the end cli_args.for_each(|a| args.push(a)); // For help, try parsing with config, and if clap fails (e.g., invalid // argument in config), fall back to parsing without config file args if help_requested { let app = clap_app::build_app(interactive_output); match app.try_get_matches_from(args) { Ok(matches) => Ok(matches), Err(_) => { // Config has invalid arguments, fall back to just env vars + CLI args let fallback_args = Self::build_args_without_config(); Ok(clap_app::build_app(interactive_output).get_matches_from(fallback_args)) } } } else { Ok(clap_app::build_app(interactive_output).get_matches_from(args)) } } pub fn config(&self, inputs: &[Input]) -> Result> { let style_components = self.style_components()?; let extra_plain = self.matches.get_count("plain") > 1; let plain_last_index = self .matches .indices_of("plain") .and_then(Iterator::max) .unwrap_or_default(); let paging_last_index = self .matches .indices_of("paging") .and_then(Iterator::max) .unwrap_or_default(); let paging_mode = match self.matches.get_one::("paging").map(|s| s.as_str()) { Some("always") => { // Disable paging if the second -p (or -pp) is specified after --paging=always if extra_plain && plain_last_index > paging_last_index { PagingMode::Never } else { PagingMode::Always } } Some("never") => PagingMode::Never, Some("auto") | None => { // If we have -pp as an option when in auto mode, the pager should be disabled. if extra_plain || self.matches.get_flag("no-paging") { PagingMode::Never } else if inputs.iter().any(Input::is_stdin) // ignore stdin when --list-themes is used because in that case no input will be read anyways && !self.matches.get_flag("list-themes") { // 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 && !std::io::stdin().is_terminal() { PagingMode::QuitIfOneScreen } else { PagingMode::Never } } else if self.interactive_output { PagingMode::QuitIfOneScreen } else { PagingMode::Never } } _ => unreachable!("other values for --paging are not allowed"), }; let mut syntax_mapping = SyntaxMapping::new(); // start building glob matchers for builtin mappings immediately // this is an appropriate approach because it's statistically likely that // all the custom mappings need to be checked if available_parallelism()?.get() > 1 { syntax_mapping.start_offload_build_all(); } if let Some(values) = self.matches.get_many::("ignored-suffix") { for suffix in values { syntax_mapping.insert_ignored_suffix(suffix); } } if let Some(values) = self.matches.get_many::("map-syntax") { // later args take precedence over earlier ones, hence `.rev()` // see: https://github.com/sharkdp/bat/pull/2755#discussion_r1456416875 for from_to in values.rev() { let parts: Vec<_> = from_to.split(':').collect(); if parts.len() != 2 { return Err("Invalid syntax mapping. The format of the -m/--map-syntax option is ':'. For example: '*.cpp:C++'.".into()); } syntax_mapping.insert(parts[0], MappingTarget::MapTo(parts[1]))?; } } let maybe_term_width = self .matches .get_one::("terminal-width") .and_then(|w| { if w.starts_with('+') || w.starts_with('-') { // Treat argument as a delta to the current terminal width w.parse().ok().map(|delta: i16| { let old_width: u16 = Term::stdout().size().1; let new_width: i32 = i32::from(old_width) + i32::from(delta); if new_width <= 0 { old_width as usize } else { new_width as usize } }) } else { w.parse().ok() } }); Ok(Config { true_color: is_truecolor_terminal(), language: self .matches .get_one::("language") .map(|s| s.as_str()) .or_else(|| { if self.matches.get_flag("show-all") { Some("show-nonprintable") } else { None } }), fallback_syntax: self .matches .get_one::("fallback-syntax") .map(|s| s.as_str()), show_nonprintable: self.matches.get_flag("show-all"), nonprintable_notation: match self .matches .get_one::("nonprintable-notation") .map(|s| s.as_str()) { Some("unicode") => NonprintableNotation::Unicode, Some("caret") => NonprintableNotation::Caret, _ => unreachable!("other values for --nonprintable-notation are not allowed"), }, binary: match self.matches.get_one::("binary").map(|s| s.as_str()) { Some("as-text") => BinaryBehavior::AsText, Some("no-printing") => BinaryBehavior::NoPrinting, _ => unreachable!("other values for --binary are not allowed"), }, wrapping_mode: { if self.matches.get_flag("chop-long-lines") { WrappingMode::NoWrapping(true) } else { match self.matches.get_one::("wrap").map(|s| s.as_str()) { Some("character") => WrappingMode::Character, Some("word") => WrappingMode::Word, Some("never") => WrappingMode::NoWrapping(true), Some("auto") | None => { if self.interactive_output || maybe_term_width.is_some() { if style_components.plain() && maybe_term_width.is_none() { WrappingMode::NoWrapping(false) } else { WrappingMode::Character } } else { // We don't have the tty width when piping to another program. // There's no point in wrapping when this is the case. WrappingMode::NoWrapping(false) } } _ => unreachable!("other values for --wrap are not allowed"), } } }, colored_output: self.matches.get_flag("force-colorization") || match self.matches.get_one::("color").map(|s| s.as_str()) { Some("always") => true, Some("never") => false, Some("auto") => !env_no_color() && self.interactive_output, _ => unreachable!("other values for --color are not allowed"), }, paging_mode, term_width: maybe_term_width.unwrap_or(Term::stdout().size().1 as usize), loop_through: !(self.interactive_output || self.matches.get_one::("color").map(|s| s.as_str()) == Some("always") || self .matches .get_one::("decorations") .map(|s| s.as_str()) == Some("always") || self.matches.get_flag("force-colorization") || self.number_from_cli), tab_width: self .matches .get_one::("tabs") .map(String::from) .and_then(|t| t.parse().ok()) .unwrap_or( if style_components.plain() && paging_mode == PagingMode::Never { 0 } else { 4 }, ), strip_ansi: match self .matches .get_one::("strip-ansi") .map(|s| s.as_str()) { Some("never") => StripAnsiMode::Never, Some("always") => StripAnsiMode::Always, Some("auto") => StripAnsiMode::Auto, _ => unreachable!("other values for --strip-ansi are not allowed"), }, quiet_empty: self.matches.get_flag("quiet-empty"), unbuffered: self.matches.get_flag("unbuffered"), theme: theme(self.theme_options()).to_string(), visible_lines: match self.matches.try_contains_id("diff").unwrap_or_default() && self.matches.get_flag("diff") { #[cfg(feature = "git")] true => VisibleLines::DiffContext( self.matches .get_one::("diff-context") .and_then(|t| t.parse().ok()) .unwrap_or(2), ), _ => VisibleLines::Ranges( self.matches .get_many::("line-range") .map(|vs| vs.map(|s| LineRange::from(s.as_str())).collect()) .transpose()? .map(LineRanges::from) .unwrap_or_default(), ), }, style_components, syntax_mapping, pager: self.matches.get_one::("pager").map(|s| s.as_str()), use_italic_text: self .matches .get_one::("italic-text") .map(|s| s.as_str()) == Some("always"), highlighted_lines: self .matches .get_many::("highlight-line") .map(|ws| ws.map(|s| LineRange::from(s.as_str())).collect()) .transpose()? .map(LineRanges::from) .map(HighlightedLineRanges) .unwrap_or_default(), use_custom_assets: !self.matches.get_flag("no-custom-assets"), #[cfg(feature = "lessopen")] use_lessopen: self.matches.get_flag("lessopen"), set_terminal_title: self.matches.get_flag("set-terminal-title"), squeeze_lines: if self.matches.get_flag("squeeze-blank") { Some( self.matches .get_one::("squeeze-limit") .map(|limit| limit.to_owned()) .unwrap_or(1), ) } else { None }, }) } pub fn inputs(&self) -> Result>> { let filenames: Option> = self .matches .get_many::("file-name") .map(|vs| vs.map(|p| p.as_path()).collect::>()); let files: Option> = self .matches .get_many::("FILE") .map(|vs| vs.map(|p| p.as_path()).collect::>()); // verify equal length of file-names and input FILEs if filenames.is_some() && files.is_some() && filenames.as_ref().map(|v| v.len()) != files.as_ref().map(|v| v.len()) { return Err("Must be one file name per input type.".into()); } let mut filenames_or_none: Box>> = match filenames { Some(filenames) => Box::new(filenames.into_iter().map(Some)), None => Box::new(std::iter::repeat(None)), }; if files.is_none() { return Ok(vec![new_stdin_input( filenames_or_none.next().unwrap_or(None), )]); } let files_or_none: Box> = match files { Some(ref files) => Box::new(files.iter().map(|name| Some(*name))), None => Box::new(std::iter::repeat(None)), }; let mut file_input = Vec::new(); for (filepath, provided_name) in files_or_none.zip(filenames_or_none) { if let Some(filepath) = filepath { if filepath.to_str().unwrap_or_default() == "-" { file_input.push(new_stdin_input(provided_name)); } else { file_input.push(new_file_input(filepath, provided_name)); } } } Ok(file_input) } fn forced_style_components(&self) -> Option { // No components if `--decorations=never``. if self .matches .get_one::("decorations") .map(|s| s.as_str()) == Some("never") { return Some(StyleComponents(HashSet::new())); } // Only line numbers if `--number`. if self.matches.get_flag("number") { return Some(StyleComponents(HashSet::from([ StyleComponent::LineNumbers, ]))); } // Plain if `--plain` is specified at least once. if self.matches.get_count("plain") > 0 { return Some(StyleComponents(HashSet::from([StyleComponent::Plain]))); } // Default behavior. None } fn style_components(&self) -> Result { let matches = &self.matches; let mut styled_components = match self.forced_style_components() { Some(forced_components) => forced_components, // Parse the `--style` arguments and merge them. None if matches.contains_id("style") => { let lists = matches .get_many::("style") .expect("styles present") .map(|v| StyleComponentList::from_str(v)) .collect::>>()?; StyleComponentList::to_components(lists, self.interactive_output, true) } // Use the default. None => StyleComponents(HashSet::from_iter( StyleComponent::Default .components(self.interactive_output) .iter() .cloned(), )), }; // If `grid` is set, remove `rule` as it is a subset of `grid`, and print a warning. if styled_components.grid() && styled_components.0.remove(&StyleComponent::Rule) { bat_warning!("Style 'rule' is a subset of style 'grid', 'rule' will not be visible."); } // Auto-disable line numbers in unbuffered mode to avoid confusion with partial lines if self.matches.get_flag("unbuffered") { styled_components.0.remove(&StyleComponent::LineNumbers); } Ok(styled_components) } fn theme_options(&self) -> ThemeOptions { Self::theme_options_from_matches(&self.matches) } fn theme_options_from_matches(matches: &ArgMatches) -> ThemeOptions { let theme = matches .get_one::("theme") .map(|t| ThemePreference::from_str(t).unwrap()) .unwrap_or_default(); let theme_dark = matches .get_one::("theme-dark") .map(|t| ThemeName::from_str(t).unwrap()); let theme_light = matches .get_one::("theme-light") .map(|t| ThemeName::from_str(t).unwrap()); ThemeOptions { theme, theme_dark, theme_light, } } } ================================================ FILE: src/bin/bat/assets.rs ================================================ use std::fs; use std::io; use std::path::Path; use std::path::PathBuf; use clap::crate_version; use bat::assets::HighlightingAssets; use bat::assets_metadata::AssetsMetadata; use bat::error::*; pub fn clear_assets(cache_dir: &Path) { clear_asset(cache_dir.join("themes.bin"), "theme set cache"); clear_asset(cache_dir.join("syntaxes.bin"), "syntax set cache"); clear_asset(cache_dir.join("metadata.yaml"), "metadata file"); } pub fn assets_from_cache_or_binary( use_custom_assets: bool, cache_dir: &Path, ) -> Result { if let Some(metadata) = AssetsMetadata::load_from_folder(cache_dir)? { if !metadata.is_compatible_with(crate_version!()) { return Err(format!( "The binary caches for the user-customized syntaxes and themes \ in '{}' are not compatible with this version of bat ({}). To solve this, \ either rebuild the cache (bat cache --build) or remove \ the custom syntaxes/themes (bat cache --clear).\n\ For more information, see:\n\n \ https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions", cache_dir.to_string_lossy(), crate_version!() ) .into()); } } let custom_assets = if use_custom_assets { HighlightingAssets::from_cache(cache_dir).ok() } else { None }; Ok(custom_assets.unwrap_or_else(HighlightingAssets::from_binary)) } fn clear_asset(path: PathBuf, description: &str) { print!("Clearing {description} ... "); match fs::remove_file(&path) { Err(err) if err.kind() == io::ErrorKind::NotFound => { println!("skipped (not present)"); } Err(err) => { println!("could not remove the cache file {path:?}: {err}"); } Ok(_) => println!("okay"), } } ================================================ FILE: src/bin/bat/clap_app.rs ================================================ use bat::style::StyleComponentList; use clap::{crate_name, crate_version, value_parser, Arg, ArgAction, ColorChoice, Command}; use once_cell::sync::Lazy; use std::env; use std::path::{Path, PathBuf}; use std::str::FromStr; static VERSION: Lazy = Lazy::new(|| { #[cfg(feature = "bugreport")] let git_version = bugreport::git_version!(fallback = ""); #[cfg(not(feature = "bugreport"))] let git_version = ""; if git_version.is_empty() { crate_version!().to_string() } else { format!("{} ({git_version})", crate_version!()) } }); pub fn build_app(interactive_output: bool) -> Command { let color_when = if interactive_output && !crate::app::env_no_color() { ColorChoice::Auto } else { ColorChoice::Never }; let mut app = Command::new(crate_name!()) .version(VERSION.as_str()) .color(color_when) .hide_possible_values(true) .args_conflicts_with_subcommands(true) .allow_external_subcommands(true) .disable_help_subcommand(true) .disable_help_flag(true) .disable_version_flag(true) .max_term_width(100) .about("A cat(1) clone with wings.") .long_about("A cat(1) clone with syntax highlighting and Git integration.") .arg( Arg::new("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.", ) .num_args(1..) .value_parser(value_parser!(PathBuf)), ) .arg( Arg::new("show-all") .long("show-all") .alias("show-nonprintable") .short('A') .action(ArgAction::SetTrue) .conflicts_with("language") .help("Show non-printable characters (space, tab, newline, ..).") .long_help( "Show non-printable characters like space, tab or newline. \ This option can also be used to print binary files. \ Use '--tabs' to control the width of the tab-placeholders.", ), ) .arg( Arg::new("nonprintable-notation") .long("nonprintable-notation") .action(ArgAction::Set) .default_value("unicode") .value_parser(["unicode", "caret"]) .value_name("notation") .hide_default_value(true) .help("Set notation for non-printable characters.") .long_help( "Set notation for non-printable characters.\n\n\ Possible values:\n \ * unicode (␇, ␊, ␀, ..)\n \ * caret (^G, ^J, ^@, ..)", ), ) .arg( Arg::new("binary") .long("binary") .action(ArgAction::Set) .default_value("no-printing") .value_parser(["no-printing", "as-text"]) .value_name("behavior") .hide_default_value(true) .help("How to treat binary content. (default: no-printing)") .long_help( "How to treat binary content. (default: no-printing)\n\n\ Possible values:\n \ * no-printing: do not print any binary content\n \ * as-text: treat binary content as normal text", ), ) .arg( Arg::new("plain") .overrides_with("plain") .overrides_with("number") .short('p') .long("plain") .action(ArgAction::Count) .help("Show plain style (alias for '--style=plain').") .long_help( "Only show plain style, no decorations. This is an alias for \ '--style=plain'. When '-p' is used twice ('-pp'), it also disables \ automatic paging (alias for '--style=plain --paging=never').", ), ) .arg( Arg::new("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.", ), ) .arg( Arg::new("fallback-syntax") .long("fallback-syntax") .visible_alias("fallback-language") .help("Set a fallback language for undetected syntaxes.") .long_help( "Set a fallback language for syntax highlighting when auto-detection fails. \ Unlike '--language', this is only used when no syntax could be detected from \ filename, custom syntax mappings, or first-line detection.", ), ) .arg( Arg::new("highlight-line") .long("highlight-line") .short('H') .action(ArgAction::Append) .value_name("N:M") .help("Highlight lines N through M.") .long_help( "Highlight the specified line ranges with a different background color \ For example:\n \ '--highlight-line 40' highlights line 40\n \ '--highlight-line 30:40' highlights lines 30 to 40\n \ '--highlight-line :40' highlights lines 1 to 40\n \ '--highlight-line 40:' highlights lines 40 to the end of the file\n \ '--highlight-line 30:+10' highlights lines 30 to 40", ), ) .arg( Arg::new("file-name") .long("file-name") .action(ArgAction::Append) .value_name("name") .value_parser(value_parser!(PathBuf)) .help("Specify the name to display for a file.") .long_help( "Specify the name to display for a file. Useful when piping \ data to bat from STDIN when bat does not otherwise know \ the filename. Note that the provided file name is also \ used for syntax detection.", ), ); #[cfg(feature = "git")] { app = app .arg( Arg::new("diff") .long("diff") .short('d') .action(ArgAction::SetTrue) .conflicts_with("line-range") .help("Only show lines that have been added/removed/modified.") .long_help( "Only show lines that have been added/removed/modified with respect \ to the Git index. Use --diff-context=N to control how much context you want to see.", ), ) .arg( Arg::new("diff-context") .long("diff-context") .overrides_with("diff-context") .value_name("N") .value_parser( |n: &str| { n.parse::() .map_err(|_| "must be a number") .map(|_| n.to_owned()) // Convert to Result .map_err(|e| e.to_string()) }, // Convert to Result<(), String> ) .hide_short_help(true) .long_help( "Include N lines of context around added/removed/modified lines when using '--diff'.", ), ) } app = app.arg( Arg::new("tabs") .long("tabs") .overrides_with("tabs") .value_name("T") .value_parser( |t: &str| { t.parse::() .map_err(|_t| "must be a number") .map(|_t| t.to_owned()) // Convert to Result .map_err(|e| e.to_string()) }, // Convert to Result<(), String> ) .help("Set the tab width to T spaces.") .long_help( "Set the tab width to T spaces. Use a width of 0 to pass tabs through \ directly", ), ) .arg( Arg::new("wrap") .long("wrap") .overrides_with("wrap") .value_name("mode") .value_parser(["auto", "never", "character", "word"]) .default_value("auto") .hide_default_value(true) .help("Specify the text-wrapping mode (*auto*, never, character, word).") .long_help("Specify the text-wrapping mode (*auto*, never, character, word). \ The '--terminal-width' option can be used in addition to \ control the output width."), ) .arg( Arg::new("chop-long-lines") .long("chop-long-lines") .short('S') .action(ArgAction::SetTrue) .help("Truncate all lines longer than screen width. Alias for '--wrap=never'."), ) .arg( Arg::new("terminal-width") .long("terminal-width") .value_name("width") .hide_short_help(true) .allow_hyphen_values(true) .value_parser( |t: &str| { let is_offset = t.starts_with('+') || t.starts_with('-'); t.parse::() .map_err(|_e| "must be an offset or number") .and_then(|v| if v == 0 && !is_offset { Err("terminal width cannot be zero") } else { Ok(t.to_owned()) }) .map_err(|e| e.to_string()) }) .help( "Explicitly set the width of the terminal instead of determining it \ automatically. If prefixed with '+' or '-', the value will be treated \ as an offset to the actual terminal width. See also: '--wrap'.", ), ) .arg( Arg::new("number") .long("number") .overrides_with("number") .short('n') .action(ArgAction::SetTrue) .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::new("color") .long("color") .overrides_with("color") .value_name("when") .value_parser(["auto", "never", "always"]) .hide_default_value(true) .default_value("auto") .help("When to use colors (*auto*, never, always).") .long_help( "Specify when to use colored output. The automatic mode \ only enables colors if an interactive terminal is detected - \ colors are automatically disabled if the output goes to a pipe.\n\ Possible values: *auto*, never, always.", ), ) .arg( Arg::new("italic-text") .long("italic-text") .value_name("when") .value_parser(["always", "never"]) .default_value("never") .hide_default_value(true) .help("Use italics in output (always, *never*)") .long_help("Specify when to use ANSI sequences for italic text in the output. Possible values: always, *never*."), ) .arg( Arg::new("decorations") .long("decorations") .overrides_with("decorations") .value_name("when") .value_parser(["auto", "never", "always"]) .default_value("auto") .hide_default_value(true) .help("When to show the decorations (*auto*, never, always).") .long_help( "Specify when to use the decorations that have been specified \ via '--style'. The automatic mode only enables decorations if \ an interactive terminal is detected. The always mode will show \ decorations even when piping output. Possible values: *auto*, never, always.", ) ) .arg( Arg::new("force-colorization") .long("force-colorization") .short('f') .action(ArgAction::SetTrue) .conflicts_with("color") .conflicts_with("decorations") .overrides_with("force-colorization") .hide_short_help(true) .long_help("Alias for '--decorations=always --color=always'. This is useful \ if the output of bat is piped to another program, but you want \ to keep the colorization/decorations.") ) .arg( Arg::new("paging") .long("paging") .overrides_with("paging") .overrides_with("no-paging") .value_name("when") .value_parser(["auto", "never", "always"]) .default_value("auto") .hide_default_value(true) .help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).") .long_help( "Specify when to use the pager. To disable the pager, use \ '--paging=never' or its alias,'-P'. To disable the pager permanently, \ set BAT_PAGING to 'never'. To control which pager is used, see the \ '--pager' option. Possible values: *auto*, never, always." ), ) .arg( Arg::new("no-paging") .short('P') .long("no-paging") .alias("no-pager") .action(ArgAction::SetTrue) .overrides_with("no-paging") .hide(true) .hide_short_help(true) .help("Alias for '--paging=never'") ) .arg( Arg::new("pager") .long("pager") .overrides_with("pager") .value_name("command") .hide_short_help(true) .help("Determine which pager to use.") .long_help( "Determine which pager is used. This option will override the \ PAGER and BAT_PAGER environment variables. The default pager is 'less'. \ If you provide '--pager=builtin', use the built-in 'minus' pager. \ To control when the pager is used, see the '--paging' option. \ Example: '--pager \"less -RF\"'." ), ) .arg( Arg::new("map-syntax") .short('m') .long("map-syntax") .action(ArgAction::Append) .value_name("glob:syntax") .help("Use the specified syntax for files matching the glob pattern ('*.cpp:C++').") .long_help( "Map a glob pattern to an existing syntax name. The glob pattern is matched \ on the full path and the filename. For example, to highlight *.build files \ with the Python syntax, use -m '*.build:Python'. To highlight files named \ '.myignore' with the Git Ignore syntax, use -m '.myignore:Git Ignore'. Note \ that the right-hand side is the *name* of the syntax, not a file extension.", ) ) .arg( Arg::new("ignored-suffix") .action(ArgAction::Append) .long("ignored-suffix") .hide_short_help(true) .help( "Ignore extension. For example:\n \ 'bat --ignored-suffix \".dev\" my_file.json.dev' will use JSON syntax, and ignore '.dev'" ) ) .arg( Arg::new("theme") .long("theme") .overrides_with("theme") .help("Set the color theme for syntax highlighting.") .long_help( "Set the theme for syntax highlighting. Use '--list-themes' to \ see all available themes. To set a default theme, add the \ '--theme=\"...\"' option to the configuration file or export the \ BAT_THEME environment variable (e.g.: export \ BAT_THEME=\"...\").\n\n\ Special values:\n\n \ * auto: Picks a dark or light theme depending on the terminal's colors (default).\n \ Use '--theme-light' and '--theme-dark' to customize the selected theme.\n \ * auto:always: Detect the terminal's colors even when the output is redirected.\n \ * auto:system: Detect the color scheme from the system-wide preference (macOS only).\n \ * dark: Use the dark theme specified by '--theme-dark'.\n \ * light: Use the light theme specified by '--theme-light'.", ), ) .arg( Arg::new("theme-light") .long("theme-light") .overrides_with("theme-light") .value_name("theme") .help("Sets the color theme for syntax highlighting used for light backgrounds.") .long_help( "Sets the theme name for syntax highlighting used when the terminal uses a light background. \ Use '--list-themes' to see all available themes. To set a default theme, add the \ '--theme-light=\"...\" option to the configuration file or export the BAT_THEME_LIGHT \ environment variable (e.g. export BAT_THEME_LIGHT=\"...\")."), ) .arg( Arg::new("theme-dark") .long("theme-dark") .overrides_with("theme-dark") .value_name("theme") .help("Sets the color theme for syntax highlighting used for dark backgrounds.") .long_help( "Sets the theme name for syntax highlighting used when the terminal uses a dark background. \ Use '--list-themes' to see all available themes. To set a default theme, add the \ '--theme-dark=\"...\" option to the configuration file or export the BAT_THEME_DARK \ environment variable (e.g. export BAT_THEME_DARK=\"...\")."), ) .arg( Arg::new("list-themes") .long("list-themes") .action(ArgAction::SetTrue) .help("Display all supported highlighting themes.") .long_help("Display a list of supported themes for syntax highlighting."), ) .arg( Arg::new("squeeze-blank") .long("squeeze-blank") .short('s') .action(ArgAction::SetTrue) .help("Squeeze consecutive empty lines.") .long_help("Squeeze consecutive empty lines into a single empty line.") ) .arg( Arg::new("squeeze-limit") .long("squeeze-limit") .value_parser(|s: &str| s.parse::().map_err(|_| "Requires a non-negative number".to_owned())) .long_help("Set the maximum number of consecutive empty lines to be printed.") .hide_short_help(true) ) .arg( Arg::new("strip-ansi") .long("strip-ansi") .overrides_with("strip-ansi") .value_name("when") .value_parser(["auto", "always", "never"]) .default_value("never") .hide_default_value(true) .help("Strip colors from the input (auto, always, *never*)") .long_help("Specify when to strip ANSI escape sequences from the input. \ The automatic mode will remove escape sequences unless the syntax highlighting \ language is plain text. Possible values: auto, always, *never*.") .hide_short_help(true) ) .arg( Arg::new("style") .long("style") .action(ArgAction::Append) .value_name("components") // Cannot use claps built in validation because we have to turn off clap's delimiters .value_parser(|val: &str| { match StyleComponentList::from_str(val) { Err(err) => Err(err), Ok(_) => Ok(val.to_owned()), } }) .help( "Comma-separated list of style elements to display \ (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).", ) .long_help( "Configure which elements (line numbers, file headers, grid \ borders, Git modifications, ..) to display in addition to the \ file contents. The argument is a comma-separated list of \ components to display (e.g. 'numbers,changes,grid') or a \ pre-defined style ('full'). To set a default style, add the \ '--style=\"..\"' option to the configuration file or export the \ BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\ When styles are specified in multiple places, the \"nearest\" set \ of styles take precedence. The command-line arguments are the highest \ priority, followed by the BAT_STYLE environment variable, and then \ the configuration file. If any set of styles consists entirely of \ components prefixed with \"+\" or \"-\", it will modify the \ previous set of styles instead of replacing them.\n\n\ By default, the following components are enabled:\n \ changes, grid, header-filename, numbers, snip\n\n\ Possible values:\n\n \ * default: enables recommended style components (default).\n \ * full: enables all available components.\n \ * auto: same as 'default', unless the output is piped.\n \ * plain: disables all available components.\n \ * changes: show Git modification markers.\n \ * header: alias for 'header-filename'.\n \ * header-filename: show filenames before the content.\n \ * header-filesize: show file sizes before the content.\n \ * grid: vertical/horizontal lines to separate side bar\n \ and the header from the content.\n \ * rule: horizontal lines to delimit files.\n \ * numbers: show line numbers in the side bar.\n \ * snip: draw separation lines between distinct line ranges.", ), ) .arg( Arg::new("line-range") .long("line-range") .short('r') .action(ArgAction::Append) .value_name("N:M") .allow_hyphen_values(true) .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\n \ '--line-range 40' only prints line 40\n \ '--line-range -10:' prints the last 10 lines\n \ '--line-range 30:+10' prints lines 30 to 40\n \ '--line-range 35::5' prints lines 30 to 40 (line 35 with 5 lines of context)\n \ '--line-range 30:40:2' prints lines 28 to 42 (range 30-40 with 2 lines of context)", ), ) .arg( Arg::new("list-languages") .long("list-languages") .short('L') .action(ArgAction::SetTrue) .conflicts_with("list-themes") .help("Display all supported languages.") .long_help("Display a list of supported languages for syntax highlighting."), ) .arg( Arg::new("unbuffered") .short('u') .long("unbuffered") .action(ArgAction::SetTrue) .help("Enable unbuffered input reading for streaming use cases.") .long_help( "Enable unbuffered input reading. When this flag is set, bat will \ display data as soon as it is available, without waiting for a \ complete line. This is useful for streaming use cases like \ 'tail -f logfile | bat -u --paging=never'. Note that line numbers \ are automatically disabled in unbuffered mode, and syntax \ highlighting may be imperfect on partial lines.", ), ) .arg( Arg::new("no-config") .long("no-config") .action(ArgAction::SetTrue) .hide(true) .help("Do not use the configuration file"), ) .arg( Arg::new("no-custom-assets") .long("no-custom-assets") .action(ArgAction::SetTrue) .hide(true) .help("Do not load custom assets"), ); #[cfg(feature = "application")] { app = app.arg( Arg::new("completion") .long("completion") .value_name("SHELL") .value_parser(["bash", "fish", "ps1", "zsh"]) .help("Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]"), ); } #[cfg(feature = "lessopen")] { app = app .arg( Arg::new("lessopen") .long("lessopen") .action(ArgAction::SetTrue) .help("Enable the $LESSOPEN preprocessor"), ) .arg( Arg::new("no-lessopen") .long("no-lessopen") .action(ArgAction::SetTrue) .overrides_with("lessopen") .hide(true) .help("Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)"), ) } app = app .arg( Arg::new("config-file") .long("config-file") .action(ArgAction::SetTrue) .conflicts_with("list-languages") .conflicts_with("list-themes") .hide(true) .help("Show path to the configuration file."), ) .arg( Arg::new("generate-config-file") .long("generate-config-file") .action(ArgAction::SetTrue) .conflicts_with("list-languages") .conflicts_with("list-themes") .hide(true) .help("Generates a default configuration file."), ) .arg( Arg::new("config-dir") .long("config-dir") .action(ArgAction::SetTrue) .hide(true) .help("Show bat's configuration directory."), ) .arg( Arg::new("cache-dir") .long("cache-dir") .action(ArgAction::SetTrue) .hide(true) .help("Show bat's cache directory."), ) .arg( Arg::new("diagnostic") .long("diagnostic") .alias("diagnostics") .action(ArgAction::SetTrue) .hide_short_help(true) .help("Show diagnostic information for bug reports."), ) .arg( Arg::new("quiet-empty") .long("quiet-empty") .short('E') .action(ArgAction::SetTrue) .help("Produce no output when the input is empty.") .long_help( "When this flag is set, bat will produce no output at all when \ the input is empty. This is useful when piping commands that may \ produce empty output, like 'git diff'.", ), ) .arg( Arg::new("acknowledgements") .long("acknowledgements") .action(ArgAction::SetTrue) .hide_short_help(true) .help("Show acknowledgements."), ) .arg( Arg::new("set-terminal-title") .long("set-terminal-title") .action(ArgAction::SetTrue) .hide_short_help(true) .help("Sets terminal title to filenames when using a pager."), ) .arg( Arg::new("help") .short('h') .long("help") .action(ArgAction::SetTrue) .help("Print help (see more with '--help')") .long_help("Print help (see a summary with '-h')"), ) .arg( Arg::new("version") .long("version") .short('V') .action(ArgAction::Version) .help("Print version"), ); // Check if the current directory contains a file name cache. Otherwise, // enable the 'bat cache' subcommand. if Path::new("cache").exists() { app } else { app.subcommand( Command::new("cache") .hide(true) .about("Modify the syntax-definition and theme cache") .arg_required_else_help(true) .arg( Arg::new("help") .short('h') .long("help") .action(ArgAction::Help) .help("Print help"), ) .arg( Arg::new("build") .long("build") .short('b') .action(ArgAction::SetTrue) .conflicts_with("clear") .help("Initialize (or update) the syntax/theme cache.") .long_help( "Initialize (or update) the syntax/theme cache by loading from \ the source directory (default: the configuration directory).", ), ) .arg( Arg::new("clear") .long("clear") .short('c') .action(ArgAction::SetTrue) .conflicts_with("build") .help("Remove the cached syntax definitions and themes."), ) .arg( Arg::new("source") .long("source") .requires("build") .value_name("dir") .help("Use a different directory to load syntaxes and themes from."), ) .arg( Arg::new("target") .long("target") .requires("build") .value_name("dir") .help( "Use a different directory to store the cached syntax and theme set.", ), ) .arg( Arg::new("blank") .long("blank") .action(ArgAction::SetTrue) .requires("build") .help( "Create completely new syntax and theme sets \ (instead of appending to the default sets).", ), ) .arg( Arg::new("acknowledgements") .long("acknowledgements") .action(ArgAction::SetTrue) .requires("build") .help("Build acknowledgements.bin."), ), ) .after_long_help( "You can use 'bat cache' to customize syntaxes and themes. \ See 'bat cache --help' for more information", ) } } #[test] fn verify_app() { build_app(false).debug_assert(); } ================================================ FILE: src/bin/bat/completions.rs ================================================ use std::env; pub const BASH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_BASH")); pub const FISH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_FISH")); pub const PS1_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_PS1")); pub const ZSH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_ZSH")); ================================================ FILE: src/bin/bat/config.rs ================================================ use std::env; use std::ffi::OsString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use crate::directories::PROJECT_DIRS; #[cfg(not(target_os = "windows"))] const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "/etc"; #[cfg(target_os = "windows")] const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "C:\\ProgramData"; pub fn system_config_file() -> PathBuf { let folder = option_env!("BAT_SYSTEM_CONFIG_PREFIX").unwrap_or(DEFAULT_SYSTEM_CONFIG_PREFIX); let mut path = PathBuf::from(folder); path.push("bat"); path.push("config"); path } pub fn config_file() -> PathBuf { env::var("BAT_CONFIG_PATH") .ok() .map(PathBuf::from) .unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config")) } pub fn generate_config_file() -> bat::error::Result<()> { let config_file = config_file(); if config_file.is_file() { println!( "A config file already exists at: {}", config_file.to_string_lossy() ); print!("Overwrite? (y/N): "); io::stdout().flush()?; let mut decision = String::new(); io::stdin().read_line(&mut decision)?; if !decision.trim().eq_ignore_ascii_case("Y") { return Ok(()); } } else { let config_dir = config_file.parent(); match config_dir { Some(path) => fs::create_dir_all(path)?, None => { return Err(format!( "Unable to write config file to: {}", config_file.to_string_lossy() ) .into()); } } } let default_config = r#"# This is `bat`s configuration file. Each line either contains a comment or # a command-line option that you want to pass to `bat` by default. You can # run `bat --help` to get a list of all possible configuration options. # Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes` # for a list of all available themes #--theme="TwoDark" # Enable this to use italic text on the terminal. This is not supported on all # terminal emulators (like tmux, by default): #--italic-text=always # Uncomment the following line to disable automatic paging: #--paging=never # Uncomment the following line if you are using less version >= 551 and want to # enable mouse scrolling support in `bat` when running inside tmux. This might # disable text selection, unless you press shift. #--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse" # Syntax mappings: map a certain filename pattern to a language. # Example 1: use the C++ syntax for Arduino .ino files # Example 2: Use ".gitignore"-style highlighting for ".ignore" files #--map-syntax "*.ino:C++" #--map-syntax ".ignore:Git Ignore" "#; fs::write(&config_file, default_config).map_err(|e| { format!( "Failed to create config file at '{}': {e}", config_file.to_string_lossy(), ) })?; println!( "Success! Config file written to {}", config_file.to_string_lossy() ); Ok(()) } pub fn get_args_from_config_file() -> Result, shell_words::ParseError> { let mut config = String::new(); let system_config = system_config_file(); let user_config = config_file(); if let Ok(c) = fs::read_to_string(&system_config) { config.push_str(&c); config.push('\n'); } // Skip the user config if it resolves to the same file as the system config, // which can happen when BAT_CONFIG_DIR is set to e.g. "/etc/bat". See #3589. if !same_file(&system_config, &user_config) { if let Ok(c) = fs::read_to_string(&user_config) { config.push_str(&c); } } get_args_from_str(&config) } fn same_file(a: &Path, b: &Path) -> bool { match (fs::canonicalize(a), fs::canonicalize(b)) { (Ok(a), Ok(b)) => a == b, _ => a == b, } } pub fn get_args_from_env_opts_var() -> Option, shell_words::ParseError>> { env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s)) } fn get_args_from_str(content: &str) -> Result, shell_words::ParseError> { let args_per_line = content .split('\n') .map(|line| line.trim()) .filter(|line| !line.is_empty()) .filter(|line| !line.starts_with('#')) .map(shell_words::split) .collect::, _>>()?; Ok(args_per_line .iter() .flatten() .map(|line| line.into()) .collect()) } pub fn get_args_from_env_vars() -> Vec { [ ("--tabs", "BAT_TABS"), ("--theme", bat::theme::env::BAT_THEME), ("--theme-dark", bat::theme::env::BAT_THEME_DARK), ("--theme-light", bat::theme::env::BAT_THEME_LIGHT), ("--pager", "BAT_PAGER"), ("--paging", "BAT_PAGING"), ("--style", "BAT_STYLE"), ] .iter() .filter_map(|(flag, key)| { env::var(key) .ok() .map(|var| [flag.to_string(), var].join("=")) }) .map(|a| a.into()) .collect() } #[test] fn empty() { let args = get_args_from_str("").unwrap(); assert!(args.is_empty()); } #[test] fn single() { assert_eq!(vec!["--plain"], get_args_from_str("--plain").unwrap()); } #[test] fn multiple() { assert_eq!( vec!["--plain", "--language=cpp"], get_args_from_str("--plain --language=cpp").unwrap() ); } #[test] fn quotes() { assert_eq!( vec!["--theme", "Sublime Snazzy"], get_args_from_str("--theme \"Sublime Snazzy\"").unwrap() ); } #[test] fn multi_line() { let config = " -p --style numbers,changes --color=always "; assert_eq!( vec!["-p", "--style", "numbers,changes", "--color=always"], get_args_from_str(config).unwrap() ); } #[test] fn comments() { let config = " # plain style -p # show line numbers and Git modifications --style numbers,changes # Always show ANSI colors --color=always "; assert_eq!( vec!["-p", "--style", "numbers,changes", "--color=always"], get_args_from_str(config).unwrap() ); } #[test] fn same_file_identical_paths() { let dir = tempfile::tempdir().unwrap(); let file = dir.path().join("config"); fs::write(&file, "").unwrap(); assert!(same_file(&file, &file)); } #[test] fn same_file_different_paths() { let dir = tempfile::tempdir().unwrap(); let a = dir.path().join("a"); let b = dir.path().join("b"); fs::write(&a, "").unwrap(); fs::write(&b, "").unwrap(); assert!(!same_file(&a, &b)); } #[test] fn same_file_nonexistent() { let dir = tempfile::tempdir().unwrap(); let a = dir.path().join("a"); let b = dir.path().join("b"); assert!(!same_file(&a, &b)); } #[cfg(unix)] #[test] fn same_file_via_symlink() { let dir = tempfile::tempdir().unwrap(); let original = dir.path().join("config"); let link = dir.path().join("link"); fs::write(&original, "").unwrap(); std::os::unix::fs::symlink(&original, &link).unwrap(); assert!(same_file(&original, &link)); } ================================================ FILE: src/bin/bat/directories.rs ================================================ use std::env; use std::path::{Path, PathBuf}; use etcetera::BaseStrategy; use once_cell::sync::Lazy; /// Wrapper for 'etcetera' that checks BAT_CACHE_PATH and BAT_CONFIG_DIR and falls back to the /// Windows known folder locations on Windows & the XDG Base Directory Specification everywhere else. pub struct BatProjectDirs { cache_dir: PathBuf, config_dir: PathBuf, } impl BatProjectDirs { fn new() -> Option { let basedirs = etcetera::choose_base_strategy().ok()?; // Checks whether or not `$BAT_CACHE_PATH` exists. If it doesn't, set the cache dir to our // system's default cache home. let cache_dir = if let Some(cache_dir) = env::var_os("BAT_CACHE_PATH").map(PathBuf::from) { cache_dir } else { basedirs.cache_dir().join("bat") }; // Checks whether or not `$BAT_CONFIG_DIR` exists. If it doesn't, set the config dir to our // system's default configuration home. let config_dir = if let Some(config_dir) = env::var_os("BAT_CONFIG_DIR").map(PathBuf::from) { config_dir } else { basedirs.config_dir().join("bat") }; Some(BatProjectDirs { cache_dir, config_dir, }) } pub fn cache_dir(&self) -> &Path { &self.cache_dir } pub fn config_dir(&self) -> &Path { &self.config_dir } } pub static PROJECT_DIRS: Lazy = Lazy::new(|| BatProjectDirs::new().expect("Could not get home directory")); ================================================ FILE: src/bin/bat/input.rs ================================================ use bat::input::Input; use std::path::Path; pub fn new_file_input<'a>(file: &'a Path, name: Option<&'a Path>) -> Input<'a> { named(Input::ordinary_file(file), name.or(Some(file))) } pub fn new_stdin_input(name: Option<&Path>) -> Input<'_> { named(Input::stdin(), name) } fn named<'a>(input: Input<'a>, name: Option<&Path>) -> Input<'a> { if let Some(provided_name) = name { let mut input = input.with_name(Some(provided_name)); input.description_mut().set_kind(Some("File".to_owned())); input } else { input } } ================================================ FILE: src/bin/bat/main.rs ================================================ #![deny(unsafe_code)] mod app; mod assets; mod clap_app; #[cfg(feature = "application")] mod completions; mod config; mod directories; mod input; use std::collections::{HashMap, HashSet}; use std::fmt::Write as _; use std::io; use std::io::{BufReader, Write}; use std::path::Path; use std::process; use bat::output::{OutputHandle, OutputType}; use bat::theme::DetectColorScheme; use nu_ansi_term::Color::Green; use nu_ansi_term::Style; use crate::{ app::App, config::{config_file, generate_config_file}, }; #[cfg(feature = "bugreport")] use crate::config::system_config_file; use assets::{assets_from_cache_or_binary, clear_assets}; use directories::PROJECT_DIRS; use globset::GlobMatcher; use bat::{ config::Config, controller::Controller, error::*, input::Input, style::{StyleComponent, StyleComponents}, theme::{color_scheme, default_theme, ColorScheme}, MappingTarget, PagingMode, }; const THEME_PREVIEW_DATA: &[u8] = include_bytes!("../../../assets/theme_preview.rs"); #[cfg(feature = "build-assets")] fn build_assets(matches: &clap::ArgMatches, config_dir: &Path, cache_dir: &Path) -> Result<()> { let source_dir = matches .get_one::("source") .map(Path::new) .unwrap_or_else(|| config_dir); bat::assets::build( source_dir, !matches.get_flag("blank"), matches.get_flag("acknowledgements"), cache_dir, clap::crate_version!(), ) } fn run_cache_subcommand( matches: &clap::ArgMatches, #[cfg(feature = "build-assets")] config_dir: &Path, default_cache_dir: &Path, ) -> Result<()> { let cache_dir = matches .get_one::("target") .map(Path::new) .unwrap_or_else(|| default_cache_dir); if matches.get_flag("build") { #[cfg(feature = "build-assets")] build_assets(matches, config_dir, cache_dir)?; #[cfg(not(feature = "build-assets"))] println!("bat has been built without the 'build-assets' feature. The 'cache --build' option is not available."); } else if matches.get_flag("clear") { clear_assets(cache_dir); } Ok(()) } fn get_syntax_mapping_to_paths<'r, 't, I>(mappings: I) -> HashMap<&'t str, Vec> where I: IntoIterator)>, 't: 'r, // target text outlives rule { let mut map = HashMap::new(); for mapping in mappings { if let (matcher, MappingTarget::MapTo(s)) = mapping { let globs = map.entry(*s).or_insert_with(Vec::new); globs.push(matcher.glob().glob().into()); } } map } pub fn get_languages(config: &Config, cache_dir: &Path) -> Result { let mut result: String = String::new(); let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?; let mut languages = assets .get_syntaxes()? .iter() .filter(|syntax| !syntax.hidden && !syntax.file_extensions.is_empty()) .cloned() .collect::>(); // Handling of file-extension conflicts, see issue #1076 for lang in &mut languages { let lang_name = lang.name.clone(); lang.file_extensions.retain(|extension| { // The 'extension' variable is not certainly a real extension. // // Skip if 'extension' starts with '.', likely a hidden file like '.vimrc' // Also skip if the 'extension' contains another real extension, likely // that is a full match file name like 'CMakeLists.txt' and 'Cargo.lock' if extension.starts_with('.') || Path::new(extension).extension().is_some() { return true; } let test_file = Path::new("test").with_extension(extension); let syntax_in_set = assets.get_syntax_for_path(test_file, &config.syntax_mapping); matches!(syntax_in_set, Ok(syntax_in_set) if syntax_in_set.syntax.name == lang_name) }); } languages.sort_by_key(|lang| lang.name.to_uppercase()); let configured_languages = get_syntax_mapping_to_paths(config.syntax_mapping.all_mappings()); for lang in &mut languages { if let Some(additional_paths) = configured_languages.get(lang.name.as_str()) { lang.file_extensions .extend(additional_paths.iter().cloned()); } } if config.loop_through { for lang in languages { writeln!(result, "{}:{}", lang.name, lang.file_extensions.join(",")).ok(); } } else { let longest = languages .iter() .map(|syntax| syntax.name.len()) .max() .unwrap_or(32); // Fallback width if they have no language definitions. let comma_separator = ", "; let separator = " "; // Line-wrapping for the possible file extension overflow. let desired_width = config.term_width - longest - separator.len(); let style = if config.colored_output { Green.normal() } else { Style::default() }; for lang in languages { write!(result, "{:width$}{separator}", lang.name, width = longest).ok(); // Number of characters on this line so far, wrap before `desired_width` let mut num_chars = 0; let mut extension = lang.file_extensions.iter().peekable(); while let Some(word) = extension.next() { // If we can't fit this word in, then create a line break and align it in. let new_chars = word.len() + comma_separator.len(); if num_chars + new_chars >= desired_width { num_chars = 0; write!(result, "\n{:width$}{separator}", "", width = longest).ok(); } num_chars += new_chars; write!(result, "{}", style.paint(&word[..])).ok(); if extension.peek().is_some() { result += comma_separator; } } result += "\n"; } } Ok(result) } fn theme_preview_file<'a>() -> Input<'a> { Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA))) } pub fn list_themes( cfg: &Config, config_dir: &Path, cache_dir: &Path, detect_color_scheme: DetectColorScheme, ) -> Result<()> { let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?; let mut config = cfg.clone(); let mut style = HashSet::new(); style.insert(StyleComponent::Plain); config.language = Some("Rust"); config.style_components = StyleComponents(style); let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default()); let mut buf = String::new(); let mut handle = OutputHandle::FmtWrite(&mut buf); for theme in assets.themes() { let default_theme_info = if default_theme_name == theme { " (default)" } else if default_theme(ColorScheme::Dark) == theme { " (default dark)" } else if default_theme(ColorScheme::Light) == theme { " (default light)" } else { "" }; if config.colored_output { handle.write_fmt(format_args!( "{}{default_theme_info}\n\n", Style::new().bold().paint(theme.to_string()), ))?; config.theme = theme.to_string(); Controller::new(&config, &assets) .run(vec![theme_preview_file()], Some(&mut handle)) .ok(); handle.write_fmt(format_args!("\n"))?; } else if config.loop_through { handle.write_fmt(format_args!("{theme}\n"))?; } else { handle.write_fmt(format_args!("{theme}{default_theme_info}\n"))?; } } if config.colored_output { handle.write_fmt(format_args!( "Further themes can be installed to '{}', \ and are added to the cache with `bat cache --build`. \ For more information, see:\n\n \ https://github.com/sharkdp/bat#adding-new-themes", config_dir.join("themes").to_string_lossy() ))?; } let mut output_type = OutputType::from_mode(config.paging_mode, config.wrapping_mode, config.pager)?; let mut writer = output_type.handle()?; writer.write_fmt(format_args!("{buf}"))?; Ok(()) } fn set_terminal_title_to(new_terminal_title: String) { let osc_command_for_setting_terminal_title = "\x1b]0;"; let osc_end_command = "\x07"; print!("{osc_command_for_setting_terminal_title}{new_terminal_title}{osc_end_command}"); io::stdout().flush().unwrap(); } fn get_new_terminal_title(inputs: &Vec) -> String { let mut new_terminal_title = "bat: ".to_string(); for (index, input) in inputs.iter().enumerate() { new_terminal_title += input.description().title(); if index < inputs.len() - 1 { new_terminal_title += ", "; } } new_terminal_title } fn run_controller(inputs: Vec, config: &Config, cache_dir: &Path) -> Result { let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?; let controller = Controller::new(config, &assets); if config.paging_mode != PagingMode::Never && config.set_terminal_title { set_terminal_title_to(get_new_terminal_title(&inputs)); } controller.run(inputs, None) } #[cfg(feature = "bugreport")] fn invoke_bugreport(app: &App, cache_dir: &Path) { use bugreport::{bugreport, collector::*, format::Markdown}; let pager = bat::config::get_pager_executable( app.matches.get_one::("pager").map(|s| s.as_str()), ) .unwrap_or_else(|| "less".to_owned()); // FIXME: Avoid non-canonical path to "less". let mut custom_assets_metadata = cache_dir.to_path_buf(); custom_assets_metadata.push("metadata.yaml"); let mut report = bugreport!() .info(SoftwareVersion::default()) .info(OperatingSystem::default()) .info(CommandLine::default()) .info(EnvironmentVariables::list(&[ "BAT_CACHE_PATH", "BAT_CONFIG_PATH", "BAT_OPTS", "BAT_PAGER", "BAT_PAGING", "BAT_STYLE", "BAT_TABS", "BAT_THEME", "COLORTERM", "LANG", "LC_ALL", "LESS", "MANPAGER", "NO_COLOR", "PAGER", "SHELL", "TERM", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", ])) .info(FileContent::new("System Config file", system_config_file())) .info(FileContent::new("Config file", config_file())) .info(FileContent::new( "Custom assets metadata", custom_assets_metadata, )) .info(DirectoryEntries::new("Custom assets", cache_dir)) .info(CompileTimeInformation::default()); #[cfg(feature = "paging")] if let Ok(resolved_path) = grep_cli::resolve_binary(pager) { report = report.info(CommandOutput::new( "Less version", resolved_path, &["--version"], )) }; report.print::(); } /// Returns `Err(..)` upon fatal errors. Otherwise, returns `Ok(true)` on full success and /// `Ok(false)` if any intermediate errors occurred (were printed). fn run() -> Result { let app = App::new()?; let config_dir = PROJECT_DIRS.config_dir(); let cache_dir = PROJECT_DIRS.cache_dir(); if app.matches.get_flag("diagnostic") { #[cfg(feature = "bugreport")] invoke_bugreport(&app, cache_dir); #[cfg(not(feature = "bugreport"))] println!("bat has been built without the 'bugreport' feature. The '--diagnostic' option is not available."); return Ok(true); } #[cfg(feature = "application")] if let Some(shell) = app.matches.get_one::("completion") { match shell.as_str() { "bash" => println!("{}", completions::BASH_COMPLETION), "fish" => println!("{}", completions::FISH_COMPLETION), "ps1" => println!("{}", completions::PS1_COMPLETION), "zsh" => println!("{}", completions::ZSH_COMPLETION), _ => unreachable!("No completion for shell '{shell}' available."), } return Ok(true); } match app.matches.subcommand() { Some(("cache", 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_present() { run_cache_subcommand( cache_matches, #[cfg(feature = "build-assets")] config_dir, cache_dir, )?; Ok(true) } else { let inputs = vec![Input::ordinary_file("cache")]; let config = app.config(&inputs)?; run_controller(inputs, &config, cache_dir) } } _ => { let inputs = app.inputs()?; let config = app.config(&inputs)?; if app.matches.get_flag("list-languages") { let languages: String = get_languages(&config, cache_dir)?; let inputs: Vec = vec![Input::from_reader(Box::new(languages.as_bytes()))]; let plain_config = Config { style_components: StyleComponents::new(StyleComponent::Plain.components(false)), paging_mode: PagingMode::QuitIfOneScreen, ..Default::default() }; run_controller(inputs, &plain_config, cache_dir) } else if app.matches.get_flag("list-themes") { list_themes(&config, config_dir, cache_dir, DetectColorScheme::default())?; Ok(true) } else if app.matches.get_flag("config-file") { println!("{}", config_file().to_string_lossy()); Ok(true) } else if app.matches.get_flag("generate-config-file") { generate_config_file()?; Ok(true) } else if app.matches.get_flag("config-dir") { writeln!(io::stdout(), "{}", config_dir.to_string_lossy())?; Ok(true) } else if app.matches.get_flag("cache-dir") { writeln!(io::stdout(), "{}", cache_dir.to_string_lossy())?; Ok(true) } else if app.matches.get_flag("acknowledgements") { writeln!(io::stdout(), "{}", bat::assets::get_acknowledgements())?; Ok(true) } else { run_controller(inputs, &config, cache_dir) } } } } fn main() { let result = run(); match result { Err(error) => { let stderr = std::io::stderr(); default_error_handler(&error, &mut stderr.lock()); process::exit(1); } Ok(false) => { process::exit(1); } Ok(true) => { process::exit(0); } } } ================================================ FILE: src/config.rs ================================================ use crate::line_range::{HighlightedLineRanges, LineRanges}; use crate::nonprintable_notation::{BinaryBehavior, NonprintableNotation}; #[cfg(feature = "paging")] use crate::paging::PagingMode; use crate::style::StyleComponents; use crate::syntax_mapping::SyntaxMapping; use crate::wrapping::WrappingMode; use crate::StripAnsiMode; #[derive(Debug, Clone)] pub enum VisibleLines { /// Show all lines which are included in the line ranges Ranges(LineRanges), #[cfg(feature = "git")] /// Only show lines surrounding added/deleted/modified lines DiffContext(usize), } impl VisibleLines { pub fn diff_mode(&self) -> bool { match self { Self::Ranges(_) => false, #[cfg(feature = "git")] Self::DiffContext(_) => true, } } } impl Default for VisibleLines { fn default() -> Self { VisibleLines::Ranges(LineRanges::default()) } } #[derive(Debug, Clone, Default)] pub struct Config<'a> { /// The explicitly configured language, if any pub language: Option<&'a str>, /// The fallback syntax used when auto-detection fails pub fallback_syntax: Option<&'a str>, /// Whether or not to show/replace non-printable characters like space, tab and newline. pub show_nonprintable: bool, /// The configured notation for non-printable characters pub nonprintable_notation: NonprintableNotation, /// How to treat binary content pub binary: BinaryBehavior, /// 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 style_components: StyleComponents, /// If and how text should be wrapped pub wrapping_mode: WrappingMode, /// Pager or STDOUT #[cfg(feature = "paging")] pub paging_mode: PagingMode, /// Specifies which lines should be printed pub visible_lines: VisibleLines, /// The syntax highlighting theme pub theme: String, /// File extension/name mappings pub syntax_mapping: SyntaxMapping<'a>, /// Command to start the pager pub pager: Option<&'a str>, /// Whether or not to use ANSI italics pub use_italic_text: bool, /// Ranges of lines which should be highlighted with a special background color pub highlighted_lines: HighlightedLineRanges, /// Whether or not to allow custom assets. If this is false or if custom assets (a.k.a. /// cached assets) are not available, assets from the binary will be used instead. pub use_custom_assets: bool, // Whether or not to use $LESSOPEN if set #[cfg(feature = "lessopen")] pub use_lessopen: bool, // Whether or not to set terminal title when using a pager pub set_terminal_title: bool, /// The maximum number of consecutive empty lines to display pub squeeze_lines: Option, // Whether or not to strip ANSI escape codes from the input pub strip_ansi: StripAnsiMode, /// Whether or not to produce no output when input is empty pub quiet_empty: bool, /// Whether or not to use unbuffered input reading for streaming use cases pub unbuffered: bool, } #[cfg(all(feature = "minimal-application", feature = "paging"))] pub fn get_pager_executable(config_pager: Option<&str>) -> Option { crate::pager::get_pager(config_pager) .ok() .flatten() .and_then(|pager| { if pager.kind != crate::pager::PagerKind::Builtin { Some(pager.bin) } else { None } }) } #[test] fn default_config_should_include_all_lines() { use crate::line_range::MaxBufferedLineNumber; use crate::line_range::RangeCheckResult; assert_eq!( LineRanges::default().check(17, MaxBufferedLineNumber::Tentative(17)), RangeCheckResult::InRange ); } #[test] fn default_config_should_highlight_no_lines() { use crate::line_range::MaxBufferedLineNumber; use crate::line_range::RangeCheckResult; assert_ne!( Config::default() .highlighted_lines .0 .check(17, MaxBufferedLineNumber::Tentative(17)), RangeCheckResult::InRange ); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_with_config_pager_less() { let result = get_pager_executable(Some("less")); assert_eq!(result, Some("less".to_string())); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_with_config_pager_builtin() { let result = get_pager_executable(Some("builtin")); assert_eq!(result, None); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_with_config_pager_more() { let result = get_pager_executable(Some("more")); assert_eq!(result, Some("more".to_string())); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_with_bat_pager() { std::env::set_var("BAT_PAGER", "most"); let result = get_pager_executable(None); assert_eq!(result, Some("most".to_string())); std::env::remove_var("BAT_PAGER"); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_with_pager_more_switches_to_less() { std::env::set_var("PAGER", "more"); let result = get_pager_executable(None); assert_eq!(result, Some("less".to_string())); std::env::remove_var("PAGER"); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_default() { // Ensure no env vars std::env::remove_var("BAT_PAGER"); std::env::remove_var("PAGER"); let result = get_pager_executable(None); assert_eq!(result, Some("less".to_string())); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_name_ignoring_arguments() { let result = get_pager_executable(Some("foo --bar")); assert_eq!(result, Some("foo".to_string())); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_name_ignoring_path() { let result = get_pager_executable(Some("/bin/foo test")); assert_eq!(result, Some("/bin/foo".to_string())); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_invalid_command() { let result = get_pager_executable(Some("invalid ' command")); assert_eq!(result, None); } #[cfg(all(feature = "minimal-application", feature = "paging"))] #[test] fn get_pager_executable_empty_config() { let result = get_pager_executable(Some("")); assert_eq!(result, None); } ================================================ FILE: src/controller.rs ================================================ use crate::assets::HighlightingAssets; use crate::config::{Config, VisibleLines}; #[cfg(feature = "git")] use crate::diff::{get_git_diff, LineChanges}; use crate::error::*; use crate::input::{Input, InputReader, OpenedInput}; #[cfg(feature = "lessopen")] use crate::lessopen::LessOpenPreprocessor; #[cfg(feature = "git")] use crate::line_range::LineRange; use crate::line_range::{LineRanges, MaxBufferedLineNumber, RangeCheckResult}; use crate::output::{OutputHandle, OutputType}; #[cfg(feature = "paging")] use crate::paging::PagingMode; use crate::printer::{InteractivePrinter, Printer, SimplePrinter}; use std::collections::VecDeque; use std::io::{self, BufRead, Write}; use std::mem; use clircle::{Clircle, Identifier}; pub struct Controller<'a> { config: &'a Config<'a>, assets: &'a HighlightingAssets, #[cfg(feature = "lessopen")] preprocessor: Option, } impl Controller<'_> { pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> { Controller { config, assets, #[cfg(feature = "lessopen")] preprocessor: LessOpenPreprocessor::new().ok(), } } pub fn run( &self, inputs: Vec, output_handle: Option<&mut OutputHandle<'_>>, ) -> Result { self.run_with_error_handler(inputs, output_handle, default_error_handler) } pub fn run_with_error_handler( &self, inputs: Vec, output_handle: Option<&mut OutputHandle<'_>>, mut handle_error: impl FnMut(&Error, &mut dyn Write), ) -> Result { // only create our own OutputType if no output handle was provided. #[allow(unused_mut)] let mut output_type_opt: Option = None; #[cfg(feature = "paging")] if output_handle.is_none() { use crate::input::InputKind; use std::path::Path; // Do not launch the pager if NONE of the input files exist let mut paging_mode = self.config.paging_mode; if self.config.paging_mode != PagingMode::Never { let call_pager = inputs.iter().any(|input| { if let InputKind::OrdinaryFile(ref path) = input.kind { Path::new(path).exists() } else { true } }); if !call_pager { paging_mode = PagingMode::Never; } } let wrapping_mode = self.config.wrapping_mode; output_type_opt = Some(OutputType::from_mode( paging_mode, wrapping_mode, self.config.pager, )?); } #[cfg(not(feature = "paging"))] if output_handle.is_none() { output_type_opt = Some(OutputType::stdout()); } let attached_to_pager = match (&output_handle, &output_type_opt) { (Some(_), _) => true, (None, Some(ot)) => ot.is_pager(), (None, None) => false, }; let stdout_identifier = if cfg!(windows) || attached_to_pager { None } else { clircle::Identifier::stdout() }; let mut writer = match (output_handle, &mut output_type_opt) { (Some(OutputHandle::FmtWrite(w)), _) => OutputHandle::FmtWrite(w), (Some(OutputHandle::IoWrite(w)), _) => OutputHandle::IoWrite(w), (None, Some(ot)) => ot.handle()?, (None, None) => unreachable!("No output handle and no output type available"), }; let mut no_errors: bool = true; let stderr = io::stderr(); for (index, input) in inputs.into_iter().enumerate() { let identifier = stdout_identifier.as_ref(); let is_first = index == 0; let result = if input.is_stdin() { self.print_input(input, &mut writer, io::stdin().lock(), identifier, is_first) } else { // Use dummy stdin since stdin is actually not used (#1902) self.print_input(input, &mut writer, io::empty(), identifier, is_first) }; if let Err(error) = result { match writer { // It doesn't make much sense to send errors straight to stderr if the user // provided their own buffer, so we just return it. OutputHandle::FmtWrite(_) => return Err(error), OutputHandle::IoWrite(ref mut writer) => { if attached_to_pager { handle_error(&error, writer); } else { handle_error(&error, &mut stderr.lock()); } } } no_errors = false; } } Ok(no_errors) } fn print_input( &self, input: Input, writer: &mut OutputHandle, stdin: R, stdout_identifier: Option<&Identifier>, is_first: bool, ) -> Result<()> { let mut opened_input = { #[cfg(feature = "lessopen")] match self.preprocessor { Some(ref preprocessor) if self.config.use_lessopen => { preprocessor.open(input, stdin, stdout_identifier)? } _ => input.open(stdin, stdout_identifier)?, } #[cfg(not(feature = "lessopen"))] input.open(stdin, stdout_identifier)? }; opened_input.reader.unbuffered = self.config.unbuffered; #[cfg(feature = "git")] let line_changes = if self.config.visible_lines.diff_mode() || (!self.config.loop_through && self.config.style_components.changes()) { match opened_input.kind { crate::input::OpenedInputKind::OrdinaryFile(ref path) => { let diff = get_git_diff(path); // Skip files without Git modifications if self.config.visible_lines.diff_mode() && diff .as_ref() .map(|changes| changes.is_empty()) .unwrap_or(false) { return Ok(()); } diff } _ if self.config.visible_lines.diff_mode() => { // Skip non-file inputs in diff mode return Ok(()); } _ => None, } } else { None }; let mut printer: Box = if self.config.loop_through { Box::new(SimplePrinter::new(self.config)) } else { Box::new(InteractivePrinter::new( self.config, self.assets, &mut opened_input, #[cfg(feature = "git")] &line_changes, )?) }; self.print_file( &mut *printer, writer, &mut opened_input, !is_first, #[cfg(feature = "git")] &line_changes, ) } fn print_file( &self, printer: &mut dyn Printer, writer: &mut OutputHandle, input: &mut OpenedInput, add_header_padding: bool, #[cfg(feature = "git")] line_changes: &Option, ) -> Result<()> { if !input.reader.first_line.is_empty() || self.config.style_components.header() { printer.print_header(writer, input, add_header_padding)?; } if !input.reader.first_line.is_empty() { let line_ranges = match self.config.visible_lines { VisibleLines::Ranges(ref line_ranges) => line_ranges.clone(), #[cfg(feature = "git")] VisibleLines::DiffContext(context) => { let mut line_ranges: Vec = vec![]; if let Some(line_changes) = line_changes { for &line in line_changes.keys() { let line = line as usize; line_ranges .push(LineRange::new(line.saturating_sub(context), line + context)); } } LineRanges::from(line_ranges) } }; self.print_file_ranges(printer, writer, &mut input.reader, &line_ranges)?; } printer.print_footer(writer, input)?; Ok(()) } fn print_file_ranges( &self, printer: &mut dyn Printer, writer: &mut OutputHandle, reader: &mut InputReader, line_ranges: &LineRanges, ) -> Result<()> { let mut current_line_buffer: Vec = Vec::new(); let mut current_line_number: usize = 1; // Buffer needs to be 1 greater than the offset to have a look-ahead line for EOF let buffer_size: usize = line_ranges.largest_offset_from_end() + 1; // Buffers multiple line data and line number let mut buffered_lines: VecDeque<(Vec, usize)> = VecDeque::with_capacity(buffer_size); let mut reached_eof: bool = false; let mut first_range: bool = true; let mut mid_range: bool = false; let style_snip = self.config.style_components.snip(); loop { if reached_eof && buffered_lines.is_empty() { // Done processing all lines break; } if !reached_eof { if reader.read_line(&mut current_line_buffer)? { // Fill the buffer buffered_lines .push_back((mem::take(&mut current_line_buffer), current_line_number)); current_line_number += 1; } else { // No more data to read reached_eof = true; } } if buffered_lines.len() < buffer_size && !reached_eof { // The buffer needs to be completely filled first continue; } let Some((line, line_nr)) = buffered_lines.pop_front() else { break; }; // Determine if the last line number in the buffer is the last line of the file or // just a line somewhere in the file let max_buffered_line_number = buffered_lines .back() .map(|(_, max_line_number)| { if reached_eof { MaxBufferedLineNumber::Final(*max_line_number) } else { MaxBufferedLineNumber::Tentative(*max_line_number) } }) .unwrap_or(MaxBufferedLineNumber::Final(line_nr)); match line_ranges.check(line_nr, max_buffered_line_number) { RangeCheckResult::BeforeOrBetweenRanges => { // 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_nr, &line, max_buffered_line_number)?; mid_range = false; } RangeCheckResult::InRange => { if style_snip { if first_range { first_range = false; mid_range = true; } else if !mid_range { mid_range = true; printer.print_snip(writer)?; } } printer.print_line(false, writer, line_nr, &line, max_buffered_line_number)?; if self.config.unbuffered { writer.flush()?; } } RangeCheckResult::AfterLastRange => { break; } } } Ok(()) } } ================================================ FILE: src/decorations.rs ================================================ #[cfg(feature = "git")] use crate::diff::LineChange; use crate::printer::{Colors, InteractivePrinter}; use nu_ansi_term::Style; #[derive(Debug, Clone)] pub(crate) struct DecorationText { pub width: usize, pub text: String, } pub(crate) trait Decoration { fn generate( &self, line_number: usize, continuation: bool, printer: &InteractivePrinter, ) -> DecorationText; fn width(&self) -> usize; } pub(crate) struct LineNumberDecoration { color: Style, cached_wrap: DecorationText, cached_wrap_invalid_at: usize, } impl LineNumberDecoration { pub(crate) 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!("{line_number:4}"); DecorationText { width: plain.len(), text: self.color.paint(plain).to_string(), } } } fn width(&self) -> usize { 4 } } #[cfg(feature = "git")] pub(crate) struct LineChangesDecoration { cached_none: DecorationText, cached_added: DecorationText, cached_removed_above: DecorationText, cached_removed_below: DecorationText, cached_modified: DecorationText, } #[cfg(feature = "git")] impl LineChangesDecoration { #[inline] fn generate_cached(style: Style, text: &str) -> DecorationText { DecorationText { text: style.paint(text).to_string(), width: text.chars().count(), } } pub(crate) 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, "~"), } } } #[cfg(feature = "git")] 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(crate) struct GridBorderDecoration { cached: DecorationText, } impl GridBorderDecoration { pub(crate) 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 } } ================================================ FILE: src/diff.rs ================================================ #![cfg(feature = "git")] use std::collections::HashMap; use std::fs; use std::path::Path; use git2::{DiffOptions, IntoCString, Repository}; #[derive(Copy, Clone, Debug)] pub enum LineChange { Added, RemovedAbove, RemovedBelow, Modified, } pub type LineChanges = HashMap; pub fn get_git_diff(filename: &Path) -> Option { 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 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) } ================================================ FILE: src/error.rs ================================================ use std::io::Write; use thiserror::Error; #[derive(Error, Debug)] #[non_exhaustive] pub enum Error { #[error(transparent)] Io(#[from] ::std::io::Error), #[error(transparent)] Fmt(#[from] ::std::fmt::Error), #[error(transparent)] SyntectError(#[from] ::syntect::Error), #[error(transparent)] SyntectLoadingError(#[from] ::syntect::LoadingError), #[error(transparent)] ParseIntError(#[from] ::std::num::ParseIntError), #[error(transparent)] GlobParsingError(#[from] ::globset::Error), #[error(transparent)] SerdeYamlError(#[from] ::serde_yaml::Error), #[error("unable to detect syntax for {0}")] UndetectedSyntax(String), #[error("unknown syntax: '{0}'")] UnknownSyntax(String), #[error("Unknown style '{0}'")] UnknownStyle(String), #[error("Use of bat as a pager is disallowed in order to avoid infinite recursion problems")] InvalidPagerValueBat, #[error("{0}")] Msg(String), #[cfg(feature = "paging")] #[error(transparent)] MinusError(#[from] ::minus::MinusError), #[cfg(feature = "lessopen")] #[error(transparent)] VarError(#[from] ::std::env::VarError), #[cfg(feature = "lessopen")] #[error(transparent)] CommandParseError(#[from] ::shell_words::ParseError), } impl From<&'static str> for Error { fn from(s: &'static str) -> Self { Error::Msg(s.to_owned()) } } impl From for Error { fn from(s: String) -> Self { Error::Msg(s) } } pub type Result = std::result::Result; pub fn default_error_handler(error: &Error, output: &mut dyn Write) { use nu_ansi_term::Color::Red; match error { Error::Io(ref io_error) if io_error.kind() == ::std::io::ErrorKind::BrokenPipe => { ::std::process::exit(0); } Error::SerdeYamlError(_) => { writeln!( output, "{}: Error while parsing metadata.yaml file: {error}", Red.paint("[bat error]"), ) .ok(); } _ => { writeln!( &mut std::io::stderr().lock(), "{}: {error}", Red.paint("[bat error]"), ) .ok(); } }; } ================================================ FILE: src/input.rs ================================================ use std::convert::TryFrom; use std::fs; use std::fs::File; use std::io::{self, BufRead, BufReader, Read}; use std::path::{Path, PathBuf}; use clircle::{Clircle, Identifier}; use content_inspector::{self, ContentType}; use crate::error::*; /// A description of an Input source. /// This tells bat how to refer to the input. #[derive(Clone)] pub struct InputDescription { pub(crate) name: String, /// The input title. /// This replaces the name if provided. title: Option, /// The input kind. kind: Option, /// A summary description of the input. /// Defaults to "{kind} '{name}'" summary: Option, } impl InputDescription { /// Creates a description for an input. pub fn new(name: impl Into) -> Self { InputDescription { name: name.into(), title: None, kind: None, summary: None, } } pub fn set_kind(&mut self, kind: Option) { self.kind = kind; } pub fn set_summary(&mut self, summary: Option) { self.summary = summary; } pub fn set_title(&mut self, title: Option) { self.title = title; } pub fn title(&self) -> &String { match &self.title { Some(title) => title, None => &self.name, } } pub fn kind(&self) -> Option<&String> { self.kind.as_ref() } pub fn summary(&self) -> String { self.summary.clone().unwrap_or_else(|| match &self.kind { None => self.name.clone(), Some(kind) => format!("{} '{}'", kind.to_lowercase(), self.name), }) } } pub(crate) enum InputKind<'a> { OrdinaryFile(PathBuf), StdIn, CustomReader(Box), } impl InputKind<'_> { pub fn description(&self) -> InputDescription { match self { InputKind::OrdinaryFile(ref path) => InputDescription::new(path.to_string_lossy()), InputKind::StdIn => InputDescription::new("STDIN"), InputKind::CustomReader(_) => InputDescription::new("READER"), } } } #[derive(Clone, Default)] pub(crate) struct InputMetadata { pub(crate) user_provided_name: Option, pub(crate) size: Option, } pub struct Input<'a> { pub(crate) kind: InputKind<'a>, pub(crate) metadata: InputMetadata, pub(crate) description: InputDescription, } pub(crate) enum OpenedInputKind { OrdinaryFile(PathBuf), StdIn, CustomReader, } pub(crate) struct OpenedInput<'a> { pub(crate) kind: OpenedInputKind, pub(crate) metadata: InputMetadata, pub(crate) reader: InputReader<'a>, pub(crate) description: InputDescription, } impl OpenedInput<'_> { /// Get the path of the file: /// If this was set by the metadata, that will take priority. /// If it wasn't, it will use the real file path (if available). pub(crate) fn path(&self) -> Option<&PathBuf> { self.metadata .user_provided_name .as_ref() .or(match self.kind { OpenedInputKind::OrdinaryFile(ref path) => Some(path), _ => None, }) } } impl<'a> Input<'a> { pub fn ordinary_file(path: impl AsRef) -> Self { Self::_ordinary_file(path.as_ref()) } fn _ordinary_file(path: &Path) -> Self { let kind = InputKind::OrdinaryFile(path.to_path_buf()); let metadata = InputMetadata { size: fs::metadata(path).map(|m| m.len()).ok(), ..InputMetadata::default() }; Input { description: kind.description(), metadata, kind, } } pub fn stdin() -> Self { let kind = InputKind::StdIn; Input { description: kind.description(), metadata: InputMetadata::default(), kind, } } pub fn from_reader(reader: Box) -> Self { let kind = InputKind::CustomReader(reader); Input { description: kind.description(), metadata: InputMetadata::default(), kind, } } pub fn is_stdin(&self) -> bool { matches!(self.kind, InputKind::StdIn) } pub fn with_name(self, provided_name: Option>) -> Self { self._with_name(provided_name.as_ref().map(|it| it.as_ref())) } fn _with_name(mut self, provided_name: Option<&Path>) -> Self { if let Some(name) = provided_name { self.description.name = name.to_string_lossy().to_string() } self.metadata.user_provided_name = provided_name.map(|n| n.to_owned()); self } pub fn description(&self) -> &InputDescription { &self.description } pub fn description_mut(&mut self) -> &mut InputDescription { &mut self.description } pub(crate) fn open( self, stdin: R, stdout_identifier: Option<&Identifier>, ) -> Result> { let description = self.description().clone(); match self.kind { InputKind::StdIn => { if let Some(stdout) = stdout_identifier { let input_identifier = Identifier::try_from(clircle::Stdio::Stdin) .map_err(|e| format!("Stdin: Error identifying file: {e}"))?; if stdout.surely_conflicts_with(&input_identifier) { return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into()); } } Ok(OpenedInput { kind: OpenedInputKind::StdIn, description, metadata: self.metadata, reader: InputReader::new(stdin), }) } InputKind::OrdinaryFile(path) => Ok(OpenedInput { kind: OpenedInputKind::OrdinaryFile(path.clone()), description, metadata: self.metadata, reader: { let mut file = File::open(&path) .map_err(|e| format!("'{}': {e}", path.to_string_lossy()))?; if file.metadata()?.is_dir() { return Err(format!("'{}' is a directory.", path.to_string_lossy()).into()); } if let Some(stdout) = stdout_identifier { let input_identifier = Identifier::try_from(file).map_err(|e| { format!("{}: Error identifying file: {e}", path.to_string_lossy()) })?; if stdout.surely_conflicts_with(&input_identifier) { return Err(format!( "IO circle detected. The input from '{}' is also an output. Aborting to avoid infinite loop.", path.to_string_lossy() ) .into()); } file = input_identifier.into_inner().expect("The file was lost in the clircle::Identifier, this should not have happened..."); } InputReader::new(BufReader::new(file)) }, }), InputKind::CustomReader(reader) => Ok(OpenedInput { description, kind: OpenedInputKind::CustomReader, metadata: self.metadata, reader: InputReader::new(BufReader::new(reader)), }), } } } pub(crate) struct InputReader<'a> { inner: Box, pub(crate) first_line: Vec, pub(crate) content_type: Option, pub(crate) unbuffered: bool, } impl<'a> InputReader<'a> { pub(crate) fn new(mut reader: R) -> InputReader<'a> { let mut first_line = vec![]; reader.read_until(b'\n', &mut first_line).ok(); let content_type = if first_line.is_empty() { None } else { Some(content_inspector::inspect(&first_line[..])) }; if content_type == Some(ContentType::UTF_16LE) { read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A).ok(); } else if content_type == Some(ContentType::UTF_16BE) { read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00).ok(); } InputReader { inner: Box::new(reader), first_line, content_type, unbuffered: false, } } pub(crate) fn read_line(&mut self, buf: &mut Vec) -> io::Result { if !self.first_line.is_empty() { buf.append(&mut self.first_line); return Ok(true); } if self.content_type == Some(ContentType::UTF_16LE) { return read_utf16_line(&mut self.inner, buf, 0x00, 0x0A); } if self.content_type == Some(ContentType::UTF_16BE) { return read_utf16_line(&mut self.inner, buf, 0x0A, 0x00); } if self.unbuffered { return self.read_line_unbuffered(buf); } let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?; Ok(res) } fn read_line_unbuffered(&mut self, buf: &mut Vec) -> io::Result { let available = self.inner.fill_buf()?; if available.is_empty() { return Ok(!buf.is_empty()); } if let Some(pos) = available.iter().position(|&b| b == b'\n') { buf.extend_from_slice(&available[..=pos]); self.inner.consume(pos + 1); } else { let len = available.len(); buf.extend_from_slice(available); self.inner.consume(len); } Ok(true) } } fn read_utf16_line( reader: &mut R, buf: &mut Vec, read_until_char: u8, preceded_by_char: u8, ) -> io::Result { loop { let mut temp = Vec::new(); let n = reader.read_until(read_until_char, &mut temp)?; if n == 0 { // EOF reached break; } buf.extend_from_slice(&temp); if buf.len() >= 2 && buf[buf.len() - 2] == preceded_by_char && buf[buf.len() - 1] == read_until_char { // end of line found break; } // end of line not found, keep going } Ok(!buf.is_empty()) } #[test] fn basic() { let content = b"#!/bin/bash\necho hello"; let mut reader = InputReader::new(&content[..]); assert_eq!(b"#!/bin/bash\n", &reader.first_line[..]); let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"#!/bin/bash\n", &buffer[..]); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"echo hello", &buffer[..]); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } #[test] fn utf16le() { let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00"; let mut reader = InputReader::new(&content[..]); assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &reader.first_line[..]); let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"\xFF\xFE\x73\x00\x0A\x00", &buffer[..]); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"\x64\x00", &buffer[..]); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } #[test] fn unbuffered_returns_partial_data() { use std::io::Cursor; let content = b"first line\npartial"; let mut reader = InputReader::new(Cursor::new(&content[..])); reader.unbuffered = true; // First call returns first_line (buffered during new()) let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"first line\n", &buffer[..]); // Subsequent calls use unbuffered reading buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"partial", &buffer[..]); // EOF buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } #[test] fn unbuffered_returns_complete_lines() { use std::io::Cursor; let content = b"line1\nline2\n"; let mut reader = InputReader::new(Cursor::new(&content[..])); reader.unbuffered = true; // First call returns first_line let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"line1\n", &buffer[..]); // Second call returns line2 (complete line with newline) buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"line2\n", &buffer[..]); // EOF buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } #[test] fn unbuffered_eof_handling() { use std::io::Cursor; let content = b"only line\n"; let mut reader = InputReader::new(Cursor::new(&content[..])); reader.unbuffered = true; // First call returns first_line let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!(b"only line\n", &buffer[..]); // EOF - empty buffer returns false buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } #[test] fn utf16le_issue3367() { let content = b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00\ \x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00\ \x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00"; let mut reader = InputReader::new(&content[..]); assert_eq!( b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00", &reader.first_line[..] ); let mut buffer = vec![]; let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!( b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00", &buffer[..] ); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!( b"\x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00", &buffer[..] ); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(res.unwrap()); assert_eq!( b"\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00", &buffer[..] ); buffer.clear(); let res = reader.read_line(&mut buffer); assert!(res.is_ok()); assert!(!res.unwrap()); assert!(buffer.is_empty()); } ================================================ FILE: src/less.rs ================================================ #![cfg(feature = "paging")] use std::ffi::OsStr; use std::process::Command; #[derive(Debug, PartialEq, Eq)] pub enum LessVersion { Less(usize), BusyBox, } pub fn retrieve_less_version(less_path: &dyn AsRef) -> Option { let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?; let cmd = Command::new(resolved_path).arg("--version").output().ok()?; if cmd.status.success() { parse_less_version(&cmd.stdout) } else { parse_less_version_busybox(&cmd.stderr) } } fn parse_less_version(output: &[u8]) -> Option { if !output.starts_with(b"less ") { return None; } let version = std::str::from_utf8(&output[5..]).ok()?; let end = version.find(|c: char| !c.is_ascii_digit())?; Some(LessVersion::Less(version[..end].parse::().ok()?)) } fn parse_less_version_busybox(output: &[u8]) -> Option { match std::str::from_utf8(output) { Ok(version) if version.contains("BusyBox ") => Some(LessVersion::BusyBox), _ => None, } } #[test] fn test_parse_less_version_487() { let output = b"less 487 (GNU regular expressions) Copyright (C) 1984-2016 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Homepage: http://www.greenwoodsoftware.com/less"; assert_eq!(Some(LessVersion::Less(487)), parse_less_version(output)); } #[test] fn test_parse_less_version_529() { let output = b"less 529 (Spencer V8 regular expressions) Copyright (C) 1984-2017 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Homepage: http://www.greenwoodsoftware.com/less"; assert_eq!(Some(LessVersion::Less(529)), parse_less_version(output)); } #[test] fn test_parse_less_version_551() { let output = b"less 551 (PCRE regular expressions) Copyright (C) 1984-2019 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Home page: http://www.greenwoodsoftware.com/less"; assert_eq!(Some(LessVersion::Less(551)), parse_less_version(output)); } #[test] fn test_parse_less_version_581_2() { let output = b"less 581.2 (PCRE2 regular expressions) Copyright (C) 1984-2021 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Home page: https://greenwoodsoftware.com/less"; assert_eq!(Some(LessVersion::Less(581)), parse_less_version(output)); } #[test] fn test_parse_less_version_wrong_program() { let output = b"more from util-linux 2.34"; assert_eq!(None, parse_less_version(output)); assert_eq!(None, parse_less_version_busybox(output)); } #[test] fn test_parse_less_version_busybox() { let output = b"pkg/less: unrecognized option '--version' BusyBox v1.35.0 (2022-04-21 10:38:11 EDT) multi-call binary. Usage: less [-EFIMmNSRh~] [FILE]... View FILE (or stdin) one screenful at a time -E Quit once the end of a file is reached -F Quit if entire file fits on first screen -I Ignore case in all searches -M,-m Display status line with line numbers and percentage through the file -N Prefix line number to each line -S Truncate long lines -R Remove color escape codes in input -~ Suppress ~s displayed past EOF"; assert_eq!( Some(LessVersion::BusyBox), parse_less_version_busybox(output) ); } #[test] fn test_parse_less_version_invalid_utf_8() { let output = b"\xff"; assert_eq!(None, parse_less_version(output)); assert_eq!(None, parse_less_version_busybox(output)); } ================================================ FILE: src/lessopen.rs ================================================ use std::convert::TryFrom; use std::env; use std::fs::File; use std::io::{BufRead, BufReader, Cursor, Read}; use std::path::PathBuf; use std::process::{ExitStatus, Stdio}; use clircle::{Clircle, Identifier}; use execute::{shell, Execute}; use crate::error::Result; use crate::{ bat_warning, input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind}, }; /// Preprocess files and/or stdin using $LESSOPEN and $LESSCLOSE pub(crate) struct LessOpenPreprocessor { lessopen: String, lessclose: Option, kind: LessOpenKind, /// Whether or not data piped via stdin is to be preprocessed preprocess_stdin: bool, } enum LessOpenKind { Piped, PipedIgnoreExitCode, TempFile, } impl LessOpenPreprocessor { /// Create a new instance of LessOpenPreprocessor /// Will return Ok if and only if $LESSOPEN is set and contains exactly one %s pub(crate) fn new() -> Result { let lessopen = env::var("LESSOPEN")?; // Ignore $LESSOPEN if it does not contains exactly one %s // Note that $LESSCLOSE has no such requirement if lessopen.match_indices("%s").count() != 1 { let error_msg = "LESSOPEN ignored: must contain exactly one %s"; bat_warning!("{error_msg}"); return Err(error_msg.into()); } // "||" means pipe directly to bat without making a temporary file // Also, if preprocessor output is empty and exit code is zero, use the empty output // Otherwise, if output is empty and exit code is nonzero, use original file contents let (kind, lessopen) = if lessopen.starts_with("||") { (LessOpenKind::Piped, lessopen.chars().skip(2).collect()) // "|" means pipe as above, but ignore exit code and always use preprocessor output even if empty } else if lessopen.starts_with('|') { ( LessOpenKind::PipedIgnoreExitCode, lessopen.chars().skip(1).collect(), ) // If neither appear, write output to a temporary file and read from that } else { (LessOpenKind::TempFile, lessopen) }; // "-" means that stdin is preprocessed along with files and may appear alongside "|" and "||" let (stdin, lessopen) = if lessopen.starts_with('-') { (true, lessopen.chars().skip(1).collect()) } else { (false, lessopen) }; Ok(Self { lessopen, lessclose: env::var("LESSCLOSE").ok(), kind, preprocess_stdin: stdin, }) } pub(crate) fn open<'a, R: BufRead + 'a>( &self, input: Input<'a>, mut stdin: R, stdout_identifier: Option<&Identifier>, ) -> Result> { let (lessopen_stdout, path_str, kind) = match input.kind { InputKind::OrdinaryFile(ref path) => { let path_str = match path.to_str() { Some(str) => str, None => return input.open(stdin, stdout_identifier), }; let mut lessopen_command = shell(self.lessopen.replacen("%s", path_str, 1)); lessopen_command.stdout(Stdio::piped()); let lessopen_output = match lessopen_command.execute_output() { Ok(output) => output, Err(_) => return input.open(stdin, stdout_identifier), }; if self.fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status) { return input.open(stdin, stdout_identifier); } ( lessopen_output.stdout, path_str.to_string(), OpenedInputKind::OrdinaryFile(path.to_path_buf()), ) } InputKind::StdIn => { if self.preprocess_stdin { if let Some(stdout) = stdout_identifier { let input_identifier = Identifier::try_from(clircle::Stdio::Stdin) .map_err(|e| format!("Stdin: Error identifying file: {e}"))?; if stdout.surely_conflicts_with(&input_identifier) { return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into()); } } // stdin isn't Clone or AsRef<[u8]>, so move it into a cloneable buffer // so the data can be used multiple times if necessary // NOTE: stdin will be empty from this point onwards let mut stdin_buffer = Vec::new(); stdin.read_to_end(&mut stdin_buffer)?; let mut lessopen_command = shell(self.lessopen.replacen("%s", "-", 1)); lessopen_command.stdout(Stdio::piped()); let lessopen_output = match lessopen_command.execute_input_output(&stdin_buffer) { Ok(output) => output, Err(_) => { return input.open(Cursor::new(stdin_buffer), stdout_identifier); } }; if self .fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status) { return input.open(Cursor::new(stdin_buffer), stdout_identifier); } ( lessopen_output.stdout, "-".to_string(), OpenedInputKind::StdIn, ) } else { return input.open(stdin, stdout_identifier); } } InputKind::CustomReader(_) => { return input.open(stdin, stdout_identifier); } }; Ok(OpenedInput { kind, reader: InputReader::new(BufReader::new( if matches!(self.kind, LessOpenKind::TempFile) { let lessopen_string = match String::from_utf8(lessopen_stdout) { Ok(string) => string, Err(_) => { return input.open(stdin, stdout_identifier); } }; // Remove newline at end of temporary file path returned by $LESSOPEN let stdout = match lessopen_string.strip_suffix("\n") { Some(stripped) => stripped.to_owned(), None => lessopen_string, }; let file = match File::open(PathBuf::from(&stdout)) { Ok(file) => file, Err(_) => { return input.open(stdin, stdout_identifier); } }; Preprocessed { kind: PreprocessedKind::TempFile(file), lessclose: self .lessclose .as_ref() .map(|s| s.replacen("%s", &path_str, 1).replacen("%s", &stdout, 1)), } } else { Preprocessed { kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout)), lessclose: self .lessclose .as_ref() .map(|s| s.replacen("%s", &path_str, 1).replacen("%s", "-", 1)), } }, )), metadata: input.metadata, description: input.description, }) } fn fall_back_to_original_file(&self, lessopen_stdout: &[u8], exit_code: ExitStatus) -> bool { lessopen_stdout.is_empty() && (!exit_code.success() || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode)) } #[cfg(test)] /// For testing purposes only /// Create an instance of LessOpenPreprocessor with specified valued for $LESSOPEN and $LESSCLOSE fn mock_new(lessopen: Option<&str>, lessclose: Option<&str>) -> Result { if let Some(command) = lessopen { env::set_var("LESSOPEN", command) } else { env::remove_var("LESSOPEN") } if let Some(command) = lessclose { env::set_var("LESSCLOSE", command) } else { env::remove_var("LESSCLOSE") } Self::new() } } enum PreprocessedKind { Piped(Cursor>), TempFile(File), } impl Read for PreprocessedKind { fn read(&mut self, buf: &mut [u8]) -> std::result::Result { match self { PreprocessedKind::Piped(data) => data.read(buf), PreprocessedKind::TempFile(data) => data.read(buf), } } } pub struct Preprocessed { kind: PreprocessedKind, lessclose: Option, } impl Read for Preprocessed { fn read(&mut self, buf: &mut [u8]) -> std::result::Result { self.kind.read(buf) } } impl Drop for Preprocessed { fn drop(&mut self) { if let Some(lessclose) = self.lessclose.clone() { let mut lessclose_command = shell(lessclose); let lessclose_output = match lessclose_command.execute_output() { Ok(output) => output, Err(_) => { bat_warning!("failed to run $LESSCLOSE to clean up temporary file"); return; } }; if lessclose_output.status.success() { bat_warning!("$LESSCLOSE exited with nonzero exit code",) }; } } } #[cfg(test)] mod tests { // All tests here are serial because they all involve reading and writing environment variables // Running them in parallel causes these tests and some others to randomly fail use serial_test::serial; use super::*; /// Reset environment variables after each test as a precaution fn reset_env_vars() { env::remove_var("LESSOPEN"); env::remove_var("LESSCLOSE"); } #[test] #[serial] fn test_just_lessopen() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(preprocessor.lessclose.is_none()); reset_env_vars(); Ok(()) } #[test] #[serial] fn test_just_lessclose() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(None, Some("lessclose.sh %s %s")); assert!(preprocessor.is_err()); reset_env_vars(); Ok(()) } #[test] #[serial] fn test_both_lessopen_and_lessclose() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("lessopen.sh %s"), Some("lessclose.sh %s %s"))?; assert_eq!(preprocessor.lessopen, "lessopen.sh %s"); assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh %s %s"); reset_env_vars(); Ok(()) } #[test] #[serial] fn test_lessopen_prefixes() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::TempFile)); assert!(!preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!( preprocessor.kind, LessOpenKind::PipedIgnoreExitCode )); assert!(!preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("||batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::Piped)); assert!(!preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("-batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::TempFile)); assert!(preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("|-batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!( preprocessor.kind, LessOpenKind::PipedIgnoreExitCode )); assert!(preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("||-batpipe %s"), None)?; assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::Piped)); assert!(preprocessor.preprocess_stdin); reset_env_vars(); Ok(()) } #[test] #[serial] fn replace_part_of_argument() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("|echo File:%s"), Some("echo File:%s Temp:%s"))?; assert_eq!(preprocessor.lessopen, "echo File:%s"); assert_eq!(preprocessor.lessclose.unwrap(), "echo File:%s Temp:%s"); reset_env_vars(); Ok(()) } } ================================================ FILE: src/lib.rs ================================================ //! `bat` is a library to print syntax highlighted content. //! //! The main struct of this crate is `PrettyPrinter` which can be used to //! configure and run the syntax highlighting. //! //! If you need more control, you can also use the structs in the submodules //! (start with `controller::Controller`), but note that the API of these //! internal modules is much more likely to change. Some or all of these //! modules might be removed in the future. //! //! "Hello world" example: //! ``` //! use bat::PrettyPrinter; //! //! PrettyPrinter::new() //! .input_from_bytes(b"Hello world!\n") //! .language("html") //! .print() //! .unwrap(); //! ``` #![deny(unsafe_code)] mod macros; pub mod assets; pub mod assets_metadata { pub use super::assets::assets_metadata::*; } pub mod config; pub mod controller; mod decorations; mod diff; pub mod error; pub mod input; mod less; #[cfg(feature = "lessopen")] mod lessopen; pub mod line_range; pub(crate) mod nonprintable_notation; pub mod output; #[cfg(feature = "paging")] mod pager; #[cfg(feature = "paging")] pub(crate) mod paging; mod preprocessor; mod pretty_printer; pub(crate) mod printer; pub mod style; pub(crate) mod syntax_mapping; mod terminal; pub mod theme; mod vscreen; pub(crate) mod wrapping; pub use nonprintable_notation::{BinaryBehavior, NonprintableNotation}; pub use preprocessor::StripAnsiMode; pub use pretty_printer::{Input, PrettyPrinter, Syntax}; pub use syntax_mapping::{MappingTarget, SyntaxMapping}; pub use wrapping::WrappingMode; #[cfg(feature = "paging")] pub use paging::PagingMode; ================================================ FILE: src/line_range.rs ================================================ use crate::error::*; use itertools::{Itertools, MinMaxResult}; #[derive(Debug, Copy, Clone)] pub struct LineRange { lower: RangeBound, upper: RangeBound, } /// Defines a boundary for a range #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub(crate) enum RangeBound { // An absolute line number marking the boundary of a range Absolute(usize), // A relative (implicitly negative) offset from the end of the file as a boundary OffsetFromEnd(usize), } impl Default for LineRange { fn default() -> LineRange { LineRange { lower: RangeBound::Absolute(usize::MIN), upper: RangeBound::Absolute(usize::MAX), } } } impl LineRange { pub fn new(from: usize, to: usize) -> Self { LineRange { lower: RangeBound::Absolute(from), upper: RangeBound::Absolute(to), } } pub fn from(range_raw: &str) -> Result { LineRange::parse_range(range_raw) } fn parse_range(range_raw: &str) -> Result { let mut new_range = LineRange::default(); let mut raw_range_iter = range_raw.bytes(); let first_byte = raw_range_iter.next().ok_or("Empty line range")?; if first_byte == b':' { if raw_range_iter.next() == Some(b'-') { // E.g. ':-3' let value = range_raw[2..].parse()?; new_range.upper = RangeBound::OffsetFromEnd(value); } else { let value = range_raw[1..].parse()?; new_range.upper = RangeBound::Absolute(value); } return Ok(new_range); } else if range_raw.bytes().last().ok_or("Empty line range")? == b':' { if first_byte == b'-' { // E.g. '-3:' let value = range_raw[1..range_raw.len() - 1].parse()?; new_range.lower = RangeBound::OffsetFromEnd(value); } else { let value = range_raw[..range_raw.len() - 1].parse()?; new_range.lower = RangeBound::Absolute(value); } return Ok(new_range); } let line_numbers: Vec<&str> = range_raw.split(':').collect(); match line_numbers.len() { 1 => { new_range.lower = RangeBound::Absolute(line_numbers[0].parse()?); new_range.upper = new_range.lower; Ok(new_range) } 2 => { let mut lower_absolute_bound: usize = line_numbers[0].parse()?; let first_byte = line_numbers[1].bytes().next(); let upper_absolute_bound = if first_byte == Some(b'+') { let more_lines = &line_numbers[1][1..] .parse() .map_err(|_| "Invalid character after +")?; lower_absolute_bound.saturating_add(*more_lines) } else if first_byte == Some(b'-') { // this will prevent values like "-+5" even though "+5" is valid integer if line_numbers[1][1..].bytes().next() == Some(b'+') { return Err("Invalid character after -".into()); } let prior_lines = &line_numbers[1][1..] .parse() .map_err(|_| "Invalid character after -")?; let prev_lower = lower_absolute_bound; lower_absolute_bound = lower_absolute_bound.saturating_sub(*prior_lines); prev_lower } else { line_numbers[1].parse()? }; new_range.lower = RangeBound::Absolute(lower_absolute_bound); new_range.upper = RangeBound::Absolute(upper_absolute_bound); Ok(new_range) } 3 => { // Handle context syntax: N::C or N:M:C if line_numbers[1].is_empty() { // Format: N::C - single line with context let line_number: usize = line_numbers[0].parse() .map_err(|_| "Invalid line number in N::C format")?; let context: usize = line_numbers[2].parse() .map_err(|_| "Invalid context number in N::C format")?; new_range.lower = RangeBound::Absolute(line_number.saturating_sub(context)); new_range.upper = RangeBound::Absolute(line_number.saturating_add(context)); } else { // Format: N:M:C - range with context let start_line: usize = line_numbers[0].parse() .map_err(|_| "Invalid start line number in N:M:C format")?; let end_line: usize = line_numbers[1].parse() .map_err(|_| "Invalid end line number in N:M:C format")?; let context: usize = line_numbers[2].parse() .map_err(|_| "Invalid context number in N:M:C format")?; new_range.lower = RangeBound::Absolute(start_line.saturating_sub(context)); new_range.upper = RangeBound::Absolute(end_line.saturating_add(context)); } Ok(new_range) } _ => Err( "Line range contained too many ':' characters. Expected format: 'N', 'N:M', 'N::C', or 'N:M:C'" .into(), ), } } /// Checks if a line number is inside the range. /// For ranges with relative offsets range bounds `max_buffered_line_number` is necessary /// to convert the offset to an absolute value. pub(crate) fn is_inside( &self, line: usize, max_buffered_line_number: MaxBufferedLineNumber, ) -> bool { match (self.lower, self.upper, max_buffered_line_number) { (RangeBound::Absolute(lower), RangeBound::Absolute(upper), _) => { lower <= line && line <= upper } ( RangeBound::Absolute(lower), RangeBound::OffsetFromEnd(offset), MaxBufferedLineNumber::Final(last_line_number), ) => lower <= line && line <= last_line_number.saturating_sub(offset), ( RangeBound::Absolute(lower), RangeBound::OffsetFromEnd(_), MaxBufferedLineNumber::Tentative(_), ) => { // We don't know the final line number yet, so the assumption is that the line is // still far enough away from the upper end of the range lower <= line } ( RangeBound::OffsetFromEnd(offset), RangeBound::Absolute(upper), MaxBufferedLineNumber::Final(last_line_number), ) => last_line_number.saturating_sub(offset) <= line && line <= upper, ( RangeBound::OffsetFromEnd(_), RangeBound::Absolute(_), MaxBufferedLineNumber::Tentative(_), ) => { // We don't know the final line number yet, so the assumption is that the line is // still too far away from the having reached the lower end of the range false } ( RangeBound::OffsetFromEnd(lower), RangeBound::OffsetFromEnd(upper), MaxBufferedLineNumber::Final(last_line_number), ) => { last_line_number.saturating_sub(lower) <= line && line <= last_line_number.saturating_sub(upper) } ( RangeBound::OffsetFromEnd(_), RangeBound::OffsetFromEnd(_), MaxBufferedLineNumber::Tentative(_), ) => { // We don't know the final line number yet, so the assumption is that we're still // too far away from the having reached the lower end of the range false } } } } #[test] fn test_parse_full() { let range = LineRange::from("40:50").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(40), range.lower); assert_eq!(RangeBound::Absolute(50), range.upper); } #[test] fn test_parse_partial_min() { let range = LineRange::from(":50").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(usize::MIN), range.lower); assert_eq!(RangeBound::Absolute(50), range.upper); } #[test] fn test_parse_partial_relative_negative_from_back() { let range = LineRange::from(":-5").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(usize::MIN), range.lower); assert_eq!(RangeBound::OffsetFromEnd(5), range.upper); } #[test] fn test_parse_relative_negative_from_back_partial() { let range = LineRange::from("-5:").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::OffsetFromEnd(5), range.lower); assert_eq!(RangeBound::Absolute(usize::MAX), range.upper); } #[test] fn test_parse_partial_max() { let range = LineRange::from("40:").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(40), range.lower); assert_eq!(RangeBound::Absolute(usize::MAX), range.upper); } #[test] fn test_parse_single() { let range = LineRange::from("40").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(40), range.lower); assert_eq!(RangeBound::Absolute(40), range.upper); } #[test] fn test_parse_fail() { // Test 4+ colon parts should still fail let range = LineRange::from("40:50:80:90"); assert!(range.is_err()); // Test invalid formats that should still fail let range = LineRange::from("-2:5"); assert!(range.is_err()); let range = LineRange::from(":40:"); assert!(range.is_err()); // Test completely malformed input let range = LineRange::from("abc:def"); assert!(range.is_err()); } #[test] fn test_parse_plus() { let range = LineRange::from("40:+10").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(40), range.lower); assert_eq!(RangeBound::Absolute(50), range.upper); } #[test] fn test_parse_plus_overflow() { let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(usize::MAX), range.lower); assert_eq!(RangeBound::Absolute(usize::MAX), range.upper); } #[test] fn test_parse_plus_fail() { let range = LineRange::from("40:+z"); assert!(range.is_err()); let range = LineRange::from("40:+-10"); assert!(range.is_err()); let range = LineRange::from("40:+"); assert!(range.is_err()); } #[test] fn test_parse_minus_success() { let range = LineRange::from("40:-10").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(30), range.lower); assert_eq!(RangeBound::Absolute(40), range.upper); } #[test] fn test_parse_minus_edge_cases_success() { let range = LineRange::from("5:-4").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(1), range.lower); assert_eq!(RangeBound::Absolute(5), range.upper); let range = LineRange::from("5:-5").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(0), range.lower); assert_eq!(RangeBound::Absolute(5), range.upper); let range = LineRange::from("5:-100").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(0), range.lower); assert_eq!(RangeBound::Absolute(5), range.upper); } #[test] fn test_parse_minus_fail() { let range = LineRange::from("40:-z"); assert!(range.is_err()); let range = LineRange::from("40:-+10"); assert!(range.is_err()); let range = LineRange::from("40:-"); assert!(range.is_err()); } #[test] fn test_parse_context_single_line() { let range = LineRange::from("35::5").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(30), range.lower); assert_eq!(RangeBound::Absolute(40), range.upper); } #[test] fn test_parse_context_range() { let range = LineRange::from("30:40:2").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(28), range.lower); assert_eq!(RangeBound::Absolute(42), range.upper); // Test the case that used to fail but should now work let range = LineRange::from("40:50:80").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(0), range.lower); // 40 - 80 = 0 (saturated) assert_eq!(RangeBound::Absolute(130), range.upper); // 50 + 80 = 130 } #[test] fn test_parse_context_edge_cases() { // Test with small line numbers that would underflow let range = LineRange::from("5::10").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(0), range.lower); assert_eq!(RangeBound::Absolute(15), range.upper); // Test with zero context let range = LineRange::from("50::0").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(50), range.lower); assert_eq!(RangeBound::Absolute(50), range.upper); // Test range with zero context let range = LineRange::from("30:40:0").expect("Shouldn't fail on test!"); assert_eq!(RangeBound::Absolute(30), range.lower); assert_eq!(RangeBound::Absolute(40), range.upper); } #[test] fn test_parse_context_fail() { let range = LineRange::from("40::z"); assert!(range.is_err()); let range = LineRange::from("::5"); assert!(range.is_err()); let range = LineRange::from("40::"); assert!(range.is_err()); let range = LineRange::from("30:40:z"); assert!(range.is_err()); let range = LineRange::from("30::40:5"); assert!(range.is_err()); } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RangeCheckResult { // Within one of the given ranges InRange, // Before the first range or within two ranges BeforeOrBetweenRanges, // Line number is outside of all ranges and larger than the last range. AfterLastRange, } /// Represents the maximum line number in the buffer when reading a file. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub(crate) enum MaxBufferedLineNumber { // The currently known maximum line number, may not be the final line number Tentative(usize), // The final line number, when EOF has been reached Final(usize), } #[derive(Debug, Clone)] pub struct LineRanges { ranges: Vec, // The largest absolute upper line number of all ranges largest_absolute_upper_bound: usize, // The smallest relative offset from the end of all ranges smallest_offset_from_end: usize, // The largest relative offset from the end of all ranges largest_offset_from_end: usize, } impl LineRanges { pub fn none() -> LineRanges { LineRanges::from(vec![]) } pub fn all() -> LineRanges { LineRanges::from(vec![LineRange::default()]) } pub fn from(ranges: Vec) -> LineRanges { let largest_absolute_upper_bound = ranges .iter() .filter_map(|r| match r.upper { RangeBound::Absolute(upper) => Some(upper), _ => None, }) .max() .unwrap_or(usize::MAX); let offsets_min_max = ranges .iter() .flat_map(|r| [r.lower, r.upper]) .filter_map(|r| match r { RangeBound::OffsetFromEnd(offset) => Some(offset), _ => None, }) .minmax(); let (smallest_offset_from_end, largest_offset_from_end) = match offsets_min_max { MinMaxResult::NoElements => (usize::MIN, usize::MIN), MinMaxResult::OneElement(offset) => (offset, offset), MinMaxResult::MinMax(min, max) => (min, max), }; LineRanges { ranges, largest_absolute_upper_bound, smallest_offset_from_end, largest_offset_from_end, } } pub(crate) fn check( &self, line: usize, max_buffered_line_number: MaxBufferedLineNumber, ) -> RangeCheckResult { if self .ranges .iter() .any(|r| r.is_inside(line, max_buffered_line_number)) { RangeCheckResult::InRange } else if matches!(max_buffered_line_number, MaxBufferedLineNumber::Final(final_line_number) if line > final_line_number.saturating_sub(self.smallest_offset_from_end)) { RangeCheckResult::AfterLastRange } else if line < self.largest_absolute_upper_bound { RangeCheckResult::BeforeOrBetweenRanges } else { RangeCheckResult::AfterLastRange } } pub(crate) fn largest_offset_from_end(&self) -> usize { self.largest_offset_from_end } } impl Default for LineRanges { fn default() -> Self { Self::all() } } #[derive(Debug, Clone)] pub struct HighlightedLineRanges(pub LineRanges); impl Default for HighlightedLineRanges { fn default() -> Self { HighlightedLineRanges(LineRanges::none()) } } #[cfg(test)] fn ranges(rs: &[&str]) -> LineRanges { LineRanges::from(rs.iter().map(|r| LineRange::from(r).unwrap()).collect()) } #[test] fn test_ranges_simple() { let ranges = ranges(&["3:8"]); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2, MaxBufferedLineNumber::Tentative(2)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(5)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(9, MaxBufferedLineNumber::Tentative(9)) ); } #[test] fn test_ranges_advanced() { let ranges = ranges(&["3:8", "11:20", "25:30"]); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(2, MaxBufferedLineNumber::Tentative(2)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(5)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(9, MaxBufferedLineNumber::Tentative(9)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(11, MaxBufferedLineNumber::Tentative(11)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(22, MaxBufferedLineNumber::Tentative(22)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(28, MaxBufferedLineNumber::Tentative(28)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(31, MaxBufferedLineNumber::Tentative(31)) ); } #[test] fn test_ranges_open_low() { let ranges = ranges(&["3:8", ":5"]); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Tentative(3)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(7, MaxBufferedLineNumber::Tentative(7)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(9, MaxBufferedLineNumber::Tentative(9)) ); } #[test] fn test_ranges_open_high() { let ranges = ranges(&["3:", "2:5"]); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(2, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(9, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(10, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Tentative(3)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(5)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(9, MaxBufferedLineNumber::Tentative(9)) ); } #[test] fn test_ranges_open_up_to_3_from_end() { let ranges = ranges(&[":-3"]); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Tentative(3)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(8)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Final(6)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(2, MaxBufferedLineNumber::Final(6)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Final(6)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(4, MaxBufferedLineNumber::Final(6)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(5, MaxBufferedLineNumber::Final(6)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(6, MaxBufferedLineNumber::Final(6)) ); } #[test] fn test_ranges_multiple_negative_from_back() { let ranges = ranges(&[":-3", ":-9"]); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Tentative(3)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(14)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Final(16)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(7, MaxBufferedLineNumber::Final(16)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(13, MaxBufferedLineNumber::Final(16)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(14, MaxBufferedLineNumber::Final(16)) ); assert_eq!( RangeCheckResult::AfterLastRange, ranges.check(16, MaxBufferedLineNumber::Final(16)) ); } #[test] fn test_ranges_3_from_back_up_to_end() { let ranges = ranges(&["-3:"]); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(3, MaxBufferedLineNumber::Tentative(3)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(5, MaxBufferedLineNumber::Tentative(8)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(1, MaxBufferedLineNumber::Final(5)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(2, MaxBufferedLineNumber::Final(5)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(3, MaxBufferedLineNumber::Final(5)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(4, MaxBufferedLineNumber::Final(5)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Final(5)) ); } #[test] fn test_ranges_multiple_negative_offsets_to_end() { let ranges = ranges(&["-3:", "-12:"]); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(5, MaxBufferedLineNumber::Tentative(8)) ); assert_eq!( RangeCheckResult::BeforeOrBetweenRanges, ranges.check(5, MaxBufferedLineNumber::Tentative(17)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(8, MaxBufferedLineNumber::Final(20)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(9, MaxBufferedLineNumber::Final(20)) ); } #[test] fn test_ranges_absolute_bound_and_offset() { let ranges = ranges(&["5:", ":-2"]); assert_eq!( RangeCheckResult::InRange, ranges.check(4, MaxBufferedLineNumber::Tentative(6)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(5, MaxBufferedLineNumber::Tentative(7)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(8, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(9, MaxBufferedLineNumber::Final(10)) ); assert_eq!( RangeCheckResult::InRange, ranges.check(10, MaxBufferedLineNumber::Final(10)) ); } #[test] fn test_ranges_all() { let ranges = LineRanges::all(); assert_eq!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); } #[test] fn test_ranges_none() { let ranges = LineRanges::none(); assert_ne!( RangeCheckResult::InRange, ranges.check(1, MaxBufferedLineNumber::Tentative(1)) ); } ================================================ FILE: src/macros.rs ================================================ #[macro_export] macro_rules! bat_warning { ($($arg:tt)*) => ({ use nu_ansi_term::Color::Yellow; eprintln!("{}: {}", Yellow.paint("[bat warning]"), format!($($arg)*)); }) } ================================================ FILE: src/nonprintable_notation.rs ================================================ /// How to print non-printable characters with /// [crate::config::Config::show_nonprintable] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub enum NonprintableNotation { /// Use caret notation (^G, ^J, ^@, ..) Caret, /// Use unicode notation (␇, ␊, ␀, ..) #[default] Unicode, } /// How to treat binary content #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub enum BinaryBehavior { /// Do not print any binary content #[default] NoPrinting, /// Treat binary content as normal text AsText, } ================================================ FILE: src/output.rs ================================================ use std::fmt; use std::io; #[cfg(feature = "paging")] use std::process::Child; #[cfg(feature = "paging")] use std::thread::{spawn, JoinHandle}; use crate::error::*; #[cfg(feature = "paging")] use crate::less::{retrieve_less_version, LessVersion}; #[cfg(feature = "paging")] use crate::paging::PagingMode; #[cfg(feature = "paging")] use crate::wrapping::WrappingMode; #[cfg(feature = "paging")] pub struct BuiltinPager { pager: minus::Pager, handle: Option>>, } #[cfg(feature = "paging")] impl BuiltinPager { fn new() -> Self { let pager = minus::Pager::new(); let handle = { let pager = pager.clone(); Some(spawn(move || { minus::dynamic_paging(pager).map_err(Error::from) })) }; Self { pager, handle } } } #[cfg(feature = "paging")] impl std::fmt::Debug for BuiltinPager { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("BuiltinPager") //.field("pager", &self.pager) /// minus::Pager doesn't implement fmt::Debug .field("handle", &self.handle) .finish() } } #[cfg(feature = "paging")] #[derive(Debug, PartialEq)] enum SingleScreenAction { Quit, Nothing, } #[derive(Debug)] pub enum OutputType { #[cfg(feature = "paging")] Pager(Child), #[cfg(feature = "paging")] BuiltinPager(BuiltinPager), Stdout(io::Stdout), } impl OutputType { #[cfg(feature = "paging")] pub fn from_mode( paging_mode: PagingMode, wrapping_mode: WrappingMode, pager: Option<&str>, ) -> Result { use self::PagingMode::*; Ok(match paging_mode { Always => OutputType::try_pager(SingleScreenAction::Nothing, wrapping_mode, pager)?, QuitIfOneScreen => { OutputType::try_pager(SingleScreenAction::Quit, wrapping_mode, pager)? } _ => OutputType::stdout(), }) } /// Try to launch the pager. Fall back to stdout in case of errors. #[cfg(feature = "paging")] fn try_pager( single_screen_action: SingleScreenAction, wrapping_mode: WrappingMode, pager_from_config: Option<&str>, ) -> Result { use crate::pager::{self, PagerKind, PagerSource}; use std::process::{Command, Stdio}; let pager_opt = pager::get_pager(pager_from_config).map_err(|_| "Could not parse pager command.")?; let pager = match pager_opt { Some(pager) => pager, None => return Ok(OutputType::stdout()), }; if pager.kind == PagerKind::Bat { return Err(Error::InvalidPagerValueBat); } if pager.kind == PagerKind::Builtin { return Ok(OutputType::BuiltinPager(BuiltinPager::new())); } let resolved_path = match grep_cli::resolve_binary(&pager.bin) { Ok(path) => path, Err(_) => { crate::bat_warning!( "Pager '{}' not found, outputting to stdout instead", pager.bin ); return Ok(OutputType::stdout()); } }; let mut p = Command::new(resolved_path); let args = pager.args; if pager.kind == PagerKind::Less { // less needs to be called with the '-R' option in order to properly interpret the // ANSI color sequences printed by bat. If someone has set PAGER="less -F", we // therefore need to overwrite the arguments and add '-R'. // // We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER // or bats '--pager' command line option. let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager; if args.is_empty() || replace_arguments_to_less { p.arg("-R"); // Short version of --RAW-CONTROL-CHARS for maximum compatibility if single_screen_action == SingleScreenAction::Quit { p.arg("-F"); // Short version of --quit-if-one-screen for compatibility } if wrapping_mode == WrappingMode::NoWrapping(true) { p.arg("-S"); // Short version of --chop-long-lines for compatibility } let less_version = retrieve_less_version(&pager.bin); // Ensures that 'less' quits together with 'bat' // The BusyBox version of less does not support -K if less_version != Some(LessVersion::BusyBox) { p.arg("-K"); // Short version of '--quit-on-intr' } // Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older // versions of 'less'. Unfortunately, it also breaks mouse-wheel support. // // See: http://www.greenwoodsoftware.com/less/news.530.html // // For newer versions (530 or 558 on Windows), we omit '--no-init' as it // is not needed anymore. if single_screen_action == SingleScreenAction::Quit { match less_version { None => { p.arg("--no-init"); } Some(LessVersion::Less(version)) if (version < 530 || (cfg!(windows) && version < 558)) => { p.arg("--no-init"); } _ => {} } } } else { p.args(args); } p.env("LESSCHARSET", "UTF-8"); #[cfg(feature = "lessopen")] // Ensures that 'less' does not preprocess input again if '$LESSOPEN' is set. p.arg("--no-lessopen"); } else { p.args(args); }; Ok(p.stdin(Stdio::piped()) .spawn() .map(OutputType::Pager) .unwrap_or_else(|_| { crate::bat_warning!( "Pager '{}' not found, outputting to stdout instead", &pager.bin ); OutputType::stdout() })) } pub(crate) fn stdout() -> Self { OutputType::Stdout(io::stdout()) } #[cfg(feature = "paging")] pub(crate) fn is_pager(&self) -> bool { matches!(self, OutputType::Pager(_) | OutputType::BuiltinPager(_)) } #[cfg(not(feature = "paging"))] pub(crate) fn is_pager(&self) -> bool { false } pub fn handle<'a>(&'a mut self) -> Result> { Ok(match *self { #[cfg(feature = "paging")] OutputType::Pager(ref mut command) => OutputHandle::IoWrite( command .stdin .as_mut() .ok_or("Could not open stdin for pager")?, ), #[cfg(feature = "paging")] OutputType::BuiltinPager(ref mut pager) => OutputHandle::FmtWrite(&mut pager.pager), OutputType::Stdout(ref mut handle) => OutputHandle::IoWrite(handle), }) } } #[cfg(feature = "paging")] impl Drop for OutputType { fn drop(&mut self) { match *self { OutputType::Pager(ref mut command) => { let _ = command.wait(); } OutputType::BuiltinPager(ref mut pager) => { if let Some(handle) = pager.handle.take() { let _ = handle.join(); } } OutputType::Stdout(_) => (), } } } pub enum OutputHandle<'a> { IoWrite(&'a mut dyn io::Write), FmtWrite(&'a mut dyn fmt::Write), } impl OutputHandle<'_> { pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> { match self { Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into), Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into), } } pub fn flush(&mut self) -> Result<()> { match self { Self::IoWrite(handle) => handle.flush().map_err(Into::into), Self::FmtWrite(_) => Ok(()), } } } ================================================ FILE: src/pager.rs ================================================ use shell_words::ParseError; use std::env; /// If we use a pager, this enum tells us from where we were told to use it. #[derive(Debug, PartialEq)] pub(crate) enum PagerSource { /// From --config Config, /// From the env var BAT_PAGER EnvVarBatPager, /// From the env var PAGER EnvVarPager, /// No pager was specified, default is used Default, } /// We know about some pagers, for example 'less'. This is a list of all pagers we know about #[derive(Debug, PartialEq)] pub(crate) enum PagerKind { /// bat Bat, /// less Less, /// more More, /// most Most, /// builtin Builtin, /// A pager we don't know about Unknown, } impl PagerKind { fn from_bin(bin: &str) -> PagerKind { use std::path::Path; if bin == "builtin" { return PagerKind::Builtin; } // Set to `less` by default on most Linux distros. let pager_bin = Path::new(bin).file_stem(); // The name of the current running binary. Normally `bat` but sometimes // `batcat` for compatibility reasons. let current_bin = env::args_os().next(); // Check if the current running binary is set to be our pager. let is_current_bin_pager = current_bin .map(|s| Path::new(&s).file_stem() == pager_bin) .unwrap_or(false); match pager_bin.map(|s| s.to_string_lossy()).as_deref() { Some("less") => PagerKind::Less, Some("more") => PagerKind::More, Some("most") => PagerKind::Most, _ if is_current_bin_pager => PagerKind::Bat, _ => PagerKind::Unknown, } } } /// A pager such as 'less', and from where we got it. #[derive(Debug)] pub(crate) struct Pager { /// The pager binary pub bin: String, /// The pager binary arguments (that we might tweak) pub args: Vec, /// What pager this is pub kind: PagerKind, /// From where this pager comes pub source: PagerSource, } impl Pager { fn new(bin: &str, args: &[String], kind: PagerKind, source: PagerSource) -> Pager { Pager { bin: String::from(bin), args: args.to_vec(), kind, source, } } } /// Returns what pager to use, after looking at both config and environment variables. pub(crate) fn get_pager(config_pager: Option<&str>) -> Result, ParseError> { let bat_pager = env::var("BAT_PAGER"); let pager = env::var("PAGER"); let (cmd, source) = match (config_pager, &bat_pager, &pager) { (Some(config_pager), _, _) => (config_pager, PagerSource::Config), (_, Ok(bat_pager), _) => (bat_pager.as_str(), PagerSource::EnvVarBatPager), (_, _, Ok(pager)) => (pager.as_str(), PagerSource::EnvVarPager), _ => ("less", PagerSource::Default), }; let parts = shell_words::split(cmd)?; match parts.split_first() { Some((bin, args)) => { let kind = PagerKind::from_bin(bin); let use_less_instead = if source == PagerSource::EnvVarPager { // 'more' and 'most' do not supports colors; automatically use // 'less' instead if the problematic pager came from the // generic PAGER env var. // If PAGER=bat, silently use 'less' instead to prevent // recursion. // Never silently use 'less' if BAT_PAGER or --pager has been // specified. matches!(kind, PagerKind::More | PagerKind::Most | PagerKind::Bat) } else { false }; Ok(Some(if use_less_instead { let no_args = vec![]; Pager::new("less", &no_args, PagerKind::Less, PagerSource::EnvVarPager) } else { Pager::new(bin, args, kind, source) })) } None => Ok(None), } } ================================================ FILE: src/paging.rs ================================================ #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum PagingMode { Always, QuitIfOneScreen, #[default] Never, } ================================================ FILE: src/preprocessor.rs ================================================ use std::fmt::Write; use crate::{ nonprintable_notation::NonprintableNotation, vscreen::{EscapeSequenceOffsets, EscapeSequenceOffsetsIterator}, }; /// Expand tabs like an ANSI-enabled expand(1). pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String { let mut buffer = String::with_capacity(line.len() * 2); for seq in EscapeSequenceOffsetsIterator::new(line) { match seq { EscapeSequenceOffsets::Text { .. } => { let mut text = &line[seq.index_of_start()..seq.index_past_end()]; 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); } _ => { // Copy the ANSI escape sequence. buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()]) } } } buffer } fn try_parse_utf8_char(input: &[u8]) -> Option<(char, usize)> { let str_from_utf8 = |seq| std::str::from_utf8(seq).ok(); let decoded = input .get(0..1) .and_then(str_from_utf8) .map(|c| (c, 1)) .or_else(|| input.get(0..2).and_then(str_from_utf8).map(|c| (c, 2))) .or_else(|| input.get(0..3).and_then(str_from_utf8).map(|c| (c, 3))) .or_else(|| input.get(0..4).and_then(str_from_utf8).map(|c| (c, 4))); decoded.map(|(seq, n)| (seq.chars().next().unwrap(), n)) } pub fn replace_nonprintable( input: &[u8], tab_width: usize, nonprintable_notation: NonprintableNotation, ) -> String { let mut output = String::new(); let tab_width = if tab_width == 0 { 4 } else { tab_width }; let mut idx = 0; let mut line_idx = 0; let len = input.len(); while idx < len { if let Some((chr, skip_ahead)) = try_parse_utf8_char(&input[idx..]) { idx += skip_ahead; line_idx += 1; match chr { // space ' ' => output.push('·'), // tab '\t' => { let tab_stop = tab_width - ((line_idx - 1) % tab_width); line_idx = 0; if tab_stop == 1 { output.push('↹'); } else { output.push('├'); output.push_str(&"─".repeat(tab_stop - 2)); output.push('┤'); } } // line feed '\x0A' => { output.push_str(match nonprintable_notation { NonprintableNotation::Caret => "^J\x0A", NonprintableNotation::Unicode => "␊\x0A", }); line_idx = 0; } // ASCII control characters '\x00'..='\x1F' => { let c = u32::from(chr); match nonprintable_notation { NonprintableNotation::Caret => { let caret_character = char::from_u32(0x40 + c).unwrap(); write!(output, "^{caret_character}").ok(); } NonprintableNotation::Unicode => { let replacement_symbol = char::from_u32(0x2400 + c).unwrap(); output.push(replacement_symbol) } } } // delete '\x7F' => match nonprintable_notation { NonprintableNotation::Caret => output.push_str("^?"), NonprintableNotation::Unicode => output.push('\u{2421}'), }, // printable ASCII c if c.is_ascii_alphanumeric() || c.is_ascii_punctuation() || c.is_ascii_graphic() => { output.push(c) } // everything else c => output.push_str(&c.escape_unicode().collect::()), } } else { write!(output, "\\x{:02X}", input[idx]).ok(); idx += 1; } } output } /// Strips ANSI escape sequences from the input. pub fn strip_ansi(line: &str) -> String { let mut buffer = String::with_capacity(line.len()); for seq in EscapeSequenceOffsetsIterator::new(line) { if let EscapeSequenceOffsets::Text { .. } = seq { buffer.push_str(&line[seq.index_of_start()..seq.index_past_end()]); } } buffer } /// Strips overstrike sequences (backspace formatting) from input. /// /// Overstrike formatting is used by man pages and some help output: /// - Bold: `X\x08X` (character, backspace, same character) /// - Underline: `_\x08X` (underscore, backspace, character) /// /// This function removes these sequences, keeping only the visible character. /// `first_backspace` is the position of the first backspace in the line. pub fn strip_overstrike(line: &str, first_backspace: usize) -> String { let mut output = String::with_capacity(line.len()); output.push_str(&line[..first_backspace]); output.pop(); let mut remaining = &line[first_backspace + 1..]; loop { if let Some(pos) = remaining.find('\x08') { output.push_str(&remaining[..pos]); output.pop(); remaining = &remaining[pos + 1..]; } else { output.push_str(remaining); break; } } output } #[derive(Debug, PartialEq, Clone, Copy, Default)] pub enum StripAnsiMode { #[default] Never, Always, Auto, } #[test] fn test_try_parse_utf8_char() { assert_eq!(try_parse_utf8_char(&[0x20]), Some((' ', 1))); assert_eq!(try_parse_utf8_char(&[0x20, 0x20]), Some((' ', 1))); assert_eq!(try_parse_utf8_char(&[0x20, 0xef]), Some((' ', 1))); assert_eq!(try_parse_utf8_char(&[0x00]), Some(('\x00', 1))); assert_eq!(try_parse_utf8_char(&[0x1b]), Some(('\x1b', 1))); assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4]), Some(('ä', 2))); assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4, 0xef]), Some(('ä', 2))); assert_eq!(try_parse_utf8_char(&[0xc3, 0xa4, 0x20]), Some(('ä', 2))); assert_eq!(try_parse_utf8_char(&[0xe2, 0x82, 0xac]), Some(('€', 3))); assert_eq!( try_parse_utf8_char(&[0xe2, 0x82, 0xac, 0xef]), Some(('€', 3)) ); assert_eq!( try_parse_utf8_char(&[0xe2, 0x82, 0xac, 0x20]), Some(('€', 3)) ); assert_eq!(try_parse_utf8_char(&[0xe2, 0x88, 0xb0]), Some(('∰', 3))); assert_eq!( try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82]), Some(('🌂', 4)) ); assert_eq!( try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82, 0xef]), Some(('🌂', 4)) ); assert_eq!( try_parse_utf8_char(&[0xf0, 0x9f, 0x8c, 0x82, 0x20]), Some(('🌂', 4)) ); assert_eq!(try_parse_utf8_char(&[]), None); assert_eq!(try_parse_utf8_char(&[0xef]), None); assert_eq!(try_parse_utf8_char(&[0xef, 0x20]), None); assert_eq!(try_parse_utf8_char(&[0xf0, 0xf0]), None); } #[test] fn test_strip_ansi() { // The sequence detection is covered by the tests in the vscreen module. assert_eq!(strip_ansi("no ansi"), "no ansi"); assert_eq!(strip_ansi("\x1B[33mone"), "one"); assert_eq!( strip_ansi("\x1B]1\x07multiple\x1B[J sequences"), "multiple sequences" ); } #[test] fn test_strip_overstrike() { // Bold: X\x08X (same char repeated) assert_eq!(strip_overstrike("H\x08Hello", 1), "Hello"); // Underline: _\x08X (underscore before char) assert_eq!(strip_overstrike("_\x08Hello", 1), "Hello"); // Multiple overstrike sequences assert_eq!(strip_overstrike("B\x08Bo\x08ol\x08ld\x08d", 1), "Bold"); // Backspace at start of line (nothing to pop) assert_eq!(strip_overstrike("\x08Hello", 0), "Hello"); // Multiple consecutive backspaces assert_eq!(strip_overstrike("ABC\x08\x08\x08XYZ", 3), "XYZ"); // Unicode with overstrike assert_eq!(strip_overstrike("ä\x08äöü", 2), "äöü"); } ================================================ FILE: src/pretty_printer.rs ================================================ use std::io::Read; use std::path::Path; use console::Term; use crate::{ assets::HighlightingAssets, config::{Config, VisibleLines}, controller::Controller, error::Result, input, line_range::{HighlightedLineRanges, LineRange, LineRanges}, output::OutputHandle, style::StyleComponent, StripAnsiMode, SyntaxMapping, WrappingMode, }; #[cfg(feature = "paging")] use crate::paging::PagingMode; #[derive(Default)] struct ActiveStyleComponents { header_filename: bool, #[cfg(feature = "git")] vcs_modification_markers: bool, grid: bool, rule: bool, line_numbers: bool, snip: bool, } #[non_exhaustive] pub struct Syntax { pub name: String, pub file_extensions: Vec, } pub struct PrettyPrinter<'a> { inputs: Vec>, config: Config<'a>, assets: HighlightingAssets, highlighted_lines: Vec, term_width: Option, active_style_components: ActiveStyleComponents, } impl<'a> PrettyPrinter<'a> { pub fn new() -> Self { let config = Config { colored_output: true, true_color: true, ..Default::default() }; PrettyPrinter { inputs: vec![], config, assets: HighlightingAssets::from_binary(), highlighted_lines: vec![], term_width: None, active_style_components: ActiveStyleComponents::default(), } } /// Add an input which should be pretty-printed pub fn input(&mut self, input: Input<'a>) -> &mut Self { self.inputs.push(input); self } /// Adds multiple inputs which should be pretty-printed pub fn inputs(&mut self, inputs: impl IntoIterator>) -> &mut Self { for input in inputs { self.inputs.push(input); } self } /// Add a file which should be pretty-printed pub fn input_file(&mut self, path: impl AsRef) -> &mut Self { self.input(Input::from_file(path).kind("File")) } /// Add multiple files which should be pretty-printed pub fn input_files(&mut self, paths: I) -> &mut Self where I: IntoIterator, P: AsRef, { self.inputs(paths.into_iter().map(Input::from_file)) } /// Add STDIN as an input pub fn input_stdin(&mut self) -> &mut Self { self.inputs.push(Input::from_stdin()); self } /// Add a byte string as an input pub fn input_from_bytes(&mut self, content: &'a [u8]) -> &mut Self { self.input_from_reader(content) } /// Add a custom reader as an input pub fn input_from_reader(&mut self, reader: R) -> &mut Self { self.inputs.push(Input::from_reader(reader)); self } /// Specify the syntax file which should be used (default: auto-detect) pub fn language(&mut self, language: &'a str) -> &mut Self { self.config.language = Some(language); self } /// The character width of the terminal (default: autodetect) pub fn term_width(&mut self, width: usize) -> &mut Self { self.term_width = Some(width); self } /// The width of tab characters (default: None - do not turn tabs to spaces) pub fn tab_width(&mut self, tab_width: Option) -> &mut Self { self.config.tab_width = tab_width.unwrap_or(0); self } /// Whether or not the output should be colorized (default: true) pub fn colored_output(&mut self, yes: bool) -> &mut Self { self.config.colored_output = yes; self } /// Whether or not to output 24bit colors (default: true) pub fn true_color(&mut self, yes: bool) -> &mut Self { self.config.true_color = yes; self } /// Whether to show a header with the file name pub fn header(&mut self, yes: bool) -> &mut Self { self.active_style_components.header_filename = yes; self } /// Whether to show line numbers pub fn line_numbers(&mut self, yes: bool) -> &mut Self { self.active_style_components.line_numbers = yes; self } /// Whether to paint a grid, separating line numbers, git changes and the code pub fn grid(&mut self, yes: bool) -> &mut Self { self.active_style_components.grid = yes; self } /// Whether to paint a horizontal rule to delimit files pub fn rule(&mut self, yes: bool) -> &mut Self { self.active_style_components.rule = yes; self } /// Whether to show modification markers for VCS changes. This has no effect if /// the `git` feature is not activated. #[cfg(feature = "git")] pub fn vcs_modification_markers(&mut self, yes: bool) -> &mut Self { self.active_style_components.vcs_modification_markers = yes; self } /// Whether to print binary content or nonprintable characters (default: no) pub fn show_nonprintable(&mut self, yes: bool) -> &mut Self { self.config.show_nonprintable = yes; self } /// Whether to show "snip" markers between visible line ranges (default: no) pub fn snip(&mut self, yes: bool) -> &mut Self { self.active_style_components.snip = yes; self } /// Whether to remove ANSI escape sequences from the input (default: never) /// /// If `Auto` is used, escape sequences will only be removed when the input /// is not plain text. pub fn strip_ansi(&mut self, mode: StripAnsiMode) -> &mut Self { self.config.strip_ansi = mode; self } /// Text wrapping mode (default: do not wrap) pub fn wrapping_mode(&mut self, mode: WrappingMode) -> &mut Self { self.config.wrapping_mode = mode; self } /// Whether or not to use ANSI italics (default: off) pub fn use_italics(&mut self, yes: bool) -> &mut Self { self.config.use_italic_text = yes; self } /// If and how to use a pager (default: no paging) #[cfg(feature = "paging")] pub fn paging_mode(&mut self, mode: PagingMode) -> &mut Self { self.config.paging_mode = mode; self } /// Specify the command to start the pager (default: use "less") #[cfg(feature = "paging")] pub fn pager(&mut self, cmd: &'a str) -> &mut Self { self.config.pager = Some(cmd); self } /// Specify the lines that should be printed (default: all) pub fn line_ranges(&mut self, ranges: LineRanges) -> &mut Self { self.config.visible_lines = VisibleLines::Ranges(ranges); self } /// Specify a line that should be highlighted (default: none). /// This can be called multiple times to highlight more than one /// line. See also: highlight_range. pub fn highlight(&mut self, line: usize) -> &mut Self { self.highlighted_lines.push(LineRange::new(line, line)); self } /// Specify a range of lines that should be highlighted (default: none). /// This can be called multiple times to highlight more than one range /// of lines. pub fn highlight_range(&mut self, from: usize, to: usize) -> &mut Self { self.highlighted_lines.push(LineRange::new(from, to)); self } /// Specify the maximum number of consecutive empty lines to print. pub fn squeeze_empty_lines(&mut self, maximum: Option) -> &mut Self { self.config.squeeze_lines = maximum; self } /// Specify the highlighting theme. /// You can use [`crate::theme::theme`] to pick a theme based on user preferences /// and the terminal's background color. pub fn theme(&mut self, theme: impl AsRef) -> &mut Self { self.config.theme = theme.as_ref().to_owned(); self } /// Specify custom file extension / file name to syntax mappings pub fn syntax_mapping(&mut self, mapping: SyntaxMapping<'a>) -> &mut Self { self.config.syntax_mapping = mapping; self } pub fn themes(&self) -> impl Iterator { self.assets.themes() } pub fn syntaxes(&self) -> impl Iterator + '_ { // We always use assets from the binary, which are guaranteed to always // be valid, so get_syntaxes() can never fail here self.assets .get_syntaxes() .unwrap() .iter() .filter(|s| !s.hidden) .map(|s| Syntax { name: s.name.clone(), file_extensions: s.file_extensions.clone(), }) } /// Pretty-print all specified inputs. This method will "use" all stored inputs. /// If you want to call 'print' multiple times, you have to call the appropriate /// input_* methods again. pub fn print(&mut self) -> Result { self.print_with_writer(None::<&mut dyn std::fmt::Write>) } /// Pretty-print all specified inputs to a specified writer. pub fn print_with_writer(&mut self, writer: Option) -> Result { let highlight_lines = std::mem::take(&mut self.highlighted_lines); self.config.highlighted_lines = HighlightedLineRanges(LineRanges::from(highlight_lines)); self.config.term_width = self .term_width .unwrap_or_else(|| Term::stdout().size().1 as usize); self.config.style_components.clear(); if self.active_style_components.grid { self.config.style_components.insert(StyleComponent::Grid); } if self.active_style_components.rule { self.config.style_components.insert(StyleComponent::Rule); } if self.active_style_components.header_filename { self.config .style_components .insert(StyleComponent::HeaderFilename); } if self.active_style_components.line_numbers { self.config .style_components .insert(StyleComponent::LineNumbers); } if self.active_style_components.snip { self.config.style_components.insert(StyleComponent::Snip); } #[cfg(feature = "git")] if self.active_style_components.vcs_modification_markers { self.config.style_components.insert(StyleComponent::Changes); } // Collect the inputs to print let inputs = std::mem::take(&mut self.inputs); // Run the controller let controller = Controller::new(&self.config, &self.assets); // If writer is provided, pass it to the controller, otherwise pass None if let Some(mut w) = writer { controller.run( inputs.into_iter().map(|i| i.into()).collect(), Some(&mut OutputHandle::FmtWrite(&mut w)), ) } else { controller.run(inputs.into_iter().map(|i| i.into()).collect(), None) } } } impl Default for PrettyPrinter<'_> { fn default() -> Self { Self::new() } } /// An input source for the pretty printer. pub struct Input<'a> { input: input::Input<'a>, } impl<'a> Input<'a> { /// A new input from a reader. pub fn from_reader(reader: R) -> Self { input::Input::from_reader(Box::new(reader)).into() } /// A new input from a file. pub fn from_file(path: impl AsRef) -> Self { input::Input::ordinary_file(path).into() } /// A new input from bytes. pub fn from_bytes(bytes: &'a [u8]) -> Self { Input::from_reader(bytes) } /// A new input from STDIN. pub fn from_stdin() -> Self { input::Input::stdin().into() } /// The filename of the input. /// This affects syntax detection and changes the default header title. pub fn name(mut self, name: impl AsRef) -> Self { self.input = self.input.with_name(Some(name)); self } /// The description for the type of input (e.g. "File") pub fn kind(mut self, kind: impl Into) -> Self { let kind = kind.into(); self.input .description_mut() .set_kind(if kind.is_empty() { None } else { Some(kind) }); self } /// The title for the input (e.g. "Descriptive title") /// This defaults to the file name. pub fn title(mut self, title: impl Into) -> Self { self.input.description_mut().set_title(Some(title.into())); self } } impl<'a> From> for Input<'a> { fn from(input: input::Input<'a>) -> Self { Self { input } } } impl<'a> From> for input::Input<'a> { fn from(Input { input }: Input<'a>) -> Self { input } } ================================================ FILE: src/printer.rs ================================================ use std::vec::Vec; use nu_ansi_term::Color::{Fixed, Green, Red, Yellow}; use nu_ansi_term::Style; use bytesize::ByteSize; use syntect::easy::HighlightLines; use syntect::highlighting::Color; use syntect::highlighting::FontStyle; use syntect::highlighting::Theme; use syntect::parsing::SyntaxSet; use content_inspector::ContentType; use encoding_rs::{UTF_16BE, UTF_16LE}; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthChar; use crate::assets::{HighlightingAssets, SyntaxReferenceInSet}; use crate::config::Config; #[cfg(feature = "git")] use crate::decorations::LineChangesDecoration; use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}; #[cfg(feature = "git")] use crate::diff::LineChanges; use crate::error::*; use crate::input::OpenedInput; use crate::line_range::{MaxBufferedLineNumber, RangeCheckResult}; use crate::output::OutputHandle; use crate::preprocessor::{expand_tabs, replace_nonprintable, strip_ansi, strip_overstrike}; use crate::style::StyleComponent; use crate::terminal::{as_terminal_escaped, to_ansi_color}; use crate::vscreen::{AnsiStyle, EscapeSequence, EscapeSequenceIterator}; use crate::wrapping::WrappingMode; use crate::BinaryBehavior; use crate::StripAnsiMode; const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI { raw_sequence: "\x1B[4m", parameters: "4", intermediates: "", final_byte: "m", }; const ANSI_UNDERLINE_DISABLE: EscapeSequence = EscapeSequence::CSI { raw_sequence: "\x1B[24m", parameters: "24", intermediates: "", final_byte: "m", }; const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting::Style { foreground: Color { r: 127, g: 127, b: 127, a: 255, }, background: Color { r: 127, g: 127, b: 127, a: 255, }, font_style: FontStyle::empty(), }; pub(crate) trait Printer { fn print_header( &mut self, handle: &mut OutputHandle, input: &OpenedInput, add_header_padding: bool, ) -> Result<()>; fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>; fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>; fn print_line( &mut self, out_of_range: bool, handle: &mut OutputHandle, line_number: usize, line_buffer: &[u8], max_buffered_line_number: MaxBufferedLineNumber, ) -> Result<()>; } pub struct SimplePrinter<'a> { config: &'a Config<'a>, consecutive_empty_lines: usize, } impl<'a> SimplePrinter<'a> { pub fn new(config: &'a Config) -> Self { SimplePrinter { config, consecutive_empty_lines: 0, } } } impl Printer for SimplePrinter<'_> { fn print_header( &mut self, _handle: &mut OutputHandle, _input: &OpenedInput, _add_header_padding: bool, ) -> Result<()> { Ok(()) } fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { Ok(()) } fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> { Ok(()) } fn print_line( &mut self, out_of_range: bool, handle: &mut OutputHandle, _line_number: usize, line_buffer: &[u8], _max_buffered_line_number: MaxBufferedLineNumber, ) -> Result<()> { // Skip squeezed lines. if let Some(squeeze_limit) = self.config.squeeze_lines { if String::from_utf8_lossy(line_buffer) .trim_end_matches(['\r', '\n']) .is_empty() { self.consecutive_empty_lines += 1; if self.consecutive_empty_lines > squeeze_limit { return Ok(()); } } else { self.consecutive_empty_lines = 0; } } if !out_of_range { if self.config.show_nonprintable { let line = replace_nonprintable( line_buffer, self.config.tab_width, self.config.nonprintable_notation, ); write!(handle, "{line}")?; } else { match handle { OutputHandle::IoWrite(handle) => handle.write_all(line_buffer)?, OutputHandle::FmtWrite(handle) => { write!( handle, "{}", std::str::from_utf8(line_buffer).map_err(|_| Error::Msg( "encountered invalid utf8 while printing to non-io buffer" .to_string() ))? )?; } } }; } Ok(()) } } struct HighlighterFromSet<'a> { highlighter: HighlightLines<'a>, syntax_set: &'a SyntaxSet, } impl<'a> HighlighterFromSet<'a> { fn new(syntax_in_set: SyntaxReferenceInSet<'a>, theme: &'a Theme) -> Self { Self { highlighter: HighlightLines::new(syntax_in_set.syntax, theme), syntax_set: syntax_in_set.syntax_set, } } } pub(crate) struct InteractivePrinter<'a> { colors: Colors, config: &'a Config<'a>, decorations: Vec>, panel_width: usize, ansi_style: AnsiStyle, content_type: Option, #[cfg(feature = "git")] pub line_changes: &'a Option, highlighter_from_set: Option>, background_color_highlight: Option, consecutive_empty_lines: usize, strip_ansi: bool, strip_overstrike: bool, } impl<'a> InteractivePrinter<'a> { pub(crate) fn new( config: &'a Config, assets: &'a HighlightingAssets, input: &mut OpenedInput, #[cfg(feature = "git")] line_changes: &'a Option, ) -> Result { let theme = assets.get_theme(&config.theme); let background_color_highlight = theme.settings.line_highlight; let colors = if config.colored_output { Colors::colored(theme, config.true_color) } else { Colors::plain() }; // Create decorations. let mut decorations: Vec> = Vec::new(); if config.style_components.numbers() { decorations.push(Box::new(LineNumberDecoration::new(&colors))); } #[cfg(feature = "git")] { if config.style_components.changes() && line_changes.as_ref().is_some_and(|c| !c.is_empty()) { 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.style_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 highlighter for the output. let is_printing_binary = input .reader .content_type .is_some_and(|c| c.is_binary() && !config.show_nonprintable); let needs_to_match_syntax = (!is_printing_binary || matches!(config.binary, BinaryBehavior::AsText)) && (config.colored_output || config.strip_ansi == StripAnsiMode::Auto); let (is_plain_text, strip_overstrike, highlighter_from_set) = if needs_to_match_syntax { // Determine the type of syntax for highlighting const PLAIN_TEXT_SYNTAX: &str = "Plain Text"; const MANPAGE_SYNTAX: &str = "Manpage"; const COMMAND_HELP_SYNTAX: &str = "Command Help"; match assets.get_syntax( config.language, config.fallback_syntax, input, &config.syntax_mapping, ) { Ok(syntax_in_set) => ( syntax_in_set.syntax.name == PLAIN_TEXT_SYNTAX, syntax_in_set.syntax.name == MANPAGE_SYNTAX || syntax_in_set.syntax.name == COMMAND_HELP_SYNTAX, Some(HighlighterFromSet::new(syntax_in_set, theme)), ), Err(Error::UndetectedSyntax(_)) => ( true, false, Some( assets .find_syntax_by_name(PLAIN_TEXT_SYNTAX)? .map(|s| HighlighterFromSet::new(s, theme)) .expect("A plain text syntax is available"), ), ), Err(e) => return Err(e), } } else { (false, false, None) }; // Determine when to strip ANSI sequences let strip_ansi = match config.strip_ansi { _ if config.show_nonprintable => false, StripAnsiMode::Always => true, StripAnsiMode::Auto if is_plain_text => false, // Plain text may already contain escape sequences. StripAnsiMode::Auto => true, _ => false, }; Ok(InteractivePrinter { panel_width, colors, config, decorations, content_type: input.reader.content_type, ansi_style: AnsiStyle::new(), #[cfg(feature = "git")] line_changes, highlighter_from_set, background_color_highlight, consecutive_empty_lines: 0, strip_ansi, strip_overstrike, }) } fn print_horizontal_line_term( &mut self, handle: &mut OutputHandle, style: Style, ) -> Result<()> { writeln!( handle, "{}", style.paint("─".repeat(self.config.term_width)) )?; Ok(()) } fn print_horizontal_line(&mut self, handle: &mut OutputHandle, grid_char: char) -> Result<()> { if self.panel_width == 0 { self.print_horizontal_line_term(handle, self.colors.grid)?; } else { let hline = "─".repeat(self.config.term_width - (self.panel_width + 1)); let hline = format!("{}{grid_char}{hline}", "─".repeat(self.panel_width)); writeln!(handle, "{}", self.colors.grid.paint(hline))?; } Ok(()) } fn create_fake_panel(&self, text: &str) -> String { if self.panel_width == 0 { return "".to_string(); } let text_truncated: String = text.chars().take(self.panel_width - 1).collect(); let text_filled: String = format!( "{text_truncated}{}", " ".repeat(self.panel_width - 1 - text_truncated.len()) ); if self.config.style_components.grid() { format!("{text_filled} │ ") } else { text_filled } } fn get_header_component_indent_length(&self) -> usize { if self.config.style_components.grid() && self.panel_width > 0 { self.panel_width + 2 } else { self.panel_width } } fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> { if self.config.style_components.grid() { write!( handle, "{}{}", " ".repeat(self.panel_width), self.colors .grid .paint(if self.panel_width > 0 { "│ " } else { "" }), ) } else { write!(handle, "{}", " ".repeat(self.panel_width)) } } fn print_header_component_with_indent( &mut self, handle: &mut OutputHandle, content: &str, ) -> Result<()> { self.print_header_component_indent(handle)?; writeln!(handle, "{content}") } fn print_header_multiline_component( &mut self, handle: &mut OutputHandle, content: &str, ) -> Result<()> { let content_width = self.config.term_width - self.get_header_component_indent_length(); if content.chars().count() <= content_width { return self.print_header_component_with_indent(handle, content); } let mut content_graphemes: Vec<&str> = content.graphemes(true).collect(); while content_graphemes.len() > content_width { let (content_line, remaining) = content_graphemes.split_at(content_width); self.print_header_component_with_indent(handle, content_line.join("").as_str())?; content_graphemes = remaining.to_vec(); } self.print_header_component_with_indent(handle, content_graphemes.join("").as_str()) } fn highlight_regions_for_line<'b>( &mut self, line: &'b str, ) -> Result> { let highlighter_from_set = match self.highlighter_from_set { Some(ref mut highlighter_from_set) => highlighter_from_set, _ => return Ok(vec![(EMPTY_SYNTECT_STYLE, line)]), }; // skip syntax highlighting on long lines let too_long = line.len() > 1024 * 16; let for_highlighting: &str = if too_long { "\n" } else { line }; let mut highlighted_line = highlighter_from_set .highlighter .highlight_line(for_highlighting, highlighter_from_set.syntax_set)?; if too_long { highlighted_line[0].1 = line; } Ok(highlighted_line) } fn preprocess(&self, text: &str, cursor: &mut usize) -> String { if self.config.tab_width > 0 { return expand_tabs(text, self.config.tab_width, cursor); } *cursor += text.len(); text.to_string() } } impl Printer for InteractivePrinter<'_> { fn print_header( &mut self, handle: &mut OutputHandle, input: &OpenedInput, add_header_padding: bool, ) -> Result<()> { // If input is empty and quiet_empty is enabled, skip all output if self.content_type.is_none() && self.config.quiet_empty { return Ok(()); } if add_header_padding && self.config.style_components.rule() { self.print_horizontal_line_term(handle, self.colors.rule)?; } if !self.config.style_components.header() { if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable && !matches!(self.config.binary, BinaryBehavior::AsText) { writeln!( handle, "{}: Binary content from {} will not be printed to the terminal \ (but will be present if the output of 'bat' is piped). You can use 'bat -A' \ to show the binary file contents.", Yellow.paint("[bat warning]"), input.description.summary(), )?; } else if self.config.style_components.grid() { self.print_horizontal_line(handle, '┬')?; } return Ok(()); } let mode = match self.content_type { Some(ContentType::BINARY) => " ", Some(ContentType::UTF_16LE) => " ", Some(ContentType::UTF_16BE) => " ", None => " ", _ => "", }; let description = &input.description; let metadata = &input.metadata; // We use this iterator to have a deterministic order for // header components. HashSet has arbitrary order, but Vec is ordered. let header_components: Vec = [ ( StyleComponent::HeaderFilename, self.config.style_components.header_filename(), ), ( StyleComponent::HeaderFilesize, self.config.style_components.header_filesize(), ), ] .iter() .filter(|(_, is_enabled)| *is_enabled) .map(|(component, _)| *component) .collect(); // Print the cornering grid before the first header component if self.config.style_components.grid() { self.print_horizontal_line(handle, '┬')?; } else { // Only pad space between files, if we haven't already drawn a horizontal rule if add_header_padding && !self.config.style_components.rule() { writeln!(handle)?; } } header_components .iter() .try_for_each(|component| match component { StyleComponent::HeaderFilename => { let header_filename = format!( "{}{}{mode}", description .kind() .map(|kind| format!("{kind}: ")) .unwrap_or_else(|| "".into()), self.colors.header_value.paint(description.title()), ); self.print_header_multiline_component(handle, &header_filename) } StyleComponent::HeaderFilesize => { let bsize = metadata .size .map(|s| format!("{}", ByteSize(s))) .unwrap_or_else(|| "-".into()); let header_filesize = format!("Size: {}", self.colors.header_value.paint(bsize)); self.print_header_multiline_component(handle, &header_filesize) } _ => Ok(()), })?; if self.config.style_components.grid() { if self.content_type.is_some_and(|c| c.is_text()) || self.config.show_nonprintable || matches!(self.config.binary, BinaryBehavior::AsText) { self.print_horizontal_line(handle, '┼')?; } else { self.print_horizontal_line(handle, '┴')?; } } Ok(()) } fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { // If input is empty and quiet_empty is enabled, skip footer if self.content_type.is_none() && self.config.quiet_empty { return Ok(()); } if self.config.style_components.grid() && (self.content_type.is_some_and(|c| c.is_text()) || self.config.show_nonprintable || matches!(self.config.binary, BinaryBehavior::AsText)) { self.print_horizontal_line(handle, '┴') } else { Ok(()) } } fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()> { let panel = self.create_fake_panel(" ..."); let panel_count = panel.chars().count(); let title = "8<"; let title_count = title.chars().count(); let snip_left = "─ ".repeat((self.config.term_width - panel_count - (title_count / 2)) / 4); let snip_left_count = snip_left.chars().count(); // Can't use .len() with Unicode. let snip_right = " ─".repeat((self.config.term_width - panel_count - snip_left_count - title_count) / 2); writeln!( handle, "{}", self.colors .grid .paint(format!("{panel}{snip_left}{title}{snip_right}")) )?; Ok(()) } fn print_line( &mut self, out_of_range: bool, handle: &mut OutputHandle, line_number: usize, line_buffer: &[u8], max_buffered_line_number: MaxBufferedLineNumber, ) -> Result<()> { let line = if self.config.show_nonprintable { replace_nonprintable( line_buffer, self.config.tab_width, self.config.nonprintable_notation, ) .into() } else { let mut line = match self.content_type { Some(ContentType::BINARY) | None if !matches!(self.config.binary, BinaryBehavior::AsText) => { return Ok(()); } Some(ContentType::UTF_16LE) => UTF_16LE.decode_with_bom_removal(line_buffer).0, Some(ContentType::UTF_16BE) => UTF_16BE.decode_with_bom_removal(line_buffer).0, _ => { let line = String::from_utf8_lossy(line_buffer); if line_number == 1 { match line.strip_prefix('\u{feff}') { Some(stripped) => stripped.to_string().into(), None => line, } } else { line } } }; if self.strip_overstrike { if let Some(pos) = line.find('\x08') { line = strip_overstrike(&line, pos).into(); } } // If ANSI escape sequences are supposed to be stripped, do it before syntax highlighting. if self.strip_ansi { line = strip_ansi(&line).into() } line }; let regions = self.highlight_regions_for_line(&line)?; if out_of_range { return Ok(()); } // Skip squeezed lines. if let Some(squeeze_limit) = self.config.squeeze_lines { if line.trim_end_matches(['\r', '\n']).is_empty() { self.consecutive_empty_lines += 1; if self.consecutive_empty_lines > squeeze_limit { return Ok(()); } } else { self.consecutive_empty_lines = 0; } } 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 = None; // Line highlighting let highlight_this_line = self .config .highlighted_lines .0 .check(line_number, max_buffered_line_number) == RangeCheckResult::InRange; if highlight_this_line && self.config.theme == "ansi" { self.ansi_style.update(ANSI_UNDERLINE_ENABLE); } let background_color = self .background_color_highlight .filter(|_| highlight_this_line); // Line decorations. if self.panel_width > 0 { let decorations = self .decorations .iter() .map(|d| d.generate(line_number, false, self)); for deco in decorations { write!(handle, "{} ", deco.text)?; cursor_max -= deco.width + 1; } } // Line contents. if matches!(self.config.wrapping_mode, WrappingMode::NoWrapping(_)) { let true_color = self.config.true_color; let colored_output = self.config.colored_output; let italics = self.config.use_italic_text; for &(style, region) in ®ions { let ansi_iterator = EscapeSequenceIterator::new(region); for chunk in ansi_iterator { match chunk { // Regular text. EscapeSequence::Text(text) => { let text = self.preprocess(text, &mut cursor_total); let text_trimmed = text.trim_end_matches(['\r', '\n']); write!( handle, "{}{}", as_terminal_escaped( style, &format!("{}{text_trimmed}", self.ansi_style), true_color, colored_output, italics, background_color ), self.ansi_style.to_reset_sequence(), )?; // Pad the rest of the line. if text.len() != text_trimmed.len() { if let Some(background_color) = background_color { let ansi_style = Style { background: to_ansi_color(background_color, true_color), ..Default::default() }; let width = if cursor_total <= cursor_max { cursor_max - cursor_total + 1 } else { 0 }; write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?; } write!(handle, "{}", &text[text_trimmed.len()..])?; } } // ANSI escape passthrough. _ => { write!(handle, "{}", chunk.raw())?; self.ansi_style.update(chunk); } } } } if !self.config.style_components.plain() && line.bytes().next_back() != Some(b'\n') { writeln!(handle)?; } } else { for &(style, region) in ®ions { let ansi_iterator = EscapeSequenceIterator::new(region); for chunk in ansi_iterator { match chunk { // Regular text. EscapeSequence::Text(text) => { let text = self .preprocess(text.trim_end_matches(['\r', '\n']), &mut cursor_total); let mut max_width = cursor_max - cursor; // line buffer (avoid calling write! for every character) let mut line_buf = String::with_capacity(max_width * 4); // Displayed width of line_buf let mut current_width = 0; let word_wrap = matches!(self.config.wrapping_mode, WrappingMode::Word); // For word wrapping, track last whitespace position. let mut last_ws_idx: Option = None; for c in text.chars() { // calculate the displayed width for next character let cw = c.width().unwrap_or(0); current_width += cw; // Track whitespace positions for word wrapping. if word_wrap && c.is_whitespace() { last_ws_idx = Some(line_buf.len()); } // if next character cannot be printed on this line, // flush the buffer. if current_width > max_width { // 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(|d| d .generate(line_number, true, self) .text) .collect::>() .join(" ") )) } else { Some("".to_string()) } } // Determine the break point and remainder // for word wrapping. let (emit_end, rest_start) = if word_wrap { if let Some(ws_idx) = last_ws_idx { // Skip the whitespace character itself // and carry the rest to the next line. let rs = ws_idx + line_buf[ws_idx..] .chars() .next() .map(|ch| ch.len_utf8()) .unwrap_or(0); (ws_idx, Some(rs)) } else { (line_buf.len(), None) } } else { (line_buf.len(), None) }; // It wraps. write!( handle, "{}{}\n{}", as_terminal_escaped( style, &format!( "{}{}", self.ansi_style, &line_buf[..emit_end] ), self.config.true_color, self.config.colored_output, self.config.use_italic_text, background_color ), self.ansi_style.to_reset_sequence(), panel_wrap.clone().unwrap() )?; cursor = 0; max_width = cursor_max; if let Some(rs) = rest_start { // Word wrap: carry remainder to next line. let remainder = line_buf[rs..].to_string(); let rem_width: usize = remainder .chars() .map(|ch| ch.width().unwrap_or(0)) .sum(); line_buf.clear(); line_buf.push_str(&remainder); current_width = rem_width + cw; } else { line_buf.clear(); current_width = cw; } last_ws_idx = None; } line_buf.push(c); } // flush the buffer cursor += current_width; write!( handle, "{}", as_terminal_escaped( style, &format!("{}{line_buf}", self.ansi_style), self.config.true_color, self.config.colored_output, self.config.use_italic_text, background_color ) )?; } // ANSI escape passthrough. _ => { write!(handle, "{}", chunk.raw())?; self.ansi_style.update(chunk); } } } } if let Some(background_color) = background_color { let ansi_style = Style { background: to_ansi_color(background_color, self.config.true_color), ..Default::default() }; write!( handle, "{}", ansi_style.paint(" ".repeat(cursor_max - cursor)) )?; } writeln!(handle)?; } if highlight_this_line && self.config.theme == "ansi" { write!(handle, "{}", ANSI_UNDERLINE_DISABLE.raw())?; self.ansi_style.update(ANSI_UNDERLINE_DISABLE); } Ok(()) } } const DEFAULT_GUTTER_COLOR: u8 = 238; #[derive(Debug, Default)] pub struct Colors { pub grid: Style, pub rule: Style, pub header_value: 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_style = Style { foreground: match theme.settings.gutter_foreground { // If the theme provides a gutter foreground color, use it. // Note: It might be the special value #00000001, in which case // to_ansi_color returns None and we use an empty Style // (resulting in the terminal's default foreground color). Some(c) => to_ansi_color(c, true_color), // Otherwise, use a specific fallback color. None => Some(Fixed(DEFAULT_GUTTER_COLOR)), }, ..Style::default() }; Colors { grid: gutter_style, rule: gutter_style, header_value: Style::new().bold(), git_added: Green.normal(), git_removed: Red.normal(), git_modified: Yellow.normal(), line_number: gutter_style, } } } ================================================ FILE: src/style.rs ================================================ use std::collections::HashSet; use std::str::FromStr; use crate::error::*; #[non_exhaustive] #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] pub enum StyleComponent { Auto, #[cfg(feature = "git")] Changes, Grid, Rule, Header, HeaderFilename, HeaderFilesize, LineNumbers, Snip, Full, Default, Plain, } impl StyleComponent { pub fn components(self, interactive_terminal: bool) -> &'static [StyleComponent] { match self { StyleComponent::Auto => { if interactive_terminal { StyleComponent::Default.components(interactive_terminal) } else { StyleComponent::Plain.components(interactive_terminal) } } #[cfg(feature = "git")] StyleComponent::Changes => &[StyleComponent::Changes], StyleComponent::Grid => &[StyleComponent::Grid], StyleComponent::Rule => &[StyleComponent::Rule], StyleComponent::Header => &[StyleComponent::HeaderFilename], StyleComponent::HeaderFilename => &[StyleComponent::HeaderFilename], StyleComponent::HeaderFilesize => &[StyleComponent::HeaderFilesize], StyleComponent::LineNumbers => &[StyleComponent::LineNumbers], StyleComponent::Snip => &[StyleComponent::Snip], StyleComponent::Full => &[ #[cfg(feature = "git")] StyleComponent::Changes, StyleComponent::Grid, StyleComponent::HeaderFilename, StyleComponent::HeaderFilesize, StyleComponent::LineNumbers, StyleComponent::Snip, ], StyleComponent::Default => &[ #[cfg(feature = "git")] StyleComponent::Changes, StyleComponent::Grid, StyleComponent::HeaderFilename, StyleComponent::LineNumbers, StyleComponent::Snip, ], StyleComponent::Plain => &[], } } } impl FromStr for StyleComponent { type Err = Error; fn from_str(s: &str) -> Result { match s { "auto" => Ok(StyleComponent::Auto), #[cfg(feature = "git")] "changes" => Ok(StyleComponent::Changes), "grid" => Ok(StyleComponent::Grid), "rule" => Ok(StyleComponent::Rule), "header" => Ok(StyleComponent::Header), "header-filename" => Ok(StyleComponent::HeaderFilename), "header-filesize" => Ok(StyleComponent::HeaderFilesize), "numbers" => Ok(StyleComponent::LineNumbers), "snip" => Ok(StyleComponent::Snip), "full" => Ok(StyleComponent::Full), "default" => Ok(StyleComponent::Default), "plain" => Ok(StyleComponent::Plain), _ => Err(format!("Unknown style '{s}'").into()), } } } #[derive(Debug, Clone, Default)] pub struct StyleComponents(pub HashSet); impl StyleComponents { pub fn new(components: &[StyleComponent]) -> StyleComponents { StyleComponents(components.iter().cloned().collect()) } #[cfg(feature = "git")] pub fn changes(&self) -> bool { self.0.contains(&StyleComponent::Changes) } pub fn grid(&self) -> bool { self.0.contains(&StyleComponent::Grid) } pub fn rule(&self) -> bool { self.0.contains(&StyleComponent::Rule) } pub fn header(&self) -> bool { self.header_filename() || self.header_filesize() } pub fn header_filename(&self) -> bool { self.0.contains(&StyleComponent::HeaderFilename) } pub fn header_filesize(&self) -> bool { self.0.contains(&StyleComponent::HeaderFilesize) } pub fn numbers(&self) -> bool { self.0.contains(&StyleComponent::LineNumbers) } pub fn snip(&self) -> bool { self.0.contains(&StyleComponent::Snip) } pub fn plain(&self) -> bool { self.0.iter().all(|c| c == &StyleComponent::Plain) } pub fn insert(&mut self, component: StyleComponent) { self.0.insert(component); } pub fn clear(&mut self) { self.0.clear(); } } #[derive(Debug, PartialEq)] enum ComponentAction { Override, Add, Remove, } impl ComponentAction { fn extract_from_str(string: &str) -> (ComponentAction, &str) { match string.chars().next() { Some('-') => (ComponentAction::Remove, string.strip_prefix('-').unwrap()), Some('+') => (ComponentAction::Add, string.strip_prefix('+').unwrap()), _ => (ComponentAction::Override, string), } } } /// A list of [StyleComponent] that can be parsed from a string. pub struct StyleComponentList(Vec<(ComponentAction, StyleComponent)>); impl StyleComponentList { fn expand_into(&self, components: &mut HashSet, interactive_terminal: bool) { for (action, component) in self.0.iter() { let subcomponents = component.components(interactive_terminal); use ComponentAction::*; match action { Override | Add => components.extend(subcomponents), Remove => components.retain(|c| !subcomponents.contains(c)), } } } /// Returns `true` if any component in the list was not prefixed with `+` or `-`. fn contains_override(&self) -> bool { self.0.iter().any(|(a, _)| *a == ComponentAction::Override) } /// Combines multiple [StyleComponentList]s into a single [StyleComponents] set. /// /// ## Precedence /// The most recent list will take precedence and override all previous lists /// unless it only contains components prefixed with `-` or `+`. When this /// happens, the list's components will be merged into the previous list. /// /// ## Example /// ```text /// [numbers,grid] + [header,changes] -> [header,changes] /// [numbers,grid] + [+header,-grid] -> [numbers,header] /// ``` /// /// ## Parameters /// - `with_default`: If true, the styles lists will build upon the StyleComponent::Auto style. pub fn to_components( lists: impl IntoIterator, interactive_terminal: bool, with_default: bool, ) -> StyleComponents { let mut components: HashSet = HashSet::new(); if with_default { components.extend(StyleComponent::Auto.components(interactive_terminal)) } StyleComponents(lists.into_iter().fold(components, |mut components, list| { if list.contains_override() { components.clear(); } list.expand_into(&mut components, interactive_terminal); components })) } } impl Default for StyleComponentList { fn default() -> Self { StyleComponentList(vec![(ComponentAction::Override, StyleComponent::Default)]) } } impl FromStr for StyleComponentList { type Err = Error; fn from_str(s: &str) -> Result { Ok(StyleComponentList( s.split(",") .map(ComponentAction::extract_from_str) // If the component starts with "-", it's meant to be removed .map(|(a, s)| Ok((a, StyleComponent::from_str(s)?))) .collect::>>()?, )) } } #[cfg(test)] mod test { use std::collections::HashSet; use std::str::FromStr; use super::ComponentAction::*; use super::StyleComponent; use super::StyleComponent::*; use super::StyleComponentList; #[test] pub fn style_component_list_parse() { assert_eq!( StyleComponentList::from_str("grid,+numbers,snip,-snip,header") .expect("no error") .0, vec![ (Override, Grid), (Add, LineNumbers), (Override, Snip), (Remove, Snip), (Override, Header), ] ); assert!(StyleComponentList::from_str("not-a-component").is_err()); assert!(StyleComponentList::from_str("grid,not-a-component").is_err()); assert!(StyleComponentList::from_str("numbers,-not-a-component").is_err()); } #[test] pub fn style_component_list_to_components() { assert_eq!( StyleComponentList::to_components( vec![StyleComponentList::from_str("grid,numbers").expect("no error")], false, false ) .0, HashSet::from([Grid, LineNumbers]) ); } #[test] pub fn style_component_list_to_components_removes_negated() { assert_eq!( StyleComponentList::to_components( vec![StyleComponentList::from_str("grid,numbers,-grid").expect("no error")], false, false ) .0, HashSet::from([LineNumbers]) ); } #[test] pub fn style_component_list_to_components_expands_subcomponents() { assert_eq!( StyleComponentList::to_components( vec![StyleComponentList::from_str("full").expect("no error")], false, false ) .0, HashSet::from_iter(Full.components(true).to_owned()) ); } #[test] pub fn style_component_list_expand_negates_subcomponents() { assert!(!StyleComponentList::to_components( vec![StyleComponentList::from_str("full,-numbers").expect("no error")], true, false ) .numbers()); } #[test] pub fn style_component_list_to_components_precedence_overrides_previous_lists() { assert_eq!( StyleComponentList::to_components( vec![ StyleComponentList::from_str("grid").expect("no error"), StyleComponentList::from_str("numbers").expect("no error"), ], false, false ) .0, HashSet::from([LineNumbers]) ); } #[test] pub fn style_component_list_to_components_precedence_merges_previous_lists() { assert_eq!( StyleComponentList::to_components( vec![ StyleComponentList::from_str("grid,header").expect("no error"), StyleComponentList::from_str("-grid").expect("no error"), StyleComponentList::from_str("+numbers").expect("no error"), ], false, false ) .0, HashSet::from([HeaderFilename, LineNumbers]) ); } #[test] pub fn style_component_list_default_builds_on_auto() { assert_eq!( StyleComponentList::to_components( vec![StyleComponentList::from_str("-numbers").expect("no error"),], true, true ) .0, { let mut expected: HashSet = HashSet::new(); expected.extend(Auto.components(true)); expected.remove(&LineNumbers); expected } ); } } ================================================ FILE: src/syntax_mapping/builtin.rs ================================================ use std::env; use globset::GlobMatcher; use once_cell::sync::Lazy; use crate::syntax_mapping::{make_glob_matcher, MappingTarget}; // Static syntax mappings generated from /src/syntax_mapping/builtins/ by the // build script (/build/syntax_mapping.rs). include!(concat!( env!("OUT_DIR"), "/codegen_static_syntax_mappings.rs" )); // The defined matcher strings are analysed at compile time and converted into // lazily-compiled `GlobMatcher`s. This is so that the string searches are moved // from run time to compile time, thus improving startup performance. // // To any future maintainer (including possibly myself) wondering why there is // not a `BuiltinMatcher` enum that looks like this: // // ``` // enum BuiltinMatcher { // Fixed(&'static str), // Dynamic(Lazy>), // } // ``` // // Because there was. I tried it and threw it out. // // Naively looking at the problem from a distance, this may seem like a good // design (strongly typed etc. etc.). It would also save on compiled size by // extracting out common behaviour into functions. But while actually // implementing the lazy matcher compilation logic, I realised that it's most // convenient for `BUILTIN_MAPPINGS` to have the following type: // // `[(Lazy>, MappingTarget); N]` // // The benefit for this is that operations like listing all builtin mappings // would be effectively memoised. The caller would not have to compile another // `GlobMatcher` for rules that they have previously visited. // // Unfortunately, this means we are going to have to store a distinct closure // for each rule anyway, which makes a `BuiltinMatcher` enum a pointless layer // of indirection. // // In the current implementation, the closure within each generated rule simply // calls either `build_matcher_fixed` or `build_matcher_dynamic`, depending on // whether the defined matcher contains dynamic segments or not. /// Compile a fixed glob string into a glob matcher. /// /// A failure to compile is a fatal error. /// /// Used internally by `Lazy>`'s lazy evaluation closure. fn build_matcher_fixed(from: &str) -> GlobMatcher { make_glob_matcher(from).expect("A builtin fixed glob matcher failed to compile") } /// Join a list of matcher segments to create a glob string, replacing all /// environment variables, then compile to a glob matcher. /// /// Returns `None` if any replacement fails, or if the joined glob string fails /// to compile. /// /// Used internally by `Lazy>`'s lazy evaluation closure. fn build_matcher_dynamic(segs: &[MatcherSegment]) -> Option { // join segments let mut buf = String::new(); for seg in segs { match seg { MatcherSegment::Text(s) => buf.push_str(s), MatcherSegment::Env(var) => { let replaced = env::var(var).ok()?; buf.push_str(&replaced); } } } // compile glob matcher let matcher = make_glob_matcher(&buf).ok()?; Some(matcher) } /// A segment of a dynamic builtin matcher. /// /// Used internally by `Lazy>`'s lazy evaluation closure. #[derive(Clone, Debug)] enum MatcherSegment { Text(&'static str), Env(&'static str), } ================================================ FILE: src/syntax_mapping/builtins/README.md ================================================ # `/src/syntax_mapping/builtins` The files in this directory define path/name-based syntax mappings, which amend and take precedence over the extension/content-based syntax mappings provided by [syntect](https://github.com/trishume/syntect). ## File organisation Each TOML file should describe the syntax mappings of a single application, or otherwise a set of logically-related rules. What defines "a single application" here is deliberately vague, since the file-splitting is purely for maintainability reasons. (Technically, we could just as well use a single TOML file.) So just use common sense. TOML files should reside in the corresponding subdirectory of the platform(s) that they intend to target. At compile time, the build script will go through each subdirectory that is applicable to the compilation target, collect the syntax mappings defined by all TOML files, and embed them into the binary. ## File syntax Each TOML file should contain a single section named `mappings`, with each of its keys being a language identifier (first column of `bat -L`; also referred to as "target"). The value of each key should be an array of strings, with each item being a glob matcher. We will call each of these items a "rule". For example, if `foo-application` uses both TOML and YAML configuration files, we could write something like this: ```toml # 30-foo-application.toml [mappings] "TOML" = [ # rules for TOML syntax go here "/usr/share/foo-application/toml-config/*.conf", "/etc/foo-application/toml-config/*.conf", ] "YAML" = [ # rules for YAML syntax go here # ... ] ``` ### Dynamic environment variable replacement In additional to the standard glob matcher syntax, rules also support dynamic replacement of environment variables at runtime. This allows us to concisely handle things like [XDG](https://specifications.freedesktop.org/basedir-spec/latest/). All environment variables intended to be replaced at runtime must be enclosed in `${}`, for example `"/foo/*/${YOUR_ENV}-suffix/*.log"`. Note that this is the **only** admissible syntax; other variable substitution syntaxes are not supported and will either cause a compile time error, or be treated as plain text. For example, if `foo-application` also supports per-user configuration files, we could write something like this: ```toml # 30-foo-application.toml [mappings] "TOML" = [ # rules for TOML syntax go here "/usr/share/foo-application/toml-config/*.conf", "/etc/foo-application/toml-config/*.conf", "${XDG_CONFIG_HOME}/foo-application/toml-config/*.conf", "${HOME}/.config/foo-application/toml-config/*.conf", ] "YAML" = [ # rules for YAML syntax go here # ... ] ``` If any environment variable replacement in a rule fails (for example when a variable is unset), or if the glob string after replacements is invalid, the entire rule will be ignored. ### Explicitly mapping to unknown Sometimes it may be necessary to "unset" a particular syntect mapping - perhaps a syntax's matching rules are "too greedy", and is claiming files that it should not. In this case, there are two special identifiers: `MappingTarget::MapToUnknown` and `MappingTarget::MapExtensionToUnknown` (corresponding to the two variants of the `syntax_mapping::MappingTarget` enum). An example of this would be `*.conf` files in general. So we may write something like this: ```toml # 99-unset-ambiguous-extensions.toml [mappings] "MappingTarget::MapExtensionToUnknown" = [ "*.conf", ] ``` ## Ordering At compile time, all TOML files applicable to the target are processed in lexicographical filename order. So `00-foo.toml` takes precedence over `10-bar.toml`, which takes precedence over `20-baz.toml`, and so on. Note that **only** the filenames of the TOML files are taken into account; the subdirectories they are placed in have no influence on ordering. This behaviour can be occasionally useful for creating high/low priority rules, such as in the aforementioned example of explicitly mapping `*.conf` files to unknown. Generally this should not be much of a concern though, since rules should be written as specifically as possible for each application. Rules within each TOML file are processed (and therefore matched) in the order in which they are defined. At runtime, the syntax selection algorithm will short-circuit and return the target of the first matching rule. ================================================ FILE: src/syntax_mapping/builtins/bsd-family/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/builtins/bsd-family/50-os-release.toml ================================================ [mappings] "Bourne Again Shell (bash)" = ["/etc/os-release", "/var/run/os-release"] ================================================ FILE: src/syntax_mapping/builtins/common/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/builtins/common/50-apache.toml ================================================ [mappings] "Apache Conf" = ["httpd.conf"] ================================================ FILE: src/syntax_mapping/builtins/common/50-aws-credentials.toml ================================================ [mappings] "INI" = ["**/.aws/credentials", "**/.aws/config"] ================================================ FILE: src/syntax_mapping/builtins/common/50-bat.toml ================================================ [mappings] "Bourne Again Shell (bash)" = ["**/bat/config"] ================================================ FILE: src/syntax_mapping/builtins/common/50-citation.toml ================================================ [mappings] "YAML" = ["CITATION.cff"] ================================================ FILE: src/syntax_mapping/builtins/common/50-container.toml ================================================ [mappings] "Dockerfile" = ["Containerfile"] ================================================ FILE: src/syntax_mapping/builtins/common/50-cpp.toml ================================================ [mappings] "C++" = [ # probably better than the default Objective C mapping #877 "*.h", ] "YAML" = [".clang-format"] ================================================ FILE: src/syntax_mapping/builtins/common/50-diff.toml ================================================ # .debdiff is the extension used for diffs in Debian packaging [mappings] "Diff" = ["*.debdiff"] ================================================ FILE: src/syntax_mapping/builtins/common/50-dotnet-xml.toml ================================================ [mappings] "XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets"] ================================================ FILE: src/syntax_mapping/builtins/common/50-f-sharp.toml ================================================ [mappings] "F#" = ["*.fs"] ================================================ FILE: src/syntax_mapping/builtins/common/50-gcloud-cli-config.toml ================================================ [mappings] "INI" = [".boto", "**/gcloud/configurations/config_*"] "Git Ignore" = [".gcloudignore"] ================================================ FILE: src/syntax_mapping/builtins/common/50-git.toml ================================================ # Global git config files rooted in `$XDG_CONFIG_HOME/git/` or `$HOME/.config/git/` # See e.g. https://git-scm.com/docs/git-config#FILES [mappings] "Git Config" = ["${XDG_CONFIG_HOME}/git/config", "${HOME}/.config/git/config"] "Git Ignore" = ["${XDG_CONFIG_HOME}/git/ignore", "${HOME}/.config/git/ignore"] "Git Attributes" = [ "${XDG_CONFIG_HOME}/git/attributes", "${HOME}/.config/git/attributes", ] ================================================ FILE: src/syntax_mapping/builtins/common/50-json.toml ================================================ # JSON Lines is a simple variation of JSON #2535 [mappings] "JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson", "*.ndjson"] ================================================ FILE: src/syntax_mapping/builtins/common/50-markdown.toml ================================================ [mappings] "Markdown" = ["*.mkd"] ================================================ FILE: src/syntax_mapping/builtins/common/50-mill.toml ================================================ [mappings] "Scala" = ["*.mill"] ================================================ FILE: src/syntax_mapping/builtins/common/50-nginx.toml ================================================ [mappings] "nginx" = ["nginx.conf", "mime.types"] ================================================ FILE: src/syntax_mapping/builtins/common/50-nix.toml ================================================ [mappings] "JSON" = ["flake.lock"] ================================================ FILE: src/syntax_mapping/builtins/common/50-nmap.toml ================================================ [mappings] # See #2151, https://nmap.org/book/nse-language.html "Lua" = ["*.nse"] ================================================ FILE: src/syntax_mapping/builtins/common/50-proxy-auto-config.toml ================================================ # 1515 [mappings] "JavaScript (Babel)" = ["*.pac"] ================================================ FILE: src/syntax_mapping/builtins/common/50-ron.toml ================================================ # Rusty Object Notation #2427 [mappings] "Rust" = ["*.ron"] ================================================ FILE: src/syntax_mapping/builtins/common/50-sarif.toml ================================================ # SARIF is a format for reporting static analysis results #2695 [mappings] "JSON" = ["*.sarif"] ================================================ FILE: src/syntax_mapping/builtins/common/50-ssh.toml ================================================ [mappings] "SSH Config" = ["**/.ssh/config"] ================================================ FILE: src/syntax_mapping/builtins/common/90-ignore-files.toml ================================================ [mappings] "Git Ignore" = [".?*ignore"] ================================================ FILE: src/syntax_mapping/builtins/common/99-unset-ambiguous-extensions.toml ================================================ [mappings] "MappingTarget::MapExtensionToUnknown" = [ # common extension used for all kinds of formats "*.conf", ] ================================================ FILE: src/syntax_mapping/builtins/common/99-unset-ambiguous-filenames.toml ================================================ [mappings] "MappingTarget::MapToUnknown" = [ # "NAnt Build File" should only match *.build files, not files named "build" "build", # "bin/rails" scripts in a Ruby project misidentified as HTML (Rails) #1008 "rails", ] ================================================ FILE: src/syntax_mapping/builtins/common/xonsh.toml ================================================ # Xonsh shell (https://xon.sh/) [mappings] "Python" = ["*.xsh", "*.xonshrc"] ================================================ FILE: src/syntax_mapping/builtins/linux/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/builtins/linux/50-containers.toml ================================================ # see https://github.com/containers/image/tree/main/docs [mappings] "TOML" = [ "/usr/share/containers/**/*.conf", "/etc/containers/**/*.conf", "${HOME}/.config/containers/**/*.conf", "${XDG_CONFIG_HOME}/containers/**/*.conf", ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-flatpak.toml ================================================ [mappings] "INI" = [ "*.flatpakref", "*.flatpakrepo" ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-kubernetes.toml ================================================ [mappings] "YAML" = ["/etc/kubernetes/*.conf"] ================================================ FILE: src/syntax_mapping/builtins/linux/50-os-release.toml ================================================ [mappings] "Bourne Again Shell (bash)" = [ "/etc/os-release", "/usr/lib/os-release", "/etc/initrd-release", "/usr/lib/extension-release.d/extension-release.*", ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-pacman.toml ================================================ [mappings] "INI" = [ # config "/etc/pacman.conf", # hooks "/usr/share/libalpm/hooks/*.hook", "/etc/pacman.d/hooks/*.hook", ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-paru.toml ================================================ # See https://github.com/Morganamilo/paru/blob/master/man/paru.conf.5 [mappings] "INI" = [ "${PARU_CONF}", "paru.conf", ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-podman-quadlet.toml ================================================ # see `man quadlet` [mappings] "INI" = [ "**/containers/systemd/**/*.{container,volume,network,kube,image,build,pod,artifact}", ] ================================================ FILE: src/syntax_mapping/builtins/linux/50-systemd.toml ================================================ [mappings] "INI" = [ "**/systemd/**/*.conf", "**/systemd/**/*.example", "*.automount", "*.device", "*.dnssd", "*.link", "*.mount", "*.netdev", "*.network", "*.nspawn", "*.path", "*.service", "*.scope", "*.slice", "*.socket", "*.swap", "*.target", "*.timer", ] ================================================ FILE: src/syntax_mapping/builtins/macos/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/builtins/unix-family/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-apache.toml ================================================ [mappings] "Apache Conf" = ["/etc/apache2/**/*.conf", "/etc/apache2/sites-*/**/*", "/etc/httpd/conf/**/*.conf"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-certbot.toml ================================================ # See https://eff-certbot.readthedocs.io/en/stable/using.html#configuration-file [mappings] "INI" = ["/etc/letsencrypt/renewal/*.conf"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-fish-shell.toml ================================================ [mappings] "YAML" = ["fish_history"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-korn-shell.toml ================================================ # KornShell is backward-compatible with the Bourne shell #2633 [mappings] "Bourne Again Shell (bash)" = [ "*.ksh", "*.kshrc" ] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-mail-spool.toml ================================================ [mappings] "Email" = ["/var/spool/mail/*", "/var/mail/*"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-nginx.toml ================================================ [mappings] "nginx" = ["/etc/nginx/**/*.conf", "/etc/nginx/sites-*/**/*"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-shell.toml ================================================ [mappings] "Bourne Again Shell (bash)" = [ # used by lots of shells "/etc/profile", "bashrc", "*.bashrc", "bash_profile", "*.bash_profile", "bash_login", "*.bash_login", "bash_logout", "*.bash_logout", "zshrc", "*.zshrc", "zprofile", "*.zprofile", "zlogin", "*.zlogin", "zlogout", "*.zlogout", "zshenv", "*.zshenv" ] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-syslog.toml ================================================ [mappings] "Syslog" = ["/var/log/dmesg"] ================================================ FILE: src/syntax_mapping/builtins/unix-family/50-wireguard.toml ================================================ # see `man wg-quick` [mappings] "INI" = ["/etc/wireguard/*.conf"] ================================================ FILE: src/syntax_mapping/builtins/windows/.gitkeep ================================================ ================================================ FILE: src/syntax_mapping/ignored_suffixes.rs ================================================ use std::ffi::OsStr; use std::fmt::Debug; use std::path::Path; use crate::error::*; #[derive(Debug, Clone)] pub struct IgnoredSuffixes<'a> { values: Vec<&'a str>, } impl Default for IgnoredSuffixes<'_> { fn default() -> Self { Self { values: vec![ // Editor etc backups "~", ".bak", ".old", ".orig", // Debian and derivatives apt/dpkg/ucf backups ".dpkg-dist", ".dpkg-new", ".dpkg-old", ".dpkg-tmp", ".ucf-dist", ".ucf-new", ".ucf-old", // Red Hat and derivatives rpm backups ".rpmnew", ".rpmorig", ".rpmsave", // Build system input/template files ".in", ], } } } impl<'a> IgnoredSuffixes<'a> { pub fn add_suffix(&mut self, suffix: &'a str) { self.values.push(suffix) } pub fn strip_suffix(&self, file_name: &'a str) -> Option<&'a str> { for suffix in self.values.iter() { if let Some(stripped_file_name) = file_name.strip_suffix(suffix) { return Some(stripped_file_name); } } None } /// If we find an ignored suffix on the file name, e.g. '~', we strip it and /// then try again without it. pub fn try_with_stripped_suffix(&self, file_name: &'a OsStr, func: F) -> Result> where F: Fn(&'a OsStr) -> Result>, { if let Some(file_str) = Path::new(file_name).to_str() { if let Some(stripped_file_name) = self.strip_suffix(file_str) { return func(OsStr::new(stripped_file_name)); } } Ok(None) } } #[test] fn internal_suffixes() { let ignored_suffixes = IgnoredSuffixes::default(); let file_names = ignored_suffixes .values .iter() .map(|suffix| format!("test.json{suffix}")); for file_name_str in file_names { let file_name = OsStr::new(&file_name_str); let expected_stripped_file_name = OsStr::new("test.json"); let stripped_file_name = ignored_suffixes .try_with_stripped_suffix(file_name, |stripped_file_name| Ok(Some(stripped_file_name))); assert_eq!( expected_stripped_file_name, stripped_file_name.unwrap().unwrap() ); } } #[test] fn external_suffixes() { let mut ignored_suffixes = IgnoredSuffixes::default(); ignored_suffixes.add_suffix(".development"); ignored_suffixes.add_suffix(".production"); let file_names = ignored_suffixes .values .iter() .map(|suffix| format!("test.json{suffix}")); for file_name_str in file_names { let file_name = OsStr::new(&file_name_str); let expected_stripped_file_name = OsStr::new("test.json"); let stripped_file_name = ignored_suffixes .try_with_stripped_suffix(file_name, |stripped_file_name| Ok(Some(stripped_file_name))); assert_eq!( expected_stripped_file_name, stripped_file_name.unwrap().unwrap() ); } } ================================================ FILE: src/syntax_mapping.rs ================================================ use std::{ path::Path, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, thread, }; use globset::{Candidate, GlobBuilder, GlobMatcher}; use once_cell::sync::Lazy; use crate::error::Result; use builtin::BUILTIN_MAPPINGS; use ignored_suffixes::IgnoredSuffixes; mod builtin; pub mod ignored_suffixes; fn make_glob_matcher(from: &str) -> Result { let matcher = GlobBuilder::new(from) .case_insensitive(true) .literal_separator(true) .build()? .compile_matcher(); Ok(matcher) } #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub enum MappingTarget<'a> { /// For mapping a path to a specific syntax. MapTo(&'a str), /// For mapping a path (typically an extension-less file name) to an unknown /// syntax. This typically means later using the contents of the first line /// of the file to determine what syntax to use. MapToUnknown, /// For mapping a file extension (e.g. `*.conf`) to an unknown syntax. This /// typically means later using the contents of the first line of the file /// to determine what syntax to use. However, if a syntax handles a file /// name that happens to have the given file extension (e.g. `resolv.conf`), /// then that association will have higher precedence, and the mapping will /// be ignored. MapExtensionToUnknown, } #[derive(Debug, Clone, Default)] pub struct SyntaxMapping<'a> { /// User-defined mappings at run time. /// /// Rules in front have precedence. custom_mappings: Vec<(GlobMatcher, MappingTarget<'a>)>, pub(crate) ignored_suffixes: IgnoredSuffixes<'a>, /// A flag to halt glob matcher building, which is offloaded to another thread. /// /// We have this so that we can signal the thread to halt early when appropriate. halt_glob_build: Arc, } impl Drop for SyntaxMapping<'_> { fn drop(&mut self) { // signal the offload thread to halt early self.halt_glob_build.store(true, Ordering::Relaxed); } } impl<'a> SyntaxMapping<'a> { pub fn new() -> SyntaxMapping<'a> { Default::default() } /// Start a thread to build the glob matchers for all builtin mappings. /// /// The use of this function while not necessary, is useful to speed up startup /// times by starting this work early in parallel. /// /// The thread halts if/when `halt_glob_build` is set to true. pub fn start_offload_build_all(&self) { let halt = Arc::clone(&self.halt_glob_build); thread::spawn(move || { for (matcher, _) in BUILTIN_MAPPINGS.iter() { if halt.load(Ordering::Relaxed) { break; } Lazy::force(matcher); } }); // Note that this thread is not joined upon completion because there's // no shared resources that need synchronization to be safely dropped. // If we later add code into this thread that requires interesting // resources (e.g. IO), it would be a good idea to store the handle // and join it on drop. } pub fn insert(&mut self, from: &str, to: MappingTarget<'a>) -> Result<()> { let matcher = make_glob_matcher(from)?; self.custom_mappings.push((matcher, to)); Ok(()) } /// Returns an iterator over all mappings. User-defined mappings are listed /// before builtin mappings; mappings in front have higher precedence. /// /// Builtin mappings' `GlobMatcher`s are lazily compiled. /// /// Note that this function only returns mappings that are valid under the /// current environment. For details see [`Self::builtin_mappings`]. pub fn all_mappings(&self) -> impl Iterator)> { self.custom_mappings() .iter() .map(|(matcher, target)| (matcher, target)) // as_ref .chain( // we need a map with a closure to "do" the lifetime variance // see: https://discord.com/channels/273534239310479360/1120124565591425034/1170543402870382653 // also, clippy false positive: // see: https://github.com/rust-lang/rust-clippy/issues/9280 #[allow(clippy::map_identity)] self.builtin_mappings().map(|rule| rule), ) } /// Returns an iterator over all valid builtin mappings. Mappings in front /// have higher precedence. /// /// The `GlabMatcher`s are lazily compiled. /// /// Mappings that are invalid under the current environment (i.e. rule /// requires environment variable(s) that is unset, or the joined string /// after variable(s) replacement is not a valid glob expression) are /// ignored. pub fn builtin_mappings( &self, ) -> impl Iterator)> { BUILTIN_MAPPINGS .iter() .filter_map(|(matcher, target)| matcher.as_ref().map(|glob| (glob, target))) } /// Returns all user-defined mappings. pub fn custom_mappings(&self) -> &[(GlobMatcher, MappingTarget<'a>)] { &self.custom_mappings } pub fn get_syntax_for(&self, path: impl AsRef) -> Option> { // Try matching on the file name as-is. let candidate = Candidate::new(&path); let candidate_filename = path.as_ref().file_name().map(Candidate::new); for (glob, syntax) in self.all_mappings() { if glob.is_match_candidate(&candidate) || candidate_filename .as_ref() .is_some_and(|filename| glob.is_match_candidate(filename)) { return Some(*syntax); } } // Try matching on the file name after removing an ignored suffix. let file_name = path.as_ref().file_name()?; self.ignored_suffixes .try_with_stripped_suffix(file_name, |stripped_file_name| { Ok(self.get_syntax_for(stripped_file_name)) }) .ok()? } pub fn insert_ignored_suffix(&mut self, suffix: &'a str) { self.ignored_suffixes.add_suffix(suffix); } } #[cfg(test)] mod tests { use super::*; #[test] fn builtin_mappings_work() { let map = SyntaxMapping::new(); assert_eq!( map.get_syntax_for("/path/to/build"), Some(MappingTarget::MapToUnknown) ); } #[test] fn all_fixed_builtin_mappings_can_compile() { let map = SyntaxMapping::new(); // collect call evaluates all lazy closures // fixed builtin mappings will panic if they fail to compile let _mappings = map.builtin_mappings().collect::>(); } #[test] fn builtin_mappings_matcher_only_compile_once() { let map = SyntaxMapping::new(); let two_iterations: Vec<_> = (0..2) .map(|_| { // addresses of every matcher map.builtin_mappings() .map(|(matcher, _)| matcher as *const _ as usize) .collect::>() }) .collect(); // if the matchers are only compiled once, their address should remain the same assert_eq!(two_iterations[0], two_iterations[1]); } #[test] fn custom_mappings_work() { let mut map = SyntaxMapping::new(); map.insert("/path/to/Cargo.lock", MappingTarget::MapTo("TOML")) .ok(); map.insert("/path/to/.ignore", MappingTarget::MapTo("Git Ignore")) .ok(); assert_eq!( map.get_syntax_for("/path/to/Cargo.lock"), Some(MappingTarget::MapTo("TOML")) ); assert_eq!(map.get_syntax_for("/path/to/other.lock"), None); assert_eq!( map.get_syntax_for("/path/to/.ignore"), Some(MappingTarget::MapTo("Git Ignore")) ); } #[test] fn custom_mappings_override_builtin() { let mut map = SyntaxMapping::new(); assert_eq!( map.get_syntax_for("/path/to/httpd.conf"), Some(MappingTarget::MapTo("Apache Conf")) ); map.insert("httpd.conf", MappingTarget::MapTo("My Syntax")) .ok(); assert_eq!( map.get_syntax_for("/path/to/httpd.conf"), Some(MappingTarget::MapTo("My Syntax")) ); } #[test] fn custom_mappings_precedence() { let mut map = SyntaxMapping::new(); map.insert("/path/to/foo", MappingTarget::MapTo("alpha")) .ok(); map.insert("/path/to/foo", MappingTarget::MapTo("bravo")) .ok(); assert_eq!( map.get_syntax_for("/path/to/foo"), Some(MappingTarget::MapTo("alpha")) ); } } ================================================ FILE: src/terminal.rs ================================================ use nu_ansi_term::Color::{self, Fixed, Rgb}; use nu_ansi_term::{self, Style}; use syntect::highlighting::{self, FontStyle}; pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> Option { if color.a == 0 { // Themes can specify one of the user-configurable terminal colors by // encoding them as #RRGGBBAA with AA set to 00 (transparent) and RR set // to the 8-bit color palette number. The built-in themes ansi, base16, // and base16-256 use this. Some(match color.r { // For the first 8 colors, use the Color enum to produce ANSI escape // sequences using codes 30-37 (foreground) and 40-47 (background). // For example, red foreground is \x1b[31m. This works on terminals // without 256-color support. 0x00 => Color::Black, 0x01 => Color::Red, 0x02 => Color::Green, 0x03 => Color::Yellow, 0x04 => Color::Blue, 0x05 => Color::Purple, 0x06 => Color::Cyan, 0x07 => Color::White, // For all other colors, use Fixed to produce escape sequences using // codes 38;5 (foreground) and 48;5 (background). For example, // bright red foreground is \x1b[38;5;9m. This only works on // terminals with 256-color support. // // TODO: When ansi_term adds support for bright variants using codes // 90-97 (foreground) and 100-107 (background), we should use those // for values 0x08 to 0x0f and only use Fixed for 0x10 to 0xff. n => Fixed(n), }) } else if color.a == 1 { // Themes can specify the terminal's default foreground/background color // (i.e. no escape sequence) using the encoding #RRGGBBAA with AA set to // 01. The built-in theme ansi uses this. None } else if true_color { Some(Rgb(color.r, color.g, color.b)) } else { Some(Fixed(ansi_colours::ansi256_from_rgb(( color.r, color.g, color.b, )))) } } pub fn as_terminal_escaped( style: highlighting::Style, text: &str, true_color: bool, colored: bool, italics: bool, background_color: Option, ) -> String { if text.is_empty() { return text.to_string(); } let mut style = if !colored { Style::default() } else { let mut color = Style { foreground: to_ansi_color(style.foreground, true_color), ..Style::default() }; if style.font_style.contains(FontStyle::BOLD) { color = color.bold(); } if style.font_style.contains(FontStyle::UNDERLINE) { color = color.underline(); } if italics && style.font_style.contains(FontStyle::ITALIC) { color = color.italic(); } color }; style.background = background_color.and_then(|c| to_ansi_color(c, true_color)); style.paint(text).to_string() } ================================================ FILE: src/theme.rs ================================================ //! Utilities for choosing an appropriate theme for syntax highlighting. use std::convert::Infallible; use std::fmt; use std::io::IsTerminal as _; use std::str::FromStr; /// Environment variable names. pub mod env { /// See [`crate::theme::ThemeOptions::theme`]. pub const BAT_THEME: &str = "BAT_THEME"; /// See [`crate::theme::ThemeOptions::theme_dark`]. pub const BAT_THEME_DARK: &str = "BAT_THEME_DARK"; /// See [`crate::theme::ThemeOptions::theme_light`]. pub const BAT_THEME_LIGHT: &str = "BAT_THEME_LIGHT"; } /// Chooses an appropriate theme or falls back to a default theme /// based on the user-provided options and the color scheme of the terminal. /// /// Intentionally returns a [`ThemeResult`] instead of a simple string so /// that downstream consumers such as `delta` can easily apply their own /// default theme and can use the detected color scheme elsewhere. pub fn theme(options: ThemeOptions) -> ThemeResult { theme_impl(options, &TerminalColorSchemeDetector) } /// The default theme, suitable for the given color scheme. /// Use [`theme`] if you want to automatically detect the color scheme from the terminal. pub const fn default_theme(color_scheme: ColorScheme) -> &'static str { match color_scheme { ColorScheme::Dark => "Monokai Extended", ColorScheme::Light => "Monokai Extended Light", } } /// Detects the color scheme from the terminal. pub fn color_scheme(when: DetectColorScheme) -> Option { color_scheme_impl(when, &TerminalColorSchemeDetector) } /// Options for configuring the theme used for syntax highlighting. /// Used together with [`theme`]. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct ThemeOptions { /// Configures how the theme is chosen. If set to a [`ThemePreference::Fixed`] value, /// then the given theme is used regardless of the terminal's background color. /// This corresponds with the `BAT_THEME` environment variable and the `--theme` option. pub theme: ThemePreference, /// The theme to use in case the terminal uses a dark background with light text. /// This corresponds with the `BAT_THEME_DARK` environment variable and the `--theme-dark` option. pub theme_dark: Option, /// The theme to use in case the terminal uses a light background with dark text. /// This corresponds with the `BAT_THEME_LIGHT` environment variable and the `--theme-light` option. pub theme_light: Option, } /// What theme should `bat` use? /// /// The easiest way to construct this is from a string: /// ``` /// # use bat::theme::{ThemePreference, DetectColorScheme}; /// let preference = ThemePreference::new("auto:system"); /// assert_eq!(ThemePreference::Auto(DetectColorScheme::System), preference); /// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ThemePreference { /// Choose between [`ThemeOptions::theme_dark`] and [`ThemeOptions::theme_light`] /// based on the terminal's color scheme. Auto(DetectColorScheme), /// Always use the same theme regardless of the terminal's color scheme. Fixed(ThemeName), /// Use a dark theme. Dark, /// Use a light theme. Light, } impl Default for ThemePreference { fn default() -> Self { ThemePreference::Auto(Default::default()) } } impl ThemePreference { /// Creates a theme preference from a string. pub fn new(s: impl Into) -> Self { use ThemePreference::*; let s = s.into(); match s.as_str() { "auto" => Auto(Default::default()), "auto:always" => Auto(DetectColorScheme::Always), "auto:system" => Auto(DetectColorScheme::System), "dark" => Dark, "light" => Light, _ => Fixed(ThemeName::new(s)), } } } impl FromStr for ThemePreference { type Err = Infallible; fn from_str(s: &str) -> Result { Ok(ThemePreference::new(s)) } } impl fmt::Display for ThemePreference { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use ThemePreference::*; match self { Auto(DetectColorScheme::Auto) => f.write_str("auto"), Auto(DetectColorScheme::Always) => f.write_str("auto:always"), Auto(DetectColorScheme::System) => f.write_str("auto:system"), Fixed(theme) => theme.fmt(f), Dark => f.write_str("dark"), Light => f.write_str("light"), } } } /// The name of a theme or the default theme. /// /// ``` /// # use bat::theme::ThemeName; /// assert_eq!(ThemeName::Default, ThemeName::new("default")); /// assert_eq!(ThemeName::Named("example".to_string()), ThemeName::new("example")); /// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ThemeName { Named(String), Default, } impl ThemeName { /// Creates a theme name from a string. pub fn new(s: impl Into) -> Self { let s = s.into(); if s == "default" { ThemeName::Default } else { ThemeName::Named(s) } } } impl FromStr for ThemeName { type Err = Infallible; fn from_str(s: &str) -> Result { Ok(ThemeName::new(s)) } } impl fmt::Display for ThemeName { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ThemeName::Named(t) => f.write_str(t), ThemeName::Default => f.write_str("default"), } } } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] pub enum DetectColorScheme { /// Only query the terminal for its colors when appropriate (i.e. when the output is not redirected). #[default] Auto, /// Always query the terminal for its colors. Always, /// Detect the system-wide dark/light preference (macOS only). System, } /// The color scheme used to pick a fitting theme. Defaults to [`ColorScheme::Dark`]. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] pub enum ColorScheme { #[default] Dark, Light, } /// The resolved theme and the color scheme as determined from /// the terminal, OS or fallback. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ThemeResult { /// The theme selected according to the [`ThemeOptions`]. pub theme: ThemeName, /// Either the user's chosen color scheme, the terminal's color scheme, the OS's /// color scheme or `None` if the color scheme was not detected because the user chose a fixed theme. pub color_scheme: Option, } impl fmt::Display for ThemeResult { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.theme { ThemeName::Named(name) => f.write_str(name), ThemeName::Default => f.write_str(default_theme(self.color_scheme.unwrap_or_default())), } } } fn theme_impl(options: ThemeOptions, detector: &dyn ColorSchemeDetector) -> ThemeResult { // Implementation note: This function is mostly pure (i.e. it has no side effects) for the sake of testing. // All the side effects (e.g. querying the terminal for its colors) are performed in the detector. match options.theme { ThemePreference::Fixed(theme) => ThemeResult { theme, color_scheme: None, }, ThemePreference::Dark => choose_theme_opt(Some(ColorScheme::Dark), options), ThemePreference::Light => choose_theme_opt(Some(ColorScheme::Light), options), ThemePreference::Auto(when) => choose_theme_opt(color_scheme_impl(when, detector), options), } } fn choose_theme_opt(color_scheme: Option, options: ThemeOptions) -> ThemeResult { ThemeResult { color_scheme, theme: color_scheme .and_then(|c| choose_theme(options, c)) .unwrap_or(ThemeName::Default), } } fn choose_theme(options: ThemeOptions, color_scheme: ColorScheme) -> Option { match color_scheme { ColorScheme::Dark => options.theme_dark, ColorScheme::Light => options.theme_light, } } fn color_scheme_impl( when: DetectColorScheme, detector: &dyn ColorSchemeDetector, ) -> Option { let should_detect = match when { DetectColorScheme::Auto => detector.should_detect(), DetectColorScheme::Always => true, DetectColorScheme::System => return color_scheme_from_system(), }; should_detect.then(|| detector.detect()).flatten() } trait ColorSchemeDetector { fn should_detect(&self) -> bool; fn detect(&self) -> Option; } struct TerminalColorSchemeDetector; impl ColorSchemeDetector for TerminalColorSchemeDetector { fn should_detect(&self) -> bool { // Querying the terminal for its colors via OSC 10 / OSC 11 requires "exclusive" access // since we read/write from the terminal and enable/disable raw mode. // This causes race conditions with pagers such as less when they are attached to the // same terminal as us. // // This is usually only an issue when the output is manually piped to a pager. // For example: `bat Cargo.toml | less`. // Otherwise, if we start the pager ourselves, then there's no race condition // since the pager is started *after* the color is detected. std::io::stdout().is_terminal() } fn detect(&self) -> Option { use terminal_colorsaurus::{theme_mode, QueryOptions, ThemeMode}; match theme_mode(QueryOptions::default()).ok()? { ThemeMode::Dark => Some(ColorScheme::Dark), ThemeMode::Light => Some(ColorScheme::Light), } } } #[cfg(not(target_os = "macos"))] fn color_scheme_from_system() -> Option { crate::bat_warning!( "Theme 'auto:system' is only supported on macOS, \ using default." ); None } #[cfg(target_os = "macos")] fn color_scheme_from_system() -> Option { const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist"; const STYLE_KEY: &str = "AppleInterfaceStyle"; let preferences_file = std::env::home_dir() .map(|home| home.join(PREFERENCES_FILE)) .expect("Could not get home directory"); match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) { Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) { Some("Dark") => Some(ColorScheme::Dark), // If the key does not exist, then light theme is currently in use. Some(_) | None => Some(ColorScheme::Light), }, // Unreachable, in theory. All macOS users have a home directory and preferences file setup. Ok(None) | Err(_) => None, } } #[cfg(test)] impl ColorSchemeDetector for Option { fn should_detect(&self) -> bool { true } fn detect(&self) -> Option { *self } } #[cfg(test)] mod tests { use super::ColorScheme::*; use super::*; use std::cell::Cell; use std::iter; mod color_scheme_detection { use super::*; #[test] fn not_called_for_dark_or_light() { for theme in [ThemePreference::Dark, ThemePreference::Light] { let detector = DetectorStub::should_detect(Some(Dark)); let options = ThemeOptions { theme, ..Default::default() }; _ = theme_impl(options, &detector); assert!(!detector.was_called.get()); } } #[test] fn called_for_always() { let detectors = [ DetectorStub::should_detect(Some(Dark)), DetectorStub::should_not_detect(), ]; for detector in detectors { let options = ThemeOptions { theme: ThemePreference::Auto(DetectColorScheme::Always), ..Default::default() }; _ = theme_impl(options, &detector); assert!(detector.was_called.get()); } } #[test] fn called_for_auto_if_should_detect() { let detector = DetectorStub::should_detect(Some(Dark)); _ = theme_impl(ThemeOptions::default(), &detector); assert!(detector.was_called.get()); } #[test] fn not_called_for_auto_if_not_should_detect() { let detector = DetectorStub::should_not_detect(); _ = theme_impl(ThemeOptions::default(), &detector); assert!(!detector.was_called.get()); } } mod precedence { use super::*; #[test] fn theme_is_preferred_over_light_or_dark_themes() { for color_scheme in optional(color_schemes()) { for options in [ ThemeOptions { theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), ..Default::default() }, ThemeOptions { theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), theme_dark: Some(ThemeName::Named("Dark Theme".to_string())), theme_light: Some(ThemeName::Named("Light Theme".to_string())), }, ] { let detector = ConstantDetector(color_scheme); assert_eq!("Theme", theme_impl(options, &detector).to_string()); } } } #[test] fn detector_is_not_called_if_theme_is_present() { let options = ThemeOptions { theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), ..Default::default() }; let detector = DetectorStub::should_detect(Some(Dark)); _ = theme_impl(options, &detector); assert!(!detector.was_called.get()); } } mod default_theme { use super::*; #[test] fn default_dark_if_unable_to_detect_color_scheme() { let detector = ConstantDetector(None); assert_eq!( default_theme(ColorScheme::Dark), theme_impl(ThemeOptions::default(), &detector).to_string() ); } // For backwards compatibility, if the default theme is requested // explicitly through BAT_THEME, we always pick the default dark theme. #[test] fn default_dark_if_requested_explicitly_through_theme() { for color_scheme in optional(color_schemes()) { let options = ThemeOptions { theme: ThemePreference::Fixed(ThemeName::Default), ..Default::default() }; let detector = ConstantDetector(color_scheme); assert_eq!( default_theme(ColorScheme::Dark), theme_impl(options, &detector).to_string() ); } } #[test] fn varies_depending_on_color_scheme() { for color_scheme in color_schemes() { for options in [ ThemeOptions::default(), ThemeOptions { theme_dark: Some(ThemeName::Default), theme_light: Some(ThemeName::Default), ..Default::default() }, ] { let detector = ConstantDetector(Some(color_scheme)); assert_eq!( default_theme(color_scheme), theme_impl(options, &detector).to_string() ); } } } } mod choosing { use super::*; #[test] fn chooses_default_theme_if_unknown() { let options = ThemeOptions { theme_dark: Some(ThemeName::Named("Dark".to_string())), theme_light: Some(ThemeName::Named("Light".to_string())), ..Default::default() }; let detector = ConstantDetector(None); assert_eq!( default_theme(ColorScheme::default()), theme_impl(options, &detector).to_string() ); } #[test] fn chooses_dark_theme_if_dark_or_unknown() { let options = ThemeOptions { theme_dark: Some(ThemeName::Named("Dark".to_string())), theme_light: Some(ThemeName::Named("Light".to_string())), ..Default::default() }; let detector = ConstantDetector(Some(ColorScheme::Dark)); assert_eq!("Dark", theme_impl(options, &detector).to_string()); } #[test] fn chooses_light_theme_if_light() { let options = ThemeOptions { theme_dark: Some(ThemeName::Named("Dark".to_string())), theme_light: Some(ThemeName::Named("Light".to_string())), ..Default::default() }; let detector = ConstantDetector(Some(ColorScheme::Light)); assert_eq!("Light", theme_impl(options, &detector).to_string()); } } mod theme_preference { use super::*; #[test] fn values_roundtrip_via_display() { let prefs = [ ThemePreference::Auto(DetectColorScheme::Auto), ThemePreference::Auto(DetectColorScheme::Always), ThemePreference::Auto(DetectColorScheme::System), ThemePreference::Fixed(ThemeName::Default), ThemePreference::Fixed(ThemeName::new("foo")), ThemePreference::Dark, ThemePreference::Light, ]; for pref in prefs { assert_eq!(pref, ThemePreference::new(pref.to_string())); } } } struct DetectorStub { should_detect: bool, color_scheme: Option, was_called: Cell, } impl DetectorStub { fn should_detect(color_scheme: Option) -> Self { DetectorStub { should_detect: true, color_scheme, was_called: Cell::default(), } } fn should_not_detect() -> Self { DetectorStub { should_detect: false, color_scheme: None, was_called: Cell::default(), } } } impl ColorSchemeDetector for DetectorStub { fn should_detect(&self) -> bool { self.should_detect } fn detect(&self) -> Option { self.was_called.set(true); self.color_scheme } } struct ConstantDetector(Option); impl ColorSchemeDetector for ConstantDetector { fn should_detect(&self) -> bool { true } fn detect(&self) -> Option { self.0 } } fn optional(value: impl Iterator) -> impl Iterator> { value.map(Some).chain(iter::once(None)) } fn color_schemes() -> impl Iterator { [Dark, Light].into_iter() } } ================================================ FILE: src/vscreen.rs ================================================ use std::{ fmt::{Display, Formatter}, iter::Peekable, str::CharIndices, }; // Wrapper to avoid unnecessary branching when input doesn't have ANSI escape sequences. pub struct AnsiStyle { attributes: Option, } impl AnsiStyle { pub fn new() -> Self { AnsiStyle { attributes: None } } pub fn update(&mut self, sequence: EscapeSequence) -> bool { match &mut self.attributes { Some(a) => a.update(sequence), None => { self.attributes = Some(Attributes::new()); self.attributes.as_mut().unwrap().update(sequence) } } } pub fn to_reset_sequence(&self) -> String { match self.attributes { Some(ref a) => a.to_reset_sequence(), None => String::new(), } } } impl Display for AnsiStyle { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self.attributes { Some(ref a) => a.fmt(f), None => Ok(()), } } } struct Attributes { has_sgr_sequences: bool, foreground: String, background: String, underlined: String, /// The character set to use. /// REGEX: `\^[()][AB0-3]` charset: String, /// A buffer for unknown sequences. unknown_buffer: String, /// ON: ^[1m /// OFF: ^[22m bold: String, /// ON: ^[2m /// OFF: ^[22m dim: String, /// ON: ^[4m /// OFF: ^[24m underline: String, /// ON: ^[3m /// OFF: ^[23m italic: String, /// ON: ^[9m /// OFF: ^[29m strike: String, /// The hyperlink sequence. /// FORMAT: \x1B]8;{ID};{URL}\e\\ /// /// `\e\\` may be replaced with BEL `\x07`. /// Setting both {ID} and {URL} to an empty string represents no hyperlink. hyperlink: String, } impl Attributes { pub fn new() -> Self { Attributes { has_sgr_sequences: false, foreground: "".to_owned(), background: "".to_owned(), underlined: "".to_owned(), charset: "".to_owned(), unknown_buffer: "".to_owned(), bold: "".to_owned(), dim: "".to_owned(), underline: "".to_owned(), italic: "".to_owned(), strike: "".to_owned(), hyperlink: "".to_owned(), } } /// Update the attributes with an escape sequence. /// Returns `false` if the sequence is unsupported. pub fn update(&mut self, sequence: EscapeSequence) -> bool { use EscapeSequence::*; match sequence { Text(_) => return false, Unknown(_) => { /* defer to update_with_unsupported */ } OSC { raw_sequence, command, .. } => { if command.starts_with("8;") { return self.update_with_hyperlink(raw_sequence); } /* defer to update_with_unsupported */ } CSI { final_byte, parameters, .. } => { match final_byte { "m" => return self.update_with_sgr(parameters), _ => { // NOTE(eth-p): We might want to ignore these, since they involve cursor or buffer manipulation. /* defer to update_with_unsupported */ } } } NF { nf_sequence, .. } => { let mut iter = nf_sequence.chars(); match iter.next() { Some('(') => return self.update_with_charset('(', iter), Some(')') => return self.update_with_charset(')', iter), _ => { /* defer to update_with_unsupported */ } } } } self.update_with_unsupported(sequence.raw()) } fn sgr_reset(&mut self) { self.has_sgr_sequences = false; self.foreground.clear(); self.background.clear(); self.underlined.clear(); self.bold.clear(); self.dim.clear(); self.underline.clear(); self.italic.clear(); self.strike.clear(); } fn update_with_sgr(&mut self, parameters: &str) -> bool { let mut iter = parameters .split(';') .map(|p| if p.is_empty() { "0" } else { p }) .map(|p| p.parse::()) .map(|p| p.unwrap_or(0)); // Treat errors as 0. self.has_sgr_sequences = true; while let Some(p) = iter.next() { match p { 0 => self.sgr_reset(), 1 => self.bold = "\x1B[1m".to_owned(), 2 => self.dim = "\x1B[2m".to_owned(), 3 => self.italic = "\x1B[3m".to_owned(), 4 => self.underline = "\x1B[4m".to_owned(), 23 => self.italic.clear(), 24 => self.underline.clear(), 22 => { self.bold.clear(); self.dim.clear(); } 30..=39 => self.foreground = Self::parse_color(p, &mut iter), 40..=49 => self.background = Self::parse_color(p, &mut iter), 58..=59 => self.underlined = Self::parse_color(p, &mut iter), 90..=97 => self.foreground = Self::parse_color(p, &mut iter), 100..=107 => self.background = Self::parse_color(p, &mut iter), _ => { // Unsupported SGR sequence. // Be compatible and pretend one just wasn't was provided. } } } true } fn update_with_unsupported(&mut self, sequence: &str) -> bool { self.unknown_buffer.push_str(sequence); false } fn update_with_hyperlink(&mut self, sequence: &str) -> bool { if sequence == "8;;" { // Empty hyperlink ID and HREF -> end of hyperlink. self.hyperlink.clear(); } else { self.hyperlink.clear(); self.hyperlink.push_str(sequence); } true } fn update_with_charset(&mut self, kind: char, set: impl Iterator) -> bool { self.charset = format!("\x1B{kind}{}", set.take(1).collect::()); true } fn parse_color(color: u16, parameters: &mut dyn Iterator) -> String { match color % 10 { 8 => match parameters.next() { Some(5) /* 256-color */ => format!("\x1B[{color};5;{}m", join(";", 1, parameters)), Some(2) /* 24-bit color */ => format!("\x1B[{color};2;{}m", join(";", 3, parameters)), Some(c) => format!("\x1B[{color};{c}m"), _ => "".to_owned(), }, 9 => "".to_owned(), _ => format!("\x1B[{color}m"), } } /// Gets an ANSI escape sequence to reset all the known attributes. pub fn to_reset_sequence(&self) -> String { let mut buf = String::with_capacity(17); // TODO: Enable me in a later pull request. // if self.has_sgr_sequences { // buf.push_str("\x1B[m"); // } if !self.hyperlink.is_empty() { buf.push_str("\x1B]8;;\x1B\\"); // Disable hyperlink. } // TODO: Enable me in a later pull request. // if !self.charset.is_empty() { // // https://espterm.github.io/docs/VT100%20escape%20codes.html // buf.push_str("\x1B(B\x1B)B"); // setusg0 and setusg1 // } buf } } impl Display for Attributes { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, "{}{}{}{}{}{}{}{}{}{}", self.foreground, self.background, self.underlined, self.charset, self.bold, self.dim, self.underline, self.italic, self.strike, self.hyperlink, ) } } fn join( delimiter: &str, limit: usize, iterator: &mut dyn Iterator, ) -> String { iterator .take(limit) .map(|i| i.to_string()) .collect::>() .join(delimiter) } /// A range of indices for a raw ANSI escape sequence. #[derive(Debug, PartialEq)] pub enum EscapeSequenceOffsets { Text { start: usize, end: usize, }, Unknown { start: usize, end: usize, }, #[allow(clippy::upper_case_acronyms)] NF { // https://en.wikipedia.org/wiki/ANSI_escape_code#nF_Escape_sequences start_sequence: usize, start: usize, end: usize, }, #[allow(clippy::upper_case_acronyms)] OSC { // https://en.wikipedia.org/wiki/ANSI_escape_code#OSC_(Operating_System_Command)_sequences start_sequence: usize, start_command: usize, start_terminator: usize, end: usize, }, #[allow(clippy::upper_case_acronyms)] CSI { // https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences start_sequence: usize, start_parameters: usize, start_intermediates: usize, start_final_byte: usize, end: usize, }, } impl EscapeSequenceOffsets { /// Returns the byte-index of the first character in the escape sequence. pub fn index_of_start(&self) -> usize { use EscapeSequenceOffsets::*; match self { Text { start, .. } => *start, Unknown { start, .. } => *start, NF { start_sequence, .. } => *start_sequence, OSC { start_sequence, .. } => *start_sequence, CSI { start_sequence, .. } => *start_sequence, } } /// Returns the byte-index past the last character in the escape sequence. pub fn index_past_end(&self) -> usize { use EscapeSequenceOffsets::*; match self { Text { end, .. } => *end, Unknown { end, .. } => *end, NF { end, .. } => *end, OSC { end, .. } => *end, CSI { end, .. } => *end, } } } /// An iterator over the offsets of ANSI/VT escape sequences within a string. /// /// ## Example /// /// ```ignore /// let iter = EscapeSequenceOffsetsIterator::new("\x1B[33mThis is yellow text.\x1B[m"); /// ``` pub struct EscapeSequenceOffsetsIterator<'a> { text: &'a str, chars: Peekable>, } impl<'a> EscapeSequenceOffsetsIterator<'a> { pub fn new(text: &'a str) -> EscapeSequenceOffsetsIterator<'a> { EscapeSequenceOffsetsIterator { text, chars: text.char_indices().peekable(), } } /// Takes values from the iterator while the predicate returns true. /// If the predicate returns false, that value is left. fn chars_take_while(&mut self, pred: impl Fn(char) -> bool) -> Option<(usize, usize)> { self.chars.peek()?; let start = self.chars.peek().unwrap().0; let mut end: usize = start; while let Some((i, c)) = self.chars.peek() { if !pred(*c) { break; } end = *i + c.len_utf8(); self.chars.next(); } Some((start, end)) } fn next_text(&mut self) -> Option { self.chars_take_while(|c| c != '\x1B') .map(|(start, end)| EscapeSequenceOffsets::Text { start, end }) } fn next_sequence(&mut self) -> Option { let (start_sequence, c) = self.chars.next().expect("to not be finished"); match self.chars.peek() { None => Some(EscapeSequenceOffsets::Unknown { start: start_sequence, end: start_sequence + c.len_utf8(), }), Some((_, ']')) => self.next_osc(start_sequence), Some((_, '[')) => self.next_csi(start_sequence), Some((i, c)) => match c { '\x20'..='\x2F' => self.next_nf(start_sequence), c => Some(EscapeSequenceOffsets::Unknown { start: start_sequence, end: i + c.len_utf8(), }), }, } } fn next_osc(&mut self, start_sequence: usize) -> Option { let (osc_open_index, osc_open_char) = self.chars.next().expect("to not be finished"); debug_assert_eq!(osc_open_char, ']'); let mut start_terminator: usize; let mut end_sequence: usize; loop { match self.chars_take_while(|c| !matches!(c, '\x07' | '\x1B')) { None => { start_terminator = self.text.len(); end_sequence = start_terminator; break; } Some((_, end)) => { start_terminator = end; end_sequence = end; } } match self.chars.next() { Some((ti, '\x07')) => { end_sequence = ti + '\x07'.len_utf8(); break; } Some((ti, '\x1B')) => { match self.chars.next() { Some((i, '\\')) => { end_sequence = i + '\\'.len_utf8(); break; } None => { end_sequence = ti + '\x1B'.len_utf8(); break; } _ => { // Repeat, since `\\`(anything) isn't a valid ST. } } } None => { // Prematurely ends. break; } Some((_, tc)) => { panic!("this should not be reached: char {tc:?}") } } } Some(EscapeSequenceOffsets::OSC { start_sequence, start_command: osc_open_index + osc_open_char.len_utf8(), start_terminator, end: end_sequence, }) } fn next_csi(&mut self, start_sequence: usize) -> Option { let (csi_open_index, csi_open_char) = self.chars.next().expect("to not be finished"); debug_assert_eq!(csi_open_char, '['); let start_parameters: usize = csi_open_index + csi_open_char.len_utf8(); // Keep iterating while within the range of `0x30-0x3F`. let mut start_intermediates: usize = start_parameters; if let Some((_, end)) = self.chars_take_while(|c| matches!(c, '\x30'..='\x3F')) { start_intermediates = end; } // Keep iterating while within the range of `0x20-0x2F`. let mut start_final_byte: usize = start_intermediates; if let Some((_, end)) = self.chars_take_while(|c| matches!(c, '\x20'..='\x2F')) { start_final_byte = end; } // Take the last char. let end_of_sequence = match self.chars.next() { None => start_final_byte, Some((i, c)) => i + c.len_utf8(), }; Some(EscapeSequenceOffsets::CSI { start_sequence, start_parameters, start_intermediates, start_final_byte, end: end_of_sequence, }) } fn next_nf(&mut self, start_sequence: usize) -> Option { let (nf_open_index, nf_open_char) = self.chars.next().expect("to not be finished"); debug_assert!(matches!(nf_open_char, '\x20'..='\x2F')); let start: usize = nf_open_index; let mut end: usize = start; // Keep iterating while within the range of `0x20-0x2F`. match self.chars_take_while(|c| matches!(c, '\x20'..='\x2F')) { Some((_, i)) => end = i, None => { return Some(EscapeSequenceOffsets::NF { start_sequence, start, end, }) } } // Get the final byte. if let Some((i, c)) = self.chars.next() { end = i + c.len_utf8() } Some(EscapeSequenceOffsets::NF { start_sequence, start, end, }) } } impl Iterator for EscapeSequenceOffsetsIterator<'_> { type Item = EscapeSequenceOffsets; fn next(&mut self) -> Option { match self.chars.peek() { Some((_, '\x1B')) => self.next_sequence(), Some((_, _)) => self.next_text(), None => None, } } } /// An iterator over ANSI/VT escape sequences within a string. /// /// ## Example /// /// ```ignore /// let iter = EscapeSequenceIterator::new("\x1B[33mThis is yellow text.\x1B[m"); /// ``` pub struct EscapeSequenceIterator<'a> { text: &'a str, offset_iter: EscapeSequenceOffsetsIterator<'a>, } impl<'a> EscapeSequenceIterator<'a> { pub fn new(text: &'a str) -> EscapeSequenceIterator<'a> { EscapeSequenceIterator { text, offset_iter: EscapeSequenceOffsetsIterator::new(text), } } } impl<'a> Iterator for EscapeSequenceIterator<'a> { type Item = EscapeSequence<'a>; fn next(&mut self) -> Option { use EscapeSequenceOffsets::*; self.offset_iter.next().map(|offsets| match offsets { Unknown { start, end } => EscapeSequence::Unknown(&self.text[start..end]), Text { start, end } => EscapeSequence::Text(&self.text[start..end]), NF { start_sequence, start, end, } => EscapeSequence::NF { raw_sequence: &self.text[start_sequence..end], nf_sequence: &self.text[start..end], }, OSC { start_sequence, start_command, start_terminator, end, } => EscapeSequence::OSC { raw_sequence: &self.text[start_sequence..end], command: &self.text[start_command..start_terminator], terminator: &self.text[start_terminator..end], }, CSI { start_sequence, start_parameters, start_intermediates, start_final_byte, end, } => EscapeSequence::CSI { raw_sequence: &self.text[start_sequence..end], parameters: &self.text[start_parameters..start_intermediates], intermediates: &self.text[start_intermediates..start_final_byte], final_byte: &self.text[start_final_byte..end], }, }) } } /// A parsed ANSI/VT100 escape sequence. #[derive(Debug, PartialEq)] pub enum EscapeSequence<'a> { Text(&'a str), Unknown(&'a str), #[allow(clippy::upper_case_acronyms)] NF { raw_sequence: &'a str, nf_sequence: &'a str, }, #[allow(clippy::upper_case_acronyms)] OSC { raw_sequence: &'a str, command: &'a str, terminator: &'a str, }, #[allow(clippy::upper_case_acronyms)] CSI { raw_sequence: &'a str, parameters: &'a str, intermediates: &'a str, final_byte: &'a str, }, } impl<'a> EscapeSequence<'a> { pub fn raw(&self) -> &'a str { use EscapeSequence::*; match *self { Text(raw) => raw, Unknown(raw) => raw, NF { raw_sequence, .. } => raw_sequence, OSC { raw_sequence, .. } => raw_sequence, CSI { raw_sequence, .. } => raw_sequence, } } } #[cfg(test)] mod tests { use crate::vscreen::{ EscapeSequence, EscapeSequenceIterator, EscapeSequenceOffsets, EscapeSequenceOffsetsIterator, }; #[test] fn test_escape_sequence_offsets_iterator_parses_text() { let mut iter = EscapeSequenceOffsetsIterator::new("text"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::Text { start: 0, end: 4 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_text_stops_at_esc() { let mut iter = EscapeSequenceOffsetsIterator::new("text\x1B[ming"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::Text { start: 0, end: 4 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_osc_with_bel() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B]abc\x07"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::OSC { start_sequence: 0, start_command: 2, start_terminator: 5, end: 6, }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_osc_with_st() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B]abc\x1B\\"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::OSC { start_sequence: 0, start_command: 2, start_terminator: 5, end: 7, }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_osc_thats_broken() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B]ab"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::OSC { start_sequence: 0, start_command: 2, start_terminator: 4, end: 4, }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_csi() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[m"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 2, start_final_byte: 2, end: 3 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_csi_with_parameters() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[1;34m"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 6, start_final_byte: 6, end: 7 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_csi_with_intermediates() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[$m"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 2, start_final_byte: 3, end: 4 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_csi_with_parameters_and_intermediates() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[1$m"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 3, start_final_byte: 4, end: 5 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_csi_thats_broken() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B["); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 2, start_final_byte: 2, end: 2 }) ); let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[1"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 3, start_final_byte: 3, end: 3 }) ); let mut iter = EscapeSequenceOffsetsIterator::new("\x1B[1$"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 0, start_parameters: 2, start_intermediates: 3, start_final_byte: 4, end: 4 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_nf() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B($0"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::NF { start_sequence: 0, start: 1, end: 4 }) ); } #[test] fn test_escape_sequence_offsets_iterator_parses_nf_thats_broken() { let mut iter = EscapeSequenceOffsetsIterator::new("\x1B("); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::NF { start_sequence: 0, start: 1, end: 1 }) ); } #[test] fn test_escape_sequence_offsets_iterator_iterates() { let mut iter = EscapeSequenceOffsetsIterator::new("text\x1B[33m\x1B]OSC\x07\x1B(0"); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::Text { start: 0, end: 4 }) ); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::CSI { start_sequence: 4, start_parameters: 6, start_intermediates: 8, start_final_byte: 8, end: 9 }) ); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::OSC { start_sequence: 9, start_command: 11, start_terminator: 14, end: 15 }) ); assert_eq!( iter.next(), Some(EscapeSequenceOffsets::NF { start_sequence: 15, start: 16, end: 18 }) ); assert_eq!(iter.next(), None); } #[test] fn test_escape_sequence_iterator_iterates() { let mut iter = EscapeSequenceIterator::new("text\x1B[33m\x1B]OSC\x07\x1B]OSC\x1B\\\x1B(0"); assert_eq!(iter.next(), Some(EscapeSequence::Text("text"))); assert_eq!( iter.next(), Some(EscapeSequence::CSI { raw_sequence: "\x1B[33m", parameters: "33", intermediates: "", final_byte: "m", }) ); assert_eq!( iter.next(), Some(EscapeSequence::OSC { raw_sequence: "\x1B]OSC\x07", command: "OSC", terminator: "\x07", }) ); assert_eq!( iter.next(), Some(EscapeSequence::OSC { raw_sequence: "\x1B]OSC\x1B\\", command: "OSC", terminator: "\x1B\\", }) ); assert_eq!( iter.next(), Some(EscapeSequence::NF { raw_sequence: "\x1B(0", nf_sequence: "(0", }) ); assert_eq!(iter.next(), None); } #[test] fn test_sgr_attributes_do_not_leak_into_wrong_field() { let mut attrs = crate::vscreen::Attributes::new(); // Bold, Dim, Italic, Underline, Foreground, Background attrs.update(EscapeSequence::CSI { raw_sequence: "\x1B[1;2;3;4;31;41m", parameters: "1;2;3;4;31;41", intermediates: "", final_byte: "m", }); assert_eq!(attrs.bold, "\x1B[1m"); assert_eq!(attrs.dim, "\x1B[2m"); assert_eq!(attrs.italic, "\x1B[3m"); assert_eq!(attrs.underline, "\x1B[4m"); assert_eq!(attrs.foreground, "\x1B[31m"); assert_eq!(attrs.background, "\x1B[41m"); // Bold, Bright Foreground, Bright Background attrs.sgr_reset(); attrs.update(EscapeSequence::CSI { raw_sequence: "\x1B[1;94;103m", parameters: "1;94;103", intermediates: "", final_byte: "m", }); assert_eq!(attrs.bold, "\x1B[1m"); assert_eq!(attrs.foreground, "\x1B[94m"); assert_eq!(attrs.background, "\x1B[103m"); } } ================================================ FILE: src/wrapping.rs ================================================ #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum WrappingMode { Character, Word, // The bool specifies whether wrapping has been explicitly disabled by the user via --wrap=never NoWrapping(bool), } impl Default for WrappingMode { fn default() -> Self { WrappingMode::NoWrapping(false) } } ================================================ FILE: tests/.gitattributes ================================================ # force LF EOLs for test fixtures examples/** text=auto eol=lf snapshots/** text=auto eol=lf syntax-tests/source/** text=auto eol=lf syntax-tests/highlighted/** text=auto eol=lf # Linguist overrides benchmarks/** linguist-vendored examples/** linguist-vendored snapshots/** linguist-vendored syntax-tests/highlighted/** linguist-vendored syntax-tests/source/** linguist-vendored ================================================ FILE: tests/assets.rs ================================================ use bat::assets::HighlightingAssets; /// This test ensures that we are not accidentally removing themes due to submodule updates. /// It is 'ignore'd by default because it requires themes.bin to be up-to-date. #[test] #[ignore] fn all_themes_are_present() { let assets = HighlightingAssets::from_binary(); let mut themes: Vec<_> = assets.themes().collect(); themes.sort_unstable(); assert_eq!( themes, vec![ "1337", "Catppuccin Frappe", "Catppuccin Latte", "Catppuccin Macchiato", "Catppuccin Mocha", "Coldark-Cold", "Coldark-Dark", "DarkNeon", "Dracula", "GitHub", "Monokai Extended", "Monokai Extended Bright", "Monokai Extended Light", "Monokai Extended Origin", "Nord", "OneHalfDark", "OneHalfLight", "Solarized (dark)", "Solarized (light)", "Sublime Snazzy", "TwoDark", "ansi", "base16", "base16-256", "gruvbox-dark", "gruvbox-light", "zenburn" ] ); } ================================================ FILE: tests/benchmarks/.gitignore ================================================ /benchmark-results ================================================ FILE: tests/benchmarks/.ignore ================================================ test-src/* ================================================ FILE: tests/benchmarks/highlighting-speed-src/grep-output-ansi-sequences.txt ================================================ .github/ISSUE_TEMPLATE/syntax_request.md:3:about: Request adding a new syntax to bat. .github/ISSUE_TEMPLATE/syntax_request.md:14:Bat supports locally-installed language definitions. See the link below: .github/ISSUE_TEMPLATE/syntax_request.md:16:https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions .github/ISSUE_TEMPLATE/question.md:3:about: Ask a question about 'bat'. .github/ISSUE_TEMPLATE/bug_report.md:21:**How did you install `bat`?** .github/ISSUE_TEMPLATE/bug_report.md:27:**bat version and environment** .github/ISSUE_TEMPLATE/bug_report.md:31:in which you're running bat. To do this, run the full `bat` command that demonstrates .github/ISSUE_TEMPLATE/bug_report.md:34: bat [other options and arguments…] --diagnostic .github/ISSUE_TEMPLATE/bug_report.md:40:If you are running bat 0.17.1 or older (where --diagnostic is not available), please .github/ISSUE_TEMPLATE/bug_report.md:43: https://github.com/sharkdp/bat/blob/master/diagnostics/info.sh .github/ISSUE_TEMPLATE/bug_report.md:46:are on Windows, please let us know your bat version and your Windows version. .github/workflows/CICD.yml:69: - name: Build and install bat .github/workflows/CICD.yml:76: - name: Build and install bat with updated assets .github/workflows/CICD.yml:94: run: bat --list-languages .github/workflows/CICD.yml:96: run: bat --list-themes .github/workflows/CICD.yml:235: - name: Run bat .github/workflows/CICD.yml:242: - name: Show diagnostics (bat --diagnostic) .github/workflows/CICD.yml:302: cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/manual/bat.1 "$ARCHIVE_DIR" .github/workflows/CICD.yml:308: cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.bash "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.bash" .github/workflows/CICD.yml:309: cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.fish "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.fish" .github/workflows/CICD.yml:310: cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/_bat.ps1 "$ARCHIVE_DIR/autocomplete/_${{ env.PROJECT_NAME }}.ps1" .github/workflows/CICD.yml:311: cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.zsh "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.zsh" .github/workflows/CICD.yml:355: install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/manual/bat.1 "${DPKG_DIR}/usr/share/man/man1/${{ env.PROJECT_NAME }}.1" .github/workflows/CICD.yml:359: install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.bash "${DPKG_DIR}/usr/share/bash-completion/completions/${{ env.PROJECT_NAME }}" .github/workflows/CICD.yml:360: install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.fish "${DPKG_DIR}/usr/share/fish/vendor_completions.d/${{ env.PROJECT_NAME }}.fish" .github/workflows/CICD.yml:361: install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.zsh "${DPKG_DIR}/usr/share/zsh/vendor-completions/_${{ env.PROJECT_NAME }}" README.md:2: bat - a cat clone with wings
README.md:3: Build Status README.md:4: license README.md:5: Version info
README.md:16: [中文] README.md:24:`bat` supports syntax highlighting for a large number of programming and markup README.md:31:`bat` communicates with `git` to show modifications with respect to the index README.md:45:By default, `bat` pipes its own output to a pager (e.g. `less`) if the output is too large for one screen. README.md:46:If you would rather `bat` work like `cat` all the time (never page output), you can set `--paging=never` as an option, either on the command line or in your configuration file. README.md:47:If you intend to alias `cat` to `bat` in your shell configuration, you can use `alias cat='bat --paging=never'` to preserve the default behavior. README.md:51:Even with a pager set, you can still use `bat` to concatenate files :wink:. README.md:52:Whenever `bat` detects a non-interactive terminal (i.e. when you pipe into another process or into a file), `bat` will act as a drop-in replacement for `cat` and fall back to printing the plain file contents, regardless of the `--pager` option's value. README.md:59:> bat README.md README.md:65:> bat src/*.rs README.md:73:> curl -s https://sh.rustup.rs | bat README.md:79:> yaml2json .travis.yml | json_pp | bat -l json README.md:84:> bat -A /etc/hosts README.md:90:bat > note.md # quickly create a new file README.md:92:bat header.md content.md footer.md > document.md README.md:94:bat -n main.rs # show line numbers (only) README.md:96:bat f - g # output 'f', then stdin, then 'g'. README.md:103:You can use `bat` as a previewer for [`fzf`](https://github.com/junegunn/fzf). To do this, README.md:104:use `bat`s `--color=always` option to force colorized output. You can also use `--line-range` README.md:108:fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' README.md:115:You can use the `-exec` option of `find` to preview all search results with `bat`: README.md:118:find … -exec bat {} + README.md:121:If you happen to use [`fd`](https://github.com/sharkdp/fd), you can use the `-X`/`--exec-batch` option to do the same: README.md:124:fd … -X bat README.md:129:With [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md), `bat` can be used as the printer for [`ripgrep`](https://github.com/BurntSushi/ripgrep) search results. README.md:132:batgrep needle src/ README.md:137:`bat` can be combined with `tail -f` to continuously monitor a given file with syntax highlighting. README.md:140:tail -f /var/log/pacman.log | bat --paging=never -l log README.md:148:You can combine `bat` with `git show` to view an older version of a given file with proper syntax README.md:152:git show v0.6.0:src/main.rs | bat -l rs README.md:157:You can combine `bat` with `git diff` to view lines around code changes with proper syntax README.md:160:batdiff() { README.md:161: git diff --name-only --diff-filter=d | xargs bat --diff README.md:164:If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras). README.md:170:The line numbers and Git modification markers in the output of `bat` can make it hard to copy README.md:171:the contents of a file. To prevent this, you can call `bat` with the `-p`/`--plain` option or README.md:174:bat main.cpp | xclip README.md:176:`bat` will detect that the output is being redirected and print the plain file contents. README.md:180:`bat` can be used as a colorizing pager for `man`, by setting the README.md:184:export MANPAGER="sh -c 'col -bx | bat -l man -p'" README.md:187:(replace `bat` with `batcat` if you are on Debian or Ubuntu) README.md:192:If you prefer to have this bundled in a new command, you can also use [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md). README.md:196:Also, note that this will [not work](https://github.com/sharkdp/bat/issues/1145) with Mandocs `man` implementation. README.md:200:The [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) script is a wrapper that will format code and print it with `bat`. README.md:205:[![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg)](https://repology.org/project/bat-cat/versions) README.md:210:`bat` is available on [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) and [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). README.md:215:sudo apt install bat README.md:218:**Important**: If you install `bat` this way, please note that the executable may be installed as `batcat` instead of `bat` (due to [a name README.md:219:clash with another package](https://github.com/sharkdp/bat/issues/982)). You can set up a `bat -> batcat` symlink or alias to prevent any issues that may come up because of this and to be consistent with other distributions: README.md:222:ln -s /usr/bin/batcat ~/.local/bin/bat README.md:229:the most recent release of `bat`, download the latest `.deb` package from the README.md:230:[release page](https://github.com/sharkdp/bat/releases) and install it via: README.md:233:sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture README.md:238:You can install [the `bat` package](https://pkgs.alpinelinux.org/packages?name=bat) README.md:242:apk add bat README.md:247:You can install [the `bat` package](https://www.archlinux.org/packages/community/x86_64/bat/) README.md:251:pacman -S bat README.md:256:You can install [the `bat` package](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) from the official [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/) repository. README.md:259:dnf install bat README.md:264:You can install [the `bat` package](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/bat) from dev-kit. README.md:267:emerge sys-apps/bat README.md:272:You can install [the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat) README.md:276:emerge sys-apps/bat README.md:281:You can install `bat` via xbps-install: README.md:283:xbps-install -S bat README.md:288:You can install `bat` via pkg: README.md:290:pkg install bat README.md:295:You can install a precompiled [`bat` package](https://www.freshports.org/textproc/bat) with pkg: README.md:298:pkg install bat README.md:304:cd /usr/ports/textproc/bat README.md:310:You can install `bat` package using [`pkg_add(1)`](https://man.openbsd.org/pkg_add.1): README.md:313:pkg_add bat README.md:318:You can install `bat` using the [nix package manager](https://nixos.org/nix): README.md:321:nix-env -i bat README.md:326:You can install `bat` with zypper: README.md:329:zypper install bat README.md:335:Existing packages may be available, but are not officially supported and may contain [issues](https://github.com/sharkdp/bat/issues/1519). README.md:339:You can install `bat` with [Homebrew on MacOS](https://formulae.brew.sh/formula/bat) or [Homebrew on Linux](https://formulae.brew.sh/formula-linux/bat): README.md:342:brew install bat README.md:347:Or install `bat` with [MacPorts](https://ports.macports.org/port/bat/summary): README.md:350:port install bat README.md:355:There are a few options to install `bat` on Windows. Once you have installed `bat`, README.md:356:take a look at the ["Using `bat` on Windows"](#using-bat-on-windows) section. README.md:364:You can install `bat` via [Chocolatey](https://chocolatey.org/packages/Bat): README.md:366:choco install bat README.md:371:You can install `bat` via [scoop](https://scoop.sh/): README.md:373:scoop install bat README.md:378:You can download prebuilt binaries from the [Release page](https://github.com/sharkdp/bat/releases), README.md:384:Check out the [Release page](https://github.com/sharkdp/bat/releases) for README.md:385:prebuilt versions of `bat` for many different architectures. Statically-linked README.md:390:If you want to build `bat` from source, you need Rust 1.46 or README.md:394:cargo install --locked bat README.md:404:Use `bat --list-themes` to get a list of all available themes for syntax README.md:405:highlighting. To select the `TwoDark` theme, call `bat` with the README.md:406:`--theme=TwoDark` option or set the `BAT_THEME` environment variable to README.md:407:`TwoDark`. Use `export BAT_THEME="TwoDark"` in your shell's startup file to README.md:408:make the change permanent. Alternatively, use `bat`s README.md:409:[configuration file](https://github.com/sharkdp/bat#configuration-file). README.md:414:bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" README.md:417:`bat` looks good on a dark background by default. However, if your terminal uses a README.md:420:['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes). README.md:424:`bat` has three themes that always use [8-bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors), README.md:444:You can use the `--style` option to control the appearance of `bat`s output. README.md:446:and line numbers but no grid and no file header. Set the `BAT_STYLE` environment README.md:447:variable to make these changes permanent or use `bat`s README.md:448:[configuration file](https://github.com/sharkdp/bat#configuration-file). README.md:452:Should you find that a particular syntax is not available within `bat`, you can follow these README.md:453:instructions to easily add new syntaxes to your current `bat` installation. README.md:455:`bat` uses the excellent [`syntect`](https://github.com/trishume/syntect/) README.md:466: mkdir -p "$(bat --config-dir)/syntaxes" README.md:467: cd "$(bat --config-dir)/syntaxes" README.md:477: bat cache --build README.md:480:3. Finally, use `bat --list-languages` to check if the new languages are available. README.md:485: bat cache --clear README.md:488:4. If you think that a specific syntax should be included in `bat` by default, please README.md:490: instructions [here](doc/assets.md): [Open Syntax Request](https://github.com/sharkdp/bat/issues/new?labels=syntax-request&template=syntax_request.md). README.md:498:mkdir -p "$(bat --config-dir)/themes" README.md:499:cd "$(bat --config-dir)/themes" README.md:505:bat cache --build README.md:508:Finally, use `bat --list-themes` to check if the new themes are available. README.md:516:(use `bat --list-languages` for an overview). README.md:518:Note: You probably want to use this option as an entry in `bat`s configuration file instead README.md:539:`bat` uses the pager that is specified in the `PAGER` environment variable. If this variable is not README.md:541:`PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in README.md:544:**Note**: If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors. README.md:547:`PAGER`/`BAT_PAGER` variables: README.md:550:export BAT_PAGER="less -RF" README.md:553:Instead of using environment variables, you can also use `bat`s [configuration file](https://github.com/sharkdp/bat#configuration-file) to configure the pager (`--pager` option). README.md:556:`bat` will pass the following command line options to the pager: `-R`/`--RAW-CONTROL-CHARS`, README.md:572:`bat` expands tabs to 4 spaces by itself, not relying on the pager. To change this, simply add the README.md:575:**Note**: Defining tab stops for the pager (via the `--pager` argument by `bat`, or via the `LESS` README.md:578:sidebar. Calling `bat` with `--tabs=0` will override it and let tabs be consumed by the pager. README.md:582:If you make use of the dark mode feature in macOS, you might want to configure `bat` to use a different README.md:587:alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" README.md:593:`bat` can also be customized with a configuration file. The location of the file is dependent README.md:596:bat --config-file README.md:599:Alternatively, you can use the `BAT_CONFIG_PATH` environment variable to point `bat` to a README.md:602:export BAT_CONFIG_PATH="/path/to/bat.conf" README.md:607:bat --generate-config-file README.md:612:The configuration file is a simple list of command line arguments. Use `bat --help` to see a full list of possible options and values. In addition, you can add comments by prepending a line with the `#` character. README.md:629:## Using `bat` on Windows README.md:631:`bat` mostly works out-of-the-box on Windows, but a few features may need extra configuration. README.md:653:or by setting `BAT_PAGER` to an empty string. README.md:657:`bat` on Windows does not natively support Cygwin's unix-style paths (`/cygdrive/*`). When passed an absolute cygwin path as an argument, `bat` will encounter the following error: `The system cannot find the path specified. (os error 3)` README.md:662:bat() { README.md:671: command bat "${args[@]}" README.md:679:If an input file contains color codes or other ANSI escape sequences, `bat` will have problems README.md:682:passing the `--color=never --wrap=never` options to `bat`. README.md:686:`bat` handles terminals *with* and *without* truecolor support. However, the colors in most syntax README.md:694:`24bit`. Otherwise, `bat` will not be able to determine whether or not 24-bit escape sequences README.md:699:Please try a different theme (see `bat --list-themes` for a list). The `OneHalfDark` and README.md:704:`bat` natively supports UTF-8 as well as UTF-16. For every other file encoding, you may need to README.md:709:iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat README.md:712:by `bat`. README.md:718:git clone --recursive https://github.com/sharkdp/bat README.md:721:cd bat README.md:730:# Build a bat binary with modified syntaxes and themes README.md:735:If you want to build an application that uses `bat`s pretty-printing README.md:736:features as a library, check out the [the API documentation](https://docs.rs/bat/). README.md:738:when you depend on `bat` as a library. README.md:753:Please contact [David Peter](https://david-peter.de/) via email if you want to report a vulnerability in `bat`. README.md:757:`bat` tries to achieve the following goals: README.md:768:Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). README.md:770:`bat` is made available under the terms of either the MIT License or the Apache License 2.0, at your option. .gitmodules:198: url = https://github.com/ArmandPhilippot/coldark-bat.git .gitmodules:202: branch = bat-source examples/list_syntaxes_and_themes.rs:1:/// A simple program that prints its own source code using the bat library examples/list_syntaxes_and_themes.rs:2:use bat::PrettyPrinter; examples/inputs.rs:3:use bat::{Input, PrettyPrinter}; examples/yaml.rs:2:use bat::{Input, PrettyPrinter}; examples/advanced.rs:1:/// A program that prints its own source code using the bat library examples/advanced.rs:2:use bat::{PagingMode, PrettyPrinter, WrappingMode}; examples/cat.rs:1:/// A very simple colorized `cat` clone, using `bat` as a library. examples/cat.rs:2:/// See `src/bin/bat` for the full `bat` application. examples/cat.rs:3:use bat::PrettyPrinter; examples/simple.rs:1:/// A simple program that prints its own source code using the bat library examples/simple.rs:2:use bat::PrettyPrinter; .gitignore:5:/assets/completions/bat.bash .gitignore:6:/assets/completions/bat.fish .gitignore:7:/assets/completions/bat.zsh .gitignore:8:/assets/manual/bat.1 src/input.rs:12:/// This tells bat how to refer to the input. src/error.rs:22: #[error("Use of bat as a pager is disallowed in order to avoid infinite recursion problems")] src/error.rs:23: InvalidPagerValueBat, src/error.rs:53: Red.paint("[bat error]"), src/error.rs:59: writeln!(output, "{}: {}", Red.paint("[bat error]"), error).ok(); src/lib.rs:1://! `bat` is a library to print syntax highlighted content. src/lib.rs:13://! use bat::PrettyPrinter; src/macros.rs:2:macro_rules! bat_warning { src/macros.rs:5: eprintln!("{}: {}", Yellow.paint("[bat warning]"), format!($($arg)*)); src/syntax_mapping.rs:52: "**/bat/config", src/pager.rs:10: /// From the env var BAT_PAGER src/pager.rs:11: EnvVarBatPager, src/pager.rs:23: /// bat src/pager.rs:24: Bat, src/pager.rs:48: Some("bat") => PagerKind::Bat, src/pager.rs:86: let bat_pager = env::var("BAT_PAGER"); src/pager.rs:89: let (cmd, source) = match (config_pager, &bat_pager, &pager) { src/pager.rs:91: (_, Ok(bat_pager), _) => (bat_pager.as_str(), PagerSource::EnvVarBatPager), src/pager.rs:105: // If PAGER=bat, silently use 'less' instead to prevent src/pager.rs:107: // Never silently use 'less' if BAT_PAGER or --pager has been src/pager.rs:109: matches!(kind, PagerKind::More | PagerKind::Most | PagerKind::Bat) src/assets.rs:16:use crate::{bat_warning, SyntaxMapping}; src/assets.rs:218: bat_warning!("Theme '{}' is deprecated, using 'ansi' instead.", theme); src/assets.rs:222: bat_warning!("Unknown theme '{}', using default.", theme) src/printer.rs:278: (but will be present if the output of 'bat' is piped). You can use 'bat -A' \ src/printer.rs:280: Yellow.paint("[bat warning]"), src/output.rs:62: if pager.kind == PagerKind::Bat { src/output.rs:63: return Err(Error::InvalidPagerValueBat); src/output.rs:78: // ANSI color sequences printed by bat. If someone has set PAGER="less -F", we src/output.rs:81: // We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER src/output.rs:82: // or bats '--pager' command line option. src/bin/bat/input.rs:1:use bat::input::Input; src/bin/bat/config.rs:10: env::var("BAT_CONFIG_PATH") src/bin/bat/config.rs:16:pub fn generate_config_file() -> bat::error::Result<()> { src/bin/bat/config.rs:46: let default_config = r#"# This is `bat`s configuration file. Each line either contains a comment or src/bin/bat/config.rs:47:# a command-line option that you want to pass to `bat` by default. You can src/bin/bat/config.rs:48:# run `bat --help` to get a list of all possible configuration options. src/bin/bat/config.rs:50:# Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes` src/bin/bat/config.rs:62:# enable mouse scrolling support in `bat` when running inside tmux. This might src/bin/bat/config.rs:98: env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s)) src/bin/bat/directories.rs:7:/// The `XDG_CACHE_HOME` environment variable is checked first. `BAT_CONFIG_DIR` src/bin/bat/directories.rs:9:/// The fallback directories are `~/.cache/bat` and `~/.config/bat`, respectively. src/bin/bat/directories.rs:10:pub struct BatProjectDirs { src/bin/bat/directories.rs:15:impl BatProjectDirs { src/bin/bat/directories.rs:16: fn new() -> Option<BatProjectDirs> { src/bin/bat/directories.rs:17: let cache_dir = BatProjectDirs::get_cache_dir()?; src/bin/bat/directories.rs:19: // Checks whether or not $BAT_CONFIG_DIR exists. If it doesn't, set our config dir src/bin/bat/directories.rs:22: if let Some(config_dir_op) = env::var_os("BAT_CONFIG_DIR").map(PathBuf::from) { src/bin/bat/directories.rs:34: config_dir_op.map(|d| d.join("bat"))? src/bin/bat/directories.rs:37: Some(BatProjectDirs { src/bin/bat/directories.rs:44: // on all OS prefer BAT_CACHE_PATH if set src/bin/bat/directories.rs:45: let cache_dir_op = env::var_os("BAT_CACHE_PATH").map(PathBuf::from); src/bin/bat/directories.rs:59: cache_dir_op.map(|d| d.join("bat")) src/bin/bat/directories.rs:72: pub static ref PROJECT_DIRS: BatProjectDirs = src/bin/bat/directories.rs:73: BatProjectDirs::new().expect("Could not get home directory"); src/bin/bat/app.rs:17:use bat::{ src/bin/bat/app.rs:19: bat_warning, src/bin/bat/app.rs:56: // Skip the arguments in bats config file src/bin/bat/app.rs:62: // Read arguments from bats config file src/bin/bat/app.rs:191: .or_else(|| env::var("BAT_TABS").ok()) src/bin/bat/app.rs:204: .or_else(|| env::var("BAT_THEME").ok()) src/bin/bat/app.rs:305: let env_style_components: Option> = env::var("BAT_STYLE") src/bin/bat/app.rs:336: bat_warning!("Style 'rule' is a subset of style 'grid', 'rule' will not be visible."); src/bin/bat/assets.rs:9:use bat::assets::HighlightingAssets; src/bin/bat/assets.rs:10:use bat::assets_metadata::AssetsMetadata; src/bin/bat/assets.rs:11:use bat::error::*; src/bin/bat/assets.rs:34: in '{}' are not compatible with this version of bat ({}). To solve this, \ src/bin/bat/assets.rs:35: either rebuild the cache (bat cache --build) or remove \ src/bin/bat/assets.rs:36: the custom syntaxes/themes (bat cache --clear).\n\ src/bin/bat/assets.rs:38: https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions", src/bin/bat/main.rs:28:use bat::{ src/bin/bat/main.rs:52: bat::assets::build(source_dir, !blank, target_dir, clap::crate_version!()) src/bin/bat/main.rs:60: println!("bat has been built without the 'build-assets' feature. The 'cache --build' option is not available."); src/bin/bat/main.rs:207: and are added to the cache with `bat cache --build`. \ src/bin/bat/main.rs:209: https://github.com/sharkdp/bat#adding-new-themes", src/bin/bat/main.rs:230: let pager = bat::config::get_pager_executable(app.matches.value_of("pager")) src/bin/bat/main.rs:243: "BAT_PAGER", src/bin/bat/main.rs:244: "BAT_CACHE_PATH", src/bin/bat/main.rs:245: "BAT_CONFIG_PATH", src/bin/bat/main.rs:246: "BAT_OPTS", src/bin/bat/main.rs:247: "BAT_STYLE", src/bin/bat/main.rs:248: "BAT_TABS", src/bin/bat/main.rs:249: "BAT_THEME", src/bin/bat/main.rs:280: println!("bat has been built without the 'bugreport' feature. The '--diagnostic' option is not available."); src/bin/bat/clap_app.rs:43: "Note: `bat -h` prints a short and concise overview while `bat --help` gives all \ src/bin/bat/clap_app.rs:127: data to bat from STDIN when bat does not otherwise know \ src/bin/bat/clap_app.rs:290: if the output of bat is piped to another program, but you want \ src/bin/bat/clap_app.rs:306: set BAT_PAGER to an empty string. To control which pager is used, see the \ src/bin/bat/clap_app.rs:330: PAGER and BAT_PAGER environment variables. The default pager is 'less'. \ src/bin/bat/clap_app.rs:363: BAT_THEME environment variable (e.g.: export \ src/bin/bat/clap_app.rs:364: BAT_THEME=\"...\").", src/bin/bat/clap_app.rs:412: BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\ src/bin/bat/clap_app.rs:497: .help("Show bat's configuration directory."), src/bin/bat/clap_app.rs:503: .help("Show bat's cache directory."), src/bin/bat/clap_app.rs:521: 'bat --ignored-suffix \".dev\" my_file.json.dev' will use JSON syntax, and ignore '.dev'" src/bin/bat/clap_app.rs:528: // enable the 'bat cache' subcommand. src/assets/serialized_syntax_set.rs:14: /// The data to use is embedded into the bat binary. src/assets/build_assets.rs:246: if std::env::var("BAT_PRINT_SYNTAX_DEPENDENCIES").is_ok() { src/assets/build_assets.rs:248: // BAT_PRINT_SYNTAX_DEPENDENCIES=1 cargo run -- cache --build --source assets --blank --target /tmp src/assets/build_assets.rs:342:/// BAT_SYNTAX_DEPENDENCIES_TO_GRAPHVIZ_DOT_FILE=/tmp/bat-syntax-dependencies.dot cargo run -- cache --build --source assets --blank --target /tmp src/assets/build_assets.rs:343:/// dot /tmp/bat-syntax-dependencies.dot -Tpng -o /tmp/bat-syntax-dependencies.png src/assets/build_assets.rs:344:/// open /tmp/bat-syntax-dependencies.png src/assets/build_assets.rs:350: if let Ok(dot_file_path) = std::env::var("BAT_SYNTAX_DEPENDENCIES_TO_GRAPHVIZ_DOT_FILE") { src/assets/build_assets.rs:424: if std::env::var("BAT_INCLUDE_SYNTAX_DEPENDENTS").is_ok() { src/assets/assets_metadata.rs:12: bat_version: Option, src/assets/assets_metadata.rs:22: bat_version: Some(current_version.to_owned()), src/assets/assets_metadata.rs:48: /// => assume that these were created by an old version of bat and return src/assets/assets_metadata.rs:69: Version::parse(current_version).expect("bat follows semantic versioning"); src/assets/assets_metadata.rs:71: .bat_version src/assets/build_assets/graphviz_utils.rs:30: writeln!(dot_file, "digraph BatSyntaxDependencies {{")?; build.rs:2:// For more details, see https://github.com/sharkdp/bat/issues/372 build.rs:4:// For bat-as-a-library, no build script is required. The build script is for build.rs:5:// the manpage and completions, which are only relevant to the bat application. build.rs:17: let project_name = option_env!("PROJECT_NAME").unwrap_or("bat"); build.rs:54: "assets/manual/bat.1.in", build.rs:55: out_dir.join("assets/manual/bat.1"), build.rs:59: "assets/completions/bat.bash.in", build.rs:60: out_dir.join("assets/completions/bat.bash"), build.rs:64: "assets/completions/bat.fish.in", build.rs:65: out_dir.join("assets/completions/bat.fish"), build.rs:69: "assets/completions/_bat.ps1.in", build.rs:70: out_dir.join("assets/completions/_bat.ps1"), build.rs:74: "assets/completions/bat.zsh.in", build.rs:75: out_dir.join("assets/completions/bat.zsh"), build.rs:89:// const BIN_NAME: &str = "bat"; .git/info/refs:21:b41fb0df6cf831081754c27a4c33227c166eee69 refs/heads/bat-0.16-updates .git/info/refs:22:b5a40d0866e6a190fbee095ac104fdc6ec168d0a refs/heads/bat-0.18.2-release .git/info/refs:23:fa0d448cd3e652ffd3c5caa4caa4bdbe2973241c refs/heads/bat-config-file .git/info/refs:24:27516c6f26dc1319dc2516e7caf1aafbe8d30aa0 refs/heads/bat-diagnostic-option .git/info/refs:25:cd501edcbded4dc344e0a0478472b0a4819c2251 refs/heads/bat-diff .git/info/refs:26:d77742b2e425cd76e2ca90a75efba4205e280859 refs/heads/bat-diff-fixes .git/info/refs:215:f1f8807a38052c8138c6f8d1b3bf125e30588712 refs/remotes/origin/bat-v0.18.3-candidate .git/FETCH_HEAD:1:619cf6e6d6641dbb913dddd56907a54c6a9f6ce6 branch 'master' of https://github.com/sharkdp/bat .git/FETCH_HEAD:2:8244eb8ef88cc1b64d27991d6a5c7c69586b8a13 not-for-merge branch 'ci-experiment' of https://github.com/sharkdp/bat .git/FETCH_HEAD:3:271842d87c816cb80dc0a1c48eefee99c9439db6 not-for-merge branch 'create_highlighted_versions-wrong-path-repro' of https://github.com/sharkdp/bat .git/FETCH_HEAD:4:c42ec074ea6accdc38b8d9278bc3810343e2d1a3 not-for-merge branch 'dependabot/submodules/assets/syntaxes/02_Extra/PowerShell-742f0b5' of https://github.com/sharkdp/bat .git/FETCH_HEAD:5:fb9c30b1f7ff648d8aa8fb35a8ff669513c8e91f not-for-merge branch 'dependabot/submodules/assets/syntaxes/02_Extra/SCSS_Sass-d3d9404' of https://github.com/sharkdp/bat .git/FETCH_HEAD:6:179d905bb92eee7272cf6fbb38db88f9294df94a not-for-merge branch 'dependabot/submodules/assets/syntaxes/02_Extra/TypeScript-ba45efd' of https://github.com/sharkdp/bat .git/FETCH_HEAD:7:b146958ecbb8c8c926159509ca7fb32a8573f897 not-for-merge branch 'release-v0.18.3' of https://github.com/sharkdp/bat .git/logs/HEAD:14:a946f3ae23e7d6d9aa6361c034e9b62859b4dbff e92e13cd4332196617df7a07bc6c55d1fd4834bb David Peter 1631038809 +0200 rebase (continue) (pick): Use BAT_CONFIG_DIR and BAT_CACHE_PATH .git/modules/assets/themes/Coldark/FETCH_HEAD:1:e44750b2a9629dd12d8ed3ad9fd50c77232170b9 not-for-merge branch 'master' of https://github.com/ArmandPhilippot/coldark-bat .git/modules/assets/themes/Coldark/logs/refs/heads/master:1:0000000000000000000000000000000000000000 b4a1c74d8d5bdd136ec530e5905b810272472545 sharkdp 1603543180 +0200 clone: from https://github.com/ArmandPhilippot/coldark-bat.git .git/modules/assets/themes/Coldark/logs/refs/remotes/origin/HEAD:1:0000000000000000000000000000000000000000 b4a1c74d8d5bdd136ec530e5905b810272472545 sharkdp 1603543180 +0200 clone: from https://github.com/ArmandPhilippot/coldark-bat.git .git/modules/assets/themes/Coldark/logs/HEAD:1:0000000000000000000000000000000000000000 b4a1c74d8d5bdd136ec530e5905b810272472545 sharkdp 1603543180 +0200 clone: from https://github.com/ArmandPhilippot/coldark-bat.git .git/modules/assets/themes/Coldark/config:8: url = https://github.com/ArmandPhilippot/coldark-bat.git .git/modules/assets/themes/gruvbox/FETCH_HEAD:1:64c47250e54298b91e2cf8d401320009aba9f991 not-for-merge branch 'bat-source' of https://github.com/subnut/gruvbox-tmTheme .git/packed-refs:22:b41fb0df6cf831081754c27a4c33227c166eee69 refs/heads/bat-0.16-updates .git/packed-refs:23:b5a40d0866e6a190fbee095ac104fdc6ec168d0a refs/heads/bat-0.18.2-release .git/packed-refs:24:fa0d448cd3e652ffd3c5caa4caa4bdbe2973241c refs/heads/bat-config-file .git/packed-refs:25:27516c6f26dc1319dc2516e7caf1aafbe8d30aa0 refs/heads/bat-diagnostic-option .git/packed-refs:26:cd501edcbded4dc344e0a0478472b0a4819c2251 refs/heads/bat-diff .git/packed-refs:27:d77742b2e425cd76e2ca90a75efba4205e280859 refs/heads/bat-diff-fixes .git/packed-refs:216:f1f8807a38052c8138c6f8d1b3bf125e30588712 refs/remotes/origin/bat-v0.18.3-candidate .git/config:7: url = https://github.com/sharkdp/bat.git .git/config:13: slug = sharkdp/bat .git/config:143:[branch "bat-config-file"] .git/config:145: merge = refs/heads/bat-config-file .git/config:176:[branch "bat-diff"] .git/config:178: merge = refs/heads/bat-diff .git/config:228: remote = git@github.com:lavifb/bat.git .git/config:231: url = https://github.com/lavifb/bat .git/config:234: remote = git@github.com:majecty/bat.git .git/config:237: url = https://github.com/majecty/bat .git/config:246: remote = git@github.com:reidwagner/bat.git .git/config:315: remote = git@github.com:hrlmartins/bat.git .git/config:369: remote = git@github.com:fvictorio/bat.git .git/config:378: remote = git@github.com:eth-p/bat.git .git/config:387: remote = git@github.com:Kogia-sima/bat.git .git/config:426: remote = git@github.com:neuronull/bat.git .git/config:429: remote = git@github.com:jmick414/bat.git .git/config:435: remote = git@github.com:dtolnay/bat.git .git/config:441: remote = git@github.com:eth-p/bat.git .git/config:444: remote = git@github.com:neuronull/bat.git .git/config:482:[branch "bat-diff-fixes"] .git/config:484: merge = refs/heads/bat-diff-fixes .git/config:486: remote = git@github.com:lzutao/bat.git .git/config:507: remote = git@github.com:eth-p/bat.git .git/config:510: remote = git@github.com:eth-p/bat.git .git/config:513: remote = git@github.com:kopecs/bat.git .git/config:516: remote = git@github.com:eth-p/bat.git .git/config:540: remote = git@github.com:rxt1077/bat.git .git/config:558: remote = git@github.com:alexnovak/bat.git .git/config:561: remote = git@github.com:guidocella/bat.git .git/config:564: remote = git@github.com:gsomix/bat.git .git/config:567: remote = git@github.com:caioalonso/bat.git .git/config:579: remote = git@github.com:mk12/bat.git .git/config:585: remote = git@github.com:kjmph/bat.git .git/config:591: remote = git@github.com:Kienyew/bat.git .git/config:603: remote = git@github.com:alexanderkarlis/bat.git .git/config:609: remote = git@github.com:ahmedelgabri/bat.git .git/config:615: remote = git@github.com:Kienyew/bat.git .git/config:618: remote = git@github.com:eth-p/bat.git .git/config:620:[branch "bat-0.16-updates"] .git/config:622: merge = refs/heads/bat-0.16-updates .git/config:624: remote = git@github.com:henil/bat.git .git/config:627: remote = git@github.com:AkshatGadhwal/bat.git .git/config:633: remote = git@github.com:loganintech/bat.git .git/config:639: remote = git@github.com:mzegar/bat.git .git/config:642: remote = git@github.com:AkshatGadhwal/bat.git .git/config:645: remote = git@github.com:AkshatGadhwal/bat.git .git/config:651: remote = git@github.com:jacobmischka/bat.git .git/config:657: url = https://github.com/forkeith/bat.git .git/config:660: remote = git@github.com:ArmandPhilippot/bat.git .git/config:664: url = https://github.com/ArmandPhilippot/coldark-bat.git .git/config:666: remote = git@github.com:adrian-rivera/bat.git .git/config:669: remote = git@github.com:eth-p/bat.git .git/config:681: remote = git@github.com:MarcoIeni/bat.git .git/config:690: remote = git@github.com:Enselic/bat.git .git/config:696: remote = git@github.com:stku1985/bat.git .git/config:699: remote = git@github.com:mk12/bat.git .git/config:702: remote = git@github.com:j0hnmeow/bat.git .git/config:708: remote = git@github.com:Enselic/bat.git .git/config:713:[branch "bat-diagnostic-option"] .git/config:715: merge = refs/heads/bat-diagnostic-option .git/config:717: url = https://github.com/niklasmohrin/bat.git .git/config:723: remote = git@github.com:paulsmith/bat.git .git/config:735: remote = git@github.com:Enselic/bat.git .git/config:762: remote = git@github.com:Enselic/bat.git .git/config:771: remote = git@github.com:brightly-salty/bat.git .git/config:774: remote = git@github.com:eth-p/bat.git .git/config:804: remote = git@github.com:matklad/bat.git .git/config:827:[branch "bat-0.18.2-release"] .git/config:829: merge = refs/heads/bat-0.18.2-release .git/config:831: remote = git@github.com:Enselic/bat.git .git/config:834: remote = git@github.com:steffahn/bat.git .git/config:837: remote = git@github.com:SarveshMD/bat.git .git/config:840: remote = git@github.com:Enselic/bat.git .git/config:852: remote = git@github.com:Enselic/bat.git .git/config:861: remote = git@github.com:bojan88/bat.git .git/config:870: remote = git@github.com:Enselic/bat.git .git/config:882: remote = git@github.com:Enselic/bat.git CHANGELOG.md:6:- `$BAT_CONFIG_DIR` is now a recognized environment variable. It has precedence over `$XDG_CONFIG_HOME`, see #1727 (@billrisher) CHANGELOG.md:25:- Include git hash in `bat -V` and `bat --version` output if present. See #1921 (@Enselic) CHANGELOG.md:42:## `bat` as a library CHANGELOG.md:45:- Remove `HighlightingAssets::from_files` and `HighlightingAssets::save_to_cache`. Instead of calling the former and then the latter you now make a single call to `bat::assets::build`. See #1802 (@Enselic) CHANGELOG.md:67:- Fix for a security vulnerability on Windows. Prior to this release, `bat` would execute programs called `less`/`less.exe` from the current working directory (instead of the one from `PATH`) with priority. An attacker might be able to use this by placing a malicious program in a shared directory where the user would execute `bat`. `bat` users on Windows are advised to upgrade to this version. See #1724 and #1472 (@Ry0taK). CHANGELOG.md:92:- The `LESS` environment variable is now included in `bat --diagnostic`, see #1589 (@Enselic) CHANGELOG.md:98:- Replaced "Advanced CSV" with a custom CSV syntax definition written especially for `bat`; see #1574 (@keith-hall) CHANGELOG.md:112:- Use a pager when `bat --list-languages` is called, see #1394 (@stku1985) CHANGELOG.md:117:- Only print themes hint in interactive mode (`bat --list-themes`), see #1439 (@rsteube) CHANGELOG.md:122:- If `PAGER` (but not `BAT_PAGER` or `--pager`) is `more` or `most`, silently use `less` instead to ensure support for colors, see #1063 (@Enselic) CHANGELOG.md:123:- If `PAGER` is `bat`, silently use `less` to prevent recursion. For `BAT_PAGER` or `--pager`, exit with error, see #1413 (@Enselic) CHANGELOG.md:125:- `BAT_CONFIG_PATH` ignored by `bat` if non-existent, see #1550 (@sharkdp) CHANGELOG.md:147:## `bat` as a library CHANGELOG.md:160:- Running `bat` without arguments fails ("output file is also an input"), see #1396 CHANGELOG.md:168:- Pass `-S` ("chop long lines") to `less` if `--wrap=never` is set in `bat`, see #1255 (@gahag) CHANGELOG.md:173:- Throw an error when `bat` is being used as `pager`, see #1343 (@adrian-rivera) CHANGELOG.md:225:## `bat` as a library CHANGELOG.md:246:- Cannot run `bat` with relative paths, see #1022 CHANGELOG.md:247:- bat mishighlights Users that start with digits in SSH config, see #984 CHANGELOG.md:268:- bat now prints an error if an invalid syntax is specified via `-l` or `--map-syntax`, see #1004 (@eth-p) CHANGELOG.md:270:## `bat` as a library CHANGELOG.md:276:- Compilation problems with `onig_sys` on various platforms have been resolved by upgrading to `syntect 4.2`, which includes a new `onig` version that allows to build `onig_sys` without the `bindgen` dependency. This removes the need for `libclang(-dev)` to be installed to compile `bat`. Package maintainers might want to remove `clang` as a build dependency. See #650 for more details. CHANGELOG.md:284: Users suffering from #865 ("no color for bat in ssh from a Windows client") can use the `ansi-dark` and `ansi-light` themes from now on. CHANGELOG.md:303:- Performance improvements when using custom caches (via `bat cache --build`): the `bat` startup time should now be twice as fast (@lzutao). CHANGELOG.md:309:## `bat` as a library CHANGELOG.md:320: in the header. This is useful when piping input into `bat`. See #654 and #892 (@neuronull). CHANGELOG.md:336:- When saving/reading user-provided syntaxes or themes, `bat` will now maintain a CHANGELOG.md:337: `metadata.yaml` file which includes information about the `bat` version which was CHANGELOG.md:342:## `bat` as a library CHANGELOG.md:346: API is still available (basically everything that is not in the root `bat` CHANGELOG.md:349: Note that this should still be considered a "beta" release of `bat`-as-a-library. CHANGELOG.md:354: everything required by `bat` the application. When depending on bat as a library, downstream CHANGELOG.md:358: bat = { version = "0.14", default-features = false } CHANGELOG.md:371:## `bat` as a library CHANGELOG.md:373:Beginning with this release, `bat` can be used as a library (#423). CHANGELOG.md:378:- Second attempt, complete restructuring of the `bat` crate, see #679 (@DrSensor) CHANGELOG.md:383:That being said, you can start using it! See the example programs in [`examples/`](https://github.com/sharkdp/bat/tree/master/examples). CHANGELOG.md:385:You can see the API documentation here: https://docs.rs/bat/ CHANGELOG.md:390: users need to update their bat config files (`bat --config-file`), if they have any `--map-syntax` settings CHANGELOG.md:407:- `BAT_CACHE_PATH` can be used to place cached `bat` assets in a non-standard path, see #829 (@neuronull) CHANGELOG.md:413:- 'bat cache' still takes precedence over existing files, see #666 (@sharkdp) CHANGELOG.md:425:- Enabled LTO, making `bat` about 10% faster, see #719 (@bolinfest, @sharkdp) CHANGELOG.md:426:- Suggestions non how to configure `bat` for MacOS dark mode, see README (@jerguslejko) CHANGELOG.md:427:- Extended ["Integration with other tools"](https://github.com/sharkdp/bat#integration-with-other-tools) section (@eth-p) CHANGELOG.md:428:- Updated [instrutions on how to use `bat` as a `man`-pager](https://github.com/sharkdp/bat#man), see #652, see #667 (@sharkdp) CHANGELOG.md:456:- `bat` is now in the official Ubuntu and Debian repositories, see #323 and #705 (@MarcoFalke) CHANGELOG.md:457:- `bat` can now be installed via MacPorts, see #675 (@bn3t) CHANGELOG.md:476:- Binary file content can now be viewed with `bat -A`, see #623, #640 (@pjsier and @sharkdp) CHANGELOG.md:477:- `bat` can now be used as a man pager. Take a look at the README and #523 for more details. CHANGELOG.md:506:- `bat` is now in the official Gentoo repositories, see #588 (@toku-sa-n) CHANGELOG.md:507:- `bat` is now in the official Alpine Linux repositories, see #586 (@5paceToast) CHANGELOG.md:508:- `bat` is in the official Fedora repositories, see #610 (@ignatenkobrain) CHANGELOG.md:534:- New ["Integration with other tools"](https://github.com/sharkdp/bat#integration-with-other-tools) section in the README. CHANGELOG.md:544:- `bat` is now available on Chocolatey, see #541 (@rasmuskriest) CHANGELOG.md:554:- **Change the default configuration directory on macOS** to `~/.config/bat`, see #442 (@lavifb). If you are on macOS, you need to copy your configuration directory from the previous place (`~/Library/Preferences/bat`) to the new place (`~/.config/bat`). CHANGELOG.md:559:- Rename `bat cache --init` to `bat cache --build`, see #498 CHANGELOG.md:560:- Move the `--config-dir` and `--cache-dir` options from `bat cache` to `bat` and hide them from the help text. CHANGELOG.md:596:- Added `BAT_CONFIG_PATH` environment variable to set a non-default path for `bat`s configuration file, see #375 (@deg4uss3r) CHANGELOG.md:618:- Avoid endless recursion when `PAGER="bat"`, see #383 (@rodorgas) CHANGELOG.md:622:- `bat` is now available on openSUSE, see #405 (@dmarcoux) CHANGELOG.md:651: The configuration file path can be accessed via `bat --config-file`. On Linux, CHANGELOG.md:652: it is stored in `~/.config/bat/config`. CHANGELOG.md:654:- Support for the `BAT_OPTS` environment variable with the same format as specified CHANGELOG.md:664: bat --map-syntax .config:json ... CHANGELOG.md:667: The option can be use multiple times. Note that you can easily make these mappings permanent by using bats new configuration file. CHANGELOG.md:671:- Support pager command-line arguments in `PAGER` and `BAT_PAGER`, see #352 (@Foxboron) CHANGELOG.md:689:- Bat Panics on Haskell Source Code, see #314 CHANGELOG.md:695:- Updated documentation on how to configure `bat`s pager CHANGELOG.md:703:- `bat` is now available via [Termux](https://termux.com/), see #341 (@fornwall) CHANGELOG.md:705:- `bat` is now available via [nix](https://nixos.org/nix), see #344 (@mgttlinger) CHANGELOG.md:707:- `bat` is now available via [Docker](https://hub.docker.com/r/danlynn/bat/), see #331 (@danlynn) CHANGELOG.md:717:- Bat Panics on Haskell Source Code, see #314 CHANGELOG.md:730: `--tabs` command-line option or the `BAT_TABS` environment variable. The CHANGELOG.md:733:- Added support for the `BAT_STYLE` environment variable, see #208 (@ms2300) CHANGELOG.md:764:- Added README section about "`bat` on Windows" (@Aankhen) CHANGELOG.md:772:- Fixed panic when running `bat --list-languages | head`, see #232 (@mchlrhw) CHANGELOG.md:786:- Major refactorings, enabling some progress on #150. In non-interactive mode, `bat` will now copy input bytes 1:1. CHANGELOG.md:792:- New themes in `$BAT_CONFIG_DIR/themes` are now loaded *in addition* to CHANGELOG.md:798:* Using `bat cache --init` leads to duplicated syntaxes, see #206 CHANGELOG.md:811:- The syntax highlighting theme can now be controlled by the `BAT_THEME` environment variable, see [README](https://github.com/sharkdp/bat#highlighting-theme) and #177 (@mandx) CHANGELOG.md:812:- The `PAGER` and `BAT_PAGER` environment variables can be used to control the pager that `bat` uses, see #158 and the [new README section](https://github.com/sharkdp/bat#using-a-different-pager) CHANGELOG.md:818:- The customization of syntax sets and theme sets is now separated. Syntax definitions are now loaded *in addition* to the ones that are stored in the `bat` binary by default. Please refer to these new sections in the README: [Adding new syntaxes](https://github.com/sharkdp/bat#adding-new-syntaxes--language-definitions), [Adding new themes](https://github.com/sharkdp/bat#adding-new-themes), also see #172 CHANGELOG.md:830:- `bat` is now in the official [Arch package repositories](https://www.archlinux.org/packages/community/x86_64/bat/). CHANGELOG.md:839:- Fix problem with `cargo test` when `bat` is not checked out in a Git repository, see #161 CHANGELOG.md:874:- [Comparison with alternative projects](https://github.com/sharkdp/bat/blob/master/doc/alternatives.md). CHANGELOG.md:875:- New "bat" logo in the README, see #119 (@jraulhernandezi) CHANGELOG.md:895: `bat cache`. See `bat cache -h` for all available commands. CHANGELOG.md:900:* Process substitution can now be used with bat (`bat <(echo a) <(echo b)`), see #80 CHANGELOG.md:912:- Added a new statically linked version of bat (`..-musl-..`) CONTRIBUTING.md:3:Thank you for considering to contribute to `bat`! CONTRIBUTING.md:9:If your contribution changes the behavior of `bat` (as opposed to a typo-fix CONTRIBUTING.md:12:therefore helps to get your changes into a new `bat` release faster. CONTRIBUTING.md:28:Please check out the [Development](https://github.com/sharkdp/bat#development) CONTRIBUTING.md:35:[feature request ticket](https://github.com/sharkdp/bat/issues/new?assignees=&labels=feature-request&template=feature_request.md) CONTRIBUTING.md:42:the [Customization](https://github.com/sharkdp/bat#customization) section CONTRIBUTING.md:47:[documentation](https://github.com/sharkdp/bat/blob/master/doc/assets.md) Cargo.toml:5:homepage = "https://github.com/sharkdp/bat" Cargo.toml:7:name = "bat" Cargo.toml:8:repository = "https://github.com/sharkdp/bat" Cargo.toml:16:# Feature required for bat the application. Should be disabled when depending on Cargo.toml:17:# bat as a library. Cargo.toml:40:# You need to use one of these if you depend on bat as a library: doc/fzf-preview.sh:6: bat \ doc/preview.sh:47:bat --color always \ doc/assets.md:3:Should you find that a particular syntax is not available within `bat` and think it should be included in `bat` by default, you can follow the instructions outlined below. doc/assets.md:5:`bat` uses the excellent [syntect](https://github.com/trishume/syntect) library to highlight source doc/assets.md:20:3. Run the `assets/create.sh` script. It calls `bat cache --build` to parse all available doc/assets.md:23:4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the doc/assets.md:24: `bat` binary. doc/assets.md:26:5. Use `bat --list-languages` to check if the new languages are available. doc/assets.md:31: file. A new binary cache file will be created once before every new release of `bat`. This doc/assets.md:36:`bat` has a set of syntax highlighting regression tests in `tests/syntax-tests`. The main idea is doc/assets.md:38:for some language is suddenly not working anymore or (2) `bat` suddenly crashes for some input (due doc/assets.md:43:1. Make sure that you are running the **latest version of `bat`** and that `bat` is available on doc/assets.md:45: your version of `bat` already has the new syntax builtin. doc/assets.md:50: be `test.rb` (adapt extension) but can also be adapted if that is necessary in order for `bat` to doc/assets.md:53: under the respective license and that the license is compatible with `bat`s license. If it doc/assets.md:62:6. Use `cat` or `bat --language=txt` to display the content of this file and make sure that the doc/assets.md:70:themes (`bat cache --clear`). doc/README-ja.md:2: bat - a cat clone with wings
doc/README-ja.md:3: Build Status doc/README-ja.md:4: license doc/README-ja.md:5: Version info
doc/README-ja.md:16: [中文] doc/README-ja.md:24:`bat` は多くのプログラミング言語やマークアップ言語の doc/README-ja.md:31:`bat` は `git` とも連携しており、差分を表現する記号が表示されます doc/README-ja.md:45:出力が1つの画面に対して大きすぎる場合、`bat` は自身の出力をページャー(例えば `less`) にパイプで繋げます。 doc/README-ja.md:50:`bat` は非対話型のターミナルを検出すると(すなわち他のプロセスにパイプしたりファイル出力していると)、 doc/README-ja.md:51:`bat` は `cat` の完全互換として振る舞い、 doc/README-ja.md:59:> bat README.md doc/README-ja.md:65:> bat src/*.rs doc/README-ja.md:73:> curl -s https://sh.rustup.rs | bat doc/README-ja.md:79:> yaml2json .travis.yml | json_pp | bat -l json doc/README-ja.md:84:> bat -A /etc/hosts doc/README-ja.md:87:`cat` の代わりに `bat` を使用する際の例: doc/README-ja.md:90:bat > note.md # quickly create a new file doc/README-ja.md:92:bat header.md content.md footer.md > document.md doc/README-ja.md:94:bat -n main.rs # show line numbers (only) doc/README-ja.md:96:bat f - g # output 'f', then stdin, then 'g'. doc/README-ja.md:103:[`fzf`](https://github.com/junegunn/fzf) のプレビューウィンドウに `bat` を使用できます。 doc/README-ja.md:104:その場合、`bat` の `--color=always` オプションを用いてカラー出力を強制しなければなりません。 doc/README-ja.md:107:fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' doc/README-ja.md:114:`find` の `-exec` オプションを使用して、`bat` ですべての検索結果をプレビューできます: doc/README-ja.md:116:find … -exec bat {} + doc/README-ja.md:119:[`fd`](https://github.com/sharkdp/fd) を使用している場合は、`-X` /`-exec-batch` オプションを使用して同じことを行うことができます: doc/README-ja.md:121:fd … -X bat doc/README-ja.md:126:[`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md) では、[`ripgrep`](https://github.com/BurntSushi/ripgrep) 検索結果のプリンターとして `bat` を使用できます。 doc/README-ja.md:129:batgrep needle src/ doc/README-ja.md:134:`bat` を `tail -f` と組み合わせて、構文強調表示を使用して特定のファイルを継続的に監視できます。 doc/README-ja.md:136:tail -f /var/log/pacman.log | bat --paging=never -l log doc/README-ja.md:142:`bat` を `git show` と組み合わせて、 doc/README-ja.md:145:git show v0.6.0:src/main.rs | bat -l rs doc/README-ja.md:152:`bat` の出力の行番号と Git 変更マーカーにより、ファイルの内容をコピーするのが難しくなる場合があります。 doc/README-ja.md:153:これを防ぐには、`-p` / `-plain` オプションを使用して `bat` を呼び出すか、 doc/README-ja.md:156:bat main.cpp | xclip doc/README-ja.md:158:`bat` は出力がリダイレクトされていることを検出し、プレーンファイルの内容を出力します。 doc/README-ja.md:162:`bat` は `MANPAGER` 環境変数を設定することにより、 doc/README-ja.md:166:export MANPAGER="sh -c 'col -bx | bat -l man -p'" doc/README-ja.md:173:これを新しいコマンドにバンドルしたい場合は [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md) も使用できます。 doc/README-ja.md:179:[`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) スクリプトは、コードをフォーマットし、`bat` で印刷するラッパーです。 doc/README-ja.md:184:[![Packaging status](https://repology.org/badge/vertical-allrepos/bat.svg)](https://repology.org/project/bat/versions) doc/README-ja.md:189:Ubuntu Eoan 19.10 または Debian 不安定版 sid 以降の [the Ubuntu `bat` package](https://packages.ubuntu.com/eoan/bat) または [the Debian `bat` package](https://packages.debian.org/sid/bat) からインストールできます: doc/README-ja.md:192:apt install bat doc/README-ja.md:195:`apt` を使用して `bat` をインストールした場合、実行可能ファイルの名前が `bat` ではなく `batcat` になることがあります([他のパッケージとの名前衝突のため](https://github.com/sharkdp/bat/issues/982))。`bat -> batcat` のシンボリックリンクまたはエイリアスを設定することで、実行可能ファイル名が異なることによる問題の発生を防ぎ、他のディストリビューションと一貫性を保てます。 doc/README-ja.md:199:ln -s /usr/bin/batcat ~/.local/bin/bat doc/README-ja.md:205:batの最新リリースを実行する場合、または Ubuntu/Debian の古いバージョンを使用している場合は、[release page](https://github.com/sharkdp/bat/releases) から最新の `.deb` パッケージをダウンロードし、 doc/README-ja.md:208:sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture doc/README-ja.md:214:公式のソースから [`bat` package](https://pkgs.alpinelinux.org/packages?name=bat) をインストールできます: doc/README-ja.md:217:apk add bat doc/README-ja.md:222:[Arch Linuxの公式リソース](https://www.archlinux.org/packages/community/x86_64/bat/) doc/README-ja.md:226:pacman -S bat doc/README-ja.md:231:公式の [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/) リポジトリから [the `bat` package](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) をインストールできます。 doc/README-ja.md:234:dnf install bat doc/README-ja.md:240:[the `bat` package](https://packages.gentoo.org/packages/sys-apps/bat) をインストールできます。 doc/README-ja.md:243:emerge sys-apps/bat doc/README-ja.md:248:xbps-install経由で `bat` をインストールできます。 doc/README-ja.md:250:xbps-install -S bat doc/README-ja.md:255:pkg を使用してプリコンパイルされた [`bat` package](https://www.freshports.org/textproc/bat) をインストールできます: doc/README-ja.md:258:pkg install bat doc/README-ja.md:264:cd /usr/ports/textproc/bat doc/README-ja.md:270:`bat` を [nix package manager](https://nixos.org/nix) 経由でインストールすることができます: doc/README-ja.md:273:nix-env -i bat doc/README-ja.md:278:`bat` をzypperでインストールすることができます: doc/README-ja.md:281:zypper install bat doc/README-ja.md:286:[Homebrew](http://braumeister.org/formula/bat)で `bat` をインストールできます: doc/README-ja.md:289:brew install bat doc/README-ja.md:292:または [MacPorts](https://ports.macports.org/port/bat/summary) で `bat` をインストールします: doc/README-ja.md:295:port install bat doc/README-ja.md:300:Windowsにbatをインストールするいくつかのオプションがあります。 doc/README-ja.md:301:batをインストールしたら [Windowsでのbatの使用](#windows-での-bat-の利用) セクションをご覧ください。 doc/README-ja.md:305:[Chocolatey](https://chocolatey.org/packages/Bat) から `bat` をインストールできます: doc/README-ja.md:307:choco install bat doc/README-ja.md:312:[scoop](https://scoop.sh/) から `bat` をインストールできます: doc/README-ja.md:314:scoop install bat doc/README-ja.md:321:[リリースページ](https://github.com/sharkdp/bat/releases) からビルド済みのバイナリをダウンロードできます。 doc/README-ja.md:327:コンテナ内で `bat` を使いたい方のために [Docker image](https://hub.docker.com/r/danlynn/bat/) が用意されています: doc/README-ja.md:329:docker pull danlynn/bat doc/README-ja.md:330:alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat' doc/README-ja.md:339:ansible-galaxy install aeimer.install_bat doc/README-ja.md:344:# Playbook to install bat doc/README-ja.md:347: - aeimer.install_bat doc/README-ja.md:350:- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat) doc/README-ja.md:351:- [GitHub](https://github.com/aeimer/ansible-install-bat) doc/README-ja.md:364:多くの異なるアーキテクチャのためのプレビルドバージョンを[リリースページ](https://github.com/sharkdp/bat/releases)からチェックしてみてください。静的にリンクされている多くのバイナリも利用できます: ファイル名に `musl` を含むアーカイブを探してみてください。 doc/README-ja.md:369:`bat` をソースからビルドしたいならば、Rust 1.36 以上の環境が必要です。 doc/README-ja.md:373:cargo install --locked bat doc/README-ja.md:382:`bat --list-themes` を使うと現在利用可能なシンタックスハイライトのテーマを入手できます。 doc/README-ja.md:384:`--theme=TwoDark` オプションをつけるか `BAT_THEME` という環境変数に doc/README-ja.md:385:`TwoDark` を代入する必要があります。 シェルの起動ファイルに `export BAT_THEME="TwoDark"` doc/README-ja.md:386:と定義すればその設定が変わることはないでしょう。あるいは、 `bat` の doc/README-ja.md:392:bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" doc/README-ja.md:395:`bat` はデフォルトだと黒い背景色のターミナルに適しています。 doc/README-ja.md:402:`--style` を使うことで `bat` の表示の見た目を変更することができます。 doc/README-ja.md:405:環境変数に `BAT_STYLE` を定義するとこれらの設定を永続的に使用することができます。 doc/README-ja.md:410:`bat` はシンタックスハイライトのための [`syntect`](https://github.com/trishume/syntect/) doc/README-ja.md:418:mkdir -p "$(bat --config-dir)/syntaxes" doc/README-ja.md:419:cd "$(bat --config-dir)/syntaxes" doc/README-ja.md:429:bat cache --build doc/README-ja.md:432:最後に `bat --list-languages` と入力すると新しい言語が利用可能かどうかチェックします。 doc/README-ja.md:437:bat cache --clear doc/README-ja.md:446:mkdir -p "$(bat --config-dir)/themes" doc/README-ja.md:447:cd "$(bat --config-dir)/themes" doc/README-ja.md:453:bat cache --build doc/README-ja.md:456:最後に、 `bat --list-themes` で新しいテーマが利用可能かチェックします doc/README-ja.md:460:`bat` は環境変数 `PAGER` に使用するページャーを明記します。 doc/README-ja.md:463:または、`PAGER` を上書きする環境変数として `BAT_PAGER` を定義することも可能です。 doc/README-ja.md:466:`PAGER`/`BAT_PAGER` 環境変数を定義してください: doc/README-ja.md:469:export BAT_PAGER="less -RF" doc/README-ja.md:472:環境変数を利用する代わりに、 `bat` の [設定ファイル](#設定ファイル) を使用して設定も可能です(`--pager` オプション) doc/README-ja.md:475:`bat` はページャーの以下のコマンドラインオプション を受け付けるでしょう: doc/README-ja.md:491:macOSでダークモード機能を使用する場合、OSテーマに基づいて異なるテーマを使用するように `bat` を構成することができます。 doc/README-ja.md:496:alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" doc/README-ja.md:501:`bat` は設定ファイルでカスタマイズすることが可能です。ファイルの場所はOSに依存します。 doc/README-ja.md:504:bat --config-file doc/README-ja.md:507:または、`BAT_CONFIG_PATH` 環境変数を使用して、`bat` が doc/README-ja.md:510:export BAT_CONFIG_PATH="/path/to/bat.conf" doc/README-ja.md:515:この設定ファイルはコマンドライン引数の単純なリストです。 `bat --help` を利用すると、利用可能なオプションとその値を閲覧することができます。さらに、`#` でコメント文を加えることができます。 doc/README-ja.md:535:## Windows での `bat` の利用 doc/README-ja.md:537:Windows 上で `bat` はほとんど動作しますが、いくつかの機能は設定を必要をする場合があります。 doc/README-ja.md:555:`BAT_PAGER` に空文字を設定することでページングを完全に無効にできます。 doc/README-ja.md:559:Windows上の `bat` は Cygwin のunix風のpath(`/cygdrive/*`)をネイティブサポートしていません。絶対的なcygwinパスを引数として受けたときに、 `bat` は以下のエラーを返すでしょう: `The system cannot find the path specified. (os error 3)` doc/README-ja.md:564:bat() { doc/README-ja.md:573: command bat "${args[@]}" doc/README-ja.md:581:`bat` はターミナルがトゥルーカラーをサポートしている/していないに関係なくサポートします。 doc/README-ja.md:588:`24bit` のどちらかを代入してください。さもなければ、`bat` はどの色を使うのか決定することができません。または、24-bit エスケープシーケンスがサポートされません doc/README-ja.md:593:異なるテーマを試してみてください(`bat --list-themes` でテーマを閲覧できます)。 doc/README-ja.md:598:`bat` は UTF-16 と同様に UTF-8 をネイティブにサポートします。 doc/README-ja.md:603:iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat doc/README-ja.md:605:注: `bat` が構文を自動検出できない場合は doc/README-ja.md:612:git clone --recursive https://github.com/sharkdp/bat doc/README-ja.md:615:cd bat doc/README-ja.md:624:# Build a bat binary with modified syntaxes and themes doc/README-ja.md:636:`bat` は以下の目標を達成しようと試みています: doc/README-ja.md:647:Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). doc/README-ja.md:649:`bat` は MIT License 及び Apache License 2.0 の両方の条件の下で配布されています。 doc/README-ko.md:2: bat - a cat clone with wings
doc/README-ko.md:3: Build Status doc/README-ko.md:4: license doc/README-ko.md:5: Version info
doc/README-ko.md:16: [中文] doc/README-ko.md:24:`bat`은 다양한 프로그래밍 및 마크업 언어의 문법 강조(syntax highlighting) 기능을 doc/README-ko.md:31:`bat`은 `git`을 통해 인덱스와 함께 변경분을 표시합니다 doc/README-ko.md:44:`bat`은 기본적으로 한 화면에 비해 출력이 큰 경우 `less`와 같은 페이저(pager)로 doc/README-ko.md:46:만약 `bat`을 언제나 `cat`처럼 작동하게 하려면 (출력을 페이지하지 않기), doc/README-ko.md:48:셸(shell) 설정에서 `cat`을 `bat`의 alias로 사용하려면, doc/README-ko.md:49:`alias cat='bat --paging=never'`를 써서 기본 행동을 유지할 수 있습니다. doc/README-ko.md:53:페이저(pager)를 사용하더라도 `bat`은 파일들을 연결(concatenate)할 수 있습니다 doc/README-ko.md:55:`bat`이 비대화형(non-interactive) 터미널(예를 들어, 다른 프로세스나 파일에 doc/README-ko.md:56:연결(pipe)한 경우)을 감지하면, `bat`은 `--pager` 옵션의 값과 상관없이 `cat`과 doc/README-ko.md:64:> bat README.md doc/README-ko.md:70:> bat src/*.rs doc/README-ko.md:78:> curl -s https://sh.rustup.rs | bat doc/README-ko.md:84:> yaml2json .travis.yml | json_pp | bat -l json doc/README-ko.md:89:> bat -A /etc/hosts doc/README-ko.md:95:bat > note.md # quickly create a new file doc/README-ko.md:97:bat header.md content.md footer.md > document.md doc/README-ko.md:99:bat -n main.rs # show line numbers (only) doc/README-ko.md:101:bat f - g # output 'f', then stdin, then 'g'. doc/README-ko.md:108:`bat`을 [`fzf`](https://github.com/junegunn/fzf)의 프리뷰로 쓸 수 있습니다. doc/README-ko.md:109:이를 위해서는 `bat`의 `--color=always` 옵션으로 항상 컬러 출력이 나오게 해야 doc/README-ko.md:113:fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' doc/README-ko.md:120:`find`의 `-exec` 옵션을 사용하여 모든 검색 결과를 `bat`로 미리 볼 수 있습니다: doc/README-ko.md:122:find … -exec bat {} + doc/README-ko.md:125:[`fd`](https://github.com/sharkdp/fd)를 사용하는 경우, `-X`/`--exec-batch` doc/README-ko.md:128:fd … -X bat doc/README-ko.md:133:[`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md)을 doc/README-ko.md:134:통해 `bat`로 [`ripgrep`](https://github.com/BurntSushi/ripgrep)의 검색 결과를 doc/README-ko.md:138:batgrep needle src/ doc/README-ko.md:143:`bat`와 `tail -f`를 함께 사용하여 주어진 파일을 문법 강조하며 지속적으로 doc/README-ko.md:146:tail -f /var/log/pacman.log | bat --paging=never -l log doc/README-ko.md:154:`bat`과 `git show`를 함께 사용하여 주어진 파일의 이전 버전을 올바른 문법 강조로 doc/README-ko.md:157:git show v0.6.0:src/main.rs | bat -l rs doc/README-ko.md:162:`bat`과 `git diff`를 함께 사용하여 수정된 코드 주위의 줄들을 올바른 문법 강조로 doc/README-ko.md:165:batdiff() { doc/README-ko.md:166: git diff --name-only --diff-filter=d | xargs bat --diff doc/README-ko.md:170:[`bat-extras`](https://github.com/eth-p/bat-extras)의 `batdiff`를 확인해 보세요. doc/README-ko.md:177:`bat` 출력에 줄 번호와 Git 수정 내역이 포함되어서 파일의 내용을 복사하기 doc/README-ko.md:179:이 경우에는 `bat`의 `-p`/`--plain` 옵션을 사용하거나 간단히 `xclip`으로 출력을 doc/README-ko.md:182:bat main.cpp | xclip doc/README-ko.md:184:`bat`는 출력이 우회되고 있다는 것을 감지하여 파일 내용 그대로를 출력합니다. doc/README-ko.md:188:`MANPAGER` 환경 변수 설정을 통해 `bat`을 `man`의 컬러 페이저(pager)로 쓸 수 doc/README-ko.md:192:export MANPAGER="sh -c 'col -bx | bat -l man -p'" doc/README-ko.md:195:(Debian이나 Ubuntu를 사용한다면 `bat`을 `batcat`으로 치환하세요.) doc/README-ko.md:200:[`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md)을 쓸 doc/README-ko.md:207:[작동하지 않습니다](https://github.com/sharkdp/bat/issues/1145). doc/README-ko.md:211:[`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) doc/README-ko.md:212:스크립트는 코드를 포맷하고 `bat`으로 출력하는 래퍼(wrapper)입니다. doc/README-ko.md:217:[![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg)](https://repology.org/project/bat-cat/versions) doc/README-ko.md:222:`bat`은 [Ubuntu](https://packages.ubuntu.com/eoan/bat)와 doc/README-ko.md:223:[Debian](https://packages.debian.org/sid/bat) 패키지 배포 과정에 도입되는 중이며, doc/README-ko.md:225:현재 Debain에서는 불안정한 "Sid" 브랜치에서만 `bat`이 제공됩니다. doc/README-ko.md:230:apt install bat doc/README-ko.md:233:**중요**: 만약 `bat`을 이와 같이 설치한다면, ([다른 패키지와의 이름 doc/README-ko.md:234:충돌](https://github.com/sharkdp/bat/issues/982)로 인하여) `bat` 대신에 doc/README-ko.md:235:`batcat`이라는 이름의 실행 파일로 설치될 수 있음을 참고하세요. doc/README-ko.md:236:이에 따른 문제들과 다른 배포판들과의 일관성을 위하여 `bat -> batcat` symlink doc/README-ko.md:240:ln -s /usr/bin/batcat ~/.local/bin/bat doc/README-ko.md:247:`bat`을 원한다면, [릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 doc/README-ko.md:251:sudo dpkg -i bat_0.18.3_amd64.deb # adapt version number and architecture doc/README-ko.md:257:[`bat` 패키지](https://pkgs.alpinelinux.org/packages?name=bat)를 설치할 수 doc/README-ko.md:261:apk add bat doc/README-ko.md:267:[`bat` 패키지](https://www.archlinux.org/packages/community/x86_64/bat/)를 doc/README-ko.md:271:pacman -S bat doc/README-ko.md:279:[`bat` 패키지](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506)를 doc/README-ko.md:283:dnf install bat doc/README-ko.md:288:dev-kit을 통해 [`bat` 패키지](https://github.com/funtoo/dev-kit/tree/1.4-release/sys-apps/bat)를 설치할 수 있습니다: doc/README-ko.md:291:emerge sys-apps/bat doc/README-ko.md:297:[`bat` 패키지](https://packages.gentoo.org/packages/sys-apps/bat)를 설치할 수 doc/README-ko.md:301:emerge sys-apps/bat doc/README-ko.md:306:xbps-install을 이용해 `bat`을 설치할 수 있습니다: doc/README-ko.md:308:xbps-install -S bat doc/README-ko.md:313:pkg를 이용해 `bat`을 설치할 수 있습니다: doc/README-ko.md:315:pkg install bat doc/README-ko.md:321:[`bat` 패키지](https://www.freshports.org/textproc/bat)를 설치할 수 있습니다: doc/README-ko.md:324:pkg install bat doc/README-ko.md:330:cd /usr/ports/textproc/bat doc/README-ko.md:336:[nix package manager](https://nixos.org/nix)를 이용해 `bat`을 설치할 수 doc/README-ko.md:340:nix-env -i bat doc/README-ko.md:345:zypper를 이용해 `bat`을 설치할 수 있습니다: doc/README-ko.md:348:zypper install bat doc/README-ko.md:355:[문제](https://github.com/sharkdp/bat/issues/1519)가 있을 수 있습니다. doc/README-ko.md:360:[macOS의 Homebrew](https://formulae.brew.sh/formula/bat) 또는 doc/README-ko.md:361:[Linux의 Homebrew](https://formulae.brew.sh/formula-linux/bat)를 이용하여 doc/README-ko.md:362:`bat`을 설치할 수 있습니다. doc/README-ko.md:365:brew install bat doc/README-ko.md:370:[MacPorts](https://ports.macports.org/port/bat/summary)를 이용하여 `bat`을 doc/README-ko.md:374:port install bat doc/README-ko.md:379:Windows에서 `bat`을 설치할 수 있는 몇 가지 옵션들이 있습니다. doc/README-ko.md:380:먼저 `bat`을 설치한 후, doc/README-ko.md:381:["Windows에서 `bat` 사용하기"](#windows에서-bat-사용하기) 섹션을 살펴보세요. doc/README-ko.md:390:[Chocolatey](https://chocolatey.org/packages/Bat)를 이용해 `bat`을 설치할 수 doc/README-ko.md:393:choco install bat doc/README-ko.md:398:[scoop](https://scoop.sh/)을 이용해 `bat`을 설치할 수 있습니다: doc/README-ko.md:400:scoop install bat doc/README-ko.md:405:[릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 사전 빌드된 doc/README-ko.md:413:[릴리즈 페이지](https://github.com/sharkdp/bat/releases)에서 다양한 아키텍처를 doc/README-ko.md:419:`bat`의 소스를 빌드하기 위해서는, Rust 1.46 이상이 필요합니다. doc/README-ko.md:423:cargo install --locked bat doc/README-ko.md:435:`bat --list-themes`을 사용하여 사용 가능한 문법 강조 테마들의 목록을 확인할 수 doc/README-ko.md:437:`TwoDark` 테마를 선택하려면, `--theme=TwoDark` 옵션과 함께 `bat`을 사용하거나 doc/README-ko.md:438:`BAT_THEME` 환경 변수를 `TwoDark`로 설정하세요. doc/README-ko.md:439:셸 시작 파일에 `export BAT_THEME="TwoDark"` 를 정의해 영구적으로 설정할 수 doc/README-ko.md:441:이 밖에 `bat`의 [설정 파일](#설정-파일)을 이용할 수 있습니다. doc/README-ko.md:447:bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" doc/README-ko.md:450:`bat`은 기본적으로 어두운 배경에 적합합니다. doc/README-ko.md:458:`bat`은 트루컬러 지원이 되더라도 항상 doc/README-ko.md:478:- 만약 터미널 테마를 바꾼다면, 이미 화면 상의 `bat`의 출력도 이에 맞추어 doc/README-ko.md:483:`--style` 옵션을 이용하면 `bat`의 출력 모양을 조절할 수 있습니다. doc/README-ko.md:486:`BAT_STYLE` 환경 변수를 정의하여 이러한 수정을 영구적으로 하거나 `bat`의 doc/README-ko.md:491:만약 `bat`에서 특정 문법이 지원되지 않을 경우, 다음의 절차를 통해 현재 `bat` doc/README-ko.md:494:`bat`은 문법 강조를 위해 훌륭한 doc/README-ko.md:506: mkdir -p "$(bat --config-dir)/syntaxes" doc/README-ko.md:507: cd "$(bat --config-dir)/syntaxes" doc/README-ko.md:517: bat cache --build doc/README-ko.md:520:3. 마지막으로, `bat --list-languages`로 새로 추가한 언어가 사용 가능한지 doc/README-ko.md:526: bat cache --clear doc/README-ko.md:529:4. 만약 특정 문법이 `bat`에 기본적으로 포함되어 있어야 한다고 생각한다면, 방침과 doc/README-ko.md:531: 주세요: [문법 요청하기](https://github.com/sharkdp/bat/issues/new?labels=syntax-request&template=syntax_request.md). doc/README-ko.md:539:mkdir -p "$(bat --config-dir)/themes" doc/README-ko.md:540:cd "$(bat --config-dir)/themes" doc/README-ko.md:546:bat cache --build doc/README-ko.md:549:마지막으로 `bat --list-themes`을 통해 새로 추가한 테마들이 사용 가능한지 doc/README-ko.md:559:(`bat --list-languages`를 통해 개요를 확인하세요). doc/README-ko.md:561:참고: 이 옵션은 커맨드 라인에 넘겨 주는 것보다는 `bat`의 설정 파일에 넣는 것이 doc/README-ko.md:584:`bat`은 환경 변수 `PAGER`에 명시된 페이저를 사용합니다. doc/README-ko.md:586:만약 다른 페이저를 사용하고 싶다면, `PAGER` 변수를 수정하거나 `BAT_PAGER` 환경 doc/README-ko.md:589:만약 커맨드라인 인수들을 페이저에게 넘겨 주려면, `PAGER`/`BAT_PAGER` 변수로 doc/README-ko.md:593:export BAT_PAGER="less -RF" doc/README-ko.md:596:환경 변수를 사용하는 대신, `bat`의 [설정 파일](#설정-파일)로 페이저를 설정할 doc/README-ko.md:600:옵션이 지정되어 있지 않다면), `bat`은 다음 옵션들을 페이저로 넘겨줍니다: doc/README-ko.md:619:`bat`은 페이저에 의존하지 않고 탭을 4 스페이스로 확장합니다. doc/README-ko.md:623:**참고**: (`bat`의 `--pager` 인자 혹은 `less`의 `LESS` 환경 변수를 통해) doc/README-ko.md:627:`bat`을 `--tabs=0`과 함께 호출하면 이를 오버라이드하여 페이저가 탭을 처리하게 doc/README-ko.md:632:macOS에서 다크 모드를 사용하고 있다면, `bat`가 OS 테마에 따라 다른 테마를 doc/README-ko.md:638:alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" doc/README-ko.md:643:`bat`는 설정 파일로도 사용자화 할 수 있습니다. doc/README-ko.md:647:bat --config-file doc/README-ko.md:650:또는, `BAT_CONFIG_PATH` 환경 변수를 사용하여 `bat`가 설정 파일의 기본 경로 doc/README-ko.md:653:export BAT_CONFIG_PATH="/path/to/bat.conf" doc/README-ko.md:658:bat --generate-config-file doc/README-ko.md:664:`bat --help`로 가능한 모든 옵션과 값들을 확인하세요. doc/README-ko.md:682:## Windows에서 `bat` 사용하기 doc/README-ko.md:684:`bat`는 대부분의 경우 Windows에서 기본적으로 잘 작동하지만, 일부 기능은 추가적인 doc/README-ko.md:715:`BAT_PAGER`을 빈 문자열로 설정하여 페이징을 완전히 비활성화 할 수 있습니다. doc/README-ko.md:719:Windows에서의 `bat`은 기본적으로 Cygwin의 unix 스타일 경로(`/cygdrive/*`)를 doc/README-ko.md:721:Cygwin 절대 경로를 인자로 받았을 때, `bat`은 다음과 같은 오류를 반환합니다: doc/README-ko.md:728:bat() { doc/README-ko.md:737: command bat "${args[@]}" doc/README-ko.md:745:`bat`은 터미널의 트루컬러 지원 여부와 상관 없이 동작합니다. doc/README-ko.md:754:그렇지 않을 경우, `bat`은 24비트 확장열(escape sequence)이 지원되는지 여부를 doc/README-ko.md:759:다른 테마를 사용해 보세요 (`bat --list-themes`에서 목록을 볼 수 있습니다). doc/README-ko.md:764:`bat`은 기본적으로 UTF-8과 UTF-16을 지원합니다. doc/README-ko.md:770:iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat doc/README-ko.md:772:참고: `bat`으로 문법 자동 감지가 되지 않는 경우에는 `-l`/`--language` 옵션을 doc/README-ko.md:779:git clone --recursive https://github.com/sharkdp/bat doc/README-ko.md:782:cd bat doc/README-ko.md:791:# 수정된 문법과 테마가 적용된 bat 바이너리 빌드 doc/README-ko.md:796:`bat`의 pretty-printing 기능을 라이브러리로 사용하는 애플리케이션을 만들고 doc/README-ko.md:797:싶다면, [API 문서](https://docs.rs/bat/)를 살펴보세요. doc/README-ko.md:798:참고로 `bat`에 라이브러리로써 의존한다면, `regex-onig`나 `regex-fancy`를 doc/README-ko.md:814:만약 `bat`의 취약점을 발견하였다면, [David Peter](https://david-peter.de/)에게 메일로 연락주시기 바랍니다. doc/README-ko.md:818:`bat`은 다음과 같은 목표를 달성하려고 합니다: doc/README-ko.md:829:Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). doc/README-ko.md:831:`bat`는 여러분의 선택에 따라 MIT 라이센스 또는 Apache 라이센스 2.0의 조건에 따라 doc/alternatives.md:3:The following table tries to give an overview *from `bat`s perspective*, i.e. we only compare doc/alternatives.md:4:categories which are relevant for `bat`. Some of these projects have completely different goals and doc/alternatives.md:5:if you are not looking for a program like `bat`, this comparison might not be for you. doc/alternatives.md:7:| | 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) | doc/alternatives.md:9:| 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: | doc/alternatives.md:43:cmd_bat="bat --style=full --color=always --paging=never '$SRC'" doc/alternatives.md:44:cmd_bat_simple="bat --plain --wrap=never --tabs=0 --color=always --paging=never '$SRC'" doc/alternatives.md:54: "$cmd_bat" \ doc/alternatives.md:55: "$cmd_bat_simple" \ doc/README-ru.md:2: bat - a cat clone with wings
doc/README-ru.md:3: Build Status doc/README-ru.md:4: license doc/README-ru.md:5: Version info
doc/README-ru.md:16: [中文] doc/README-ru.md:24:`bat` поддерживает выделение синтаксиса для огромного количества языков программирования и разметки: doc/README-ru.md:29:`bat` использует `git`, чтобы показать изменения в коде doc/README-ru.md:42:`bat` умеет перенаправлять вывод в `less`, если вывод не помещается на экране полностью. doc/README-ru.md:47:`bat` обнаружит неинтерактивный терминал (например, когда вы перенаправляете вывод в файл или процесс), он будет работать как утилита `cat` и выведет содержимое файлов как обычный текст (без подсветки синтаксиса). doc/README-ru.md:54:> bat README.md doc/README-ru.md:60:> bat src/*.rs doc/README-ru.md:66:> curl -s https://sh.rustup.rs | bat doc/README-ru.md:72:> yaml2json .travis.yml | json_pp | bat -l json doc/README-ru.md:77:> bat -A /etc/hosts doc/README-ru.md:83:bat > note.md # мгновенно создаем новый файл doc/README-ru.md:85:bat header.md content.md footer.md > document.md doc/README-ru.md:87:bat -n main.rs # показываем только количество строк doc/README-ru.md:89:bat f - g # выводит 'f' в stdin, а потом 'g'. doc/README-ru.md:96:Вы можете использовать флаг `-exec` в `find`, чтобы посмотреть превью всех файлов в `bat` doc/README-ru.md:98:find … -exec bat {} + doc/README-ru.md:101:Если вы используете [`fd`](https://github.com/sharkdp/fd), применяйте для этого флаг `-X`/`--exec-batch`: doc/README-ru.md:103:fd … -X bat doc/README-ru.md:108:С помощью [`batgrep`](https://github.com/eth-p/bat-extras/blob/master/doc/batgrep.md), `bat` может быть использован для вывода результата запроса [`ripgrep`](https://github.com/BurntSushi/ripgrep) doc/README-ru.md:111:batgrep needle src/ doc/README-ru.md:116:`bat` может быть использован вместе с `tail -f`, чтобы выводить содержимое файла с подсветкой синтаксиса в реальном времени. doc/README-ru.md:118:tail -f /var/log/pacman.log | bat --paging=never -l log doc/README-ru.md:124:Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с выделением синтаксиса: doc/README-ru.md:126:git show v0.6.0:src/main.rs | bat -l rs doc/README-ru.md:136:bat main.cpp | xclip doc/README-ru.md:138:`bat` обнаружит перенаправление вывода и выведет обычный текст без выделения синтаксиса. doc/README-ru.md:142:`bat` может быть использован в виде выделения цвета для `man`, для этого установите переменную окружения doc/README-ru.md:146:export MANPAGER="sh -c 'col -bx | bat -l man -p'" doc/README-ru.md:152:Если вы хотите сделать этой одной командой, вы можете использовать [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md). doc/README-ru.md:158:[`Prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) — скрипт, который форматирует код и выводит его с помощью `bat`. doc/README-ru.md:163:[![Packaging status](https://repology.org/badge/vertical-allrepos/bat.svg)](https://repology.org/project/bat/versions) doc/README-ru.md:168:`bat` есть в репозиториях [Ubuntu](https://packages.ubuntu.com/eoan/bat) и doc/README-ru.md:169:[Debian](https://packages.debian.org/sid/bat) и доступен начиная с Ubuntu Eoan 19.10. На Debian `bat` пока что доступен только с нестабильной веткой "Sid". doc/README-ru.md:171:Если ваша версия Ubuntu/Debian достаточно новая, вы можете установить `bat` так: doc/README-ru.md:174:apt install bat doc/README-ru.md:177:Если вы установили `bat` таким образом, то бинарный файл может быть установлен как `batcat` вместо `bat` (из-за [конфликта имени с другим пакетом](https://github.com/sharkdp/bat/issues/982)). Вы можете сделать симлинк или алиас `bat -> batcat`, чтобы предотвратить подобные проблемы и в других дистрибутивах. doc/README-ru.md:181:ln -s /usr/bin/batcat ~/.local/bin/bat doc/README-ru.md:187:Если пакет еще недоступен в вашем Ubuntu/Debian дистрибутиве или вы хотите установить самую последнюю версию `bat`, то вы можете скачать самый последний `deb`-пакет отсюда: doc/README-ru.md:188:[release page](https://github.com/sharkdp/bat/releases) и установить так: doc/README-ru.md:191:sudo dpkg -i bat_0.18.3_amd64.deb # измените архитектуру и версию doc/README-ru.md:196:Вы можете установить [`bat`](https://pkgs.alpinelinux.org/packages?name=bat) из официальных источников: doc/README-ru.md:199:apk add bat doc/README-ru.md:204:Вы можете установить [`bat`](https://www.archlinux.org/packages/community/x86_64/bat/) из официального источника: doc/README-ru.md:207:pacman -S bat doc/README-ru.md:212:Вы можете установить [`bat`](https://koji.fedoraproject.org/koji/packageinfo?packageID=27506) из официального репозитория [Fedora Modular](https://docs.fedoraproject.org/en-US/modularity/using-modules/). doc/README-ru.md:215:dnf install bat doc/README-ru.md:220:Вы можете установить [`bat`](https://packages.gentoo.org/packages/sys-apps/bat) из официальных источников: doc/README-ru.md:223:emerge sys-apps/bat doc/README-ru.md:228:Вы можете установить `bat` с помощью `xbps-install`: doc/README-ru.md:230:xbps-install -S bat doc/README-ru.md:235:Вы можете установить [`bat`](https://www.freshports.org/textproc/bat) с помощью `pkg`: doc/README-ru.md:238:pkg install bat doc/README-ru.md:244:cd /usr/ports/textproc/bat doc/README-ru.md:250:Вы можете установить `bat`, используя [nix package manager](https://nixos.org/nix): doc/README-ru.md:253:nix-env -i bat doc/README-ru.md:258:Вы можете установить `bat` с помощью `zypper`: doc/README-ru.md:261:zypper install bat doc/README-ru.md:266:Вы можете установить `bat` с помощью [Homebrew](http://braumeister.org/formula/bat): doc/README-ru.md:269:brew install bat doc/README-ru.md:272:Или же установить его с помощью [MacPorts](https://ports.macports.org/port/bat/summary): doc/README-ru.md:275:port install bat doc/README-ru.md:280:Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#using-bat-on-windows). doc/README-ru.md:284:Вы можете установить `bat` с помощью [Chocolatey](https://chocolatey.org/packages/Bat): doc/README-ru.md:286:choco install bat doc/README-ru.md:291:Вы можете установить `bat` с помощью [scoop](https://scoop.sh/): doc/README-ru.md:293:scoop install bat doc/README-ru.md:300:Их вы можете скачать на [странице релизов](https://github.com/sharkdp/bat/releases). doc/README-ru.md:306:Вы можете использовать [Docker image](https://hub.docker.com/r/danlynn/bat/), чтобы запустить `bat` в контейнере: doc/README-ru.md:308:docker pull danlynn/bat doc/README-ru.md:309:alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat' doc/README-ru.md:314:Вы можете установить `bat` с [Ansible](https://www.ansible.com/): doc/README-ru.md:318:ansible-galaxy install aeimer.install_bat doc/README-ru.md:323:# Playbook для установки bat doc/README-ru.md:326: - aeimer.install_bat doc/README-ru.md:329:- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat) doc/README-ru.md:330:- [GitHub](https://github.com/aeimer/ansible-install-bat) doc/README-ru.md:342:Перейдите на [страницу релизов](https://github.com/sharkdp/bat/releases) для doc/README-ru.md:343:скомпилированных файлов `bat` для различных платформ. Бинарные файлы со статической связкой так же доступны: выбирайте архив с `musl` в имени. doc/README-ru.md:347:Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.46 или выше. После этого используйте `cargo`, чтобы все скомпилировать: doc/README-ru.md:350:cargo install --locked bat doc/README-ru.md:357:Используйте `bat --list-themes`, чтобы вывести список всех доступных тем. Для выбора темы `TwoDark` используйте `bat` с флагом doc/README-ru.md:358:`--theme=TwoDark` или выставьте переменную окружения `BAT_THEME` в `TwoDark`. Используйте `export BAT_THEME="TwoDark"` в конфигурационном файле вашей оболочки, чтобы изменить ее навсегда. Или же используйте [конфигурационный файл](https://github.com/sharkdp/bat#configuration-file) `bat`. doc/README-ru.md:362:bat --list-themes | fzf --preview="bat --theme={} --color=always /путь/к/файлу" doc/README-ru.md:365:`bat` отлично смотрится на темном фоне. Однако если ваш терминал использует светлую тему, то такие темы как `GitHub` или `OneHalfLight` будут смотреться куда лучше! doc/README-ru.md:366:Вы также можете использовать новую тему, для этого перейдите [в раздел добавления тем](https://github.com/sharkdp/bat#добавление-новых-тем). doc/README-ru.md:370:Вы можете использовать флаг `--style`, чтобы изменять внешний вид вывода в `bat`. doc/README-ru.md:371:Например, вы можете использовать `--style=numbers,changes`, чтобы показать только количество строк и изменений в Git. Установите переменную окружения `BAT_STYLE` чтобы изменить это навсегда, или используйте [конфиг файл](https://github.com/sharkdp/bat#configuration-file) `bat`. doc/README-ru.md:375:`bat` использует [`syntect`](https://github.com/trishume/syntect/) для выделения синтаксиса. `syntect` может читать doc/README-ru.md:382:mkdir -p "$(bat --config-dir)/syntaxes" doc/README-ru.md:383:cd "$(bat --config-dir)/syntaxes" doc/README-ru.md:393:bat cache --build doc/README-ru.md:396:Теперь вы можете использовать `bat --list-languages`, чтобы проверить, доступны ли новые языки. doc/README-ru.md:401:bat cache --clear doc/README-ru.md:410:mkdir -p "$(bat --config-dir)/themes" doc/README-ru.md:411:cd "$(bat --config-dir)/themes" doc/README-ru.md:417:bat cache --build doc/README-ru.md:420:Теперь используйте `bat --list-themes`, чтобы проверить доступность новых тем. doc/README-ru.md:424:`bat` использует пейджер, указанный в переменной окружения `PAGER`. Если она не задана, то используется `less`. doc/README-ru.md:425:Если вы желаете использовать другой пейджер, вы можете либо изменить переменную `PAGER`, либо `BAT_PAGER` чтобы перезаписать то, что указано в `PAGER`. doc/README-ru.md:430:export BAT_PAGER="less -RF" doc/README-ru.md:433:Так же вы можете использовать [файл конфигурации](https://github.com/sharkdp/bat#configuration-file) `bat` (флаг `--pager`). doc/README-ru.md:436:`bat` задаст следующие флаги для пейджера: doc/README-ru.md:449:Если вы используете темный режим в macOS, возможно вы захотите чтобы `bat` использовал другую тему, основанную на теме вашей ОС. Следующий сниппет использует тему `default`, когда у вас включен темный режим, и тему `GitHub`, когда включен светлый. doc/README-ru.md:452:alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" doc/README-ru.md:457:`bat` также может быть кастомизирован с помощью файла конфигурации. Его местоположение зависит от вашей ОС: чтобы посмотреть его путь, введите doc/README-ru.md:459:bat --config-file doc/README-ru.md:462:Также вы можете установить переменную окружения `BAT_CONFIG_PATH`, чтобы изменить путь к файлу конфигурации. doc/README-ru.md:464:export BAT_CONFIG_PATH="/path/to/bat.conf" doc/README-ru.md:469:bat --generate-config-file doc/README-ru.md:474:Файл конфигурации - это всего лишь набор аргументов. Введите `bat --help`, чтобы просмотреть список всех возможных флагов и аргументов. Также вы можете закомментировать строку с помощью `#`. doc/README-ru.md:494:## Использование `bat` в Windows doc/README-ru.md:496:`bat` полностью работоспособен "из коробки", но для некоторых возможностей могут понадобиться дополнительные настройки. doc/README-ru.md:509:или установить `BAT_PAGER` равным пустой строке. doc/README-ru.md:513:Из коробки `bat` не поддерживает пути в стиле Unix (`/cygdrive/*`). Когда указан абсолютный путь cygwin, `bat` выдаст следующую ошибку: `The system cannot find the path specified. (os error 3)` doc/README-ru.md:518:bat() { doc/README-ru.md:527: command bat "${args[@]}" doc/README-ru.md:535:`bat` поддерживает терминалы *с* и *без* поддержки truecolor. Однако подсветка синтаксиса не оптимизирована для терминалов с 8-битными цветами, и рекомендуется использовать терминалы с поддержкой 24-битных цветов (`terminator`, `konsole`, `iTerm2`, ...). doc/README-ru.md:539:`24bit`. Иначе `bat` не сможет определить поддержку 24-битных цветов (и будет использовать 8-битные). doc/README-ru.md:543:Используйте другую тему (`bat --list-themes` выведет список всех установленных тем). Темы `OneHalfDark` и doc/README-ru.md:548:`bat` поддерживает UTF-8 и UTF-16. Файлы в других кодировках, возможно, придётся перекодировать, так как кодировка может быть распознана неверно. Используйте `iconv`. doc/README-ru.md:551:iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat doc/README-ru.md:553:Внимание: вам может понадобится флаг `-l`/`--language`, если `bat` не сможет автоматически определить синтаксис. doc/README-ru.md:559:git clone --recursive https://github.com/sharkdp/bat doc/README-ru.md:562:cd bat doc/README-ru.md:571:# Компилирование исполняего файла bat с другим синтаксисом и темами doc/README-ru.md:583:Цели проекта `bat`: doc/README-ru.md:590:Есть очень много альтернатив `bat`. Смотрите [этот документ](doc/alternatives.md) для сравнения. doc/README-ru.md:593:Copyright (c) 2018-2021 [Разработчики bat](https://github.com/sharkdp/bat). doc/README-ru.md:595:`bat` распостраняется под лицензями MIT License и Apache License 2.0 (на выбор пользователя). doc/release-checklist.md:5:See this page for a good overview: https://deps.rs/repo/github/sharkdp/bat doc/release-checklist.md:27: sure that it is available on the `PATH` (`bat --version` should show the doc/release-checklist.md:41: this, install the latest `bat` version again (to include the new synaxes doc/release-checklist.md:50:- [ ] Go to https://github.com/sharkdp/bat/releases/new to create the new Cargo.lock:85:name = "bat" LICENSE-MIT:1:Copyright (c) 2018-2021 bat-developers (https://github.com/sharkdp/bat). assets/themes/Coldark/README.md:5:# Coldark - Bat assets/themes/Coldark/README.md:7:![GitHub License](https://img.shields.io/github/license/ArmandPhilippot/coldark-bat?colorA=111b27&color=d0dae7&logo=Github&logoColor=e3eaf2&style=for-the-badge) ![GitHub package.json version](https://img.shields.io/github/package-json/v/ArmandPhilippot/coldark-bat?colorA=111b27&color=d0dae7&logo=Github&logoColor=e3eaf2&style=for-the-badge) assets/themes/Coldark/README.md:15:This Coldark version is designed for [bat](https://github.com/sharkdp/bat) command. assets/themes/Coldark/README.md:21:The `bat` version uses almost the same colors as [VS code version](https://github.com/ArmandPhilippot/coldark-vscode). The scopes seems a little different and a little less complete, hence the difference. assets/themes/Coldark/README.md:69:1. Install `bat` (on Manjaro: `pacman -S bat`) assets/themes/Coldark/README.md:70:2. Create themes folder: `mkdir -p "$(bat --config-dir)/themes"` assets/themes/Coldark/README.md:71:3. Go inside this new folder: `cd "$(bat --config-dir)/themes"` assets/themes/Coldark/README.md:72:4. Clone this repo: `git clone https://github.com/ArmandPhilippot/coldark-bat` assets/themes/Coldark/README.md:73:5. Update the binary cache: `bat cache --build` assets/themes/Coldark/README.md:75:Then, if you use `bat --list-themes`, you should see the themes. assets/themes/Coldark/README.md:77:Coldark Bat is now present in [bat repo](https://github.com/sharkdp/bat). It may be present in the list of themes in a future version without having to install it manually. assets/themes/Coldark/README.md:81:To select one of the Coldark themes, call `bat` with the `--theme=Coldark-Cold` (or `--theme=Coldark-Dark`) option or set the `BAT_THEME` environment variable to `Coldark-Cold` (or `Coldark-Dark`). Use `export BAT_THEME="Coldark-Cold"` (or `export BAT_THEME="Coldark-Dark"`) in your shell's startup file to make the change permanent. assets/themes/Coldark/README.md:91:| [![Coldark Cold PHP](./assets/coldark-cold-bat-php.jpg)](./assets/coldark-cold-bat-php.jpg) | [![Coldark Cold Markdown](./assets/coldark-cold-bat-markdown.jpg)](./assets/coldark-cold-bat-markdown.jpg) | assets/themes/Coldark/README.md:97:| [![Coldark Dark PHP](./assets/coldark-dark-bat-php.jpg)](./assets/coldark-dark-bat-php.jpg) | [![Coldark Dark Markdown](./assets/coldark-dark-bat-markdown.jpg)](./assets/coldark-dark-bat-markdown.jpg) | assets/themes/Coldark/README.md:101:This project is open source and available under the [MIT License](https://github.com/ArmandPhilippot/coldark-bat/blob/master/LICENSE). assets/themes/Coldark/Coldark-Cold.tmTheme:6: Project: Coldark Bat assets/themes/Coldark/Coldark-Cold.tmTheme:7: Repository: https://github.com/ArmandPhilippot/coldark-bat assets/themes/Coldark/package.json:2: "name": "coldark-bat", assets/themes/Coldark/package.json:15: "homepage": "https://github.com/ArmandPhilippot/coldark-bat#readme", assets/themes/Coldark/package.json:18: "url": "https://github.com/ArmandPhilippot/coldark-bat" assets/themes/Coldark/package.json:21: "url": "https://github.com/ArmandPhilippot/coldark-bat/issues" assets/themes/Coldark/CHANGELOG.md:10:## [v1.0.5](https://github.com/ArmandPhilippot/coldark-bat/compare/v1.0.4...v1.0.5) assets/themes/Coldark/CHANGELOG.md:19:- fix: change red color for both versions [`93ee1f3`](https://github.com/ArmandPhilippot/coldark-bat/commit/93ee1f3fb5e08ecf66baee03dd3900c0abcdc1e9) assets/themes/Coldark/CHANGELOG.md:21:## [v1.0.4](https://github.com/ArmandPhilippot/coldark-bat/compare/v1.0.3...v1.0.4) - 2020-10-28 assets/themes/Coldark/CHANGELOG.md:25:- Update Coldark Colors / Complete Markdown syntax highlighting [`a355b1d`](https://github.com/ArmandPhilippot/coldark-bat/commit/a355b1d75611d12d322dd47f2ea7799b663a7738) assets/themes/Coldark/CHANGELOG.md:26:- Update colors, logo, banner & add some screenshots [`0b13521`](https://github.com/ArmandPhilippot/coldark-bat/commit/0b13521b6018c04d00304121bcf47fe04fa266ee) assets/themes/Coldark/CHANGELOG.md:27:- build: update auto-changelog command [`2cd0f6e`](https://github.com/ArmandPhilippot/coldark-bat/commit/2cd0f6ea22280c892b564348aab72a45f7b28223) assets/themes/Coldark/CHANGELOG.md:29:## [v1.0.3](https://github.com/ArmandPhilippot/coldark-bat/compare/v1.0.2...v1.0.3) - 2020-10-19 assets/themes/Coldark/CHANGELOG.md:33:- fix: color for pseudo-class/element in CSS [`1fada34`](https://github.com/ArmandPhilippot/coldark-bat/commit/1fada3494ae545fd186b1cb6c7d98c5860bcbcfe) assets/themes/Coldark/CHANGELOG.md:35:## [v1.0.2](https://github.com/ArmandPhilippot/coldark-bat/compare/v1.0.1...v1.0.2) - 2020-10-18 assets/themes/Coldark/CHANGELOG.md:39:- fix: update scopes to be up to date with VS Code theme [`e92f6a7`](https://github.com/ArmandPhilippot/coldark-bat/commit/e92f6a7d7832d269cdec0754a198a589a4567a00) assets/themes/Coldark/CHANGELOG.md:41:## [v1.0.1](https://github.com/ArmandPhilippot/coldark-bat/compare/v1.0.0...v1.0.1) - 2020-10-17 assets/themes/Coldark/CHANGELOG.md:45:- docs: fix export command [`0439c73`](https://github.com/ArmandPhilippot/coldark-bat/commit/0439c73d4af9c6a3254467dc7c6a758796f78267) assets/themes/Coldark/CHANGELOG.md:51:- feat: Coldark for bat command [`18fa11d`](https://github.com/ArmandPhilippot/coldark-bat/commit/18fa11d259bd4c1b5d3278b1ef91dbf8a13e5ee1) assets/themes/Coldark/CHANGELOG.md:52:- Initial commit [`80b7c34`](https://github.com/ArmandPhilippot/coldark-bat/commit/80b7c34079e11ae69fdd94d5839305fedd9fe847) assets/themes/Coldark/CHANGELOG.md:53:- docs: add README [`e904c4d`](https://github.com/ArmandPhilippot/coldark-bat/commit/e904c4d78e3ff7653b25a6215441ad643408aedf) assets/themes/Coldark/Coldark-Dark.tmTheme:6: Project: Coldark Bat assets/themes/Coldark/Coldark-Dark.tmTheme:7: Repository: https://github.com/ArmandPhilippot/coldark-bat assets/themes/Solarized/samples/test.md:26: a verbatim or "code" block assets/themes/onehalf/README.md:43: - [x] [bat](https://github.com/sharkdp/bat) assets/themes/base16.tmTheme:8: the bat theme base16-256 instead. assets/themes/ansi.tmTheme:26: Explicitly set the gutter color since bat falls back to a assets/themes/DarkNeon/Mou/Dark Neon Eighties.txt:77:VERBATIM assets/themes/DarkNeon/Mou/Dark Neon.txt:77:VERBATIM assets/themes/DarkNeon/Mou/Dark Neon Light.txt:77:VERBATIM assets/themes/TwoDark/icons/Prefs/icon_script.tmPreferences:6: source.dosbatch, source.shell assets/themes/TwoDark/src/svg/gfx_quick-panel-row-selected.svg:60:pQxTwpjGFbAti4KEppoxavUgB0Kt5geqNtU3yigwdL9zPN5DHw0QItval6DB1kZEzQTiJdJEmU3x assets/themes/gruvbox/README.md:4:This branch is being used as a submodule in [bat](https://github.com/sharkdp/bat) for the _gruvbox_ family of themes assets/themes/gruvbox/gruvbox-dark.tmTheme:259: entity.name.val.declaration, entity.name.variable, meta.definition.variable, storage.type.variable, support.type.custom-property, support.type.variable-name, variable, variable.interpolation variable, variable.other.interpolation variable, variable.parameter.dosbatch, variable.parameter.output.function.matlab, variable.parameter.sass assets/themes/gruvbox/gruvbox-light.tmTheme:259: entity.name.val.declaration, entity.name.variable, meta.definition.variable, storage.type.variable, support.type.custom-property, support.type.variable-name, variable, variable.interpolation variable, variable.other.interpolation variable, variable.parameter.dosbatch, variable.parameter.output.function.matlab, variable.parameter.sass assets/syntaxes/02_Extra/Slim/Demo/demo.slim:152:/ Verbatim assets/syntaxes/02_Extra/Slim/Demo/demo.slim:163: 'Verbatim text with space after assets/syntaxes/02_Extra/Slim/Syntaxes/Ruby Slim.YAML-tmLanguage:130: comment: Verbatim text (can include HTML tags and copied lines) assets/syntaxes/02_Extra/Slim/Syntaxes/Ruby Slim.tmLanguage:326: Verbatim text (can include HTML tags and copied lines) assets/syntaxes/02_Extra/LLVM/README.md:2:LLVM syntax highlighting definitions based on [LLVM.tmBundle](https://github.com/whitequark/LLVM.tmBundle) created by [whitequark](https://github.com/whitequark) for [bat](https://github.com/sharkdp/bat). assets/syntaxes/02_Extra/Puppet/Puppet.sublime-build:8: "cmd": ["puppet.bat", "parser", "validate", "--color=false", "$file" ] assets/syntaxes/02_Extra/Slim.sublime-syntax:117: comment: Verbatim text (can include HTML tags and copied lines) assets/syntaxes/02_Extra/Assembly (x86_64).sublime-syntax:463: - match: '(?i)\bat\b' assets/syntaxes/02_Extra/HTML (Twig).sublime-syntax:377: - match: '(?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\''\"]\|)|\{%\sfilter\s)(batch|convert_encoding|date|date_modify|default|e(?:scape)?|format|join|merge|number_format|replace|round|slice|split|trim)(\()' assets/syntaxes/02_Extra/HTML (Twig).sublime-syntax:479: - match: (?<=\s)((?:end)?(?:autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)|as|do|else|elseif|extends|flush|from|ignore missing|import|include|only|use|with)(?=\s) assets/syntaxes/02_Extra/TypsecriptReact.sublime-syntax:2325: |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:3584: // The advantage of this approach is its simplicity. For the case of batch compilation, assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:37221: // Literal files are always included verbatim. An "include" or "exclude" specification cannot assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48035: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48036: if (verbatimTargetName === "export=" /* ExportEquals */ && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48038: verbatimTargetName = "default" /* Default */; assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48040: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48085: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:48094: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:98916: // If he number will be printed verbatim and it doesn't already contain a dot, add one assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:101096: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:105964: // Get next batch of affected files assets/syntaxes/02_Extra/TypeScript/tsserver/typingsInstaller.js:108618: // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39425: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39426: if (verbatimTargetName === "export=" && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39427: verbatimTargetName = "default"; assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39429: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39452: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/tsc.js:39457: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:3595: // The advantage of this approach is its simplicity. For the case of batch compilation, assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:37232: // Literal files are always included verbatim. An "include" or "exclude" specification cannot assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48046: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48047: if (verbatimTargetName === "export=" /* ExportEquals */ && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48049: verbatimTargetName = "default" /* Default */; assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48051: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48096: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:48105: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:98927: // If he number will be printed verbatim and it doesn't already contain a dot, add one assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:101107: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:105975: // Get next batch of affected files assets/syntaxes/02_Extra/TypeScript/tsserver/tsserver.js:108629: // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:3789: // The advantage of this approach is its simplicity. For the case of batch compilation, assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:37426: // Literal files are always included verbatim. An "include" or "exclude" specification cannot assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48240: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48241: if (verbatimTargetName === "export=" /* ExportEquals */ && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48243: verbatimTargetName = "default" /* Default */; assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48245: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48290: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:48299: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:99121: // If he number will be printed verbatim and it doesn't already contain a dot, add one assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:101301: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:106169: // Get next batch of affected files assets/syntaxes/02_Extra/TypeScript/tsserver/typescriptServices.js:108823: // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:3789: // The advantage of this approach is its simplicity. For the case of batch compilation, assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:37426: // Literal files are always included verbatim. An "include" or "exclude" specification cannot assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48240: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48241: if (verbatimTargetName === "export=" /* ExportEquals */ && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48243: verbatimTargetName = "default" /* Default */; assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48245: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48290: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:48299: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:99121: // If he number will be printed verbatim and it doesn't already contain a dot, add one assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:101301: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:106169: // Get next batch of affected files assets/syntaxes/02_Extra/TypeScript/tsserver/tsserverlibrary.js:108823: // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:3789: // The advantage of this approach is its simplicity. For the case of batch compilation, assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:37426: // Literal files are always included verbatim. An "include" or "exclude" specification cannot assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48240: var verbatimTargetName = ts.unescapeLeadingUnderscores(target.escapedName); assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48241: if (verbatimTargetName === "export=" /* ExportEquals */ && (compilerOptions.esModuleInterop || compilerOptions.allowSyntheticDefaultImports)) { assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48243: verbatimTargetName = "default" /* Default */; assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48245: var targetName = getInternalSymbolName(target, verbatimTargetName); assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48290: ts.factory.createImportSpecifier(localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, ts.factory.createIdentifier(localName)) assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:48299: serializeExportSpecifier(ts.unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined); assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:99121: // If he number will be printed verbatim and it doesn't already contain a dot, add one assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:101301: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:106169: // Get next batch of affected files assets/syntaxes/02_Extra/TypeScript/tsserver/typescript.js:108823: // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch assets/syntaxes/02_Extra/TypeScript/tsserver/lib.scripthost.d.ts:161: * Gets/sets the script mode - interactive(true) or batch(false). assets/syntaxes/02_Extra/TypeScript/TypeScript.tmLanguage:6080: |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule assets/syntaxes/02_Extra/TypeScript/TypeScriptReact.tmLanguage:6026: |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule assets/syntaxes/02_Extra/Org mode/README.org:25:- [X] =Verbatim= assets/syntaxes/02_Extra/PowerShell/examples/test.ps1:281:a.bat assets/syntaxes/02_Extra/PowerShell/examples/test.ps1:282:aa.bat assets/syntaxes/02_Extra/PowerShell/examples/test.ps1:283:aaa.bat assets/syntaxes/02_Extra/PowerShell/examples/test.ps1:284:aaaa.bat assets/syntaxes/02_Extra/PowerShell/PowerShellSyntax.tmLanguage:255: (\b(([A-Za-z0-9\-_\.]+)\.(?i:exe|com|cmd|bat))\b) assets/syntaxes/02_Extra/PowerShell/PowerShellSyntax.tmLanguage:503: (?:(\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 assets/syntaxes/02_Extra/ssh-config/src/options.yaml:54: BatchMode: assets/syntaxes/02_Extra/ssh-config/SSH Config.sublime-syntax:215: BatchMode|CanonicalizeFallbackLocal|CheckHostIP|Compression| assets/syntaxes/02_Extra/ssh-config/Support/SSH Config.sublime-completions:41: "trigger": "BatchMode", assets/syntaxes/02_Extra/ssh-config/Support/SSH Config.sublime-completions:42: "contents": "BatchMode", assets/syntaxes/02_Extra/ssh-config/Support/SSH Config.sublime-completions:47: "trigger": "batchmode", assets/syntaxes/02_Extra/ssh-config/Support/SSH Config.sublime-completions:48: "contents": "BatchMode ${0:{ yes | no \\}}", assets/syntaxes/02_Extra/http-request-response/README.md:3:It was originally designed for use in https://github.com/sharkdp/bat, so it is not using any Sublime Text 4 features, as https://github.com/trishume/syntect does not support them yet. So this package should work in Sublime Text 3 also. assets/syntaxes/02_Extra/http-request-response/docs/CONTRIBUTING.md:9:If you are not a Sublime Text user, and are contributing to improve a tool that uses the `syntect` Rust library, such as `bat`, assets/syntaxes/02_Extra/Crystal/Crystal.tmLanguage:353: \b(initialize|new|loop|include|extend|raise|getter|setter|property|class_getter|class_setter|class_property|describe|context|it|with|delegate|def_hash|def_equals|def_equals_and_hash|forward_missing_to|record|assert_responds_to|spawn|annotation|verbatim)\b[!?]? assets/syntaxes/02_Extra/Lean/README.md:22:* Batch file execution assets/syntaxes/02_Extra/Lean/README.md:178:* `lean.batchExecute` (Lean: Batch Execute File): execute the current file using Lean (bound to ctrl+shift+r by default) assets/syntaxes/02_Extra/Lean/README.md:287:* Properly set working directory when executing in batch mode. assets/syntaxes/02_Extra/Lean/src/batch.ts:6:let batchOutputChannel: OutputChannel; assets/syntaxes/02_Extra/Lean/src/batch.ts:8:export function batchExecuteFile( assets/syntaxes/02_Extra/Lean/src/batch.ts:13: batchOutputChannel = batchOutputChannel || assets/syntaxes/02_Extra/Lean/src/batch.ts:14: window.createOutputChannel('Lean: Batch File Output'); assets/syntaxes/02_Extra/Lean/src/batch.ts:23: batchOutputChannel.clear(); assets/syntaxes/02_Extra/Lean/src/batch.ts:26: batchOutputChannel.appendLine(line); assets/syntaxes/02_Extra/Lean/src/batch.ts:30: batchOutputChannel.appendLine(line); assets/syntaxes/02_Extra/Lean/src/batch.ts:37: batchOutputChannel.show(true); assets/syntaxes/02_Extra/Lean/src/extension.ts:3:import { batchExecuteFile } from './batch'; assets/syntaxes/02_Extra/Lean/src/extension.ts:67: commands.registerTextEditorCommand('lean.batchExecute', assets/syntaxes/02_Extra/Lean/src/extension.ts:68: (editor, edit, args) => { batchExecuteFile(server, editor, edit, args); }), assets/syntaxes/02_Extra/Lean/package.json:281: "command": "lean.batchExecute", assets/syntaxes/02_Extra/Lean/package.json:283: "title": "Batch Execute File", assets/syntaxes/02_Extra/Lean/package.json:350: "command": "lean.batchExecute", assets/syntaxes/02_Extra/Lean/package.json:373: "command": "lean.batchExecute", assets/syntaxes/02_Extra/Lean/syntaxes/lean-markdown.json:571: "fenced_code_block_dosbatch": { assets/syntaxes/02_Extra/Lean/syntaxes/lean-markdown.json:572: "begin": "(^)(\\s*)(`{3,}|~{3,})\\s*(?i:(bat|batch)((\\s+|:|\\{)[^`~]*)?$)", assets/syntaxes/02_Extra/Lean/syntaxes/lean-markdown.json:595: "contentName": "meta.embedded.block.dosbatch", assets/syntaxes/02_Extra/Lean/syntaxes/lean-markdown.json:598: "include": "source.batchfile" assets/syntaxes/02_Extra/Lean/syntaxes/lean-markdown.json:1774: "include": "#fenced_code_block_dosbatch" assets/syntaxes/02_Extra/Lean/syntaxes/lean.json:21: { "match": "\\battribute\\b\\s*\\[[^\\]]*\\]", "name": "storage.modifier.lean" }, assets/syntaxes/02_Extra/Lean/package-lock.json:1946: "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", assets/syntaxes/02_Extra/Lean/package-lock.json:4288: "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", assets/syntaxes/02_Extra/Lean/package-lock.json:7099: "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", assets/syntaxes/02_Extra/Lean/package-lock.json:9705: "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", assets/syntaxes/02_Extra/Lean/package-lock.json:11662: "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", assets/syntaxes/02_Extra/Lean/package-lock.json:14054: "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", assets/syntaxes/02_Extra/CMake/CMakeCommands.yml:4:add_custom_command: [OUTPUT, COMMAND, ARGS, MAIN_DEPENDENCY, DEPENDS, BYPRODUCTS, IMPLICIT_DEPENDS, WORKING_DIRECTORY, COMMENT, DEPFILE, VERBATIM, APPEND, USES_TERMINAL COMMAND_EXPAND_LISTS, TARGET, PRE_BUILD, PRE_LINK, POST_BUILD] assets/syntaxes/02_Extra/CMake/CMakeCommands.yml:5:add_custom_target: [ALL, COMMAND, DEPENDS, BYPRODUCTS, WORKING_DIRECTORY, COMMENT, VERBATIM, USES_TERMINAL, COMMAND_EXPAND_LISTS, SOURCES] assets/syntaxes/02_Extra/CMake/CMakeVariables.sublime-completions:1:{"completions":[{"contents":"ANDROID","trigger":"ANDROID\tbuiltin variable"},{"contents":"APPLE","trigger":"APPLE\tbuiltin variable"},{"contents":"BORLAND","trigger":"BORLAND\tbuiltin variable"},{"contents":"BUILD_SHARED_LIBS","trigger":"BUILD_SHARED_LIBS\tbuiltin variable"},{"contents":"CACHE","trigger":"CACHE\tbuiltin variable"},{"contents":"CMAKE_ABSOLUTE_DESTINATION_FILES","trigger":"CMAKE_ABSOLUTE_DESTINATION_FILES\tbuiltin variable"},{"contents":"CMAKE_AIX_EXPORT_ALL_SYMBOLS","trigger":"CMAKE_AIX_EXPORT_ALL_SYMBOLS\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS","trigger":"CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS\tbuiltin variable"},{"contents":"CMAKE_ANDROID_API","trigger":"CMAKE_ANDROID_API\tbuiltin variable"},{"contents":"CMAKE_ANDROID_API_MIN","trigger":"CMAKE_ANDROID_API_MIN\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ARCH","trigger":"CMAKE_ANDROID_ARCH\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ARCH_ABI","trigger":"CMAKE_ANDROID_ARCH_ABI\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ARM_MODE","trigger":"CMAKE_ANDROID_ARM_MODE\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ARM_NEON","trigger":"CMAKE_ANDROID_ARM_NEON\tbuiltin variable"},{"contents":"CMAKE_ANDROID_ASSETS_DIRECTORIES","trigger":"CMAKE_ANDROID_ASSETS_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_ANDROID_GUI","trigger":"CMAKE_ANDROID_GUI\tbuiltin variable"},{"contents":"CMAKE_ANDROID_JAR_DEPENDENCIES","trigger":"CMAKE_ANDROID_JAR_DEPENDENCIES\tbuiltin variable"},{"contents":"CMAKE_ANDROID_JAR_DIRECTORIES","trigger":"CMAKE_ANDROID_JAR_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_ANDROID_JAVA_SOURCE_DIR","trigger":"CMAKE_ANDROID_JAVA_SOURCE_DIR\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES","trigger":"CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES","trigger":"CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NDK","trigger":"CMAKE_ANDROID_NDK\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NDK_DEPRECATED_HEADERS","trigger":"CMAKE_ANDROID_NDK_DEPRECATED_HEADERS\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG","trigger":"CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG\tbuiltin variable"},{"contents":"CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION","trigger":"CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION\tbuiltin variable"},{"contents":"CMAKE_ANDROID_PROCESS_MAX","trigger":"CMAKE_ANDROID_PROCESS_MAX\tbuiltin variable"},{"contents":"CMAKE_ANDROID_PROGUARD","trigger":"CMAKE_ANDROID_PROGUARD\tbuiltin variable"},{"contents":"CMAKE_ANDROID_PROGUARD_CONFIG_PATH","trigger":"CMAKE_ANDROID_PROGUARD_CONFIG_PATH\tbuiltin variable"},{"contents":"CMAKE_ANDROID_SECURE_PROPS_PATH","trigger":"CMAKE_ANDROID_SECURE_PROPS_PATH\tbuiltin variable"},{"contents":"CMAKE_ANDROID_SKIP_ANT_STEP","trigger":"CMAKE_ANDROID_SKIP_ANT_STEP\tbuiltin variable"},{"contents":"CMAKE_ANDROID_STANDALONE_TOOLCHAIN","trigger":"CMAKE_ANDROID_STANDALONE_TOOLCHAIN\tbuiltin variable"},{"contents":"CMAKE_ANDROID_STL_TYPE","trigger":"CMAKE_ANDROID_STL_TYPE\tbuiltin variable"},{"contents":"CMAKE_APPBUNDLE_PATH","trigger":"CMAKE_APPBUNDLE_PATH\tbuiltin variable"},{"contents":"CMAKE_APPLE_SILICON_PROCESSOR","trigger":"CMAKE_APPLE_SILICON_PROCESSOR\tbuiltin variable"},{"contents":"CMAKE_AR","trigger":"CMAKE_AR\tbuiltin variable"},{"contents":"CMAKE_ARCHIVE_OUTPUT_DIRECTORY","trigger":"CMAKE_ARCHIVE_OUTPUT_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_ARGC","trigger":"CMAKE_ARGC\tbuiltin variable"},{"contents":"CMAKE_ARGV0","trigger":"CMAKE_ARGV0\tbuiltin variable"},{"contents":"CMAKE_AUTOGEN_ORIGIN_DEPENDS","trigger":"CMAKE_AUTOGEN_ORIGIN_DEPENDS\tbuiltin variable"},{"contents":"CMAKE_AUTOGEN_PARALLEL","trigger":"CMAKE_AUTOGEN_PARALLEL\tbuiltin variable"},{"contents":"CMAKE_AUTOGEN_VERBOSE","trigger":"CMAKE_AUTOGEN_VERBOSE\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC","trigger":"CMAKE_AUTOMOC\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_COMPILER_PREDEFINES","trigger":"CMAKE_AUTOMOC_COMPILER_PREDEFINES\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_DEPEND_FILTERS","trigger":"CMAKE_AUTOMOC_DEPEND_FILTERS\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_MACRO_NAMES","trigger":"CMAKE_AUTOMOC_MACRO_NAMES\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_MOC_OPTIONS","trigger":"CMAKE_AUTOMOC_MOC_OPTIONS\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_PATH_PREFIX","trigger":"CMAKE_AUTOMOC_PATH_PREFIX\tbuiltin variable"},{"contents":"CMAKE_AUTOMOC_RELAXED_MODE","trigger":"CMAKE_AUTOMOC_RELAXED_MODE\tbuiltin variable"},{"contents":"CMAKE_AUTORCC","trigger":"CMAKE_AUTORCC\tbuiltin variable"},{"contents":"CMAKE_AUTORCC_OPTIONS","trigger":"CMAKE_AUTORCC_OPTIONS\tbuiltin variable"},{"contents":"CMAKE_AUTOUIC","trigger":"CMAKE_AUTOUIC\tbuiltin variable"},{"contents":"CMAKE_AUTOUIC_OPTIONS","trigger":"CMAKE_AUTOUIC_OPTIONS\tbuiltin variable"},{"contents":"CMAKE_AUTOUIC_SEARCH_PATHS","trigger":"CMAKE_AUTOUIC_SEARCH_PATHS\tbuiltin variable"},{"contents":"CMAKE_BACKWARDS_COMPATIBILITY","trigger":"CMAKE_BACKWARDS_COMPATIBILITY\tbuiltin variable"},{"contents":"CMAKE_BINARY_DIR","trigger":"CMAKE_BINARY_DIR\tbuiltin variable"},{"contents":"CMAKE_BUILD_RPATH","trigger":"CMAKE_BUILD_RPATH\tbuiltin variable"},{"contents":"CMAKE_BUILD_RPATH_USE_ORIGIN","trigger":"CMAKE_BUILD_RPATH_USE_ORIGIN\tbuiltin variable"},{"contents":"CMAKE_BUILD_TOOL","trigger":"CMAKE_BUILD_TOOL\tbuiltin variable"},{"contents":"CMAKE_BUILD_TYPE","trigger":"CMAKE_BUILD_TYPE\tbuiltin variable"},{"contents":"CMAKE_BUILD_WITH_INSTALL_NAME_DIR","trigger":"CMAKE_BUILD_WITH_INSTALL_NAME_DIR\tbuiltin variable"},{"contents":"CMAKE_BUILD_WITH_INSTALL_RPATH","trigger":"CMAKE_BUILD_WITH_INSTALL_RPATH\tbuiltin variable"},{"contents":"CMAKE_CACHEFILE_DIR","trigger":"CMAKE_CACHEFILE_DIR\tbuiltin variable"},{"contents":"CMAKE_CACHE_MAJOR_VERSION","trigger":"CMAKE_CACHE_MAJOR_VERSION\tbuiltin variable"},{"contents":"CMAKE_CACHE_MINOR_VERSION","trigger":"CMAKE_CACHE_MINOR_VERSION\tbuiltin variable"},{"contents":"CMAKE_CACHE_PATCH_VERSION","trigger":"CMAKE_CACHE_PATCH_VERSION\tbuiltin variable"},{"contents":"CMAKE_CFG_INTDIR","trigger":"CMAKE_CFG_INTDIR\tbuiltin variable"},{"contents":"CMAKE_CLANG_VFS_OVERLAY","trigger":"CMAKE_CLANG_VFS_OVERLAY\tbuiltin variable"},{"contents":"CMAKE_CL_64","trigger":"CMAKE_CL_64\tbuiltin variable"},{"contents":"CMAKE_CODEBLOCKS_COMPILER_ID","trigger":"CMAKE_CODEBLOCKS_COMPILER_ID\tbuiltin variable"},{"contents":"CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES","trigger":"CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES\tbuiltin variable"},{"contents":"CMAKE_CODELITE_USE_TARGETS","trigger":"CMAKE_CODELITE_USE_TARGETS\tbuiltin variable"},{"contents":"CMAKE_COLOR_MAKEFILE","trigger":"CMAKE_COLOR_MAKEFILE\tbuiltin variable"},{"contents":"CMAKE_COMMAND","trigger":"CMAKE_COMMAND\tbuiltin variable"},{"contents":"CMAKE_COMPILER_2005","trigger":"CMAKE_COMPILER_2005\tbuiltin variable"},{"contents":"CMAKE_COMPILER_IS_GNUCC","trigger":"CMAKE_COMPILER_IS_GNUCC\tbuiltin variable"},{"contents":"CMAKE_COMPILER_IS_GNUCXX","trigger":"CMAKE_COMPILER_IS_GNUCXX\tbuiltin variable"},{"contents":"CMAKE_COMPILER_IS_GNUG77","trigger":"CMAKE_COMPILER_IS_GNUG77\tbuiltin variable"},{"contents":"CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY","trigger":"CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_CONFIGURATION_TYPES","trigger":"CMAKE_CONFIGURATION_TYPES\tbuiltin variable"},{"contents":"CMAKE_CPACK_COMMAND","trigger":"CMAKE_CPACK_COMMAND\tbuiltin variable"},{"contents":"CMAKE_CROSSCOMPILING","trigger":"CMAKE_CROSSCOMPILING\tbuiltin variable"},{"contents":"CMAKE_CROSSCOMPILING_EMULATOR","trigger":"CMAKE_CROSSCOMPILING_EMULATOR\tbuiltin variable"},{"contents":"CMAKE_CROSS_CONFIGS","trigger":"CMAKE_CROSS_CONFIGS\tbuiltin variable"},{"contents":"CMAKE_CTEST_ARGUMENTS","trigger":"CMAKE_CTEST_ARGUMENTS\tbuiltin variable"},{"contents":"CMAKE_CTEST_COMMAND","trigger":"CMAKE_CTEST_COMMAND\tbuiltin variable"},{"contents":"CMAKE_CUDA_ARCHITECTURES","trigger":"CMAKE_CUDA_ARCHITECTURES\tbuiltin variable"},{"contents":"CMAKE_CUDA_COMPILE_FEATURES","trigger":"CMAKE_CUDA_COMPILE_FEATURES\tbuiltin variable"},{"contents":"CMAKE_CUDA_EXTENSIONS","trigger":"CMAKE_CUDA_EXTENSIONS\tbuiltin variable"},{"contents":"CMAKE_CUDA_HOST_COMPILER","trigger":"CMAKE_CUDA_HOST_COMPILER\tbuiltin variable"},{"contents":"CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS","trigger":"CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS\tbuiltin variable"},{"contents":"CMAKE_CUDA_RUNTIME_LIBRARY","trigger":"CMAKE_CUDA_RUNTIME_LIBRARY\tbuiltin variable"},{"contents":"CMAKE_CUDA_SEPARABLE_COMPILATION","trigger":"CMAKE_CUDA_SEPARABLE_COMPILATION\tbuiltin variable"},{"contents":"CMAKE_CUDA_STANDARD","trigger":"CMAKE_CUDA_STANDARD\tbuiltin variable"},{"contents":"CMAKE_CUDA_STANDARD_REQUIRED","trigger":"CMAKE_CUDA_STANDARD_REQUIRED\tbuiltin variable"},{"contents":"CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES","trigger":"CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_CURRENT_BINARY_DIR","trigger":"CMAKE_CURRENT_BINARY_DIR\tbuiltin variable"},{"contents":"CMAKE_CURRENT_FUNCTION","trigger":"CMAKE_CURRENT_FUNCTION\tbuiltin variable"},{"contents":"CMAKE_CURRENT_FUNCTION_LIST_DIR","trigger":"CMAKE_CURRENT_FUNCTION_LIST_DIR\tbuiltin variable"},{"contents":"CMAKE_CURRENT_FUNCTION_LIST_FILE","trigger":"CMAKE_CURRENT_FUNCTION_LIST_FILE\tbuiltin variable"},{"contents":"CMAKE_CURRENT_FUNCTION_LIST_LINE","trigger":"CMAKE_CURRENT_FUNCTION_LIST_LINE\tbuiltin variable"},{"contents":"CMAKE_CURRENT_LIST_DIR","trigger":"CMAKE_CURRENT_LIST_DIR\tbuiltin variable"},{"contents":"CMAKE_CURRENT_LIST_FILE","trigger":"CMAKE_CURRENT_LIST_FILE\tbuiltin variable"},{"contents":"CMAKE_CURRENT_LIST_LINE","trigger":"CMAKE_CURRENT_LIST_LINE\tbuiltin variable"},{"contents":"CMAKE_CURRENT_SOURCE_DIR","trigger":"CMAKE_CURRENT_SOURCE_DIR\tbuiltin variable"},{"contents":"CMAKE_CXX_COMPILE_FEATURES","trigger":"CMAKE_CXX_COMPILE_FEATURES\tbuiltin variable"},{"contents":"CMAKE_CXX_EXTENSIONS","trigger":"CMAKE_CXX_EXTENSIONS\tbuiltin variable"},{"contents":"CMAKE_CXX_STANDARD","trigger":"CMAKE_CXX_STANDARD\tbuiltin variable"},{"contents":"CMAKE_CXX_STANDARD_REQUIRED","trigger":"CMAKE_CXX_STANDARD_REQUIRED\tbuiltin variable"},{"contents":"CMAKE_C_COMPILE_FEATURES","trigger":"CMAKE_C_COMPILE_FEATURES\tbuiltin variable"},{"contents":"CMAKE_C_EXTENSIONS","trigger":"CMAKE_C_EXTENSIONS\tbuiltin variable"},{"contents":"CMAKE_C_STANDARD","trigger":"CMAKE_C_STANDARD\tbuiltin variable"},{"contents":"CMAKE_C_STANDARD_REQUIRED","trigger":"CMAKE_C_STANDARD_REQUIRED\tbuiltin variable"},{"contents":"CMAKE_DEBUG_POSTFIX","trigger":"CMAKE_DEBUG_POSTFIX\tbuiltin variable"},{"contents":"CMAKE_DEBUG_TARGET_PROPERTIES","trigger":"CMAKE_DEBUG_TARGET_PROPERTIES\tbuiltin variable"},{"contents":"CMAKE_DEFAULT_BUILD_TYPE","trigger":"CMAKE_DEFAULT_BUILD_TYPE\tbuiltin variable"},{"contents":"CMAKE_DEFAULT_CONFIGS","trigger":"CMAKE_DEFAULT_CONFIGS\tbuiltin variable"},{"contents":"CMAKE_DEPENDS_IN_PROJECT_ONLY","trigger":"CMAKE_DEPENDS_IN_PROJECT_ONLY\tbuiltin variable"},{"contents":"CMAKE_DIRECTORY_LABELS","trigger":"CMAKE_DIRECTORY_LABELS\tbuiltin variable"},{"contents":"CMAKE_DISABLE_PRECOMPILE_HEADERS","trigger":"CMAKE_DISABLE_PRECOMPILE_HEADERS\tbuiltin variable"},{"contents":"CMAKE_DL_LIBS","trigger":"CMAKE_DL_LIBS\tbuiltin variable"},{"contents":"CMAKE_DOTNET_TARGET_FRAMEWORK","trigger":"CMAKE_DOTNET_TARGET_FRAMEWORK\tbuiltin variable"},{"contents":"CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION","trigger":"CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION\tbuiltin variable"},{"contents":"CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES","trigger":"CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES\tbuiltin variable"},{"contents":"CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT","trigger":"CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT\tbuiltin variable"},{"contents":"CMAKE_ECLIPSE_MAKE_ARGUMENTS","trigger":"CMAKE_ECLIPSE_MAKE_ARGUMENTS\tbuiltin variable"},{"contents":"CMAKE_ECLIPSE_RESOURCE_ENCODING","trigger":"CMAKE_ECLIPSE_RESOURCE_ENCODING\tbuiltin variable"},{"contents":"CMAKE_ECLIPSE_VERSION","trigger":"CMAKE_ECLIPSE_VERSION\tbuiltin variable"},{"contents":"CMAKE_EDIT_COMMAND","trigger":"CMAKE_EDIT_COMMAND\tbuiltin variable"},{"contents":"CMAKE_ENABLE_EXPORTS","trigger":"CMAKE_ENABLE_EXPORTS\tbuiltin variable"},{"contents":"CMAKE_ERROR_DEPRECATED","trigger":"CMAKE_ERROR_DEPRECATED\tbuiltin variable"},{"contents":"CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION","trigger":"CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION\tbuiltin variable"},{"contents":"CMAKE_EXECUTABLE_SUFFIX","trigger":"CMAKE_EXECUTABLE_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_EXECUTE_PROCESS_COMMAND_ECHO","trigger":"CMAKE_EXECUTE_PROCESS_COMMAND_ECHO\tbuiltin variable"},{"contents":"CMAKE_EXE_LINKER_FLAGS","trigger":"CMAKE_EXE_LINKER_FLAGS\tbuiltin variable"},{"contents":"CMAKE_EXE_LINKER_FLAGS_INIT","trigger":"CMAKE_EXE_LINKER_FLAGS_INIT\tbuiltin variable"},{"contents":"CMAKE_EXPORT_COMPILE_COMMANDS","trigger":"CMAKE_EXPORT_COMPILE_COMMANDS\tbuiltin variable"},{"contents":"CMAKE_EXPORT_NO_PACKAGE_REGISTRY","trigger":"CMAKE_EXPORT_NO_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_EXPORT_PACKAGE_REGISTRY","trigger":"CMAKE_EXPORT_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_EXTRA_GENERATOR","trigger":"CMAKE_EXTRA_GENERATOR\tbuiltin variable"},{"contents":"CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES","trigger":"CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES\tbuiltin variable"},{"contents":"CMAKE_FIND_APPBUNDLE","trigger":"CMAKE_FIND_APPBUNDLE\tbuiltin variable"},{"contents":"CMAKE_FIND_DEBUG_MODE","trigger":"CMAKE_FIND_DEBUG_MODE\tbuiltin variable"},{"contents":"CMAKE_FIND_FRAMEWORK","trigger":"CMAKE_FIND_FRAMEWORK\tbuiltin variable"},{"contents":"CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX","trigger":"CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_FIND_LIBRARY_PREFIXES","trigger":"CMAKE_FIND_LIBRARY_PREFIXES\tbuiltin variable"},{"contents":"CMAKE_FIND_LIBRARY_SUFFIXES","trigger":"CMAKE_FIND_LIBRARY_SUFFIXES\tbuiltin variable"},{"contents":"CMAKE_FIND_NO_INSTALL_PREFIX","trigger":"CMAKE_FIND_NO_INSTALL_PREFIX\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_NAME","trigger":"CMAKE_FIND_PACKAGE_NAME\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY","trigger":"CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY","trigger":"CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_PREFER_CONFIG","trigger":"CMAKE_FIND_PACKAGE_PREFER_CONFIG\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS","trigger":"CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_SORT_DIRECTION","trigger":"CMAKE_FIND_PACKAGE_SORT_DIRECTION\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_SORT_ORDER","trigger":"CMAKE_FIND_PACKAGE_SORT_ORDER\tbuiltin variable"},{"contents":"CMAKE_FIND_PACKAGE_WARN_NO_MODULE","trigger":"CMAKE_FIND_PACKAGE_WARN_NO_MODULE\tbuiltin variable"},{"contents":"CMAKE_FIND_ROOT_PATH","trigger":"CMAKE_FIND_ROOT_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE","trigger":"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE\tbuiltin variable"},{"contents":"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY","trigger":"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY\tbuiltin variable"},{"contents":"CMAKE_FIND_ROOT_PATH_MODE_PACKAGE","trigger":"CMAKE_FIND_ROOT_PATH_MODE_PACKAGE\tbuiltin variable"},{"contents":"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM","trigger":"CMAKE_FIND_ROOT_PATH_MODE_PROGRAM\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH","trigger":"CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_CMAKE_PATH","trigger":"CMAKE_FIND_USE_CMAKE_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_CMAKE_SYSTEM_PATH","trigger":"CMAKE_FIND_USE_CMAKE_SYSTEM_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_PACKAGE_REGISTRY","trigger":"CMAKE_FIND_USE_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_PACKAGE_ROOT_PATH","trigger":"CMAKE_FIND_USE_PACKAGE_ROOT_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH","trigger":"CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH\tbuiltin variable"},{"contents":"CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY","trigger":"CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY\tbuiltin variable"},{"contents":"CMAKE_FOLDER","trigger":"CMAKE_FOLDER\tbuiltin variable"},{"contents":"CMAKE_FRAMEWORK","trigger":"CMAKE_FRAMEWORK\tbuiltin variable"},{"contents":"CMAKE_FRAMEWORK_PATH","trigger":"CMAKE_FRAMEWORK_PATH\tbuiltin variable"},{"contents":"CMAKE_Fortran_FORMAT","trigger":"CMAKE_Fortran_FORMAT\tbuiltin variable"},{"contents":"CMAKE_Fortran_MODDIR_DEFAULT","trigger":"CMAKE_Fortran_MODDIR_DEFAULT\tbuiltin variable"},{"contents":"CMAKE_Fortran_MODDIR_FLAG","trigger":"CMAKE_Fortran_MODDIR_FLAG\tbuiltin variable"},{"contents":"CMAKE_Fortran_MODOUT_FLAG","trigger":"CMAKE_Fortran_MODOUT_FLAG\tbuiltin variable"},{"contents":"CMAKE_Fortran_MODULE_DIRECTORY","trigger":"CMAKE_Fortran_MODULE_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_Fortran_PREPROCESS","trigger":"CMAKE_Fortran_PREPROCESS\tbuiltin variable"},{"contents":"CMAKE_GENERATOR","trigger":"CMAKE_GENERATOR\tbuiltin variable"},{"contents":"CMAKE_GENERATOR_INSTANCE","trigger":"CMAKE_GENERATOR_INSTANCE\tbuiltin variable"},{"contents":"CMAKE_GENERATOR_PLATFORM","trigger":"CMAKE_GENERATOR_PLATFORM\tbuiltin variable"},{"contents":"CMAKE_GENERATOR_TOOLSET","trigger":"CMAKE_GENERATOR_TOOLSET\tbuiltin variable"},{"contents":"CMAKE_GHS_NO_SOURCE_GROUP_FILE","trigger":"CMAKE_GHS_NO_SOURCE_GROUP_FILE\tbuiltin variable"},{"contents":"CMAKE_GLOBAL_AUTOGEN_TARGET","trigger":"CMAKE_GLOBAL_AUTOGEN_TARGET\tbuiltin variable"},{"contents":"CMAKE_GLOBAL_AUTOGEN_TARGET_NAME","trigger":"CMAKE_GLOBAL_AUTOGEN_TARGET_NAME\tbuiltin variable"},{"contents":"CMAKE_GLOBAL_AUTORCC_TARGET","trigger":"CMAKE_GLOBAL_AUTORCC_TARGET\tbuiltin variable"},{"contents":"CMAKE_GLOBAL_AUTORCC_TARGET_NAME","trigger":"CMAKE_GLOBAL_AUTORCC_TARGET_NAME\tbuiltin variable"},{"contents":"CMAKE_GNUtoMS","trigger":"CMAKE_GNUtoMS\tbuiltin variable"},{"contents":"CMAKE_HOME_DIRECTORY","trigger":"CMAKE_HOME_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_HOST_APPLE","trigger":"CMAKE_HOST_APPLE\tbuiltin variable"},{"contents":"CMAKE_HOST_SOLARIS","trigger":"CMAKE_HOST_SOLARIS\tbuiltin variable"},{"contents":"CMAKE_HOST_SYSTEM","trigger":"CMAKE_HOST_SYSTEM\tbuiltin variable"},{"contents":"CMAKE_HOST_SYSTEM_NAME","trigger":"CMAKE_HOST_SYSTEM_NAME\tbuiltin variable"},{"contents":"CMAKE_HOST_SYSTEM_PROCESSOR","trigger":"CMAKE_HOST_SYSTEM_PROCESSOR\tbuiltin variable"},{"contents":"CMAKE_HOST_SYSTEM_VERSION","trigger":"CMAKE_HOST_SYSTEM_VERSION\tbuiltin variable"},{"contents":"CMAKE_HOST_UNIX","trigger":"CMAKE_HOST_UNIX\tbuiltin variable"},{"contents":"CMAKE_HOST_WIN32","trigger":"CMAKE_HOST_WIN32\tbuiltin variable"},{"contents":"CMAKE_IGNORE_PATH","trigger":"CMAKE_IGNORE_PATH\tbuiltin variable"},{"contents":"CMAKE_IMPORT_LIBRARY_PREFIX","trigger":"CMAKE_IMPORT_LIBRARY_PREFIX\tbuiltin variable"},{"contents":"CMAKE_IMPORT_LIBRARY_SUFFIX","trigger":"CMAKE_IMPORT_LIBRARY_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_INCLUDE_CURRENT_DIR","trigger":"CMAKE_INCLUDE_CURRENT_DIR\tbuiltin variable"},{"contents":"CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE","trigger":"CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE\tbuiltin variable"},{"contents":"CMAKE_INCLUDE_DIRECTORIES_BEFORE","trigger":"CMAKE_INCLUDE_DIRECTORIES_BEFORE\tbuiltin variable"},{"contents":"CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE","trigger":"CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE\tbuiltin variable"},{"contents":"CMAKE_INCLUDE_PATH","trigger":"CMAKE_INCLUDE_PATH\tbuiltin variable"},{"contents":"CMAKE_INSTALL_DEFAULT_COMPONENT_NAME","trigger":"CMAKE_INSTALL_DEFAULT_COMPONENT_NAME\tbuiltin variable"},{"contents":"CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS","trigger":"CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS\tbuiltin variable"},{"contents":"CMAKE_INSTALL_MESSAGE","trigger":"CMAKE_INSTALL_MESSAGE\tbuiltin variable"},{"contents":"CMAKE_INSTALL_NAME_DIR","trigger":"CMAKE_INSTALL_NAME_DIR\tbuiltin variable"},{"contents":"CMAKE_INSTALL_PREFIX","trigger":"CMAKE_INSTALL_PREFIX\tbuiltin variable"},{"contents":"CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT","trigger":"CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT\tbuiltin variable"},{"contents":"CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH","trigger":"CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH\tbuiltin variable"},{"contents":"CMAKE_INSTALL_RPATH","trigger":"CMAKE_INSTALL_RPATH\tbuiltin variable"},{"contents":"CMAKE_INSTALL_RPATH_USE_LINK_PATH","trigger":"CMAKE_INSTALL_RPATH_USE_LINK_PATH\tbuiltin variable"},{"contents":"CMAKE_INTERNAL_PLATFORM_ABI","trigger":"CMAKE_INTERNAL_PLATFORM_ABI\tbuiltin variable"},{"contents":"CMAKE_INTERPROCEDURAL_OPTIMIZATION","trigger":"CMAKE_INTERPROCEDURAL_OPTIMIZATION\tbuiltin variable"},{"contents":"CMAKE_IOS_INSTALL_COMBINED","trigger":"CMAKE_IOS_INSTALL_COMBINED\tbuiltin variable"},{"contents":"CMAKE_ISPC_HEADER_DIRECTORY","trigger":"CMAKE_ISPC_HEADER_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_ISPC_HEADER_SUFFIX","trigger":"CMAKE_ISPC_HEADER_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_ISPC_INSTRUCTION_SETS","trigger":"CMAKE_ISPC_INSTRUCTION_SETS\tbuiltin variable"},{"contents":"CMAKE_JOB_POOLS","trigger":"CMAKE_JOB_POOLS\tbuiltin variable"},{"contents":"CMAKE_JOB_POOL_COMPILE","trigger":"CMAKE_JOB_POOL_COMPILE\tbuiltin variable"},{"contents":"CMAKE_JOB_POOL_LINK","trigger":"CMAKE_JOB_POOL_LINK\tbuiltin variable"},{"contents":"CMAKE_JOB_POOL_PRECOMPILE_HEADER","trigger":"CMAKE_JOB_POOL_PRECOMPILE_HEADER\tbuiltin variable"},{"contents":"CMAKE_LIBRARY_ARCHITECTURE","trigger":"CMAKE_LIBRARY_ARCHITECTURE\tbuiltin variable"},{"contents":"CMAKE_LIBRARY_ARCHITECTURE_REGEX","trigger":"CMAKE_LIBRARY_ARCHITECTURE_REGEX\tbuiltin variable"},{"contents":"CMAKE_LIBRARY_OUTPUT_DIRECTORY","trigger":"CMAKE_LIBRARY_OUTPUT_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_LIBRARY_PATH","trigger":"CMAKE_LIBRARY_PATH\tbuiltin variable"},{"contents":"CMAKE_LIBRARY_PATH_FLAG","trigger":"CMAKE_LIBRARY_PATH_FLAG\tbuiltin variable"},{"contents":"CMAKE_LINK_DEF_FILE_FLAG","trigger":"CMAKE_LINK_DEF_FILE_FLAG\tbuiltin variable"},{"contents":"CMAKE_LINK_DEPENDS_NO_SHARED","trigger":"CMAKE_LINK_DEPENDS_NO_SHARED\tbuiltin variable"},{"contents":"CMAKE_LINK_DIRECTORIES_BEFORE","trigger":"CMAKE_LINK_DIRECTORIES_BEFORE\tbuiltin variable"},{"contents":"CMAKE_LINK_INTERFACE_LIBRARIES","trigger":"CMAKE_LINK_INTERFACE_LIBRARIES\tbuiltin variable"},{"contents":"CMAKE_LINK_LIBRARY_FILE_FLAG","trigger":"CMAKE_LINK_LIBRARY_FILE_FLAG\tbuiltin variable"},{"contents":"CMAKE_LINK_LIBRARY_FLAG","trigger":"CMAKE_LINK_LIBRARY_FLAG\tbuiltin variable"},{"contents":"CMAKE_LINK_LIBRARY_SUFFIX","trigger":"CMAKE_LINK_LIBRARY_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_LINK_SEARCH_END_STATIC","trigger":"CMAKE_LINK_SEARCH_END_STATIC\tbuiltin variable"},{"contents":"CMAKE_LINK_SEARCH_START_STATIC","trigger":"CMAKE_LINK_SEARCH_START_STATIC\tbuiltin variable"},{"contents":"CMAKE_LINK_WHAT_YOU_USE","trigger":"CMAKE_LINK_WHAT_YOU_USE\tbuiltin variable"},{"contents":"CMAKE_MACOSX_BUNDLE","trigger":"CMAKE_MACOSX_BUNDLE\tbuiltin variable"},{"contents":"CMAKE_MACOSX_RPATH","trigger":"CMAKE_MACOSX_RPATH\tbuiltin variable"},{"contents":"CMAKE_MAJOR_VERSION","trigger":"CMAKE_MAJOR_VERSION\tbuiltin variable"},{"contents":"CMAKE_MAKE_PROGRAM","trigger":"CMAKE_MAKE_PROGRAM\tbuiltin variable"},{"contents":"CMAKE_MATCH_COUNT","trigger":"CMAKE_MATCH_COUNT\tbuiltin variable"},{"contents":"CMAKE_MAXIMUM_RECURSION_DEPTH","trigger":"CMAKE_MAXIMUM_RECURSION_DEPTH\tbuiltin variable"},{"contents":"CMAKE_MESSAGE_CONTEXT","trigger":"CMAKE_MESSAGE_CONTEXT\tbuiltin variable"},{"contents":"CMAKE_MESSAGE_CONTEXT_SHOW","trigger":"CMAKE_MESSAGE_CONTEXT_SHOW\tbuiltin variable"},{"contents":"CMAKE_MESSAGE_INDENT","trigger":"CMAKE_MESSAGE_INDENT\tbuiltin variable"},{"contents":"CMAKE_MESSAGE_LOG_LEVEL","trigger":"CMAKE_MESSAGE_LOG_LEVEL\tbuiltin variable"},{"contents":"CMAKE_MFC_FLAG","trigger":"CMAKE_MFC_FLAG\tbuiltin variable"},{"contents":"CMAKE_MINIMUM_REQUIRED_VERSION","trigger":"CMAKE_MINIMUM_REQUIRED_VERSION\tbuiltin variable"},{"contents":"CMAKE_MINOR_VERSION","trigger":"CMAKE_MINOR_VERSION\tbuiltin variable"},{"contents":"CMAKE_MODULE_LINKER_FLAGS","trigger":"CMAKE_MODULE_LINKER_FLAGS\tbuiltin variable"},{"contents":"CMAKE_MODULE_LINKER_FLAGS_INIT","trigger":"CMAKE_MODULE_LINKER_FLAGS_INIT\tbuiltin variable"},{"contents":"CMAKE_MODULE_PATH","trigger":"CMAKE_MODULE_PATH\tbuiltin variable"},{"contents":"CMAKE_MSVCIDE_RUN_PATH","trigger":"CMAKE_MSVCIDE_RUN_PATH\tbuiltin variable"},{"contents":"CMAKE_MSVC_RUNTIME_LIBRARY","trigger":"CMAKE_MSVC_RUNTIME_LIBRARY\tbuiltin variable"},{"contents":"CMAKE_NETRC","trigger":"CMAKE_NETRC\tbuiltin variable"},{"contents":"CMAKE_NETRC_FILE","trigger":"CMAKE_NETRC_FILE\tbuiltin variable"},{"contents":"CMAKE_NINJA_OUTPUT_PATH_PREFIX","trigger":"CMAKE_NINJA_OUTPUT_PATH_PREFIX\tbuiltin variable"},{"contents":"CMAKE_NOT_USING_CONFIG_FLAGS","trigger":"CMAKE_NOT_USING_CONFIG_FLAGS\tbuiltin variable"},{"contents":"CMAKE_NO_BUILTIN_CHRPATH","trigger":"CMAKE_NO_BUILTIN_CHRPATH\tbuiltin variable"},{"contents":"CMAKE_NO_SYSTEM_FROM_IMPORTED","trigger":"CMAKE_NO_SYSTEM_FROM_IMPORTED\tbuiltin variable"},{"contents":"CMAKE_OBJCXX_EXTENSIONS","trigger":"CMAKE_OBJCXX_EXTENSIONS\tbuiltin variable"},{"contents":"CMAKE_OBJCXX_STANDARD","trigger":"CMAKE_OBJCXX_STANDARD\tbuiltin variable"},{"contents":"CMAKE_OBJCXX_STANDARD_REQUIRED","trigger":"CMAKE_OBJCXX_STANDARD_REQUIRED\tbuiltin variable"},{"contents":"CMAKE_OBJC_EXTENSIONS","trigger":"CMAKE_OBJC_EXTENSIONS\tbuiltin variable"},{"contents":"CMAKE_OBJC_STANDARD","trigger":"CMAKE_OBJC_STANDARD\tbuiltin variable"},{"contents":"CMAKE_OBJC_STANDARD_REQUIRED","trigger":"CMAKE_OBJC_STANDARD_REQUIRED\tbuiltin variable"},{"contents":"CMAKE_OBJECT_PATH_MAX","trigger":"CMAKE_OBJECT_PATH_MAX\tbuiltin variable"},{"contents":"CMAKE_OPTIMIZE_DEPENDENCIES","trigger":"CMAKE_OPTIMIZE_DEPENDENCIES\tbuiltin variable"},{"contents":"CMAKE_OSX_ARCHITECTURES","trigger":"CMAKE_OSX_ARCHITECTURES\tbuiltin variable"},{"contents":"CMAKE_OSX_DEPLOYMENT_TARGET","trigger":"CMAKE_OSX_DEPLOYMENT_TARGET\tbuiltin variable"},{"contents":"CMAKE_OSX_SYSROOT","trigger":"CMAKE_OSX_SYSROOT\tbuiltin variable"},{"contents":"CMAKE_PARENT_LIST_FILE","trigger":"CMAKE_PARENT_LIST_FILE\tbuiltin variable"},{"contents":"CMAKE_PATCH_VERSION","trigger":"CMAKE_PATCH_VERSION\tbuiltin variable"},{"contents":"CMAKE_PCH_INSTANTIATE_TEMPLATES","trigger":"CMAKE_PCH_INSTANTIATE_TEMPLATES\tbuiltin variable"},{"contents":"CMAKE_PCH_WARN_INVALID","trigger":"CMAKE_PCH_WARN_INVALID\tbuiltin variable"},{"contents":"CMAKE_PDB_OUTPUT_DIRECTORY","trigger":"CMAKE_PDB_OUTPUT_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_POSITION_INDEPENDENT_CODE","trigger":"CMAKE_POSITION_INDEPENDENT_CODE\tbuiltin variable"},{"contents":"CMAKE_PREFIX_PATH","trigger":"CMAKE_PREFIX_PATH\tbuiltin variable"},{"contents":"CMAKE_PROGRAM_PATH","trigger":"CMAKE_PROGRAM_PATH\tbuiltin variable"},{"contents":"CMAKE_PROJECT_DESCRIPTION","trigger":"CMAKE_PROJECT_DESCRIPTION\tbuiltin variable"},{"contents":"CMAKE_PROJECT_HOMEPAGE_URL","trigger":"CMAKE_PROJECT_HOMEPAGE_URL\tbuiltin variable"},{"contents":"CMAKE_PROJECT_INCLUDE","trigger":"CMAKE_PROJECT_INCLUDE\tbuiltin variable"},{"contents":"CMAKE_PROJECT_INCLUDE_BEFORE","trigger":"CMAKE_PROJECT_INCLUDE_BEFORE\tbuiltin variable"},{"contents":"CMAKE_PROJECT_NAME","trigger":"CMAKE_PROJECT_NAME\tbuiltin variable"},{"contents":"CMAKE_PROJECT_VERSION","trigger":"CMAKE_PROJECT_VERSION\tbuiltin variable"},{"contents":"CMAKE_PROJECT_VERSION_MAJOR","trigger":"CMAKE_PROJECT_VERSION_MAJOR\tbuiltin variable"},{"contents":"CMAKE_PROJECT_VERSION_MINOR","trigger":"CMAKE_PROJECT_VERSION_MINOR\tbuiltin variable"},{"contents":"CMAKE_PROJECT_VERSION_PATCH","trigger":"CMAKE_PROJECT_VERSION_PATCH\tbuiltin variable"},{"contents":"CMAKE_PROJECT_VERSION_TWEAK","trigger":"CMAKE_PROJECT_VERSION_TWEAK\tbuiltin variable"},{"contents":"CMAKE_RANLIB","trigger":"CMAKE_RANLIB\tbuiltin variable"},{"contents":"CMAKE_ROOT","trigger":"CMAKE_ROOT\tbuiltin variable"},{"contents":"CMAKE_RULE_MESSAGES","trigger":"CMAKE_RULE_MESSAGES\tbuiltin variable"},{"contents":"CMAKE_RUNTIME_OUTPUT_DIRECTORY","trigger":"CMAKE_RUNTIME_OUTPUT_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_SCRIPT_MODE_FILE","trigger":"CMAKE_SCRIPT_MODE_FILE\tbuiltin variable"},{"contents":"CMAKE_SHARED_LIBRARY_PREFIX","trigger":"CMAKE_SHARED_LIBRARY_PREFIX\tbuiltin variable"},{"contents":"CMAKE_SHARED_LIBRARY_SUFFIX","trigger":"CMAKE_SHARED_LIBRARY_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_SHARED_LINKER_FLAGS","trigger":"CMAKE_SHARED_LINKER_FLAGS\tbuiltin variable"},{"contents":"CMAKE_SHARED_LINKER_FLAGS_INIT","trigger":"CMAKE_SHARED_LINKER_FLAGS_INIT\tbuiltin variable"},{"contents":"CMAKE_SHARED_MODULE_PREFIX","trigger":"CMAKE_SHARED_MODULE_PREFIX\tbuiltin variable"},{"contents":"CMAKE_SHARED_MODULE_SUFFIX","trigger":"CMAKE_SHARED_MODULE_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_SIZEOF_VOID_P","trigger":"CMAKE_SIZEOF_VOID_P\tbuiltin variable"},{"contents":"CMAKE_SKIP_BUILD_RPATH","trigger":"CMAKE_SKIP_BUILD_RPATH\tbuiltin variable"},{"contents":"CMAKE_SKIP_INSTALL_ALL_DEPENDENCY","trigger":"CMAKE_SKIP_INSTALL_ALL_DEPENDENCY\tbuiltin variable"},{"contents":"CMAKE_SKIP_INSTALL_RPATH","trigger":"CMAKE_SKIP_INSTALL_RPATH\tbuiltin variable"},{"contents":"CMAKE_SKIP_INSTALL_RULES","trigger":"CMAKE_SKIP_INSTALL_RULES\tbuiltin variable"},{"contents":"CMAKE_SKIP_RPATH","trigger":"CMAKE_SKIP_RPATH\tbuiltin variable"},{"contents":"CMAKE_SOURCE_DIR","trigger":"CMAKE_SOURCE_DIR\tbuiltin variable"},{"contents":"CMAKE_STAGING_PREFIX","trigger":"CMAKE_STAGING_PREFIX\tbuiltin variable"},{"contents":"CMAKE_STATIC_LIBRARY_PREFIX","trigger":"CMAKE_STATIC_LIBRARY_PREFIX\tbuiltin variable"},{"contents":"CMAKE_STATIC_LIBRARY_SUFFIX","trigger":"CMAKE_STATIC_LIBRARY_SUFFIX\tbuiltin variable"},{"contents":"CMAKE_STATIC_LINKER_FLAGS","trigger":"CMAKE_STATIC_LINKER_FLAGS\tbuiltin variable"},{"contents":"CMAKE_STATIC_LINKER_FLAGS_INIT","trigger":"CMAKE_STATIC_LINKER_FLAGS_INIT\tbuiltin variable"},{"contents":"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS","trigger":"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS\tbuiltin variable"},{"contents":"CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE","trigger":"CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE\tbuiltin variable"},{"contents":"CMAKE_SUPPRESS_REGENERATION","trigger":"CMAKE_SUPPRESS_REGENERATION\tbuiltin variable"},{"contents":"CMAKE_SYSROOT","trigger":"CMAKE_SYSROOT\tbuiltin variable"},{"contents":"CMAKE_SYSROOT_COMPILE","trigger":"CMAKE_SYSROOT_COMPILE\tbuiltin variable"},{"contents":"CMAKE_SYSROOT_LINK","trigger":"CMAKE_SYSROOT_LINK\tbuiltin variable"},{"contents":"CMAKE_SYSTEM","trigger":"CMAKE_SYSTEM\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_APPBUNDLE_PATH","trigger":"CMAKE_SYSTEM_APPBUNDLE_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_FRAMEWORK_PATH","trigger":"CMAKE_SYSTEM_FRAMEWORK_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_IGNORE_PATH","trigger":"CMAKE_SYSTEM_IGNORE_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_INCLUDE_PATH","trigger":"CMAKE_SYSTEM_INCLUDE_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_LIBRARY_PATH","trigger":"CMAKE_SYSTEM_LIBRARY_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_NAME","trigger":"CMAKE_SYSTEM_NAME\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_PREFIX_PATH","trigger":"CMAKE_SYSTEM_PREFIX_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_PROCESSOR","trigger":"CMAKE_SYSTEM_PROCESSOR\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_PROGRAM_PATH","trigger":"CMAKE_SYSTEM_PROGRAM_PATH\tbuiltin variable"},{"contents":"CMAKE_SYSTEM_VERSION","trigger":"CMAKE_SYSTEM_VERSION\tbuiltin variable"},{"contents":"CMAKE_Swift_LANGUAGE_VERSION","trigger":"CMAKE_Swift_LANGUAGE_VERSION\tbuiltin variable"},{"contents":"CMAKE_Swift_MODULE_DIRECTORY","trigger":"CMAKE_Swift_MODULE_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_Swift_NUM_THREADS","trigger":"CMAKE_Swift_NUM_THREADS\tbuiltin variable"},{"contents":"CMAKE_TOOLCHAIN_FILE","trigger":"CMAKE_TOOLCHAIN_FILE\tbuiltin variable"},{"contents":"CMAKE_TRY_COMPILE_CONFIGURATION","trigger":"CMAKE_TRY_COMPILE_CONFIGURATION\tbuiltin variable"},{"contents":"CMAKE_TRY_COMPILE_PLATFORM_VARIABLES","trigger":"CMAKE_TRY_COMPILE_PLATFORM_VARIABLES\tbuiltin variable"},{"contents":"CMAKE_TRY_COMPILE_TARGET_TYPE","trigger":"CMAKE_TRY_COMPILE_TARGET_TYPE\tbuiltin variable"},{"contents":"CMAKE_TWEAK_VERSION","trigger":"CMAKE_TWEAK_VERSION\tbuiltin variable"},{"contents":"CMAKE_UNITY_BUILD","trigger":"CMAKE_UNITY_BUILD\tbuiltin variable"},{"contents":"CMAKE_UNITY_BUILD_BATCH_SIZE","trigger":"CMAKE_UNITY_BUILD_BATCH_SIZE\tbuiltin variable"},{"contents":"CMAKE_USER_MAKE_RULES_OVERRIDE","trigger":"CMAKE_USER_MAKE_RULES_OVERRIDE\tbuiltin variable"},{"contents":"CMAKE_USE_RELATIVE_PATHS","trigger":"CMAKE_USE_RELATIVE_PATHS\tbuiltin variable"},{"contents":"CMAKE_VERBOSE_MAKEFILE","trigger":"CMAKE_VERBOSE_MAKEFILE\tbuiltin variable"},{"contents":"CMAKE_VERSION","trigger":"CMAKE_VERSION\tbuiltin variable"},{"contents":"CMAKE_VISIBILITY_INLINES_HIDDEN","trigger":"CMAKE_VISIBILITY_INLINES_HIDDEN\tbuiltin variable"},{"contents":"CMAKE_VS_DEVENV_COMMAND","trigger":"CMAKE_VS_DEVENV_COMMAND\tbuiltin variable"},{"contents":"CMAKE_VS_GLOBALS","trigger":"CMAKE_VS_GLOBALS\tbuiltin variable"},{"contents":"CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD","trigger":"CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD\tbuiltin variable"},{"contents":"CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD","trigger":"CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD\tbuiltin variable"},{"contents":"CMAKE_VS_INTEL_Fortran_PROJECT_VERSION","trigger":"CMAKE_VS_INTEL_Fortran_PROJECT_VERSION\tbuiltin variable"},{"contents":"CMAKE_VS_JUST_MY_CODE_DEBUGGING","trigger":"CMAKE_VS_JUST_MY_CODE_DEBUGGING\tbuiltin variable"},{"contents":"CMAKE_VS_MSBUILD_COMMAND","trigger":"CMAKE_VS_MSBUILD_COMMAND\tbuiltin variable"},{"contents":"CMAKE_VS_NsightTegra_VERSION","trigger":"CMAKE_VS_NsightTegra_VERSION\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_NAME","trigger":"CMAKE_VS_PLATFORM_NAME\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_NAME_DEFAULT","trigger":"CMAKE_VS_PLATFORM_NAME_DEFAULT\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_TOOLSET","trigger":"CMAKE_VS_PLATFORM_TOOLSET\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_TOOLSET_CUDA","trigger":"CMAKE_VS_PLATFORM_TOOLSET_CUDA\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR","trigger":"CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE","trigger":"CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE\tbuiltin variable"},{"contents":"CMAKE_VS_PLATFORM_TOOLSET_VERSION","trigger":"CMAKE_VS_PLATFORM_TOOLSET_VERSION\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_EXCLUDE_DIRECTORIES","trigger":"CMAKE_VS_SDK_EXCLUDE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES","trigger":"CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_INCLUDE_DIRECTORIES","trigger":"CMAKE_VS_SDK_INCLUDE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_LIBRARY_DIRECTORIES","trigger":"CMAKE_VS_SDK_LIBRARY_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES","trigger":"CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_REFERENCE_DIRECTORIES","trigger":"CMAKE_VS_SDK_REFERENCE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_SDK_SOURCE_DIRECTORIES","trigger":"CMAKE_VS_SDK_SOURCE_DIRECTORIES\tbuiltin variable"},{"contents":"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION","trigger":"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION\tbuiltin variable"},{"contents":"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM","trigger":"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM\tbuiltin variable"},{"contents":"CMAKE_VS_WINRT_BY_DEFAULT","trigger":"CMAKE_VS_WINRT_BY_DEFAULT\tbuiltin variable"},{"contents":"CMAKE_WARN_DEPRECATED","trigger":"CMAKE_WARN_DEPRECATED\tbuiltin variable"},{"contents":"CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION","trigger":"CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION\tbuiltin variable"},{"contents":"CMAKE_WIN32_EXECUTABLE","trigger":"CMAKE_WIN32_EXECUTABLE\tbuiltin variable"},{"contents":"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS","trigger":"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS\tbuiltin variable"},{"contents":"CMAKE_XCODE_BUILD_SYSTEM","trigger":"CMAKE_XCODE_BUILD_SYSTEM\tbuiltin variable"},{"contents":"CMAKE_XCODE_GENERATE_SCHEME","trigger":"CMAKE_XCODE_GENERATE_SCHEME\tbuiltin variable"},{"contents":"CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY","trigger":"CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY\tbuiltin variable"},{"contents":"CMAKE_XCODE_LINK_BUILD_PHASE_MODE","trigger":"CMAKE_XCODE_LINK_BUILD_PHASE_MODE\tbuiltin variable"},{"contents":"CMAKE_XCODE_PLATFORM_TOOLSET","trigger":"CMAKE_XCODE_PLATFORM_TOOLSET\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER","trigger":"CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN","trigger":"CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING","trigger":"CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER","trigger":"CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS","trigger":"CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE","trigger":"CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_ENVIRONMENT","trigger":"CMAKE_XCODE_SCHEME_ENVIRONMENT\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_GUARD_MALLOC","trigger":"CMAKE_XCODE_SCHEME_GUARD_MALLOC\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP","trigger":"CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES","trigger":"CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE","trigger":"CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_MALLOC_STACK","trigger":"CMAKE_XCODE_SCHEME_MALLOC_STACK\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_THREAD_SANITIZER","trigger":"CMAKE_XCODE_SCHEME_THREAD_SANITIZER\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP","trigger":"CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER","trigger":"CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP","trigger":"CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_WORKING_DIRECTORY","trigger":"CMAKE_XCODE_SCHEME_WORKING_DIRECTORY\tbuiltin variable"},{"contents":"CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS","trigger":"CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS\tbuiltin variable"},{"contents":"CPACK_ABSOLUTE_DESTINATION_FILES","trigger":"CPACK_ABSOLUTE_DESTINATION_FILES\tbuiltin variable"},{"contents":"CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY","trigger":"CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY\tbuiltin variable"},{"contents":"CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION","trigger":"CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION\tbuiltin variable"},{"contents":"CPACK_INCLUDE_TOPLEVEL_DIRECTORY","trigger":"CPACK_INCLUDE_TOPLEVEL_DIRECTORY\tbuiltin variable"},{"contents":"CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS","trigger":"CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS\tbuiltin variable"},{"contents":"CPACK_PACKAGING_INSTALL_PREFIX","trigger":"CPACK_PACKAGING_INSTALL_PREFIX\tbuiltin variable"},{"contents":"CPACK_SET_DESTDIR","trigger":"CPACK_SET_DESTDIR\tbuiltin variable"},{"contents":"CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION","trigger":"CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION\tbuiltin variable"},{"contents":"CTEST_BINARY_DIRECTORY","trigger":"CTEST_BINARY_DIRECTORY\tbuiltin variable"},{"contents":"CTEST_BUILD_COMMAND","trigger":"CTEST_BUILD_COMMAND\tbuiltin variable"},{"contents":"CTEST_BUILD_NAME","trigger":"CTEST_BUILD_NAME\tbuiltin variable"},{"contents":"CTEST_BZR_COMMAND","trigger":"CTEST_BZR_COMMAND\tbuiltin variable"},{"contents":"CTEST_BZR_UPDATE_OPTIONS","trigger":"CTEST_BZR_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_CHANGE_ID","trigger":"CTEST_CHANGE_ID\tbuiltin variable"},{"contents":"CTEST_CHECKOUT_COMMAND","trigger":"CTEST_CHECKOUT_COMMAND\tbuiltin variable"},{"contents":"CTEST_CONFIGURATION_TYPE","trigger":"CTEST_CONFIGURATION_TYPE\tbuiltin variable"},{"contents":"CTEST_CONFIGURE_COMMAND","trigger":"CTEST_CONFIGURE_COMMAND\tbuiltin variable"},{"contents":"CTEST_COVERAGE_COMMAND","trigger":"CTEST_COVERAGE_COMMAND\tbuiltin variable"},{"contents":"CTEST_COVERAGE_EXTRA_FLAGS","trigger":"CTEST_COVERAGE_EXTRA_FLAGS\tbuiltin variable"},{"contents":"CTEST_CURL_OPTIONS","trigger":"CTEST_CURL_OPTIONS\tbuiltin variable"},{"contents":"CTEST_CUSTOM_COVERAGE_EXCLUDE","trigger":"CTEST_CUSTOM_COVERAGE_EXCLUDE\tbuiltin variable"},{"contents":"CTEST_CUSTOM_ERROR_EXCEPTION","trigger":"CTEST_CUSTOM_ERROR_EXCEPTION\tbuiltin variable"},{"contents":"CTEST_CUSTOM_ERROR_MATCH","trigger":"CTEST_CUSTOM_ERROR_MATCH\tbuiltin variable"},{"contents":"CTEST_CUSTOM_ERROR_POST_CONTEXT","trigger":"CTEST_CUSTOM_ERROR_POST_CONTEXT\tbuiltin variable"},{"contents":"CTEST_CUSTOM_ERROR_PRE_CONTEXT","trigger":"CTEST_CUSTOM_ERROR_PRE_CONTEXT\tbuiltin variable"},{"contents":"CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE","trigger":"CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE\tbuiltin variable"},{"contents":"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS","trigger":"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS\tbuiltin variable"},{"contents":"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS","trigger":"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS\tbuiltin variable"},{"contents":"CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE","trigger":"CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE\tbuiltin variable"},{"contents":"CTEST_CUSTOM_MEMCHECK_IGNORE","trigger":"CTEST_CUSTOM_MEMCHECK_IGNORE\tbuiltin variable"},{"contents":"CTEST_CUSTOM_POST_MEMCHECK","trigger":"CTEST_CUSTOM_POST_MEMCHECK\tbuiltin variable"},{"contents":"CTEST_CUSTOM_POST_TEST","trigger":"CTEST_CUSTOM_POST_TEST\tbuiltin variable"},{"contents":"CTEST_CUSTOM_PRE_MEMCHECK","trigger":"CTEST_CUSTOM_PRE_MEMCHECK\tbuiltin variable"},{"contents":"CTEST_CUSTOM_PRE_TEST","trigger":"CTEST_CUSTOM_PRE_TEST\tbuiltin variable"},{"contents":"CTEST_CUSTOM_TESTS_IGNORE","trigger":"CTEST_CUSTOM_TESTS_IGNORE\tbuiltin variable"},{"contents":"CTEST_CUSTOM_WARNING_EXCEPTION","trigger":"CTEST_CUSTOM_WARNING_EXCEPTION\tbuiltin variable"},{"contents":"CTEST_CUSTOM_WARNING_MATCH","trigger":"CTEST_CUSTOM_WARNING_MATCH\tbuiltin variable"},{"contents":"CTEST_CVS_CHECKOUT","trigger":"CTEST_CVS_CHECKOUT\tbuiltin variable"},{"contents":"CTEST_CVS_COMMAND","trigger":"CTEST_CVS_COMMAND\tbuiltin variable"},{"contents":"CTEST_CVS_UPDATE_OPTIONS","trigger":"CTEST_CVS_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_DROP_LOCATION","trigger":"CTEST_DROP_LOCATION\tbuiltin variable"},{"contents":"CTEST_DROP_METHOD","trigger":"CTEST_DROP_METHOD\tbuiltin variable"},{"contents":"CTEST_DROP_SITE","trigger":"CTEST_DROP_SITE\tbuiltin variable"},{"contents":"CTEST_DROP_SITE_CDASH","trigger":"CTEST_DROP_SITE_CDASH\tbuiltin variable"},{"contents":"CTEST_DROP_SITE_PASSWORD","trigger":"CTEST_DROP_SITE_PASSWORD\tbuiltin variable"},{"contents":"CTEST_DROP_SITE_USER","trigger":"CTEST_DROP_SITE_USER\tbuiltin variable"},{"contents":"CTEST_EXTRA_COVERAGE_GLOB","trigger":"CTEST_EXTRA_COVERAGE_GLOB\tbuiltin variable"},{"contents":"CTEST_GIT_COMMAND","trigger":"CTEST_GIT_COMMAND\tbuiltin variable"},{"contents":"CTEST_GIT_INIT_SUBMODULES","trigger":"CTEST_GIT_INIT_SUBMODULES\tbuiltin variable"},{"contents":"CTEST_GIT_UPDATE_CUSTOM","trigger":"CTEST_GIT_UPDATE_CUSTOM\tbuiltin variable"},{"contents":"CTEST_GIT_UPDATE_OPTIONS","trigger":"CTEST_GIT_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_HG_COMMAND","trigger":"CTEST_HG_COMMAND\tbuiltin variable"},{"contents":"CTEST_HG_UPDATE_OPTIONS","trigger":"CTEST_HG_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_LABELS_FOR_SUBPROJECTS","trigger":"CTEST_LABELS_FOR_SUBPROJECTS\tbuiltin variable"},{"contents":"CTEST_MEMORYCHECK_COMMAND","trigger":"CTEST_MEMORYCHECK_COMMAND\tbuiltin variable"},{"contents":"CTEST_MEMORYCHECK_COMMAND_OPTIONS","trigger":"CTEST_MEMORYCHECK_COMMAND_OPTIONS\tbuiltin variable"},{"contents":"CTEST_MEMORYCHECK_SANITIZER_OPTIONS","trigger":"CTEST_MEMORYCHECK_SANITIZER_OPTIONS\tbuiltin variable"},{"contents":"CTEST_MEMORYCHECK_SUPPRESSIONS_FILE","trigger":"CTEST_MEMORYCHECK_SUPPRESSIONS_FILE\tbuiltin variable"},{"contents":"CTEST_MEMORYCHECK_TYPE","trigger":"CTEST_MEMORYCHECK_TYPE\tbuiltin variable"},{"contents":"CTEST_NIGHTLY_START_TIME","trigger":"CTEST_NIGHTLY_START_TIME\tbuiltin variable"},{"contents":"CTEST_P4_CLIENT","trigger":"CTEST_P4_CLIENT\tbuiltin variable"},{"contents":"CTEST_P4_COMMAND","trigger":"CTEST_P4_COMMAND\tbuiltin variable"},{"contents":"CTEST_P4_OPTIONS","trigger":"CTEST_P4_OPTIONS\tbuiltin variable"},{"contents":"CTEST_P4_UPDATE_OPTIONS","trigger":"CTEST_P4_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_RESOURCE_SPEC_FILE","trigger":"CTEST_RESOURCE_SPEC_FILE\tbuiltin variable"},{"contents":"CTEST_RUN_CURRENT_SCRIPT","trigger":"CTEST_RUN_CURRENT_SCRIPT\tbuiltin variable"},{"contents":"CTEST_SCP_COMMAND","trigger":"CTEST_SCP_COMMAND\tbuiltin variable"},{"contents":"CTEST_SITE","trigger":"CTEST_SITE\tbuiltin variable"},{"contents":"CTEST_SOURCE_DIRECTORY","trigger":"CTEST_SOURCE_DIRECTORY\tbuiltin variable"},{"contents":"CTEST_SUBMIT_URL","trigger":"CTEST_SUBMIT_URL\tbuiltin variable"},{"contents":"CTEST_SVN_COMMAND","trigger":"CTEST_SVN_COMMAND\tbuiltin variable"},{"contents":"CTEST_SVN_OPTIONS","trigger":"CTEST_SVN_OPTIONS\tbuiltin variable"},{"contents":"CTEST_SVN_UPDATE_OPTIONS","trigger":"CTEST_SVN_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_TEST_LOAD","trigger":"CTEST_TEST_LOAD\tbuiltin variable"},{"contents":"CTEST_TEST_TIMEOUT","trigger":"CTEST_TEST_TIMEOUT\tbuiltin variable"},{"contents":"CTEST_TRIGGER_SITE","trigger":"CTEST_TRIGGER_SITE\tbuiltin variable"},{"contents":"CTEST_UPDATE_COMMAND","trigger":"CTEST_UPDATE_COMMAND\tbuiltin variable"},{"contents":"CTEST_UPDATE_OPTIONS","trigger":"CTEST_UPDATE_OPTIONS\tbuiltin variable"},{"contents":"CTEST_UPDATE_VERSION_ONLY","trigger":"CTEST_UPDATE_VERSION_ONLY\tbuiltin variable"},{"contents":"CTEST_UPDATE_VERSION_OVERRIDE","trigger":"CTEST_UPDATE_VERSION_OVERRIDE\tbuiltin variable"},{"contents":"CTEST_USE_LAUNCHERS","trigger":"CTEST_USE_LAUNCHERS\tbuiltin variable"},{"contents":"CYGWIN","trigger":"CYGWIN\tbuiltin variable"},{"contents":"ENV","trigger":"ENV\tbuiltin variable"},{"contents":"EXECUTABLE_OUTPUT_PATH","trigger":"EXECUTABLE_OUTPUT_PATH\tbuiltin variable"},{"contents":"GHS-MULTI","trigger":"GHS-MULTI\tbuiltin variable"},{"contents":"IOS","trigger":"IOS\tbuiltin variable"},{"contents":"LIBRARY_OUTPUT_PATH","trigger":"LIBRARY_OUTPUT_PATH\tbuiltin variable"},{"contents":"MINGW","trigger":"MINGW\tbuiltin variable"},{"contents":"MSVC","trigger":"MSVC\tbuiltin variable"},{"contents":"MSVC10","trigger":"MSVC10\tbuiltin variable"},{"contents":"MSVC11","trigger":"MSVC11\tbuiltin variable"},{"contents":"MSVC12","trigger":"MSVC12\tbuiltin variable"},{"contents":"MSVC14","trigger":"MSVC14\tbuiltin variable"},{"contents":"MSVC60","trigger":"MSVC60\tbuiltin variable"},{"contents":"MSVC70","trigger":"MSVC70\tbuiltin variable"},{"contents":"MSVC71","trigger":"MSVC71\tbuiltin variable"},{"contents":"MSVC80","trigger":"MSVC80\tbuiltin variable"},{"contents":"MSVC90","trigger":"MSVC90\tbuiltin variable"},{"contents":"MSVC_IDE","trigger":"MSVC_IDE\tbuiltin variable"},{"contents":"MSVC_TOOLSET_VERSION","trigger":"MSVC_TOOLSET_VERSION\tbuiltin variable"},{"contents":"MSVC_VERSION","trigger":"MSVC_VERSION\tbuiltin variable"},{"contents":"MSYS","trigger":"MSYS\tbuiltin variable"},{"contents":"PROJECT_BINARY_DIR","trigger":"PROJECT_BINARY_DIR\tbuiltin variable"},{"contents":"PROJECT_DESCRIPTION","trigger":"PROJECT_DESCRIPTION\tbuiltin variable"},{"contents":"PROJECT_HOMEPAGE_URL","trigger":"PROJECT_HOMEPAGE_URL\tbuiltin variable"},{"contents":"PROJECT_NAME","trigger":"PROJECT_NAME\tbuiltin variable"},{"contents":"PROJECT_SOURCE_DIR","trigger":"PROJECT_SOURCE_DIR\tbuiltin variable"},{"contents":"PROJECT_VERSION","trigger":"PROJECT_VERSION\tbuiltin variable"},{"contents":"PROJECT_VERSION_MAJOR","trigger":"PROJECT_VERSION_MAJOR\tbuiltin variable"},{"contents":"PROJECT_VERSION_MINOR","trigger":"PROJECT_VERSION_MINOR\tbuiltin variable"},{"contents":"PROJECT_VERSION_PATCH","trigger":"PROJECT_VERSION_PATCH\tbuiltin variable"},{"contents":"PROJECT_VERSION_TWEAK","trigger":"PROJECT_VERSION_TWEAK\tbuiltin variable"},{"contents":"UNIX","trigger":"UNIX\tbuiltin variable"},{"contents":"WIN32","trigger":"WIN32\tbuiltin variable"},{"contents":"WINCE","trigger":"WINCE\tbuiltin variable"},{"contents":"WINDOWS_PHONE","trigger":"WINDOWS_PHONE\tbuiltin variable"},{"contents":"WINDOWS_STORE","trigger":"WINDOWS_STORE\tbuiltin variable"},{"contents":"XCODE","trigger":"XCODE\tbuiltin variable"},{"contents":"XCODE_VERSION","trigger":"XCODE_VERSION\tbuiltin variable"}],"scope":"variable.other.readwrite.cmake"} assets/syntaxes/02_Extra/CMake/CMakeCommands.sublime-syntax:30: - match: \bVERBATIM\b assets/syntaxes/02_Extra/CMake/CMakeCommands.sublime-syntax:31: scope: variable.parameter.VERBATIM.cmake assets/syntaxes/02_Extra/CMake/CMakeCommands.sublime-syntax:59: - match: \bVERBATIM\b assets/syntaxes/02_Extra/CMake/CMakeCommands.sublime-syntax:60: scope: variable.parameter.VERBATIM.cmake assets/syntaxes/02_Extra/SCSS_Sass/Syntaxes/Sass.sublime-syntax:1830: - match: '\bat\b' assets/syntaxes/02_Extra/Elixir/builds/Elixir - mix format $file.sublime-build:6: "cmd": ["mix.bat", "format", "$file", "--dot-formatter", "$folder/.formatter.exs"], assets/syntaxes/02_Extra/Elixir/builds/Elixir - elixir $file.sublime-build:6: "cmd": ["elixir.bat", "$file_name"] assets/syntaxes/02_Extra/Lean.sublime-syntax:23: - match: '\battribute\b\s*\[[^\]]*\]' assets/syntaxes/02_Extra/PowerShell.sublime-syntax:86: - match: '(\b(([A-Za-z0-9\-_\.]+)\.(?i:exe|com|cmd|bat))\b)' assets/syntaxes/02_Extra/PowerShell.sublime-syntax:174: - 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' assets/syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax:129: - meta_content_scope: meta.environment.embedded.dosbatch.mediawiki source.dosbatch.embedded assets/syntaxes/02_Extra/MediaWiki/MediawikiNG.sublime-syntax:132: - include: scope:source.dosbatch assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/Util/RFC1751.py:125: "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/Util/RFC1751.py:189: "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:12177: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMGowFAYHKoZIzj0CAQYJKyQDAwIIAQEJA1IABHJlM+Jnc6xyChFbAt6JrBWWZnfi\nObfFd6HBW4ECex/rc+ZzYB4hGqkqzLWFvAbMJ0thyeYUdG7dJI0czPjYsatLwVzF\njN8RYGXOl2fyoyI9\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:13141: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMHowFAYHKoZIzj0CAQYJKyQDAwIIAQELA2IABATZ1KYtbrAgc+c4seQ5zs1UQAMZ\nEfRRkOtgYqM1NfxSabz8JdSvwdrg662UjXcy2AKa836Jo86n3ziwIPYkkG/KbZRO\nFIaFP+jlupz7otdKhS7Fh9Rv5JkXw2RBjvfspQ==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_secp256r1_sha256_test.json:2410: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3q0Rx6WzloYvIZdNxHUvre/5lO/p\nu9BatBN2XqgLbh8d4/BkDorG7c+Jz/U8QOJlu5QHijQ3Nt8HqgMY/H/h/w==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.lin.x64/Crypto/SelfTest/PublicKey/test_import_RSA.py:444:MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/Util/RFC1751.py:125: "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/Util/RFC1751.py:189: "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:12177: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMGowFAYHKoZIzj0CAQYJKyQDAwIIAQEJA1IABHJlM+Jnc6xyChFbAt6JrBWWZnfi\nObfFd6HBW4ECex/rc+ZzYB4hGqkqzLWFvAbMJ0thyeYUdG7dJI0czPjYsatLwVzF\njN8RYGXOl2fyoyI9\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:13141: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMHowFAYHKoZIzj0CAQYJKyQDAwIIAQELA2IABATZ1KYtbrAgc+c4seQ5zs1UQAMZ\nEfRRkOtgYqM1NfxSabz8JdSvwdrg662UjXcy2AKa836Jo86n3ziwIPYkkG/KbZRO\nFIaFP+jlupz7otdKhS7Fh9Rv5JkXw2RBjvfspQ==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_secp256r1_sha256_test.json:2410: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3q0Rx6WzloYvIZdNxHUvre/5lO/p\nu9BatBN2XqgLbh8d4/BkDorG7c+Jz/U8QOJlu5QHijQ3Nt8HqgMY/H/h/w==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.win.x64/Crypto/SelfTest/PublicKey/test_import_RSA.py:444:MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/Util/RFC1751.py:125: "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/Util/RFC1751.py:189: "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:12177: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMGowFAYHKoZIzj0CAQYJKyQDAwIIAQEJA1IABHJlM+Jnc6xyChFbAt6JrBWWZnfi\nObfFd6HBW4ECex/rc+ZzYB4hGqkqzLWFvAbMJ0thyeYUdG7dJI0czPjYsatLwVzF\njN8RYGXOl2fyoyI9\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_test.json:13141: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMHowFAYHKoZIzj0CAQYJKyQDAwIIAQELA2IABATZ1KYtbrAgc+c4seQ5zs1UQAMZ\nEfRRkOtgYqM1NfxSabz8JdSvwdrg662UjXcy2AKa836Jo86n3ziwIPYkkG/KbZRO\nFIaFP+jlupz7otdKhS7Fh9Rv5JkXw2RBjvfspQ==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/SelfTest/Signature/test_vectors/wycheproof/ecdsa_secp256r1_sha256_test.json:2410: "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3q0Rx6WzloYvIZdNxHUvre/5lO/p\nu9BatBN2XqgLbh8d4/BkDorG7c+Jz/U8QOJlu5QHijQ3Nt8HqgMY/H/h/w==\n-----END PUBLIC KEY-----", assets/syntaxes/02_Extra/MediaWiki/lib/Crypto.osx.x64/Crypto/SelfTest/PublicKey/test_import_RSA.py:444:MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL assets/syntaxes/02_Extra/Julia/julia_unicode/emoji_symbols.py:69: ("\\:battery:", u"🔋"), assets/syntaxes/02_Extra/Julia/julia_unicode/emoji_symbols.py:576: ("\\:tanabata_tree:", u"🎋"), assets/syntaxes/02_Extra/Julia/julia_unicode/emoji_symbols.py:729: ("\\:bath:", u"🛀"), assets/syntaxes/02_Extra/Julia/julia_unicode/emoji_symbols.py:804: ("\\:bathtub:", u"🛁"), assets/syntaxes/02_Extra/Crystal.sublime-syntax:136: - match: '\b(initialize|new|loop|include|extend|raise|getter|setter|property|class_getter|class_setter|class_property|describe|context|it|with|delegate|def_hash|def_equals|def_equals_and_hash|forward_missing_to|record|assert_responds_to|spawn|annotation|verbatim)\b[!?]?' assets/syntaxes/02_Extra/Dart/docgen.py:30: cmd = ["docgen.bat", "--no-include-sdk", path] assets/syntaxes/02_Extra/Dart/docgen.py:58: cmd = ["docgen.bat", "--no-include-sdk", "--serve", path] assets/syntaxes/02_Extra/Dart/lib/sdk.py:177: return self.get_bin_tool('pub', '.bat') assets/syntaxes/02_Extra/Dart/lib/sdk.py:183: return self.get_bin_tool('dart2js', '.bat') assets/syntaxes/02_Extra/Dart/lib/sdk.py:189: return self.get_bin_tool('dartanalyzer', '.bat') assets/syntaxes/02_Extra/Dart/lib/sdk.py:195: return self.get_bin_tool('docgen', '.bat') assets/syntaxes/02_Extra/Dart/lib/sdk.py:247: self.path = SDK().get_bin_tool('dartfmt', '.bat') assets/syntaxes/02_Extra/Dart/sublime_plugin_lib/path.py:142: Useful to add .exe to @original, .bat, etc if ST is running on Windows. assets/syntaxes/02_Extra/Dart/sublime_plugin_lib/path.py:186: """ Useful to add .exe, .bat, etc. to @original if ST is running on assets/syntaxes/02_Extra/Dart/Support/Dart.sublime-build:19: "cmd": ["dart2js.bat", "--minify", "-o$file.js", "$file"] assets/syntaxes/02_Extra/Dart/Support/Dart - Pubspec.sublime-build:21: "cmd": ["pub.bat", "upgrade"] assets/syntaxes/02_Extra/Dart/Support/Dart - Pubspec.sublime-build:36: "cmd": ["pub.bat", "version"] assets/syntaxes/02_Extra/LESS/Syntaxes/LESS.sublime-syntax:1709: - match: '\bat\b' assets/syntaxes/02_Extra/Email/README.md:15::mouse: Using [bat](https://github.com/sharkdp/bat) *(bat is a cat clone with syntax highlighting and Git integration)* assets/syntaxes/02_Extra/Email/README.md:16:![bat](https://raw.githubusercontent.com/mariozaizar/email.sublime-syntax/master/demo/bat.png) assets/syntaxes/02_Extra/Email/link_bat.sh:3:# We use bat to verify the sintax. bat is a cat clone with syntax highlighting assets/syntaxes/02_Extra/Email/link_bat.sh:4:# and Git integration. bat uses syntect library for syntax highlighting which assets/syntaxes/02_Extra/Email/link_bat.sh:7:# https://github.com/sharkdp/bat assets/syntaxes/02_Extra/Email/link_bat.sh:9:bat --version || brew install bat # Mac OS only assets/syntaxes/02_Extra/Email/link_bat.sh:11:BAT_PATH=$(bat --config-dir) assets/syntaxes/02_Extra/Email/link_bat.sh:13:mkdir -p "$BAT_PATH/syntaxes" assets/syntaxes/02_Extra/Email/link_bat.sh:14:mkdir -p "$BAT_PATH/themes" assets/syntaxes/02_Extra/Email/link_bat.sh:16:INSTALL_PATH=${BAT_PATH}/syntaxes assets/syntaxes/02_Extra/Email/link_bat.sh:19:bat cache --build assets/syntaxes/02_Extra/Email/link_bat.sh:20:bat --list-languages | grep "Email" assets/syntaxes/02_Extra/Email/link_bat.sh:22:bat demo/email.eml assets/syntaxes/02_Extra/TypeScript.sublime-syntax:2446: |AudioNode|AudioParam|BatteryManager|BeforeUnloadEvent|BiquadFilterNode|Blob|BufferSource|ByteString|CSS|CSSConditionRule assets/syntaxes/02_Extra/HTML (Twig)/Preferences/Indentation.tmPreferences:22: ^\s*\{%-?\s(end(?:autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)|(else))(?:(?!%\}).)*\s-?%\} assets/syntaxes/02_Extra/HTML (Twig)/Preferences/Indentation.tmPreferences:36: ^\s*\{%-?\s(autoescape|block|embed|filter|for|if|else|macro|raw|sandbox|set|spaceless|trans|verbatim)(?:(?!%\}).)*\s-?%\}(?!.*\{%-?\send\1) assets/syntaxes/02_Extra/HTML (Twig)/Preferences/Folding.tmPreferences:16: |\{%\s+(autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim) assets/syntaxes/02_Extra/HTML (Twig)/Preferences/Folding.tmPreferences:23: |\{%\s+end(autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim) assets/syntaxes/02_Extra/HTML (Twig)/Snippets/verbatim.tmSnippet:6: {% verbatim %} assets/syntaxes/02_Extra/HTML (Twig)/Snippets/verbatim.tmSnippet:8:{% endverbatim %} assets/syntaxes/02_Extra/HTML (Twig)/Snippets/verbatim.tmSnippet:10: verbatim assets/syntaxes/02_Extra/HTML (Twig)/Snippets/verbatim.tmSnippet:14: verbatim assets/syntaxes/02_Extra/HTML (Twig)/Syntaxes/HTML (Twig).tmLanguage:1374: (?<=\s)((?:end)?(?:autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)|as|do|else|elseif|extends|flush|from|ignore missing|import|include|only|use|with)(?=\s) assets/syntaxes/02_Extra/HTML (Twig)/Syntaxes/HTML (Twig).tmLanguage:1590: (?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\'\"]\|)|\{%\sfilter\s)(batch|convert_encoding|date|date_modify|default|e(?:scape)?|format|join|merge|number_format|replace|round|slice|split|trim)(\() assets/syntaxes/02_Extra/requirementstxt/LICENSE:5: Everyone is permitted to copy and distribute verbatim copies assets/syntaxes/02_Extra/requirementstxt/LICENSE:195: 4. Conveying Verbatim Copies. assets/syntaxes/02_Extra/requirementstxt/LICENSE:197: You may convey verbatim copies of the Program's source code as you assets/syntaxes/01_Packages/Batch File/Symbol List.tmPreferences:7: source.dosbatch entity.name.label - meta.function-call assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:4:name: Batch File assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:6: - bat assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:8:scope: source.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:31: scope: keyword.control.statement.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:34: 1: keyword.control.statement.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:35: 2: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:36: 3: keyword.control.flow.return.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:37: 4: meta.function-call.dosbatch variable.function.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:40: 1: keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:41: 2: keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:42: 3: keyword.other.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:44: scope: keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:46: scope: keyword.control.repeat.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:50: scope: keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:60: scope: keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:64: scope: keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:74: 1: punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:75: 2: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:76: 3: keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:78: - meta_scope: string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:80: scope: punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:88: 1: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:89: 2: keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:91: - meta_content_scope: string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:96: scope: punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:98: - meta_scope: string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:101: scope: punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:108: scope: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:112: - meta_content_scope: meta.expression.set.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:120: 1: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:121: 2: keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:123: - meta_scope: meta.prompt.set.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:132: scope: comment.line.ignored.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:135: - meta_content_scope: string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:145: scope: punctuation.section.group.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:148: scope: punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:153: - meta_scope: meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:155: scope: punctuation.section.group.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:158: scope: punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:164: scope: keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:167: 1: constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:168: 2: keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:170: scope: keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:173: 1: constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:174: 2: keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:176: scope: keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:180: scope: keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:182: scope: keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:186: - meta_scope: string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:190: scope: punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:193: scope: punctuation.section.group.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:195: - meta_scope: meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:202: - meta_scope: meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:204: scope: punctuation.section.group.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:207: scope: punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:214: - meta_scope: string.quoted.double.dosbatch meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:216: scope: punctuation.section.group.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:219: scope: punctuation.section.group.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:227: scope: keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:233: scope: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:238: scope: variable.parameter.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:240: 1: punctuation.definition.variable.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:242: scope: variable.language.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:244: 1: punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:245: 2: punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:252: scope: punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:254: - meta_scope: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:257: 1: punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:261: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:263: - meta_content_scope: meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:269: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:271: - meta_content_scope: meta.variable.substitution.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:276: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:282: scope: string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:287: scope: punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:289: - meta_scope: variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:292: 1: punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:296: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:298: - meta_content_scope: meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:304: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:306: - meta_content_scope: meta.variable.substitution.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:312: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:318: scope: string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:322: scope: string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:326: scope: constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:331: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:335: scope: constant.numeric.integer.hexadecimal.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:337: 1: punctuation.definition.numeric.hexadecimal.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:339: scope: constant.numeric.integer.octal.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:341: 1: punctuation.definition.numeric.octal.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:343: scope: constant.numeric.integer.decimal.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:347: scope: constant.language.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:351: scope: keyword.operator.at.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:353: scope: keyword.operator.comparison.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:355: scope: keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:357: scope: keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:359: scope: keyword.operator.pipe.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:361: scope: keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:366: 1: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:367: 2: entity.name.label.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:372: 1: keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:375: scope: comment.line.rem.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:378: scope: punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:380: - meta_scope: comment.line.colon.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:386: scope: keyword.command.rem.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:390: - meta_content_scope: comment.line.rem.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:392: scope: comment.line.rem.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:395: scope: invalid.illegal.unexpected-character.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:399: scope: punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:401: - meta_scope: string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:404: 1: punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:405: 2: invalid.illegal.newline.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:412: scope: punctuation.section.group.begin.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:414: - meta_scope: meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:416: scope: punctuation.section.group.end.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:419: scope: punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/Batch File.sublime-syntax:424: scope: constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/Comments.tmPreferences:7: source.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:1::: SYNTAX TEST "Packages/Batch File/Batch File.sublime-syntax" assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:4::: ^^^ keyword.command.rem.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:5::: ^^^^^^^^^^^^^^^^ comment.line.rem.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:6::: ^ invalid.illegal.unexpected-character.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:7::: ^ invalid.illegal.unexpected-character.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:8::: ^ invalid.illegal.unexpected-character.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:12::: ^^^^^^^^^^^^^ - comment.line.rem.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:19::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:20::: ^^^^^^^^^^ comment.line.colon.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:23::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:26::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:29::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:32::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:35::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:46::: ^ keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:47::: ^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:48::: ^^^^^^^^^^^^ comment.line.colon.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:51:::^^ punctuation.definition.comment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:52:::^^^^^^^^^^^^^^^^^^^^^^ comment.line.colon.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:55::: ^ punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:56::: ^^^^^ string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:57::: ^ punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:60::: ^ invalid.illegal.newline.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:63::: ^ keyword.operator.at.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:66::: ^ - keyword.operator.at.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:69::: ^^^^ keyword.control.statement.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:70::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:71::: ^^^ keyword.control.flow.return.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:74::: ^^^^ keyword.control.statement.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:75::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:76::: ^^^ meta.function-call.dosbatch variable.function.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:79::: ^^^^ keyword.control.statement.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:80::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:81::: ^^^ meta.function-call.dosbatch variable.function.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:85::: ^^^^ keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:86::: ^ keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:89::: ^^ keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:93::: ^ keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:94::: ^^ keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:97::: ^^ keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:98::: ^^ keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:99::: ^ keyword.operator.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:103::: ^^ keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:104::: ^^^ keyword.operator.comparison.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:107::: ^^ keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:108::: ^^^ keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:109::: ^^^ keyword.operator.comparison.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:113::: ^^ keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:114::: ^^^^^^^^^^^^ variable.language.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:115::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:116::: ^ variable.language.dosbatch punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:119::: ^^ keyword.control.conditional.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:120::: ^^ keyword.operator.comparison.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:123::: ^^^ keyword.control.repeat.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:124::: ^ constant.numeric.integer.decimal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:127::: ^ keyword.operator.pipe.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:130:::^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:131::: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entity.name.label.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:134:::^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:135::: ^^^ entity.name.label.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:138::: ^ punctuation.definition.variable.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:139::: ^^ variable.parameter.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:140::: ^ punctuation.definition.variable.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:141::: ^^ variable.parameter.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:142::: ^ punctuation.definition.variable.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:143::: ^^^^^^^^^^^ variable.parameter.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:144::: ^ punctuation.definition.variable.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:145::: ^^^ variable.parameter.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:148::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:149::: ^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:150::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:151::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:152::: ^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:153::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:156::: ^^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:157::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:158::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:159::: ^^^^^^^^^ meta.variable.substitution.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:160::: ^^^^ string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:161::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:162::: ^^^^ string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:163::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:164::: ^^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:165::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:166::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:167::: ^^^^^^^^^ meta.variable.substitution.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:168::: ^^^^ string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:169::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:170::: ^^^^ string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:171::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:175::: ^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:176::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:177::: ^^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:178::: ^^^^ meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:179::: ^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:180::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:181::: ^^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:182::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:183::: ^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:184::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:185::: ^^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:186::: ^^^^ meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:187::: ^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:188::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:189::: ^^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:190::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:193::: ^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:194::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:195::: ^^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:196::: ^^ meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:197::: ^^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:198::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:199::: ^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:200::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:201::: ^^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:202::: ^^ meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:203::: ^^ constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:204::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:207::: ^^^^^^^^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:208::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:209::: ^^^^^ meta.variable.substitution.dosbatch variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:210::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:211::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:212::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:213::: ^^^^^^^^^^^ meta.variable.substitution.dosbatch variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:214::: ^^^^ meta.variable.substitution.dosbatch meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:215::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:216::: ^^ meta.variable.substitution.dosbatch constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:217::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:220::: ^^^^^^^^^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:221::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:222::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:223::: ^^^^^^^^^^^ meta.variable.substitution.dosbatch variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:224::: ^^^^ meta.variable.substitution.dosbatch meta.variable.substring.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:225::: ^ meta.variable.substitution.dosbatch punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:226::: ^^ meta.variable.substitution.dosbatch constant.numeric.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:227::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:230::: ^^^^^^^^^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:231::: ^^^ - keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:234::: ^^^^^^^^^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:235::: ^^^ - keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:239::: ^^^ constant.numeric.integer.octal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:240::: ^ punctuation.definition.numeric.octal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:241::: ^^^^ constant.numeric.integer.hexadecimal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:242::: ^^ punctuation.definition.numeric.hexadecimal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:243::: ^^ constant.numeric.integer.decimal.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:247::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:248::: ^^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:249::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:253::: ^^^^^^^^^ meta.expression.set.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:254::: ^^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:257::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:260::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:263::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:266::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:269::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:272::: ^^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:275::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:276::: ^ keyword.operator.logical.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:279::: ^^^^^ meta.group.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:280::: ^ punctuation.section.group.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:281::: ^ punctuation.section.group.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:282::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:283::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:284::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:287::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:288::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:289::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:290::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:293::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:294::: ^^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:297::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:298::: ^^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:301::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:302::: ^^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:305::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:306::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:309::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:310::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:313::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:314::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:317::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:320::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:321::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:324::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:325::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:328::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:329::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:332::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:333::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:336::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:337::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:340::: ^^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:343::: ^^ keyword.operator.assignment.augmented.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:346::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:347::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:348::: ^ punctuation.separator.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:349::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:350::: ^ keyword.operator.arithmetic.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:436::: ^^^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:444::: ^^^^^^^^^^^ string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:445::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:446::: ^ - constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:447::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:448::: ^ - constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:449::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:450::: ^ - constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:454::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:455::: ^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:456::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:457::: ^ keyword.operator.redirection.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:459::: ^ punctuation.definition.variable.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:460::: ^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:461::: ^ punctuation.definition.variable.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:464::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:465::: ^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:466::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:467::: ^^^^^^^^^^^^^ meta.prompt.set.dosbatch string.unquoted - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:468::: ^ - meta.prompt.set.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:470::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:471::: ^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:472::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:473::: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.prompt.set.dosbatch string.unquoted - variable.other.readwrite.dosbatch - comment assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:474::: ^ - meta.prompt.set.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:476::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:477::: ^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:478::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:479::: ^ - meta.prompt.set.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:493::: ^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:494::: ^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:498::: ^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:499::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:500::: ^ punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:501::: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:502::: ^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:503::: ^^ constant.character.escape.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:504::: ^ punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:505::: ^^^ string.unquoted.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:508:::^^^^^^ keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:510::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:511::: ^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:512::: ^ keyword.operator.assignment.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:513::: ^ punctuation.definition.string.begin.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:514::: ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.prompt.set.dosbatch string.quoted assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:515::: ^ punctuation.definition.string.end.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:516::: ^ keyword.operator.conditional.dosbatch - meta.prompt.set.dosbatch - string assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:517::: ^^^^ keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:518::: ^^^^^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:520:::^^^^^^ keyword.command.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:542::: ^^^^ - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:543::: ^^^^^ variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:544::: ^ keyword.operator.assignment.dosbatch - variable.other.readwrite.dosbatch assets/syntaxes/01_Packages/Batch File/syntax_test_batch_file.bat:545::: ^^^^^^^^^^^^^^^^ meta.prompt.set.dosbatch string.quoted - variable.other.readwrite.dosbatch - comment assets/syntaxes/01_Packages/CSS/CSS.sublime-syntax:1257: - match: '\bat\b' assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:35:var verbatim_singleline = @"foo"; assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:37:var verbatim_singleline_interpolated_none = $@"foo bar"; assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:39:var verbatim_singleline_interpolated_yes = $@"foo {bar} foo"; assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:42:var verbatim_multiline = @"foo bar assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:45:var verbatim_multiline_interpolated_none = $@"foo bar assets/syntaxes/01_Packages/C#/tests/syntax_test_Strings.cs:48:var verbatim_multiline_interpolated_yes = $@"foo {bar} assets/syntaxes/01_Packages/C#/tests/syntax_test_GeneralStructure.cs:344: case BLBodyBattleLibrary.ContextType.TapUp: assets/syntaxes/01_Packages/C#/tests/syntax_test_Generics.cs:57:string verbatim = @"This is a test "" of a verbatim string literal - C:\User"; assets/syntaxes/01_Packages/C#/tests/syntax_test_c#.cs:35:string verbatim = @"This is a test "" of a verbatim string literal - C:\User"; assets/syntaxes/01_Packages/PHP/PHP.sublime-completions:2082: { "trigger": "mssql_fetch_batch", "contents": "mssql_fetch_batch(${1:result})" }, assets/syntaxes/01_Packages/PHP/PHP Source.sublime-syntax:407: # verbatim and the indexer should find the name in the original source assets/syntaxes/01_Packages/PHP/PHP Source.sublime-syntax:447: # verbatim and the indexer should find the name in the original source assets/syntaxes/01_Packages/PHP/PHP Source.sublime-syntax:2082: mssql_bind | mssql_close | mssql_connect | mssql_data_seek | mssql_execute | mssql_fetch_array | mssql_fetch_assoc | mssql_fetch_batch | assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:29: - include: verbatim assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:311: verbatim: assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:312: - match: '((\\)begin)(\{)\s*((?:[vV]erbatim|alltt)\*?)\s*(\})' assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:321: - meta_scope: meta.environment.verbatim.verbatim.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:322: - meta_content_scope: markup.raw.verbatim.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:541: - meta_scope: meta.environment.verbatim.verb.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:777: - meta_scope: meta.environment.verbatim.lstinline.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:784: - meta_content_scope: meta.environment.verbatim.lstinline.latex markup.raw.verb.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:786: scope: meta.environment.verbatim.lstinline.latex punctuation.definition.group.brace.end.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:792: - meta_content_scope: meta.environment.verbatim.lstinline.latex markup.raw.verb.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:794: scope: meta.environment.verbatim.lstinline.latex punctuation.definition.verb.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:806: - meta_scope: meta.environment.verbatim.lstlisting.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:938: - meta_scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1146: - meta_scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1149: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1157: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.c.latex source.c.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1163: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1171: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.c++.latex source.c++.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1177: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1185: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.diff.latex source.diff.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1191: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1199: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.go.latex source.go.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1205: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1213: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.haskell.latex source.haskell.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1219: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1227: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.html.latex text.html.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1233: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1241: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.java.latex source.java.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1247: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1255: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.js.latex source.js.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1261: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1269: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.json.latex source.json.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1275: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1283: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.latex.latex text.tex.latex.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1289: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1297: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.lisp.latex source.lisp.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1303: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1311: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.lua.latex source.lua.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1317: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1325: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.objc.latex source.objc.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1331: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1339: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.objc++.latex source.objc++.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1345: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1353: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.perl.latex source.perl.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1359: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1367: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.php.latex source.php.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1373: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1381: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.python.latex source.python.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1387: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1395: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.r.latex source.r.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1401: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1409: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.ruby.latex source.ruby.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1415: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1423: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.shell.latex source.shell.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1429: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1437: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.sql.latex source.sql.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1443: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1451: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.xml.latex text.xml.embedded assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1457: scope: meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/LaTeX.sublime-syntax:1465: embed_scope: meta.environment.verbatim.minted.latex meta.environment.embedded.yaml.latex source.yaml.embedded assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:261:% VERBATIM assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:267:% ^ meta.environment.verbatim.verb.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:271:% ^ meta.environment.verbatim.verb.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:274:% ^^^^^^^^^^^^^^ meta.environment.verbatim.verb.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:277:% <- - meta.environment.verbatim.verb.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:279:\begin{verbatim} assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:282:The \emph{verbatim} environment sets everything in verbatim. assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:283:% <- meta.environment.verbatim.verbatim.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:284:% ^ markup.raw.verbatim.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:290:\end{verbatim} assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:397:% <- meta.environment.verbatim.lstlisting.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:407:% <- meta.environment.verbatim.lstlisting.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:415:% <- meta.environment.verbatim.lstlisting.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:423:% ^^^^^^^^^^^^^^^^^^^^^ meta.environment.verbatim.lstinline.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:428:% ^ - meta.environment.verbatim.lstinline.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:431:% ^^^^^^^^^^^^^^^^^^^^^ meta.environment.verbatim.lstinline.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:433:% ^ - meta.environment.verbatim.lstinline.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:443:% <- meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:451:% ^ meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:459:% ^ meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/LaTeX/syntax_test_latex.tex:464:% ^ meta.environment.verbatim.minted.latex assets/syntaxes/01_Packages/Java/Ant.sublime-build:10: "cmd": ["ant.bat"] assets/syntaxes/01_Packages/Matlab/Matlab.sublime-syntax:325: - match: \b(zerom|zero22pi|zdatam-ui|zdatam|wrapToPi|wrapTo360|wrapTo2Pi|wrapTo180|worldmap|worldfilewrite|worldfileread|westof|vmap0ui|vmap0rhead|vmap0read|vmap0data|vinvtran|viewshed|vfwdtran|vec2mtx|utmzoneui|utmzone|utmgeoid|usgsdems|usgsdem|usgs24kdem|usamap|updategeostruct|unwrapMultipart|unitstr|unitsratio|undotrim|undoclip|uimaptbx|trimdata|trimcart|trackui|trackg|track2|track1|track|toRadians|toDegrees|tissot|timezone|timedim|time2str|tightmap|tigerp|tigermif|tgrline|textm|tbase|tagm-ui|tagm|symbolm|surfm|surflsrm|surflm|surfdist|surfacem|str2angle|stem3m|stdm|stdist|spzerom|spcread|smoothlong|sm2rad|sm2nm|sm2km|sm2deg|sizem|showm-ui|showm|showaxes|shapewrite|shaperead|shapeinfo|shaderel|setpostn|setm|setltln|seedm|sectorg|sec2hr|sec2hms|sec2hm|sdtsinfo|sdtsdemread|scxsc|scirclui|scircleg|scircle2|scircle1|scatterm|scaleruler|satbath|rsphere|roundn|rotatetext|rotatem|rootlayr|rhxrh|restack|resizem|removeExtraNanSeparators|refvec2mat|refmat2vec|reducem|reckon|readmtx|readfk5|readfields|rcurve|rad2sm|rad2nm|rad2km|rad2dms|rad2dm|rad2deg|quiverm|quiver3m|qrydata|putpole|projlist|projinv|projfwd|project|previewmap|polyxpoly|polysplit|polymerge|polyjoin|polycut|polybool|poly2fv|poly2cw|poly2ccw|polcmap|plotm|plot3m|plabel|pixcenters|pix2map|pix2latlon|pcolorm|patchm|patchesm|parallelui|paperscale|panzoom|originui|org2pol|onem|npi2pi|northarrow|nm2sm|nm2rad|nm2km|nm2deg|newpole|neworig|navfix|nanm|nanclip|namem|n2ecc|mobjects|mlayers|mlabelzero22pi|mlabel|minvtran|minaxis|mfwdtran|meshm|meshlsrm|meshgrat|meridianfwd|meridianarc|meanm|mdistort|mat2hms|mat2dms|mapview|maptrims|maptrimp|maptriml|maptrim|maptool|mapshow|maps|mapprofile|mapoutline|maplist|mapbbox|map2pix|makesymbolspec|makerefmat|makemapped|makedbfspec|makeattribspec|majaxis|lv2ecef|ltln2val|los2|linem|linecirc|limitm|lightmui|lightm|legs|lcolorbar|latlon2pix|kmlwrite|km2sm|km2rad|km2nm|km2deg|ispolycw|ismapped|ismap|isShapeMultipart|intrplon|intrplat|interpm|inputm|ind2rgb8|imbedm|hr2sec|hr2hms|hr2hm|hms2sec|hms2mat|hms2hr|hms2hm|histr|hista|hidem-ui|hidem|handlem-ui|handlem|gtopo30s|gtopo30|gtextm|gshhs|grn2eqa|gridm|grid2image|grepfields|gradientm|globedems|globedem|getworldfilename|getseeds|getm|geotiffread|geotiffinfo|geotiff2mstruct|geoshow|geoloc2grid|geodetic2geocentricLat|geodetic2ecef|geocentric2geodeticLat|gcxsc|gcxgc|gcwaypts|gcpmap|gcm|gc2sc|fromRadians|fromDegrees|framem|flatearthpoly|flat2ecc|fipsname|findm|filterm|fillm|fill3m|extractm|extractfield|etopo5|etopo|eqa2grn|epsm|encodem|ellipse1|elevation|egm96geoid|ecef2lv|ecef2geodetic|ecc2n|ecc2flat|eastof|dteds|dted|driftvel|driftcorr|dreckon|dms2rad|dms2mat|dms2dm|dms2degrees|dms2deg|dm2degrees|distortcalc|distdim|distance|dist2str|displaym|departure|demdataui|demcmap|degrees2dms|degrees2dm|deg2sm|deg2rad|deg2nm|deg2km|deg2dms|deg2dm|defaultm|dcwrhead|dcwread|dcwgaz|dcwdata|daspectm|crossfix|convertlat|contourm|contourfm|contourcmap|contour3m|cometm|comet3m|combntns|colorui|colorm|cmapui|clrmenu|closePolygonParts|clmo-ui|clmo|clma|clipdata|clegendm|clabelm|circcirc|changem|cart2grn|camupm|camtargm|camposm|bufferm|azimuth|axesscale|axesmui|axesm|axes2ecc|avhrrlambert|avhrrgoode|areaquad|areamat|areaint|arcgridread|antipode|angledim|angl2str|almanac)\b assets/syntaxes/01_Packages/RestructuredText/reStructuredText.sublime-syntax:41: comment: verbatim blocks assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:95:Verbatim tests assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:100: Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:105: Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:112: Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:114: Also Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:119: Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:121: Also Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:127: Verbatim assets/syntaxes/01_Packages/RestructuredText/syntax_test_restructuredtext.rst:129:Not verbatim assets/syntaxes/01_Packages/Go/Indents/GoIndent.tmPreferences:4:batch-reindent real-world code without wrecking it. As such, these rules are assets/syntaxes/01_Packages/Go/Indents/GoIndent.tmPreferences:5:optimized for convenience while typing, not for batch reindentation. assets/syntaxes/01_Packages/YAML/YAML.sublime-syntax:64: c_ns_tag_property: |- # c-verbatim-tag | c-ns-shorthand-tag | c-non-specific-tag assets/manual/bat.1.in:113:\fB-P\fR. To disable the pager permanently, set BAT_PAGER to an empty string. To control assets/manual/bat.1.in:118:Determine which pager is used. This option will override the PAGER and BAT_PAGER assets/manual/bat.1.in:134:export the BAT_THEME environment variable (e.g.: export BAT_THEME="..."). assets/manual/bat.1.in:146:export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible assets/manual/bat.1.in:194:Alternatively, you can use the BAT_CONFIG_PATH environment variable to point {{PROJECT_EXECUTABLE}} to a non-default assets/manual/bat.1.in:235:\fBhttps://github.com/sharkdp/bat\fR assets/completions/bat.bash.in:5:_bat() { assets/completions/bat.bash.in:88:} && complete -F _bat {{PROJECT_EXECUTABLE}} assets/completions/_bat.ps1.in:64: [CompletionResult]::new('--config-dir', 'config-dir', [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.') assets/completions/_bat.ps1.in:65: [CompletionResult]::new('--cache-dir', 'cache-dir', [CompletionResultType]::ParameterName, 'Show bat''s cache directory.') assets/completions/bat.zsh.in:49: '(: --config-dir)'--config-dir'[Show bat'"'"'s configuration directory]' assets/completions/bat.zsh.in:52: '(: --cache-dir)'--cache-dir'[Show bat'"'"'s cache directory]' assets/create.sh:43:bat cache --clear assets/create.sh:56:bat cache --build --blank --source="$ASSET_DIR" --target="$ASSET_DIR" assets/metadata.yaml:2:bat_version: 0.18.3 tests/integration_tests.rs:34:fn bat_raw_command_with_config() -> Command { tests/integration_tests.rs:35: let mut cmd = Command::cargo_bin("bat").unwrap(); tests/integration_tests.rs:37: cmd.env_remove("BAT_CACHE_PATH"); tests/integration_tests.rs:38: cmd.env_remove("BAT_CONFIG_DIR"); tests/integration_tests.rs:39: cmd.env_remove("BAT_CONFIG_PATH"); tests/integration_tests.rs:40: cmd.env_remove("BAT_OPTS"); tests/integration_tests.rs:41: cmd.env_remove("BAT_PAGER"); tests/integration_tests.rs:42: cmd.env_remove("BAT_STYLE"); tests/integration_tests.rs:43: cmd.env_remove("BAT_TABS"); tests/integration_tests.rs:44: cmd.env_remove("BAT_THEME"); tests/integration_tests.rs:51:fn bat_raw_command() -> Command { tests/integration_tests.rs:52: let mut cmd = bat_raw_command_with_config(); tests/integration_tests.rs:57:fn bat_with_config() -> assert_cmd::Command { tests/integration_tests.rs:58: assert_cmd::Command::from_std(bat_raw_command_with_config()) tests/integration_tests.rs:61:fn bat() -> assert_cmd::Command { tests/integration_tests.rs:62: assert_cmd::Command::from_std(bat_raw_command()) tests/integration_tests.rs:67: bat() tests/integration_tests.rs:77: bat() tests/integration_tests.rs:86: bat() tests/integration_tests.rs:96: bat() tests/integration_tests.rs:108: bat() tests/integration_tests.rs:118: bat() tests/integration_tests.rs:128: bat() tests/integration_tests.rs:138: bat() tests/integration_tests.rs:149: bat() tests/integration_tests.rs:160: bat() tests/integration_tests.rs:170: bat() tests/integration_tests.rs:181: bat() tests/integration_tests.rs:192: bat() tests/integration_tests.rs:202: bat() tests/integration_tests.rs:212: bat() tests/integration_tests.rs:222: bat() tests/integration_tests.rs:245: let res = bat_raw_command() tests/integration_tests.rs:261: let res = bat_raw_command() tests/integration_tests.rs:277: let res = bat_raw_command() tests/integration_tests.rs:293: let res = bat_raw_command() tests/integration_tests.rs:307: // To simulate bat getting started from the shell, a process is created with stdin and stdout tests/integration_tests.rs:308: // as the slave end of a pseudo terminal. Although both point to the same "file", bat should tests/integration_tests.rs:316: let mut child = bat_raw_command() tests/integration_tests.rs:349: bat() tests/integration_tests.rs:372: bat() tests/integration_tests.rs:395: bat() tests/integration_tests.rs:418: bat() tests/integration_tests.rs:441: bat() tests/integration_tests.rs:464: bat() tests/integration_tests.rs:487: bat() tests/integration_tests.rs:510: bat().arg("non-existing-file").assert().failure(); tests/integration_tests.rs:515: bat().arg("sub_directory").assert().failure(); tests/integration_tests.rs:520: bat() tests/integration_tests.rs:530: bat() tests/integration_tests.rs:541: bat() tests/integration_tests.rs:543: .env("BAT_PAGER", "echo pager-output") tests/integration_tests.rs:553: bat() tests/integration_tests.rs:555: .env("BAT_PAGER", "") tests/integration_tests.rs:564:fn env_var_pager_value_bat() { tests/integration_tests.rs:565: bat() tests/integration_tests.rs:566: .env("PAGER", "bat") tests/integration_tests.rs:575:fn env_var_bat_pager_value_bat() { tests/integration_tests.rs:576: bat() tests/integration_tests.rs:577: .env("BAT_PAGER", "bat") tests/integration_tests.rs:582: .stderr(predicate::str::contains("bat as a pager is disallowed")); tests/integration_tests.rs:586:fn pager_value_bat() { tests/integration_tests.rs:587: bat() tests/integration_tests.rs:588: .arg("--pager=bat") tests/integration_tests.rs:593: .stderr(predicate::str::contains("bat as a pager is disallowed")); tests/integration_tests.rs:603: bat() tests/integration_tests.rs:613:/// If the bat-specific BAT_PAGER is used, obey the wish of the user tests/integration_tests.rs:617:fn pager_most_from_bat_pager_env_var() { tests/integration_tests.rs:619: bat() tests/integration_tests.rs:620: .env("BAT_PAGER", mocked_pagers::from("most")) tests/integration_tests.rs:629:/// Same reasoning with --pager as with BAT_PAGER tests/integration_tests.rs:634: bat() tests/integration_tests.rs:649: bat() tests/integration_tests.rs:664: bat() tests/integration_tests.rs:676: bat() tests/integration_tests.rs:687: bat() tests/integration_tests.rs:699: bat() tests/integration_tests.rs:700: .env("BAT_PAGER", "mismatched-quotes 'a") tests/integration_tests.rs:710: bat() tests/integration_tests.rs:714: .stdout(predicate::str::contains("BAT_PAGER=")) tests/integration_tests.rs:720: bat_with_config() tests/integration_tests.rs:721: .env("BAT_CONFIG_PATH", "bat.conf") tests/integration_tests.rs:725: .stdout("bat.conf\n"); tests/integration_tests.rs:727: bat_with_config() tests/integration_tests.rs:728: .env("BAT_CONFIG_PATH", "not-existing.conf") tests/integration_tests.rs:740: // Create the file with bat tests/integration_tests.rs:741: bat_with_config() tests/integration_tests.rs:742: .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) tests/integration_tests.rs:756:fn config_location_from_bat_config_dir_variable() { tests/integration_tests.rs:757: bat_with_config() tests/integration_tests.rs:758: .env("BAT_CONFIG_DIR", "conf/") tests/integration_tests.rs:767: bat_with_config() tests/integration_tests.rs:768: .env("BAT_CONFIG_PATH", "bat.conf") tests/integration_tests.rs:778: bat() tests/integration_tests.rs:789: bat_with_config() tests/integration_tests.rs:799: bat_with_config() tests/integration_tests.rs:810: bat_with_config() tests/integration_tests.rs:820: bat_with_config().arg("cach").assert().failure(); tests/integration_tests.rs:827: bat() tests/integration_tests.rs:836: bat_with_config() tests/integration_tests.rs:878: bat() tests/integration_tests.rs:898: bat() tests/integration_tests.rs:910: bat() tests/integration_tests.rs:922: bat() tests/integration_tests.rs:936: bat() tests/integration_tests.rs:950: bat() tests/integration_tests.rs:966: bat_with_config() tests/integration_tests.rs:979: bat() tests/integration_tests.rs:995: bat() tests/integration_tests.rs:1008: bat() tests/integration_tests.rs:1020: bat() tests/integration_tests.rs:1040: bat() tests/integration_tests.rs:1057: .stderr("\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n"); tests/integration_tests.rs:1077: bat() tests/integration_tests.rs:1093: bat() tests/integration_tests.rs:1105: let cmd_for_file = bat() tests/integration_tests.rs:1114: let cmd_for_stdin = bat() tests/integration_tests.rs:1134: bat() tests/integration_tests.rs:1147: bat() tests/integration_tests.rs:1157: bat() tests/integration_tests.rs:1169: bat() tests/integration_tests.rs:1181: bat() tests/integration_tests.rs:1193: bat() tests/integration_tests.rs:1204:// Regression test for https://github.com/sharkdp/bat/issues/299 tests/integration_tests.rs:1207: bat() tests/integration_tests.rs:1231: bat() tests/integration_tests.rs:1240: bat() tests/integration_tests.rs:1250: bat() tests/examples/regression_tests/issue_985.js:3:# bat --map-syntax '*.js:Markdown' --file-name 'issue_985.js' < issue_985.js tests/examples/regression_tests/issue_985.js:4:# bat --map-syntax '*.js:Markdown' --file-name 'issue_985.js' issue_985.js tests/utils/mocked_pagers.rs:16:/// On Windows: 'most' -> 'most.bat' tests/utils/mocked_pagers.rs:19: format!("{}.bat", base) tests/benchmarks/benchmark-results/syntax-highlighting-speed-miniz.c.md:3:| `bat … miniz.c` | 96.2 ± 1.9 | 92.6 | 99.6 | 1.00 | tests/benchmarks/benchmark-results/syntax-highlighting-speed-jquery.js.md:3:| `bat … jquery.js` | 692.4 ± 5.6 | 684.2 | 701.8 | 1.00 | tests/benchmarks/benchmark-results/syntax-highlighting-speed-test_multiarray.py.json:4: "command": "bat … test_multiarray.py", tests/benchmarks/benchmark-results/syntax-highlighting-speed-jquery.js.json:4: "command": "bat … jquery.js", tests/benchmarks/benchmark-results/plain-text-speed.json:4: "command": "bat … --language=txt test_multiarray.py", tests/benchmarks/benchmark-results/syntax-highlighting-speed-test_multiarray.ansi-sequences.txt.md:3:| `bat … test_multiarray.ansi-sequences.txt` | 125.3 ± 5.6 | 119.3 | 140.4 | 1.00 | tests/benchmarks/benchmark-results/syntax-highlighting-speed-test_multiarray.py.md:3:| `bat … test_multiarray.py` | 924.7 ± 4.4 | 917.1 | 932.3 | 1.00 | tests/benchmarks/benchmark-results/report.md:1:## `bat` benchmark results tests/benchmarks/benchmark-results/report.md:7:| `bat` | 6.9 ± 0.6 | 5.6 | 9.2 | 1.00 | tests/benchmarks/benchmark-results/report.md:13:| `bat … --language=txt test_multiarray.py` | 10.4 ± 0.6 | 9.0 | 12.1 | 1.00 | tests/benchmarks/benchmark-results/report.md:19:| `bat … jquery.js` | 692.4 ± 5.6 | 684.2 | 701.8 | 1.00 | tests/benchmarks/benchmark-results/report.md:25:| `bat … miniz.c` | 96.2 ± 1.9 | 92.6 | 99.6 | 1.00 | tests/benchmarks/benchmark-results/report.md:31:| `bat … test_multiarray.ansi-sequences.txt` | 125.3 ± 5.6 | 119.3 | 140.4 | 1.00 | tests/benchmarks/benchmark-results/report.md:37:| `bat … test_multiarray.py` | 924.7 ± 4.4 | 917.1 | 932.3 | 1.00 | tests/benchmarks/benchmark-results/startup-time.md:3:| `bat` | 6.9 ± 0.6 | 5.6 | 9.2 | 1.00 | tests/benchmarks/benchmark-results/syntax-highlighting-speed-miniz.c.json:4: "command": "bat … miniz.c", tests/benchmarks/benchmark-results/plain-text-speed.md:3:| `bat … --language=txt test_multiarray.py` | 10.4 ± 0.6 | 9.0 | 12.1 | 1.00 | tests/benchmarks/benchmark-results/syntax-highlighting-speed-jquery-3.3.1.js.json:4: "command": "/home/shark/.cargo-target/release/bat --style=full --color=always --paging=never test-src/jquery-3.3.1.js", tests/benchmarks/benchmark-results/syntax-highlighting-speed-test_multiarray.highlighted.txt.json:4: "command": "bat … test_multiarray.highlighted.txt", tests/benchmarks/benchmark-results/syntax-highlighting-speed-test_multiarray.ansi-sequences.txt.json:4: "command": "bat … test_multiarray.ansi-sequences.txt", tests/benchmarks/benchmark-results/syntax-highlighting-speed-jquery-3.3.1.min.js.json:4: "command": "/home/shark/.cargo-target/release/bat --style=full --color=always --paging=never test-src/jquery-3.3.1.min.js", tests/benchmarks/benchmark-results/ansi-sequence-forwarding.json:4: "command": "bat … test_multiarray.highlighted.txt", tests/benchmarks/benchmark-results/startup-time.json:4: "command": "bat", tests/benchmarks/run-benchmarks.sh:33:unset BAT_CACHE_PATH tests/benchmarks/run-benchmarks.sh:34:unset BAT_CONFIG_DIR tests/benchmarks/run-benchmarks.sh:35:unset BAT_CONFIG_PATH tests/benchmarks/run-benchmarks.sh:36:unset BAT_OPTS tests/benchmarks/run-benchmarks.sh:37:unset BAT_PAGER tests/benchmarks/run-benchmarks.sh:38:unset BAT_STYLE tests/benchmarks/run-benchmarks.sh:39:unset BAT_TABS tests/benchmarks/run-benchmarks.sh:40:unset BAT_THEME tests/benchmarks/run-benchmarks.sh:50:TARGET_RELEASE="${TARGET_DIR}/release/bat" tests/benchmarks/run-benchmarks.sh:55:BAT='' tests/benchmarks/run-benchmarks.sh:58: --system) BAT="bat" ;; tests/benchmarks/run-benchmarks.sh:59: --release) BAT="$TARGET_RELEASE" ;; tests/benchmarks/run-benchmarks.sh:60: --bat=*) BAT="${arg:6}" ;; tests/benchmarks/run-benchmarks.sh:64:if [[ -z "$BAT" ]]; then tests/benchmarks/run-benchmarks.sh:65: echo "A build of 'bat' must be specified for benchmarking." tests/benchmarks/run-benchmarks.sh:66: echo "You can use '--system', '--release' or '--bat=path/to/bat'." tests/benchmarks/run-benchmarks.sh:70:if ! command -v "$BAT" &>/dev/null; then tests/benchmarks/run-benchmarks.sh:71: echo "Could not find the build of bat to benchmark ($BAT)." tests/benchmarks/run-benchmarks.sh:72: case "$BAT" in tests/benchmarks/run-benchmarks.sh:73: "bat") echo "Make you sure to symlink 'batcat' as 'bat'." ;; tests/benchmarks/run-benchmarks.sh:83:echo "## \`bat\` benchmark results" >> "$REPORT" tests/benchmarks/run-benchmarks.sh:88: "$(printf "%q" "$BAT") --no-config" \ tests/benchmarks/run-benchmarks.sh:89: --command-name "bat" \ tests/benchmarks/run-benchmarks.sh:98: "$(printf "%q" "$BAT") --no-config --language=txt --style=plain test-src/test_multiarray.py" \ tests/benchmarks/run-benchmarks.sh:99: --command-name 'bat … --language=txt test_multiarray.py' \ tests/benchmarks/run-benchmarks.sh:111: "$(printf "%q" "$BAT") --no-config --style=full --color=always '$SRC'" \ tests/benchmarks/run-benchmarks.sh:112: --command-name "bat … ${filename}" \ tests/snapshots/generate_snapshots.py:35:def build_bat(): tests/snapshots/generate_snapshots.py:36: print("building bat") tests/snapshots/generate_snapshots.py:55:build_bat() tests/syntax-tests/create_highlighted_versions.py:11:BAT_OPTIONS = [ tests/syntax-tests/create_highlighted_versions.py:23: "bat_options", tests/syntax-tests/create_highlighted_versions.py:28: options = BAT_OPTIONS.copy() tests/syntax-tests/create_highlighted_versions.py:31: options_file = path.join(source_dirpath, "bat_options") tests/syntax-tests/create_highlighted_versions.py:44: env.pop("BAT_CACHE_PATH", None) tests/syntax-tests/create_highlighted_versions.py:45: env.pop("BAT_CONFIG_DIR", None) tests/syntax-tests/create_highlighted_versions.py:46: env.pop("BAT_CONFIG_PATH", None) tests/syntax-tests/create_highlighted_versions.py:47: env.pop("BAT_OPTS", None) tests/syntax-tests/create_highlighted_versions.py:48: env.pop("BAT_PAGER", None) tests/syntax-tests/create_highlighted_versions.py:49: env.pop("BAT_STYLE", None) tests/syntax-tests/create_highlighted_versions.py:50: env.pop("BAT_TABS", None) tests/syntax-tests/create_highlighted_versions.py:51: env.pop("BAT_THEME", None) tests/syntax-tests/create_highlighted_versions.py:62: bat_output = subprocess.check_output( tests/syntax-tests/create_highlighted_versions.py:63: ["bat"] + get_options(source) + [source], tests/syntax-tests/create_highlighted_versions.py:74: output_file.write(bat_output) tests/syntax-tests/create_highlighted_versions.py:98: "=== bat stdout:\n{}".format(err.stdout.decode("utf-8")), tests/syntax-tests/create_highlighted_versions.py:102: "=== bat stderr:\n{}".format(err.stderr.decode("utf-8")), tests/syntax-tests/create_highlighted_versions.py:108: "Error: Could not execute 'bat'. Please make sure that the executable " tests/syntax-tests/BatTestCustomAssets.sublime-syntax:4:name: BatTestCustomAssets tests/syntax-tests/BatTestCustomAssets.sublime-syntax:6: - battestcustomassets tests/syntax-tests/BatTestCustomAssets.sublime-syntax:7:scope: source.battestcustomassets tests/syntax-tests/BatTestCustomAssets.sublime-syntax:9:# This syntax is used to test if custom assets work with bat. tests/syntax-tests/BatTestCustomAssets.sublime-syntax:20: 1: keyword.other.battestcustomassets-key tests/syntax-tests/BatTestCustomAssets.sublime-syntax:21: 2: string.other.battestcustomassets-value tests/syntax-tests/highlighted/C/test.c:21: /* This C program was written to help bat tests/syntax-tests/highlighted/QML/BatSyntaxTest.qml:19: service: "org.bat.service" tests/syntax-tests/highlighted/QML/BatSyntaxTest.qml:41: text: qsTr("Install Bat.") tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:16: ## `bat` as a library tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:17:diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:19:--- a/src/bin/bat/app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:20:+++ b/src/bin/bat/app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:23: use bat::{ tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:61:diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:63:--- a/src/bin/bat/clap_app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:64:+++ b/src/bin/bat/clap_app.rs tests/syntax-tests/highlighted/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:66: data to bat from STDIN when bat does not otherwise know \ tests/syntax-tests/highlighted/Git Attributes/example.gitattributes:10:*.bat text eol=crlf tests/syntax-tests/highlighted/SSH Config/ssh_config:8: BatchMode no tests/syntax-tests/highlighted/Manpage/bat-0.16.man:1:BAT(1) General Commands Manual BAT(1) tests/syntax-tests/highlighted/Manpage/bat-0.16.man:4: bat - a cat(1) clone with syntax highlighting and Git integration. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:7: bat [OPTIONS] [FILE]... tests/syntax-tests/highlighted/Manpage/bat-0.16.man:9: bat cache [CACHE-OPTIONS] [--build|--clear] tests/syntax-tests/highlighted/Manpage/bat-0.16.man:12: bat prints the syntax-highlighted content of a collection of FILEs to tests/syntax-tests/highlighted/Manpage/bat-0.16.man:16: bat supports a large number of programming and markup languages. It tests/syntax-tests/highlighted/Manpage/bat-0.16.man:18: git index. bat automatically pipes its output through a pager (by de‐ tests/syntax-tests/highlighted/Manpage/bat-0.16.man:21: Whenever the output of bat goes to a non-interactive terminal, i.e. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:22: when the output is piped into another process or into a file, bat will tests/syntax-tests/highlighted/Manpage/bat-0.16.man:112: if the output of bat is piped to another program, but you want tests/syntax-tests/highlighted/Manpage/bat-0.16.man:119: set BAT_PAGER to an empty string. To control which pager is tests/syntax-tests/highlighted/Manpage/bat-0.16.man:126: PAGER and BAT_PAGER environment variables. The default pager is tests/syntax-tests/highlighted/Manpage/bat-0.16.man:143: BAT_THEME environment variable (e.g.: export BAT_THEME="..."). tests/syntax-tests/highlighted/Manpage/bat-0.16.man:156: to the configuration file or export the BAT_STYLE environment tests/syntax-tests/highlighted/Manpage/bat-0.16.man:157: variable (e.g.: export BAT_STYLE=".."). Possible values: *auto*, tests/syntax-tests/highlighted/Manpage/bat-0.16.man:202: bat can also be customized with a configuration file. The location of tests/syntax-tests/highlighted/Manpage/bat-0.16.man:206: bat --config-file tests/syntax-tests/highlighted/Manpage/bat-0.16.man:208: Alternatively, you can use the BAT_CONFIG_PATH environment variable to tests/syntax-tests/highlighted/Manpage/bat-0.16.man:209: point bat to a non-default location of the configuration file. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:212: bat supports Sublime Text .sublime-syntax language files, and can be tests/syntax-tests/highlighted/Manpage/bat-0.16.man:214: do this, add the .sublime-snytax language files to `$(bat --config- tests/syntax-tests/highlighted/Manpage/bat-0.16.man:215: dir)/syntaxes` and run `bat cache --build`. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:219: mkdir -p "$(bat --config-dir)/syntaxes" tests/syntax-tests/highlighted/Manpage/bat-0.16.man:220: cd "$(bat --config-dir)/syntaxes" tests/syntax-tests/highlighted/Manpage/bat-0.16.man:227: bat cache --build tests/syntax-tests/highlighted/Manpage/bat-0.16.man:229: Once the cache is built, the new language will be visible in `bat tests/syntax-tests/highlighted/Manpage/bat-0.16.man:232: cache with `bat cache --clear`. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:235: Similarly to custom languages, bat supports Sublime Text .tmTheme tests/syntax-tests/highlighted/Manpage/bat-0.16.man:236: themes. These can be installed to `$(bat --config-dir)/themes`, and tests/syntax-tests/highlighted/Manpage/bat-0.16.man:237: are added to the cache with `bat cache --build`. tests/syntax-tests/highlighted/Manpage/bat-0.16.man:240: For more information and up-to-date documentation, visit the bat repo: tests/syntax-tests/highlighted/Manpage/bat-0.16.man:241: https://github.com/sharkdp/bat tests/syntax-tests/highlighted/Manpage/bat-0.16.man:243: BAT(1) tests/syntax-tests/highlighted/Svelte/App.svelte:30: // This block is a regression test for a bat panic when a LiveScript syntax definition is missing tests/syntax-tests/highlighted/VimL/source.vim:77:" Error case from issue #1604 (https://github.com/sharkdp/bat/issues/1064) tests/syntax-tests/highlighted/Java/test.java:3:/* This Java program was submitted to help bat tests/syntax-tests/highlighted/Sass/example.sass:46: background-image: url("https://github.com/sharkdp/bat/raw/master/doc/logo-header.svg") tests/syntax-tests/highlighted/HTML/test.html:5: <title>Bat Syntax Test tests/syntax-tests/highlighted/Cpp/test.cpp:6:/* This C program was submitted to help bat tests/syntax-tests/highlighted/Crystal/test.cr:1:# An example file to test Crystal syntax highlighting in bat tests/syntax-tests/highlighted/Crystal/test.cr:58:greeter = Greeter.new("bat") tests/syntax-tests/highlighted/GLSL/test.glsl:38: // This GLSL code serves the purpose of bat syntax highlighting tests tests/syntax-tests/highlighted/CMake/CMakeLists.txt:3:project(hello-bat VERSION 0.0.1 LANGUAGES C) tests/syntax-tests/highlighted/CMake/CMakeLists.txt:8:add_executable(hello-bat SOURCES) tests/syntax-tests/highlighted/CMake/CMakeLists.txt:11:target_link_libraries(hello-bat assimp) tests/syntax-tests/highlighted/SCSS/example.scss:48: background-image: url("https://github.com/sharkdp/bat/raw/master/doc/logo-header.svg"); tests/syntax-tests/highlighted/TOML/Cargo.toml:5:homepage = "https://github.com/sharkdp/bat" tests/syntax-tests/highlighted/TOML/Cargo.toml:7:name = "bat" tests/syntax-tests/highlighted/TOML/Cargo.toml:9:repository = "https://github.com/sharkdp/bat" tests/syntax-tests/highlighted/TOML/Cargo.toml:20:# Feature required for bat the application. Should be disabled when depending on tests/syntax-tests/highlighted/TOML/Cargo.toml:21:# bat as a library. tests/syntax-tests/highlighted/Erlang/bat_erlang.erl:1:-module(bat_erlang). tests/syntax-tests/highlighted/Bash/batgrep.sh:3:# bat-extras | Copyright (C) 2020 eth-p and contributors | MIT License tests/syntax-tests/highlighted/Bash/batgrep.sh:5:# Repository: https://github.com/eth-p/bat-extras tests/syntax-tests/highlighted/Bash/batgrep.sh:6:# Issues: https://github.com/eth-p/bat-extras/issues tests/syntax-tests/highlighted/Bash/batgrep.sh:37:printc "%{YELLOW}[%s warning]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 tests/syntax-tests/highlighted/Bash/batgrep.sh:40:printc "%{RED}[%s error]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 tests/syntax-tests/highlighted/Bash/batgrep.sh:116:if [[ -n ${BAT_PAGER+x} ]];then tests/syntax-tests/highlighted/Bash/batgrep.sh:117:SCRIPT_PAGER_CMD=($BAT_PAGER) tests/syntax-tests/highlighted/Bash/batgrep.sh:169:printc "%{RED}%s: '%s' requires a value%{CLEAR}\n" "batgrep" "$ARG" tests/syntax-tests/highlighted/Bash/batgrep.sh:185:*)printc "%{RED}%s: '--color' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" tests/syntax-tests/highlighted/Bash/batgrep.sh:217:*)printc "%{RED}%s: '--paging' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" tests/syntax-tests/highlighted/Bash/batgrep.sh:238:"batgrep" \ tests/syntax-tests/highlighted/Bash/batgrep.sh:241:"https://github.com/eth-p/bat-extras" tests/syntax-tests/highlighted/Bash/batgrep.sh:269:bat_version(){ tests/syntax-tests/highlighted/Bash/batgrep.sh:270:"bat" --version|cut -d ' ' -f 2 tests/syntax-tests/highlighted/Bash/batgrep.sh:319:BAT_ARGS=() tests/syntax-tests/highlighted/Bash/batgrep.sh:330:BAT_STYLE="header,numbers" tests/syntax-tests/highlighted/Bash/batgrep.sh:331:if version_compare "$(bat_version)" -gt "0.12";then tests/syntax-tests/highlighted/Bash/batgrep.sh:419:printc "%{RED}%s: unknown option '%s'%{CLEAR}\n" "batgrep" "$OPT" 1>&2 tests/syntax-tests/highlighted/Bash/batgrep.sh:444:BAT_ARGS+=("--color=always") tests/syntax-tests/highlighted/Bash/batgrep.sh:446:BAT_ARGS+=("--color=never") tests/syntax-tests/highlighted/Bash/batgrep.sh:462:'the pager was explicitly disabled by $BAT_PAGER or the' \ tests/syntax-tests/highlighted/Bash/batgrep.sh:482:"bat" "${BAT_ARGS[@]}" \ tests/syntax-tests/highlighted/Bash/batgrep.sh:485:--style="$BAT_STYLE$OPT_SNIP" \ tests/syntax-tests/highlighted/Bash/simple.sh:15: | cat | bat - | cat tests/syntax-tests/highlighted/Bash/simple.sh:20:if command -v bat &> /dev/null; then tests/syntax-tests/highlighted/Rust/output.rs:39: let pager_from_env = match (env::var("BAT_PAGER"), env::var("PAGER")) { tests/syntax-tests/highlighted/Rust/output.rs:40: (Ok(bat_pager), _) => Some(bat_pager), tests/syntax-tests/highlighted/Rust/output.rs:43: // ANSI color sequences printed by bat. If someone has set PAGER="less -F", we tests/syntax-tests/highlighted/Rust/output.rs:46: // We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER tests/syntax-tests/highlighted/Rust/output.rs:47: // or bats '--pager' command line option. tests/syntax-tests/highlighted/Rust/output.rs:71: if pager_path.file_stem() == Some(&OsString::from("bat")) { tests/syntax-tests/source/C/test.c:21: /* This C program was written to help bat tests/syntax-tests/source/QML/BatSyntaxTest.qml:19: service: "org.bat.service" tests/syntax-tests/source/QML/BatSyntaxTest.qml:41: text: qsTr("Install Bat.") tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:16: ## `bat` as a library tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:17:diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:19:--- a/src/bin/bat/app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:20:+++ b/src/bin/bat/app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:23: use bat::{ tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:61:diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:63:--- a/src/bin/bat/clap_app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:64:+++ b/src/bin/bat/clap_app.rs tests/syntax-tests/source/Diff/82e7786e747b1fcfac1f963ae6415a22ec9caae1.diff:66: data to bat from STDIN when bat does not otherwise know \ tests/syntax-tests/source/Git Attributes/example.gitattributes:10:*.bat text eol=crlf tests/syntax-tests/source/SSH Config/ssh_config:8: BatchMode no tests/syntax-tests/source/Manpage/bat-0.16.man:1:BAT(1) General Commands Manual BAT(1) tests/syntax-tests/source/Manpage/bat-0.16.man:4: bat - a cat(1) clone with syntax highlighting and Git integration. tests/syntax-tests/source/Manpage/bat-0.16.man:7: bat [OPTIONS] [FILE]... tests/syntax-tests/source/Manpage/bat-0.16.man:9: bat cache [CACHE-OPTIONS] [--build|--clear] tests/syntax-tests/source/Manpage/bat-0.16.man:12: bat prints the syntax-highlighted content of a collection of FILEs to tests/syntax-tests/source/Manpage/bat-0.16.man:16: bat supports a large number of programming and markup languages. It tests/syntax-tests/source/Manpage/bat-0.16.man:18: git index. bat automatically pipes its output through a pager (by de‐ tests/syntax-tests/source/Manpage/bat-0.16.man:21: Whenever the output of bat goes to a non-interactive terminal, i.e. tests/syntax-tests/source/Manpage/bat-0.16.man:22: when the output is piped into another process or into a file, bat will tests/syntax-tests/source/Manpage/bat-0.16.man:112: if the output of bat is piped to another program, but you want tests/syntax-tests/source/Manpage/bat-0.16.man:119: set BAT_PAGER to an empty string. To control which pager is tests/syntax-tests/source/Manpage/bat-0.16.man:126: PAGER and BAT_PAGER environment variables. The default pager is tests/syntax-tests/source/Manpage/bat-0.16.man:143: BAT_THEME environment variable (e.g.: export BAT_THEME="..."). tests/syntax-tests/source/Manpage/bat-0.16.man:156: to the configuration file or export the BAT_STYLE environment tests/syntax-tests/source/Manpage/bat-0.16.man:157: variable (e.g.: export BAT_STYLE=".."). Possible values: *auto*, tests/syntax-tests/source/Manpage/bat-0.16.man:202: bat can also be customized with a configuration file. The location of tests/syntax-tests/source/Manpage/bat-0.16.man:206: bat --config-file tests/syntax-tests/source/Manpage/bat-0.16.man:208: Alternatively, you can use the BAT_CONFIG_PATH environment variable to tests/syntax-tests/source/Manpage/bat-0.16.man:209: point bat to a non-default location of the configuration file. tests/syntax-tests/source/Manpage/bat-0.16.man:212: bat supports Sublime Text .sublime-syntax language files, and can be tests/syntax-tests/source/Manpage/bat-0.16.man:214: do this, add the .sublime-snytax language files to `$(bat --config- tests/syntax-tests/source/Manpage/bat-0.16.man:215: dir)/syntaxes` and run `bat cache --build`. tests/syntax-tests/source/Manpage/bat-0.16.man:219: mkdir -p "$(bat --config-dir)/syntaxes" tests/syntax-tests/source/Manpage/bat-0.16.man:220: cd "$(bat --config-dir)/syntaxes" tests/syntax-tests/source/Manpage/bat-0.16.man:227: bat cache --build tests/syntax-tests/source/Manpage/bat-0.16.man:229: Once the cache is built, the new language will be visible in `bat tests/syntax-tests/source/Manpage/bat-0.16.man:232: cache with `bat cache --clear`. tests/syntax-tests/source/Manpage/bat-0.16.man:235: Similarly to custom languages, bat supports Sublime Text .tmTheme tests/syntax-tests/source/Manpage/bat-0.16.man:236: themes. These can be installed to `$(bat --config-dir)/themes`, and tests/syntax-tests/source/Manpage/bat-0.16.man:237: are added to the cache with `bat cache --build`. tests/syntax-tests/source/Manpage/bat-0.16.man:240: For more information and up-to-date documentation, visit the bat repo: tests/syntax-tests/source/Manpage/bat-0.16.man:241: https://github.com/sharkdp/bat tests/syntax-tests/source/Manpage/bat-0.16.man:243: BAT(1) tests/syntax-tests/source/Svelte/App.svelte:30: // This block is a regression test for a bat panic when a LiveScript syntax definition is missing tests/syntax-tests/source/VimL/source.vim:77:" Error case from issue #1604 (https://github.com/sharkdp/bat/issues/1064) tests/syntax-tests/source/Git Config/LICENSE.md:1:The `test.gitconfig` file has been added from https://github.com/sharkdp/bat/pull/1336#issuecomment-715905807. Its "free to use". tests/syntax-tests/source/Java/test.java:3:/* This Java program was submitted to help bat tests/syntax-tests/source/Sass/example.sass:46: background-image: url("https://github.com/sharkdp/bat/raw/master/doc/logo-header.svg") tests/syntax-tests/source/HTML/test.html:5: Bat Syntax Test tests/syntax-tests/source/Cpp/test.cpp:6:/* This C program was submitted to help bat tests/syntax-tests/source/Crystal/test.cr:1:# An example file to test Crystal syntax highlighting in bat tests/syntax-tests/source/Crystal/test.cr:58:greeter = Greeter.new("bat") tests/syntax-tests/source/GLSL/test.glsl:38: // This GLSL code serves the purpose of bat syntax highlighting tests tests/syntax-tests/source/Java Server Page (JSP)/LICENSE.md:216:For the Eclipse JDT Core Batch Compiler (ecj-x.x.x.jar) component and the tests/syntax-tests/source/Java Server Page (JSP)/NOTICE:23:JDT Core Batch Compiler component, which is open source software. tests/syntax-tests/source/CMake/CMakeLists.txt:3:project(hello-bat VERSION 0.0.1 LANGUAGES C) tests/syntax-tests/source/CMake/CMakeLists.txt:8:add_executable(hello-bat SOURCES) tests/syntax-tests/source/CMake/CMakeLists.txt:11:target_link_libraries(hello-bat assimp) tests/syntax-tests/source/SCSS/example.scss:48: background-image: url("https://github.com/sharkdp/bat/raw/master/doc/logo-header.svg"); tests/syntax-tests/source/TOML/Cargo.toml:5:homepage = "https://github.com/sharkdp/bat" tests/syntax-tests/source/TOML/Cargo.toml:7:name = "bat" tests/syntax-tests/source/TOML/Cargo.toml:9:repository = "https://github.com/sharkdp/bat" tests/syntax-tests/source/TOML/Cargo.toml:20:# Feature required for bat the application. Should be disabled when depending on tests/syntax-tests/source/TOML/Cargo.toml:21:# bat as a library. tests/syntax-tests/source/Erlang/bat_erlang.erl:1:-module(bat_erlang). tests/syntax-tests/source/Batch/LICENSE.md:1:The `build.bat` file has been added from https://github.com/Leandros/ClangOnWindows/blob/master/build.bat under the following license: tests/syntax-tests/source/Bash/batgrep.sh:3:# bat-extras | Copyright (C) 2020 eth-p and contributors | MIT License tests/syntax-tests/source/Bash/batgrep.sh:5:# Repository: https://github.com/eth-p/bat-extras tests/syntax-tests/source/Bash/batgrep.sh:6:# Issues: https://github.com/eth-p/bat-extras/issues tests/syntax-tests/source/Bash/batgrep.sh:37:printc "%{YELLOW}[%s warning]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 tests/syntax-tests/source/Bash/batgrep.sh:40:printc "%{RED}[%s error]%{CLEAR}: $1%{CLEAR}\n" "batgrep" "${@:2}" 1>&2 tests/syntax-tests/source/Bash/batgrep.sh:116:if [[ -n ${BAT_PAGER+x} ]];then tests/syntax-tests/source/Bash/batgrep.sh:117:SCRIPT_PAGER_CMD=($BAT_PAGER) tests/syntax-tests/source/Bash/batgrep.sh:169:printc "%{RED}%s: '%s' requires a value%{CLEAR}\n" "batgrep" "$ARG" tests/syntax-tests/source/Bash/batgrep.sh:185:*)printc "%{RED}%s: '--color' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" tests/syntax-tests/source/Bash/batgrep.sh:217:*)printc "%{RED}%s: '--paging' expects value of 'auto', 'always', or 'never'%{CLEAR}\n" "batgrep" tests/syntax-tests/source/Bash/batgrep.sh:238:"batgrep" \ tests/syntax-tests/source/Bash/batgrep.sh:241:"https://github.com/eth-p/bat-extras" tests/syntax-tests/source/Bash/batgrep.sh:269:bat_version(){ tests/syntax-tests/source/Bash/batgrep.sh:270:"bat" --version|cut -d ' ' -f 2 tests/syntax-tests/source/Bash/batgrep.sh:319:BAT_ARGS=() tests/syntax-tests/source/Bash/batgrep.sh:330:BAT_STYLE="header,numbers" tests/syntax-tests/source/Bash/batgrep.sh:331:if version_compare "$(bat_version)" -gt "0.12";then tests/syntax-tests/source/Bash/batgrep.sh:419:printc "%{RED}%s: unknown option '%s'%{CLEAR}\n" "batgrep" "$OPT" 1>&2 tests/syntax-tests/source/Bash/batgrep.sh:444:BAT_ARGS+=("--color=always") tests/syntax-tests/source/Bash/batgrep.sh:446:BAT_ARGS+=("--color=never") tests/syntax-tests/source/Bash/batgrep.sh:462:'the pager was explicitly disabled by $BAT_PAGER or the' \ tests/syntax-tests/source/Bash/batgrep.sh:482:"bat" "${BAT_ARGS[@]}" \ tests/syntax-tests/source/Bash/batgrep.sh:485:--style="$BAT_STYLE$OPT_SNIP" \ tests/syntax-tests/source/Bash/simple.sh:15: | cat | bat - | cat tests/syntax-tests/source/Bash/simple.sh:20:if command -v bat &> /dev/null; then tests/syntax-tests/source/Rust/output.rs:39: let pager_from_env = match (env::var("BAT_PAGER"), env::var("PAGER")) { tests/syntax-tests/source/Rust/output.rs:40: (Ok(bat_pager), _) => Some(bat_pager), tests/syntax-tests/source/Rust/output.rs:43: // ANSI color sequences printed by bat. If someone has set PAGER="less -F", we tests/syntax-tests/source/Rust/output.rs:46: // We only do this for PAGER (as it is not specific to 'bat'), not for BAT_PAGER tests/syntax-tests/source/Rust/output.rs:47: // or bats '--pager' command line option. tests/syntax-tests/source/Rust/output.rs:71: if pager_path.file_stem() == Some(&OsString::from("bat")) { tests/syntax-tests/test_custom_assets.sh:6:BAT_CONFIG_DIR=$(mktemp -d) tests/syntax-tests/test_custom_assets.sh:7:export BAT_CONFIG_DIR tests/syntax-tests/test_custom_assets.sh:9:BAT_CACHE_PATH=$(mktemp -d) tests/syntax-tests/test_custom_assets.sh:10:export BAT_CACHE_PATH tests/syntax-tests/test_custom_assets.sh:13:BAT_CONFIG_DIR = ${BAT_CONFIG_DIR} tests/syntax-tests/test_custom_assets.sh:14:BAT_CACHE_PATH = ${BAT_CACHE_PATH} tests/syntax-tests/test_custom_assets.sh:20: "--language=BatTestCustomAssets" tests/syntax-tests/test_custom_assets.sh:21: "tests/syntax-tests/source/BatTestCustomAssets/NoColorsUnlessCustomAssetsAreUsed.battestcustomassets" tests/syntax-tests/test_custom_assets.sh:42:echo_step "TEST: Make sure 'BatTestCustomAssets' is not part of integrated syntaxes" tests/syntax-tests/test_custom_assets.sh:43:bat -f "${custom_syntax_args[@]}" && tests/syntax-tests/test_custom_assets.sh:46:echo_step "PREPARE: Install custom syntax 'BatTestCustomAssets'" tests/syntax-tests/test_custom_assets.sh:47:custom_syntaxes_dir="$(bat --config-dir)/syntaxes" tests/syntax-tests/test_custom_assets.sh:49:cp -v "tests/syntax-tests/BatTestCustomAssets.sublime-syntax" \ tests/syntax-tests/test_custom_assets.sh:50: "${custom_syntaxes_dir}/BatTestCustomAssets.sublime-syntax" tests/syntax-tests/test_custom_assets.sh:52:echo_step "PREPARE: Build custom assets to enable 'BatTestCustomAssets' syntax" tests/syntax-tests/test_custom_assets.sh:53:bat cache --build tests/syntax-tests/test_custom_assets.sh:55:echo_step "TEST: 'BatTestCustomAssets' is a known syntax" tests/syntax-tests/test_custom_assets.sh:56:bat -f "${custom_syntax_args[@]}" || tests/syntax-tests/test_custom_assets.sh:60:bat -f "${integrated_syntax_args[@]}" || tests/syntax-tests/test_custom_assets.sh:63:echo_step "TEST: 'BatTestCustomAssets' is an unknown syntax with --no-custom-assets" tests/syntax-tests/test_custom_assets.sh:64:bat -f --no-custom-assets "${custom_syntax_args[@]}" && tests/syntax-tests/test_custom_assets.sh:67:echo_step "TEST: 'bat cache --clear' removes all files" tests/syntax-tests/test_custom_assets.sh:68:bat cache --clear tests/syntax-tests/test_custom_assets.sh:69:remaining_files=$(ls -A "${BAT_CACHE_PATH}") tests/syntax-tests/test_custom_assets.sh:74:rm -rv "${BAT_CONFIG_DIR}" "${BAT_CACHE_PATH}" tests/assets.rs:1:use bat::assets::HighlightingAssets; tests/no_duplicate_extensions.rs:3:use bat::assets::HighlightingAssets; tests/scripts/find-slow-to-highlight-files.py:3:# This script goes through all languages that are supported by 'bat'. For each tests/scripts/find-slow-to-highlight-files.py:5:# given folder for matching files. It calls 'bat' for each of these files and tests/scripts/find-slow-to-highlight-files.py:8:# execution of 'bat'. tests/scripts/find-slow-to-highlight-files.py:11:# - bat (in the $PATH) tests/scripts/find-slow-to-highlight-files.py:24:# Maximum time we allow `bat` to run tests/scripts/find-slow-to-highlight-files.py:25:BAT_TIMEOUT_SEC = 10 tests/scripts/find-slow-to-highlight-files.py:62: sp.check_output(["bat", "--color=always", path], timeout=BAT_TIMEOUT_SEC) tests/scripts/find-slow-to-highlight-files.py:77: if num_chars < THRESHOLD_SPEED * BAT_TIMEOUT_SEC: tests/scripts/find-slow-to-highlight-files.py:78: print(f" Error: bat timed out on file '{path.decode()}'.") tests/scripts/find-slow-to-highlight-files.py:81: f" Warning: bat timed out on file '{path.decode()} (but the file is large)." tests/scripts/find-slow-to-highlight-files.py:85:def measure_bat_startup_speed(): tests/scripts/find-slow-to-highlight-files.py:90: ["bat", "--color=always", "--language=py"], stdin=sp.PIPE, stdout=sp.PIPE tests/scripts/find-slow-to-highlight-files.py:102: output = sp.check_output(["bat", "--list-languages"]).decode() tests/scripts/find-slow-to-highlight-files.py:113: print("Measuring 'bat' startup speed ... ", flush=True, end="") tests/scripts/find-slow-to-highlight-files.py:114: startup_time = measure_bat_startup_speed() tests/tester.rs:13:pub struct BatTester { tests/tester.rs:17: /// Path to the *bat* executable tests/tester.rs:21:impl BatTester { tests/tester.rs:35: .expect("bat failed"); tests/tester.rs:52:impl Default for BatTester { tests/tester.rs:61: .expect("bat executable directory") tests/tester.rs:64: let exe_name = if cfg!(windows) { "bat.exe" } else { "bat" }; tests/tester.rs:67: BatTester { temp_dir, exe } tests/tester.rs:86: let signature = Signature::now("bat test runner", "bat@test.runner")?; tests/snapshot_tests.rs:3:use crate::tester::BatTester; tests/snapshot_tests.rs:10: let bat_tester = BatTester::default(); tests/snapshot_tests.rs:11: bat_tester.test_snapshot(stringify!($test_name), $style); diagnostics/info.sh:2:_modules=('system' 'bat' 'bat_config' 'bat_wrapper' 'bat_wrapper_function' 'tool') diagnostics/info.sh:10:BAT="bat" diagnostics/info.sh:11:if ! command -v bat &>/dev/null; then diagnostics/info.sh:12: if command -v batcat &> /dev/null; then diagnostics/info.sh:13: BAT="batcat" diagnostics/info.sh:17: "Unable to find a bat executable on your PATH." \ diagnostics/info.sh:18: "Please ensure that 'bat' exists and is not named something else." diagnostics/info.sh:28:_bat_:description() { diagnostics/info.sh:29: _collects "Version information for 'bat'." diagnostics/info.sh:30: _collects "Custom syntaxes and themes for 'bat'." diagnostics/info.sh:33:_bat_config_:description() { diagnostics/info.sh:34: _collects "The environment variables used by 'bat'." diagnostics/info.sh:35: _collects "The 'bat' configuration file." diagnostics/info.sh:38:_bat_wrapper_:description() { diagnostics/info.sh:39: _collects "Any wrapper script used by 'bat'." diagnostics/info.sh:42:_bat_wrapper_function_:description() { diagnostics/info.sh:43: _collects "The wrapper function surrounding 'bat' (if applicable)." diagnostics/info.sh:57:_bat_:run() { diagnostics/info.sh:58: _out "$BAT" --version diagnostics/info.sh:59: _out env | grep '^BAT_\|^PAGER=' diagnostics/info.sh:62: cache_dir="$($BAT --cache-dir)" diagnostics/info.sh:64: _print_command "$BAT" "--list-languages" diagnostics/info.sh:69: _print_command "$BAT" "--list-themes" diagnostics/info.sh:74:_bat_config_:run() { diagnostics/info.sh:75: if [[ -f "$("$BAT" --config-file)" ]]; then diagnostics/info.sh:76: _out_fence cat "$("$BAT" --config-file)" diagnostics/info.sh:80:_bat_wrapper_:run() { diagnostics/info.sh:81: _bat_wrapper_:detect_wrapper() { diagnostics/info.sh:82: local bat="$1" diagnostics/info.sh:83: if file "$(command -v "${bat}")" | grep "text executable" &> /dev/null; then diagnostics/info.sh:84: _out_fence cat "$(command -v "${bat}")" diagnostics/info.sh:88: printf "\nNo wrapper script for '%s'.\n" "${bat}" diagnostics/info.sh:91: _bat_wrapper_:detect_wrapper bat diagnostics/info.sh:92: if [[ "$BAT" != "bat" ]]; then diagnostics/info.sh:93: _bat_wrapper_:detect_wrapper "$BAT" diagnostics/info.sh:97:_bat_wrapper_function_:run() { diagnostics/info.sh:98: _bat_wrapper_function_:detect_wrapper() { diagnostics/info.sh:125: _bat_wrapper_function_:detect_wrapper bat diagnostics/info.sh:126: _bat_wrapper_function_:detect_wrapper cat diagnostics/info.sh:127: if [[ "$BAT" != "bat" ]]; then diagnostics/info.sh:128: _bat_wrapper_function_:detect_wrapper "$BAT" diagnostics/info.sh:180:system and bat configuration. It will give you a small preview of the commands diagnostics/info.sh:201: | sed "s/\"\$BAT\"/$BAT/" 1>&2 diagnostics/info.sh:228:# Tell the user if their executable isn't named "bat". diagnostics/info.sh:229:if [[ "$BAT" != "bat" ]] && [[ "$1" != '-y' ]]; then diagnostics/info.sh:235: printf "The %s executable on your system is named '%s'.\n%s\n" "bat" "$BAT" \ ================================================ FILE: tests/benchmarks/highlighting-speed-src/jquery.js ================================================ /*! * jQuery JavaScript Library v3.3.1 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2018-01-20T17:24Z */ ( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory and get jQuery. // For environments that do not have a `window` with a `document` // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common // enough that all such attempts are guarded in a try block. "use strict"; var arr = []; var document = window.document; var getProto = Object.getPrototypeOf; var slice = arr.slice; var concat = arr.concat; var push = arr.push; var indexOf = arr.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var fnToString = hasOwn.toString; var ObjectFunctionString = fnToString.call( Object ); var support = {}; var isFunction = function isFunction( obj ) { // Support: Chrome <=57, Firefox <=52 // In some browsers, typeof returns "function" for HTML elements // (i.e., `typeof document.createElement( "object" ) === "function"`). // We don't want to classify *any* DOM node as a function. return typeof obj === "function" && typeof obj.nodeType !== "number"; }; var isWindow = function isWindow( obj ) { return obj != null && obj === obj.window; }; var preservedScriptAttributes = { type: true, src: true, noModule: true }; function DOMEval( code, doc, node ) { doc = doc || document; var i, script = doc.createElement( "script" ); script.text = code; if ( node ) { for ( i in preservedScriptAttributes ) { if ( node[ i ] ) { script[ i ] = node[ i ]; } } } doc.head.appendChild( script ).parentNode.removeChild( script ); } function toType( obj ) { if ( obj == null ) { return obj + ""; } // Support: Android <=2.3 only (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call( obj ) ] || "object" : typeof obj; } /* global Symbol */ // Defining this global in .eslintrc.json would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module var version = "3.3.1", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, // Support: Android <=4.0 only // Make sure we trim BOM and NBSP rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, toArray: function() { return slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { // Return all the elements in a clean array if ( num == null ) { return slice.call( this ); } // Return just the one element from the set return num < 0 ? this[ num + this.length ] : this[ num ]; }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, map: function( callback ) { return this.pushStack( jQuery.map( this, function( elem, i ) { return callback.call( elem, i, elem ); } ) ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); }, end: function() { return this.prevObject || this.constructor(); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: arr.sort, splice: arr.splice }; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && Array.isArray( src ) ? src : []; } else { clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend( { // Unique for each copy of jQuery on the page expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), // Assume jQuery is ready without the ready module isReady: true, error: function( msg ) { throw new Error( msg ); }, noop: function() {}, isPlainObject: function( obj ) { var proto, Ctor; // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if ( !obj || toString.call( obj ) !== "[object Object]" ) { return false; } proto = getProto( obj ); // Objects with no prototype (e.g., `Object.create( null )`) are plain if ( !proto ) { return true; } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; }, isEmptyObject: function( obj ) { /* eslint-disable no-unused-vars */ // See https://github.com/eslint/eslint/issues/6125 var name; for ( name in obj ) { return false; } return true; }, // Evaluates a script in a global context globalEval: function( code ) { DOMEval( code ); }, each: function( obj, callback ) { var length, i = 0; if ( isArrayLike( obj ) ) { length = obj.length; for ( ; i < length; i++ ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } else { for ( i in obj ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } return obj; }, // Support: Android <=4.0 only trim: function( text ) { return text == null ? "" : ( text + "" ).replace( rtrim, "" ); }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { return arr == null ? -1 : indexOf.call( arr, elem, i ); }, // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; for ( ; j < len; j++ ) { first[ i++ ] = second[ j ]; } first.length = i; return first; }, grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { callbackInverse = !callback( elems[ i ], i ); if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, // arg is for internal usage only map: function( elems, callback, arg ) { var length, value, i = 0, ret = []; // Go through the array, translating each of the items to their new values if ( isArrayLike( elems ) ) { length = elems.length; for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // Flatten any nested arrays return concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support: support } ); if ( typeof Symbol === "function" ) { jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; } // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), function( i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); function isArrayLike( obj ) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE var length = !!obj && "length" in obj && obj.length, type = toType( obj ); if ( isFunction( obj ) || isWindow( obj ) ) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! * Sizzle CSS Selector Engine v2.3.3 * https://sizzlejs.com/ * * Copyright jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2016-08-08 */ (function( window ) { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // Instance methods hasOwn = ({}).hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { if ( list[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + identifier + ")" ), "CLASS": new RegExp( "^\\.(" + identifier + ")" ), "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), funescape = function( _, escaped, escapedWhitespace ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, fcssescape = function( ch, asCodePoint ) { if ( asCodePoint ) { // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER if ( ch === "\0" ) { return "\uFFFD"; } // Control characters and (dependent upon position) numbers get escaped as code points return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped return "\\" + ch; }, // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE unloadHandler = function() { setDocument(); }, disabledAncestor = addCombinator( function( elem ) { return elem.disabled === true && ("form" in elem || "label" in elem); }, { dir: "parentNode", next: "legend" } ); // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, // nodeType defaults to 9, since context defaults to document nodeType = context ? context.nodeType : 9; results = results || []; // Return early from calls with invalid selector or context if ( typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { return results; } // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; if ( documentIsHTML ) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // ID selector if ( (m = match[1]) ) { // Document context if ( nodeType === 9 ) { if ( (elem = context.getElementById( m )) ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } // Element context } else { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( newContext && (elem = newContext.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Type selector } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // Take advantage of querySelectorAll if ( support.qsa && !compilerCache[ selector + " " ] && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { if ( nodeType !== 1 ) { newContext = context; newSelector = selector; // qSA looks outside Element context, which is not what we want // Thanks to Andrew Dupont for this workaround technique // Support: IE <=8 // Exclude object elements } else if ( context.nodeName.toLowerCase() !== "object" ) { // Capture the context ID, setting it first if necessary if ( (nid = context.getAttribute( "id" )) ) { nid = nid.replace( rcssescape, fcssescape ); } else { context.setAttribute( "id", (nid = expando) ); } // Prefix every selector in the list groups = tokenize( selector ); i = groups.length; while ( i-- ) { groups[i] = "#" + nid + " " + toSelector( groups[i] ); } newSelector = groups.join( "," ); // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch ( qsaError ) { } finally { if ( nid === expando ) { context.removeAttribute( "id" ); } } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key + " " ] = value); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { var el = document.createElement("fieldset"); try { return !!fn( el ); } catch (e) { return false; } finally { // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } // release memory in IE el = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split("|"), i = arr.length; while ( i-- ) { Expr.attrHandle[ arr[i] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } /** * Returns a function to use in pseudos for :enabled/:disabled * @param {Boolean} disabled true for :disabled; false for :enabled */ function createDisabledPseudo( disabled ) { // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable return function( elem ) { // Only certain elements can match :enabled or :disabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled if ( "form" in elem ) { // Check for inherited disabledness on relevant non-disabled elements: // * listed form-associated elements in a disabled fieldset // https://html.spec.whatwg.org/multipage/forms.html#category-listed // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled // * option elements in a disabled optgroup // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled // All such elements have a "form" property. if ( elem.parentNode && elem.disabled === false ) { // Option elements defer to a parent optgroup if present if ( "label" in elem ) { if ( "label" in elem.parentNode ) { return elem.parentNode.disabled === disabled; } else { return elem.disabled === disabled; } } // Support: IE 6 - 11 // Use the isDisabled shortcut property to check for disabled fieldset ancestors return elem.isDisabled === disabled || // Where there is no isDisabled, check manually /* jshint -W018 */ elem.isDisabled !== !disabled && disabledAncestor( elem ) === disabled; } return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't // even exist on them, let alone have a boolean value. } else if ( "label" in elem ) { return elem.disabled === disabled; } // Remaining elements are neither :enabled nor :disabled return false; }; } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo( fn ) { return markFunction(function( argument ) { argument = +argument; return markFunction(function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ (j = matchIndexes[i]) ] ) { seed[j] = !(matches[j] = seed[j]); } } }); }); } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience support = Sizzle.support = {}; /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var hasCompare, subWindow, doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } // Update global variables document = doc; docElem = document.documentElement; documentIsHTML = !isXML( document ); // Support: IE 9-11, Edge // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) if ( preferredDoc !== document && (subWindow = document.defaultView) && subWindow.top !== subWindow ) { // Support: IE 11, Edge if ( subWindow.addEventListener ) { subWindow.addEventListener( "unload", unloadHandler, false ); // Support: IE 9 - 10 only } else if ( subWindow.attachEvent ) { subWindow.attachEvent( "onunload", unloadHandler ); } } /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) support.attributes = assert(function( el ) { el.className = "i"; return !el.getAttribute("className"); }); /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert(function( el ) { el.appendChild( document.createComment("") ); return !el.getElementsByTagName("*").length; }); // Support: IE<9 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programmatically-set names, // so use a roundabout getElementsByName test support.getById = assert(function( el ) { docElem.appendChild( el ).id = expando; return !document.getElementsByName || !document.getElementsByName( expando ).length; }); // ID filter and find if ( support.getById ) { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute("id") === attrId; }; }; Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var elem = context.getElementById( id ); return elem ? [ elem ] : []; } }; } else { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; // Support: IE 6 - 7 only // getElementById is not reliable as a find shortcut Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var node, i, elems, elem = context.getElementById( id ); if ( elem ) { // Verify the id attribute node = elem.getAttributeNode("id"); if ( node && node.value === id ) { return [ elem ]; } // Fall back on getElementsByName elems = context.getElementsByName( id ); i = 0; while ( (elem = elems[i++]) ) { node = elem.getAttributeNode("id"); if ( node && node.value === id ) { return [ elem ]; } } } return []; } }; } // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); // DocumentFragment nodes don't have gEBTN } else if ( support.qsa ) { return context.querySelectorAll( tag ); } } : function( tag, context ) { var elem, tmp = [], i = 0, // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { while ( (elem = results[i++]) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } } return tmp; } return results; }; // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { return context.getElementsByClassName( className ); } }; /* QSA/matchesSelector ---------------------------------------------------------------------- */ // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = []; if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { // Build QSA regex // Regex strategy adopted from Diego Perini assert(function( el ) { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // https://bugs.jquery.com/ticket/12359 docElem.appendChild( el ).innerHTML = "" + ""; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section if ( el.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly if ( !el.querySelectorAll("[selected]").length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { rbuggyQSA.push("~="); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !el.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } // Support: Safari 8+, iOS 8+ // https://bugs.webkit.org/show_bug.cgi?id=136851 // In-page `selector#id sibling-combinator selector` fails if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { rbuggyQSA.push(".#.+[+~]"); } }); assert(function( el ) { el.innerHTML = "" + ""; // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment var input = document.createElement("input"); input.setAttribute( "type", "hidden" ); el.appendChild( input ).setAttribute( "name", "D" ); // Support: IE8 // Enforce case-sensitivity of name attribute if ( el.querySelectorAll("[name=d]").length ) { rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if ( el.querySelectorAll(":enabled").length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Support: IE9-11+ // IE's :disabled selector does not pick up the children of disabled fieldsets docElem.appendChild( el ).disabled = true; if ( el.querySelectorAll(":disabled").length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Opera 10-11 does not throw on post-comma invalid pseudos el.querySelectorAll("*,:x"); rbuggyQSA.push(",.*:"); }); } if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector) )) ) { assert(function( el ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( el, "*" ); // This should fail with an exception // Gecko does not error, returns false instead matches.call( el, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); }); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); /* Contains ---------------------------------------------------------------------- */ hasCompare = rnative.test( docElem.compareDocumentPosition ); // Element contains another // Purposefully self-exclusive // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; return a === bup || !!( bup && bup.nodeType === 1 && ( adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 )); } : function( a, b ) { if ( b ) { while ( (b = b.parentNode) ) { if ( b === a ) { return true; } } } return false; }; /* Sorting ---------------------------------------------------------------------- */ // Document order sorting sortOrder = hasCompare ? function( a, b ) { // Flag for duplicate removal if ( a === b ) { hasDuplicate = true; return 0; } // Sort on method existence if only one input has compareDocumentPosition var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; if ( compare ) { return compare; } // Calculate position if both inputs belong to the same document compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected 1; // Disconnected nodes if ( compare & 1 || (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { return -1; } if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { return 1; } // Maintain original order return sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; } : function( a, b ) { // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; return 0; } var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ]; // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { return a === document ? -1 : b === document ? 1 : aup ? -1 : bup ? 1 : sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check } else if ( aup === bup ) { return siblingCheck( a, b ); } // Otherwise we need full lists of their ancestors for comparison cur = a; while ( (cur = cur.parentNode) ) { ap.unshift( cur ); } cur = b; while ( (cur = cur.parentNode) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy while ( ap[i] === bp[i] ) { i++; } return i ? // Do a sibling check if the nodes have a common ancestor siblingCheck( ap[i], bp[i] ) : // Otherwise nodes in our document sort first ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; }; return document; }; Sizzle.matches = function( expr, elements ) { return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); if ( support.matchesSelector && documentIsHTML && !compilerCache[ expr + " " ] && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9 elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch (e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { // Set document vars if needed if ( ( context.ownerDocument || context ) !== document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; }; Sizzle.escape = function( sel ) { return (sel + "").replace( rcssescape, fcssescape ); }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Document sorting and removing duplicates * @param {ArrayLike} results */ Sizzle.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates; sortInput = !support.sortStable && results.slice( 0 ); results.sort( sortOrder ); if ( hasDuplicate ) { while ( (elem = results[i++]) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } } while ( j-- ) { results.splice( duplicates[ j ], 1 ); } } // Clear input after sorting to release objects // See https://github.com/jquery/sizzle/pull/225 sortInput = null; return results; }; /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { var node, ret = "", i = 0, nodeType = elem.nodeType; if ( !nodeType ) { // If no nodeType, this is expected to be an array while ( (node = elem[i++]) ) { // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } // Do not include comment or processing instruction nodes return ret; }; Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }, preFilter: { "ATTR": function( match ) { match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase(); if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments } else if ( match[3] ) { Sizzle.error( match[0] ); } return match; }, "PSEUDO": function( match ) { var excess, unquoted = !match[6] && match[2]; if ( matchExpr["CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is if ( match[3] ) { match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) (excess = tokenize( unquoted, true )) && // advance to the next closing parenthesis (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }, filter: { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { var pattern = classCache[ className + " " ]; return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); }); }, "ATTR": function( name, operator, check ) { return function( elem ) { var result = Sizzle.attr( elem, name ); if ( result == null ) { return operator === "!="; } if ( !operator ) { return true; } result += ""; return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; }, "CHILD": function( type, what, argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; return first === 1 && last === 0 ? // Shortcut for :nth-*(n) function( elem ) { return !!elem.parentNode; } : function( elem, context, xml ) { var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType, diff = false; if ( parent ) { // :(first|last|only)-(child|of-type) if ( simple ) { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { return false; } } // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } return true; } start = [ forward ? parent.firstChild : parent.lastChild ]; // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { // Seek `elem` from a previously-cached index // ...in a gzip-friendly way node = parent; outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; while ( (node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start (diff = nodeIndex = 0) || start.pop()) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } } else { // Use previously-cached element index if available if ( useCache ) { // ...in a gzip-friendly way node = elem; outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex; } // xml :nth-child(...) // or :nth-last-child(...) or :nth(-last)?-of-type(...) if ( diff === false ) { // Use the same loop as above to seek `elem` from the start while ( (node = ++nodeIndex && node && node[ dir ] || (diff = nodeIndex = 0) || start.pop()) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { // Cache the index of each encountered element if ( useCache ) { outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); uniqueCache[ type ] = [ dirruns, diff ]; } if ( node === elem ) { break; } } } } } // Incorporate the offset, then check against cycle size diff -= last; return diff === first || ( diff % first === 0 && diff / first >= 0 ); } }; }, "PSEUDO": function( pseudo, argument ) { // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos var args, fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || Sizzle.error( "unsupported pseudo: " + pseudo ); // The user may use createPseudo to indicate that // arguments are needed to create the filter function // just as Sizzle does if ( fn[ expando ] ) { return fn( argument ); } // But maintain support for old signatures if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? markFunction(function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { idx = indexOf( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : function( elem ) { return fn( elem, 0, args ); }; } return fn; } }, pseudos: { // Potentially complex pseudos "not": markFunction(function( selector ) { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators var input = [], results = [], matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? markFunction(function( seed, matches, context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { if ( (elem = unmatched[i]) ) { seed[i] = !(matches[i] = elem); } } }) : function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); // Don't keep the element (issue #299) input[0] = null; return !results.pop(); }; }), "has": markFunction(function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; }), "contains": markFunction(function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; }), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value // being equal to the identifier C, // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { // lang value must be a valid identifier if ( !ridentifier.test(lang || "") ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { if ( (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); return false; }; }), // Miscellaneous "target": function( elem ) { var hash = window.location && window.location.hash; return hash && hash.slice( 1 ) === elem.id; }, "root": function( elem ) { return elem === docElem; }, "focus": function( elem ) { return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); }, // Boolean properties "enabled": createDisabledPseudo( false ), "disabled": createDisabledPseudo( true ), "checked": function( elem ) { // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); }, "selected": function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, // Contents "empty": function( elem ) { // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) // nodeType < 6 works because attributes (2) do not appear as children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { if ( elem.nodeType < 6 ) { return false; } } return true; }, "parent": function( elem ) { return !Expr.pseudos["empty"]( elem ); }, // Element/input types "header": function( elem ) { return rheader.test( elem.nodeName ); }, "input": function( elem ) { return rinputs.test( elem.nodeName ); }, "button": function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === "button" || name === "button"; }, "text": function( elem ) { var attr; return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); }, // Position-in-collection "first": createPositionalPseudo(function() { return [ 0 ]; }), "last": createPositionalPseudo(function( matchIndexes, length ) { return [ length - 1 ]; }), "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; }), "even": createPositionalPseudo(function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "odd": createPositionalPseudo(function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; }), "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; }) } }; Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { Expr.pseudos[ i ] = createInputPseudo( i ); } for ( i in { submit: true, reset: true } ) { Expr.pseudos[ i ] = createButtonPseudo( i ); } // Easy API for creating new setFilters function setFilters() {} setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); tokenize = Sizzle.tokenize = function( selector, parseOnly ) { var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[ selector + " " ]; if ( cached ) { return parseOnly ? 0 : cached.slice( 0 ); } soFar = selector; groups = []; preFilters = Expr.preFilter; while ( soFar ) { // Comma and first run if ( !matched || (match = rcomma.exec( soFar )) ) { if ( match ) { // Don't consume trailing commas as valid soFar = soFar.slice( match[0].length ) || soFar; } groups.push( (tokens = []) ); } matched = false; // Combinators if ( (match = rcombinators.exec( soFar )) ) { matched = match.shift(); tokens.push({ value: matched, // Cast descendant combinators to space type: match[0].replace( rtrim, " " ) }); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || (match = preFilters[ type ]( match ))) ) { matched = match.shift(); tokens.push({ value: matched, type: type, matches: match }); soFar = soFar.slice( matched.length ); } } if ( !matched ) { break; } } // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens return parseOnly ? soFar.length : soFar ? Sizzle.error( selector ) : // Cache the tokens tokenCache( selector, groups ).slice( 0 ); }; function toSelector( tokens ) { var i = 0, len = tokens.length, selector = ""; for ( ; i < len; i++ ) { selector += tokens[i].value; } return selector; } function addCombinator( matcher, combinator, base ) { var dir = combinator.dir, skip = combinator.next, key = skip || dir, checkNonElements = base && key === "parentNode", doneName = done++; return combinator.first ? // Check against closest ancestor/preceding element function( elem, context, xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } } return false; } : // Check against all ancestor/preceding elements function( elem, context, xml ) { var oldCache, uniqueCache, outerCache, newCache = [ dirruns, doneName ]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if ( xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; } } } } else { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || (elem[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); if ( skip && skip === elem.nodeName.toLowerCase() ) { elem = elem[ dir ] || elem; } else if ( (oldCache = uniqueCache[ key ]) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements return (newCache[ 2 ] = oldCache[ 2 ]); } else { // Reuse newcache so results back-propagate to previous elements uniqueCache[ key ] = newCache; // A match means we're done; a fail means we have to keep checking if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { return true; } } } } } return false; }; } function elementMatcher( matchers ) { return matchers.length > 1 ? function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { if ( !matchers[i]( elem, context, xml ) ) { return false; } } return true; } : matchers[0]; } function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { Sizzle( selector, contexts[i], results ); } return results; } function condense( unmatched, map, filter, context, xml ) { var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null; for ( ; i < len; i++ ) { if ( (elem = unmatched[i]) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { map.push( i ); } } } } return newUnmatched; } function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { if ( postFilter && !postFilter[ expando ] ) { postFilter = setMatcher( postFilter ); } if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } return markFunction(function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : elems, matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? // ...intermediate processing is necessary [] : // ...otherwise use results directly results : matcherIn; // Find primary matches if ( matcher ) { matcher( matcherIn, matcherOut, context, xml ); } // Apply postFilter if ( postFilter ) { temp = condense( matcherOut, postMap ); postFilter( temp, [], context, xml ); // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { if ( (elem = temp[i]) ) { matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); } } } if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) ) { // Restore matcherIn since elem is not yet a final match temp.push( (matcherIn[i] = elem) ); } } postFinder( null, (matcherOut = []), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } } } // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut ); if ( postFinder ) { postFinder( null, results, matcherOut, xml ); } else { push.apply( results, matcherOut ); } } }); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[ tokens[0].type ], implicitRelative = leadingRelative || Expr.relative[" "], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) matchContext = addCombinator( function( elem ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); // Avoid hanging onto element (issue #299) checkContext = null; return ret; } ]; for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; } else { matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { if ( Expr.relative[ tokens[j].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), j < len && toSelector( tokens ) ); } matchers.push( matcher ); } } return elementMatcher( matchers ); } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function( seed, context, xml, results, outermost ) { var elem, j, matcher, matchedCount = 0, i = "0", unmatched = seed && [], setMatched = [], contextBackup = outermostContext, // We must always have either seed elements or outermost context elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), // Use integer dirruns iff this is the outermost matcher dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), len = elems.length; if ( outermost ) { outermostContext = context === document || context || outermost; } // Add elements passing elementMatchers directly to results // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id for ( ; i !== len && (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; if ( !context && elem.ownerDocument !== document ) { setDocument( elem ); xml = !documentIsHTML; } while ( (matcher = elementMatchers[j++]) ) { if ( matcher( elem, context || document, xml) ) { results.push( elem ); break; } } if ( outermost ) { dirruns = dirrunsUnique; } } // Track unmatched elements for set filters if ( bySet ) { // They will have gone through all possible matchers if ( (elem = !matcher && elem) ) { matchedCount--; } // Lengthen the array for every element, matched or not if ( seed ) { unmatched.push( elem ); } } } // `i` is now the count of elements visited above, and adding it to `matchedCount` // makes the latter nonnegative. matchedCount += i; // Apply set filters to unmatched elements // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` // equals `i`), unless we didn't visit _any_ elements in the above loop because we have // no element matchers and no seed. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that // case, which will result in a "00" `matchedCount` that differs from `i` but is also // numerically zero. if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { if ( !(unmatched[i] || setMatched[i]) ) { setMatched[i] = pop.call( results ); } } } // Discard index placeholder values to get only actual matches setMatched = condense( setMatched ); } // Add matches to results push.apply( results, setMatched ); // Seedless set matches succeeding multiple successful matchers stipulate sorting if ( outermost && !seed && setMatched.length > 0 && ( matchedCount + setMatchers.length ) > 1 ) { Sizzle.uniqueSort( results ); } } // Override manipulation of globals by nested matchers if ( outermost ) { dirruns = dirrunsUnique; outermostContext = contextBackup; } return unmatched; }; return bySet ? markFunction( superMatcher ) : superMatcher; } compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], cached = compilerCache[ selector + " " ]; if ( !cached ) { // Generate a function of recursive functions that can be used to check each element if ( !match ) { match = tokenize( selector ); } i = match.length; while ( i-- ) { cached = matcherFromTokens( match[i] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { elementMatchers.push( cached ); } } // Cache the compiled function cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); // Save selector and tokenization cached.selector = selector; } return cached; }; /** * A low-level selection function that works with Sizzle's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled * selector function built with Sizzle.compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set of elements to match against */ select = Sizzle.select = function( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, match = !seed && tokenize( (selector = compiled.selector || selector) ); results = results || []; // Try to minimize operations if there is only one selector in the list and no seed // (the latter of which guarantees us context) if ( match.length === 1 ) { // Reduce context if the leading compound selector is an ID tokens = match[0] = match[0].slice( 0 ); if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; if ( !context ) { return results; // Precompiled matchers will still verify ancestry, so step up a level } else if ( compiled ) { context = context.parentNode; } selector = selector.slice( tokens.shift().value.length ); } // Fetch a seed set for right-to-left matching i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; while ( i-- ) { token = tokens[i]; // Abort if we hit a combinator if ( Expr.relative[ (type = token.type) ] ) { break; } if ( (find = Expr.find[ type ]) ) { // Search, expanding context for leading sibling combinators if ( (seed = find( token.matches[0].replace( runescape, funescape ), rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context )) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); selector = seed.length && toSelector( tokens ); if ( !selector ) { push.apply( results, seed ); return results; } break; } } } } // Compile and execute a filtering function if one is not provided // Provide `match` to avoid retokenization if we modified the selector above ( compiled || compile( selector, match ) )( seed, context, !documentIsHTML, results, !context || rsibling.test( selector ) && testContext( context.parentNode ) || context ); return results; }; // One-time assignments // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate; // Initialize against the default document setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert(function( el ) { // Should return 1, but returns 4 (following) return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; }); // Support: IE<8 // Prevent attribute/property "interpolation" // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !assert(function( el ) { el.innerHTML = ""; return el.firstChild.getAttribute("href") === "#" ; }) ) { addHandle( "type|href|height|width", function( elem, name, isXML ) { if ( !isXML ) { return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); } }); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") if ( !support.attributes || !assert(function( el ) { el.innerHTML = ""; el.firstChild.setAttribute( "value", "" ); return el.firstChild.getAttribute( "value" ) === ""; }) ) { addHandle( "value", function( elem, name, isXML ) { if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { return elem.defaultValue; } }); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies if ( !assert(function( el ) { return el.getAttribute("disabled") == null; }) ) { addHandle( booleans, function( elem, name, isXML ) { var val; if ( !isXML ) { return elem[ name ] === true ? name.toLowerCase() : (val = elem.getAttributeNode( name )) && val.specified ? val.value : null; } }); } return Sizzle; })( window ); jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; // Deprecated jQuery.expr[ ":" ] = jQuery.expr.pseudos; jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; jQuery.escapeSelector = Sizzle.escape; var dir = function( elem, dir, until ) { var matched = [], truncate = until !== undefined; while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { if ( elem.nodeType === 1 ) { if ( truncate && jQuery( elem ).is( until ) ) { break; } matched.push( elem ); } } return matched; }; var siblings = function( n, elem ) { var matched = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { matched.push( n ); } } return matched; }; var rneedsContext = jQuery.expr.match.needsContext; function nodeName( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }; var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { if ( isFunction( qualifier ) ) { return jQuery.grep( elements, function( elem, i ) { return !!qualifier.call( elem, i, elem ) !== not; } ); } // Single element if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; } ); } // Arraylike of elements (jQuery, arguments, Array) if ( typeof qualifier !== "string" ) { return jQuery.grep( elements, function( elem ) { return ( indexOf.call( qualifier, elem ) > -1 ) !== not; } ); } // Filtered directly for both simple and complex selectors return jQuery.filter( qualifier, elements, not ); } jQuery.filter = function( expr, elems, not ) { var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } if ( elems.length === 1 && elem.nodeType === 1 ) { return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; } return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; } ) ); }; jQuery.fn.extend( { find: function( selector ) { var i, ret, len = this.length, self = this; if ( typeof selector !== "string" ) { return this.pushStack( jQuery( selector ).filter( function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } } ) ); } ret = this.pushStack( [] ); for ( i = 0; i < len; i++ ) { jQuery.find( selector, self[ i ], ret ); } return len > 1 ? jQuery.uniqueSort( ret ) : ret; }, filter: function( selector ) { return this.pushStack( winnow( this, selector || [], false ) ); }, not: function( selector ) { return this.pushStack( winnow( this, selector || [], true ) ); }, is: function( selector ) { return !!winnow( this, // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". typeof selector === "string" && rneedsContext.test( selector ) ? jQuery( selector ) : selector || [], false ).length; } } ); // Initialize a jQuery object // A central reference to the root jQuery(document) var rootjQuery, // A simple way to check for HTML strings // Prioritize #id over to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; // Handle HTML strings if ( typeof selector === "string" ) { if ( selector[ 0 ] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if ( match && ( match[ 1 ] || !context ) ) { // HANDLE: $(html) -> $(array) if ( match[ 1 ] ) { context = context instanceof jQuery ? context[ 0 ] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( match[ 1 ], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById( match[ 2 ] ); if ( elem ) { // Inject the element directly into the jQuery object this[ 0 ] = elem; this.length = 1; } return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || root ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this[ 0 ] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( isFunction( selector ) ) { return root.ready !== undefined ? root.ready( selector ) : // Execute immediately if ready is not present selector( jQuery ); } return jQuery.makeArray( selector, this ); }; // Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn; // Initialize central reference rootjQuery = jQuery( document ); var rparentsprev = /^(?:parents|prev(?:Until|All))/, // Methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend( { has: function( target ) { var targets = jQuery( target, this ), l = targets.length; return this.filter( function() { var i = 0; for ( ; i < l; i++ ) { if ( jQuery.contains( this, targets[ i ] ) ) { return true; } } } ); }, closest: function( selectors, context ) { var cur, i = 0, l = this.length, matched = [], targets = typeof selectors !== "string" && jQuery( selectors ); // Positional selectors never match, since there's no _selection_ context if ( !rneedsContext.test( selectors ) ) { for ( ; i < l; i++ ) { for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { // Always skip document fragments if ( cur.nodeType < 11 && ( targets ? targets.index( cur ) > -1 : // Don't pass non-elements to Sizzle cur.nodeType === 1 && jQuery.find.matchesSelector( cur, selectors ) ) ) { matched.push( cur ); break; } } } } return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); }, // Determine the position of an element within the set index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; } // Index in selector if ( typeof elem === "string" ) { return indexOf.call( jQuery( elem ), this[ 0 ] ); } // Locate the position of the desired element return indexOf.call( this, // If it receives a jQuery object, the first element is used elem.jquery ? elem[ 0 ] : elem ); }, add: function( selector, context ) { return this.pushStack( jQuery.uniqueSort( jQuery.merge( this.get(), jQuery( selector, context ) ) ) ); }, addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter( selector ) ); } } ); function sibling( cur, dir ) { while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} return cur; } jQuery.each( { parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return dir( elem, "parentNode", until ); }, next: function( elem ) { return sibling( elem, "nextSibling" ); }, prev: function( elem ) { return sibling( elem, "previousSibling" ); }, nextAll: function( elem ) { return dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return siblings( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { return siblings( elem.firstChild ); }, contents: function( elem ) { if ( nodeName( elem, "iframe" ) ) { return elem.contentDocument; } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only // Treat the template element as a regular one in browsers that // don't support it. if ( nodeName( elem, "template" ) ) { elem = elem.content || elem; } return jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var matched = jQuery.map( this, fn, until ); if ( name.slice( -5 ) !== "Until" ) { selector = until; } if ( selector && typeof selector === "string" ) { matched = jQuery.filter( selector, matched ); } if ( this.length > 1 ) { // Remove duplicates if ( !guaranteedUnique[ name ] ) { jQuery.uniqueSort( matched ); } // Reverse order for parents* and prev-derivatives if ( rparentsprev.test( name ) ) { matched.reverse(); } } return this.pushStack( matched ); }; } ); var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); // Convert String-formatted options into Object-formatted ones function createOptions( options ) { var object = {}; jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { object[ flag ] = true; } ); return object; } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? createOptions( options ) : jQuery.extend( {}, options ); var // Flag to know if list is currently firing firing, // Last fire value for non-forgettable lists memory, // Flag to know if list was already fired fired, // Flag to prevent firing locked, // Actual callback list list = [], // Queue of execution data for repeatable lists queue = [], // Index of currently firing callback (modified by add/remove as needed) firingIndex = -1, // Fire callbacks fire = function() { // Enforce single-firing locked = locked || options.once; // Execute callbacks for all pending executions, // respecting firingIndex overrides and runtime changes fired = firing = true; for ( ; queue.length; firingIndex = -1 ) { memory = queue.shift(); while ( ++firingIndex < list.length ) { // Run callback and check for early termination if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && options.stopOnFalse ) { // Jump to end and forget the data so .add doesn't re-fire firingIndex = list.length; memory = false; } } } // Forget the data if we're done with it if ( !options.memory ) { memory = false; } firing = false; // Clean up if we're done firing for good if ( locked ) { // Keep an empty list if we have data for future add calls if ( memory ) { list = []; // Otherwise, this object is spent } else { list = ""; } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // If we have memory from a past run, we should fire after adding if ( memory && !firing ) { firingIndex = list.length - 1; queue.push( memory ); } ( function add( args ) { jQuery.each( args, function( _, arg ) { if ( isFunction( arg ) ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && toType( arg ) !== "string" ) { // Inspect recursively add( arg ); } } ); } )( arguments ); if ( memory && !firing ) { fire(); } } return this; }, // Remove a callback from the list remove: function() { jQuery.each( arguments, function( _, arg ) { var index; while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( index <= firingIndex ) { firingIndex--; } } } ); return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : list.length > 0; }, // Remove all callbacks from the list empty: function() { if ( list ) { list = []; } return this; }, // Disable .fire and .add // Abort any current/pending executions // Clear all callbacks and values disable: function() { locked = queue = []; list = memory = ""; return this; }, disabled: function() { return !list; }, // Disable .fire // Also disable .add unless we have memory (since it would have no effect) // Abort any pending executions lock: function() { locked = queue = []; if ( !memory && !firing ) { list = memory = ""; } return this; }, locked: function() { return !!locked; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( !locked ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; queue.push( args ); if ( !firing ) { fire(); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; }; function Identity( v ) { return v; } function Thrower( ex ) { throw ex; } function adoptValue( value, resolve, reject, noValue ) { var method; try { // Check for promise aspect first to privilege synchronous behavior if ( value && isFunction( ( method = value.promise ) ) ) { method.call( value ).done( resolve ).fail( reject ); // Other thenables } else if ( value && isFunction( ( method = value.then ) ) ) { method.call( value, resolve, reject ); // Other non-thenables } else { // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: // * false: [ value ].slice( 0 ) => resolve( value ) // * true: [ value ].slice( 1 ) => resolve() resolve.apply( undefined, [ value ].slice( noValue ) ); } // For Promises/A+, convert exceptions into rejections // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in // Deferred#then to conditionally suppress rejection. } catch ( value ) { // Support: Android 4.0 only // Strict mode functions invoked without .call/.apply get global-object context reject.apply( undefined, [ value ] ); } } jQuery.extend( { Deferred: function( func ) { var tuples = [ // action, add listener, callbacks, // ... .then handlers, argument index, [final state] [ "notify", "progress", jQuery.Callbacks( "memory" ), jQuery.Callbacks( "memory" ), 2 ], [ "resolve", "done", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 0, "resolved" ], [ "reject", "fail", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 1, "rejected" ] ], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done( arguments ).fail( arguments ); return this; }, "catch": function( fn ) { return promise.then( null, fn ); }, // Keep pipe for back-compat pipe: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred( function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { // Map tuples (progress, done, fail) to arguments (done, fail, progress) var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; // deferred.progress(function() { bind to newDefer or newDefer.notify }) // deferred.done(function() { bind to newDefer or newDefer.resolve }) // deferred.fail(function() { bind to newDefer or newDefer.reject }) deferred[ tuple[ 1 ] ]( function() { var returned = fn && fn.apply( this, arguments ); if ( returned && isFunction( returned.promise ) ) { returned.promise() .progress( newDefer.notify ) .done( newDefer.resolve ) .fail( newDefer.reject ); } else { newDefer[ tuple[ 0 ] + "With" ]( this, fn ? [ returned ] : arguments ); } } ); } ); fns = null; } ).promise(); }, then: function( onFulfilled, onRejected, onProgress ) { var maxDepth = 0; function resolve( depth, deferred, handler, special ) { return function() { var that = this, args = arguments, mightThrow = function() { var returned, then; // Support: Promises/A+ section 2.3.3.3.3 // https://promisesaplus.com/#point-59 // Ignore double-resolution attempts if ( depth < maxDepth ) { return; } returned = handler.apply( that, args ); // Support: Promises/A+ section 2.3.1 // https://promisesaplus.com/#point-48 if ( returned === deferred.promise() ) { throw new TypeError( "Thenable self-resolution" ); } // Support: Promises/A+ sections 2.3.3.1, 3.5 // https://promisesaplus.com/#point-54 // https://promisesaplus.com/#point-75 // Retrieve `then` only once then = returned && // Support: Promises/A+ section 2.3.4 // https://promisesaplus.com/#point-64 // Only check objects and functions for thenability ( typeof returned === "object" || typeof returned === "function" ) && returned.then; // Handle a returned thenable if ( isFunction( then ) ) { // Special processors (notify) just wait for resolution if ( special ) { then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ) ); // Normal processors (resolve) also hook into progress } else { // ...and disregard older resolution values maxDepth++; then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ), resolve( maxDepth, deferred, Identity, deferred.notifyWith ) ); } // Handle all other returned values } else { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Identity ) { that = undefined; args = [ returned ]; } // Process the value(s) // Default process is resolve ( special || deferred.resolveWith )( that, args ); } }, // Only normal processors (resolve) catch and reject exceptions process = special ? mightThrow : function() { try { mightThrow(); } catch ( e ) { if ( jQuery.Deferred.exceptionHook ) { jQuery.Deferred.exceptionHook( e, process.stackTrace ); } // Support: Promises/A+ section 2.3.3.3.4.1 // https://promisesaplus.com/#point-61 // Ignore post-resolution exceptions if ( depth + 1 >= maxDepth ) { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Thrower ) { that = undefined; args = [ e ]; } deferred.rejectWith( that, args ); } } }; // Support: Promises/A+ section 2.3.3.3.1 // https://promisesaplus.com/#point-57 // Re-resolve promises immediately to dodge false rejection from // subsequent errors if ( depth ) { process(); } else { // Call an optional hook to record the stack, in case of exception // since it's otherwise lost when execution goes async if ( jQuery.Deferred.getStackHook ) { process.stackTrace = jQuery.Deferred.getStackHook(); } window.setTimeout( process ); } }; } return jQuery.Deferred( function( newDefer ) { // progress_handlers.add( ... ) tuples[ 0 ][ 3 ].add( resolve( 0, newDefer, isFunction( onProgress ) ? onProgress : Identity, newDefer.notifyWith ) ); // fulfilled_handlers.add( ... ) tuples[ 1 ][ 3 ].add( resolve( 0, newDefer, isFunction( onFulfilled ) ? onFulfilled : Identity ) ); // rejected_handlers.add( ... ) tuples[ 2 ][ 3 ].add( resolve( 0, newDefer, isFunction( onRejected ) ? onRejected : Thrower ) ); } ).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; // Add list-specific methods jQuery.each( tuples, function( i, tuple ) { var list = tuple[ 2 ], stateString = tuple[ 5 ]; // promise.progress = list.add // promise.done = list.add // promise.fail = list.add promise[ tuple[ 1 ] ] = list.add; // Handle state if ( stateString ) { list.add( function() { // state = "resolved" (i.e., fulfilled) // state = "rejected" state = stateString; }, // rejected_callbacks.disable // fulfilled_callbacks.disable tuples[ 3 - i ][ 2 ].disable, // rejected_handlers.disable // fulfilled_handlers.disable tuples[ 3 - i ][ 3 ].disable, // progress_callbacks.lock tuples[ 0 ][ 2 ].lock, // progress_handlers.lock tuples[ 0 ][ 3 ].lock ); } // progress_handlers.fire // fulfilled_handlers.fire // rejected_handlers.fire list.add( tuple[ 3 ].fire ); // deferred.notify = function() { deferred.notifyWith(...) } // deferred.resolve = function() { deferred.resolveWith(...) } // deferred.reject = function() { deferred.rejectWith(...) } deferred[ tuple[ 0 ] ] = function() { deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); return this; }; // deferred.notifyWith = list.fireWith // deferred.resolveWith = list.fireWith // deferred.rejectWith = list.fireWith deferred[ tuple[ 0 ] + "With" ] = list.fireWith; } ); // Make the deferred a promise promise.promise( deferred ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( singleValue ) { var // count of uncompleted subordinates remaining = arguments.length, // count of unprocessed arguments i = remaining, // subordinate fulfillment data resolveContexts = Array( i ), resolveValues = slice.call( arguments ), // the master Deferred master = jQuery.Deferred(), // subordinate callback factory updateFunc = function( i ) { return function( value ) { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { master.resolveWith( resolveContexts, resolveValues ); } }; }; // Single- and empty arguments are adopted like Promise.resolve if ( remaining <= 1 ) { adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, !remaining ); // Use .then() to unwrap secondary thenables (cf. gh-3000) if ( master.state() === "pending" || isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { return master.then(); } } // Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); } return master.promise(); } } ); // These usually indicate a programmer mistake during development, // warn about them ASAP rather than swallowing them by default. var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; jQuery.Deferred.exceptionHook = function( error, stack ) { // Support: IE 8 - 9 only // Console exists when dev tools are open, which can happen at any time if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); } }; jQuery.readyException = function( error ) { window.setTimeout( function() { throw error; } ); }; // The deferred used on DOM ready var readyList = jQuery.Deferred(); jQuery.fn.ready = function( fn ) { readyList .then( fn ) // Wrap jQuery.readyException in a function so that the lookup // happens at the time of error handling instead of callback // registration. .catch( function( error ) { jQuery.readyException( error ); } ); return this; }; jQuery.extend( { // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Handle when the DOM is ready ready: function( wait ) { // Abort if there are pending holds or we're already ready if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); } } ); jQuery.ready.then = readyList.then; // The ready event handler and self cleanup method function completed() { document.removeEventListener( "DOMContentLoaded", completed ); window.removeEventListener( "load", completed ); jQuery.ready(); } // Catch cases where $(document).ready() is called // after the browser event has already occurred. // Support: IE <=9 - 10 only // Older IE sometimes signals "interactive" too soon if ( document.readyState === "complete" || ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout( jQuery.ready ); } else { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed ); } // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, len = elems.length, bulk = key == null; // Sets many values if ( toType( key ) === "object" ) { chainable = true; for ( i in key ) { access( elems, fn, i, key[ i ], true, emptyGet, raw ); } // Sets one value } else if ( value !== undefined ) { chainable = true; if ( !isFunction( value ) ) { raw = true; } if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < len; i++ ) { fn( elems[ i ], key, raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); } } } if ( chainable ) { return elems; } // Gets if ( bulk ) { return fn.call( elems ); } return len ? fn( elems[ 0 ], key ) : emptyGet; }; // Matches dashed string for camelizing var rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace() function fcamelCase( all, letter ) { return letter.toUpperCase(); } // Convert dashed to camelCase; used by the css and data modules // Support: IE <=9 - 11, Edge 12 - 15 // Microsoft forgot to hump their vendor prefix (#9572) function camelCase( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); } var acceptData = function( owner ) { // Accepts only: // - Node // - Node.ELEMENT_NODE // - Node.DOCUMENT_NODE // - Object // - Any return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); }; function Data() { this.expando = jQuery.expando + Data.uid++; } Data.uid = 1; Data.prototype = { cache: function( owner ) { // Check if the owner object already has a cache var value = owner[ this.expando ]; // If not, create one if ( !value ) { value = {}; // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. // Always return an empty object. if ( acceptData( owner ) ) { // If it is a node unlikely to be stringify-ed or looped over // use plain assignment if ( owner.nodeType ) { owner[ this.expando ] = value; // Otherwise secure it in a non-enumerable property // configurable must be true to allow the property to be // deleted when data is removed } else { Object.defineProperty( owner, this.expando, { value: value, configurable: true } ); } } } return value; }, set: function( owner, data, value ) { var prop, cache = this.cache( owner ); // Handle: [ owner, key, value ] args // Always use camelCase key (gh-2257) if ( typeof data === "string" ) { cache[ camelCase( data ) ] = value; // Handle: [ owner, { properties } ] args } else { // Copy the properties one-by-one to the cache object for ( prop in data ) { cache[ camelCase( prop ) ] = data[ prop ]; } } return cache; }, get: function( owner, key ) { return key === undefined ? this.cache( owner ) : // Always use camelCase key (gh-2257) owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; }, access: function( owner, key, value ) { // In cases where either: // // 1. No key was specified // 2. A string key was specified, but no value provided // // Take the "read" path and allow the get method to determine // which value to return, respectively either: // // 1. The entire cache object // 2. The data stored at the key // if ( key === undefined || ( ( key && typeof key === "string" ) && value === undefined ) ) { return this.get( owner, key ); } // When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties // 2. A key and value // this.set( owner, key, value ); // Since the "set" path can have two possible entry points // return the expected data based on which path was taken[*] return value !== undefined ? value : key; }, remove: function( owner, key ) { var i, cache = owner[ this.expando ]; if ( cache === undefined ) { return; } if ( key !== undefined ) { // Support array or space separated string of keys if ( Array.isArray( key ) ) { // If key is an array of keys... // We always set camelCase keys, so remove that. key = key.map( camelCase ); } else { key = camelCase( key ); // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace key = key in cache ? [ key ] : ( key.match( rnothtmlwhite ) || [] ); } i = key.length; while ( i-- ) { delete cache[ key[ i ] ]; } } // Remove the expando if there's no more data if ( key === undefined || jQuery.isEmptyObject( cache ) ) { // Support: Chrome <=35 - 45 // Webkit & Blink performance suffers when deleting properties // from DOM nodes, so set to undefined instead // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) if ( owner.nodeType ) { owner[ this.expando ] = undefined; } else { delete owner[ this.expando ]; } } }, hasData: function( owner ) { var cache = owner[ this.expando ]; return cache !== undefined && !jQuery.isEmptyObject( cache ); } }; var dataPriv = new Data(); var dataUser = new Data(); // Implementation Summary // // 1. Enforce API surface and semantic compatibility with 1.9.x branch // 2. Improve the module's maintainability by reducing the storage // paths to a single mechanism. // 3. Use the same single mechanism to support "private" and "user" data. // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) // 5. Avoid exposing implementation details on user objects (eg. expando properties) // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, rmultiDash = /[A-Z]/g; function getData( data ) { if ( data === "true" ) { return true; } if ( data === "false" ) { return false; } if ( data === "null" ) { return null; } // Only convert to a number if it doesn't change the string if ( data === +data + "" ) { return +data; } if ( rbrace.test( data ) ) { return JSON.parse( data ); } return data; } function dataAttr( elem, key, data ) { var name; // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = getData( data ); } catch ( e ) {} // Make sure we set the data so it isn't changed later dataUser.set( elem, key, data ); } else { data = undefined; } } return data; } jQuery.extend( { hasData: function( elem ) { return dataUser.hasData( elem ) || dataPriv.hasData( elem ); }, data: function( elem, name, data ) { return dataUser.access( elem, name, data ); }, removeData: function( elem, name ) { dataUser.remove( elem, name ); }, // TODO: Now that all calls to _data and _removeData have been replaced // with direct calls to dataPriv methods, these can be deprecated. _data: function( elem, name, data ) { return dataPriv.access( elem, name, data ); }, _removeData: function( elem, name ) { dataPriv.remove( elem, name ); } } ); jQuery.fn.extend( { data: function( key, value ) { var i, name, data, elem = this[ 0 ], attrs = elem && elem.attributes; // Gets all values if ( key === undefined ) { if ( this.length ) { data = dataUser.get( elem ); if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { i = attrs.length; while ( i-- ) { // Support: IE 11 only // The attrs elements can be null (#14894) if ( attrs[ i ] ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { name = camelCase( name.slice( 5 ) ); dataAttr( elem, name, data[ name ] ); } } } dataPriv.set( elem, "hasDataAttrs", true ); } } return data; } // Sets multiple values if ( typeof key === "object" ) { return this.each( function() { dataUser.set( this, key ); } ); } return access( this, function( value ) { var data; // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the // `value` parameter was not undefined. An empty jQuery object // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. if ( elem && value === undefined ) { // Attempt to get data from the cache // The key will always be camelCased in Data data = dataUser.get( elem, key ); if ( data !== undefined ) { return data; } // Attempt to "discover" the data in // HTML5 custom data-* attrs data = dataAttr( elem, key ); if ( data !== undefined ) { return data; } // We tried really hard, but the data doesn't exist. return; } // Set the data... this.each( function() { // We always store the camelCased key dataUser.set( this, key, value ); } ); }, null, value, arguments.length > 1, null, true ); }, removeData: function( key ) { return this.each( function() { dataUser.remove( this, key ); } ); } } ); jQuery.extend( { queue: function( elem, type, data ) { var queue; if ( elem ) { type = ( type || "fx" ) + "queue"; queue = dataPriv.get( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !queue || Array.isArray( data ) ) { queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); } else { queue.push( data ); } } return queue || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), startLength = queue.length, fn = queue.shift(), hooks = jQuery._queueHooks( elem, type ), next = function() { jQuery.dequeue( elem, type ); }; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); startLength--; } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } // Clear up the last queue stop function delete hooks.stop; fn.call( elem, next, hooks ); } if ( !startLength && hooks ) { hooks.empty.fire(); } }, // Not public - generate a queueHooks object, or return the current one _queueHooks: function( elem, type ) { var key = type + "queueHooks"; return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { empty: jQuery.Callbacks( "once memory" ).add( function() { dataPriv.remove( elem, [ type + "queue", key ] ); } ) } ); } } ); jQuery.fn.extend( { queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } if ( arguments.length < setter ) { return jQuery.queue( this[ 0 ], type ); } return data === undefined ? this : this.each( function() { var queue = jQuery.queue( this, type, data ); // Ensure a hooks for this queue jQuery._queueHooks( this, type ); if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { jQuery.dequeue( this, type ); } } ); }, dequeue: function( type ) { return this.each( function() { jQuery.dequeue( this, type ); } ); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, obj ) { var tmp, count = 1, defer = jQuery.Deferred(), elements = this, i = this.length, resolve = function() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } }; if ( typeof type !== "string" ) { obj = type; type = undefined; } type = type || "fx"; while ( i-- ) { tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; tmp.empty.add( resolve ); } } resolve(); return defer.promise( obj ); } } ); var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; var isHiddenWithinTree = function( elem, el ) { // isHiddenWithinTree might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; // Inline style trumps all return elem.style.display === "none" || elem.style.display === "" && // Otherwise, check computed style // Support: Firefox <=43 - 45 // Disconnected elements can have computed display: none, so first confirm that elem is // in the document. jQuery.contains( elem.ownerDocument, elem ) && jQuery.css( elem, "display" ) === "none"; }; var swap = function( elem, options, callback, args ) { var ret, name, old = {}; // Remember the old values, and insert the new ones for ( name in options ) { old[ name ] = elem.style[ name ]; elem.style[ name ] = options[ name ]; } ret = callback.apply( elem, args || [] ); // Revert the old values for ( name in options ) { elem.style[ name ] = old[ name ]; } return ret; }; function adjustCSS( elem, prop, valueParts, tween ) { var adjusted, scale, maxIterations = 20, currentValue = tween ? function() { return tween.cur(); } : function() { return jQuery.css( elem, prop, "" ); }, initial = currentValue(), unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), // Starting value computation is required for potential unit mismatches initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && rcssNum.exec( jQuery.css( elem, prop ) ); if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { // Support: Firefox <=54 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) initial = initial / 2; // Trust units reported by jQuery.css unit = unit || initialInUnit[ 3 ]; // Iteratively approximate from a nonzero starting point initialInUnit = +initial || 1; while ( maxIterations-- ) { // Evaluate and update our best guess (doubling guesses that zero out). // Finish if the scale equals or crosses 1 (making the old*new product non-positive). jQuery.style( elem, prop, initialInUnit + unit ); if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { maxIterations = 0; } initialInUnit = initialInUnit / scale; } initialInUnit = initialInUnit * 2; jQuery.style( elem, prop, initialInUnit + unit ); // Make sure we update the tween properties later on valueParts = valueParts || []; } if ( valueParts ) { initialInUnit = +initialInUnit || +initial || 0; // Apply relative offset (+=/-=) if specified adjusted = valueParts[ 1 ] ? initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : +valueParts[ 2 ]; if ( tween ) { tween.unit = unit; tween.start = initialInUnit; tween.end = adjusted; } } return adjusted; } var defaultDisplayMap = {}; function getDefaultDisplay( elem ) { var temp, doc = elem.ownerDocument, nodeName = elem.nodeName, display = defaultDisplayMap[ nodeName ]; if ( display ) { return display; } temp = doc.body.appendChild( doc.createElement( nodeName ) ); display = jQuery.css( temp, "display" ); temp.parentNode.removeChild( temp ); if ( display === "none" ) { display = "block"; } defaultDisplayMap[ nodeName ] = display; return display; } function showHide( elements, show ) { var display, elem, values = [], index = 0, length = elements.length; // Determine new display value for elements that need to change for ( ; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } display = elem.style.display; if ( show ) { // Since we force visibility upon cascade-hidden elements, an immediate (and slow) // check is required in this first loop unless we have a nonempty display value (either // inline or about-to-be-restored) if ( display === "none" ) { values[ index ] = dataPriv.get( elem, "display" ) || null; if ( !values[ index ] ) { elem.style.display = ""; } } if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { values[ index ] = getDefaultDisplay( elem ); } } else { if ( display !== "none" ) { values[ index ] = "none"; // Remember what we're overwriting dataPriv.set( elem, "display", display ); } } } // Set the display of the elements in a second loop to avoid constant reflow for ( index = 0; index < length; index++ ) { if ( values[ index ] != null ) { elements[ index ].style.display = values[ index ]; } } return elements; } jQuery.fn.extend( { show: function() { return showHide( this, true ); }, hide: function() { return showHide( this ); }, toggle: function( state ) { if ( typeof state === "boolean" ) { return state ? this.show() : this.hide(); } return this.each( function() { if ( isHiddenWithinTree( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } } ); } } ); var rcheckableType = ( /^(?:checkbox|radio)$/i ); var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); // We have to close these tags to support XHTML (#13200) var wrapMap = { // Support: IE <=9 only option: [ 1, "" ], // XHTML parsers do not magically insert elements in the // same way that tag soup parsers do. So we cannot shorten // this by omitting or other required elements. thead: [ 1, "", "
" ], col: [ 2, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], _default: [ 0, "", "" ] }; // Support: IE <=9 only wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; function getAll( context, tag ) { // Support: IE <=9 - 11 only // Use typeof to avoid zero-argument method invocation on host objects (#15151) var ret; if ( typeof context.getElementsByTagName !== "undefined" ) { ret = context.getElementsByTagName( tag || "*" ); } else if ( typeof context.querySelectorAll !== "undefined" ) { ret = context.querySelectorAll( tag || "*" ); } else { ret = []; } if ( tag === undefined || tag && nodeName( context, tag ) ) { return jQuery.merge( [ context ], ret ); } return ret; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { var i = 0, l = elems.length; for ( ; i < l; i++ ) { dataPriv.set( elems[ i ], "globalEval", !refElements || dataPriv.get( refElements[ i ], "globalEval" ) ); } } var rhtml = /<|&#?\w+;/; function buildFragment( elems, context, scripts, selection, ignored ) { var elem, tmp, tag, wrap, contains, j, fragment = context.createDocumentFragment(), nodes = [], i = 0, l = elems.length; for ( ; i < l; i++ ) { elem = elems[ i ]; if ( elem || elem === 0 ) { // Add nodes directly if ( toType( elem ) === "object" ) { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node } else if ( !rhtml.test( elem ) ) { nodes.push( context.createTextNode( elem ) ); // Convert html into DOM nodes } else { tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); // Deserialize a standard representation tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; // Descend through wrappers to the right content j = wrap[ 0 ]; while ( j-- ) { tmp = tmp.lastChild; } // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, tmp.childNodes ); // Remember the top-level container tmp = fragment.firstChild; // Ensure the created nodes are orphaned (#12392) tmp.textContent = ""; } } } // Remove wrapper from fragment fragment.textContent = ""; i = 0; while ( ( elem = nodes[ i++ ] ) ) { // Skip elements already in the context collection (trac-4087) if ( selection && jQuery.inArray( elem, selection ) > -1 ) { if ( ignored ) { ignored.push( elem ); } continue; } contains = jQuery.contains( elem.ownerDocument, elem ); // Append to fragment tmp = getAll( fragment.appendChild( elem ), "script" ); // Preserve script evaluation history if ( contains ) { setGlobalEval( tmp ); } // Capture executables if ( scripts ) { j = 0; while ( ( elem = tmp[ j++ ] ) ) { if ( rscriptType.test( elem.type || "" ) ) { scripts.push( elem ); } } } } return fragment; } ( function() { var fragment = document.createDocumentFragment(), div = fragment.appendChild( document.createElement( "div" ) ), input = document.createElement( "input" ); // Support: Android 4.0 - 4.3 only // Check state lost if the name is set (#11217) // Support: Windows Web Apps (WWA) // `name` and `type` must use .setAttribute for WWA (#14901) input.setAttribute( "type", "radio" ); input.setAttribute( "checked", "checked" ); input.setAttribute( "name", "t" ); div.appendChild( input ); // Support: Android <=4.1 only // Older WebKit doesn't clone checked state correctly in fragments support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; // Support: IE <=11 only // Make sure textarea (and checkbox) defaultValue is properly cloned div.innerHTML = ""; support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; } )(); var documentElement = document.documentElement; var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { return true; } function returnFalse() { return false; } // Support: IE <=9 only // See #13393 for more info function safeActiveElement() { try { return document.activeElement; } catch ( err ) { } } function on( elem, types, selector, data, fn, one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { on( elem, type, selector, data, types[ type ], one ); } return elem; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return elem; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return elem.each( function() { jQuery.event.add( this, types, fn, data, selector ); } ); } /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { global: {}, add: function( elem, types, handler, data, selector ) { var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.get( elem ); // Don't attach events to noData or text/comment nodes (but allow plain objects) if ( !elemData ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; } // Ensure that invalid selectors throw exceptions at attach time // Evaluate against documentElement in case elem is a non-element node (e.g., document) if ( selector ) { jQuery.find.matchesSelector( documentElement, selector ); } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first if ( !( events = elemData.events ) ) { events = elemData.events = {}; } if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; }; } // Handle multiple events separated by a space types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[ t ] ) || []; type = origType = tmp[ 1 ]; namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { continue; } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend( { type: type, origType: origType, data: data, handler: handler, guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), namespace: namespaces.join( "." ) }, handleObjIn ); // Init the event handler queue if we're the first if ( !( handlers = events[ type ] ) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } }, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var j, origCount, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); if ( !elemData || !( events = elemData.events ) ) { return; } // Once for each type.namespace in types; type may be omitted types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[ t ] ) || []; type = origType = tmp[ 1 ]; namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; tmp = tmp[ 2 ] && new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); // Remove matching events origCount = j = handlers.length; while ( j-- ) { handleObj = handlers[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !tmp || tmp.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { handlers.splice( j, 1 ); if ( handleObj.selector ) { handlers.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove data and the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { dataPriv.remove( elem, "handle events" ); } }, dispatch: function( nativeEvent ) { // Make a writable jQuery.Event from the native event object var event = jQuery.event.fix( nativeEvent ); var i, j, ret, matched, handleObj, handlerQueue, args = new Array( arguments.length ), handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[ 0 ] = event; for ( i = 1; i < arguments.length; i++ ) { args[ i ] = arguments[ i ]; } event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { return; } // Determine handlers handlerQueue = jQuery.event.handlers.call( this, event, handlers ); // Run delegates first; they may want to stop propagation beneath us i = 0; while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { event.currentTarget = matched.elem; j = 0; while ( ( handleObj = matched.handlers[ j++ ] ) && !event.isImmediatePropagationStopped() ) { // Triggered event must either 1) have no namespace, or 2) have namespace(s) // a subset or equal to those in the bound event (both can have no namespace). if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || handleObj.handler ).apply( matched.elem, args ); if ( ret !== undefined ) { if ( ( event.result = ret ) === false ) { event.preventDefault(); event.stopPropagation(); } } } } } // Call the postDispatch hook for the mapped type if ( special.postDispatch ) { special.postDispatch.call( this, event ); } return event.result; }, handlers: function( event, handlers ) { var i, handleObj, sel, matchedHandlers, matchedSelectors, handlerQueue = [], delegateCount = handlers.delegateCount, cur = event.target; // Find delegate handlers if ( delegateCount && // Support: IE <=9 // Black-hole SVG instance trees (trac-13180) cur.nodeType && // Support: Firefox <=42 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click // Support: IE 11 only // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) !( event.type === "click" && event.button >= 1 ) ) { for ( ; cur !== this; cur = cur.parentNode || this ) { // Don't check non-elements (#13208) // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { matchedHandlers = []; matchedSelectors = {}; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; // Don't conflict with Object.prototype properties (#13203) sel = handleObj.selector + " "; if ( matchedSelectors[ sel ] === undefined ) { matchedSelectors[ sel ] = handleObj.needsContext ? jQuery( sel, this ).index( cur ) > -1 : jQuery.find( sel, this, null, [ cur ] ).length; } if ( matchedSelectors[ sel ] ) { matchedHandlers.push( handleObj ); } } if ( matchedHandlers.length ) { handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); } } } } // Add the remaining (directly-bound) handlers cur = this; if ( delegateCount < handlers.length ) { handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); } return handlerQueue; }, addProp: function( name, hook ) { Object.defineProperty( jQuery.Event.prototype, name, { enumerable: true, configurable: true, get: isFunction( hook ) ? function() { if ( this.originalEvent ) { return hook( this.originalEvent ); } } : function() { if ( this.originalEvent ) { return this.originalEvent[ name ]; } }, set: function( value ) { Object.defineProperty( this, name, { enumerable: true, configurable: true, writable: true, value: value } ); } } ); }, fix: function( originalEvent ) { return originalEvent[ jQuery.expando ] ? originalEvent : new jQuery.Event( originalEvent ); }, special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== safeActiveElement() && this.focus ) { this.focus(); return false; } }, delegateType: "focusin" }, blur: { trigger: function() { if ( this === safeActiveElement() && this.blur ) { this.blur(); return false; } }, delegateType: "focusout" }, click: { // For checkbox, fire native event so checked state will be right trigger: function() { if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { this.click(); return false; } }, // For cross-browser consistency, don't fire native .click() on links _default: function( event ) { return nodeName( event.target, "a" ); } }, beforeunload: { postDispatch: function( event ) { // Support: Firefox 20+ // Firefox doesn't alert if the returnValue field is not set. if ( event.result !== undefined && event.originalEvent ) { event.originalEvent.returnValue = event.result; } } } } }; jQuery.removeEvent = function( elem, type, handle ) { // This "if" is needed for plain objects if ( elem.removeEventListener ) { elem.removeEventListener( type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !( this instanceof jQuery.Event ) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: Android <=2.3 only src.returnValue === false ? returnTrue : returnFalse; // Create target properties // Support: Safari <=6 - 7 only // Target should not be a text node (#504, #13143) this.target = ( src.target && src.target.nodeType === 3 ) ? src.target.parentNode : src.target; this.currentTarget = src.currentTarget; this.relatedTarget = src.relatedTarget; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || Date.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { constructor: jQuery.Event, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, isSimulated: false, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( e && !this.isSimulated ) { e.preventDefault(); } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( e && !this.isSimulated ) { e.stopPropagation(); } }, stopImmediatePropagation: function() { var e = this.originalEvent; this.isImmediatePropagationStopped = returnTrue; if ( e && !this.isSimulated ) { e.stopImmediatePropagation(); } this.stopPropagation(); } }; // Includes all common event props including KeyEvent and MouseEvent specific props jQuery.each( { altKey: true, bubbles: true, cancelable: true, changedTouches: true, ctrlKey: true, detail: true, eventPhase: true, metaKey: true, pageX: true, pageY: true, shiftKey: true, view: true, "char": true, charCode: true, key: true, keyCode: true, button: true, buttons: true, clientX: true, clientY: true, offsetX: true, offsetY: true, pointerId: true, pointerType: true, screenX: true, screenY: true, targetTouches: true, toElement: true, touches: true, which: function( event ) { var button = event.button; // Add which for key events if ( event.which == null && rkeyEvent.test( event.type ) ) { return event.charCode != null ? event.charCode : event.keyCode; } // Add which for click: 1 === left; 2 === middle; 3 === right if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { if ( button & 1 ) { return 1; } if ( button & 2 ) { return 3; } if ( button & 4 ) { return 2; } return 0; } return event.which; } }, jQuery.event.addProp ); // Create mouseenter/leave events using mouseover/out and event-time checks // so that event delegation works in jQuery. // Do the same for pointerenter/pointerleave and pointerover/pointerout // // Support: Safari 7 only // Safari sends mouseenter too often; see: // https://bugs.chromium.org/p/chromium/issues/detail?id=470258 // for the description of the bug (it existed in older Chrome versions as well). jQuery.each( { mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", pointerleave: "pointerout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var ret, target = this, related = event.relatedTarget, handleObj = event.handleObj; // For mouseenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; } ); jQuery.fn.extend( { on: function( types, selector, data, fn ) { return on( this, types, selector, data, fn ); }, one: function( types, selector, data, fn ) { return on( this, types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { var handleObj, type; if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each( function() { jQuery.event.remove( this, types, fn, selector ); } ); } } ); var /* eslint-disable max-len */ // See https://github.com/eslint/eslint/issues/3229 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, /* eslint-enable */ // Support: IE <=10 - 11, Edge 12 - 13 only // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ rnoInnerhtml = /\s*$/g; // Prefer a tbody over its parent table for containing new rows function manipulationTarget( elem, content ) { if ( nodeName( elem, "table" ) && nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { return jQuery( elem ).children( "tbody" )[ 0 ] || elem; } return elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; return elem; } function restoreScript( elem ) { if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { elem.type = elem.type.slice( 5 ); } else { elem.removeAttribute( "type" ); } return elem; } function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; } // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { pdataOld = dataPriv.access( src ); pdataCur = dataPriv.set( dest, pdataOld ); events = pdataOld.events; if ( events ) { delete pdataCur.handle; pdataCur.events = {}; for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } } // 2. Copy user data if ( dataUser.hasData( src ) ) { udataOld = dataUser.access( src ); udataCur = jQuery.extend( {}, udataOld ); dataUser.set( dest, udataCur ); } } // Fix IE bugs, see support tests function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button. if ( nodeName === "input" && rcheckableType.test( src.type ) ) { dest.checked = src.checked; // Fails to return the selected option to the default selected state when cloning options } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } } function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays args = concat.apply( [], args ); var fragment, first, scripts, hasScripts, node, doc, i = 0, l = collection.length, iNoClone = l - 1, value = args[ 0 ], valueIsFunction = isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit if ( valueIsFunction || ( l > 1 && typeof value === "string" && !support.checkClone && rchecked.test( value ) ) ) { return collection.each( function( index ) { var self = collection.eq( index ); if ( valueIsFunction ) { args[ 0 ] = value.call( this, index, self.html() ); } domManip( self, args, callback, ignored ); } ); } if ( l ) { fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { fragment = first; } // Require either new content or an interest in ignored elements to invoke the callback if ( first || ignored ) { scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); hasScripts = scripts.length; // Use the original fragment for the last item // instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for ( ; i < l; i++ ) { node = fragment; if ( i !== iNoClone ) { node = jQuery.clone( node, true, true ); // Keep references to cloned scripts for later restoration if ( hasScripts ) { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( scripts, getAll( node, "script" ) ); } } callback.call( collection[ i ], node, i ); } if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; // Reenable scripts jQuery.map( scripts, restoreScript ); // Evaluate executable scripts on first document insertion for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && !dataPriv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { // Optional AJAX dependency, but won't run scripts if not present if ( jQuery._evalUrl ) { jQuery._evalUrl( node.src ); } } else { DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); } } } } } } return collection; } function remove( elem, selector, keepData ) { var node, nodes = selector ? jQuery.filter( selector, elem ) : elem, i = 0; for ( ; ( node = nodes[ i ] ) != null; i++ ) { if ( !keepData && node.nodeType === 1 ) { jQuery.cleanData( getAll( node ) ); } if ( node.parentNode ) { if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { setGlobalEval( getAll( node, "script" ) ); } node.parentNode.removeChild( node ); } } return elem; } jQuery.extend( { htmlPrefilter: function( html ) { return html.replace( rxhtmlTag, "<$1>" ); }, clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), inPage = jQuery.contains( elem.ownerDocument, elem ); // Fix IE cloning issues if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); for ( i = 0, l = srcElements.length; i < l; i++ ) { fixInput( srcElements[ i ], destElements[ i ] ); } } // Copy the events from the original to the clone if ( dataAndEvents ) { if ( deepDataAndEvents ) { srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); for ( i = 0, l = srcElements.length; i < l; i++ ) { cloneCopyEvent( srcElements[ i ], destElements[ i ] ); } } else { cloneCopyEvent( elem, clone ); } } // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } // Return the cloned set return clone; }, cleanData: function( elems ) { var data, elem, type, special = jQuery.event.special, i = 0; for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { if ( acceptData( elem ) ) { if ( ( data = elem[ dataPriv.expando ] ) ) { if ( data.events ) { for ( type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } } // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataPriv.expando ] = undefined; } if ( elem[ dataUser.expando ] ) { // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataUser.expando ] = undefined; } } } } } ); jQuery.fn.extend( { detach: function( selector ) { return remove( this, selector, true ); }, remove: function( selector ) { return remove( this, selector ); }, text: function( value ) { return access( this, function( value ) { return value === undefined ? jQuery.text( this ) : this.empty().each( function() { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { this.textContent = value; } } ); }, null, value, arguments.length ); }, append: function() { return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } } ); }, prepend: function() { return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } } ); }, before: function() { return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } } ); }, after: function() { return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } } ); }, empty: function() { var elem, i = 0; for ( ; ( elem = this[ i ] ) != null; i++ ) { if ( elem.nodeType === 1 ) { // Prevent memory leaks jQuery.cleanData( getAll( elem, false ) ); // Remove any remaining nodes elem.textContent = ""; } } return this; }, clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; return this.map( function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); } ); }, html: function( value ) { return access( this, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined && elem.nodeType === 1 ) { return elem.innerHTML; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = jQuery.htmlPrefilter( value ); try { for ( ; i < l; i++ ) { elem = this[ i ] || {}; // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; // If using innerHTML throws an exception, use the fallback method } catch ( e ) {} } if ( elem ) { this.empty().append( value ); } }, null, value, arguments.length ); }, replaceWith: function() { var ignored = []; // Make the changes, replacing each non-ignored context element with the new content return domManip( this, arguments, function( elem ) { var parent = this.parentNode; if ( jQuery.inArray( this, ignored ) < 0 ) { jQuery.cleanData( getAll( this ) ); if ( parent ) { parent.replaceChild( elem, this ); } } // Force callback invocation }, ignored ); } } ); jQuery.each( { appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { var elems, ret = [], insert = jQuery( selector ), last = insert.length - 1, i = 0; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems ); // Support: Android <=4.0 only, PhantomJS 1 only // .get() because push.apply(_, arraylike) throws on ancient WebKit push.apply( ret, elems.get() ); } return this.pushStack( ret ); }; } ); var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); var getStyles = function( elem ) { // Support: IE <=11 only, Firefox <=30 (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" var view = elem.ownerDocument.defaultView; if ( !view || !view.opener ) { view = window; } return view.getComputedStyle( elem ); }; var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); ( function() { // Executing both pixelPosition & boxSizingReliable tests require only one layout // so they're executed at the same time to save the second computation. function computeStyleTests() { // This is a singleton, we need to execute it only once if ( !div ) { return; } container.style.cssText = "position:absolute;left:-11111px;width:60px;" + "margin-top:1px;padding:0;border:0"; div.style.cssText = "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + "margin:auto;border:1px;padding:1px;" + "width:60%;top:1%"; documentElement.appendChild( container ).appendChild( div ); var divStyle = window.getComputedStyle( div ); pixelPositionVal = divStyle.top !== "1%"; // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 // Some styles come back with percentage values, even though they shouldn't div.style.right = "60%"; pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; // Support: IE 9 - 11 only // Detect misreporting of content dimensions for box-sizing:border-box elements boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; // Support: IE 9 only // Detect overflow:scroll screwiness (gh-3699) div.style.position = "absolute"; scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; documentElement.removeChild( container ); // Nullify the div so it wouldn't be stored in the memory and // it will also be a sign that checks already performed div = null; } function roundPixelMeasures( measure ) { return Math.round( parseFloat( measure ) ); } var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, reliableMarginLeftVal, container = document.createElement( "div" ), div = document.createElement( "div" ); // Finish early in limited (non-browser) environments if ( !div.style ) { return; } // Support: IE <=9 - 11 only // Style of cloned element affects source element cloned (#8908) div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; support.clearCloneStyle = div.style.backgroundClip === "content-box"; jQuery.extend( support, { boxSizingReliable: function() { computeStyleTests(); return boxSizingReliableVal; }, pixelBoxStyles: function() { computeStyleTests(); return pixelBoxStylesVal; }, pixelPosition: function() { computeStyleTests(); return pixelPositionVal; }, reliableMarginLeft: function() { computeStyleTests(); return reliableMarginLeftVal; }, scrollboxSize: function() { computeStyleTests(); return scrollboxSizeVal; } } ); } )(); function curCSS( elem, name, computed ) { var width, minWidth, maxWidth, ret, // Support: Firefox 51+ // Retrieving style before computed somehow // fixes an issue with getting wrong values // on detached elements style = elem.style; computed = computed || getStyles( elem ); // getPropertyValue is needed for: // .css('filter') (IE 9 only, #12537) // .css('--customProperty) (#3144) if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // A tribute to the "awesome hack by Dean Edwards" // Android Browser returns percentage for some values, // but width seems to be reliably pixels. // This is against the CSSOM draft spec: // https://drafts.csswg.org/cssom/#resolved-values if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; } } return ret !== undefined ? // Support: IE <=9 - 11 only // IE returns zIndex value as an integer. ret + "" : ret; } function addGetHookIf( conditionFn, hookFn ) { // Define the hook, we'll check on the first run if it's really needed. return { get: function() { if ( conditionFn() ) { // Hook not needed (or it's not possible to use it due // to missing dependency), remove it. delete this.get; return; } // Hook needed; redefine it so that the support test is not executed again. return ( this.get = hookFn ).apply( this, arguments ); } }; } var // Swappable if display is none or starts with table // except "table", "table-cell", or "table-caption" // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, rcustomProp = /^--/, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: "0", fontWeight: "400" }, cssPrefixes = [ "Webkit", "Moz", "ms" ], emptyStyle = document.createElement( "div" ).style; // Return a css property mapped to a potentially vendor prefixed property function vendorPropName( name ) { // Shortcut for names that are not vendor prefixed if ( name in emptyStyle ) { return name; } // Check for vendor prefixed names var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), i = cssPrefixes.length; while ( i-- ) { name = cssPrefixes[ i ] + capName; if ( name in emptyStyle ) { return name; } } } // Return a property mapped along what jQuery.cssProps suggests or to // a vendor prefixed property. function finalPropName( name ) { var ret = jQuery.cssProps[ name ]; if ( !ret ) { ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; } return ret; } function setPositiveNumber( elem, value, subtract ) { // Any relative (+/-) values have already been // normalized at this point var matches = rcssNum.exec( value ); return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : value; } function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { var i = dimension === "width" ? 1 : 0, extra = 0, delta = 0; // Adjustment may not be necessary if ( box === ( isBorderBox ? "border" : "content" ) ) { return 0; } for ( ; i < 4; i += 2 ) { // Both box models exclude margin if ( box === "margin" ) { delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); } // If we get here with a content-box, we're seeking "padding" or "border" or "margin" if ( !isBorderBox ) { // Add padding delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // For "border" or "margin", add border if ( box !== "padding" ) { delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); // But still keep track of it otherwise } else { extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } // If we get here with a border-box (content + padding + border), we're seeking "content" or // "padding" or "margin" } else { // For "content", subtract padding if ( box === "content" ) { delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // For "content" or "padding", subtract border if ( box !== "margin" ) { delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } // Account for positive content-box scroll gutter when requested by providing computedVal if ( !isBorderBox && computedVal >= 0 ) { // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border // Assuming integer scroll gutter, subtract the rest and round down delta += Math.max( 0, Math.ceil( elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - computedVal - delta - extra - 0.5 ) ); } return delta; } function getWidthOrHeight( elem, dimension, extra ) { // Start with computed style var styles = getStyles( elem ), val = curCSS( elem, dimension, styles ), isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", valueIsBorderBox = isBorderBox; // Support: Firefox <=54 // Return a confounding non-pixel value or feign ignorance, as appropriate. if ( rnumnonpx.test( val ) ) { if ( !extra ) { return val; } val = "auto"; } // Check for style in case a browser which returns unreliable values // for getComputedStyle silently falls back to the reliable elem.style valueIsBorderBox = valueIsBorderBox && ( support.boxSizingReliable() || val === elem.style[ dimension ] ); // Fall back to offsetWidth/offsetHeight when value is "auto" // This happens for inline elements with no explicit setting (gh-3571) // Support: Android <=4.1 - 4.3 only // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) if ( val === "auto" || !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; // offsetWidth/offsetHeight provide border-box values valueIsBorderBox = true; } // Normalize "" and auto val = parseFloat( val ) || 0; // Adjust for the element's box model return ( val + boxModelAdjustment( elem, dimension, extra || ( isBorderBox ? "border" : "content" ), valueIsBorderBox, styles, // Provide the current computed size to request scroll gutter calculation (gh-3589) val ) ) + "px"; } jQuery.extend( { // Add in style property hooks for overriding the default // behavior of getting and setting a style property cssHooks: { opacity: { get: function( elem, computed ) { if ( computed ) { // We should always get a number back from opacity var ret = curCSS( elem, "opacity" ); return ret === "" ? "1" : ret; } } } }, // Don't automatically add "px" to these possibly-unitless properties cssNumber: { "animationIterationCount": true, "columnCount": true, "fillOpacity": true, "flexGrow": true, "flexShrink": true, "fontWeight": true, "lineHeight": true, "opacity": true, "order": true, "orphans": true, "widows": true, "zIndex": true, "zoom": true }, // Add in properties whose names you wish to fix before // setting or getting the value cssProps: {}, // Get and set the style property on a DOM Node style: function( elem, name, value, extra ) { // Don't set styles on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } // Make sure that we're working with the right name var ret, type, hooks, origName = camelCase( name ), isCustomProp = rcustomProp.test( name ), style = elem.style; // Make sure that we're working with the right name. We don't // want to query the value if it is a CSS custom property // since they are user-defined. if ( !isCustomProp ) { name = finalPropName( origName ); } // Gets hook for the prefixed version, then unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // Check if we're setting a value if ( value !== undefined ) { type = typeof value; // Convert "+=" or "-=" to relative numbers (#7345) if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { value = adjustCSS( elem, name, ret ); // Fixes bug #9237 type = "number"; } // Make sure that null and NaN values aren't set (#7116) if ( value == null || value !== value ) { return; } // If a number was passed in, add the unit (except for certain CSS properties) if ( type === "number" ) { value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); } // background-* props affect original clone's values if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { style[ name ] = "inherit"; } // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !( "set" in hooks ) || ( value = hooks.set( elem, value, extra ) ) !== undefined ) { if ( isCustomProp ) { style.setProperty( name, value ); } else { style[ name ] = value; } } } else { // If a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { return ret; } // Otherwise just get the value from the style object return style[ name ]; } }, css: function( elem, name, extra, styles ) { var val, num, hooks, origName = camelCase( name ), isCustomProp = rcustomProp.test( name ); // Make sure that we're working with the right name. We don't // want to modify the value if it is a CSS custom property // since they are user-defined. if ( !isCustomProp ) { name = finalPropName( origName ); } // Try prefixed name followed by the unprefixed name hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { val = curCSS( elem, name, styles ); } // Convert "normal" to computed value if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // Make numeric if forced or a qualifier was provided and val looks numeric if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || isFinite( num ) ? num || 0 : val; } return val; } } ); jQuery.each( [ "height", "width" ], function( i, dimension ) { jQuery.cssHooks[ dimension ] = { get: function( elem, computed, extra ) { if ( computed ) { // Certain elements can have dimension info if we invisibly show them // but it must have a current display style that would benefit return rdisplayswap.test( jQuery.css( elem, "display" ) ) && // Support: Safari 8+ // Table columns in Safari have non-zero offsetWidth & zero // getBoundingClientRect().width unless display is changed. // Support: IE <=11 only // Running getBoundingClientRect on a disconnected node // in IE throws an error. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? swap( elem, cssShow, function() { return getWidthOrHeight( elem, dimension, extra ); } ) : getWidthOrHeight( elem, dimension, extra ); } }, set: function( elem, value, extra ) { var matches, styles = getStyles( elem ), isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", subtract = extra && boxModelAdjustment( elem, dimension, extra, isBorderBox, styles ); // Account for unreliable border-box dimensions by comparing offset* to computed and // faking a content-box to get border and padding (gh-3699) if ( isBorderBox && support.scrollboxSize() === styles.position ) { subtract -= Math.ceil( elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - parseFloat( styles[ dimension ] ) - boxModelAdjustment( elem, dimension, "border", false, styles ) - 0.5 ); } // Convert to pixels if value adjustment is needed if ( subtract && ( matches = rcssNum.exec( value ) ) && ( matches[ 3 ] || "px" ) !== "px" ) { elem.style[ dimension ] = value; value = jQuery.css( elem, dimension ); } return setPositiveNumber( elem, value, subtract ); } }; } ); jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, function( elem, computed ) { if ( computed ) { return ( parseFloat( curCSS( elem, "marginLeft" ) ) || elem.getBoundingClientRect().left - swap( elem, { marginLeft: 0 }, function() { return elem.getBoundingClientRect().left; } ) ) + "px"; } } ); // These hooks are used by animate to expand properties jQuery.each( { margin: "", padding: "", border: "Width" }, function( prefix, suffix ) { jQuery.cssHooks[ prefix + suffix ] = { expand: function( value ) { var i = 0, expanded = {}, // Assumes a single number if not a string parts = typeof value === "string" ? value.split( " " ) : [ value ]; for ( ; i < 4; i++ ) { expanded[ prefix + cssExpand[ i ] + suffix ] = parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; } return expanded; } }; if ( prefix !== "margin" ) { jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; } } ); jQuery.fn.extend( { css: function( name, value ) { return access( this, function( elem, name, value ) { var styles, len, map = {}, i = 0; if ( Array.isArray( name ) ) { styles = getStyles( elem ); len = name.length; for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); } return map; } return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); } } ); function Tween( elem, options, prop, end, easing ) { return new Tween.prototype.init( elem, options, prop, end, easing ); } jQuery.Tween = Tween; Tween.prototype = { constructor: Tween, init: function( elem, options, prop, end, easing, unit ) { this.elem = elem; this.prop = prop; this.easing = easing || jQuery.easing._default; this.options = options; this.start = this.now = this.cur(); this.end = end; this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); }, cur: function() { var hooks = Tween.propHooks[ this.prop ]; return hooks && hooks.get ? hooks.get( this ) : Tween.propHooks._default.get( this ); }, run: function( percent ) { var eased, hooks = Tween.propHooks[ this.prop ]; if ( this.options.duration ) { this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration ); } else { this.pos = eased = percent; } this.now = ( this.end - this.start ) * eased + this.start; if ( this.options.step ) { this.options.step.call( this.elem, this.now, this ); } if ( hooks && hooks.set ) { hooks.set( this ); } else { Tween.propHooks._default.set( this ); } return this; } }; Tween.prototype.init.prototype = Tween.prototype; Tween.propHooks = { _default: { get: function( tween ) { var result; // Use a property on the element directly when it is not a DOM element, // or when there is no matching style property that exists. if ( tween.elem.nodeType !== 1 || tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { return tween.elem[ tween.prop ]; } // Passing an empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails. // Simple values such as "10px" are parsed to Float; // complex values such as "rotate(1rad)" are returned as-is. result = jQuery.css( tween.elem, tween.prop, "" ); // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === "auto" ? 0 : result; }, set: function( tween ) { // Use step hook for back compat. // Use cssHook if its there. // Use .style if available and use plain properties where available. if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.nodeType === 1 && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; } } } }; // Support: IE <=9 only // Panic based approach to setting things on disconnected nodes Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { set: function( tween ) { if ( tween.elem.nodeType && tween.elem.parentNode ) { tween.elem[ tween.prop ] = tween.now; } } }; jQuery.easing = { linear: function( p ) { return p; }, swing: function( p ) { return 0.5 - Math.cos( p * Math.PI ) / 2; }, _default: "swing" }; jQuery.fx = Tween.prototype.init; // Back compat <1.8 extension point jQuery.fx.step = {}; var fxNow, inProgress, rfxtypes = /^(?:toggle|show|hide)$/, rrun = /queueHooks$/; function schedule() { if ( inProgress ) { if ( document.hidden === false && window.requestAnimationFrame ) { window.requestAnimationFrame( schedule ); } else { window.setTimeout( schedule, jQuery.fx.interval ); } jQuery.fx.tick(); } } // Animations created synchronously will run synchronously function createFxNow() { window.setTimeout( function() { fxNow = undefined; } ); return ( fxNow = Date.now() ); } // Generate parameters to create a standard animation function genFx( type, includeWidth ) { var which, i = 0, attrs = { height: type }; // If we include width, step value is 1 to do all cssExpand values, // otherwise step value is 2 to skip over Left and Right includeWidth = includeWidth ? 1 : 0; for ( ; i < 4; i += 2 - includeWidth ) { which = cssExpand[ i ]; attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; } if ( includeWidth ) { attrs.opacity = attrs.width = type; } return attrs; } function createTween( value, prop, animation ) { var tween, collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), index = 0, length = collection.length; for ( ; index < length; index++ ) { if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { // We're done with this property return tween; } } } function defaultPrefilter( elem, props, opts ) { var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, isBox = "width" in props || "height" in props, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHiddenWithinTree( elem ), dataShow = dataPriv.get( elem, "fxshow" ); // Queue-skipping animations hijack the fx hooks if ( !opts.queue ) { hooks = jQuery._queueHooks( elem, "fx" ); if ( hooks.unqueued == null ) { hooks.unqueued = 0; oldfire = hooks.empty.fire; hooks.empty.fire = function() { if ( !hooks.unqueued ) { oldfire(); } }; } hooks.unqueued++; anim.always( function() { // Ensure the complete handler is called before this completes anim.always( function() { hooks.unqueued--; if ( !jQuery.queue( elem, "fx" ).length ) { hooks.empty.fire(); } } ); } ); } // Detect show/hide animations for ( prop in props ) { value = props[ prop ]; if ( rfxtypes.test( value ) ) { delete props[ prop ]; toggle = toggle || value === "toggle"; if ( value === ( hidden ? "hide" : "show" ) ) { // Pretend to be hidden if this is a "show" and // there is still data from a stopped show/hide if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { hidden = true; // Ignore all other no-op show/hide data } else { continue; } } orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); } } // Bail out if this is a no-op like .hide().hide() propTween = !jQuery.isEmptyObject( props ); if ( !propTween && jQuery.isEmptyObject( orig ) ) { return; } // Restrict "overflow" and "display" styles during box animations if ( isBox && elem.nodeType === 1 ) { // Support: IE <=9 - 11, Edge 12 - 15 // Record all 3 overflow attributes because IE does not infer the shorthand // from identically-valued overflowX and overflowY and Edge just mirrors // the overflowX value there. opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; // Identify a display type, preferring old show/hide data over the CSS cascade restoreDisplay = dataShow && dataShow.display; if ( restoreDisplay == null ) { restoreDisplay = dataPriv.get( elem, "display" ); } display = jQuery.css( elem, "display" ); if ( display === "none" ) { if ( restoreDisplay ) { display = restoreDisplay; } else { // Get nonempty value(s) by temporarily forcing visibility showHide( [ elem ], true ); restoreDisplay = elem.style.display || restoreDisplay; display = jQuery.css( elem, "display" ); showHide( [ elem ] ); } } // Animate inline elements as inline-block if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { if ( jQuery.css( elem, "float" ) === "none" ) { // Restore the original display value at the end of pure show/hide animations if ( !propTween ) { anim.done( function() { style.display = restoreDisplay; } ); if ( restoreDisplay == null ) { display = style.display; restoreDisplay = display === "none" ? "" : display; } } style.display = "inline-block"; } } } if ( opts.overflow ) { style.overflow = "hidden"; anim.always( function() { style.overflow = opts.overflow[ 0 ]; style.overflowX = opts.overflow[ 1 ]; style.overflowY = opts.overflow[ 2 ]; } ); } // Implement show/hide animations propTween = false; for ( prop in orig ) { // General show/hide setup for this element animation if ( !propTween ) { if ( dataShow ) { if ( "hidden" in dataShow ) { hidden = dataShow.hidden; } } else { dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); } // Store hidden/visible for toggle so `.stop().toggle()` "reverses" if ( toggle ) { dataShow.hidden = !hidden; } // Show elements before animating them if ( hidden ) { showHide( [ elem ], true ); } /* eslint-disable no-loop-func */ anim.done( function() { /* eslint-enable no-loop-func */ // The final step of a "hide" animation is actually hiding the element if ( !hidden ) { showHide( [ elem ] ); } dataPriv.remove( elem, "fxshow" ); for ( prop in orig ) { jQuery.style( elem, prop, orig[ prop ] ); } } ); } // Per-property setup propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); if ( !( prop in dataShow ) ) { dataShow[ prop ] = propTween.start; if ( hidden ) { propTween.end = propTween.start; propTween.start = 0; } } } } function propFilter( props, specialEasing ) { var index, name, easing, value, hooks; // camelCase, specialEasing and expand cssHook pass for ( index in props ) { name = camelCase( index ); easing = specialEasing[ name ]; value = props[ index ]; if ( Array.isArray( value ) ) { easing = value[ 1 ]; value = props[ index ] = value[ 0 ]; } if ( index !== name ) { props[ name ] = value; delete props[ index ]; } hooks = jQuery.cssHooks[ name ]; if ( hooks && "expand" in hooks ) { value = hooks.expand( value ); delete props[ name ]; // Not quite $.extend, this won't overwrite existing keys. // Reusing 'index' because we have the correct "name" for ( index in value ) { if ( !( index in props ) ) { props[ index ] = value[ index ]; specialEasing[ index ] = easing; } } } else { specialEasing[ name ] = easing; } } } function Animation( elem, properties, options ) { var result, stopped, index = 0, length = Animation.prefilters.length, deferred = jQuery.Deferred().always( function() { // Don't match elem in the :animated selector delete tick.elem; } ), tick = function() { if ( stopped ) { return false; } var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), // Support: Android 2.3 only // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) temp = remaining / animation.duration || 0, percent = 1 - temp, index = 0, length = animation.tweens.length; for ( ; index < length; index++ ) { animation.tweens[ index ].run( percent ); } deferred.notifyWith( elem, [ animation, percent, remaining ] ); // If there's more to do, yield if ( percent < 1 && length ) { return remaining; } // If this was an empty animation, synthesize a final progress notification if ( !length ) { deferred.notifyWith( elem, [ animation, 1, 0 ] ); } // Resolve the animation and report its conclusion deferred.resolveWith( elem, [ animation ] ); return false; }, animation = deferred.promise( { elem: elem, props: jQuery.extend( {}, properties ), opts: jQuery.extend( true, { specialEasing: {}, easing: jQuery.easing._default }, options ), originalProperties: properties, originalOptions: options, startTime: fxNow || createFxNow(), duration: options.duration, tweens: [], createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); return tween; }, stop: function( gotoEnd ) { var index = 0, // If we are going to the end, we want to run all the tweens // otherwise we skip this part length = gotoEnd ? animation.tweens.length : 0; if ( stopped ) { return this; } stopped = true; for ( ; index < length; index++ ) { animation.tweens[ index ].run( 1 ); } // Resolve when we played the last frame; otherwise, reject if ( gotoEnd ) { deferred.notifyWith( elem, [ animation, 1, 0 ] ); deferred.resolveWith( elem, [ animation, gotoEnd ] ); } else { deferred.rejectWith( elem, [ animation, gotoEnd ] ); } return this; } } ), props = animation.props; propFilter( props, animation.opts.specialEasing ); for ( ; index < length; index++ ) { result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); if ( result ) { if ( isFunction( result.stop ) ) { jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = result.stop.bind( result ); } return result; } } jQuery.map( props, createTween, animation ); if ( isFunction( animation.opts.start ) ) { animation.opts.start.call( elem, animation ); } // Attach callbacks from options animation .progress( animation.opts.progress ) .done( animation.opts.done, animation.opts.complete ) .fail( animation.opts.fail ) .always( animation.opts.always ); jQuery.fx.timer( jQuery.extend( tick, { elem: elem, anim: animation, queue: animation.opts.queue } ) ); return animation; } jQuery.Animation = jQuery.extend( Animation, { tweeners: { "*": [ function( prop, value ) { var tween = this.createTween( prop, value ); adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); return tween; } ] }, tweener: function( props, callback ) { if ( isFunction( props ) ) { callback = props; props = [ "*" ]; } else { props = props.match( rnothtmlwhite ); } var prop, index = 0, length = props.length; for ( ; index < length; index++ ) { prop = props[ index ]; Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; Animation.tweeners[ prop ].unshift( callback ); } }, prefilters: [ defaultPrefilter ], prefilter: function( callback, prepend ) { if ( prepend ) { Animation.prefilters.unshift( callback ); } else { Animation.prefilters.push( callback ); } } } ); jQuery.speed = function( speed, easing, fn ) { var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { complete: fn || !fn && easing || isFunction( speed ) && speed, duration: speed, easing: fn && easing || easing && !isFunction( easing ) && easing }; // Go to the end state if fx are off if ( jQuery.fx.off ) { opt.duration = 0; } else { if ( typeof opt.duration !== "number" ) { if ( opt.duration in jQuery.fx.speeds ) { opt.duration = jQuery.fx.speeds[ opt.duration ]; } else { opt.duration = jQuery.fx.speeds._default; } } } // Normalize opt.queue - true/undefined/null -> "fx" if ( opt.queue == null || opt.queue === true ) { opt.queue = "fx"; } // Queueing opt.old = opt.complete; opt.complete = function() { if ( isFunction( opt.old ) ) { opt.old.call( this ); } if ( opt.queue ) { jQuery.dequeue( this, opt.queue ); } }; return opt; }; jQuery.fn.extend( { fadeTo: function( speed, to, easing, callback ) { // Show any hidden elements after setting opacity to 0 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() // Animate to the value specified .end().animate( { opacity: to }, speed, easing, callback ); }, animate: function( prop, speed, easing, callback ) { var empty = jQuery.isEmptyObject( prop ), optall = jQuery.speed( speed, easing, callback ), doAnimation = function() { // Operate on a copy of prop so per-property easing won't be lost var anim = Animation( this, jQuery.extend( {}, prop ), optall ); // Empty animations, or finishing resolves immediately if ( empty || dataPriv.get( this, "finish" ) ) { anim.stop( true ); } }; doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : this.queue( optall.queue, doAnimation ); }, stop: function( type, clearQueue, gotoEnd ) { var stopQueue = function( hooks ) { var stop = hooks.stop; delete hooks.stop; stop( gotoEnd ); }; if ( typeof type !== "string" ) { gotoEnd = clearQueue; clearQueue = type; type = undefined; } if ( clearQueue && type !== false ) { this.queue( type || "fx", [] ); } return this.each( function() { var dequeue = true, index = type != null && type + "queueHooks", timers = jQuery.timers, data = dataPriv.get( this ); if ( index ) { if ( data[ index ] && data[ index ].stop ) { stopQueue( data[ index ] ); } } else { for ( index in data ) { if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { stopQueue( data[ index ] ); } } } for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && ( type == null || timers[ index ].queue === type ) ) { timers[ index ].anim.stop( gotoEnd ); dequeue = false; timers.splice( index, 1 ); } } // Start the next in the queue if the last step wasn't forced. // Timers currently will call their complete callbacks, which // will dequeue but only if they were gotoEnd. if ( dequeue || !gotoEnd ) { jQuery.dequeue( this, type ); } } ); }, finish: function( type ) { if ( type !== false ) { type = type || "fx"; } return this.each( function() { var index, data = dataPriv.get( this ), queue = data[ type + "queue" ], hooks = data[ type + "queueHooks" ], timers = jQuery.timers, length = queue ? queue.length : 0; // Enable finishing flag on private data data.finish = true; // Empty the queue first jQuery.queue( this, type, [] ); if ( hooks && hooks.stop ) { hooks.stop.call( this, true ); } // Look for any active animations, and finish them for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && timers[ index ].queue === type ) { timers[ index ].anim.stop( true ); timers.splice( index, 1 ); } } // Look for any animations in the old queue and finish them for ( index = 0; index < length; index++ ) { if ( queue[ index ] && queue[ index ].finish ) { queue[ index ].finish.call( this ); } } // Turn off finishing flag delete data.finish; } ); } } ); jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { return speed == null || typeof speed === "boolean" ? cssFn.apply( this, arguments ) : this.animate( genFx( name, true ), speed, easing, callback ); }; } ); // Generate shortcuts for custom animations jQuery.each( { slideDown: genFx( "show" ), slideUp: genFx( "hide" ), slideToggle: genFx( "toggle" ), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function( name, props ) { jQuery.fn[ name ] = function( speed, easing, callback ) { return this.animate( props, speed, easing, callback ); }; } ); jQuery.timers = []; jQuery.fx.tick = function() { var timer, i = 0, timers = jQuery.timers; fxNow = Date.now(); for ( ; i < timers.length; i++ ) { timer = timers[ i ]; // Run the timer and safely remove it when done (allowing for external removal) if ( !timer() && timers[ i ] === timer ) { timers.splice( i--, 1 ); } } if ( !timers.length ) { jQuery.fx.stop(); } fxNow = undefined; }; jQuery.fx.timer = function( timer ) { jQuery.timers.push( timer ); jQuery.fx.start(); }; jQuery.fx.interval = 13; jQuery.fx.start = function() { if ( inProgress ) { return; } inProgress = true; schedule(); }; jQuery.fx.stop = function() { inProgress = null; }; jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400 }; // Based off of the plugin by Clint Helfers, with permission. // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ jQuery.fn.delay = function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = window.setTimeout( next, time ); hooks.stop = function() { window.clearTimeout( timeout ); }; } ); }; ( function() { var input = document.createElement( "input" ), select = document.createElement( "select" ), opt = select.appendChild( document.createElement( "option" ) ); input.type = "checkbox"; // Support: Android <=4.3 only // Default value for a checkbox should be "on" support.checkOn = input.value !== ""; // Support: IE <=11 only // Must access selectedIndex to make default options select support.optSelected = opt.selected; // Support: IE <=11 only // An input loses its value after becoming a radio input = document.createElement( "input" ); input.value = "t"; input.type = "radio"; support.radioValue = input.value === "t"; } )(); var boolHook, attrHandle = jQuery.expr.attrHandle; jQuery.fn.extend( { attr: function( name, value ) { return access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each( function() { jQuery.removeAttr( this, name ); } ); } } ); jQuery.extend( { attr: function( elem, name, value ) { var ret, hooks, nType = elem.nodeType; // Don't get/set attributes on text, comment and attribute nodes if ( nType === 3 || nType === 8 || nType === 2 ) { return; } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } // Attribute hooks are determined by the lowercase version // Grab necessary hook if one is defined if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { hooks = jQuery.attrHooks[ name.toLowerCase() ] || ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return; } if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } elem.setAttribute( name, value + "" ); return value; } if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret; }, attrHooks: { type: { set: function( elem, value ) { if ( !support.radioValue && value === "radio" && nodeName( elem, "input" ) ) { var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } } }, removeAttr: function( elem, value ) { var name, i = 0, // Attribute names can contain non-HTML whitespace characters // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 attrNames = value && value.match( rnothtmlwhite ); if ( attrNames && elem.nodeType === 1 ) { while ( ( name = attrNames[ i++ ] ) ) { elem.removeAttribute( name ); } } } } ); // Hooks for boolean attributes boolHook = { set: function( elem, value, name ) { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { elem.setAttribute( name, name ); } return name; } }; jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { var getter = attrHandle[ name ] || jQuery.find.attr; attrHandle[ name ] = function( elem, name, isXML ) { var ret, handle, lowercaseName = name.toLowerCase(); if ( !isXML ) { // Avoid an infinite loop by temporarily removing this function from the getter handle = attrHandle[ lowercaseName ]; attrHandle[ lowercaseName ] = ret; ret = getter( elem, name, isXML ) != null ? lowercaseName : null; attrHandle[ lowercaseName ] = handle; } return ret; }; } ); var rfocusable = /^(?:input|select|textarea|button)$/i, rclickable = /^(?:a|area)$/i; jQuery.fn.extend( { prop: function( name, value ) { return access( this, jQuery.prop, name, value, arguments.length > 1 ); }, removeProp: function( name ) { return this.each( function() { delete this[ jQuery.propFix[ name ] || name ]; } ); } } ); jQuery.extend( { prop: function( elem, name, value ) { var ret, hooks, nType = elem.nodeType; // Don't get/set properties on text, comment and attribute nodes if ( nType === 3 || nType === 8 || nType === 2 ) { return; } if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } return ( elem[ name ] = value ); } if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } return elem[ name ]; }, propHooks: { tabIndex: { get: function( elem ) { // Support: IE <=9 - 11 only // elem.tabIndex doesn't always return the // correct value when it hasn't been explicitly set // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ // Use proper attribute retrieval(#12072) var tabindex = jQuery.find.attr( elem, "tabindex" ); if ( tabindex ) { return parseInt( tabindex, 10 ); } if ( rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ) { return 0; } return -1; } } }, propFix: { "for": "htmlFor", "class": "className" } } ); // Support: IE <=11 only // Accessing the selectedIndex property // forces the browser to respect setting selected // on the option // The getter ensures a default option is selected // when in an optgroup // eslint rule "no-unused-expressions" is disabled for this code // since it considers such accessions noop if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { /* eslint no-unused-expressions: "off" */ var parent = elem.parentNode; if ( parent && parent.parentNode ) { parent.parentNode.selectedIndex; } return null; }, set: function( elem ) { /* eslint no-unused-expressions: "off" */ var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } } }; } jQuery.each( [ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; } ); // Strip and collapse whitespace according to HTML spec // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace function stripAndCollapse( value ) { var tokens = value.match( rnothtmlwhite ) || []; return tokens.join( " " ); } function getClass( elem ) { return elem.getAttribute && elem.getAttribute( "class" ) || ""; } function classesToArray( value ) { if ( Array.isArray( value ) ) { return value; } if ( typeof value === "string" ) { return value.match( rnothtmlwhite ) || []; } return []; } jQuery.fn.extend( { addClass: function( value ) { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; if ( isFunction( value ) ) { return this.each( function( j ) { jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); } ); } classes = classesToArray( value ); if ( classes.length ) { while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { j = 0; while ( ( clazz = classes[ j++ ] ) ) { if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { elem.setAttribute( "class", finalValue ); } } } } return this; }, removeClass: function( value ) { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; if ( isFunction( value ) ) { return this.each( function( j ) { jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); } ); } if ( !arguments.length ) { return this.attr( "class", "" ); } classes = classesToArray( value ); if ( classes.length ) { while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); // This expression is here for better compressibility (see addClass) cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { j = 0; while ( ( clazz = classes[ j++ ] ) ) { // Remove *all* instances while ( cur.indexOf( " " + clazz + " " ) > -1 ) { cur = cur.replace( " " + clazz + " ", " " ); } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { elem.setAttribute( "class", finalValue ); } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isValidValue = type === "string" || Array.isArray( value ); if ( typeof stateVal === "boolean" && isValidValue ) { return stateVal ? this.addClass( value ) : this.removeClass( value ); } if ( isFunction( value ) ) { return this.each( function( i ) { jQuery( this ).toggleClass( value.call( this, i, getClass( this ), stateVal ), stateVal ); } ); } return this.each( function() { var className, i, self, classNames; if ( isValidValue ) { // Toggle individual class names i = 0; self = jQuery( this ); classNames = classesToArray( value ); while ( ( className = classNames[ i++ ] ) ) { // Check each className given, space separated list if ( self.hasClass( className ) ) { self.removeClass( className ); } else { self.addClass( className ); } } // Toggle whole class name } else if ( value === undefined || type === "boolean" ) { className = getClass( this ); if ( className ) { // Store className if set dataPriv.set( this, "__className__", className ); } // If the element has a class name or if we're passed `false`, // then remove the whole classname (if there was one, the above saved it). // Otherwise bring back whatever was previously saved (if anything), // falling back to the empty string if nothing was stored. if ( this.setAttribute ) { this.setAttribute( "class", className || value === false ? "" : dataPriv.get( this, "__className__" ) || "" ); } } } ); }, hasClass: function( selector ) { var className, elem, i = 0; className = " " + selector + " "; while ( ( elem = this[ i++ ] ) ) { if ( elem.nodeType === 1 && ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { return true; } } return false; } } ); var rreturn = /\r/g; jQuery.fn.extend( { val: function( value ) { var hooks, ret, valueIsFunction, elem = this[ 0 ]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; if ( hooks && "get" in hooks && ( ret = hooks.get( elem, "value" ) ) !== undefined ) { return ret; } ret = elem.value; // Handle most common string cases if ( typeof ret === "string" ) { return ret.replace( rreturn, "" ); } // Handle cases where value is null/undef or number return ret == null ? "" : ret; } return; } valueIsFunction = isFunction( value ); return this.each( function( i ) { var val; if ( this.nodeType !== 1 ) { return; } if ( valueIsFunction ) { val = value.call( this, i, jQuery( this ).val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( Array.isArray( val ) ) { val = jQuery.map( val, function( value ) { return value == null ? "" : value + ""; } ); } hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // If set returns undefined, fall back to normal setting if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } } ); } } ); jQuery.extend( { valHooks: { option: { get: function( elem ) { var val = jQuery.find.attr( elem, "value" ); return val != null ? val : // Support: IE <=10 - 11 only // option.text throws exceptions (#14686, #14858) // Strip and collapse whitespace // https://html.spec.whatwg.org/#strip-and-collapse-whitespace stripAndCollapse( jQuery.text( elem ) ); } }, select: { get: function( elem ) { var value, option, i, options = elem.options, index = elem.selectedIndex, one = elem.type === "select-one", values = one ? null : [], max = one ? index + 1 : options.length; if ( index < 0 ) { i = max; } else { i = one ? index : 0; } // Loop through all the selected options for ( ; i < max; i++ ) { option = options[ i ]; // Support: IE <=9 only // IE8-9 doesn't update selected after form reset (#2551) if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup !option.disabled && ( !option.parentNode.disabled || !nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } return values; }, set: function( elem, value ) { var optionSet, option, options = elem.options, values = jQuery.makeArray( value ), i = options.length; while ( i-- ) { option = options[ i ]; /* eslint-disable no-cond-assign */ if ( option.selected = jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 ) { optionSet = true; } /* eslint-enable no-cond-assign */ } // Force browsers to behave consistently when non-matching value is set if ( !optionSet ) { elem.selectedIndex = -1; } return values; } } } } ); // Radios and checkboxes getter/setter jQuery.each( [ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { set: function( elem, value ) { if ( Array.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); } } }; if ( !support.checkOn ) { jQuery.valHooks[ this ].get = function( elem ) { return elem.getAttribute( "value" ) === null ? "on" : elem.value; }; } } ); // Return jQuery for attributes-only inclusion support.focusin = "onfocusin" in window; var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, stopPropagationCallback = function( e ) { e.stopPropagation(); }; jQuery.extend( jQuery.event, { trigger: function( event, data, elem, onlyHandlers ) { var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, eventPath = [ elem || document ], type = hasOwn.call( event, "type" ) ? event.type : event, namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; cur = lastElement = tmp = elem = elem || document; // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf( "." ) > -1 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split( "." ); type = namespaces.shift(); namespaces.sort(); } ontype = type.indexOf( ":" ) < 0 && "on" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[ jQuery.expando ] ? event : new jQuery.Event( type, typeof event === "object" && event ); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3; event.namespace = namespaces.join( "." ); event.rnamespace = event.namespace ? new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : null; // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ? [ event ] : jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { bubbleType = special.delegateType || type; if ( !rfocusMorph.test( bubbleType + type ) ) { cur = cur.parentNode; } for ( ; cur; cur = cur.parentNode ) { eventPath.push( cur ); tmp = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( tmp === ( elem.ownerDocument || document ) ) { eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path i = 0; while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { lastElement = cur; event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Native handler handle = ontype && cur[ ontype ]; if ( handle && handle.apply && acceptData( cur ) ) { event.result = handle.apply( cur, data ); if ( event.result === false ) { event.preventDefault(); } } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( ( !special._default || special._default.apply( eventPath.pop(), data ) === false ) && acceptData( elem ) ) { // Call a native DOM method on the target with the same name as the event. // Don't do default actions on window, that's where global variables be (#6170) if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ ontype ]; if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; if ( event.isPropagationStopped() ) { lastElement.addEventListener( type, stopPropagationCallback ); } elem[ type ](); if ( event.isPropagationStopped() ) { lastElement.removeEventListener( type, stopPropagationCallback ); } jQuery.event.triggered = undefined; if ( tmp ) { elem[ ontype ] = tmp; } } } } return event.result; }, // Piggyback on a donor event to simulate a different one // Used only for `focus(in | out)` events simulate: function( type, elem, event ) { var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true } ); jQuery.event.trigger( e, null, elem ); } } ); jQuery.fn.extend( { trigger: function( type, data ) { return this.each( function() { jQuery.event.trigger( type, data, this ); } ); }, triggerHandler: function( type, data ) { var elem = this[ 0 ]; if ( elem ) { return jQuery.event.trigger( type, data, elem, true ); } } } ); // Support: Firefox <=44 // Firefox doesn't have focus(in | out) events // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 // // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 // focus(in | out) events fire after focus & blur events, // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 if ( !support.focusin ) { jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler on the document while someone wants focusin/focusout var handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); }; jQuery.event.special[ fix ] = { setup: function() { var doc = this.ownerDocument || this, attaches = dataPriv.access( doc, fix ); if ( !attaches ) { doc.addEventListener( orig, handler, true ); } dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); }, teardown: function() { var doc = this.ownerDocument || this, attaches = dataPriv.access( doc, fix ) - 1; if ( !attaches ) { doc.removeEventListener( orig, handler, true ); dataPriv.remove( doc, fix ); } else { dataPriv.access( doc, fix, attaches ); } } }; } ); } var location = window.location; var nonce = Date.now(); var rquery = ( /\?/ ); // Cross-browser xml parsing jQuery.parseXML = function( data ) { var xml; if ( !data || typeof data !== "string" ) { return null; } // Support: IE 9 - 11 only // IE throws on parseFromString with invalid input. try { xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); } catch ( e ) { xml = undefined; } if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }; var rbracket = /\[\]$/, rCRLF = /\r?\n/g, rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, rsubmittable = /^(?:input|select|textarea|keygen)/i; function buildParams( prefix, obj, traditional, add ) { var name; if ( Array.isArray( obj ) ) { // Serialize array item. jQuery.each( obj, function( i, v ) { if ( traditional || rbracket.test( prefix ) ) { // Treat each array item as a scalar. add( prefix, v ); } else { // Item is non-scalar (array or object), encode its numeric index. buildParams( prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", v, traditional, add ); } } ); } else if ( !traditional && toType( obj ) === "object" ) { // Serialize object item. for ( name in obj ) { buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); } } else { // Serialize scalar item. add( prefix, obj ); } } // Serialize an array of form elements or a set of // key/values into a query string jQuery.param = function( a, traditional ) { var prefix, s = [], add = function( key, valueOrFunction ) { // If value is a function, invoke it and use its return value var value = isFunction( valueOrFunction ) ? valueOrFunction() : valueOrFunction; s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value == null ? "" : value ); }; // If an array was passed in, assume that it is an array of form elements. if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { // Serialize the form elements jQuery.each( a, function() { add( this.name, this.value ); } ); } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for ( prefix in a ) { buildParams( prefix, a[ prefix ], traditional, add ); } } // Return the resulting serialization return s.join( "&" ); }; jQuery.fn.extend( { serialize: function() { return jQuery.param( this.serializeArray() ); }, serializeArray: function() { return this.map( function() { // Can add propHook for "elements" to filter or add form elements var elements = jQuery.prop( this, "elements" ); return elements ? jQuery.makeArray( elements ) : this; } ) .filter( function() { var type = this.type; // Use .is( ":disabled" ) so that fieldset[disabled] works return this.name && !jQuery( this ).is( ":disabled" ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); } ) .map( function( i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { return null; } if ( Array.isArray( val ) ) { return jQuery.map( val, function( val ) { return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; } ); } return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; } ).get(); } } ); var r20 = /%20/g, rhash = /#.*$/, rantiCache = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, // #7653, #8125, #8152: local protocol detection rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, /* Prefilters * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) * 2) These are called: * - BEFORE asking for a transport * - AFTER param serialization (s.data is a string if s.processData is true) * 3) key is the dataType * 4) the catchall symbol "*" can be used * 5) execution will start with transport dataType and THEN continue down to "*" if needed */ prefilters = {}, /* Transports bindings * 1) key is the dataType * 2) the catchall symbol "*" can be used * 3) selection will start with transport dataType and THEN go to "*" if needed */ transports = {}, // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression allTypes = "*/".concat( "*" ), // Anchor tag for parsing the document origin originAnchor = document.createElement( "a" ); originAnchor.href = location.href; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { // dataTypeExpression is optional and defaults to "*" return function( dataTypeExpression, func ) { if ( typeof dataTypeExpression !== "string" ) { func = dataTypeExpression; dataTypeExpression = "*"; } var dataType, i = 0, dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; if ( isFunction( func ) ) { // For each dataType in the dataTypeExpression while ( ( dataType = dataTypes[ i++ ] ) ) { // Prepend if requested if ( dataType[ 0 ] === "+" ) { dataType = dataType.slice( 1 ) || "*"; ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); // Otherwise append } else { ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); } } } }; } // Base inspection function for prefilters and transports function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { var inspected = {}, seekingTransport = ( structure === transports ); function inspect( dataType ) { var selected; inspected[ dataType ] = true; jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { options.dataTypes.unshift( dataTypeOrTransport ); inspect( dataTypeOrTransport ); return false; } else if ( seekingTransport ) { return !( selected = dataTypeOrTransport ); } } ); return selected; } return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); } // A special extend for ajax options // that takes "flat" options (not to be deep extended) // Fixes #9887 function ajaxExtend( target, src ) { var key, deep, flatOptions = jQuery.ajaxSettings.flatOptions || {}; for ( key in src ) { if ( src[ key ] !== undefined ) { ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; } } if ( deep ) { jQuery.extend( true, target, deep ); } return target; } /* Handles responses to an ajax request: * - finds the right dataType (mediates between content-type and expected dataType) * - returns the corresponding response */ function ajaxHandleResponses( s, jqXHR, responses ) { var ct, type, finalDataType, firstDataType, contents = s.contents, dataTypes = s.dataTypes; // Remove auto dataType and get content-type in the process while ( dataTypes[ 0 ] === "*" ) { dataTypes.shift(); if ( ct === undefined ) { ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); } } // Check if we're dealing with a known content-type if ( ct ) { for ( type in contents ) { if ( contents[ type ] && contents[ type ].test( ct ) ) { dataTypes.unshift( type ); break; } } } // Check to see if we have a response for the expected dataType if ( dataTypes[ 0 ] in responses ) { finalDataType = dataTypes[ 0 ]; } else { // Try convertible dataTypes for ( type in responses ) { if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { finalDataType = type; break; } if ( !firstDataType ) { firstDataType = type; } } // Or just use first one finalDataType = finalDataType || firstDataType; } // If we found a dataType // We add the dataType to the list if needed // and return the corresponding response if ( finalDataType ) { if ( finalDataType !== dataTypes[ 0 ] ) { dataTypes.unshift( finalDataType ); } return responses[ finalDataType ]; } } /* Chain conversions given the request and the original response * Also sets the responseXXX fields on the jqXHR instance */ function ajaxConvert( s, response, jqXHR, isSuccess ) { var conv2, current, conv, tmp, prev, converters = {}, // Work with a copy of dataTypes in case we need to modify it for conversion dataTypes = s.dataTypes.slice(); // Create converters map with lowercased keys if ( dataTypes[ 1 ] ) { for ( conv in s.converters ) { converters[ conv.toLowerCase() ] = s.converters[ conv ]; } } current = dataTypes.shift(); // Convert to each sequential dataType while ( current ) { if ( s.responseFields[ current ] ) { jqXHR[ s.responseFields[ current ] ] = response; } // Apply the dataFilter if provided if ( !prev && isSuccess && s.dataFilter ) { response = s.dataFilter( response, s.dataType ); } prev = current; current = dataTypes.shift(); if ( current ) { // There's only work to do if current dataType is non-auto if ( current === "*" ) { current = prev; // Convert response if prev dataType is non-auto and differs from current } else if ( prev !== "*" && prev !== current ) { // Seek a direct converter conv = converters[ prev + " " + current ] || converters[ "* " + current ]; // If none found, seek a pair if ( !conv ) { for ( conv2 in converters ) { // If conv2 outputs current tmp = conv2.split( " " ); if ( tmp[ 1 ] === current ) { // If prev can be converted to accepted input conv = converters[ prev + " " + tmp[ 0 ] ] || converters[ "* " + tmp[ 0 ] ]; if ( conv ) { // Condense equivalence converters if ( conv === true ) { conv = converters[ conv2 ]; // Otherwise, insert the intermediate dataType } else if ( converters[ conv2 ] !== true ) { current = tmp[ 0 ]; dataTypes.unshift( tmp[ 1 ] ); } break; } } } } // Apply converter (if not an equivalence) if ( conv !== true ) { // Unless errors are allowed to bubble, catch and return them if ( conv && s.throws ) { response = conv( response ); } else { try { response = conv( response ); } catch ( e ) { return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; } } } } } } return { state: "success", data: response }; } jQuery.extend( { // Counter for holding the number of active queries active: 0, // Last-Modified header cache for next request lastModified: {}, etag: {}, ajaxSettings: { url: location.href, type: "GET", isLocal: rlocalProtocol.test( location.protocol ), global: true, processData: true, async: true, contentType: "application/x-www-form-urlencoded; charset=UTF-8", /* timeout: 0, data: null, dataType: null, username: null, password: null, cache: null, throws: false, traditional: false, headers: {}, */ accepts: { "*": allTypes, text: "text/plain", html: "text/html", xml: "application/xml, text/xml", json: "application/json, text/javascript" }, contents: { xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/ }, responseFields: { xml: "responseXML", text: "responseText", json: "responseJSON" }, // Data converters // Keys separate source (or catchall "*") and destination types with a single space converters: { // Convert anything to text "* text": String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": JSON.parse, // Parse text as xml "text xml": jQuery.parseXML }, // For options that shouldn't be deep extended: // you can add your own custom options here if // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { url: true, context: true } }, // Creates a full fledged settings object into target // with both ajaxSettings and settings fields. // If target is omitted, writes into ajaxSettings. ajaxSetup: function( target, settings ) { return settings ? // Building a settings object ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : // Extending ajaxSettings ajaxExtend( jQuery.ajaxSettings, target ); }, ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), ajaxTransport: addToPrefiltersOrTransports( transports ), // Main method ajax: function( url, options ) { // If url is an object, simulate pre-1.5 signature if ( typeof url === "object" ) { options = url; url = undefined; } // Force options to be an object options = options || {}; var transport, // URL without anti-cache param cacheURL, // Response headers responseHeadersString, responseHeaders, // timeout handle timeoutTimer, // Url cleanup var urlAnchor, // Request state (becomes false upon send and true upon completion) completed, // To know if global events are to be dispatched fireGlobals, // Loop variable i, // uncached part of the url uncached, // Create the final options object s = jQuery.ajaxSetup( {}, options ), // Callbacks context callbackContext = s.context || s, // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? jQuery( callbackContext ) : jQuery.event, // Deferreds deferred = jQuery.Deferred(), completeDeferred = jQuery.Callbacks( "once memory" ), // Status-dependent callbacks statusCode = s.statusCode || {}, // Headers (they are sent all at once) requestHeaders = {}, requestHeadersNames = {}, // Default abort message strAbort = "canceled", // Fake xhr jqXHR = { readyState: 0, // Builds headers hashtable if needed getResponseHeader: function( key ) { var match; if ( completed ) { if ( !responseHeaders ) { responseHeaders = {}; while ( ( match = rheaders.exec( responseHeadersString ) ) ) { responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; } } match = responseHeaders[ key.toLowerCase() ]; } return match == null ? null : match; }, // Raw string getAllResponseHeaders: function() { return completed ? responseHeadersString : null; }, // Caches the header setRequestHeader: function( name, value ) { if ( completed == null ) { name = requestHeadersNames[ name.toLowerCase() ] = requestHeadersNames[ name.toLowerCase() ] || name; requestHeaders[ name ] = value; } return this; }, // Overrides response content-type header overrideMimeType: function( type ) { if ( completed == null ) { s.mimeType = type; } return this; }, // Status-dependent callbacks statusCode: function( map ) { var code; if ( map ) { if ( completed ) { // Execute the appropriate callbacks jqXHR.always( map[ jqXHR.status ] ); } else { // Lazy-add the new callbacks in a way that preserves old ones for ( code in map ) { statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; } } } return this; }, // Cancel the request abort: function( statusText ) { var finalText = statusText || strAbort; if ( transport ) { transport.abort( finalText ); } done( 0, finalText ); return this; } }; // Attach deferreds deferred.promise( jqXHR ); // Add protocol if not provided (prefilters might expect it) // Handle falsy url in the settings object (#10093: consistency with old signature) // We also use the url parameter if available s.url = ( ( url || s.url || location.href ) + "" ) .replace( rprotocol, location.protocol + "//" ); // Alias method option to type as per ticket #12004 s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; // A cross-domain request is in order when the origin doesn't match the current origin. if ( s.crossDomain == null ) { urlAnchor = document.createElement( "a" ); // Support: IE <=8 - 11, Edge 12 - 15 // IE throws exception on accessing the href property if url is malformed, // e.g. http://example.com:80x/ try { urlAnchor.href = s.url; // Support: IE <=8 - 11 only // Anchor's host property isn't correctly set when s.url is relative urlAnchor.href = urlAnchor.href; s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== urlAnchor.protocol + "//" + urlAnchor.host; } catch ( e ) { // If there is an error parsing the URL, assume it is crossDomain, // it can be rejected by the transport if it is invalid s.crossDomain = true; } } // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); } // Apply prefilters inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); // If request was aborted inside a prefilter, stop there if ( completed ) { return jqXHR; } // We can fire global events as of now if asked to // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { jQuery.event.trigger( "ajaxStart" ); } // Uppercase the type s.type = s.type.toUpperCase(); // Determine if request has content s.hasContent = !rnoContent.test( s.type ); // Save the URL in case we're toying with the If-Modified-Since // and/or If-None-Match header later on // Remove hash to simplify url manipulation cacheURL = s.url.replace( rhash, "" ); // More options handling for requests with no content if ( !s.hasContent ) { // Remember the hash so we can put it back uncached = s.url.slice( cacheURL.length ); // If data is available and should be processed, append data to url if ( s.data && ( s.processData || typeof s.data === "string" ) ) { cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; // #9682: remove data so that it's not used in an eventual retry delete s.data; } // Add or update anti-cache param if needed if ( s.cache === false ) { cacheURL = cacheURL.replace( rantiCache, "$1" ); uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; } // Put hash and anti-cache on the URL that will be requested (gh-1732) s.url = cacheURL + uncached; // Change '%20' to '+' if this is encoded form body content (gh-2658) } else if ( s.data && s.processData && ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { s.data = s.data.replace( r20, "+" ); } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { if ( jQuery.lastModified[ cacheURL ] ) { jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); } if ( jQuery.etag[ cacheURL ] ) { jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); } } // Set the correct header, if data is being sent if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { jqXHR.setRequestHeader( "Content-Type", s.contentType ); } // Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( "Accept", s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : s.accepts[ "*" ] ); // Check for headers option for ( i in s.headers ) { jqXHR.setRequestHeader( i, s.headers[ i ] ); } // Allow custom headers/mimetypes and early abort if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { // Abort if not done already and return return jqXHR.abort(); } // Aborting is no longer a cancellation strAbort = "abort"; // Install callbacks on deferreds completeDeferred.add( s.complete ); jqXHR.done( s.success ); jqXHR.fail( s.error ); // Get transport transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); // If no transport, we auto-abort if ( !transport ) { done( -1, "No Transport" ); } else { jqXHR.readyState = 1; // Send global event if ( fireGlobals ) { globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); } // If request was aborted inside ajaxSend, stop there if ( completed ) { return jqXHR; } // Timeout if ( s.async && s.timeout > 0 ) { timeoutTimer = window.setTimeout( function() { jqXHR.abort( "timeout" ); }, s.timeout ); } try { completed = false; transport.send( requestHeaders, done ); } catch ( e ) { // Rethrow post-completion exceptions if ( completed ) { throw e; } // Propagate others as results done( -1, e ); } } // Callback for when everything is done function done( status, nativeStatusText, responses, headers ) { var isSuccess, success, error, response, modified, statusText = nativeStatusText; // Ignore repeat invocations if ( completed ) { return; } completed = true; // Clear timeout if it exists if ( timeoutTimer ) { window.clearTimeout( timeoutTimer ); } // Dereference transport for early garbage collection // (no matter how long the jqXHR object will be used) transport = undefined; // Cache response headers responseHeadersString = headers || ""; // Set readyState jqXHR.readyState = status > 0 ? 4 : 0; // Determine if successful isSuccess = status >= 200 && status < 300 || status === 304; // Get response data if ( responses ) { response = ajaxHandleResponses( s, jqXHR, responses ); } // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); // If successful, handle type chaining if ( isSuccess ) { // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { modified = jqXHR.getResponseHeader( "Last-Modified" ); if ( modified ) { jQuery.lastModified[ cacheURL ] = modified; } modified = jqXHR.getResponseHeader( "etag" ); if ( modified ) { jQuery.etag[ cacheURL ] = modified; } } // if no content if ( status === 204 || s.type === "HEAD" ) { statusText = "nocontent"; // if not modified } else if ( status === 304 ) { statusText = "notmodified"; // If we have data, let's convert it } else { statusText = response.state; success = response.data; error = response.error; isSuccess = !error; } } else { // Extract error from statusText and normalize for non-aborts error = statusText; if ( status || !statusText ) { statusText = "error"; if ( status < 0 ) { status = 0; } } } // Set data for the fake xhr object jqXHR.status = status; jqXHR.statusText = ( nativeStatusText || statusText ) + ""; // Success/Error if ( isSuccess ) { deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); } else { deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); } // Status-dependent callbacks jqXHR.statusCode( statusCode ); statusCode = undefined; if ( fireGlobals ) { globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", [ jqXHR, s, isSuccess ? success : error ] ); } // Complete completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); if ( fireGlobals ) { globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); // Handle the global AJAX counter if ( !( --jQuery.active ) ) { jQuery.event.trigger( "ajaxStop" ); } } } return jqXHR; }, getJSON: function( url, data, callback ) { return jQuery.get( url, data, callback, "json" ); }, getScript: function( url, callback ) { return jQuery.get( url, undefined, callback, "script" ); } } ); jQuery.each( [ "get", "post" ], function( i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // Shift arguments if data argument was omitted if ( isFunction( data ) ) { type = type || callback; callback = data; data = undefined; } // The url can be an options object (which then must have .url) return jQuery.ajax( jQuery.extend( { url: url, type: method, dataType: type, data: data, success: callback }, jQuery.isPlainObject( url ) && url ) ); }; } ); jQuery._evalUrl = function( url ) { return jQuery.ajax( { url: url, // Make this explicit, since user can override this through ajaxSetup (#11264) type: "GET", dataType: "script", cache: true, async: false, global: false, "throws": true } ); }; jQuery.fn.extend( { wrapAll: function( html ) { var wrap; if ( this[ 0 ] ) { if ( isFunction( html ) ) { html = html.call( this[ 0 ] ); } // The elements to wrap the target around wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); if ( this[ 0 ].parentNode ) { wrap.insertBefore( this[ 0 ] ); } wrap.map( function() { var elem = this; while ( elem.firstElementChild ) { elem = elem.firstElementChild; } return elem; } ).append( this ); } return this; }, wrapInner: function( html ) { if ( isFunction( html ) ) { return this.each( function( i ) { jQuery( this ).wrapInner( html.call( this, i ) ); } ); } return this.each( function() { var self = jQuery( this ), contents = self.contents(); if ( contents.length ) { contents.wrapAll( html ); } else { self.append( html ); } } ); }, wrap: function( html ) { var htmlIsFunction = isFunction( html ); return this.each( function( i ) { jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); } ); }, unwrap: function( selector ) { this.parent( selector ).not( "body" ).each( function() { jQuery( this ).replaceWith( this.childNodes ); } ); return this; } } ); jQuery.expr.pseudos.hidden = function( elem ) { return !jQuery.expr.pseudos.visible( elem ); }; jQuery.expr.pseudos.visible = function( elem ) { return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); }; jQuery.ajaxSettings.xhr = function() { try { return new window.XMLHttpRequest(); } catch ( e ) {} }; var xhrSuccessStatus = { // File protocol always yields status code 0, assume 200 0: 200, // Support: IE <=9 only // #1450: sometimes IE returns 1223 when it should be 204 1223: 204 }, xhrSupported = jQuery.ajaxSettings.xhr(); support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); support.ajax = xhrSupported = !!xhrSupported; jQuery.ajaxTransport( function( options ) { var callback, errorCallback; // Cross domain only allowed if supported through XMLHttpRequest if ( support.cors || xhrSupported && !options.crossDomain ) { return { send: function( headers, complete ) { var i, xhr = options.xhr(); xhr.open( options.type, options.url, options.async, options.username, options.password ); // Apply custom fields if provided if ( options.xhrFields ) { for ( i in options.xhrFields ) { xhr[ i ] = options.xhrFields[ i ]; } } // Override mime type if needed if ( options.mimeType && xhr.overrideMimeType ) { xhr.overrideMimeType( options.mimeType ); } // X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { headers[ "X-Requested-With" ] = "XMLHttpRequest"; } // Set headers for ( i in headers ) { xhr.setRequestHeader( i, headers[ i ] ); } // Callback callback = function( type ) { return function() { if ( callback ) { callback = errorCallback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = xhr.onreadystatechange = null; if ( type === "abort" ) { xhr.abort(); } else if ( type === "error" ) { // Support: IE <=9 only // On a manual native abort, IE9 throws // errors on any property access that is not readyState if ( typeof xhr.status !== "number" ) { complete( 0, "error" ); } else { complete( // File: protocol always yields status 0; see #8605, #14207 xhr.status, xhr.statusText ); } } else { complete( xhrSuccessStatus[ xhr.status ] || xhr.status, xhr.statusText, // Support: IE <=9 only // IE9 has no XHR2 but throws on binary (trac-11426) // For XHR2 non-text, let the caller handle it (gh-2498) ( xhr.responseType || "text" ) !== "text" || typeof xhr.responseText !== "string" ? { binary: xhr.response } : { text: xhr.responseText }, xhr.getAllResponseHeaders() ); } } }; }; // Listen to events xhr.onload = callback(); errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); // Support: IE 9 only // Use onreadystatechange to replace onabort // to handle uncaught aborts if ( xhr.onabort !== undefined ) { xhr.onabort = errorCallback; } else { xhr.onreadystatechange = function() { // Check readyState before timeout as it changes if ( xhr.readyState === 4 ) { // Allow onerror to be called first, // but that will not handle a native abort // Also, save errorCallback to a variable // as xhr.onerror cannot be accessed window.setTimeout( function() { if ( callback ) { errorCallback(); } } ); } }; } // Create the abort callback callback = callback( "abort" ); try { // Do send the request (this may raise an exception) xhr.send( options.hasContent && options.data || null ); } catch ( e ) { // #14683: Only rethrow if this hasn't been notified as an error yet if ( callback ) { throw e; } } }, abort: function() { if ( callback ) { callback(); } } }; } } ); // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) jQuery.ajaxPrefilter( function( s ) { if ( s.crossDomain ) { s.contents.script = false; } } ); // Install script dataType jQuery.ajaxSetup( { accepts: { script: "text/javascript, application/javascript, " + "application/ecmascript, application/x-ecmascript" }, contents: { script: /\b(?:java|ecma)script\b/ }, converters: { "text script": function( text ) { jQuery.globalEval( text ); return text; } } } ); // Handle cache's special case and crossDomain jQuery.ajaxPrefilter( "script", function( s ) { if ( s.cache === undefined ) { s.cache = false; } if ( s.crossDomain ) { s.type = "GET"; } } ); // Bind script tag hack transport jQuery.ajaxTransport( "script", function( s ) { // This transport only deals with cross domain requests if ( s.crossDomain ) { var script, callback; return { send: function( _, complete ) { script = jQuery( "

Here find some simple tags


Lorem ipsum dolor sit amet consectetur adipisicing elit. A quo, autem quaerat explicabo impedit mollitia amet molestiae nulla cum architecto ducimus itaque sit blanditiis quasi animi optio ab facilis nihil?

Here are some escaped characters: & (ampersand), à (a with grave), № (numero sign).

This is a form that demonstrates loose attribute formatting

A table with normal closing tags

Pet Features
Feature Cat Dog
Tail
Eyes
Ears
Barking
Litter Box

A table without closing tags

Pet Features
Feature Cat Dog
Tail
Eyes
Ears
Barking
Litter Box

A math section with CDATA

You can add a string to a number, but this stringifies the number:

a / b - 7 = a / b - 7
================================================ FILE: tests/syntax-tests/source/Haskell/test.hs ================================================ {-# LANGUAGE OverloadedStrings #-} -- simple parser for a Lisp-like syntax I wrote some time ago import Data.Void (Void) import Data.Text (Text) import qualified Data.Text as T import Text.Megaparsec.Char import Text.Megaparsec.Error (errorBundlePretty) import Text.Megaparsec hiding (State) import qualified Text.Megaparsec.Char.Lexer as L data LispVal = Symbol Text | List [LispVal] | Number Integer | String Text | LispTrue | LispFalse | Nil deriving (Show, Eq) type Parser = Parsec Void Text readStr :: Text -> Either String [LispVal] readStr t = case parse pLisp "f" t of Right parsed -> Right parsed Left err -> Left $ errorBundlePretty err {-# INLINABLE readStr #-} sc :: Parser () sc = L.space space1 (L.skipLineComment ";") empty {-# INLINABLE sc #-} lexeme :: Parser a -> Parser a lexeme = L.lexeme sc {-# INLINE lexeme #-} symbol :: Text -> Parser Text symbol = L.symbol sc {-# INLINE symbol #-} symbol' :: Text -> Parser Text symbol' = L.symbol' sc {-# INLINE symbol' #-} pNil :: Parser LispVal pNil = symbol' "nil" >> return Nil {-# INLINE pNil #-} integer :: Parser Integer integer = lexeme L.decimal {-# INLINE integer #-} lispSymbols :: Parser Char lispSymbols = oneOf ("#$%&|*+-/:<=>?@^_~" :: String) {-# INLINE lispSymbols #-} pLispVal :: Parser LispVal pLispVal = choice [pList, pNumber, pSymbol, pNil, pString] {-# INLINE pLispVal #-} pSymbol :: Parser LispVal pSymbol = (Symbol . T.pack <$> lexeme (some (letterChar <|> lispSymbols))) {-# INLINABLE pSymbol #-} pList :: Parser LispVal pList = List <$> between (symbol "(") (symbol ")") (many pLispVal) {-# INLINABLE pList #-} pLisp :: Parser [LispVal] pLisp = some pLispVal {-# INLINE pLisp #-} pNumber :: Parser LispVal pNumber = Number <$> integer {-# INLINE pNumber #-} pString :: Parser LispVal pString = do str <- char '\"' *> manyTill L.charLiteral (char '\"') return $ String (T.pack str) {-# INLINABLE pString #-} ================================================ FILE: tests/syntax-tests/source/Hosts/hosts ================================================ #this is a comment in the hosts file 127.0.0.1 localhost 192.168.0.1 sample.test #a comment 192.160.0.200 try.sample.test try #another comment 216.58.223.238 google.com ::1 localhost.try ip6-localhost ================================================ FILE: tests/syntax-tests/source/INI/test.inf ================================================ [section] key=value # This file is just for testing that the INI syntax is registered to handle # the .inf file extension, it is not testing the syntax highlighting capabilities # of the INI syntax itself ================================================ FILE: tests/syntax-tests/source/INI/test.ini ================================================ [section] key=value numeric = 42 quotes="this value is quoted" quotes2="this is not a comment ;foo" different_quotes='these are other characters' [another one] first = value ; comment on own line ;another one second=value ; comment at the end of a line third = value;another one # is this a comment? maybe. [section.with.dots] [section\with\backspaces] [section;with;semicola] ================================================ FILE: tests/syntax-tests/source/Idris2/LICENSE.md ================================================ The `test.idr` file has been added from https://github.com/buzden/sublime-syntax-idris2 under the following license: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 ================================================ FILE: tests/syntax-tests/source/Idris2/test.idr ================================================ -- some code in Idris module XX.X''' import Data.Nat data X = A | B namespace X ||| Documentation record Y where [noHints] constructor MkY' field1 : Nat {auto x : Nat} namespace X' { parameters (x : A (Maybe b)) x : Nat } u : () u = () k, w, u : Char k = '\NUL' w = 'w' x = [1, 0, 3, "sdf\{d}", 0xFF, 0o77, 0b10_1, 100_100] f : Int -> Int f = if x > 0 then x else 0 () SS `elem` S $ do x <- a [1, 2, 3] let ukuk = akak rewrite $ Wow Wow Wow Wow.Wow b W (W) pure $ f A B c D (EE) E (&&&) : Nat -> Nat -> Nat z &&& y = d + ?foo (&&&) x y = ?asfda public export covering (.fun) : X a Y b => Nat -> Nat Z .fun = haha.fun haha .N (.fun) Z = ahah $ \case x@(x, y) => Prelude.Types.ahahah (.N) : Nat -> Nat Z .N = Z (.N) (S n) = (.N) n xx : Name xx = `{Full.Name} infixr 0 ^^^, &&& xxx : ? xxx = case x of Z => lalalaCamelCase z => alalalCamelCase ff : Nat -> TTImp ff 0 = let x = 0 in val ff _ = `(let x = 0 in ~val ^~^ ~(abc)) ff _ = f `(let x = 0 in ~val ^~^ ~(abc)) x %language ElabReflection %runElab X.sf ads %macro %inline fff : List Decl fff = `[ f : Nat -> Nat f Z = haha %runElab %search @{%World} ] private infixr 4 ^--^ (^--^) : Nat -> Nat -> Nat (^--^) Z Z = Z x ^--^ y = x + y x : (y : Vect n (Maybe (Maybe (&&&) Nat))) -> {x : Nat} -> {auto _ : Monoid a} -> {default 4 xx : Nat} -> {default (f x Y) xx' : Nat} -> String x Z S = ?foo x y _ = "a b \{show $ let x = 0 in y} y >>= z" multiline : String multiline = """ A multiline string\NUL """ f' : Nat -> Nat f' = x' 4 x : Char x = '\BEL' x = '\\' x = '\'' x = '\o755' x = 'a' xx : Int xx = 0o7_5_5 ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.bak ================================================ // foo.bak (editor etc backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.dpkg-dist ================================================ // foo.dpkg-dist (Debian dpkg backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.dpkg-old ================================================ // foo.dpkg-old (Debian dpkg backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.in ================================================ // foo.in (build system input) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.in.in ================================================ // foo.in.in (build system input, doubly replaced) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.old ================================================ // foo.old (editor etc backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.orig ================================================ // foo.orig (editor, diff etc backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.orig~ ================================================ // foo.orig~ (backup of an editor, diff etc backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.rpmnew ================================================ // foo.rpmnew (Red Hat rpm backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.rpmorig ================================================ // foo.rpmorig (Red Hat rpm backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.rpmsave ================================================ // foo.rpmsave (Red Hat rpm backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.ucf-dist ================================================ // foo.ucf-dist (Debian ucf backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.ucf-new ================================================ // foo.ucf-new (Debian ucf backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs.ucf-old ================================================ // foo.ucf-old (Debian ucf backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.rs~ ================================================ // foo~ (editor backup) should highlight same as foo ================================================ FILE: tests/syntax-tests/source/Ignored suffixes/test.unknown~ ================================================ // foo~ for unknown foo should not highlight ================================================ FILE: tests/syntax-tests/source/JQ/LICENSE.md ================================================ The `sample.jq` file was taken from [SublimeJQ] under the following license: [SublimeJQ]: https://github.com/zogwarg/SublimeJQ MIT License Copyright (c) 2017 Thomas Buick 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. ================================================ FILE: tests/syntax-tests/source/JQ/sample.jq ================================================ import "../imported-file" ; # With Comments ! def weird($a; $b; $c): [ $a, $b, $c ] | transpose | reduce .[][] as $item ( []; . + $item.property ) ; . | weird (.a; .b; .c) | ( if (. | contains("never") ) then "Why yes" else 12.23 end ) as $never | { hello, why: "because", hello: ( weird | ascii_upcase ), format_eg: ( . | @json "My json string \( . | this | part | just | white | ascii_upcase | transpose)" ), never: $never, "literal_key": literal_value, "this": 12.1e12, "part": "almost" "like": [ 12, 2 "json" { "quite": { similar: "but not quite" } } ], } | ( # And with very basic brace matching # Invalid End ] # Other invalid ends ( [ } ] ) # A "valid" sequence ( [ { key: () , other_key:( [ [] [[]] ] ), gaga } ] ) # A "invalid" sequence ( [ { key: () , other_key:( [ [] [[] ] ), gaga } ] ) "A string\n whith escaped characters \" because we can" ) ================================================ FILE: tests/syntax-tests/source/JSON/example.ndjson ================================================ {"some":"thing"} {"foo":17,"bar":false,"quux":true} {"may":{"include":"nested","objects":["and","arrays"]}} ================================================ FILE: tests/syntax-tests/source/JSON/test.json ================================================ [ { "name": "john", "age": 42, "isCustomer": false, "children": [] }, { "name": "james", "age": 35, "isCustomer": true, "children": [ { "name": "linus", "age": 4 }, { "name": "sandra", "age": 2 } ] }, { "name": "jessica", "age": null, "isCustomer": false, "children": [] } ] ================================================ FILE: tests/syntax-tests/source/Java/test.java ================================================ import java.util.Scanner; /* This Java program was submitted to help bat * with its syntax highlighting tests */ public class Main { public static void main(String[] arg) { Scanner st = new Scanner(System.in); int t; t = st.nextInt(); String tem; tem = st.nextLine(); for(int zz=0;zz <%-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --%> <%@page session="false" contentType="text/html; charset=ISO-8859-1" %> <%@page import="java.util.Enumeration" %> <%@page import="jakarta.servlet.http.HttpSession" %> <%@page import="org.apache.catalina.Session" %> <%@page import="org.apache.catalina.manager.JspHelper" %> <%@page import="org.apache.catalina.util.ContextName" %> <%--!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"--%> <% String path = (String) request.getAttribute("path"); String version = (String) request.getAttribute("version"); ContextName cn = new ContextName(path, version); Session currentSession = (Session)request.getAttribute("currentSession"); String currentSessionId = null; HttpSession currentHttpSession = null; if (currentSession != null) { currentHttpSession = currentSession.getSession(); currentSessionId = JspHelper.escapeXml(currentSession.getId()); } else { currentSessionId = "Session invalidated"; } String submitUrl = JspHelper.escapeXml(response.encodeURL( ((HttpServletRequest) pageContext.getRequest()).getRequestURI() + "?path=" + path + "&version=" + version)); %> Sessions Administration: details for <%= currentSessionId %> <% if (currentHttpSession == null) { %>

<%=currentSessionId%>

<% } else { %>

Details for Session <%= currentSessionId %>

Session Id <%= currentSessionId %>
Guessed Locale <%= JspHelper.guessDisplayLocaleFromSession(currentSession) %>
Guessed User <%= JspHelper.guessDisplayUserFromSession(currentSession) %>
Creation Time <%= JspHelper.getDisplayCreationTimeForSession(currentSession) %>
Last Accessed Time <%= JspHelper.getDisplayLastAccessedTimeForSession(currentSession) %>
Session Max Inactive Interval <%= JspHelper.secondsToTimeString(currentSession.getMaxInactiveInterval()) %>
Used Time <%= JspHelper.getDisplayUsedTimeForSession(currentSession) %>
Inactive Time <%= JspHelper.getDisplayInactiveTimeForSession(currentSession) %>
TTL <%= JspHelper.getDisplayTTLForSession(currentSession) %>
<% if ("Primary".equals(request.getParameter("sessionType"))) { %> <% } %>
<%= JspHelper.escapeXml(request.getAttribute("error")) %>
<%= JspHelper.escapeXml(request.getAttribute("message")) %>
<% int nAttributes = 0; Enumeration attributeNamesEnumeration = currentHttpSession.getAttributeNames(); while (attributeNamesEnumeration.hasMoreElements()) { attributeNamesEnumeration.nextElement(); ++nAttributes; } %> <%--tfoot> <% attributeNamesEnumeration = currentHttpSession.getAttributeNames(); while (attributeNamesEnumeration.hasMoreElements()) { String attributeName = attributeNamesEnumeration.nextElement(); %> <% } // end while %>
<%= JspHelper.formatNumber(nAttributes) %> attributes
Remove Attribute Attribute name Attribute value
TODO: set Max Inactive Interval on sessions
<% if ("Primary".equals(request.getParameter("sessionType"))) { %> <% } else { out.print("Primary sessions only"); } %>
<%= JspHelper.escapeXml(attributeName) %> <% Object attributeValue = currentHttpSession.getAttribute(attributeName); %>"><%= JspHelper.escapeXml(attributeValue) %>
<% } // endif%>

<%--div style="display: none;">

Valid HTML 4.01! Valid XHTML 1.0! Valid XHTML 1.1!

================================================ FILE: tests/syntax-tests/source/JavaScript/test.js ================================================ let letNumber = 1000; const constNumber = 10; var varNumber = -1234; const constNegativeFloat = -1.23; var tooMuch = Infinity; nothing = null; let listofthings = ["thing", 'thing2', `foo`, ["bar"]]; // Simple comment /** * ######### * Multiline * comment * ######### */ let test; for (let i = 0; i < constNumber; i++) { if (test) continue; else test += 1; // random things } while(test < 100 && typeof test === "number") { test = test > 30 ? test+5 : test+1; } function weatherSays(when=Date.now()) { return "rain"; } const thereAreClouds = true; const cloudsCount = 20; switch(weatherSays(Date.now())) { case 'rain': break; case 'sun': default: break; } let rain = false; if ((thereAreClouds && cloudsCount >= 20) || weatherSays() === "rain") { rain = false; } else if (thereAreClouds && weatherSays() == "rain") { // oh no, unsafe two equals checking! rain = true; } else { rain = !!cloudsCount; } class Forecast { constructor(where, isGonnaRainA=true, isGonnaRainB=false, isGonnaRainC=false, ...randomArgs) { this.station = { location: [where.x, where.y, where.z], surroundings: { zoneA: { location: [1, 2, 3], isGonnaRain: isGonnaRainA }, zoneB: { location: [-1, 2, 2], isGonnaRain: isGonnaRainB }, zoneC: { location: [-2, 0, 0], isGonnaRainC: isGonnaRainC }, } }; } async getLocalPrevisions() { const rainZones = [this.station.surroundings.zoneA.isGonnaRain, this.station.surroundings.zoneB.isGonnaRain, this.station.surroundings.zoneC.isGonnaRain]; return await rainZones.filter(z => !!z).length > (rainZones.length / 2); } communicatePrevisions(isGonnaRain=undefined) { if (isGonnaRain) console.log("Take the umbrella."); } destroy() { delete this.station; } static startHiring() { console.log("We're looking for weather presenters."); console.log("A lot of presenters came. Hiring stops."); } /* This forecasting station is magic. It can generate rain, but this method is secret because it's a generator function - nobody uses them! */ * generateRainInZoneC(clouds=[1, 2, 3]) { this.station.surroundings.zoneC.isGonnaRain = true; const makeRain = () => { return "raining!"; }; yield clouds; // first, keeps clouds do { console.log(makeRain()); yield clouds.pop(); // then all clouds do rain } while(clouds.length >= 1); } } Forecast.startHiring(); const forecasting = new Forecast([3, 3, 3]); (async() => { const raining = forecasting.generateRainInZoneC(); raining.next(); forecasting.communicatePrevisions(await forecasting.getLocalPrevisions()); raining.next(); raining.next(); raining.return("stop!"); forecasting.destroy(); })(); ================================================ FILE: tests/syntax-tests/source/Jinja2/template.jinja2 ================================================ {% extends 'base.jinja2' %}

{% block title %}{% endblock %}

{% for entry in entries %} Entry {{ loop.index }} {% if entry.show %}

{{ entry.value }}

{% else if false %}

No value

{% endif %} {% endfor %} {% set some_value = 123 %}
{{ some_value | custom_filter }}, {{ some_value | abs }}
{% endset %} {{ some_dict['val'].val }} {# comment #} {# longer comment {{ value }} #} {% raw %} {{ do not transform }} {% endraw %} {% macro some_macro(value) -%}

{{ value }}

{%- endmacro %} {% if another_val is defined %}

{{ another_val }}

{% else %}

Unknown

{% endif %} ================================================ FILE: tests/syntax-tests/source/Julia/test.jl ================================================ x = 3 y = 2x typeof(y) f(x) = 2 + x f f(10) function g(x, y) z = x + y return z^2 end g(1, 2) let s = 0 for i in 1:10 s += i # Equivalent to s = s + i end s end typeof(1:10) function mysum(n) s = 0 for i in 1:n s += i end return s end mysum(100) a = 3 a < 5 if a < 5 "small" else "big" end v = [1, 2, 3] typeof(v) v[2] v[2] = 10 v2 = [i^2 for i in 1:10] M = [1 2 3 4] typeof(M) zeros(5, 5) zeros(Int, 4, 5) [i + j for i in 1:5, j in 1:6] ================================================ FILE: tests/syntax-tests/source/Kotlin/test.kt ================================================ import kotlin.math.* data class Example( val name: String, val numbers: List ) fun interface JokeInterface { fun isFunny(): Boolean } abstract class AbstractJoke : JokeInterface { override fun isFunny() = false abstract fun content(): String } class Joke : AbstractJoke() { override fun isFunny(): Boolean { return true } override fun content(): String = "content of joke here, haha" } class DelegatedJoke(val joke: Joke) : JokeInterface by joke { val number: Long = 123L companion object { const val someConstant = "some constant text" } } object SomeSingleton sealed class Shape { abstract fun area(): Double } data class Square(val sideLength: Double) : Shape() { override fun area(): Double = sideLength.pow(2) } object Point : Shape() { override fun area() = .0 } class Circle(val radius: Double) : Shape() { override fun area(): Double { return PI * radius * radius } } fun String.extensionMethod() = "test" fun main() { val name = """ multiline string some numbers: 123123 42 """.trimIndent() val example = Example(name = name, numbers = listOf(512, 42, null, -1)) example.numbers .filterNotNull() .forEach { println(it) } setOf(Joke(), DelegatedJoke(Joke()).joke) .filter(JokeInterface::isFunny) .map(AbstractJoke::content) .forEachIndexed { index: Int, joke -> println("I heard a funny joke(#${index + 1}): $joke") } listOf(Square(12.3), Point, Circle(5.2)) .associateWith(Shape::area) .toList() .sortedBy { it.second } .forEach { println("${it.first}: ${it.second}") } println("some string".extensionMethod()) require(SomeSingleton::class.simpleName == "SomeSingletonName") { "something does not seem right..." } } ================================================ FILE: tests/syntax-tests/source/LLVM/test.ll ================================================ ; ModuleID = 'test.c' source_filename = "test.c" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" @.str = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1 ; Function Attrs: noinline norecurse optnone uwtable define dso_local i32 @main(i32 %0, i8** %1) #0 { %3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca i8**, align 8 store i32 0, i32* %3, align 4 store i32 %0, i32* %4, align 4 store i8** %1, i8*** %5, align 8 %6 = call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0)) ret i32 1337 } declare dso_local i32 @puts(i8*) #1 attributes #0 = { noinline norecurse optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{!"clang version 10.0.0-4ubuntu1 "} ================================================ FILE: tests/syntax-tests/source/Lean/LICENSE.md ================================================ The `test.lean` file has been adpated from - multiple files of [Mathematics in Lean](https://leanprover-community.github.io/mathematics_in_lean/) under the Apache 2.0 license, - and https://github.com/Julian/lean-across-the-board under the MIT license. ## Mathematics in Lean (Apache 2.0) Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2020 Jeremy Avigad, Patrick Massot. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ## Julian/lean-across-the-board (MIT) Copyright (c) 2020 Julian Berman 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. ================================================ FILE: tests/syntax-tests/source/Lean/test.lean ================================================ import MIL.Common import Mathlib.Topology.Instances.Real.Defs open Set Filter Topology variable {α : Type*} variable (s t : Set ℕ) variable (ssubt : s ⊆ t) variable {α : Type*} (s : Set (Set α)) -- Apostrophes are allowed in variable names variable (f'_x x' : ℕ) variable (bangwI' jablu'DI' QaQqu' nay' Ghay'cha' he' : ℕ) -- In the next example we could use `tauto` in each proof instead of knowing the lemmas example {α : Type*} (s : Set α) : Filter α := { sets := { t | s ⊆ t } univ_sets := subset_univ s sets_of_superset := fun hU hUV ↦ Subset.trans hU hUV inter_sets := fun hU hV ↦ subset_inter hU hV } namespace chess.utils section repr @[class] structure One₂ (α : Type) where /-- The element one -/ one : α structure StandardTwoSimplex where x : ℝ y : ℝ z : ℝ x_nonneg : 0 ≤ x y_nonneg : 0 ≤ y z_nonneg : 0 ≤ z sum_eq : x + y + z = 1 #check Pi.ringHom #check ker_Pi_Quotient_mk #eval 1 + 1 /-- The homomorphism from ``R ⧸ ⨅ i, I i`` to ``Π i, R ⧸ I i`` featured in the Chinese Remainder Theorem. -/ def chineseMap (I : ι → Ideal R) : (R ⧸ ⨅ i, I i) →+* Π i, R ⧸ I i := Ideal.Quotient.lift (⨅ i, I i) (Pi.ringHom fun i : ι ↦ Ideal.Quotient.mk (I i)) (by simp [← RingHom.mem_ker, ker_Pi_Quotient_mk]) lemma chineseMap_mk (I : ι → Ideal R) (x : R) : chineseMap I (Quotient.mk _ x) = fun i : ι ↦ Ideal.Quotient.mk (I i) x := rfl theorem isCoprime_Inf {I : Ideal R} {J : ι → Ideal R} {s : Finset ι} (hf : ∀ j ∈ s, IsCoprime I (J j)) : IsCoprime I (⨅ j ∈ s, J j) := by classical simp_rw [isCoprime_iff_add] at * induction s using Finset.induction with | empty => simp | @insert i s _ hs => rw [Finset.iInf_insert, inf_comm, one_eq_top, eq_top_iff, ← one_eq_top] set K := ⨅ j ∈ s, J j calc 1 = I + K := (hs fun j hj ↦ hf j (Finset.mem_insert_of_mem hj)).symm _ = I + K * (I + J i) := by rw [hf i (Finset.mem_insert_self i s), mul_one] _ = (1 + K) * I + K * J i := by ring _ ≤ I + K ⊓ J i := by gcongr ; apply mul_le_left ; apply mul_le_inf class Ring₃ (R : Type) extends AddGroup₃ R, Monoid₃ R, MulZeroClass R where /-- Multiplication is left distributive over addition -/ left_distrib : ∀ a b c : R, a * (b + c) = a * b + a * c /-- Multiplication is right distributive over addition -/ right_distrib : ∀ a b c : R, (a + b) * c = a * c + b * c instance {R : Type} [Ring₃ R] : AddCommGroup₃ R := { Ring₃.toAddGroup₃ with add_comm := by sorry } end repr end chess.utils ================================================ FILE: tests/syntax-tests/source/Less/example.less ================================================ // Load fonts @import url(https://fonts.googleapis.com/css?family=Lustria|Lato:700); // Color scheme https://kuler.adobe.com/Salmon-on-Ice-color-theme-2291686/ @dk: #3E454C; // dark @hl: #2185C5; // highlight @hll: #7ECEFD; // lighter highlight @lt: #FFF6E5; // light @ct: #FF7F66; // contrast // Sizes @contentWidth: 750px; @marginTop: 50px; @marginSide: 100px; // Fonts and Text @font: 'Lustria', serif; @headerFont: 'Lato', sans; @fontSize: 19px; @fontSizeH1: 50px; @fontSizeH2: 30px; @parSep: 40px; @linkSizeFactor: 0.8; // Sizes for small devices @smallMarginTop: 25px; @smallMarginSide: 25px; @smallFontSize: 18px; @smallFontSizeH1: 40px; @smallFontSizeH2: 28px; @smallParSep: 25px; #wrapper { width: 100%; margin: auto; min-height: 100%; height: auto !important; height: 100%; overflow: hidden !important; position: relative; } ================================================ FILE: tests/syntax-tests/source/Lisp/LICENSE.md ================================================ The `utils.lisp` file has been added from https://github.com/zkat/chillax under the following license: Copyright © 2009-2010 Kat Marchán 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. ================================================ FILE: tests/syntax-tests/source/Lisp/utils.lisp ================================================ (cl:defpackage :chillax.utils (:use :cl :alexandria) (:export :fun :mkhash :hashget :strcat :dequote :at)) (in-package :chillax.utils) ;;; Functions (defmacro fun (&body body) "This macro puts the FUN back in FUNCTION." `(lambda (&optional _) (declare (ignorable _)) ,@body)) ;;; Hash tables (defun mkhash (&rest keys-and-values &aux (table (make-hash-table :test #'equal))) "Convenience function for `literal' hash table definition." (loop for (key val) on keys-and-values by #'cddr do (setf (gethash key table) val) finally (return table))) (defun hashget (hash &rest keys) "Convenience function for recursively accessing hash tables." (reduce (lambda (h k) (gethash k h)) keys :initial-value hash)) (define-compiler-macro hashget (hash &rest keys) (if (null keys) hash (let ((hash-sym (make-symbol "HASH")) (key-syms (loop for i below (length keys) collect (make-symbol (format nil "~:@(~:R~)-KEY" i))))) `(let ((,hash-sym ,hash) ,@(loop for key in keys for sym in key-syms collect `(,sym ,key))) ,(reduce (lambda (hash key) `(gethash ,key ,hash)) key-syms :initial-value hash-sym))))) (defun (setf hashget) (new-value hash key &rest more-keys) "Uses the last key given to hashget to insert NEW-VALUE into the hash table returned by the second-to-last key. tl;dr: DWIM SETF function for HASHGET." (if more-keys (setf (gethash (car (last more-keys)) (apply #'hashget hash key (butlast more-keys))) new-value) (setf (gethash key hash) new-value))) ;;; Strings (defun strcat (string &rest more-strings) (apply #'concatenate 'string string more-strings)) (defun dequote (string) (let ((len (length string))) (if (and (> len 1) (starts-with #\" string) (ends-with #\" string)) (subseq string 1 (- len 1)) string))) ;;; ;;; At ;;; (defgeneric at (doc &rest keys)) (defgeneric (setf at) (new-value doc key &rest more-keys)) (defmethod at ((doc hash-table) &rest keys) (apply #'hashget doc keys)) (defmethod (setf at) (new-value (doc hash-table) key &rest more-keys) (apply #'(setf hashget) new-value doc key more-keys)) (defmethod at ((doc list) &rest keys) (reduce (lambda (alist key) (cdr (assoc key alist :test #'equal))) keys :initial-value doc)) (defmethod (setf at) (new-value (doc list) key &rest more-keys) (if more-keys (setf (cdr (assoc (car (last more-keys)) (apply #'at doc key (butlast more-keys)) :test #'equal)) new-value) (setf (cdr (assoc key doc :test #'equal)) new-value))) ;; A playful alias. (defun @ (doc &rest keys) (apply #'at doc keys)) (defun (setf @) (new-value doc key &rest more-keys) (apply #'(setf at) new-value doc key more-keys)) ================================================ FILE: tests/syntax-tests/source/Literate Haskell/Main.lhs ================================================ \documentclass{article} \begin{document} \section*{Introduction} Text outside code environments should follow TeX/LaTeX highlighting. The code environment delimiters themselves should be highlighted. Text inside code environments should follow regular Haskell highlighting. \begin{code} import Data.List import System.Environment import Text.Printf twoSumN :: Int -> [Int] -> [Int] twoSumN _ [] = [] twoSumN n (x : xs) | (n - x) `elem` xs = [x, n - x] | otherwise = twoSumN n xs threeSumN :: Int -> [Int] -> [Int] threeSumN _ [] = [] threeSumN n (x : xs) | null partial = threeSumN n xs | otherwise = x : partial where partial = twoSumN (n - x) xs \end{code} Text in-between code environments. % LaTeX comment. \begin{code} output :: String -> IO () output path = do input <- sort . map read . filter (not . null) . lines <$> readFile path printf "File: %s\n" path printf " Part 1: %d\n" . product . twoSumN 2020 $ input printf " Part 2: %d\n" . product . threeSumN 2020 $ input -- Haskell comment inside code environment. main :: IO () main = getArgs >>= mapM_ output \end{code} \end{document} ================================================ FILE: tests/syntax-tests/source/LiveScript/LICENSE.md ================================================ The `livescript-demo.ls` file has been added from https://github.com/paulmillr/LiveScript.tmbundle under the following license: The MIT License (MIT) Copyright (c) 2012 Paul Miller (http://paulmillr.com/), Jeremy Ashkenas 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. ================================================ FILE: tests/syntax-tests/source/LiveScript/livescript-demo.ls ================================================ a = -> 1 const b = --> 2 var c = ~> 3 d = ~~> e = (a) -> (b) ~> (c) --> (d, e) ~~> 5 dashes-identifiers = -> a - a b -- c 1-1 1- -1 a- a a -a //abc #eaze #@ // // a #baze // publi if it is \abc and ($-y = !(a,) ->) ~= map //a#// then match that | _ | otherwise => implements $("#abc #@a") switch |a=>b | a then b if a => b else c underscores_i$d = -> /regexp1/ and //regexp2//g 'strings' and "strings" and \strings ([2 til 10] or [1 to 50]) |> map (* 2) |> filter (> 5) |> fold (+) setTimeout _, 3000 <| do-stuff _.map; _abc; __ class Class extends Anc-est-or (args) -> copy = (from, to, callback) --> error, data <- read file return callback error if error? error <~ write file, data return callback error if error? callback() $(\#gafBr).text $t.fmtFloat(efb.gaf) -> ~> ~~> --> # Comment /* Comment */ # error, data <- read file /* error, data <- read file */ add = (a=1, b=2) --> a + b add 1 2 do-stuff! do-stuff? # do-stuff? 1 do-stuff + 1 @do-stuff +1 @do-stuff /1 a b c |> d <| e f(g) 'cats' is 'cats' 'cats' `_.is-insensitive` 'CATS' setTimeout _, 1000 <| !-> console.log 'Who summoned me' private-list = yield @get-private-list! switch | true => "#@@spaghetti" ~function add a=1, b=2 => a + b row.0._id new Spaghetti (++a++) (++ 2 ++) (.cool.) (+ a -) (/ 2 *) (ina -a in) (-> a) (ina in$a) (a is-in) (in) ((((((+ a((a)))))))) ================================================ FILE: tests/syntax-tests/source/Log/example.log ================================================ 2021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html 2021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html 2022-03-16T17:41:02.519 helix_term::application [WARN] unhandled window/showMessage: ShowMessageParams { typ: Error, message: "rust-analyzer failed to load workspace: Failed to read Cargo metadata from Cargo.toml file /home/zeta/dev/raytracer/Cargo.toml, cargo 1.61.0-nightly (65c8266 2022-03-09): Failed to run `\"cargo\" \"metadata\" \"--format-version\" \"1\" \"--manifest-path\" \"/home/zeta/dev/raytracer/Cargo.toml\" \"--filter-platform\" \"wasm32-unknown-unknown\"`: `cargo metadata` exited with an error: Updating crates.io index\nerror: failed to select a version for `parking_lot`.\n ... required by package `raytracer v0.1.0 (/home/zeta/dev/raytracer)`\nversions that meet the requirements `^0.12.0` are: 0.12.0\n\nthe package `raytracer` depends on `parking_lot`, with features: `wasm-bindgen` but `parking_lot` does not have these features.\n\n\nfailed to select a version for `parking_lot` which could resolve this conflict\n" } ================================================ FILE: tests/syntax-tests/source/Lua/test.lua ================================================ --- Finds factorial of a number. -- @param value Number to find factorial. -- @return Factorial of number. local function factorial(value) if value <= 1 then return 1 else return value * factorial(value - 1) end end --- Joins a table of strings into a new string. -- @param table Table of strings. -- @param separator Separator character. -- @return Joined string. local function join(table, separator) local data = "" for index, value in ipairs(table) do data = data .. value .. separator end data = data:sub(1, data:len() - 1) return data end local a = factorial(5) print(a) local b = join({ "l", "u", "a" }, ",") print(b) ================================================ FILE: tests/syntax-tests/source/MATLAB/LICENSE.md ================================================ The `test.matlab` file is a modified version of https://github.com/pygments/pygments/blob/3e1b79c82d2df318f63f24984d875fd2a3400808/tests/test_matlab.py under the following license: Copyright (c) 2006-2020 by the respective authors (see AUTHORS file). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: tests/syntax-tests/source/MATLAB/test.matlab ================================================ function zz=sample(aa) %%%%%%%%%%%%%%%%%% % some comments %%%%%%%%%%%%%%%%%% x = 'a string'; % some 'ticks' in a comment y = 'a string with ''interal'' quotes'; for i=1:20 disp(i); end a = rand(30); b = rand(30); c = a .* b ./ a \ ... comment at end of line and continuation (b .* a + b - a); c = a' * b'; % note: these ticks are for transpose, not quotes. disp('a comment symbol, %, in a string'); !echo abc % this isn't a comment - it's passed to system command function y=myfunc(x) y = exp(x); %{ a block comment %} function no_arg_func fprintf('%s\n', 'function with no args') end ================================================ FILE: tests/syntax-tests/source/Makefile/LICENSE.md ================================================ The `Makefile` (https://github.com/redis/redis/blob/6.0.8/src/Makefile) file has been added from Redis (https://github.com/redis/redis) under the following license: Copyright (c) 2006-2020, Salvatore Sanfilippo All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: tests/syntax-tests/source/Makefile/Makefile ================================================ # Redis Makefile # Copyright (C) 2009 Salvatore Sanfilippo # This file is released under the BSD license, see the COPYING file # # The Makefile composes the final FINAL_CFLAGS and FINAL_LDFLAGS using # what is needed for Redis plus the standard CFLAGS and LDFLAGS passed. # However when building the dependencies (Jemalloc, Lua, Hiredis, ...) # CFLAGS and LDFLAGS are propagated to the dependencies, so to pass # flags only to be used when compiling / linking Redis itself REDIS_CFLAGS # and REDIS_LDFLAGS are used instead (this is the case of 'make gcov'). # # Dependencies are stored in the Makefile.dep file. To rebuild this file # Just use 'make dep', but this is only needed by developers. release_hdr := $(shell sh -c './mkreleasehdr.sh') uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') OPTIMIZATION?=-O2 DEPENDENCY_TARGETS=hiredis linenoise lua NODEPS:=clean distclean # Default settings STD=-std=c11 -pedantic -DREDIS_STATIC='' ifneq (,$(findstring clang,$(CC))) ifneq (,$(findstring FreeBSD,$(uname_S))) STD+=-Wno-c11-extensions endif endif WARN=-Wall -W -Wno-missing-field-initializers OPT=$(OPTIMIZATION) PREFIX?=/usr/local INSTALL_BIN=$(PREFIX)/bin INSTALL=install PKG_CONFIG?=pkg-config # Default allocator defaults to Jemalloc if it's not an ARM MALLOC=libc ifneq ($(uname_M),armv6l) ifneq ($(uname_M),armv7l) ifeq ($(uname_S),Linux) MALLOC=jemalloc endif endif endif # To get ARM stack traces if Redis crashes we need a special C flag. ifneq (,$(filter aarch64 armv,$(uname_M))) CFLAGS+=-funwind-tables else ifneq (,$(findstring armv,$(uname_M))) CFLAGS+=-funwind-tables endif endif # Backwards compatibility for selecting an allocator ifeq ($(USE_TCMALLOC),yes) MALLOC=tcmalloc endif ifeq ($(USE_TCMALLOC_MINIMAL),yes) MALLOC=tcmalloc_minimal endif ifeq ($(USE_JEMALLOC),yes) MALLOC=jemalloc endif ifeq ($(USE_JEMALLOC),no) MALLOC=libc endif # Override default settings if possible -include .make-settings FINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS) FINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG) FINAL_LIBS=-lm DEBUG=-g -ggdb # Linux ARM needs -latomic at linking time ifneq (,$(filter aarch64 armv,$(uname_M))) FINAL_LIBS+=-latomic else ifneq (,$(findstring armv,$(uname_M))) FINAL_LIBS+=-latomic endif endif ifeq ($(uname_S),SunOS) # SunOS ifneq ($(@@),32bit) CFLAGS+= -m64 LDFLAGS+= -m64 endif DEBUG=-g DEBUG_FLAGS=-g export CFLAGS LDFLAGS DEBUG DEBUG_FLAGS INSTALL=cp -pf FINAL_CFLAGS+= -D__EXTENSIONS__ -D_XPG6 FINAL_LIBS+= -ldl -lnsl -lsocket -lresolv -lpthread -lrt else ifeq ($(uname_S),Darwin) # Darwin FINAL_LIBS+= -ldl OPENSSL_CFLAGS=-I/usr/local/opt/openssl/include OPENSSL_LDFLAGS=-L/usr/local/opt/openssl/lib else ifeq ($(uname_S),AIX) # AIX FINAL_LDFLAGS+= -Wl,-bexpall FINAL_LIBS+=-ldl -pthread -lcrypt -lbsd else ifeq ($(uname_S),OpenBSD) # OpenBSD FINAL_LIBS+= -lpthread ifeq ($(USE_BACKTRACE),yes) FINAL_CFLAGS+= -DUSE_BACKTRACE -I/usr/local/include FINAL_LDFLAGS+= -L/usr/local/lib FINAL_LIBS+= -lexecinfo endif else ifeq ($(uname_S),FreeBSD) # FreeBSD FINAL_LIBS+= -lpthread -lexecinfo else ifeq ($(uname_S),DragonFly) # FreeBSD FINAL_LIBS+= -lpthread -lexecinfo else ifeq ($(uname_S),OpenBSD) # OpenBSD FINAL_LIBS+= -lpthread -lexecinfo else ifeq ($(uname_S),NetBSD) # NetBSD FINAL_LIBS+= -lpthread -lexecinfo else # All the other OSes (notably Linux) FINAL_LDFLAGS+= -rdynamic FINAL_LIBS+=-ldl -pthread -lrt endif endif endif endif endif endif endif endif # Include paths to dependencies FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src # Determine systemd support and/or build preference (defaulting to auto-detection) BUILD_WITH_SYSTEMD=no # If 'USE_SYSTEMD' in the environment is neither "no" nor "yes", try to # auto-detect libsystemd's presence and link accordingly. ifneq ($(USE_SYSTEMD),no) LIBSYSTEMD_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libsystemd && echo $$?) # If libsystemd cannot be detected, continue building without support for it # (unless a later check tells us otherwise) ifeq ($(LIBSYSTEMD_PKGCONFIG),0) BUILD_WITH_SYSTEMD=yes endif endif ifeq ($(USE_SYSTEMD),yes) ifneq ($(LIBSYSTEMD_PKGCONFIG),0) $(error USE_SYSTEMD is set to "$(USE_SYSTEMD)", but $(PKG_CONFIG) cannot find libsystemd) endif # Force building with libsystemd BUILD_WITH_SYSTEMD=yes endif ifeq ($(BUILD_WITH_SYSTEMD),yes) FINAL_LIBS+=$(shell $(PKG_CONFIG) --libs libsystemd) FINAL_CFLAGS+= -DHAVE_LIBSYSTEMD endif ifeq ($(MALLOC),tcmalloc) FINAL_CFLAGS+= -DUSE_TCMALLOC FINAL_LIBS+= -ltcmalloc endif ifeq ($(MALLOC),tcmalloc_minimal) FINAL_CFLAGS+= -DUSE_TCMALLOC FINAL_LIBS+= -ltcmalloc_minimal endif ifeq ($(MALLOC),jemalloc) DEPENDENCY_TARGETS+= jemalloc FINAL_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS) endif ifeq ($(BUILD_TLS),yes) FINAL_CFLAGS+=-DUSE_OPENSSL $(OPENSSL_CFLAGS) FINAL_LDFLAGS+=$(OPENSSL_LDFLAGS) LIBSSL_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libssl && echo $$?) ifeq ($(LIBSSL_PKGCONFIG),0) LIBSSL_LIBS=$(shell $(PKG_CONFIG) --libs libssl) else LIBSSL_LIBS=-lssl endif LIBCRYPTO_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libcrypto && echo $$?) ifeq ($(LIBCRYPTO_PKGCONFIG),0) LIBCRYPTO_LIBS=$(shell $(PKG_CONFIG) --libs libcrypto) else LIBCRYPTO_LIBS=-lcrypto endif FINAL_LIBS += ../deps/hiredis/libhiredis_ssl.a $(LIBSSL_LIBS) $(LIBCRYPTO_LIBS) endif REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS) REDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS) REDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL) CCCOLOR="\033[34m" LINKCOLOR="\033[34;1m" SRCCOLOR="\033[33m" BINCOLOR="\033[37;1m" MAKECOLOR="\033[32;1m" ENDCOLOR="\033[0m" ifndef V QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2; QUIET_LINK = @printf ' %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2; QUIET_INSTALL = @printf ' %b %b\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2; endif REDIS_SERVER_NAME=redis-server REDIS_SENTINEL_NAME=redis-sentinel REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o gopher.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o REDIS_CLI_NAME=redis-cli REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o crcspeed.o crc64.o siphash.o crc16.o REDIS_BENCHMARK_NAME=redis-benchmark REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o REDIS_CHECK_RDB_NAME=redis-check-rdb REDIS_CHECK_AOF_NAME=redis-check-aof all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) @echo "" @echo "Hint: It's a good idea to run 'make test' ;)" @echo "" Makefile.dep: -$(REDIS_CC) -MM *.c > Makefile.dep 2> /dev/null || true ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS)))) -include Makefile.dep endif .PHONY: all persist-settings: distclean echo STD=$(STD) >> .make-settings echo WARN=$(WARN) >> .make-settings echo OPT=$(OPT) >> .make-settings echo MALLOC=$(MALLOC) >> .make-settings echo BUILD_TLS=$(BUILD_TLS) >> .make-settings echo USE_SYSTEMD=$(USE_SYSTEMD) >> .make-settings echo CFLAGS=$(CFLAGS) >> .make-settings echo LDFLAGS=$(LDFLAGS) >> .make-settings echo REDIS_CFLAGS=$(REDIS_CFLAGS) >> .make-settings echo REDIS_LDFLAGS=$(REDIS_LDFLAGS) >> .make-settings echo PREV_FINAL_CFLAGS=$(FINAL_CFLAGS) >> .make-settings echo PREV_FINAL_LDFLAGS=$(FINAL_LDFLAGS) >> .make-settings -(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS)) .PHONY: persist-settings # Prerequisites target .make-prerequisites: @touch $@ # Clean everything, persist settings and build dependencies if anything changed ifneq ($(strip $(PREV_FINAL_CFLAGS)), $(strip $(FINAL_CFLAGS))) .make-prerequisites: persist-settings endif ifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS))) .make-prerequisites: persist-settings endif # redis-server $(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(FINAL_LIBS) # redis-sentinel $(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME) $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) # redis-check-rdb $(REDIS_CHECK_RDB_NAME): $(REDIS_SERVER_NAME) $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_RDB_NAME) # redis-check-aof $(REDIS_CHECK_AOF_NAME): $(REDIS_SERVER_NAME) $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME) # redis-cli $(REDIS_CLI_NAME): $(REDIS_CLI_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS) # redis-benchmark $(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS) dict-benchmark: dict.c zmalloc.c sds.c siphash.c $(REDIS_CC) $(FINAL_CFLAGS) $^ -D DICT_BENCHMARK_MAIN -o $@ $(FINAL_LIBS) DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d) -include $(DEP) # Because the jemalloc.h header is generated as a part of the jemalloc build, # building it should complete before building any other object. Instead of # depending on a single artifact, build all dependencies first. %.o: %.c .make-prerequisites $(REDIS_CC) -MMD -o $@ -c $< clean: rm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep dict-benchmark rm -f $(DEP) .PHONY: clean distclean: clean -(cd ../deps && $(MAKE) distclean) -(rm -f .make-*) .PHONY: distclean test: $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME) @(cd ..; ./runtest) test-sentinel: $(REDIS_SENTINEL_NAME) @(cd ..; ./runtest-sentinel) check: test lcov: $(MAKE) gcov @(set -e; cd ..; ./runtest --clients 1) @geninfo -o redis.info . @genhtml --legend -o lcov-html redis.info test-sds: sds.c sds.h $(REDIS_CC) sds.c zmalloc.c -DSDS_TEST_MAIN $(FINAL_LIBS) -o /tmp/sds_test /tmp/sds_test .PHONY: lcov bench: $(REDIS_BENCHMARK_NAME) ./$(REDIS_BENCHMARK_NAME) 32bit: @echo "" @echo "WARNING: if it fails under Linux you probably need to install libc6-dev-i386" @echo "" $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" gcov: $(MAKE) REDIS_CFLAGS="-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST" REDIS_LDFLAGS="-fprofile-arcs -ftest-coverage" noopt: $(MAKE) OPTIMIZATION="-O0" valgrind: $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" helgrind: $(MAKE) OPTIMIZATION="-O0" MALLOC="libc" CFLAGS="-D__ATOMIC_VAR_FORCE_SYNC_MACROS" src/help.h: @../utils/generate-command-help.rb > help.h install: all @mkdir -p $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN) @ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME) uninstall: rm -f $(INSTALL_BIN)/{$(REDIS_SERVER_NAME),$(REDIS_BENCHMARK_NAME),$(REDIS_CLI_NAME),$(REDIS_CHECK_RDB_NAME),$(REDIS_CHECK_AOF_NAME),$(REDIS_SENTINEL_NAME)} ================================================ FILE: tests/syntax-tests/source/Manpage/bat-0.16.man ================================================ BAT(1) General Commands Manual BAT(1) NAME bat - a cat(1) clone with syntax highlighting and Git integration. USAGE bat [OPTIONS] [FILE]... bat cache [CACHE-OPTIONS] [--build|--clear] DESCRIPTION bat prints the syntax-highlighted content of a collection of FILEs to the terminal. If no FILE is specified, or when FILE is '-', it reads from standard input. bat supports a large number of programming and markup languages. It also communicates with git(1) to show modifications with respect to the git index. bat automatically pipes its output through a pager (by de‐ fault: less). Whenever the output of bat goes to a non-interactive terminal, i.e. when the output is piped into another process or into a file, bat will act as a drop-in replacement for cat(1) and fall back to printing the plain file contents. OPTIONS General remarks: Command-line options like '-l'/'--language' that take values can be specified as either '--language value', '--lan‐ guage=value', '-l value' or '-lvalue'. -A, --show-all Show non-printable characters like space, tab or newline. Use '--tabs' to control the width of the tab-placeholders. -p, --plain Only show plain style, no decorations. This is an alias for '--style=plain'. When '-p' is used twice ('-pp'), it also dis‐ ables automatic paging (alias for '--style=plain --pager=never'). -l, --language Explicitly set the language for syntax highlighting. The lan‐ guage can be specified as a name (like 'C++' or 'LaTeX') or pos‐ sible file extension (like 'cpp', 'hpp' or 'md'). Use '--list-languages' to show all supported language names and file extensions. -H, --highlight-line ... Highlight the specified line ranges with a different background color For example: --highlight-line 40 highlights line 40 --highlight-line 30:40 highlights lines 30 to 40 --highlight-line :40 highlights lines 1 to 40 --highlight-line 40: highlights lines 40 to the end of the file --tabs Set the tab width to T spaces. Use a width of 0 to pass tabs through directly --wrap Specify the text-wrapping mode (*auto*, never, character). The '--terminal-width' option can be used in addition to control the output width. --terminal-width Explicitly set the width of the terminal instead of determining it automatically. If prefixed with '+' or '-', the value will be treated as an offset to the actual terminal width. See also: '--wrap'. -n, --number Only show line numbers, no other decorations. This is an alias for '--style=numbers' --color Specify when to use colored output. The automatic mode only en‐ ables colors if an interactive terminal is detected. Possible values: *auto*, never, always. --italic-text Specify when to use ANSI sequences for italic text in the out‐ put. Possible values: always, *never*. --decorations Specify when to use the decorations that have been specified via '--style'. The automatic mode only enables decorations if an in‐ teractive terminal is detected. Possible values: *auto*, never, always. -f, --force-colorization Alias for '--decorations=always --color=always'. This is useful if the output of bat is piped to another program, but you want to keep the colorization/decorations. --paging Specify when to use the pager. To disable the pager, use '--pag‐ ing=never' or its alias, -P. To disable the pager permanently, set BAT_PAGER to an empty string. To control which pager is used, see the '--pager' option. Possible values: *auto*, never, always. --pager Determine which pager is used. This option will override the PAGER and BAT_PAGER environment variables. The default pager is 'less'. To control when the pager is used, see the '--paging' option. Example: '--pager "less -RF"'. -m, --map-syntax ... Map a glob pattern to an existing syntax name. The glob pattern is matched on the full path and the filename. For example, to highlight *.build files with the Python syntax, use -m '*.build:Python'. To highlight files named '.myignore' with the Git Ignore syntax, use -m '.myignore:Git Ignore'. --theme Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To set a default theme, add the '--theme="..."' option to the configuration file or export the BAT_THEME environment variable (e.g.: export BAT_THEME="..."). --list-themes Display a list of supported themes for syntax highlighting. --style Configure which elements (line numbers, file headers, grid bor‐ ders, Git modifications, ..) to display in addition to the file contents. The argument is a comma-separated list of components to display (e.g. 'numbers,changes,grid') or a pre-defined style ('full'). To set a default style, add the '--style=".."' option to the configuration file or export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible values: *auto*, full, plain, changes, header, grid, numbers, snip. -r, --line-range ... Only print the specified range of lines for each file. For exam‐ ple: --line-range 30:40 prints lines 30 to 40 --line-range :40 prints lines 1 to 40 --line-range 40: prints lines 40 to the end of the file -L, --list-languages Display a list of supported languages for syntax highlighting. -u, --unbuffered This option exists for POSIX-compliance reasons ('u' is for 'un‐ buffered'). The output is always unbuffered - this option is simply ignored. -h, --help Print this help message. -V, --version Show version information. POSITIONAL ARGUMENTS ... Files to print and concatenate. Use a dash ('-') or no argument at all to read from standard input. SUBCOMMANDS cache - Modify the syntax-definition and theme cache. FILES bat can also be customized with a configuration file. The location of the file is dependent on your operating system. To get the default path for your system, call: bat --config-file Alternatively, you can use the BAT_CONFIG_PATH environment variable to point bat to a non-default location of the configuration file. ADDING CUSTOM LANGUAGES bat supports Sublime Text .sublime-syntax language files, and can be customized to add additional languages to your local installation. To do this, add the .sublime-snytax language files to `$(bat --config- dir)/syntaxes` and run `bat cache --build`. Example: 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 # And then build the cache. bat cache --build Once the cache is built, the new language will be visible in `bat --list-languages`. If you ever want to remove the custom languages, you can clear the cache with `bat cache --clear`. ADDING CUSTOM THEMES Similarly to custom languages, bat supports Sublime Text .tmTheme themes. These can be installed to `$(bat --config-dir)/themes`, and are added to the cache with `bat cache --build`. MORE INFORMATION For more information and up-to-date documentation, visit the bat repo: https://github.com/sharkdp/bat BAT(1) ================================================ FILE: tests/syntax-tests/source/Manpage/fzf-0.33.0.man ================================================ fzf(1) fzf - a command-line fuzzy finder fzf(1) NAME fzf - a command-line fuzzy finder SYNOPSIS fzf [options] DESCRIPTION fzf is a general-purpose command-line fuzzy finder. OPTIONS Search mode -x, --extended Extended-search mode. Since 0.10.9, this is enabled by default. You can disable it with +x or --no-extended. -e, --exact Enable exact-match -i Case-insensitive match (default: smart-case match) +i Case-sensitive match --literal Do not normalize latin script letters for matching. --scheme=SCHEME Choose scoring scheme tailored for different types of input. default Generic scoring scheme designed to work well with any type of input path Scoring scheme for paths (additional bonus point only after path separator) history Scoring scheme for command history (no additional bonus points). Sets --tiebreak=index as well. --algo=TYPE Fuzzy matching algorithm (default: v2) v2 Optimal scoring algorithm (quality) v1 Faster but not guaranteed to find the optimal result (performance) -n, --nth=N[,..] Comma-separated list of field index expressions for limiting search scope. See FIELD INDEX EXPRESSION for the details. --with-nth=N[,..] Transform the presentation of each line using field index expressions -d, --delimiter=STR Field delimiter regex for --nth and --with-nth (default: AWK-style) --disabled Do not perform search. With this option, fzf becomes a simple selector interface rather than a "fuzzy finder". You can later enable the search using enable-search or toggle- search action. Search result +s, --no-sort Do not sort the result --tac Reverse the order of the input e.g. history | fzf --tac --no-sort --tiebreak=CRI[,..] Comma-separated list of sort criteria to apply when the scores are tied. length Prefers line with shorter length chunk Prefers line with shorter matched chunk (delimited by whitespaces) begin Prefers line with matched substring closer to the beginning end Prefers line with matched substring closer to the end index Prefers line that appeared earlier in the input stream - Each criterion should appear only once in the list - index is only allowed at the end of the list - index is implicitly appended to the list when not specified - Default is length (or equivalently length,index) - If end is found in the list, fzf will scan each line backwards Interface -m, --multi Enable multi-select with tab/shift-tab. It optionally takes an integer argument which denotes the maximum number of items that can be selected. +m, --no-multi Disable multi-select --no-mouse Disable mouse --bind=KEYBINDS Comma-separated list of custom key bindings. See KEY/EVENT BINDINGS for the details. --cycle Enable cyclic scroll --keep-right Keep the right end of the line visible when it's too long. Effective only when the query string is empty. --scroll-off=LINES Number of screen lines to keep above or below when scrolling to the top or to the bottom (default: 0). --no-hscroll Disable horizontal scroll --hscroll-off=COLS Number of screen columns to keep to the right of the highlighted substring (default: 10). Setting it to a large value will cause the text to be positioned on the center of the screen. --filepath-word Make word-wise movements and actions respect path separators. The following actions are affected: backward-kill-word backward-word forward-word kill-word --jump-labels=CHARS Label characters for jump and jump-accept Layout --height=HEIGHT[%] Display fzf window below the cursor with the given height instead of using the full screen. --min-height=HEIGHT Minimum height when --height is given in percent (default: 10). Ignored when --height is not specified. --layout=LAYOUT Choose the layout (default: default) default Display from the bottom of the screen reverse Display from the top of the screen reverse-list Display from the top of the screen, prompt at the bottom --reverse A synonym for --layout=reverse --border[=BORDER_OPT] Draw border around the finder rounded Border with rounded corners (default) sharp Border with sharp corners horizontal Horizontal lines above and below the finder vertical Vertical lines on each side of the finder top (up) bottom (down) left right none --no-unicode Use ASCII characters instead of Unicode box drawing characters to draw border --margin=MARGIN Comma-separated expression for margins around the finder. TRBL Same margin for top, right, bottom, and left TB,RL Vertical, horizontal margin T,RL,B Top, horizontal, bottom margin T,R,B,L Top, right, bottom, left margin Each part can be given in absolute number or in percentage relative to the terminal size with % suffix. e.g. fzf --margin 10% fzf --margin 1,5% --padding=PADDING Comma-separated expression for padding inside the border. Padding is distinguishable from margin only when --border option is used. e.g. fzf --margin 5% --padding 5% --border --preview 'cat {}' \ --color bg:#222222,preview-bg:#333333 TRBL Same padding for top, right, bottom, and left TB,RL Vertical, horizontal padding T,RL,B Top, horizontal, bottom padding T,R,B,L Top, right, bottom, left padding --info=STYLE Determines the display style of finder info. default Display on the next line to the prompt inline Display on the same line hidden Do not display finder info --no-info A synonym for --info=hidden --prompt=STR Input prompt (default: '> ') --pointer=STR Pointer to the current line (default: '>') --marker=STR Multi-select marker (default: '>') --header=STR The given string will be printed as the sticky header. The lines are displayed in the given order from top to bottom regardless of --layout option, and are not affected by --with-nth. ANSI color codes are processed even when --ansi is not set. --header-lines=N The first N lines of the input are treated as the sticky header. When --with-nth is set, the lines are transformed just like the other lines that follow. --header-first Print header before the prompt line --ellipsis=STR Ellipsis to show when line is truncated (default: '..') Display --ansi Enable processing of ANSI color codes --tabstop=SPACES Number of spaces for a tab character (default: 8) --color=[BASE_SCHEME][,COLOR_NAME[:ANSI_COLOR][:ANSI_ATTRIBUTES]]... Color configuration. The name of the base color scheme is followed by custom color mappings. BASE SCHEME: (default: dark on 256-color terminal, otherwise 16) dark Color scheme for dark 256-color terminal light Color scheme for light 256-color terminal 16 Color scheme for 16-color terminal bw No colors (equivalent to --no-color) COLOR NAMES: fg Text bg Background preview-fg Preview window text preview-bg Preview window background hl Highlighted substrings fg+ Text (current line) bg+ Background (current line) gutter Gutter on the left (defaults to bg+) hl+ Highlighted substrings (current line) query Query string disabled Query string when search is disabled info Info line (match counters) border Border around the window (--border and --preview) prompt Prompt pointer Pointer to the current line marker Multi-select marker spinner Streaming input indicator header Header ANSI COLORS: -1 Default terminal foreground/background color (or the original color of the text) 0 ~ 15 16 base colors black red green yellow blue magenta cyan white bright-black (gray | grey) bright-red bright-green bright-yellow bright-blue bright-magenta bright-cyan bright-white 16 ~ 255 ANSI 256 colors #rrggbb 24-bit colors ANSI ATTRIBUTES: (Only applies to foreground colors) regular Clears previously set attributes; should precede the other ones bold underline reverse dim italic strikethrough EXAMPLES: # Seoul256 theme with 8-bit colors # (https://github.com/junegunn/seoul256.vim) fzf --color='bg:237,bg+:236,info:143,border:240,spinner:108' \ --color='hl:65,fg:252,header:65,fg+:252' \ --color='pointer:161,marker:168,prompt:110,hl+:108' # Seoul256 theme with 24-bit colors fzf --color='bg:#4B4B4B,bg+:#3F3F3F,info:#BDBB72,border:#6B6B6B,spinner:#98BC99' \ --color='hl:#719872,fg:#D9D9D9,header:#719872,fg+:#D9D9D9' \ --color='pointer:#E12672,marker:#E17899,prompt:#98BEDE,hl+:#98BC99' --no-bold Do not use bold text --black Use black background History --history=HISTORY_FILE Load search history from the specified file and update the file on completion. When enabled, CTRL-N and CTRL-P are automatically remapped to next-history and previous-history. --history-size=N Maximum number of entries in the history file (default: 1000). The file is automatically truncated when the number of the lines exceeds the value. Preview --preview=COMMAND Execute the given command for the current line and display the result on the preview window. {} in the command is the placeholder that is replaced to the single-quoted string of the current line. To transform the replacement string, specify field index expressions between the braces (See FIELD INDEX EXPRESSION for the details). e.g. fzf --preview='head -$LINES {}' ls -l | fzf --preview="echo user={3} when={-4..-2}; cat {-1}" --header-lines=1 fzf exports $FZF_PREVIEW_LINES and $FZF_PREVIEW_COLUMNS so that they represent the exact size of the preview window. (It also overrides $LINES and $COLUMNS with the same values but they can be reset by the default shell, so prefer to refer to the ones with FZF_PREVIEW_ prefix.) A placeholder expression starting with + flag will be replaced to the space-separated list of the selected lines (or the current line if no selection was made) individually quoted. e.g. fzf --multi --preview='head -10 {+}' git log --oneline | fzf --multi --preview 'git show {+1}' When using a field index expression, leading and trailing whitespace is stripped from the replacement string. To preserve the whitespace, use the s flag. Also, {q} is replaced to the current query string, and {n} is replaced to zero-based ordinal index of the line. Use {+n} if you want all index numbers when multiple lines are selected. A placeholder expression with f flag is replaced to the path of a temporary file that holds the evaluated list. This is useful when you multi-select a large number of items and the length of the evaluated string may exceed ARG_MAX. e.g. # Press CTRL-A to select 100K items and see the sum of all the numbers. # This won't work properly without 'f' flag due to ARG_MAX limit. seq 100000 | fzf --multi --bind ctrl-a:select-all \ --preview "awk '{sum+=\$1} END {print sum}' {+f}" Note that you can escape a placeholder pattern by prepending a backslash. Preview window will be updated even when there is no match for the current query if any of the placeholder expressions evaluates to a non-empty string. Since 0.24.0, fzf can render partial preview content before the preview command completes. ANSI escape sequence for clearing the display (CSI 2 J) is supported, so you can use it to implement preview window that is constantly updating. e.g. fzf --preview 'for i in $(seq 100000); do (( i % 200 == 0 )) && printf "\033[2J" echo "$i" sleep 0.01 done' --preview-window=[POSITION][,SIZE[%]][,border-BORDER_OPT][,[no]wrap][,[no]follow][,[no]cycle][,[no]hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default][,