diff --git a/.gitignore b/.gitignore index 6a6fc782a..64a837dfd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target helix-term/rustfmt.toml result runtime/grammars +.DS_Store diff --git a/Cargo.lock b/Cargo.lock index 86dace16c..f4f03c797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.1.37" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "shlex", ] @@ -383,7 +383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", "winapi", ] @@ -522,7 +522,7 @@ dependencies = [ "gix-worktree", "once_cell", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -535,7 +535,7 @@ dependencies = [ "gix-date", "gix-utils", "itoa", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -552,7 +552,7 @@ dependencies = [ "gix-trace", "kstring", "smallvec", - "thiserror", + "thiserror 1.0.69", "unicode-bom", ] @@ -562,7 +562,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f78312288bd02052be5dbc2ecbc342c9f4eb791986d86c0a5c06b92dc72efa" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -571,7 +571,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c28b58ba04f0c004722344390af9dbc85888fbb84be1981afb934da4114d4cf" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -597,7 +597,7 @@ dependencies = [ "gix-features", "gix-hash", "memmap2", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -616,7 +616,7 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror", + "thiserror 1.0.69", "unicode-bom", "winnow", ] @@ -631,7 +631,7 @@ dependencies = [ "bstr", "gix-path", "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -643,7 +643,7 @@ dependencies = [ "bstr", "itoa", "jiff", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -664,7 +664,7 @@ dependencies = [ "gix-traverse", "gix-worktree", "imara-diff", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -684,7 +684,7 @@ dependencies = [ "gix-trace", "gix-utils", "gix-worktree", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -700,7 +700,7 @@ dependencies = [ "gix-path", "gix-ref", "gix-sec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -718,7 +718,7 @@ dependencies = [ "once_cell", "prodash", "sha1_smol", - "thiserror", + "thiserror 1.0.69", "walkdir", ] @@ -740,7 +740,7 @@ dependencies = [ "gix-trace", "gix-utils", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -773,7 +773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "952c3a29f1bc1007cc901abce7479943abfa42016db089de33d0a4fa3c85bfe8" dependencies = [ "faster-hex", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -825,7 +825,7 @@ dependencies = [ "memmap2", "rustix", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -836,7 +836,7 @@ checksum = "5102acdf4acae2644e38dbbd18cdfba9597a218f7d85f810fe5430207e03c2de" dependencies = [ "gix-tempfile", "gix-utils", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -855,7 +855,7 @@ dependencies = [ "gix-validate", "itoa", "smallvec", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -877,7 +877,7 @@ dependencies = [ "gix-quote", "parking_lot", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -895,7 +895,7 @@ dependencies = [ "gix-path", "memmap2", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -907,7 +907,7 @@ dependencies = [ "bstr", "faster-hex", "gix-trace", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -920,7 +920,7 @@ dependencies = [ "gix-trace", "home", "once_cell", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -935,7 +935,7 @@ dependencies = [ "gix-config-value", "gix-glob", "gix-path", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -946,7 +946,7 @@ checksum = "f89f9a1525dcfd9639e282ea939f5ab0d09d93cf2b90c1fc6104f1b9582a8e49" dependencies = [ "bstr", "gix-utils", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -966,7 +966,7 @@ dependencies = [ "gix-utils", "gix-validate", "memmap2", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -981,7 +981,7 @@ dependencies = [ "gix-revision", "gix-validate", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -996,7 +996,7 @@ dependencies = [ "gix-hash", "gix-object", "gix-revwalk", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1011,7 +1011,7 @@ dependencies = [ "gix-hashtable", "gix-object", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1046,7 +1046,7 @@ dependencies = [ "gix-pathspec", "gix-worktree", "portable-atomic", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1061,7 +1061,7 @@ dependencies = [ "gix-pathspec", "gix-refspec", "gix-url", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1098,7 +1098,7 @@ dependencies = [ "gix-object", "gix-revwalk", "smallvec", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1110,7 +1110,7 @@ dependencies = [ "bstr", "gix-features", "gix-path", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -1132,7 +1132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e187b263461bc36cea17650141567753bc6207d036cedd1de6e81a52f277ff68" dependencies = [ "bstr", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1263,7 +1263,7 @@ dependencies = [ "log", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "tokio", ] @@ -1319,7 +1319,7 @@ dependencies = [ "serde", "serde_json", "slotmap", - "thiserror", + "thiserror 2.0.3", "tokio", "tokio-stream", ] @@ -1392,7 +1392,7 @@ dependencies = [ "smallvec", "tempfile", "termini", - "thiserror", + "thiserror 2.0.3", "tokio", "tokio-stream", "toml", @@ -1459,7 +1459,7 @@ dependencies = [ "serde_json", "slotmap", "tempfile", - "thiserror", + "thiserror 2.0.3", "tokio", "tokio-stream", "toml", @@ -1755,9 +1755,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libloading" @@ -1911,9 +1911,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "open" -version = "5.3.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" +checksum = "3ecd52f0b8d15c40ce4820aa251ed5de032e5d91fab27f7db2f40d42a8bdf69c" dependencies = [ "is-wsl", "libc", @@ -2128,9 +2128,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags", "errno", @@ -2182,9 +2182,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -2398,18 +2398,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -2551,9 +2571,9 @@ checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-general-category" -version = "0.6.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7" +checksum = "24adfe8311434967077a6adff125729161e6e4934d76f6b7c55318ac5c9246d3" [[package]] name = "unicode-ident" @@ -2691,9 +2711,9 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "which" -version = "6.0.3" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" dependencies = [ "either", "home", diff --git a/Cargo.toml b/Cargo.toml index 763992480..b690267d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ package.helix-term.opt-level = 2 tree-sitter = { version = "0.22" } nucleo = "0.5.0" slotmap = "1.0.7" -thiserror = "1.0" +thiserror = "2.0" [workspace.package] version = "24.7.0" diff --git a/book/src/building-from-source.md b/book/src/building-from-source.md index 42ed57a27..539e9cf86 100644 --- a/book/src/building-from-source.md +++ b/book/src/building-from-source.md @@ -117,7 +117,7 @@ to package the runtime into `/usr/lib/helix/runtime`. The rough steps a build script could follow are: 1. `export HELIX_DEFAULT_RUNTIME=/usr/lib/helix/runtime` -1. `cargo build --profile opt --locked --path helix-term` +1. `cargo build --profile opt --locked` 1. `cp -r runtime $BUILD_DIR/usr/lib/helix/` 1. `cp target/opt/hx $BUILD_DIR/usr/bin/hx` diff --git a/book/src/configuration.md b/book/src/configuration.md index 0cd12568b..317007efc 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -27,8 +27,8 @@ hidden = false You can use a custom configuration file by specifying it with the `-c` or `--config` command line argument, for example `hx -c path/to/custom-config.toml`. -Additionally, you can reload the configuration file by sending the USR1 -signal to the Helix process on Unix operating systems, such as by using the command `pkill -USR1 hx`. +You can reload the config file by issuing the `:config-reload` command. Alternatively, on Unix operating systems, you can reload it by sending the USR1 +signal to the Helix process, such as by using the command `pkill -USR1 hx`. Finally, you can have a `config.toml` local to a project by putting it under a `.helix` directory in your repository. Its settings will be merged with the configuration directory `config.toml` and the built-in configuration. diff --git a/book/src/editor.md b/book/src/editor.md index 82d5f8461..fa5aef47e 100644 --- a/book/src/editor.md +++ b/book/src/editor.md @@ -24,6 +24,7 @@ |--|--|---------| | `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` | | `mouse` | Enable mouse mode | `true` | +| `default-yank-register` | Default register used for yank/paste | `"` | | `middle-click-paste` | Middle click paste support | `true` | | `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` | | `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`
Windows: `["cmd", "/C"]` | @@ -52,6 +53,30 @@ | `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches. If the chosen heuristic is not available, a different one will be used as a fallback (the fallback order being `hybrid` -> `tree-sitter` -> `simple`). | `hybrid` | `jump-label-alphabet` | The characters that are used to generate two character jump labels. Characters at the start of the alphabet are used first. | `"abcdefghijklmnopqrstuvwxyz"` | `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | "disable" +| `clipboard-provider` | Which API to use for clipboard interaction. One of `pasteboard` (MacOS), `wayland`, `x-clip`, `x-sel`, `win-32-yank`, `termux`, `tmux`, `windows`, `termcode`, `none`, or a custom command set. | Platform and environment specific. | + +### `[editor.clipboard-provider]` Section + +Helix can be configured wither to use a builtin clipboard configuration or to use +a provided command. + +For instance, setting it to use OSC 52 termcodes, the configuration would be: +```toml +[editor] +clipboard-provider = "termcode" +``` + +Alternatively, Helix can be configured to use arbitary commands for clipboard integration: + +```toml +[editor.clipboard-provider.custom] +yank = { command = "cat", args = ["test.txt"] } +paste = { command = "tee", args = ["test.txt"] } +primary-yank = { command = "cat", args = ["test-primary.txt"] } # optional +primary-paste = { command = "tee", args = ["test-primary.txt"] } # optional +``` + +For custom commands the contents of the yank/paste is communicated over stdin/stdout. ### `[editor.statusline]` Section @@ -428,7 +453,8 @@ fn main() { The new diagnostic rendering is not yet enabled by default. As soon as end of line or inline diagnostics are enabled the old diagnostics rendering is automatically disabled. The recommended default setting are: -``` +```toml +[editor] end-of-line-diagnostics = "hint" [editor.inline-diagnostics] cursor-line = "warning" # show warnings and errors on the cursorline inline diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 09f15b374..28f25ba3f 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -91,7 +91,7 @@ | hosts | ✓ | | | | | html | ✓ | | | `vscode-html-language-server`, `superhtml` | | hurl | ✓ | ✓ | ✓ | | -| hyprlang | ✓ | | ✓ | | +| hyprlang | ✓ | | ✓ | `hyprls` | | idris | | | | `idris2-lsp` | | iex | ✓ | | | | | ini | ✓ | | | | @@ -136,6 +136,7 @@ | move | ✓ | | | | | msbuild | ✓ | | ✓ | | | nasm | ✓ | ✓ | | | +| nestedtext | ✓ | ✓ | ✓ | | | nickel | ✓ | | ✓ | `nls` | | nim | ✓ | ✓ | ✓ | `nimlangserver` | | nix | ✓ | ✓ | | `nil`, `nixd` | @@ -168,6 +169,7 @@ | purescript | ✓ | ✓ | | `purescript-language-server` | | python | ✓ | ✓ | ✓ | `ruff`, `jedi-language-server`, `pylsp` | | qml | ✓ | | ✓ | `qmlls` | +| quint | ✓ | | | `quint-language-server` | | r | ✓ | | | `R` | | racket | ✓ | | ✓ | `racket` | | regex | ✓ | | | | @@ -189,6 +191,7 @@ | sml | ✓ | | | | | snakemake | ✓ | | ✓ | `pylsp` | | solidity | ✓ | ✓ | | `solc` | +| spade | ✓ | | ✓ | `spade-language-server` | | spicedb | ✓ | | | | | sql | ✓ | ✓ | | | | sshclientconfig | ✓ | | | | @@ -204,6 +207,7 @@ | task | ✓ | | | | | tcl | ✓ | | ✓ | | | templ | ✓ | | | `templ` | +| textproto | ✓ | ✓ | ✓ | | | tfvars | ✓ | | ✓ | `terraform-ls` | | thrift | ✓ | | | | | todotxt | ✓ | | | | @@ -215,7 +219,7 @@ | typespec | ✓ | ✓ | ✓ | `tsp-server` | | typst | ✓ | | | `tinymist`, `typst-lsp` | | ungrammar | ✓ | | | | -| unison | ✓ | | ✓ | | +| unison | ✓ | ✓ | ✓ | | | uxntal | ✓ | | | | | v | ✓ | ✓ | ✓ | `v-analyzer` | | vala | ✓ | ✓ | | `vala-language-server` | diff --git a/book/src/keymap.md b/book/src/keymap.md index 71ae5e31f..28113ea0b 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -112,42 +112,43 @@ Normal mode is the default mode when you launch helix. You can return to it from ### Selection manipulation -| Key | Description | Command | -| ----- | ----------- | ------- | -| `s` | Select all regex matches inside selections | `select_regex` | -| `S` | Split selection into sub selections on regex matches | `split_selection` | -| `Alt-s` | Split selection on newlines | `split_selection_on_newline` | -| `Alt-minus` | Merge selections | `merge_selections` | -| `Alt-_` | Merge consecutive selections | `merge_consecutive_selections` | -| `&` | Align selection in columns | `align_selections` | -| `_` | Trim whitespace from the selection | `trim_selections` | -| `;` | Collapse selection onto a single cursor | `collapse_selection` | -| `Alt-;` | Flip selection cursor and anchor | `flip_selections` | -| `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` | -| `,` | Keep only the primary selection | `keep_primary_selection` | -| `Alt-,` | Remove the primary selection | `remove_primary_selection` | -| `C` | Copy selection onto the next line (Add cursor below) | `copy_selection_on_next_line` | -| `Alt-C` | Copy selection onto the previous line (Add cursor above) | `copy_selection_on_prev_line` | -| `(` | Rotate main selection backward | `rotate_selections_backward` | -| `)` | Rotate main selection forward | `rotate_selections_forward` | -| `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` | -| `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` | -| `%` | Select entire file | `select_all` | -| `x` | Select current line, if already selected, extend to next line | `extend_line_below` | -| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` | -| `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` | -| `J` | Join lines inside selection | `join_selections` | -| `Alt-J` | Join lines inside selection and select the inserted space | `join_selections_space` | -| `K` | Keep selections matching the regex | `keep_selections` | -| `Alt-K` | Remove selections matching the regex | `remove_selections` | -| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` | -| `Alt-o`, `Alt-up` | Expand selection to parent syntax node (**TS**) | `expand_selection` | -| `Alt-i`, `Alt-down` | Shrink syntax tree object selection (**TS**) | `shrink_selection` | -| `Alt-p`, `Alt-left` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` | -| `Alt-n`, `Alt-right` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` | -| `Alt-a` | Select all sibling nodes in syntax tree (**TS**) | `select_all_siblings` | -| `Alt-e` | Move to end of parent node in syntax tree (**TS**) | `move_parent_node_end` | -| `Alt-b` | Move to start of parent node in syntax tree (**TS**) | `move_parent_node_start` | +| Key | Description | Command | +| ----- | ----------- | ------- | +| `s` | Select all regex matches inside selections | `select_regex` | +| `S` | Split selection into sub selections on regex matches | `split_selection` | +| `Alt-s` | Split selection on newlines | `split_selection_on_newline` | +| `Alt-minus` | Merge selections | `merge_selections` | +| `Alt-_` | Merge consecutive selections | `merge_consecutive_selections` | +| `&` | Align selection in columns | `align_selections` | +| `_` | Trim whitespace from the selection | `trim_selections` | +| `;` | Collapse selection onto a single cursor | `collapse_selection` | +| `Alt-;` | Flip selection cursor and anchor | `flip_selections` | +| `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` | +| `,` | Keep only the primary selection | `keep_primary_selection` | +| `Alt-,` | Remove the primary selection | `remove_primary_selection` | +| `C` | Copy selection onto the next line (Add cursor below) | `copy_selection_on_next_line` | +| `Alt-C` | Copy selection onto the previous line (Add cursor above) | `copy_selection_on_prev_line` | +| `(` | Rotate main selection backward | `rotate_selections_backward` | +| `)` | Rotate main selection forward | `rotate_selections_forward` | +| `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` | +| `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` | +| `%` | Select entire file | `select_all` | +| `x` | Select current line, if already selected, extend to next line | `extend_line_below` | +| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` | +| `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` | +| `J` | Join lines inside selection | `join_selections` | +| `Alt-J` | Join lines inside selection and select the inserted space | `join_selections_space` | +| `K` | Keep selections matching the regex | `keep_selections` | +| `Alt-K` | Remove selections matching the regex | `remove_selections` | +| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` | +| `Alt-o`, `Alt-up` | Expand selection to parent syntax node (**TS**) | `expand_selection` | +| `Alt-i`, `Alt-down` | Shrink syntax tree object selection (**TS**) | `shrink_selection` | +| `Alt-p`, `Alt-left` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` | +| `Alt-n`, `Alt-right` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` | +| `Alt-a` | Select all sibling nodes in syntax tree (**TS**) | `select_all_siblings` | +| `Alt-I`, `Alt-Shift-down`| Select all children nodes in syntax tree (**TS**) | `select_all_children` | +| `Alt-e` | Move to end of parent node in syntax tree (**TS**) | `move_parent_node_end` | +| `Alt-b` | Move to start of parent node in syntax tree (**TS**) | `move_parent_node_start` | ### Search @@ -281,7 +282,7 @@ This layer is a kludge of mappings, mostly pickers. | Key | Description | Command | | ----- | ----------- | ------- | -| `f` | Open file picker | `file_picker` | +| `f` | Open file picker at LSP workspace root | `file_picker` | | `F` | Open file picker at current working directory | `file_picker_in_current_directory` | | `b` | Open buffer picker | `buffer_picker` | | `j` | Open jumplist picker | `jumplist_picker` | diff --git a/book/src/package-managers.md b/book/src/package-managers.md index 441de45e0..a08baccd1 100644 --- a/book/src/package-managers.md +++ b/book/src/package-managers.md @@ -101,7 +101,15 @@ Download the official Helix AppImage from the [latest releases](https://github.c chmod +x helix-*.AppImage # change permission for executable mode ./helix-*.AppImage # run helix ``` - + +You can optionally [add the `.desktop` file](./building-from-source.md#configure-the-desktop-shortcut). Helix must be installed in `PATH` with the name `hx`. For example: +```sh +mkdir -p "$HOME/.local/bin" +mv helix-*.AppImage "$HOME/.local/bin/hx" +``` + +and make sure `~/.local/bin` is in your `PATH`. + ## macOS ### Homebrew Core diff --git a/book/src/remapping.md b/book/src/remapping.md index e3efdf16f..41e20f84b 100644 --- a/book/src/remapping.md +++ b/book/src/remapping.md @@ -4,10 +4,31 @@ Helix currently supports one-way key remapping through a simple TOML configurati file. (More powerful solutions such as rebinding via commands will be available in the future). +There are three kinds of commands that can be used in keymaps: + +* Static commands: commands like `move_char_right` which are usually bound to + keys and used for movement and editing. A list of static commands is + available in the [Keymap](./keymap.html) documentation and in the source code + in [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) + at the invocation of `static_commands!` macro. +* Typable commands: commands that can be executed from command mode (`:`), for + example `:write!`. See the [Commands](./commands.html) documentation for a + list of available typeable commands or the `TypableCommandList` declaration in + the source code at [`helix-term/src/commands/typed.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands/typed.rs). +* Macros: sequences of keys that are executed in order. These keybindings + start with `@` and then list any number of keys to be executed. For example + `@miw` can be used to select the surrounding word. For now, macro keybindings + are not allowed in keybinding sequences due to limitations in the way that + command sequences are executed. Modifier keys (e.g. Alt+o) can be used + like `""`, e.g. `"@miw"` + To remap keys, create a `config.toml` file in your `helix` configuration directory (default `~/.config/helix` on Linux systems) with a structure like this: +> 💡 To set a modifier + key as a keymap, type `A-X = ...` or `C-X = ...` for Alt + X or Ctrl + X. Combine with Shift using a dash, e.g. `C-S-esc`. +> Within macros, wrap them in `<>`, e.g. `` and `` to distinguish from the `A` or `C` keys. + ```toml # At most one section each of 'keys.normal', 'keys.insert' and 'keys.select' [keys.normal] @@ -18,6 +39,7 @@ w = "move_line_up" # Maps the 'w' key move_line_up "C-S-esc" = "extend_line" # Maps Ctrl-Shift-Escape to extend_line g = { a = "code_action" } # Maps `ga` to show possible code actions "ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below then re-enter normal mode +"A-x" = "@x" # Maps Alt-x to a macro selecting the whole line and deleting it without yanking it [keys.insert] "A-x" = "normal_mode" # Maps Alt-X to enter normal mode @@ -74,21 +96,3 @@ Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes | Escape | `"esc"` | Keys can be disabled by binding them to the `no_op` command. - -## Commands - -There are three kinds of commands that can be used in keymaps: - -* Static commands: commands like `move_char_right` which are usually bound to - keys and used for movement and editing. A list of static commands is - available in the [Keymap](./keymap.html) documentation and in the source code - in [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) - at the invocation of `static_commands!` macro and the `TypableCommandList`. -* Typable commands: commands that can be executed from command mode (`:`), for - example `:write!`. See the [Commands](./commands.html) documentation for a - list of available typeable commands. -* Macros: sequences of keys that are executed in order. These keybindings - start with `@` and then list any number of keys to be executed. For example - `@miw` can be used to select the surrounding word. For now, macro keybindings - are not allowed in keybinding sequences due to limitations in the way that - command sequences are executed. diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index db06f0081..d7f9d7206 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -29,7 +29,7 @@ unicode-segmentation = "1.12" # For now lets lock the version to avoid rendering glitches # when installing without `--locked` unicode-width = "=0.1.12" -unicode-general-category = "0.6" +unicode-general-category = "1.0" slotmap.workspace = true tree-sitter.workspace = true once_cell = "1.20" diff --git a/helix-core/src/wrap.rs b/helix-core/src/wrap.rs index f32d6f4bc..337b389ae 100644 --- a/helix-core/src/wrap.rs +++ b/helix-core/src/wrap.rs @@ -4,6 +4,8 @@ use textwrap::{Options, WordSplitter::NoHyphenation}; /// Given a slice of text, return the text re-wrapped to fit it /// within the given width. pub fn reflow_hard_wrap(text: &str, text_width: usize) -> SmartString { - let options = Options::new(text_width).word_splitter(NoHyphenation); + let options = Options::new(text_width) + .word_splitter(NoHyphenation) + .word_separator(textwrap::WordSeparator::AsciiSpace); textwrap::refill(text, options).into() } diff --git a/helix-lsp-types/Cargo.toml b/helix-lsp-types/Cargo.toml index b44e4c93a..cb6b94307 100644 --- a/helix-lsp-types/Cargo.toml +++ b/helix-lsp-types/Cargo.toml @@ -23,7 +23,7 @@ license = "MIT" [dependencies] bitflags = "2.6.0" serde = { version = "1.0.215", features = ["derive"] } -serde_json = "1.0.132" +serde_json = "1.0.133" serde_repr = "0.1" url = {version = "2.5.3", features = ["serde"]} diff --git a/helix-stdx/Cargo.toml b/helix-stdx/Cargo.toml index c4fbe5e78..4e85adb5b 100644 --- a/helix-stdx/Cargo.toml +++ b/helix-stdx/Cargo.toml @@ -15,7 +15,7 @@ homepage.workspace = true dunce = "1.0" etcetera = "0.8" ropey = { version = "1.6.1", default-features = false } -which = "6.0" +which = "7.0" regex-cursor = "0.1.4" bitflags = "2.6" diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index cd2cfe034..1c399a47c 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -56,10 +56,10 @@ ignore = "0.4" pulldown-cmark = { version = "0.12", default-features = false } # file type detection content_inspector = "0.2.4" -thiserror = "1.0" +thiserror.workspace = true # opening URLs -open = "5.3.0" +open = "5.3.1" url = "2.5.3" # config @@ -74,7 +74,7 @@ grep-searcher = "0.1.14" [target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100 signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } -libc = "0.2.162" +libc = "0.2.164" [target.'cfg(target_os = "macos")'.dependencies] crossterm = { version = "0.28", features = ["event-stream", "use-dev-tty", "libc"] } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index ee2949fa0..61855d356 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2735,7 +2735,9 @@ fn delete_selection_impl(cx: &mut Context, op: Operation, yank: YankAction) { // yank the selection let text = doc.text().slice(..); let values: Vec = selection.fragments(text).map(Cow::into_owned).collect(); - let reg_name = cx.register.unwrap_or('"'); + let reg_name = cx + .register + .unwrap_or_else(|| cx.editor.config.load().default_yank_register); if let Err(err) = cx.editor.registers.write(reg_name, values) { cx.editor.set_error(err.to_string()); return; @@ -4221,7 +4223,11 @@ fn commit_undo_checkpoint(cx: &mut Context) { // Yank / Paste fn yank(cx: &mut Context) { - yank_impl(cx.editor, cx.register.unwrap_or('"')); + yank_impl( + cx.editor, + cx.register + .unwrap_or(cx.editor.config().default_yank_register), + ); exit_select_mode(cx); } @@ -4282,7 +4288,12 @@ fn yank_joined_impl(editor: &mut Editor, separator: &str, register: char) { fn yank_joined(cx: &mut Context) { let separator = doc!(cx.editor).line_ending.as_str(); - yank_joined_impl(cx.editor, separator, cx.register.unwrap_or('"')); + yank_joined_impl( + cx.editor, + separator, + cx.register + .unwrap_or(cx.editor.config().default_yank_register), + ); exit_select_mode(cx); } @@ -4339,6 +4350,10 @@ fn paste_impl( return; } + if mode == Mode::Insert { + doc.append_changes_to_history(view); + } + let repeat = std::iter::repeat( // `values` is asserted to have at least one entry above. values @@ -4438,7 +4453,12 @@ fn paste_primary_clipboard_before(cx: &mut Context) { } fn replace_with_yanked(cx: &mut Context) { - replace_with_yanked_impl(cx.editor, cx.register.unwrap_or('"'), cx.count()); + replace_with_yanked_impl( + cx.editor, + cx.register + .unwrap_or(cx.editor.config().default_yank_register), + cx.count(), + ); exit_select_mode(cx); } @@ -4501,7 +4521,8 @@ fn paste(editor: &mut Editor, register: char, pos: Paste, count: usize) { fn paste_after(cx: &mut Context) { paste( cx.editor, - cx.register.unwrap_or('"'), + cx.register + .unwrap_or(cx.editor.config().default_yank_register), Paste::After, cx.count(), ); @@ -4511,7 +4532,8 @@ fn paste_after(cx: &mut Context) { fn paste_before(cx: &mut Context) { paste( cx.editor, - cx.register.unwrap_or('"'), + cx.register + .unwrap_or(cx.editor.config().default_yank_register), Paste::Before, cx.count(), ); @@ -5365,7 +5387,8 @@ fn insert_register(cx: &mut Context) { cx.register = Some(ch); paste( cx.editor, - cx.register.unwrap_or('"'), + cx.register + .unwrap_or(cx.editor.config().default_yank_register), Paste::Cursor, cx.count(), ); diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 68ba9bab5..7402a06f3 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1074,7 +1074,7 @@ fn show_clipboard_provider( } cx.editor - .set_status(cx.editor.registers.clipboard_provider_name().to_string()); + .set_status(cx.editor.registers.clipboard_provider_name()); Ok(()) } diff --git a/helix-term/src/health.rs b/helix-term/src/health.rs index 0bbb5735c..e59fd74dc 100644 --- a/helix-term/src/health.rs +++ b/helix-term/src/health.rs @@ -1,10 +1,10 @@ +use crate::config::{Config, ConfigLoadError}; use crossterm::{ style::{Color, Print, Stylize}, tty::IsTty, }; use helix_core::config::{default_lang_config, user_lang_config}; use helix_loader::grammar::load_runtime_file; -use helix_view::clipboard::get_clipboard_provider; use std::io::Write; #[derive(Copy, Clone)] @@ -53,7 +53,6 @@ pub fn general() -> std::io::Result<()> { let lang_file = helix_loader::lang_config_file(); let log_file = helix_loader::log_file(); let rt_dirs = helix_loader::runtime_dirs(); - let clipboard_provider = get_clipboard_provider(); if config_file.exists() { writeln!(stdout, "Config file: {}", config_file.display())?; @@ -92,7 +91,6 @@ pub fn general() -> std::io::Result<()> { writeln!(stdout, "{}", msg.yellow())?; } } - writeln!(stdout, "Clipboard provider: {}", clipboard_provider.name())?; Ok(()) } @@ -101,8 +99,19 @@ pub fn clipboard() -> std::io::Result<()> { let stdout = std::io::stdout(); let mut stdout = stdout.lock(); - let board = get_clipboard_provider(); - match board.name().as_ref() { + let config = match Config::load_default() { + Ok(config) => config, + Err(ConfigLoadError::Error(err)) if err.kind() == std::io::ErrorKind::NotFound => { + Config::default() + } + Err(err) => { + writeln!(stdout, "{}", "Configuration file malformed".red())?; + writeln!(stdout, "{}", err)?; + return Ok(()); + } + }; + + match config.editor.clipboard_provider.name().as_ref() { "none" => { writeln!( stdout, diff --git a/helix-view/src/clipboard.rs b/helix-view/src/clipboard.rs index 379accc7e..5e16461e0 100644 --- a/helix-view/src/clipboard.rs +++ b/helix-view/src/clipboard.rs @@ -1,356 +1,224 @@ // Implementation reference: https://github.com/neovim/neovim/blob/f2906a4669a2eef6d7bf86a29648793d63c98949/runtime/autoload/provider/clipboard.vim#L68-L152 -use anyhow::Result; +use serde::{Deserialize, Serialize}; use std::borrow::Cow; +use thiserror::Error; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] pub enum ClipboardType { Clipboard, Selection, } -pub trait ClipboardProvider: std::fmt::Debug { - fn name(&self) -> Cow; - fn get_contents(&self, clipboard_type: ClipboardType) -> Result; - fn set_contents(&mut self, contents: String, clipboard_type: ClipboardType) -> Result<()>; +#[derive(Debug, Error)] +pub enum ClipboardError { + #[error(transparent)] + IoError(#[from] std::io::Error), + #[error("could not convert terminal output to UTF-8: {0}")] + FromUtf8Error(#[from] std::string::FromUtf8Error), + #[cfg(windows)] + #[error("Windows API error: {0}")] + WinAPI(#[from] clipboard_win::ErrorCode), + #[error("clipboard provider command failed")] + CommandFailed, + #[error("failed to write to clipboard provider's stdin")] + StdinWriteFailed, + #[error("clipboard provider did not return any contents")] + MissingStdout, + #[error("This clipboard provider does not support reading")] + ReadingNotSupported, } -#[cfg(not(windows))] -macro_rules! command_provider { - (paste => $get_prg:literal $( , $get_arg:literal )* ; copy => $set_prg:literal $( , $set_arg:literal )* ; ) => {{ - log::debug!( - "Using {} to interact with the system clipboard", - if $set_prg != $get_prg { format!("{}+{}", $set_prg, $get_prg)} else { $set_prg.to_string() } - ); - Box::new(provider::command::Provider { - get_cmd: provider::command::Config { - prg: $get_prg, - args: &[ $( $get_arg ),* ], - }, - set_cmd: provider::command::Config { - prg: $set_prg, - args: &[ $( $set_arg ),* ], - }, - get_primary_cmd: None, - set_primary_cmd: None, - }) - }}; - - (paste => $get_prg:literal $( , $get_arg:literal )* ; - copy => $set_prg:literal $( , $set_arg:literal )* ; - primary_paste => $pr_get_prg:literal $( , $pr_get_arg:literal )* ; - primary_copy => $pr_set_prg:literal $( , $pr_set_arg:literal )* ; - ) => {{ - log::debug!( - "Using {} to interact with the system and selection (primary) clipboard", - if $set_prg != $get_prg { format!("{}+{}", $set_prg, $get_prg)} else { $set_prg.to_string() } - ); - Box::new(provider::command::Provider { - get_cmd: provider::command::Config { - prg: $get_prg, - args: &[ $( $get_arg ),* ], - }, - set_cmd: provider::command::Config { - prg: $set_prg, - args: &[ $( $set_arg ),* ], - }, - get_primary_cmd: Some(provider::command::Config { - prg: $pr_get_prg, - args: &[ $( $pr_get_arg ),* ], - }), - set_primary_cmd: Some(provider::command::Config { - prg: $pr_set_prg, - args: &[ $( $pr_set_arg ),* ], - }), - }) - }}; -} - -#[cfg(windows)] -pub fn get_clipboard_provider() -> Box { - Box::::default() -} - -#[cfg(target_os = "macos")] -pub fn get_clipboard_provider() -> Box { - use helix_stdx::env::{binary_exists, env_var_is_set}; - - if env_var_is_set("TMUX") && binary_exists("tmux") { - command_provider! { - paste => "tmux", "save-buffer", "-"; - copy => "tmux", "load-buffer", "-w", "-"; - } - } else if binary_exists("pbcopy") && binary_exists("pbpaste") { - command_provider! { - paste => "pbpaste"; - copy => "pbcopy"; - } - } else { - Box::new(provider::FallbackProvider::new()) - } -} +type Result = std::result::Result; +#[cfg(not(target_arch = "wasm32"))] +pub use external::ClipboardProvider; #[cfg(target_arch = "wasm32")] -pub fn get_clipboard_provider() -> Box { - // TODO: - Box::new(provider::FallbackProvider::new()) -} +pub use noop::ClipboardProvider; -#[cfg(not(any(windows, target_arch = "wasm32", target_os = "macos")))] -pub fn get_clipboard_provider() -> Box { - use helix_stdx::env::{binary_exists, env_var_is_set}; - use provider::command::is_exit_success; - // TODO: support for user-defined provider, probably when we have plugin support by setting a - // variable? - - if env_var_is_set("WAYLAND_DISPLAY") && binary_exists("wl-copy") && binary_exists("wl-paste") { - command_provider! { - paste => "wl-paste", "--no-newline"; - copy => "wl-copy", "--type", "text/plain"; - primary_paste => "wl-paste", "-p", "--no-newline"; - primary_copy => "wl-copy", "-p", "--type", "text/plain"; - } - } else if env_var_is_set("DISPLAY") && binary_exists("xclip") { - command_provider! { - paste => "xclip", "-o", "-selection", "clipboard"; - copy => "xclip", "-i", "-selection", "clipboard"; - primary_paste => "xclip", "-o"; - primary_copy => "xclip", "-i"; - } - } else if env_var_is_set("DISPLAY") - && binary_exists("xsel") - && is_exit_success("xsel", &["-o", "-b"]) - { - // FIXME: check performance of is_exit_success - command_provider! { - paste => "xsel", "-o", "-b"; - copy => "xsel", "-i", "-b"; - primary_paste => "xsel", "-o"; - primary_copy => "xsel", "-i"; - } - } else if binary_exists("win32yank.exe") { - command_provider! { - paste => "win32yank.exe", "-o", "--lf"; - copy => "win32yank.exe", "-i", "--crlf"; - } - } else if binary_exists("termux-clipboard-set") && binary_exists("termux-clipboard-get") { - command_provider! { - paste => "termux-clipboard-get"; - copy => "termux-clipboard-set"; - } - } else if env_var_is_set("TMUX") && binary_exists("tmux") { - command_provider! { - paste => "tmux", "save-buffer", "-"; - copy => "tmux", "load-buffer", "-w", "-"; - } - } else { - Box::new(provider::FallbackProvider::new()) - } -} +// Clipboard not supported for wasm +#[cfg(target_arch = "wasm32")] +mod noop { + use super::*; -#[cfg(not(target_os = "windows"))] -pub mod provider { - use super::{ClipboardProvider, ClipboardType}; - use anyhow::Result; - use std::borrow::Cow; + #[derive(Debug, Clone)] + pub enum ClipboardProvider {} - #[cfg(feature = "term")] - mod osc52 { - use {super::ClipboardType, crate::base64}; + impl ClipboardProvider { + pub fn detect() -> Self { + Self + } - #[derive(Debug)] - pub struct SetClipboardCommand { - encoded_content: String, - clipboard_type: ClipboardType, + pub fn name(&self) -> Cow { + "none".into() } - impl SetClipboardCommand { - pub fn new(content: &str, clipboard_type: ClipboardType) -> Self { - Self { - encoded_content: base64::encode(content.as_bytes()), - clipboard_type, - } - } + pub fn get_contents(&self, _clipboard_type: ClipboardType) -> Result { + Err(ClipboardError::ReadingNotSupported) } - impl crossterm::Command for SetClipboardCommand { - fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result { - let kind = match &self.clipboard_type { - ClipboardType::Clipboard => "c", - ClipboardType::Selection => "p", - }; - // Send an OSC 52 set command: https://terminalguide.namepad.de/seq/osc-52/ - write!(f, "\x1b]52;{};{}\x1b\\", kind, &self.encoded_content) - } + pub fn set_contents(&self, _content: &str, _clipboard_type: ClipboardType) -> Result<()> { + Ok(()) } } +} - #[derive(Debug)] - pub struct FallbackProvider { - buf: String, - primary_buf: String, - } +#[cfg(not(target_arch = "wasm32"))] +mod external { + use super::*; - impl FallbackProvider { - pub fn new() -> Self { - #[cfg(feature = "term")] - log::debug!( - "No native clipboard provider found. Yanking by OSC 52 and pasting will be internal to Helix" - ); - #[cfg(not(feature = "term"))] - log::warn!( - "No native clipboard provider found! Yanking and pasting will be internal to Helix" - ); - Self { - buf: String::new(), - primary_buf: String::new(), - } - } + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] + pub struct Command { + command: Cow<'static, str>, + #[serde(default)] + args: Cow<'static, [Cow<'static, str>]>, } - impl Default for FallbackProvider { - fn default() -> Self { - Self::new() - } + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] + #[serde(rename_all = "kebab-case")] + pub struct CommandProvider { + yank: Command, + paste: Command, + yank_primary: Option, + paste_primary: Option, } - impl ClipboardProvider for FallbackProvider { + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] + #[serde(rename_all = "kebab-case")] + #[allow(clippy::large_enum_variant)] + pub enum ClipboardProvider { + Pasteboard, + Wayland, + XClip, + XSel, + Win32Yank, + Tmux, + #[cfg(windows)] + Windows, + Termux, #[cfg(feature = "term")] - fn name(&self) -> Cow { - Cow::Borrowed("termcode") - } - - #[cfg(not(feature = "term"))] - fn name(&self) -> Cow { - Cow::Borrowed("none") - } + Termcode, + Custom(CommandProvider), + None, + } - fn get_contents(&self, clipboard_type: ClipboardType) -> Result { - // This is the same noop if term is enabled or not. - // We don't use the get side of OSC 52 as it isn't often enabled, it's a security hole, - // and it would require this to be async to listen for the response - let value = match clipboard_type { - ClipboardType::Clipboard => self.buf.clone(), - ClipboardType::Selection => self.primary_buf.clone(), - }; + impl Default for ClipboardProvider { + #[cfg(windows)] + fn default() -> Self { + use helix_stdx::env::binary_exists; - Ok(value) + if binary_exists("win32yank.exe") { + Self::Win32Yank + } else { + Self::Windows + } } - fn set_contents(&mut self, content: String, clipboard_type: ClipboardType) -> Result<()> { - #[cfg(feature = "term")] - crossterm::execute!( - std::io::stdout(), - osc52::SetClipboardCommand::new(&content, clipboard_type) - )?; - // Set our internal variables to use in get_content regardless of using OSC 52 - match clipboard_type { - ClipboardType::Clipboard => self.buf = content, - ClipboardType::Selection => self.primary_buf = content, + #[cfg(target_os = "macos")] + fn default() -> Self { + use helix_stdx::env::{binary_exists, env_var_is_set}; + + if env_var_is_set("TMUX") && binary_exists("tmux") { + Self::Tmux + } else if binary_exists("pbcopy") && binary_exists("pbpaste") { + Self::Pasteboard + } else if cfg!(feature = "term") { + Self::Termcode + } else { + Self::None } - Ok(()) } - } - - #[cfg(not(target_arch = "wasm32"))] - pub mod command { - use super::*; - use anyhow::{bail, Context as _}; #[cfg(not(any(windows, target_os = "macos")))] - pub fn is_exit_success(program: &str, args: &[&str]) -> bool { - std::process::Command::new(program) - .args(args) - .output() - .ok() - .and_then(|out| out.status.success().then_some(())) - .is_some() - } + fn default() -> Self { + use helix_stdx::env::{binary_exists, env_var_is_set}; + + fn is_exit_success(program: &str, args: &[&str]) -> bool { + std::process::Command::new(program) + .args(args) + .output() + .ok() + .and_then(|out| out.status.success().then_some(())) + .is_some() + } - #[derive(Debug)] - pub struct Config { - pub prg: &'static str, - pub args: &'static [&'static str], + if env_var_is_set("WAYLAND_DISPLAY") + && binary_exists("wl-copy") + && binary_exists("wl-paste") + { + Self::Wayland + } else if env_var_is_set("DISPLAY") && binary_exists("xclip") { + Self::XClip + } else if env_var_is_set("DISPLAY") + && binary_exists("xsel") + // FIXME: check performance of is_exit_success + && is_exit_success("xsel", &["-o", "-b"]) + { + Self::XSel + } else if binary_exists("termux-clipboard-set") && binary_exists("termux-clipboard-get") + { + Self::Termux + } else if env_var_is_set("TMUX") && binary_exists("tmux") { + Self::Tmux + } else if binary_exists("win32yank.exe") { + Self::Win32Yank + } else if cfg!(feature = "term") { + Self::Termcode + } else { + Self::None + } } + } - impl Config { - fn execute(&self, input: Option<&str>, pipe_output: bool) -> Result> { - use std::io::Write; - use std::process::{Command, Stdio}; - - let stdin = input.map(|_| Stdio::piped()).unwrap_or_else(Stdio::null); - let stdout = pipe_output.then(Stdio::piped).unwrap_or_else(Stdio::null); - - let mut command: Command = Command::new(self.prg); - - let mut command_mut: &mut Command = command - .args(self.args) - .stdin(stdin) - .stdout(stdout) - .stderr(Stdio::null()); - - // Fix for https://github.com/helix-editor/helix/issues/5424 - if cfg!(unix) { - use std::os::unix::process::CommandExt; - - unsafe { - command_mut = command_mut.pre_exec(|| match libc::setsid() { - -1 => Err(std::io::Error::last_os_error()), - _ => Ok(()), - }); - } - } - - let mut child = command_mut.spawn()?; - - if let Some(input) = input { - let mut stdin = child.stdin.take().context("stdin is missing")?; - stdin - .write_all(input.as_bytes()) - .context("couldn't write in stdin")?; - } - - // TODO: add timer? - let output = child.wait_with_output()?; - - if !output.status.success() { - bail!("clipboard provider {} failed", self.prg); - } - - if pipe_output { - Ok(Some(String::from_utf8(output.stdout)?)) + impl ClipboardProvider { + pub fn name(&self) -> Cow<'_, str> { + fn builtin_name<'a>( + name: &'static str, + provider: &'static CommandProvider, + ) -> Cow<'a, str> { + if provider.yank.command != provider.paste.command { + Cow::Owned(format!( + "{} ({}+{})", + name, provider.yank.command, provider.paste.command + )) } else { - Ok(None) + Cow::Owned(format!("{} ({})", name, provider.yank.command)) } } - } - - #[derive(Debug)] - pub struct Provider { - pub get_cmd: Config, - pub set_cmd: Config, - pub get_primary_cmd: Option, - pub set_primary_cmd: Option, - } - impl ClipboardProvider for Provider { - fn name(&self) -> Cow { - if self.get_cmd.prg != self.set_cmd.prg { - Cow::Owned(format!("{}+{}", self.get_cmd.prg, self.set_cmd.prg)) - } else { - Cow::Borrowed(self.get_cmd.prg) - } + match self { + // These names should match the config option names from Serde + Self::Pasteboard => builtin_name("pasteboard", &PASTEBOARD), + Self::Wayland => builtin_name("wayland", &WL_CLIPBOARD), + Self::XClip => builtin_name("x-clip", &XCLIP), + Self::XSel => builtin_name("x-sel", &XSEL), + Self::Win32Yank => builtin_name("win-32-yank", &WIN32), + Self::Tmux => builtin_name("tmux", &TMUX), + Self::Termux => builtin_name("termux", &TERMUX), + #[cfg(windows)] + Self::Windows => "windows".into(), + #[cfg(feature = "term")] + Self::Termcode => "termcode".into(), + Self::Custom(command_provider) => Cow::Owned(format!( + "custom ({}+{})", + command_provider.yank.command, command_provider.paste.command + )), + Self::None => "none".into(), } + } - fn get_contents(&self, clipboard_type: ClipboardType) -> Result { + pub fn get_contents(&self, clipboard_type: &ClipboardType) -> Result { + fn yank_from_builtin( + provider: CommandProvider, + clipboard_type: &ClipboardType, + ) -> Result { match clipboard_type { - ClipboardType::Clipboard => Ok(self - .get_cmd - .execute(None, true)? - .context("output is missing")?), + ClipboardType::Clipboard => execute_command(&provider.yank, None, true)? + .ok_or(ClipboardError::MissingStdout), ClipboardType::Selection => { - if let Some(cmd) = &self.get_primary_cmd { - return cmd.execute(None, true)?.context("output is missing"); + if let Some(cmd) = provider.yank_primary.as_ref() { + return execute_command(cmd, None, true)? + .ok_or(ClipboardError::MissingStdout); } Ok(String::new()) @@ -358,56 +226,274 @@ pub mod provider { } } - fn set_contents(&mut self, value: String, clipboard_type: ClipboardType) -> Result<()> { + match self { + Self::Pasteboard => yank_from_builtin(PASTEBOARD, clipboard_type), + Self::Wayland => yank_from_builtin(WL_CLIPBOARD, clipboard_type), + Self::XClip => yank_from_builtin(XCLIP, clipboard_type), + Self::XSel => yank_from_builtin(XSEL, clipboard_type), + Self::Win32Yank => yank_from_builtin(WIN32, clipboard_type), + Self::Tmux => yank_from_builtin(TMUX, clipboard_type), + Self::Termux => yank_from_builtin(TERMUX, clipboard_type), + #[cfg(target_os = "windows")] + Self::Windows => match clipboard_type { + ClipboardType::Clipboard => { + let contents = + clipboard_win::get_clipboard(clipboard_win::formats::Unicode)?; + Ok(contents) + } + ClipboardType::Selection => Ok(String::new()), + }, + #[cfg(feature = "term")] + Self::Termcode => Err(ClipboardError::ReadingNotSupported), + Self::Custom(command_provider) => { + execute_command(&command_provider.yank, None, true)? + .ok_or(ClipboardError::MissingStdout) + } + Self::None => Err(ClipboardError::ReadingNotSupported), + } + } + + pub fn set_contents(&self, content: &str, clipboard_type: ClipboardType) -> Result<()> { + fn paste_to_builtin( + provider: CommandProvider, + content: &str, + clipboard_type: ClipboardType, + ) -> Result<()> { let cmd = match clipboard_type { - ClipboardType::Clipboard => &self.set_cmd, + ClipboardType::Clipboard => &provider.paste, ClipboardType::Selection => { - if let Some(cmd) = &self.set_primary_cmd { + if let Some(cmd) = provider.paste_primary.as_ref() { cmd } else { return Ok(()); } } }; - cmd.execute(Some(&value), false).map(|_| ()) + + execute_command(cmd, Some(content), false).map(|_| ()) + } + + match self { + Self::Pasteboard => paste_to_builtin(PASTEBOARD, content, clipboard_type), + Self::Wayland => paste_to_builtin(WL_CLIPBOARD, content, clipboard_type), + Self::XClip => paste_to_builtin(XCLIP, content, clipboard_type), + Self::XSel => paste_to_builtin(XSEL, content, clipboard_type), + Self::Win32Yank => paste_to_builtin(WIN32, content, clipboard_type), + Self::Tmux => paste_to_builtin(TMUX, content, clipboard_type), + Self::Termux => paste_to_builtin(TERMUX, content, clipboard_type), + #[cfg(target_os = "windows")] + Self::Windows => match clipboard_type { + ClipboardType::Clipboard => { + clipboard_win::set_clipboard(clipboard_win::formats::Unicode, content)?; + Ok(()) + } + ClipboardType::Selection => Ok(()), + }, + #[cfg(feature = "term")] + Self::Termcode => { + crossterm::queue!( + std::io::stdout(), + osc52::SetClipboardCommand::new(content, clipboard_type) + )?; + Ok(()) + } + Self::Custom(command_provider) => match clipboard_type { + ClipboardType::Clipboard => { + execute_command(&command_provider.paste, Some(content), false).map(|_| ()) + } + ClipboardType::Selection => { + if let Some(cmd) = &command_provider.paste_primary { + execute_command(cmd, Some(content), false).map(|_| ()) + } else { + Ok(()) + } + } + }, + Self::None => Ok(()), } } } -} -#[cfg(target_os = "windows")] -mod provider { - use super::{ClipboardProvider, ClipboardType}; - use anyhow::Result; - use std::borrow::Cow; + macro_rules! command_provider { + ($name:ident, + yank => $yank_cmd:literal $( , $yank_arg:literal )* ; + paste => $paste_cmd:literal $( , $paste_arg:literal )* ; ) => { + const $name: CommandProvider = CommandProvider { + yank: Command { + command: Cow::Borrowed($yank_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($yank_arg) ),* ]) + }, + paste: Command { + command: Cow::Borrowed($paste_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($paste_arg) ),* ]) + }, + yank_primary: None, + paste_primary: None, + }; + }; + ($name:ident, + yank => $yank_cmd:literal $( , $yank_arg:literal )* ; + paste => $paste_cmd:literal $( , $paste_arg:literal )* ; + yank_primary => $yank_primary_cmd:literal $( , $yank_primary_arg:literal )* ; + paste_primary => $paste_primary_cmd:literal $( , $paste_primary_arg:literal )* ; ) => { + const $name: CommandProvider = CommandProvider { + yank: Command { + command: Cow::Borrowed($yank_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($yank_arg) ),* ]) + }, + paste: Command { + command: Cow::Borrowed($paste_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($paste_arg) ),* ]) + }, + yank_primary: Some(Command { + command: Cow::Borrowed($yank_primary_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($yank_primary_arg) ),* ]) + }), + paste_primary: Some(Command { + command: Cow::Borrowed($paste_primary_cmd), + args: Cow::Borrowed(&[ $( Cow::Borrowed($paste_primary_arg) ),* ]) + }), + }; + }; + } - #[derive(Default, Debug)] - pub struct WindowsProvider; + command_provider! { + TMUX, + yank => "tmux", "save-buffer", "-"; + paste => "tmux", "load-buffer", "-w", "-"; + } + command_provider! { + PASTEBOARD, + yank => "pbpaste"; + paste => "pbcopy"; + } + command_provider! { + WL_CLIPBOARD, + yank => "wl-paste", "--no-newline"; + paste => "wl-copy", "--type", "text/plain"; + yank_primary => "wl-paste", "-p", "--no-newline"; + paste_primary => "wl-copy", "-p", "--type", "text/plain"; + } + command_provider! { + XCLIP, + yank => "xclip", "-o", "-selection", "clipboard"; + paste => "xclip", "-i", "-selection", "clipboard"; + yank_primary => "xclip", "-o"; + paste_primary => "xclip", "-i"; + } + command_provider! { + XSEL, + yank => "xsel", "-o", "-b"; + paste => "xsel", "-i", "-b"; + yank_primary => "xsel", "-o"; + paste_primary => "xsel", "-i"; + } + command_provider! { + WIN32, + yank => "win32yank.exe", "-o", "--lf"; + paste => "win32yank.exe", "-i", "--crlf"; + } + command_provider! { + TERMUX, + yank => "termux-clipboard-get"; + paste => "termux-clipboard-set"; + } - impl ClipboardProvider for WindowsProvider { - fn name(&self) -> Cow { - log::debug!("Using clipboard-win to interact with the system clipboard"); - Cow::Borrowed("clipboard-win") + #[cfg(feature = "term")] + mod osc52 { + use {super::ClipboardType, crate::base64}; + + pub struct SetClipboardCommand { + encoded_content: String, + clipboard_type: ClipboardType, } - fn get_contents(&self, clipboard_type: ClipboardType) -> Result { - match clipboard_type { - ClipboardType::Clipboard => { - let contents = clipboard_win::get_clipboard(clipboard_win::formats::Unicode)?; - Ok(contents) + impl SetClipboardCommand { + pub fn new(content: &str, clipboard_type: ClipboardType) -> Self { + Self { + encoded_content: base64::encode(content.as_bytes()), + clipboard_type, } - ClipboardType::Selection => Ok(String::new()), } } - fn set_contents(&mut self, contents: String, clipboard_type: ClipboardType) -> Result<()> { - match clipboard_type { - ClipboardType::Clipboard => { - clipboard_win::set_clipboard(clipboard_win::formats::Unicode, contents)?; - } - ClipboardType::Selection => {} - }; - Ok(()) + impl crossterm::Command for SetClipboardCommand { + fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result { + let kind = match &self.clipboard_type { + ClipboardType::Clipboard => "c", + ClipboardType::Selection => "p", + }; + // Send an OSC 52 set command: https://terminalguide.namepad.de/seq/osc-52/ + write!(f, "\x1b]52;{};{}\x1b\\", kind, &self.encoded_content) + } + #[cfg(windows)] + fn execute_winapi(&self) -> std::result::Result<(), std::io::Error> { + Err(std::io::Error::new( + std::io::ErrorKind::Other, + "OSC clipboard codes not supported by winapi.", + )) + } + } + } + + fn execute_command( + cmd: &Command, + input: Option<&str>, + pipe_output: bool, + ) -> Result> { + use std::io::Write; + use std::process::{Command, Stdio}; + + let stdin = input.map(|_| Stdio::piped()).unwrap_or_else(Stdio::null); + let stdout = pipe_output.then(Stdio::piped).unwrap_or_else(Stdio::null); + + let mut command: Command = Command::new(cmd.command.as_ref()); + + #[allow(unused_mut)] + let mut command_mut: &mut Command = command + .args(cmd.args.iter().map(AsRef::as_ref)) + .stdin(stdin) + .stdout(stdout) + .stderr(Stdio::null()); + + // Fix for https://github.com/helix-editor/helix/issues/5424 + #[cfg(unix)] + { + use std::os::unix::process::CommandExt; + + unsafe { + command_mut = command_mut.pre_exec(|| match libc::setsid() { + -1 => Err(std::io::Error::last_os_error()), + _ => Ok(()), + }); + } + } + + let mut child = command_mut.spawn()?; + + if let Some(input) = input { + let mut stdin = child.stdin.take().ok_or(ClipboardError::StdinWriteFailed)?; + stdin + .write_all(input.as_bytes()) + .map_err(|_| ClipboardError::StdinWriteFailed)?; + } + + // TODO: add timer? + let output = child.wait_with_output()?; + + if !output.status.success() { + log::error!( + "clipboard provider {} failed with stderr: \"{}\"", + cmd.command, + String::from_utf8_lossy(&output.stderr) + ); + return Err(ClipboardError::CommandFailed); + } + + if pipe_output { + Ok(Some(String::from_utf8(output.stdout)?)) + } else { + Ok(None) } } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 26dea3a21..9e1bee8e1 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -1,5 +1,6 @@ use crate::{ annotations::diagnostics::{DiagnosticFilter, InlineDiagnosticsConfig}, + clipboard::ClipboardProvider, document::{ DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint, }, @@ -269,6 +270,8 @@ pub struct Config { pub auto_completion: bool, /// Automatic formatting on save. Defaults to true. pub auto_format: bool, + /// Default register used for yank/paste. Defaults to '"' + pub default_yank_register: char, /// Automatic save on focus lost and/or after delay. /// Time delay in milliseconds since last edit after which auto save timer triggers. /// Time delay defaults to false with 3000ms delay. Focus lost defaults to false. @@ -345,6 +348,8 @@ pub struct Config { /// Display diagnostic below the line they occur. pub inline_diagnostics: InlineDiagnosticsConfig, pub end_of_line_diagnostics: DiagnosticFilter, + // Set to override the default clipboard provider + pub clipboard_provider: ClipboardProvider, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)] @@ -948,6 +953,7 @@ impl Default for Config { auto_pairs: AutoPairConfig::default(), auto_completion: true, auto_format: true, + default_yank_register: '"', auto_save: AutoSave::default(), idle_timeout: Duration::from_millis(250), completion_timeout: Duration::from_millis(250), @@ -982,6 +988,7 @@ impl Default for Config { jump_label_alphabet: ('a'..='z').collect(), inline_diagnostics: InlineDiagnosticsConfig::default(), end_of_line_diagnostics: DiagnosticFilter::Disable, + clipboard_provider: ClipboardProvider::default(), } } } @@ -1183,7 +1190,10 @@ impl Editor { theme_loader, last_theme: None, last_selection: None, - registers: Registers::default(), + registers: Registers::new(Box::new(arc_swap::access::Map::new( + Arc::clone(&config), + |config: &Config| &config.clipboard_provider, + ))), status_msg: None, autoinfo: None, idle_timer: Box::pin(sleep(conf.idle_timeout)), diff --git a/helix-view/src/register.rs b/helix-view/src/register.rs index 3a2e1b7cc..3f7844cd6 100644 --- a/helix-view/src/register.rs +++ b/helix-view/src/register.rs @@ -1,10 +1,11 @@ use std::{borrow::Cow, collections::HashMap, iter}; use anyhow::Result; +use arc_swap::access::DynAccess; use helix_core::NATIVE_LINE_ENDING; use crate::{ - clipboard::{get_clipboard_provider, ClipboardProvider, ClipboardType}, + clipboard::{ClipboardProvider, ClipboardType}, Editor, }; @@ -20,28 +21,25 @@ use crate::{ /// * Document path (`%`): filename of the current buffer /// * System clipboard (`*`) /// * Primary clipboard (`+`) -#[derive(Debug)] pub struct Registers { /// The mapping of register to values. /// Values are stored in reverse order when inserted with `Registers::write`. /// The order is reversed again in `Registers::read`. This allows us to /// efficiently prepend new values in `Registers::push`. inner: HashMap>, - clipboard_provider: Box, + clipboard_provider: Box>, pub last_search_register: char, } -impl Default for Registers { - fn default() -> Self { +impl Registers { + pub fn new(clipboard_provider: Box>) -> Self { Self { inner: Default::default(), - clipboard_provider: get_clipboard_provider(), + clipboard_provider, last_search_register: '/', } } -} -impl Registers { pub fn read<'a>(&'a self, name: char, editor: &'a Editor) -> Option> { match name { '_' => Some(RegisterValues::new(iter::empty())), @@ -64,7 +62,7 @@ impl Registers { Some(RegisterValues::new(iter::once(path))) } '*' | '+' => Some(read_from_clipboard( - self.clipboard_provider.as_ref(), + &self.clipboard_provider.load(), self.inner.get(&name), match name { '+' => ClipboardType::Clipboard, @@ -84,8 +82,8 @@ impl Registers { '_' => Ok(()), '#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support writing")), '*' | '+' => { - self.clipboard_provider.set_contents( - values.join(NATIVE_LINE_ENDING.as_str()), + self.clipboard_provider.load().set_contents( + &values.join(NATIVE_LINE_ENDING.as_str()), match name { '+' => ClipboardType::Clipboard, '*' => ClipboardType::Selection, @@ -114,7 +112,10 @@ impl Registers { '*' => ClipboardType::Selection, _ => unreachable!(), }; - let contents = self.clipboard_provider.get_contents(clipboard_type)?; + let contents = self + .clipboard_provider + .load() + .get_contents(&clipboard_type)?; let saved_values = self.inner.entry(name).or_default(); if !contents_are_saved(saved_values, &contents) { @@ -127,7 +128,8 @@ impl Registers { } value.push_str(&contents); self.clipboard_provider - .set_contents(value, clipboard_type)?; + .load() + .set_contents(&value, clipboard_type)?; Ok(()) } @@ -198,7 +200,8 @@ impl Registers { fn clear_clipboard(&mut self, clipboard_type: ClipboardType) { if let Err(err) = self .clipboard_provider - .set_contents("".into(), clipboard_type) + .load() + .set_contents("", clipboard_type) { log::error!( "Failed to clear {} clipboard: {err}", @@ -210,17 +213,17 @@ impl Registers { } } - pub fn clipboard_provider_name(&self) -> Cow { - self.clipboard_provider.name() + pub fn clipboard_provider_name(&self) -> String { + self.clipboard_provider.load().name().into_owned() } } fn read_from_clipboard<'a>( - provider: &dyn ClipboardProvider, + provider: &ClipboardProvider, saved_values: Option<&'a Vec>, clipboard_type: ClipboardType, ) -> RegisterValues<'a> { - match provider.get_contents(clipboard_type) { + match provider.get_contents(&clipboard_type) { Ok(contents) => { // If we're pasting the same values that we just yanked, re-use // the saved values. This allows pasting multiple selections diff --git a/languages.toml b/languages.toml index f24c70d81..ea6e6893f 100644 --- a/languages.toml +++ b/languages.toml @@ -44,6 +44,7 @@ gleam = { command = "gleam", args = ["lsp"] } glsl_analyzer = { command = "glsl_analyzer" } graphql-language-service = { command = "graphql-lsp", args = ["server", "-m", "stream"] } haskell-language-server = { command = "haskell-language-server-wrapper", args = ["--lsp"] } +hyprls = { command = "hyprls" } idris2-lsp = { command = "idris2-lsp" } intelephense = { command = "intelephense", args = ["--stdio"] } jdtls = { command = "jdtls" } @@ -83,6 +84,7 @@ pyright = { command = "pyright-langserver", args = ["--stdio"], config = {} } basedpyright = { command = "basedpyright-langserver", args = ["--stdio"], config = {} } pylyzer = { command = "pylyzer", args = ["--server"] } qmlls = { command = "qmlls" } +quint-language-server = { command = "quint-language-server", args = ["--stdio"] } r = { command = "R", args = ["--no-echo", "-e", "languageserver::run()"] } racket = { command = "racket", args = ["-l", "racket-langserver"] } regols = { command = "regols" } @@ -94,6 +96,7 @@ slint-lsp = { command = "slint-lsp", args = [] } solargraph = { command = "solargraph", args = ["stdio"] } solc = { command = "solc", args = ["--lsp"] } sourcekit-lsp = { command = "sourcekit-lsp" } +spade-language-server = {command = "spade-language-server"} svlangserver = { command = "svlangserver", args = [] } swipl = { command = "swipl", args = [ "-g", "use_module(library(lsp_server))", "-g", "lsp_server:main", "-t", "halt", "--", "stdio" ] } superhtml = { command = "superhtml", args = ["lsp"]} @@ -344,6 +347,19 @@ indent = { tab-width = 2, unit = " " } name = "protobuf" source = { git = "https://github.com/yusdacra/tree-sitter-protobuf", rev = "19c211a01434d9f03efff99f85e19f967591b175"} +[[language]] +name = "textproto" +file-types = ["txtpb", "textpb", "textproto"] +comment-token = "#" +scope = "source.textproto" +indent = { tab-width = 2, unit = " " } +formatter = { command = "txtpbfmt" } +auto-format = true + +[[grammar]] +name = "textproto" +source = { git = "https://github.com/PorterAtGoogle/tree-sitter-textproto", rev = "568471b80fd8793d37ed01865d8c2208a9fefd1b"} + [[language]] name = "elixir" scope = "source.elixir" @@ -451,6 +467,7 @@ file-types = [ "avsc", "ldtk", "ldtkl", + { glob = ".swift-format" }, ] language-servers = [ "vscode-json-language-server" ] auto-format = true @@ -464,7 +481,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "73076 name = "jsonc" scope = "source.json" injection-regex = "jsonc" -file-types = ["jsonc"] +file-types = ["jsonc", { glob = "tsconfig.json" }] grammar = "json" language-servers = [ "vscode-json-language-server" ] auto-format = true @@ -729,6 +746,7 @@ injection-regex = "(js|javascript)" language-id = "javascript" file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", { glob = ".node_repl_history" }, { glob = "jakefile" }] shebangs = ["node"] +roots = [ "package.json" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } language-servers = [ "typescript-language-server" ] @@ -756,6 +774,7 @@ scope = "source.jsx" injection-regex = "jsx" language-id = "javascriptreact" file-types = ["jsx"] +roots = [ "package.json" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } language-servers = [ "typescript-language-server" ] @@ -769,6 +788,7 @@ injection-regex = "(ts|typescript)" language-id = "typescript" file-types = ["ts", "mts", "cts"] shebangs = ["deno", "bun", "ts-node"] +roots = [ "package.json", "tsconfig.json" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } language-servers = [ "typescript-language-server" ] @@ -801,6 +821,7 @@ scope = "source.tsx" injection-regex = "(tsx)" # |typescript language-id = "typescriptreact" file-types = ["tsx"] +roots = [ "package.json", "tsconfig.json" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } language-servers = [ "typescript-language-server" ] @@ -1305,7 +1326,7 @@ source = { git = "https://github.com/ikatyang/tree-sitter-vue", rev = "91fe27547 [[language]] name = "yaml" scope = "source.yaml" -file-types = ["yml", "yaml", { glob = ".prettierrc" }] +file-types = ["yml", "yaml", { glob = ".prettierrc" }, { glob = ".clangd" }, { glob = ".clang-format" }] comment-token = "#" indent = { tab-width = 2, unit = " " } language-servers = [ "yaml-language-server", "ansible-language-server" ] @@ -1315,6 +1336,15 @@ injection-regex = "yml|yaml" name = "yaml" source = { git = "https://github.com/ikatyang/tree-sitter-yaml", rev = "0e36bed171768908f331ff7dff9d956bae016efb" } +[[language]] +name = "nestedtext" +scope = "text.nested" +injection-regex = "nestedtext" +file-types = ["nt"] +comment-token = "#" +indent = { tab-width = 4, unit = " " } +grammar = "yaml" + [[language]] name = "haskell" scope = "source.haskell" @@ -1365,7 +1395,7 @@ injection-regex = "zig" file-types = ["zig", "zon"] roots = ["build.zig"] auto-format = true -comment-token = "//" +comment-tokens = ["//", "///", "//!"] language-servers = [ "zls" ] indent = { tab-width = 4, unit = " " } formatter = { command = "zig" , args = ["fmt", "--stdin"] } @@ -1470,7 +1500,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "perl" -source = { git = "https://github.com/tree-sitter-perl/tree-sitter-perl", rev = "e99bb5283805db4cb86c964722d709df21b0ac16" } +source = { git = "https://github.com/tree-sitter-perl/tree-sitter-perl", rev = "72a08a496a23212f23802490ef6f4700d68cfd0e" } [[language]] name = "pod" @@ -1480,7 +1510,7 @@ file-types = ["pod"] [[grammar]] name = "pod" -source = { git = "https://github.com/tree-sitter-perl/tree-sitter-pod", rev = "39da859947b94abdee43e431368e1ae975c0a424" } +source = { git = "https://github.com/tree-sitter-perl/tree-sitter-pod", rev = "0bf8387987c21bf2f8ed41d2575a8f22b139687f" } [[language]] name = "racket" @@ -1542,7 +1572,7 @@ injection-regex = "llvm" [[grammar]] name = "llvm" -source = { git = "https://github.com/benwilliamgraham/tree-sitter-llvm", rev = "e9948edc41e9e5869af99dddb2b5ff5cc5581af6" } +source = { git = "https://github.com/benwilliamgraham/tree-sitter-llvm", rev = "c14cb839003348692158b845db9edda201374548" } [[language]] name = "llvm-mir" @@ -1554,7 +1584,7 @@ injection-regex = "mir" [[grammar]] name = "llvm-mir" -source = { git = "https://github.com/Flakebi/tree-sitter-llvm-mir", rev = "06fabca19454b2dc00c1b211a7cb7ad0bc2585f1" } +source = { git = "https://github.com/Flakebi/tree-sitter-llvm-mir", rev = "d166ff8c5950f80b0a476956e7a0ad2f27c12505" } [[language]] name = "llvm-mir-yaml" @@ -1577,13 +1607,13 @@ injection-regex = "tablegen" [[grammar]] name = "tablegen" -source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd8a937347175fd58db83d4c4cdaeb6069bd2" } +source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "3e9c4822ab5cdcccf4f8aa9dcd42117f736d51d9" } [[language]] name = "markdown" scope = "source.md" injection-regex = "md|markdown" -file-types = ["md", "markdown", "mdx", "mkd", "mkdn", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook", { glob = "PULLREQ_EDITMSG" }] +file-types = ["md", "livemd", "markdown", "mdx", "mkd", "mkdn", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook", { glob = "PULLREQ_EDITMSG" }] roots = [".marksman.toml"] language-servers = [ "marksman", "markdown-oxide" ] indent = { tab-width = 2, unit = " " } @@ -1808,7 +1838,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "rescript" -source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "467dcf99f68c47823d7b378779a6b282d7ef9782" } +source = { git = "https://github.com/rescript-lang/tree-sitter-rescript", rev = "5e2a44a9d886b0a509f5bfd0437d33b4871fbac5" } [[language]] name = "erlang" @@ -1967,7 +1997,6 @@ roots = [ "Package.swift" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } formatter = { command = "swift-format" } -auto-format = true language-servers = [ "sourcekit-lsp" ] [[grammar]] @@ -2202,7 +2231,7 @@ source = { git = "https://github.com/staysail/tree-sitter-meson", rev = "32a83e8 [[language]] name = "sshclientconfig" scope = "source.sshclientconfig" -file-types = [{ glob = ".ssh/config" }, { glob = "/etc/ssh/ssh_config" }] +file-types = [{ glob = ".ssh/config" }, { glob = "/etc/ssh/ssh_config" }, { glob = "ssh_config.d/*.conf" } ] comment-token = "#" [[grammar]] @@ -2793,7 +2822,7 @@ source = { git = "https://github.com/inko-lang/tree-sitter-inko", rev = "7860637 [[language]] name = "bicep" scope = "source.bicep" -file-types = ["bicep"] +file-types = ["bicep","bicepparam"] auto-format = true comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } @@ -2802,7 +2831,7 @@ language-servers = [ "bicep-langserver" ] [[grammar]] name = "bicep" -source = { git = "https://github.com/the-mikedavis/tree-sitter-bicep", rev = "d8e097fcfa143854861ef737161163a09cc2916b" } +source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-bicep", rev = "0092c7d1bd6bb22ce0a6f78497d50ea2b87f19c0" } [[language]] name = "qml" @@ -2983,7 +3012,7 @@ indent = { tab-width = 8, unit = " " } [[grammar]] name = "nasm" -source = { git = "https://github.com/naclsn/tree-sitter-nasm", rev = "a0db15db6fcfb1bf2cc8702500e55e558825c48b" } +source = { git = "https://github.com/naclsn/tree-sitter-nasm", rev = "570f3d7be01fffc751237f4cfcf52d04e20532d1" } [[language]] name = "gas" @@ -3316,7 +3345,7 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "unison" -source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "1f505e2447fa876a87aee47ff3d70b9e141c744f" } +source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "3c97db76d3cdbd002dfba493620c2d5df2fd6fa9" } [[language]] name = "todotxt" @@ -3550,6 +3579,7 @@ roots = ["hyprland.conf"] file-types = [ { glob = "hyprland.conf" }, { glob = "hyprpaper.conf" }, { glob = "hypridle.conf" }, { glob = "hyprlock.conf" } ] comment-token = "#" grammar = "hyprlang" +language-servers = ["hyprls"] [[grammar]] name = "hyprlang" @@ -3839,11 +3869,15 @@ source = { git = "https://github.com/Decurity/tree-sitter-circom", rev = "021505 name = "snakemake" scope = "source.snakemake" roots = ["Snakefile", "config.yaml", "environment.yaml", "workflow/"] -file-types = ["smk", "Snakefile"] +file-types = ["smk", { glob = "Snakefile" } ] comment-tokens = ["#", "##"] indent = { tab-width = 2, unit = " " } language-servers = ["pylsp" ] +[language.formatter] +command = "snakefmt" +args = ["-"] + [[grammar]] name = "snakemake" source = { git = "https://github.com/osthomas/tree-sitter-snakemake", rev = "e909815acdbe37e69440261ebb1091ed52e1dec6" } @@ -3859,3 +3893,41 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "cylc" source = { git = "https://github.com/elliotfontaine/tree-sitter-cylc", rev = "30dd40d9bf23912e4aefa93eeb4c7090bda3d0f6" } + +[[language]] +name = "quint" +scope = "source.quint" +file-types = ["qnt"] +language-servers = ["quint-language-server"] +comment-token = "//" +block-comment-tokens = { start = "/*", end = "*/" } +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "quint" +source = { git = "https://github.com/gruhn/tree-sitter-quint", rev = "eebbd01edfeff6404778c92efe5554e42e506a18" } + +[[language]] +name = "spade" +scope = "source.spade" +roots = ["swim.toml"] +file-types = ['spade'] +injection-regex = "spade" +comment-tokens = ["//", "///"] +block-comment-tokens = [ + { start = "/*", end = "*/" }, + { start = "/**", end = "*/" }, +] +language-servers = [ "spade-language-server" ] +indent = { tab-width = 4, unit = " " } + +[language.auto-pairs] +'(' = ')' +'{' = '}' +'[' = ']' +'"' = '"' +'<' = '>' + +[[grammar]] +name = "spade" +source = { git = "https://gitlab.com/spade-lang/tree-sitter-spade/", rev = "4d5b141017c61fe7e168e0a5c5721ee62b0d9572" } diff --git a/pr.md b/pr.md new file mode 100644 index 000000000..0ea65a5ad --- /dev/null +++ b/pr.md @@ -0,0 +1,24 @@ +Syntax symbol pickers +== + +This adds two new symbol picker commands that use tree-sitter rather than LSP. We run a new `symbols.scm` query across the file and extract tagged things like function definitions, types, classes, etc. For languages with unambiguous syntax this behaves roughly the same as the LSP symbol picker (`s`). It's less precise though since we don't have semantic info about the language. For example it can easily produce false positives for C/C++ because of preprocessor magic. + +The hope is to start introducing LSP-like features for navigation that can work without installing or running a language server. I made these two pickers in particular because I don't like LSP equivalents in ErlangLS - the document symbol picker can take a long time to show up during boot and the workspace symbol picker only searches for module names. The other motivation is to have some navigation features in cases when running a language server is too cumbersome - either to set up or because of resource constraints. For example `clangd` needs a fair amount of setup (`compile_commands.json`) that you might not want to do when quickly reading through a codebase. + +GitHub already uses tree-sitter like this to provide [imprecise code navigation](https://docs.github.com/en/repositories/working-with-files/using-files/navigating-code-on-github#about-navigating-code-on-github). It should be possible to find definitions and references as well like `gd` and `gr` - this is left as a follow-up. + +This PR also adds commands that either open the LSP symbol picker or the syntax one if a language server is not available. This way you can customize a language to not use the LSP symbol pickers, for example: + +```toml +[[language]] +name = "erlang" +language-servers = [{ name = "erlang-ls", except-features = ["document-symbols", "workspace-symbols"] }] +``` + +and `s` will use the syntax symbol picker, while `s` on a Rust file will still prefer the language server. + +--- + +Outstanding question - how closely should we try to match LSP symbol kind? Not at all? Should we have markup specific symbol kinds? (For example see markdown's `symbols.scm`). + +Also this PR needs docs on writing `symbols.scm` queries. diff --git a/runtime/queries/bicep/highlights.scm b/runtime/queries/bicep/highlights.scm index b6f928726..b80de7fd7 100644 --- a/runtime/queries/bicep/highlights.scm +++ b/runtime/queries/bicep/highlights.scm @@ -1,73 +1,232 @@ -; Keywords +; Includes +[ + "import" + "provider" + "with" + "as" + "from" +] @keyword.control.import + +; Namespaces +(module_declaration + (identifier) @namespace) + +; Builtins +(primitive_type) @type.builtin + +((member_expression + object: (identifier) @type.builtin) + (#eq? @type.builtin "sys")) + +; Functions +(call_expression + function: (identifier) @function) + +(user_defined_function + name: (identifier) @function) + +; Properties +(object_property + (identifier) @function.method + ":" @punctuation.delimiter + (_)) + +(object_property + (compatible_identifier) @function.method + ":" @punctuation.delimiter + (_)) + +(property_identifier) @function.method + +; Attributes +(decorator + "@" @attribute) + +(decorator + (call_expression + (identifier) @attribute)) + +(decorator + (call_expression + (member_expression + object: (identifier) @attribute + property: (property_identifier) @attribute))) + +; Types +(type_declaration + (identifier) @type) +(type_declaration + (identifier) + "=" + (identifier) @type) + +(type + (identifier) @type) + +(resource_declaration + (identifier) @type) + +(resource_expression + (identifier) @type) + +; Parameters +(parameter_declaration + (identifier) @variable.parameter + (_)) + +(call_expression + function: (_) + (arguments + (identifier) @variable.parameter)) + +(call_expression + function: (_) + (arguments + (member_expression + object: (identifier) @variable.parameter))) + +(parameter + . + (identifier) @variable.parameter) + +; Variables +(variable_declaration + (identifier) @variable + (_)) + +(metadata_declaration + (identifier) @variable + (_)) + +(output_declaration + (identifier) @variable + (_)) + +(object_property + (_) + ":" + (identifier) @variable) + +(for_statement + "for" + (for_loop_parameters + (loop_variable) @variable + (loop_enumerator) @variable)) + +; Conditionals +"if" @keyword.conditional + +(ternary_expression + "?" @keyword.control.conditional + ":" @keyword.control.conditional) + +; Loops +(for_statement + "for" @keyword.control.repeat + "in" + ":" @punctuation.delimiter) + +; Keywords [ "module" - "var" + "metadata" + "output" "param" - "import" "resource" "existing" - "if" "targetScope" - "output" + "type" + "var" + "using" + "test" ] @keyword -; Functions +"func" @keyword.function -(decorator) @function.builtin +"assert" @keyword.control.exception -(functionCall) @function +; Operators +[ + "+" + "-" + "*" + "/" + "%" + "||" + "&&" + "|" + "==" + "!=" + "=~" + "!~" + ">" + ">=" + "<=" + "<" + "??" + "=" + "!" + ".?" +] @operator -(functionCall - (functionArgument - (variableAccess) @variable)) +(subscript_expression + "?" @operator) -; Literals/Types +(nullable_type + "?" @operator) -[ - "(" - ")" - "[" - "]" - "{" - "}" -] @punctuation.bracket +"in" @keyword.operator -(resourceDeclaration - (string - (stringLiteral) @string.special)) +; Literals +(string) @string -(moduleDeclaration - (string - (stringLiteral) @string.special)) +(escape_sequence) @constant.character -[ - (string) - (stringLiteral) -] @string +(number) @constant.number -(nullLiteral) @keyword -(booleanLiteral) @constant.builtin.boolean -(integerLiteral) @constant.numeric.integer -(comment) @comment +(boolean) @constant.builtin.boolean -(string - (variableAccess - (identifier) @variable)) +(null) @constant.builtin -(type) @type +; Misc +(compatible_identifier + "?" @punctuation.special) -; Variables +(nullable_return_type) @punctuation.special + +[ + "{" + "}" +] @punctuation.bracket -(localVariable) @variable +[ + "[" + "]" +] @punctuation.bracket -; Statements +[ + "(" + ")" +] @punctuation.bracket -(object - (objectProperty - (identifier) @identifier)) +[ + "." + ":" + "::" + "=>" +] @punctuation.delimiter -(propertyAccess - (identifier) @identifier) - -(ifCondition) @keyword.control.conditional +; Interpolation +(interpolation + "${" @punctuation.special + "}" @punctuation.special) + +(interpolation + (identifier) @variable) + +; Comments +[ + (comment) + (diagnostic_comment) +] @comment diff --git a/runtime/queries/comment/highlights.scm b/runtime/queries/comment/highlights.scm index e0916cece..8d1232453 100644 --- a/runtime/queries/comment/highlights.scm +++ b/runtime/queries/comment/highlights.scm @@ -21,10 +21,10 @@ ; Error level tags ((tag (name) @error) - (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG)$")) + (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG|INVARIANT)$")) ("text" @error - (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG)$")) + (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG|INVARIANT)$")) (tag (name) @ui.text diff --git a/runtime/queries/llvm-mir/highlights.scm b/runtime/queries/llvm-mir/highlights.scm index 792346122..743b9690b 100644 --- a/runtime/queries/llvm-mir/highlights.scm +++ b/runtime/queries/llvm-mir/highlights.scm @@ -75,11 +75,16 @@ "pre-instr-symbol" "post-instr-symbol" "heap-alloc-marker" + "pcsections" + "mmra" + "cfi-type" "debug-instr-number" "debug-location" + "dbg-instr-ref" "mcsymbol" "tied-def" "target-flags" + "vscale" "CustomRegMask" "same_value" "def_cfa_register" @@ -118,11 +123,16 @@ "got" "jump-table" "syncscope" - "address-taken" + "machine-block-address-taken" + "ir-block-address-taken" "landing-pad" "inlineasm-br-indirect-target" "ehfunclet-entry" + "bb_id" + "call-frame-size" "bbsections" + "Exception" + "Cold" (intpred) (floatpred) diff --git a/runtime/queries/llvm/highlights.scm b/runtime/queries/llvm/highlights.scm index cb705197e..4de2a1655 100644 --- a/runtime/queries/llvm/highlights.scm +++ b/runtime/queries/llvm/highlights.scm @@ -17,9 +17,11 @@ [ "to" + "nneg" "nuw" "nsw" "exact" + "disjoint" "unwind" "from" "cleanup" diff --git a/runtime/queries/nestedtext/highlights.scm b/runtime/queries/nestedtext/highlights.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/nestedtext/highlights.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/nestedtext/indents.scm b/runtime/queries/nestedtext/indents.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/nestedtext/indents.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/nestedtext/injections.scm b/runtime/queries/nestedtext/injections.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/nestedtext/injections.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/nestedtext/textobjects.scm b/runtime/queries/nestedtext/textobjects.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/nestedtext/textobjects.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/nix/injections.scm b/runtime/queries/nix/injections.scm index 9804b75be..2fb8918a7 100644 --- a/runtime/queries/nix/injections.scm +++ b/runtime/queries/nix/injections.scm @@ -127,6 +127,16 @@ (#set! injection.language "haskell") (#set! injection.combined)) +; pkgs.writers.writeNim[Bin] name attrs content +(apply_expression + (apply_expression + function: (apply_expression + function: ((_) @_func))) + argument: (indented_string_expression (string_fragment) @injection.content) + (#match? @_func "(^|\\.)writeNim(Bin)?$") + (#set! injection.language "nim") + (#set! injection.combined)) + ; pkgs.writers.writeJS[Bin] name attrs content (apply_expression (apply_expression diff --git a/runtime/queries/perl/highlights.scm b/runtime/queries/perl/highlights.scm index c2496f9fb..bf5918b95 100644 --- a/runtime/queries/perl/highlights.scm +++ b/runtime/queries/perl/highlights.scm @@ -1,9 +1,9 @@ [ - "use" "no" "require" "package" + "use" "no" "require" "package" "class" "role" ] @keyword.control.import [ - "sub" + "sub" "method" "async" "extended" ] @keyword.function [ @@ -17,7 +17,7 @@ ] @keyword.control.repeat [ - "my" "our" "local" + "my" "our" "local" "state" ] @keyword.storage.modifier [ @@ -29,9 +29,10 @@ ] @constant.builtin (phaser_statement phase: _ @keyword.directive) +(class_phaser_statement phase: _ @keyword.directive) [ - "or" "and" + "or" "xor" "and" "eq" "ne" "cmp" "lt" "le" "ge" "gt" "isa" ] @keyword.operator @@ -55,7 +56,7 @@ [(quoted_regexp) (match_regexp)] @string.regexp -(autoquoted_bareword _?) @string.special +(autoquoted_bareword) @string.special [(scalar) (arraylen)] @variable (scalar_deref_expression ["->" "$" "*"] @variable) diff --git a/runtime/queries/quint/highlights.scm b/runtime/queries/quint/highlights.scm new file mode 100644 index 000000000..edb56fbad --- /dev/null +++ b/runtime/queries/quint/highlights.scm @@ -0,0 +1,94 @@ +[ + "module" + "type" + "assume" + "const" + "var" + "val" + "nondet" + "def" + "pure" + "action" + "temporal" + "run" +] @keyword + +(match_expr "match" @keyword.control.conditional) + +(if_else_condition + "if" @keyword.control.conditional + "else" @keyword.control.conditional) + +(import "import" @keyword.control.import) +(import "as" @keyword.control.import) +(import "from" @keyword.control.import) +(export "export" @keyword.control.import) +(export "as" @keyword.control.import) + +[ + "true" + "false" + "Int" + "Nat" + "Bool" +] @constant.builtin + +[ + ";" + "." + "," +] @punctuation.delimiter + +[ + "-" + "+" + "*" + "/" + "%" + "<" + "<=" + "=" + "==" + "!=" + "=>" + ">" + ">=" + "^" + "->" +] @operator + +(infix_and "and" @operator) +(infix_or "or" @operator) +(infix_iff "iff" @operator) +(infix_implies "implies" @operator) + +(braced_and "and" @keyword) +(braced_or "or" @keyword) +(braced_all "all" @keyword) +(braced_any "any" @keyword) + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(polymorphic_type + (type) @type.parameter) + +(variant_constructor) @type.enum.variant + +(type) @type +(int_literal) @constant.numeric.integer +(comment) @comment +(string) @string + +(operator_application + operator: (qualified_identifier) @function) + +(operator_definition + name: (qualified_identifier) @function + arguments: (typed_argument_list)) diff --git a/runtime/queries/rescript/highlights.scm b/runtime/queries/rescript/highlights.scm index ed41322b4..51d37b87c 100644 --- a/runtime/queries/rescript/highlights.scm +++ b/runtime/queries/rescript/highlights.scm @@ -10,11 +10,10 @@ [ (type_identifier) (unit_type) + (list) + (list_pattern) ] @type -(list ["list{" "}"] @type) -(list_pattern ["list{" "}"] @type) - [ (variant_identifier) (polyvar_identifier) @@ -72,14 +71,16 @@ ; single parameter with no parens (function parameter: (value_identifier) @variable.parameter) +; first-level descructuring (required for nvim-tree-sitter as it only matches direct +; children and the above patterns do not match destructuring patterns in NeoVim) +(parameter (tuple_pattern (tuple_item_pattern (value_identifier) @variable.parameter))) +(parameter (array_pattern (value_identifier) @variable.parameter)) +(parameter (record_pattern (value_identifier) @variable.parameter)) + ; Meta ;----- -[ - "@" - "@@" - (decorator_identifier) -] @keyword.directive +(decorator_identifier) @keyword.directive (extension_identifier) @keyword ("%") @keyword @@ -87,7 +88,7 @@ ; Misc ;----- -; (subscript_expression index: (string) @attribute) +(subscript_expression index: (string) @attribute) (polyvar_type_pattern "#" @constant) [ @@ -101,18 +102,21 @@ "external" "let" "module" + "mutable" "private" "rec" "type" "and" "assert" - "async" "await" "with" - "unpack" -] @keyword.storage.type + "lazy" + "constraint" +] @keyword + +((function "async" @keyword.storage)) -"mutable" @keyword.storage.modifier +(module_unpack "unpack" @keyword) [ "if" @@ -169,6 +173,7 @@ "->" "|>" ":>" + "+=" (uncurry) ] @operator diff --git a/runtime/queries/rescript/injections.scm b/runtime/queries/rescript/injections.scm index 03e29b008..67f530d3b 100644 --- a/runtime/queries/rescript/injections.scm +++ b/runtime/queries/rescript/injections.scm @@ -1,8 +1,29 @@ -((comment) @injection.content - (#set! injection.language "comment")) +((comment) @injection.content (#set! injection.language "comment")) -((raw_js) @injection.content - (#set! injection.language "javascript")) +; %re +(extension_expression + (extension_identifier) @_name + (#eq? @_name "re") + (expression_statement (_) @injection.content (#set! injection.language "regex"))) + +; %raw +(extension_expression + (extension_identifier) @_name + (#eq? @_name "raw") + (expression_statement + (_ (_) @injection.content (#set! injection.language "javascript")))) + +; %graphql +(extension_expression + (extension_identifier) @_name + (#eq? @_name "graphql") + (expression_statement + (_ (_) @injection.content (#set! injection.language "graphql")))) + +; %relay +(extension_expression + (extension_identifier) @_name + (#eq? @_name "relay") + (expression_statement + (_ (_) @injection.content (#set! injection.language "graphql") ))) -((raw_gql) @injection.content - (#set! injection.language "graphql")) \ No newline at end of file diff --git a/runtime/queries/rescript/locals.scm b/runtime/queries/rescript/locals.scm index 1240ed160..4de73890e 100644 --- a/runtime/queries/rescript/locals.scm +++ b/runtime/queries/rescript/locals.scm @@ -1,7 +1,7 @@ (switch_expression) @local.scope -(if_expression) @local.scope ; Definitions ;------------ -(type_declaration) @local.defintion -(let_binding) @local.defintion +(type_declaration) @local.definition +(let_binding) @local.definition +(module_declaration) @local.definition diff --git a/runtime/queries/rescript/textobjects.scm b/runtime/queries/rescript/textobjects.scm index 4f1d8c53a..32c77b8f9 100644 --- a/runtime/queries/rescript/textobjects.scm +++ b/runtime/queries/rescript/textobjects.scm @@ -1,7 +1,7 @@ ; Classes (modules) ;------------------ -(module_declaration definition: ((_) @class.inside)) @class.around +(module_binding definition: ((_) @class.inside)) @class.around ; Blocks ;------- diff --git a/runtime/queries/solidity/highlights.scm b/runtime/queries/solidity/highlights.scm index 73f354a25..8b5dae420 100644 --- a/runtime/queries/solidity/highlights.scm +++ b/runtime/queries/solidity/highlights.scm @@ -12,6 +12,8 @@ (unicode_string_literal) (yul_string_literal) ] @string +(hex_string_literal "hex" @string.special.symbol) +(unicode_string_literal "unicode" @string.special.symbol) [ (number_literal) (yul_decimal_number) @@ -20,6 +22,7 @@ [ (true) (false) + (yul_boolean) ] @constant.builtin.boolean (comment) @comment @@ -44,18 +47,18 @@ (type_name "(" @punctuation.bracket "=>" @punctuation.delimiter ")" @punctuation.bracket) ; Definitions -(struct_declaration +(struct_declaration name: (identifier) @type) -(enum_declaration +(enum_declaration name: (identifier) @type) (contract_declaration - name: (identifier) @type) + name: (identifier) @type) (library_declaration - name: (identifier) @type) + name: (identifier) @type) (interface_declaration name: (identifier) @type) -(event_definition - name: (identifier) @type) +(event_definition + name: (identifier) @type) (function_definition name: (identifier) @function) diff --git a/runtime/queries/spade/highlights.scm b/runtime/queries/spade/highlights.scm new file mode 100644 index 000000000..08511b859 --- /dev/null +++ b/runtime/queries/spade/highlights.scm @@ -0,0 +1,130 @@ +(self) @variable.builtin + +(unit_definition (identifier) @function) + +(parameter (identifier) @variable.parameter) + +((pipeline_reg_marker) @keyword) + +(scoped_identifier + path: (identifier) @namespace) +(scoped_identifier + (scoped_identifier + name: (identifier) @namespace)) + +((builtin_type) @type.builtin) + +((identifier) @type.builtin + (#any-of? + @type.builtin + "uint" + "Option" + "Memory")) + +((identifier) @type.enum.variant.builtin + (#any-of? @type.enum.variant.builtin "Some" "None")) + +((pipeline_stage_name) @label) + +((stage_reference + stage: (identifier) @label)) + +[ + "pipeline" + "let" + "set" + "entity" + "fn" + "reg" + "reset" + "initial" + "inst" + "assert" + "struct" + "enum" + "stage" + "impl" + "port" + "decl" + "mod" + "where" + "trait" +] @keyword + +[ + "use" +] @keyword.import + +[ + "$if" + "$else" + "$config" +] @keyword.directive + +((comptime_if ["{" "}"] @keyword.directive)) +((comptime_else ["{" "}"] @keyword.directive)) + +((attribute) ["#" "[" "]"] @punctuation.delimiter) + +[ + "else" + "if" + "match" +] @keyword.control.conditional + +(bool_literal) @constant.builtin.boolean +(int_literal) @constant.numeric.integer + +[ + "&" + "inv" + "-" + "=>" + ">" + "<" + "::<" + "::$<" + "=" + "->" + "~" + "!" +] @operator + + +((op_add) @operator) +((op_sub) @operator) +((op_mul) @operator) +((op_equals) @operator) +((op_lt) @operator) +((op_gt) @operator) +((op_le) @operator) +((op_ge) @operator) +((op_lshift) @operator) +((op_rshift) @operator) +((op_bitwise_and) @operator) +((op_bitwise_xor) @operator) +((op_bitwise_or) @operator) +((op_logical_and) @operator) +((op_logical_or) @operator) + + +[ + (line_comment) + (block_comment) +] @comment + +[ + (doc_comment) +] @comment.block.documentation + + +((identifier) @type + (#match? @type "[A-Z]")) + +((scoped_identifier + name: (identifier) @type) + (#match? @type "^[A-Z]")) + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + diff --git a/runtime/queries/spade/indents.scm b/runtime/queries/spade/indents.scm new file mode 100644 index 000000000..dc30bdc3e --- /dev/null +++ b/runtime/queries/spade/indents.scm @@ -0,0 +1,27 @@ + +[ + (unit_definition) + (struct_definition) + (enum_definition) + (enum_member) + (impl) + (mod) + (argument_list) + (let_binding) + (block) + (tuple_literal) + (array_literal) + (paren_expression) + (turbofish) + (generic_parameters) + (named_unpack) + (positional_unpack) + (tuple_pattern) +] @indent + +[ + "}" + "]" + ")" +] @outdent + diff --git a/runtime/queries/tablegen/highlights.scm b/runtime/queries/tablegen/highlights.scm index 8ade5ba9a..188fa2ef0 100644 --- a/runtime/queries/tablegen/highlights.scm +++ b/runtime/queries/tablegen/highlights.scm @@ -68,7 +68,9 @@ "def" "defset" "defvar" + "deftype" "assert" + "dump" ] @keyword [ diff --git a/runtime/queries/textproto/highlights.scm b/runtime/queries/textproto/highlights.scm new file mode 100644 index 000000000..766897f44 --- /dev/null +++ b/runtime/queries/textproto/highlights.scm @@ -0,0 +1,22 @@ +(string) @string + +(field_name) @variable.other.member + +(comment) @comment + +(number) @constant.numeric +; covers e.g. booleans and "inf" +(scalar_value (identifier)) @constant +; Covers "-inf" +(scalar_value (signed_identifier)) @constant.numeric + +[ + (open_squiggly) + (close_squiggly) + (open_square) + (close_square) + (open_arrow) + (close_arrow) +] @punctuation.bracket + +"," @punctuation.delimiter diff --git a/runtime/queries/textproto/indents.scm b/runtime/queries/textproto/indents.scm new file mode 100644 index 000000000..ebea3ff39 --- /dev/null +++ b/runtime/queries/textproto/indents.scm @@ -0,0 +1,11 @@ +[ + (message_value) + (message_list) + (scalar_list) +] @indent + +[ + (close_arrow) + (close_square) + (close_squiggly) +] @outdent diff --git a/runtime/queries/textproto/textobjects.scm b/runtime/queries/textproto/textobjects.scm new file mode 100644 index 000000000..9cc428c6a --- /dev/null +++ b/runtime/queries/textproto/textobjects.scm @@ -0,0 +1,12 @@ +(message_field + (_) @entry.inside) @entry.around + +(scalar_field + (_) @entry.inside) @entry.around + +(message_list + (_) @entry.around) + +(scalar_list + (_) @entry.around) + diff --git a/runtime/queries/unison/highlights.scm b/runtime/queries/unison/highlights.scm index 711779295..4c8f0c234 100644 --- a/runtime/queries/unison/highlights.scm +++ b/runtime/queries/unison/highlights.scm @@ -9,32 +9,25 @@ ;; Keywords [ (kw_forall) - (type_kw) (kw_equals) (do) + (kw_let) (ability) (where) ] @keyword (kw_let) @keyword.function -(type_kw) @keyword.storage.type -(unique) @keyword.storage.modifier +(type_kw) @keyword.storage.modifier (structural) @keyword.storage.modifier ("use") @keyword.control.import - - -[ - (type_constructor) -] @constructor +(unique) @keyword.storage.modifier [ (operator) (pipe) (arrow_symbol) - (">") (or) (and) - (bang) ] @operator [ @@ -48,24 +41,62 @@ (blank_pattern) @variable.builtin +(pattern) @variable + +(use_clause) @keyword.import + ;; Types -(record_field name: (wordy_id) @variable.other.member type: (_) @type) -(type_constructor (type_name (wordy_id) @constructor)) -(ability_declaration type_name: (wordy_id) @type type_arg: (wordy_id) @variable.parameter) -(effect (wordy_id) @special) ;; NOTE: an effect is just like a type, but in signature we special case it +(record_field + (field_name) @variable.other.member + type: (regular_identifier) @type) + +(type_name) @type + +(type_declaration + (regular_identifier) @type.enum.variant) + +(ability_name + (path)? @namespace + (regular_identifier) @type) -;; Namespaces -(path) @namespace -(namespace) @namespace +(ability_declaration + (ability_name) @type + (type_argument) @variable.parameter) -;; Terms -(type_signature term_name: (path)? @variable term_name: (wordy_id) @variable) -(type_signature (wordy_id) @type) -(type_signature (term_type(delayed(wordy_id))) @type) +(type_constructor) @constructor -(term_definition param: (wordy_id) @variable.parameter) +(constructor + (constructor_name) @constructor) -(function_application function_name: (path)? function_name: (wordy_id) @function) +(constructor + type: (regular_identifier) @type) + +(effect + (regular_identifier) @special) ; NOTE: an effect is a special type + +; Namespaces +(path) @module + +(namespace) @module + +; Terms +(type_signature + term_name: (path) @module + term_name: (regular_identifier) @variable) + +(type_signature + term_name: (regular_identifier) @variable) + +(term_type) @type + +(term_definition + name: (path) @namespace) + +(term_definition + name: (regular_identifier) @variable) + +(term_definition + param: (regular_identifier) @variable.parameter) ;; Punctuation [ @@ -82,4 +113,6 @@ "]" ] @punctuation.bracket -(test_watch_expression (wordy_id) @keyword.directive) +(watch_expression) @keyword.directive + +(test_watch_expression) @keyword.directive diff --git a/runtime/queries/unison/indents.scm b/runtime/queries/unison/indents.scm index 6cb15517c..9ebe26ced 100644 --- a/runtime/queries/unison/indents.scm +++ b/runtime/queries/unison/indents.scm @@ -1,11 +1,6 @@ [ (term_definition) - (type_declaration) (pattern) - (tuple_or_parenthesized) - (literal_list) - (tuple_pattern) - (function_application) (exp_if) (constructor) (delay_block) diff --git a/runtime/queries/unison/textobjects.scm b/runtime/queries/unison/textobjects.scm new file mode 100644 index 000000000..02a908368 --- /dev/null +++ b/runtime/queries/unison/textobjects.scm @@ -0,0 +1,15 @@ +(term_declaration) @function.around + +(type_declaration) @class.inside +(record) @class.inside + +(comment) @comment.inside +(comment)+ @comment.around + +(doc_block) @comment.around + +(literal_list) @entry.around + +(parenthesized_or_tuple_pattern) @entry.around + +(pattern) @entry.around diff --git a/runtime/themes/adwaita-light.toml b/runtime/themes/adwaita-light.toml new file mode 100644 index 000000000..5bbbaf68d --- /dev/null +++ b/runtime/themes/adwaita-light.toml @@ -0,0 +1,110 @@ +inherits="adwaita-dark" +"attribute" = "orange_5" + +"type" = "teal_4" +"type.builtin" = "teal_4" + +"constructor" = "blue_4" + +"constant" = "violet_4" +"constant.builtin" = { fg = "violet_4", modifiers = ["bold"] } +"constant.character" = "teal_5" +"constant.numeric" = { fg = "teal_5", modifiers = ["bold"] } +"constant.character.escape" = "violet_4" + +"string" = "teal_3" +"string.regexp" = "purple_4" +"string.special" = "blue_4" + +"comment" = "light_6" + +"variable" = "dark_5" +"variable.parameter" = "orange_4" +"variable.builtin" = "orange_4" +"variable.other" = "teal_4" +"variable.other.member" = "teal_5" + +"label" = "purple_4" + +"punctuation" = "dark_4" +"punctuation.delimiter" = "dark_4" +"punctuation.bracket" = "dark_4" +"punctuation.special" = "red_5" + +"keyword" = { fg = "orange_4", modifiers = ["bold"] } +"keyword.control" = { fg = "orange_4", modifiers = ["bold"] } +"keyword.operator" = "purple_4" +"keyword.directive" = { fg = "orange_4", modifiers = ["bold"] } +"keyword.function" = "orange_4" +"keyword.storage" = { fg = "orange_4", modifiers = ["bold"] } + +"operator" = "purple_4" + +"function" = "blue_4" +"function.builtin" = "blue_4" +"function.macro" = { fg = "blue_4", modifiers = ["bold"] } +"function.special" = { fg = "blue_4", modifiers = ["bold"] } + +"tag" = "teal_4" + +"namespace" = "orange_4" + +"markup" = "dark_4" +"markup.heading" = { fg = "teal_4", modifiers = ["bold"] } +"markup.list" = { fg = "orange_4", modifiers = ["bold"] } +"markup.bold" = { fg = "dark_4", modifiers = ["bold"] } +"markup.italic" = { fg = "dark_4", modifiers = ["italic"] } +"markup.link" = { fg = "blue_5", modifiers = ["underlined"] } +"markup.quote" = { fg = "dark_3", modifiers = ["italic"] } +"diff.plus" = "teal_5" +"diff.minus" = "red_3" +"diff.delta" = "orange_5" +"diff.delta.moved" = "orange_4" + +"ui.background" = { fg = "dark_4", bg = "light_1" } +"ui.background.separator" = { fg = "split_and_borders", bg = "light_2" } +"ui.cursor" = { fg = "light_2", bg = "dark_5" } +"ui.cursor.insert" = { fg = "light_2", bg = "dark_4" } +"ui.cursor.primary.insert" = { fg = "light_2", bg = "yellow_5" } +"ui.cursor.select" = { fg = "light_2", bg = "dark_5" } +"ui.cursor.match" = { fg = "light_2", bg = "blue_1" } +"ui.cursor.primary" = { fg = "light_2", bg = "dark_6" } +"ui.linenr" = "light_5" +"ui.linenr.selected" = { fg = "dark_2", bg = "light_3", modifiers = [ + "bold", +] } +"ui.statusline" = { fg = "dark_4", bg = "light_4" } +"ui.statusline.inactive" = { fg = "dark_3", bg = "light_3" } +"ui.statusline.insert" = { fg = "light_5", bg = "teal_3" } +"ui.statusline.select" = { fg = "light_4", bg = "blue_3" } +"ui.popup" = { bg = "light_3" } +"ui.window" = "split_and_borders" +"ui.help" = { bg = "light_3" } +"ui.text" = "dark_4" +"ui.virtual" = "light_1" +"ui.virtual.ruler" = { bg = "light_5"} +"ui.menu" = { fg = "dark_4", bg = "light_3" } +"ui.menu.selected" = { fg = "dark_4", bg = "blue_1" } +"ui.menu.scroll" = { fg = "dark_6", bg = "light_3" } +"ui.selection" = { bg = "blue_0" } +"ui.selection.primary" = { bg = "blue_0" } +"ui.cursorline.primary" = { bg = "light_3" } +"ui.virtual.whitespace" = "light_7" + +"warning" = "yellow_4" +"error" = "red_5" +"info" = "purple_3" +"hint" = "blue_3" + +"diagnostic.hint" = { fg = "blue_4", modifiers = ["dim"] } +"diagnostic.info" = { fg = "purple_4", modifiers = ["dim"] } +"diagnostic.error" = { fg = "red_5", modifiers = ["underlined"] } +"diagnostic.warning" = { fg = "yellow_4", modifiers = ["underlined"] } +"diagnostic.unnecessary" = { modifiers = ["dim"] } +"diagnostic.deprecated" = { modifiers = ["crossed_out"] } + +"ui.bufferline" = { fg = "light_7", bg = "light_2" } +"ui.bufferline.active" = { fg = "dark_4", bg = "light_4", modifiers = ["bold"]} + +[palette] +blue_0 = "#d3e4f9" diff --git a/runtime/themes/carbonfox.toml b/runtime/themes/carbonfox.toml new file mode 100644 index 000000000..12e812955 --- /dev/null +++ b/runtime/themes/carbonfox.toml @@ -0,0 +1,50 @@ +# Author: github.com/ETCaton +# License: MIT License +# Carbonfox +# +# Based on Helix's Nightfox port with changes to align it to Nightfox's Carbonfox theme +# Any 'custom' colors are replicating the result of the linear color blending done in the original +# Neovim theme. +# https://github.com/EdenEast/nightfox.nvim/blob/d3e8b1acc095baf57af81bb5e89fe7c4359eb619/lua/nightfox/lib/color.lua#L236-L247 + +inherits = 'nightfox' + +# DIAGNOSTICS +# For brevity: All blends here are a blend between bg1 and the fg value with factor of 0.15 +"warning" = { fg = "magenta", bg = "#2f2939" } +"error.bg" = "#361f29" +"info.bg" = "#252c39" +"hint" = { fg = "orange", bg = "#1c3433" } + +[palette] +black = "#282828" +red = "#ee5396" +red-dim = "#ca4780" +green = "#25be6a" +green-dim = "#1fa25a" +yellow = "#08bdba" +yellow-bright = "#2dc7c4" +blue = "#78a9ff" +blue-bright = "#8cb6ff" +blue-dim = "#6690d9" +magenta = "#be95ff" +magenta-bright = "#c8a5ff" +cyan = "#33b1ff" +cyan-bright = "#52bdff" +cyan-dim = "#2b96d9" +orange = "#3ddbd9" +orange-bright = "#5ae0df" +pink = "#ff7eb6" +pink-bright = "#ff91c1" +# spec +bg0 = "#0c0c0c" +bg1 = "#161616" +bg2 = "#252525" +bg3 = "#353535" +bg4 = "#535353" +fg0 = "#f9fbff" +fg1 = "#f2f4f8" +fg2 = "#b6b8bb" +fg3 = "#7b7c7e" +sel0 = "#2a2a2a" +sel1 = "#525253" diff --git a/runtime/themes/eiffel.toml b/runtime/themes/eiffel.toml new file mode 100644 index 000000000..ba0f5c60d --- /dev/null +++ b/runtime/themes/eiffel.toml @@ -0,0 +1,180 @@ +## Author: mesmere <95945959+mesmere@users.noreply.github.com> +## Original design by Ian Joyner + +"attribute" = { fg = "markup", modifiers = ["italic"] } +"comment" = "comments" +"comment.block" = "comments" +"comment.block.documentation" = "comments" +"comment.line" = "comments" +#"constant" = "" +"constant.builtin" = { fg = "builtins", modifiers = ["italic"] } +"constant.character" = "strings" +"constant.character.escape" = "symbols" +"constant.numeric" = { fg = "constants_numeric", modifiers = ["italic"] } +"constructor" = { modifiers = ["italic"] } +"function" = { fg = "members" } +"function.builtin" = "builtins" +"function.macro" = "preprocessor" +"function.method" = { fg = "members", modifiers = ["italic"] } +#"function.method.private" = "" +"function.special" = "preprocessor" +"keyword" = { fg = "ui_text" } +"keyword.control" = { fg = "keywords", modifiers = ["bold"] } +"keyword.directive" = { fg = "preprocessor", modifiers = ["bold"] } +#"keyword.function" = "" +"keyword.operator" = { fg = "operators", modifiers = ["italic"] } +#"keyword.storage" = "" +#"label" = "" +#"namespace" = "" +"operator" = { fg = "operators", modifiers = ["bold"] } +#"punctuation" = "" +#"punctuation.bracket" = "" +#"punctuation.delimiter" = "" +"punctuation.special" = "strings" +#"special" = "" +"string" = "strings" +"string.regexp" = "symbols" +"string.special" = "symbols" +"tag" = "markup" +"type" = { modifiers = ["italic"] } +#"type.builtin" = "" +#"type.enum" = "" +#"type.parameter" = "" +#"variable" = "" +"variable.builtin" = "builtins" +"variable.other.member" = { fg = "members", modifiers = ["italic"] } +#"variable.other.member.private" = "" +#"variable.parameter" = "" +"markup" = "markup" +"markup.heading" = { fg = "markup_headings", modifiers = ["bold"] } +#"markup.heading.marker" = "" +"markup.list" = "markup_lists" +"markup.bold" = { modifiers = ["bold"] } +"markup.italic" = { modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } +"markup.link.url" = { fg = "strings", underline.style = "line" } # Match HTML href/src attributes. +#"markup.link.label" = "" +"markup.link.text" = "ui_text" +"markup.quote" = { fg = "black", modifiers = ["italic"] } +"markup.raw" = "strings" +#"markup.raw.inline" = "" +#"markup.raw.block" = "" + +"diff.delta" = "diff_delta" +"diff.minus" = "diff_minus" +"diff.plus" = "diff_plus" + +"ui.background" = { bg = "ui_background" } +#"ui.background.separator" = "" +"ui.bufferline" = { fg = "ui_text_dim", bg = "ui_background_accent" } +"ui.bufferline.active" = { fg = "ui_text", bg = "ui_background_accent" } +"ui.bufferline.background" = { bg = "ui_background_accent" } +#"ui.cursor" = { modifiers = ['reversed'] } +"ui.cursor.insert" = { bg = "ui_mode_insert_accent" } +"ui.cursor.match" = { modifiers = ['reversed'] } +"ui.cursor.normal" = { bg = "ui_mode_normal_accent" } +"ui.cursor.select" = { bg = "ui_mode_select_accent" } +#"ui.cursor.primary" = "" +"ui.cursor.primary.insert" = { bg = "ui_mode_insert" } +#"ui.cursor.primary.match" = "" +"ui.cursor.primary.normal" = { bg = "ui_mode_normal" } +"ui.cursor.primary.select" = { bg = "ui_mode_select" } +"ui.cursorcolumn.primary" = { bg = "ui_background_accent" } +#"ui.cursorcolumn.secondary" = "" +"ui.cursorline.primary" = { bg = "ui_background_accent" } +#"ui.cursorline.secondary" = "" +"ui.debug.active" = { fg = "ui_debug_breakpoint" } +"ui.debug.breakpoint" = { fg = "ui_debug_breakpoint" } +"ui.gutter" = { bg = "ui_background" } +"ui.gutter.selected" = { bg = "ui_background_accent" } +"ui.help" = { fg = "ui_text", bg = "ui_menu" } +"ui.highlight" = { fg = "ui_highlight_line_text", bg = "ui_highlight_line" } # fg is not respected https://github.com/helix-editor/helix/issues/11141 +"ui.highlight.frameline" = { fg = "ui_highlight_line_text", bg = "ui_highlight_line" } +"ui.linenr" = "ui_text_dim" +"ui.linenr.selected" = { fg = "ui_text_dim", bg = "ui_background_accent" } +"ui.menu" = { fg = "ui_menu_text", bg = "ui_menu" } +"ui.menu.scroll" = { fg = "ui_menu_handle", bg = "ui_menu_selected" } +"ui.menu.selected" = { fg = "ui_text", bg = "ui_menu_selected" } +#"ui.picker" = { fg = "ui_text", bg = "ui_menu" } # Styling the picker is currently unsupported. +"ui.picker.header" = { bg = "ui_background_accent" } +"ui.picker.header.column" = "ui_text" +"ui.picker.header.column.active" = { fg = "ui_text", modifiers = ["bold"], underline = { style = "line" } } +"ui.popup" = { fg = "ui_text", bg = "ui_background_accent" } +"ui.popup.info" = { fg = "ui_text", bg = "ui_menu" } +"ui.selection" = { bg = "ui_selection" } +#"ui.selection.primary" = { bg = "ui_selection", underline.style = "line" } +"ui.statusline" = { fg = "ui_text", bg = "ui_background_accent" } +#"ui.statusline.inactive" = { fg = "", bg = "" } +"ui.statusline.insert" = { fg = "ui_mode_insert_text", bg = "ui_mode_insert", modifiers = ["bold"] } +"ui.statusline.normal" = { fg = "ui_mode_normal_text", bg = "ui_mode_normal", modifiers = ["bold"] } +"ui.statusline.select" = { fg = "ui_mode_select_text", bg = "ui_mode_select", modifiers = ["bold"] } +"ui.text" = "ui_text" +"ui.text.focus" = { fg = "ui_text", modifiers = ["bold"] } +"ui.text.inactive" = "ui_text_dim" +#"ui.text.info" = "" +"ui.virtual.indent-guide" = "ui_text_dim" +"ui.virtual.inlay-hint" = "ui_text_dim" +#"ui.virtual.inlay-hint.parameter" = "" +#"ui.virtual.inlay-hint.type" = "" +"ui.virtual.jump-label" = { fg = "white", bg = "ui_jumplabel", modifiers = ["bold"] } +"ui.virtual.ruler" = { bg = "ui_background_accent" } +"ui.virtual.whitespace" = "ui_text_dim" +"ui.virtual.wrap" = "ui_text_dim" +"ui.window" = "ui_split_line" + +info = { fg = 'ui_diagnostic_info' } +hint = { fg = 'ui_diagnostic_hint', modifiers = ['bold'] } +warning = { fg = 'ui_diagnostic_warning', modifiers = ['bold'] } +error = { fg = 'ui_diagnostic_error', modifiers = ['bold'] } + +"diagnostic.info" = { fg = "ui_diagnostic_info", underline = { style = "curl", color = "ui_diagnostic_info" } } +"diagnostic.hint" = { fg = "ui_diagnostic_hint", underline = { style = "curl", color = "ui_diagnostic_hint" } } +"diagnostic.warning" = { fg = "ui_diagnostic_warning", underline = { style = "curl", color = "ui_diagnostic_warning" } } +"diagnostic.error" = { fg = "ui_diagnostic_error", underline = { style = "curl", color = "ui_diagnostic_error" } } +"diagnostic.unnecessary" = { modifiers = ["dim"] } +"diagnostic.deprecated" = { modifiers = ["crossed_out"] } + +[palette] +builtins = "#585cf6" +comments = "#00b418" +constants_numeric = "#cd0000" +diff_delta = "#0000a2" +diff_minus = "#990000" +diff_plus = "#00b418" +keywords = "#0100b6" +markup = "#1c02ff" +markup_headings = "#0c07ff" +markup_lists = "#b90690" +members = "#0206ff" +operators = "#0100b6" +preprocessor = "#0c450d" +strings = "#d80800" +symbols = "#26b31a" +ui_background = "#ffffff" +ui_background_accent = "#ededed" +ui_highlight_line = "#0100b6" +ui_highlight_line_text = "#ffffff" +ui_debug_breakpoint = "#990000" +ui_diagnostic_error = "#990000" +ui_diagnostic_hint = "#06960e" +ui_diagnostic_info = "#808080" +ui_diagnostic_warning = "#fafa28" +ui_jumplabel = "#990000" +ui_menu = "#c3dcff" +ui_menu_selected = "#a3bcdf" +ui_menu_handle = "#839cbf" +ui_menu_text = "#000000" +ui_mode_insert = "#009608" +ui_mode_insert_accent = "#73e678" +ui_mode_insert_text = "#ffffff" +ui_mode_normal = "#444444" +ui_mode_normal_accent = "#cccccc" +ui_mode_normal_text = "#ffffff" +ui_mode_select = "#000096" +ui_mode_select_accent = "#7373e6" +ui_mode_select_text = "#ffffff" +ui_selection = "#c3dcff" +ui_split_line = "#000000" +ui_statusline = "#000000" +ui_text = "#000000" +ui_text_dim = "#808080" diff --git a/runtime/themes/hex_lavender.toml b/runtime/themes/hex_lavender.toml index d7c54be69..b14f3cafd 100644 --- a/runtime/themes/hex_lavender.toml +++ b/runtime/themes/hex_lavender.toml @@ -1,13 +1,15 @@ +# Author : portalsurfer + inherits = "hex_steel" [palette] t1 = "#0e0e0d" -t2 = "#121311" +t2 = "#181a17" t3 = "#2b3444" t4 = "#61586f" t5 = "#686e73" t6 = "#878480" -t7 = "#897dca" +t7 = "#8e80de" t8 = "#7b89a3" t9 = "#bcb6ba" t10 = "#9db2b8" @@ -20,12 +22,20 @@ highlight_three = "#29bbff" black = "#000000" selection = "#290019" +selection_fg = "#958e9a" -comment = "#9aacfe" +comment = "#404768" comment_doc = "#0affa9" error = "#ff0900" warning = "#ffbf00" display = "#57ff89" info = "#dad7d5" -# + +hints = "#44273f" +ruler = "#1c1f1b" + +diff_minus = "#ff4000" +diff_delta = "#0078bd" +diff_plus = "#c9d400" +diff_delta_moved = "#0048bd" \ No newline at end of file diff --git a/runtime/themes/hex_poison.toml b/runtime/themes/hex_poison.toml new file mode 100644 index 000000000..0d6e13eee --- /dev/null +++ b/runtime/themes/hex_poison.toml @@ -0,0 +1,41 @@ +# Author : portalsurfer + +inherits = "hex_steel" + +[palette] +t1 = "#121211" +t2 = "#1e1f1b" +t3 = "#4c513a" +t4 = "#5a6052" +t5 = "#6f6d6f" +t8 = "#7e808a" +t7 = "#b1b354" +t10 = "#6fa197" +t9 = "#3f4a4e" +t6 = "#98acaa" +t11 = "#6fd7a8" + +highlight = "#ff2e5f" +highlight_two = "#0affa9" +highlight_three = "#d7ff52" + +black = "#000000" + +selection = "#290019" +selection_fg = "#c8e732" + +comment = "#396884" +comment_doc = "#234048" + +error = "#c73500" +warning = "#dcbb00" +display = "#57ff89" +info = "#dad7d5" + +hints = "#313d3c" +ruler = "#21221e" + +diff_minus = "#ff4000" +diff_delta = "#16a7c7" +diff_plus = "#c9d400" +diff_delta_moved = "#0048bd" \ No newline at end of file diff --git a/runtime/themes/hex_steel.toml b/runtime/themes/hex_steel.toml index fb4fc1fd8..d133cf7f3 100644 --- a/runtime/themes/hex_steel.toml +++ b/runtime/themes/hex_steel.toml @@ -1,14 +1,16 @@ +# Author : portalsurfer + "comment" = { fg = "comment" } "comment.block.documentation" = { bg = "comment_doc", modifiers = ["italic"] } "constant" = { fg = "t11" } "function" = { fg = "t10" } -"function.method" = { fg = "t10" } +"function.method" = { fg = "t7" } "function.macro" = { fg = "t7" } "keyword.storage.modifier" = { fg = "t7" } "keyword.control.import" = { fg = "t8" } "keyword.control" = { fg = "t8" } -"keyword.function" = { fg = "t7" } +"keyword.function" = { fg = "t11" } "keyword" = { fg = "t6" } "operator" = { fg = "t8" } "punctuation" = { fg = "t9" } @@ -18,6 +20,8 @@ "type" = { fg = "t8", modifiers = ["bold"] } "namespace" = { fg = "t6", modifiers = ["bold"] } "variable" = { fg = "t4" } +"variable.parameter" = { fg = "t6" } +"variable.other.member" = { fg = "t3" } "label" = { fg = "t4" } "diff.plus" = { fg = "diff_plus" } @@ -25,10 +29,12 @@ "diff.delta.moved" = { fg = "diff_delta_moved" } "diff.minus" = { fg = "diff_minus" } -"ui.cursor.insert" = { fg = "t2", bg = "highlight" } -"ui.cursor.select" = { fg = "t2", bg = "highlight_two" } -"ui.cursor" = { fg = "t1", bg = "highlight_three" } -"ui.cursor.match" = { fg = "highlight", bg = "selection", modifiers = ["bold"] } +"ui.cursor.primary.insert" = { fg = "t2", bg = "highlight" } +"ui.cursor.primary.select" = { fg = "t2", bg = "highlight_two" } +"ui.cursor.primary" = { fg = "t1", bg = "highlight_three" } +"ui.cursor.match" = { fg = "highlight", bg = "t1", modifiers = ["bold"] } +"ui.cursorline.primary" = { bg = "ruler" } +"ui.cursorline.secondary" = { bg = "ruler" } "ui.linenr" = { fg = "t3", bg = "t2" } "ui.linenr.selected" = { fg = "highlight_three", bg = "t2" } @@ -42,10 +48,7 @@ "ui.popup" = { fg = "t4", bg = "t1" } "ui.window" = { fg = "t4" } -"ui.selection.primary" = { bg = "selection" } -"ui.selection" = { bg = "selection" } - -"ui.cursorline.primary" = { bg = "t1" } +"ui.selection" = { fg = "selection_fg", bg = "selection" } "ui.statusline" = { fg = "t4", bg = "t1" } "ui.statusline.inactive" = { fg = "t4", bg = "t1" } @@ -55,17 +58,20 @@ "ui.text" = { fg = "t4" } "ui.text.focus" = { fg = "highlight_three", modifiers = ["bold"] } -# -"ui.virtual.ruler" = { bg = "t1" } + +"ui.virtual.ruler" = { bg = "ruler" } "ui.virtual.indent-guide" = { fg = "t3" } "ui.virtual.whitespace" = { fg = "t3" } +"ui.virtual.jump-label" = { fg = "t11", modifiers = ["bold"] } +"ui.virtual.inlay-hint" = { fg = "hints", modifiers = ["bold"] } + +"ui.bufferline" = { fg = "t3", bg = "t1" } +"ui.bufferline.active" = { fg = "t7", bg = "t2" } "diagnostic.error" = { underline = { color = "error", style = "curl" } } "diagnostic.warning" = { underline = { color = "warning", style = "curl" } } "diagnostic.info" = { underline = { color = "info", style = "curl" } } "diagnostic.hint" = { underline = { color = "display", style = "curl" } } -"diagnostic.unnecessary" = { modifiers = ["dim"] } -"diagnostic.deprecated" = { modifiers = ["crossed_out"] } "error" = { fg = "error", modifiers = ["bold"] } "warning" = { fg = "warning", modifiers = ["bold"] } @@ -73,14 +79,14 @@ "hint" = { fg = "display", modifiers = ["bold"] } "special" = { fg = "t7", modifiers = ["bold"] } -"markup.heading" = { fg = "t4" } -"markup.list" = { fg = "t4" } +"markup.heading" = { fg = "t7" } +"markup.list" = { fg = "t7" } "markup.bold" = { fg = "t4" } "markup.italic" = { fg = "t4" } "markup.strikethrough" = { fg = "t4", modifiers = ["crossed_out"] } -"markup.link.url" = { fg = "t4", modifiers = ["underlined"] } -"markup.link.text" = { fg = "t4" } -"markup.quote" = { fg = "t4" } +"markup.link.url" = { fg = "t11", modifiers = ["underlined"] } +"markup.link.text" = { fg = "t11" } +"markup.quote" = { fg = "t5" } "markup.raw" = { fg = "t4" } [palette] @@ -93,25 +99,28 @@ t6 = "#6e8789" t7 = "#d85c60" t8 = "#9bc1bb" t9 = "#b5c5c5" -t10 = "#c0d0ce" +t10 = "#c3c3bd" t11 = "#f78c5e" -highlight = "#3f36f2" +highlight = "#f23672" highlight_two = "#f69c3c" highlight_three = "#d4d987" -selection = "#032d4a" +selection = "#4a9aa6" +selection_fg = "#080a0b" black = "#000000" -comment = "#d4d987" +comment = "#654642" comment_doc = "#234048" +hints = "#31353c" +ruler = "#222320" -error = "#ff0900" +error = "#ff4000" warning = "#ffbf00" display = "#42baff" info = "#dad7d5" -diff_minus = "#ff0900" +diff_minus = "#ff4000" diff_delta = "#0078bd" -diff_plus = "#87a800" +diff_plus = "#c9d400" diff_delta_moved = "#0048bd" diff --git a/runtime/themes/hex_toxic.toml b/runtime/themes/hex_toxic.toml index 33bfa6e5f..33f51185b 100644 --- a/runtime/themes/hex_toxic.toml +++ b/runtime/themes/hex_toxic.toml @@ -1,3 +1,5 @@ +# Author : portalsurfer + inherits = "hex_steel" [palette] @@ -19,12 +21,21 @@ highlight_three = "#f8ed8b" black = "#000000" -selection = "#382e1e" +selection = "#b10656" +selection_fg = "#101719" -comment = "#61bdd1" +comment = "#417e8c" comment_doc = "#234048" error = "#ff0900" warning = "#ffbf00" display = "#57ff89" info = "#dad7d5" + +hints = "#39515c" +ruler = "#1e3039" + +diff_minus = "#ff4000" +diff_delta = "#0078bd" +diff_plus = "#c9d400" +diff_delta_moved = "#0048bd" \ No newline at end of file diff --git a/runtime/themes/licenses/carbonfox.license b/runtime/themes/licenses/carbonfox.license new file mode 100644 index 000000000..4f446e776 --- /dev/null +++ b/runtime/themes/licenses/carbonfox.license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 James Simpson + +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. \ No newline at end of file diff --git a/runtime/themes/modus_operandi.toml b/runtime/themes/modus_operandi.toml index 362f97778..5d84741bc 100644 --- a/runtime/themes/modus_operandi.toml +++ b/runtime/themes/modus_operandi.toml @@ -1,6 +1,6 @@ # Author: Alexis Mousset # Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou -# Version 4.4.0 +# Version 4.6.0 # # Syntax highlighting diff --git a/runtime/themes/modus_operandi_deuteranopia.toml b/runtime/themes/modus_operandi_deuteranopia.toml index 27f19a7ad..24d460f6d 100644 --- a/runtime/themes/modus_operandi_deuteranopia.toml +++ b/runtime/themes/modus_operandi_deuteranopia.toml @@ -2,7 +2,7 @@ # modus_operandi.toml variant # # This variant is optimized for users with red-green color deficiency (deuteranopia) -# Version 4.4.0 +# Version 4.6.0 inherits = "modus_operandi" diff --git a/runtime/themes/modus_operandi_tinted.toml b/runtime/themes/modus_operandi_tinted.toml index 1f285361b..63c74f2a1 100644 --- a/runtime/themes/modus_operandi_tinted.toml +++ b/runtime/themes/modus_operandi_tinted.toml @@ -1,6 +1,6 @@ # Author: Alexis Mousset # modus_operandi.toml variant -# Version 4.4.0 +# Version 4.6.0 inherits = "modus_operandi" diff --git a/runtime/themes/modus_operandi_tritanopia.toml b/runtime/themes/modus_operandi_tritanopia.toml index 49d40e931..90fa59f6c 100644 --- a/runtime/themes/modus_operandi_tritanopia.toml +++ b/runtime/themes/modus_operandi_tritanopia.toml @@ -2,7 +2,7 @@ # modus_operandi.toml variant # # This variant is optimized for users with blue-yellow color deficiency (tritanopia) -# Version 4.4.0 +# Version 4.6.0 inherits = "modus_operandi" diff --git a/runtime/themes/modus_vivendi.toml b/runtime/themes/modus_vivendi.toml index 952683ee7..00c55e3b0 100644 --- a/runtime/themes/modus_vivendi.toml +++ b/runtime/themes/modus_vivendi.toml @@ -1,7 +1,7 @@ # Author: Matous Dzivjak # Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou # Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-theme.el -# Version 4.4.0 +# Version 4.6.0 # Syntax highlighting # ------------------- @@ -124,7 +124,7 @@ bg-inactive = "#303030" # Common accent foregrounds red = "#ff5f59" red-warmer = "#ff6b55" -red-cooler = "#ff7f9f" +red-cooler = "#ff7f86" red-faint = "#ff9580" red-intense = "#ff5f5f" green = "#44bc44" diff --git a/runtime/themes/modus_vivendi_deuteranopia.toml b/runtime/themes/modus_vivendi_deuteranopia.toml index 294196f31..a787359e0 100644 --- a/runtime/themes/modus_vivendi_deuteranopia.toml +++ b/runtime/themes/modus_vivendi_deuteranopia.toml @@ -1,7 +1,7 @@ # Author: Matous Dzivjak # Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou # Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-deuteranopia-theme.el -# Version 4.3.0 +# Version 4.6.0 inherits = "modus_vivendi" @@ -37,7 +37,7 @@ border = "#646464" # Common accent foregrounds red = "#ff5f59" red-warmer = "#ff6b55" -red-cooler = "#ff7f9f" +red-cooler = "#ff7f86" red-faint = "#ff9580" red-intense = "#ff5f5f" green = "#44bc44" diff --git a/runtime/themes/modus_vivendi_tinted.toml b/runtime/themes/modus_vivendi_tinted.toml index 2f9e2bb19..c7f9f76f3 100644 --- a/runtime/themes/modus_vivendi_tinted.toml +++ b/runtime/themes/modus_vivendi_tinted.toml @@ -1,7 +1,7 @@ # Author: Matous Dzivjak # Adapted from: https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou # Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-tinted-theme.el -# Version 4.4.0 +# Version 4.6.0 inherits = "modus_vivendi" @@ -23,7 +23,7 @@ border = "#61647a" # Common accent foregrounds red = "#ff5f59" red-warmer = "#ff6b55" -red-cooler = "#ff7f9f" +red-cooler = "#ff7f86" red-faint = "#ff9f80" red-intense = "#ff5f5f" green = "#44bc44" diff --git a/runtime/themes/modus_vivendi_tritanopia.toml b/runtime/themes/modus_vivendi_tritanopia.toml index 7d8569d23..89cbee75e 100644 --- a/runtime/themes/modus_vivendi_tritanopia.toml +++ b/runtime/themes/modus_vivendi_tritanopia.toml @@ -1,7 +1,7 @@ # Author: Matous Dzivjak # Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou # Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-tritanopia-theme.el -# Version 4.3.0 +# Version 4.6.0 inherits = "modus_vivendi" @@ -51,7 +51,7 @@ border = "#646464" # Common accent foregrounds red = "#ff5f59" red-warmer = "#ff6740" -red-cooler = "#ff6f9f" +red-cooler = "#ff7f86" red-faint = "#ff9070" red-intense = "#ff5f5f" green = "#44bc44" diff --git a/runtime/themes/monokai.toml b/runtime/themes/monokai.toml index 22e6d0639..dfa7040ce 100644 --- a/runtime/themes/monokai.toml +++ b/runtime/themes/monokai.toml @@ -1,5 +1,7 @@ # Author: Shafkath Shuhan +"tag" = { fg = "tag" } + "namespace" = { fg = "type" } "module" = { fg = "type" } @@ -116,3 +118,4 @@ cursor = "#a6a6a6" inactive_cursor = "#878b91" widget = "#1e1f1c" selection = "#414339" +tag = "#F92672" diff --git a/runtime/themes/onedarker.toml b/runtime/themes/onedarker.toml index ffa3ae2dc..221b394b0 100644 --- a/runtime/themes/onedarker.toml +++ b/runtime/themes/onedarker.toml @@ -74,9 +74,9 @@ "ui.statusline" = { fg = "white", bg = "light-black" } "ui.statusline.inactive" = { fg = "light-gray", bg = "light-black" } -"ui.statusline.normal" = { fg = "light-black", bg = "purple" } -"ui.statusline.insert" = { fg = "light-black", bg = "green" } -"ui.statusline.select" = { fg = "light-black", bg = "cyan" } +"ui.statusline.normal" = { fg = "light-black", bg = "purple", modifiers = ["bold"] } +"ui.statusline.insert" = { fg = "light-black", bg = "green", modifiers = ["bold"] } +"ui.statusline.select" = { fg = "light-black", bg = "cyan", modifiers = ["bold"] } "ui.bufferline" = { fg = "light-gray", bg = "light-black" } "ui.bufferline.active" = { fg = "light-black", bg = "blue", underline = { color = "light-black", style = "line" } } diff --git a/runtime/themes/seoul256-dark-hard.toml b/runtime/themes/seoul256-dark-hard.toml new file mode 100644 index 000000000..fa918d29a --- /dev/null +++ b/runtime/themes/seoul256-dark-hard.toml @@ -0,0 +1,16 @@ +# Seoul256 Dark Hard +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +inherits = "seoul256-dark" + +"ui.background" = { bg = "gray1" } +"ui.gutter" = { bg = "gray2" } +"ui.cursorline.primary" = { bg = "gray" } +"ui.gutter.selected" = { bg = "gray" } +"ui.linenr.selected" = { bg = "gray", fg = "magenta", modifiers = ["bold"] } +"ui.virtual.inlay-hint" = { fg = "gray4", modifiers = ["bold"] } + +"ui.help" = { bg = "gray" } +"ui.popup" = { bg = "gray" } +"ui.menu" = { bg = "gray" } diff --git a/runtime/themes/seoul256-dark-soft.toml b/runtime/themes/seoul256-dark-soft.toml new file mode 100644 index 000000000..548d0c182 --- /dev/null +++ b/runtime/themes/seoul256-dark-soft.toml @@ -0,0 +1,15 @@ +# Seoul256 Dark Soft +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +inherits = "seoul256-dark" + +"ui.background" = { bg = "gray8" } +"ui.gutter" = { bg = "gray6" } +"ui.cursorline.primary" = { bg = "gray5" } +"ui.gutter.selected" = { bg = "gray5" } +"ui.linenr.selected" = { bg = "gray5", fg = "magenta", modifiers = ["bold"] } + +"ui.help" = { bg = "gray5" } +"ui.popup" = { bg = "gray5" } +"ui.menu" = { bg = "gray5" } diff --git a/runtime/themes/seoul256-dark.toml b/runtime/themes/seoul256-dark.toml new file mode 100644 index 000000000..df9d43df0 --- /dev/null +++ b/runtime/themes/seoul256-dark.toml @@ -0,0 +1,161 @@ +# Seoul256 Dark +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +# Syntax highlighting configuration +"attribute" = { fg = "yellow" } +"comment" = { fg = "green1" } +"constant" = { fg = "blue5" } +"constant.numeric" = { fg = "yellow1" } +"constant.builtin.boolean" = { fg = "purple" } +"constant.character.escape" = { fg = "salmon" } +"constructor" = { fg = "yellow" } +"function" = { fg = "yellow2" } +"function.builtin" = { fg = "blue1" } +"function.method" = { fg = "salmon" } +"function.macro" = { fg = "yellow2" } +"keyword" = { fg = "mauve" } +"label" = { fg = "magenta" } +"namespace" = { fg = "cyan" } +"operator" = { fg = "yellow3" } +"punctuation" = { fg = "brown" } +"special" = { fg = "yellow2" } +"string" = { fg = "blue" } +"type" = { fg = "yellow" } +"type.builtin" = { fg = "salmon" } +"variable" = { fg = "white" } +"variable.builtin" = { fg = "salmon" } +"variable.parameter" = { fg = "white" } +"variable.other.member" = { fg = "white" } + +"markup.heading" = { fg = "salmon2", modifiers = ["bold"] } +"markup.raw.inline" = { fg = "green" } +"markup.bold" = { fg = "yellow1", modifiers = ["bold"] } +"markup.italic" = { fg = "magenta1", modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } +"markup.list" = { fg = "salmon" } +"markup.quote" = { fg = "yellow" } +"markup.link.url" = { fg = "cyan", modifiers = ["underlined"] } +"markup.link.text" = { fg = "salmon2" } + +"diff.plus" = { fg = "green3" } +"diff.delta" = { fg = "blue1" } +"diff.minus" = { fg = "magenta3" } + +"diagnostic.info".underline = { color = "cyan", style = "curl" } +"diagnostic.hint".underline = { color = "green1", style = "curl" } +"diagnostic.warning".underline = { color = "yellow1", style = "curl" } +"diagnostic.error".underline = { color = "red", style = "curl" } +"diagnostic.unnecessary" = { modifiers = ["dim"] } +"diagnostic.deprecated" = { modifiers = ["crossed_out"] } +"info" = { fg = "blue2", modifiers = ["bold"] } +"hint" = { fg = "blue3", modifiers = ["bold"] } +"warning" = { fg = "yellow", modifiers = ["bold"] } +"error" = { fg = "red", modifiers = ["bold"] } + +"ui.background" = { bg = "gray4" } +"ui.gutter" = { bg = "gray5" } +"ui.gutter.selected" = { bg = "gray3" } +"ui.virtual" = { fg = "gray6" } +"ui.virtual.indent-guide" = { fg = "gray6" } +"ui.virtual.whitespace" = { fg = "gray6" } +"ui.virtual.ruler" = { bg = "gray5" } +"ui.virtual.inlay-hint" = { fg = "gray9", modifiers = ["bold"] } +"ui.virtual.jump-label" = { fg = "red", modifiers = ["bold"] } + +"ui.cursor" = { fg = "white", modifiers = ["reversed"] } +"ui.cursor.primary" = { fg = "white", modifiers = ["reversed"] } +"ui.cursor.match" = { bg = "gray4", modifiers = ["underlined"] } +"ui.cursor.insert" = { fg = "blue1" } + +"ui.selection" = { bg = "magenta2" } +"ui.selection.primary" = { bg = "blue4" } +"ui.cursorline.primary" = { bg = "gray3" } + +"ui.highlight" = { bg = "gray5" } +"ui.highlight.frameline" = { bg = "red" } + +"ui.linenr" = { fg = "yellow4" } +"ui.linenr.selected" = { bg = "gray3", fg = "magenta", modifiers = ["bold"] } + +"ui.statusline" = { fg = "magenta2", bg = "yellow2" } +"ui.statusline.inactive" = { fg = "gray6", bg = "black" } +"ui.statusline.normal" = { fg = "black", bg = "blue2" } +"ui.statusline.insert" = { fg = "black", bg = "green2" } +"ui.statusline.select" = { fg = "black", bg = "magenta" } + +"ui.text" = { fg = "white" } +"ui.text.focus" = { fg = "white", bg = "magenta2", modifiers = ["bold"] } + +"ui.help" = { fg = "white", bg = "gray3" } +"ui.popup" = { fg = "white", bg = "gray3" } +"ui.window" = { fg = "white" } +"ui.menu" = { fg = "white", bg = "gray3" } +"ui.menu.selected" = { fg = "white", bg = "magenta2" } +"ui.menu.scroll" = { fg = "gray7", bg = "gray6" } + +"ui.debug" = { fg = "red" } + +# Colors (Seoul256) +[palette] +black = '#000000' # Black +black1 = '#14161B' +red = '#d70000' # Red +green = '#afd75f' # Greenish Yellow +green1 = '#5f875f' # Greenish Gray +green2 = '#5f8700' # Green +green3 = '#87af87' +green4 = '#5f5f00' +yellow = '#d8af5f' # Yellow +yellow1 = '#ffd787' # Bright Yellow +yellow2 = '#d7d7af' # Yellowish +yellow3 = '#d7d787' # Yellow Dim +yellow4 = '#87875f' # Olive +yellow5 = '#6B5300' +blue = '#87afaf' # Light Blue +blue1 = '#5f87d7' # Bright Blue +blue2 = '#5f5f87' # Blue +blue3 = '#a6dbff' # Lightest Blue +blue4 = '#005f5f' # Blue Green +blue5 = '#5fafaf' # Dark Blue +blue6 = '#008787' +magenta = '#af5f5f' # Magenta +magenta1 = '#af5f87' # Soft Magenta +magenta2 = '#875f5f' # Dark Magenta +magenta3 = '#d7005f' # Darker Magenta +cyan = '#87d7d7' # Bright Cyan +cyan1 = '#afd7d7' +white = '#d0d0d0' # White +white1 = '#dadada' # White +purple = '#8787af' # Purple +brown = '#af875f' # Brownish +brown1 = '#875f00' # Brownish +orange = '#ff5f00' # Orange +salmon = '#ffaf87' # Salmon +salmon1 = '#d78787' # Salmon Bright +salmon2 = '#d7afaf' # Salmon Light +salmon3 = '#d7875f' # Yellowish +mauve = '#d75f87' # Mauve + +gray = '#121212' # Very Dark Gray +gray1 = '#1c1c1c' # Darker Gray +gray2 = '#262626' # Dark Gray +gray3 = '#303030' # Dark Medium Gray +gray4 = '#3a3a3a' # Medium Gray +gray5 = '#444444' # Lighter Medium Gray +gray6 = '#585858' # Light Gray +gray7 = '#626262' # Lighter Gray +gray8 = '#4e4e4e' # Even Lighter Gray +gray9 = '#5f5f5f' +gray10 = '#c6c6c6' +gray11 = '#eeeeee' +gray12 = '#e4e4e4' +gray13 = '#bcbcbc' + +# 233 = '#121212' +# 234 = '#1c1c1c' +# 235 = '#262626' +# 236 = '#303030' +# 237 = '#3a3a3a' # Default +# 238 = '#444444' +# 239 = '#4e4e4e' diff --git a/runtime/themes/seoul256-light-hard.toml b/runtime/themes/seoul256-light-hard.toml new file mode 100644 index 000000000..c1f92fac1 --- /dev/null +++ b/runtime/themes/seoul256-light-hard.toml @@ -0,0 +1,16 @@ +# Seoul256 Light Hard +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +inherits = "seoul256-light" + +"ui.background" = { bg = "gray11" } +"ui.cursor.match" = { bg = "gray10", modifiers = ["underlined"] } +"ui.gutter" = { bg = "white1" } +"ui.cursorline.primary" = { bg = "gray12" } +"ui.gutter.selected" = { bg = "gray12" } +"ui.linenr.selected" = { bg = "gray12", fg = "magenta", modifiers = ["bold"] } + +"ui.help" = { fg = "black1", bg = "gray12" } +"ui.popup" = { fg = "black1", bg = "gray12" } +"ui.menu" = { fg = "black1", bg = "gray12" } diff --git a/runtime/themes/seoul256-light-soft.toml b/runtime/themes/seoul256-light-soft.toml new file mode 100644 index 000000000..0a25bb696 --- /dev/null +++ b/runtime/themes/seoul256-light-soft.toml @@ -0,0 +1,16 @@ +# Seoul256 Light Soft +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +inherits = "seoul256-light" + +"ui.background" = { bg = "white" } +"ui.cursor.match" = { bg = "gray13", modifiers = ["underlined"] } +"ui.gutter" = { bg = "gray13" } +"ui.cursorline.primary" = { bg = "gray10" } +"ui.gutter.selected" = { bg = "gray10" } +"ui.linenr.selected" = { bg = "gray10", fg = "magenta", modifiers = ["bold"] } + +"ui.help" = { fg = "black1", bg = "gray10" } +"ui.popup" = { fg = "black1", bg = "gray10" } +"ui.menu" = { fg = "black1", bg = "gray10" } diff --git a/runtime/themes/seoul256-light.toml b/runtime/themes/seoul256-light.toml new file mode 100644 index 000000000..4f45a9d02 --- /dev/null +++ b/runtime/themes/seoul256-light.toml @@ -0,0 +1,51 @@ +# Seoul256 Light +# Author : EricHenry +# Original Creator: https://github.com/junegunn/seoul256.vim + +inherits = "seoul256-dark" + +"constructor" = { fg = "brown1" } +"constant.numeric" = { fg = "magenta2" } +"constant.builtin.boolean" = { fg = "mauve" } +"constant.character.escape" = { fg = "salmon3" } +"function" = { fg = "green4" } +"function.builtin" = { fg = "blue1" } +"function.method" = { fg = "salmon" } +"function.macro" = { fg = "green4" } +"namespace" = { fg = "blue4" } +"operator" = { fg = "brown1" } +"punctuation" = { fg = "brown1" } +"special" = { fg = "green4" } +"string" = { fg = "blue6" } +"type" = { fg = "brown1" } +"type.builtin" = { fg = "salmon3" } +"variable" = { fg = "black1" } +"variable.builtin" = { fg = "salmon3" } +"variable.parameter" = { fg = "black1" } +"variable.other.member" = { fg = "black1" } + +"diagnostic.info".underline = { color = "green1", style = "curl" } +"info" = { fg = "green1", modifiers = ["bold"] } +"hint" = { fg = "blue", modifiers = ["bold"] } +"warning" = { fg = "yellow5", modifiers = ["bold"] } + +"ui.background" = { bg = "white1" } +"ui.cursor" = { fg = "gray4", modifiers = ["reversed"] } +"ui.cursor.primary" = { fg = "gray4", modifiers = ["reversed"] } +"ui.cursor.match" = { bg = "gray13", modifiers = ["underlined"] } +"ui.cursor.insert" = { fg = "blue1" } +"ui.cursorline.primary" = { bg = "white" } +"ui.gutter" = { bg = "gray10" } +"ui.gutter.selected" = { bg = "white" } +"ui.linenr.selected" = { bg = "white", fg = "magenta", modifiers = ["bold"] } +"ui.virtual.inlay-hint" = { fg = "gray6", modifiers = ["bold"] } + +"ui.selection" = { bg = "yellow2" } +"ui.selection.primary" = { bg = "cyan1" } + +"ui.text" = { fg = "black1" } + +"ui.help" = { fg = "black1", bg = "white" } +"ui.popup" = { fg = "black1", bg = "white" } +"ui.menu" = { fg = "black1", bg = "white" } + diff --git a/runtime/themes/serika-dark.toml b/runtime/themes/serika-dark.toml index eb8d6c839..10ceacd15 100644 --- a/runtime/themes/serika-dark.toml +++ b/runtime/themes/serika-dark.toml @@ -53,6 +53,7 @@ "ui.virtual.whitespace" = "bg2" "ui.virtual.ruler" = { bg = "grey2" } "ui.virtual.inlay-hint" = { fg = "grey2", modifiers = ["italic"] } +"ui.virtual.jump-label" = { fg = "nasty-red", modifiers = ["bold"] } "hint" = "blue" "info" = "aqua" diff --git a/runtime/themes/spacebones_light.toml b/runtime/themes/spacebones_light.toml index 7870f67ca..1d744019b 100644 --- a/runtime/themes/spacebones_light.toml +++ b/runtime/themes/spacebones_light.toml @@ -63,7 +63,7 @@ "ui.window" = { bg = "bg1" } "ui.help" = { bg = "bg1", fg = "fg1" } "ui.text" = { fg = "fg1" } -"ui.text.focus" = { fg = "fg1" } +"ui.text.focus" = { fg = "fg1", modifiers = ["bold"] } "ui.selection" = { bg = "hl2" } "ui.selection.primary" = { bg = "hl1" } "ui.cursor.primary" = { modifiers = ["reversed"] } diff --git a/runtime/themes/sunset.toml b/runtime/themes/sunset.toml new file mode 100644 index 000000000..2683f0a8b --- /dev/null +++ b/runtime/themes/sunset.toml @@ -0,0 +1,159 @@ +# Sunset +# Author : Egor Afanasin +# Repo: https://github.com/pithecantrope/sunset + +# Syntax highlighting +# ---------------------------------------------------------------- +attribute = "rose" + +type = "rose" +"type.builtin" = { fg = "rose", modifiers = ["italic"] } + +constructor = "wood" + +constant = "fire" +"constant.builtin" = { fg = "fire", modifiers = ["italic"] } +"constant.character" = "wood" +"constant.character.escape" = "pink" +"constant.numeric" = "wood" + +string = "grass" +"string.regexp" = "pink" +"string.special" = "rose" +"string.special.symbol" = "fire" + +comment = { fg = "cmnt", modifiers = ["italic"] } +"comment.block.documentation" = "grass" + +variable = "text" +"variable.builtin" = { fg = "sky", modifiers = ["italic"] } +# TODO: variable.parameter +"variable.other.member" = "mud" + +label = "sky" + +punctuation = "cmnt" +"punctuation.special" = "wine" + +keyword = "sun" +"keyword.control.return" = { fg = "sun", modifiers = ["italic"] } +"keyword.control.exception" = { fg = "sun", modifiers = ["italic"] } +"keyword.directive" = "sky" + +operator = "wine" + +function = "peach" +"function.builtin" = { fg = "peach", modifiers = ["italic"] } +"function.macro" = "pink" + +tag = "peach" + +namespace = { fg = "pink", modifiers = ["italic"] } + +special = "sky" + +# Editor interface +# ---------------------------------------------------------------- +"markup.heading.marker" = "sun" +"markup.heading.1" = "attn" +"markup.heading.2" = "fire" +"markup.heading.3" = "rose" +"markup.heading.4" = "peach" +"markup.heading.5" = "wine" +"markup.heading.6" = "grass" + +"markup.list" = "wood" + +"markup.bold" = { modifiers = ["bold"] } +"markup.italic" = { modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } + +"markup.link.url" = { fg = "sky", underline.style = "line" } +"markup.link.label" = { fg = "sky", modifiers = ["italic"] } +"markup.link.text" = "mud" + +"markup.quote" = "grass" + +"markup.raw" = "pink" + +"diff.plus" = "grass" +"diff.minus" = "attn" +"diff.delta" = "sky" + +# User interface +# ---------------------------------------------------------------- +"ui.background" = { fg = "text", bg = "base" } + +"ui.cursor" = { modifiers = ["reversed"] } +"ui.cursor.match" = { fg = "attn", modifiers = ["bold"] } + +# TODO: ui.debug + +"ui.linenr" = "block" +"ui.linenr.selected" = "cmnt" + +"ui.statusline" = { bg = "block" } +"ui.statusline.inactive" = { fg = "cmnt" } +"ui.statusline.normal" = { fg = "block", bg = "sun", modifiers = ["bold"] } +"ui.statusline.insert" = { fg = "block", bg = "grass", modifiers = ["bold"] } +"ui.statusline.select" = { fg = "block", bg = "wine", modifiers = ["bold"] } + +"ui.bufferline" = { fg = "cmnt", bg = "block" } +"ui.bufferline.active" = "sun" + +"ui.popup" = { fg = "text", bg = "base" } +"ui.popup.info" = { fg = "text", bg = "block" } + +"ui.window" = { fg = "block", modifiers = ["bold"] } + +"ui.help" = { fg = "text", bg = "block" } + +"ui.text" = { fg = "text", bg = "base" } +"ui.text.focus" = "sun" +"ui.text.inactive" = { fg = "cmnt", modifiers = ["italic"] } +"ui.text.info" = { bg = "block" } + +"ui.virtual" = { fg = "block" } +"ui.virtual.ruler" = { bg = "block" } +"ui.virtual.indent-guide" = "sel" +"ui.virtual.jump-label" = { fg = "attn", modifiers = ["bold"] } + +"ui.menu" = { fg = "text", bg = "base" } +"ui.menu.selected" = { bg = "sel" } +"ui.menu.scroll" = "sel" + +"ui.selection" = { bg = "sel" } + +"ui.highlight" = { bg = "sel" } + +error = "attn" +warning = "fire" +info = "pink" +hint = "sky" + +diagnostic = { underline.style = "line" } + +[palette] +# Reddish +fire = "#EE7711" +rose = "#EE7777" +peach = "#EEBB77" +pink = "#EEAAAA" +wood = "#997755" + +# Greenish +grass = "#66CC33" +mud = "#BBCC77" +sun = "#EEEE11" + +# Bluish +sky = "#77AAAA" +wine = "#775599" + +# Ui +base = "#111111" +block = "#222222" +sel = "#333333" +cmnt = "#777777" +text = "#EEEEEE" +attn = "#EE1111" diff --git a/runtime/themes/yo.toml b/runtime/themes/yo.toml new file mode 100644 index 000000000..55c805204 --- /dev/null +++ b/runtime/themes/yo.toml @@ -0,0 +1,125 @@ +# Author: Michael McClintock +# License: MIT + +# Yo - Themes for Helix inspired by Zenbones & Alabaster with Radix Colors. +# https://github.com/mrmcc3/yo-theme-helix + +# background/text +"ui.background" = { fg = "p11", bg = "p2" } +"ui.background.separator" = { fg = "p7" } +"ui.text" = { fg = "p11" } +"ui.text.focus" = { fg = "p12", modifiers = ["bold"] } + +# popups/menus +"ui.window" = { fg = "p7" } +"ui.popup" = { fg = "p12", bg = "p4" } +"ui.popup.info" = { fg = "p12", bg = "p2" } +"ui.text.info" = { fg = "p12", bg = "p2" } +"ui.help" = { fg = "p12", bg = "p2" } +"ui.menu" = { fg = "p11", bg = "p4" } +"ui.menu.selected" = { fg = "p12", modifiers = ["bold"] } +"ui.menu.scroll" = { fg = "p8", bg = "p4" } +"ui.picker.header.column" = { underline.style = "line" } + +# cursor/selection +"ui.cursor" = { fg = "p2", bg = "p11" } +"ui.cursor.insert" = { fg = "p2", bg = "keyword" } +"ui.cursor.select" = { fg = "p2", bg = "p12" } +"ui.cursor.match" = { fg = "p12", modifiers = ["bold"] } +"ui.cursor.primary" = { fg = "p2", bg = "p11", modifiers = ["bold"] } +"ui.cursor.primary.insert" = { fg = "p2", bg = "keyword", modifiers = ["bold"] } +"ui.cursor.primary.select" = { fg = "p2", bg = "p12", modifiers = ["bold"] } +"ui.selection" = { bg = "p4" } +"ui.selection.primary" = { bg = "p5" } +"ui.cursorline.primary" = { bg = "p3" } +"ui.cursorcolumn.primary" = { bg = "p3" } + +# line numbers / diff +"ui.linenr" = { fg = "p7" } +"ui.linenr.selected" = { fg = "p11" } +diff = { fg = "p8" } + +# bufferline/statusline +"ui.bufferline" = { fg = "p11", bg = "p4" } +"ui.bufferline.active" = { fg = "p2", bg = "p11" } +"ui.statusline" = { fg = "p11", bg = "p4" } +"ui.statusline.inactive" = { fg = "p11", bg = "p2" } +"ui.statusline.normal" = { fg = "p2", bg = "p11" } +"ui.statusline.insert" = { fg = "p2", bg = "keyword" } +"ui.statusline.select" = { fg = "p2", bg = "p12" } +"ui.statusline.separator" = { fg = "p7" } + +# virtual +"ui.virtual" = { fg = "p6" } +"ui.virtual.ruler" = { bg = "p3" } +"ui.virtual.inlay-hint" = { fg = "p7", underline.style = "dotted" } +"ui.virtual.jump-label" = { fg = "p12", modifiers = [ + "bold", +], underline = { style = "curl", color = "info" } } + +# diagnostics +error = { fg = "error", modifiers = ["bold"] } +warning = { fg = "warning", modifiers = ["bold"] } +info = { fg = "info", modifiers = ["bold"] } +hint = { fg = "info", modifiers = ["bold"] } +"diagnostic.error" = { fg = "error", modifiers = ["bold"] } +"diagnostic.warning" = { fg = "warning", modifiers = ["bold"] } +"diagnostic.info" = { fg = "info", modifiers = ["bold"] } +"diagnostic.hint" = { fg = "info", modifiers = ["bold"] } +# "diagnostic.unnecessary" = {} +# "diagnostic.deprecated" = {} + +# code +comment = { fg = "info" } +keyword = { fg = "keyword" } +operator = { fg = "keyword" } +string = { fg = "string" } +constant = { fg = "constant" } +"string.special.symbol" = { fg = "constant" } +variable = { fg = "p10" } +namespace = { fg = "p10" } +punctuation = { fg = "p9" } +"punctuation.delimiter" = { fg = "p8" } +function = { fg = "p11" } +attribute = { fg = "p10" } +tag = { fg = "keyword" } +label = { fg = "p12" } +constructor = { fg = "p12" } +type = { fg = "p12" } + +# markup +"markup.bold" = { modifiers = ["bold"] } +"markup.italic" = { modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } +"markup.heading" = { fg = "p12", modifiers = ["bold"] } +"markup.heading.marker" = { fg = "p8" } +"markup.list" = { fg = "p8" } +"markup.link.url" = { underline.style = "line" } +"markup.link.label" = { underline.style = "dotted" } +# "markup.link.text" = {} +"markup.quote" = { fg = "p10" } +# "markup.raw" = {} + +[palette] # https://www.radix-ui.com/colors + +# grayDark +p1 = "#111111" +p2 = "#191919" +p3 = "#222222" +p4 = "#2a2a2a" +p5 = "#313131" +p6 = "#3a3a3a" +p7 = "#484848" +p8 = "#606060" +p9 = "#6e6e6e" +p10 = "#7b7b7b" +p11 = "#b4b4b4" +p12 = "#eeeeee" + +error = "#ec5d5e" # redDark-10 +warning = "#ff801f" # orangeDark-10 +info = "#3b9eff" # blueDark-10 + +string = "#33b074" # greenDark-10 +constant = "#9a5cd0" # purpleDark-10 +keyword = "#ae8c7e" # bronzeDark-10 diff --git a/runtime/themes/yo_berry.toml b/runtime/themes/yo_berry.toml new file mode 100644 index 000000000..1aaac1a92 --- /dev/null +++ b/runtime/themes/yo_berry.toml @@ -0,0 +1,31 @@ +# Author: Michael McClintock +# License: MIT + +# Yo - Themes for Helix inspired by Zenbones & Alabaster with Radix Colors. +# https://github.com/mrmcc3/yo-theme-helix + +inherits = "yo" + +[palette] + +# mauveDark +p1 = "#121113" +p2 = "#1a191b" +p3 = "#232225" +p4 = "#2b292d" +p5 = "#323035" +p6 = "#3c393f" +p7 = "#49474e" +p8 = "#625f69" +p9 = "#6f6d78" +p10 = "#7c7a85" +p11 = "#b5b2bc" +p12 = "#eeeef0" + +error = "#ee518a" # crimsonDark-10 +warning = "#ffff57" # yellowDark-10 +info = "#3b9eff" # blueDark-10 + +string = "#0eb39e" # teal-10 +constant = "#b658c4" # plum-10 +keyword = "#9eb1ff" # indigo-11 diff --git a/runtime/themes/yo_light.toml b/runtime/themes/yo_light.toml new file mode 100644 index 000000000..15c149184 --- /dev/null +++ b/runtime/themes/yo_light.toml @@ -0,0 +1,34 @@ +# Author: Michael McClintock +# License: MIT + +# Yo - Themes for Helix inspired by Zenbones & Alabaster with Radix Colors. +# https://github.com/mrmcc3/yo-theme-helix + +inherits = "yo" + +"ui.virtual.inlay-hint" = { fg = "p8", underline.style = "dotted" } +"markup.quote" = { fg = "p9" } + +[palette] + +# gray +p1 = "#fcfcfc" +p2 = "#f9f9f9" +p3 = "#f0f0f0" +p4 = "#e8e8e8" +p5 = "#e0e0e0" +p6 = "#d9d9d9" +p7 = "#cecece" +p8 = "#bbbbbb" +p9 = "#8d8d8d" +p10 = "#838383" +p11 = "#646464" +p12 = "#202020" + +error = "#dc3e42" # red-10 +warning = "#ef5f00" # orange-10 +info = "#0588f0" # blue-10 + +string = "#2b9a66" # green-10 +constant = "#8347b9" # purple-10 +keyword = "#957468" # bronze-10 diff --git a/runtime/tutor b/runtime/tutor index d24f83d5e..194a01f0d 100644 --- a/runtime/tutor +++ b/runtime/tutor @@ -1223,7 +1223,7 @@ letters! that is not good grammar. you can fix this. to the matching ). You can do the same on the line below: for example move to ], and press mm to jump to [ . - --> you can (jump between matching parenthesis) + --> you can (jump between matching parentheses) --> or between matching [ square brackets ] --> now { you know the drill: this works with brackets too } @@ -1238,19 +1238,19 @@ letters! that is not good grammar. you can fix this. pair of brackets or other delimiters. In the lines below: - move to the --> line, put your cursor in normal mode at any - location between the parenthesis, for example at 'x', and press - mi( or mi) to select the whole content inside the parenthesis - (parenthesis excluded). As usual, you can then do anything you want + location between the parentheses, for example at 'x', and press + mi( or mi) to select the whole content inside the parentheses + (parentheses excluded). As usual, you can then do anything you want with the selection (for example, press c to change it) - --> outside and (inside x parenthesis) - and outside again + --> outside and (inside x parentheses) - and outside again Test below that you can do the same with [], or {}, or with nested combinations of these (this will act on the immediately surrounding matching pair). This also works with "" and similar --> test [ with square brackets ] ! - --> try ( with nested [ pairs of ( parenthesis) and "brackets" ]) + --> try ( with nested [ pairs of ( parentheses) and "brackets" ]) ================================================================= = 12.3 USING MATCH MODE SELECT AROUND = @@ -1284,7 +1284,7 @@ letters! that is not good grammar. you can fix this. move in normal mode the cursor to the start of select, then enter selection mode with v , then select the 4 next words with 4e ), * ii) press ms( or ms) to surround the selection with a pair of - parenthesis. + parentheses. --> so, select all of this, and surround it with () @@ -1304,9 +1304,9 @@ letters! that is not good grammar. you can fix this. command. On the line below, move the cursor anywhere within the pair of (), for example to the 'x', then from there, in normal mode, press md( or md) to delete the surrounding - pair of parenthesis. + pair of parentheses. - --> delete (the x pair of parenthesis) from within! + --> delete (the x pair of parentheses) from within! You can naturally delete other kinds of surroundings: