From 7961355ba1c0cd521372496c507a31a51b41ddf2 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Wed, 24 Nov 2021 12:17:41 +0530 Subject: Change cursor shape on mode change Fixes #323. Due to terminal limitations we can only change the shape of the primary cursor. --- book/src/configuration.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'book/src') diff --git a/book/src/configuration.md b/book/src/configuration.md index 2ed48d51..a40a8959 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -5,9 +5,26 @@ To override global configuration parameters, create a `config.toml` file located * Linux and Mac: `~/.config/helix/config.toml` * Windows: `%AppData%\helix\config.toml` +Example config: + +```toml +theme = "onedark" + +[editor] +line-number = "relative" +mouse = false + +[editor.cursor-shape] +normal = "underline" +insert = "block" + +[editor.file-picker] +hidden = false +``` + ## Editor -`[editor]` section of the config. +### `[editor]` Section | Key | Description | Default | |--|--|---------| @@ -24,7 +41,28 @@ To override global configuration parameters, create a `config.toml` file located | `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` | | `auto-info` | Whether to display infoboxes | `true` | -`[editor.filepicker]` section of the config. Sets options for file picker and global search. All but the last key listed in the default file-picker configuration below are IgnoreOptions: whether hidden files and files listed within ignore files are ignored by (not visible in) the helix file picker and global search. There is also one other key, `max-depth` available, which is not defined by default. +### `[editor.cursor-shape]` Section + +Defines the shape of cursor in each mode. Note that due to limitations +of the terminal environment, only the primary cursor can change shape. + +| Key | Description | Default | +| --- | ----------- | -------- | +| `normal` | Cursor shape in [normal mode][normal mode] | `block` | +| `insert` | Cursor shape in [insert mode][insert mode] | `bar` | +| `select` | Cursor shape in [select mode][select mode] | `underline` | + +[normal mode]: ./keymap.md#normal-mode +[insert mode]: ./keymap.md#insert-mode +[select mode]: ./keymap.md#select--extend-mode + +### `[editor.filepicker]` Section + +Sets options for file picker and global search. All but the last key listed in +the default file-picker configuration below are IgnoreOptions: whether hidden +files and files listed within ignore files are ignored by (not visible in) the +helix file picker and global search. There is also one other key, `max-depth` +available, which is not defined by default. | Key | Description | Default | |--|--|---------| -- cgit v1.2.3-70-g09d2 From 058796c18e786309322731ff68b15a0f3901b60b Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 29 Nov 2021 11:09:04 +0530 Subject: Change default cursors to block for all modes --- book/src/configuration.md | 15 ++++++++------- helix-view/src/editor.rs | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'book/src') diff --git a/book/src/configuration.md b/book/src/configuration.md index a40a8959..2998bcdc 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -15,8 +15,9 @@ line-number = "relative" mouse = false [editor.cursor-shape] -normal = "underline" -insert = "block" +insert = "bar" +normal = "block" +select = "underline" [editor.file-picker] hidden = false @@ -46,11 +47,11 @@ hidden = false Defines the shape of cursor in each mode. Note that due to limitations of the terminal environment, only the primary cursor can change shape. -| Key | Description | Default | -| --- | ----------- | -------- | -| `normal` | Cursor shape in [normal mode][normal mode] | `block` | -| `insert` | Cursor shape in [insert mode][insert mode] | `bar` | -| `select` | Cursor shape in [select mode][select mode] | `underline` | +| Key | Description | Default | +| --- | ----------- | ------- | +| `normal` | Cursor shape in [normal mode][normal mode] | `block` | +| `insert` | Cursor shape in [insert mode][insert mode] | `block` | +| `select` | Cursor shape in [select mode][select mode] | `block` | [normal mode]: ./keymap.md#normal-mode [insert mode]: ./keymap.md#insert-mode diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 9c77f270..b558c183 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -122,9 +122,9 @@ impl std::ops::Deref for CursorShapeConfig { impl Default for CursorShapeConfig { fn default() -> Self { Self(hashmap!( - Mode::Insert => CursorKind::Bar, + Mode::Insert => CursorKind::Block, Mode::Normal => CursorKind::Block, - Mode::Select => CursorKind::Underline, + Mode::Select => CursorKind::Block, )) } } -- cgit v1.2.3-70-g09d2 From 3e15aead4adc5139417230d15b38112cdc4f7043 Mon Sep 17 00:00:00 2001 From: George Rodrigues Date: Tue, 30 Nov 2021 21:11:25 -0300 Subject: Fix typo on docs (#1201) --- book/src/guides/adding_languages.md | 2 +- helix-core/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'book/src') diff --git a/book/src/guides/adding_languages.md b/book/src/guides/adding_languages.md index 446eb479..9ad2c285 100644 --- a/book/src/guides/adding_languages.md +++ b/book/src/guides/adding_languages.md @@ -2,7 +2,7 @@ ## Submodules -To add a new langauge, you should first add a tree-sitter submodule. To do this, +To add a new language, you should first add a tree-sitter submodule. To do this, you can run the command ```sh git submodule add -f helix-syntax/languages/tree-sitter- diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs index de7e95c1..8ef41ef3 100644 --- a/helix-core/src/lib.rs +++ b/helix-core/src/lib.rs @@ -158,7 +158,7 @@ mod merge_toml_tests { "; let base: Value = toml::from_slice(include_bytes!("../../languages.toml")) - .expect("Couldn't parse built-in langauges config"); + .expect("Couldn't parse built-in languages config"); let user: Value = toml::from_str(USER).unwrap(); let merged = merge_toml_values(base, user); -- cgit v1.2.3-70-g09d2 From e2b428cc2d23965ab7a91809c5705ede0298107d Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Thu, 2 Dec 2021 12:46:57 +0800 Subject: Add last modified file (gm) (#1093) --- book/src/keymap.md | 3 ++- helix-term/src/commands.rs | 19 +++++++++++++++++-- helix-term/src/keymap.rs | 3 ++- helix-view/src/document.rs | 6 ++++++ helix-view/src/editor.rs | 14 ++++++++++++-- helix-view/src/view.rs | 6 ++++++ 6 files changed, 45 insertions(+), 6 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 865a700b..59353db9 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -165,13 +165,14 @@ Jumps to various locations. | `l` | Go to the end of the line | `goto_line_end` | | `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` | | `t` | Go to the top of the screen | `goto_window_top` | -| `m` | Go to the middle of the screen | `goto_window_middle` | +| `c` | Go to the middle of the screen | `goto_window_center` | | `b` | Go to the bottom of the screen | `goto_window_bottom` | | `d` | Go to definition (**LSP**) | `goto_definition` | | `y` | Go to type definition (**LSP**) | `goto_type_definition` | | `r` | Go to references (**LSP**) | `goto_reference` | | `i` | Go to implementation (**LSP**) | `goto_implementation` | | `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` | +| `m` | Go to the last modified/alternate file | `goto_last_modified_file` | | `n` | Go to next buffer | `goto_next_buffer` | | `p` | Go to previous buffer | `goto_previous_buffer` | | `.` | Go to last modification in current file | `goto_last_modification` | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 4a389429..a50b16f3 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -264,9 +264,10 @@ impl Command { goto_file_vsplit, "Goto files in the selection in vertical splits", goto_reference, "Goto references", goto_window_top, "Goto window top", - goto_window_middle, "Goto window middle", + goto_window_center, "Goto window center", goto_window_bottom, "Goto window bottom", goto_last_accessed_file, "Goto last accessed file", + goto_last_modified_file, "Goto last modified file", goto_last_modification, "Goto last modification", goto_line, "Goto line", goto_last_line, "Goto last line", @@ -763,7 +764,7 @@ fn goto_window_top(cx: &mut Context) { goto_window(cx, Align::Top) } -fn goto_window_middle(cx: &mut Context) { +fn goto_window_center(cx: &mut Context) { goto_window(cx, Align::Center) } @@ -3610,6 +3611,20 @@ fn goto_last_modification(cx: &mut Context) { } } +fn goto_last_modified_file(cx: &mut Context) { + let view = view!(cx.editor); + let alternate_file = view + .last_modified_docs + .into_iter() + .flatten() + .find(|&id| id != view.doc); + if let Some(alt) = alternate_file { + cx.editor.switch(alt, Action::Replace); + } else { + cx.editor.set_error("no last modified buffer".to_owned()) + } +} + fn select_mode(cx: &mut Context) { let (view, doc) = current!(cx.editor); let text = doc.text().slice(..); diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 06639dcd..73cb15f8 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -521,9 +521,10 @@ impl Default for Keymaps { "r" => goto_reference, "i" => goto_implementation, "t" => goto_window_top, - "m" => goto_window_middle, + "c" => goto_window_center, "b" => goto_window_bottom, "a" => goto_last_accessed_file, + "m" => goto_last_modified_file, "n" => goto_next_buffer, "p" => goto_previous_buffer, "." => goto_last_modification, diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 76b19a07..2cb33fe3 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -104,6 +104,7 @@ pub struct Document { last_saved_revision: usize, version: i32, // should be usize? + pub(crate) modified_since_accessed: bool, diagnostics: Vec, language_server: Option>, @@ -127,6 +128,7 @@ impl fmt::Debug for Document { // .field("history", &self.history) .field("last_saved_revision", &self.last_saved_revision) .field("version", &self.version) + .field("modified_since_accessed", &self.modified_since_accessed) .field("diagnostics", &self.diagnostics) // .field("language_server", &self.language_server) .finish() @@ -344,6 +346,7 @@ impl Document { history: Cell::new(History::default()), savepoint: None, last_saved_revision: 0, + modified_since_accessed: false, language_server: None, } } @@ -639,6 +642,9 @@ impl Document { selection.clone().ensure_invariants(self.text.slice(..)), ); } + + // set modified since accessed + self.modified_since_accessed = true; } if !transaction.changes().is_empty() { diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index d5913a51..9034d12c 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -369,7 +369,8 @@ impl Editor { .tree .traverse() .any(|(_, v)| v.doc == doc.id && v.id != view.id); - let view = view_mut!(self); + + let (view, doc) = current!(self); if remove_empty_scratch { // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable // borrow, invalidating direct access to `doc.id`. @@ -378,7 +379,16 @@ impl Editor { } else { let jump = (view.doc, doc.selection(view.id).clone()); view.jumps.push(jump); - view.last_accessed_doc = Some(view.doc); + // Set last accessed doc if it is a different document + if doc.id != id { + view.last_accessed_doc = Some(view.doc); + // Set last modified doc if modified and last modified doc is different + if std::mem::take(&mut doc.modified_since_accessed) + && view.last_modified_docs[0] != Some(id) + { + view.last_modified_docs = [Some(view.doc), view.last_modified_docs[0]]; + } + } } let view_id = view.id; diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 217a4940..94d67acd 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -75,6 +75,11 @@ pub struct View { pub jumps: JumpList, /// the last accessed file before the current one pub last_accessed_doc: Option, + /// the last modified files before the current one + /// ordered from most frequent to least frequent + // uses two docs because we want to be able to swap between the + // two last modified docs which we need to manually keep track of + pub last_modified_docs: [Option; 2], } impl View { @@ -86,6 +91,7 @@ impl View { area: Rect::default(), // will get calculated upon inserting into tree jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel last_accessed_doc: None, + last_modified_docs: [None, None], } } -- cgit v1.2.3-70-g09d2 From cab09093dd5bf9b4707bfdfd8529b348c02670ea Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 6 Dec 2021 12:24:25 +0900 Subject: fix: Normalize backtab into shift-tab Fixes #1150 --- book/src/remapping.md | 5 ++--- helix-term/src/ui/menu.rs | 2 +- helix-term/src/ui/picker.rs | 2 +- helix-term/src/ui/prompt.rs | 2 +- helix-view/src/input.rs | 24 ++++++++++++++---------- helix-view/src/keyboard.rs | 5 +---- 6 files changed, 20 insertions(+), 20 deletions(-) (limited to 'book/src') diff --git a/book/src/remapping.md b/book/src/remapping.md index fffd189b..ad63b60b 100644 --- a/book/src/remapping.md +++ b/book/src/remapping.md @@ -42,10 +42,9 @@ Control, Shift and Alt modifiers are encoded respectively with the prefixes | Down | `"down"` | | Home | `"home"` | | End | `"end"` | -| Page | `"pageup"` | -| Page | `"pagedown"` | +| Page Up | `"pageup"` | +| Page Down | `"pagedown"` | | Tab | `"tab"` | -| Back | `"backtab"` | | Delete | `"del"` | | Insert | `"ins"` | | Null | `"null"` | diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index e891c149..9a885a36 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -202,7 +202,7 @@ impl Component for Menu { return close_fn; } // arrow up/ctrl-p/shift-tab prev completion choice (including updating the doc) - shift!(BackTab) | key!(Up) | ctrl!('p') | ctrl!('k') => { + shift!(Tab) | key!(Up) | ctrl!('p') | ctrl!('k') => { self.move_up(); (self.callback_fn)(cx.editor, self.selection(), MenuEvent::Update); return EventResult::Consumed(None); diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 16bf08a3..1c963f97 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -410,7 +410,7 @@ impl Component for Picker { }))); match key_event.into() { - shift!(BackTab) | key!(Up) | ctrl!('p') | ctrl!('k') => { + shift!(Tab) | key!(Up) | ctrl!('p') | ctrl!('k') => { self.move_up(); } key!(Tab) | key!(Down) | ctrl!('n') | ctrl!('j') => { diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index e90b0772..a7ef231c 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -505,7 +505,7 @@ impl Component for Prompt { self.change_completion_selection(CompletionDirection::Forward); (self.callback_fn)(cx, &self.line, PromptEvent::Update) } - shift!(BackTab) => { + shift!(Tab) => { self.change_completion_selection(CompletionDirection::Backward); (self.callback_fn)(cx, &self.line, PromptEvent::Update) } diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs index 580204cc..b207c3ed 100644 --- a/helix-view/src/input.rs +++ b/helix-view/src/input.rs @@ -36,7 +36,6 @@ pub(crate) mod keys { pub(crate) const PAGEUP: &str = "pageup"; pub(crate) const PAGEDOWN: &str = "pagedown"; pub(crate) const TAB: &str = "tab"; - pub(crate) const BACKTAB: &str = "backtab"; pub(crate) const DELETE: &str = "del"; pub(crate) const INSERT: &str = "ins"; pub(crate) const NULL: &str = "null"; @@ -82,7 +81,6 @@ impl fmt::Display for KeyEvent { KeyCode::PageUp => f.write_str(keys::PAGEUP)?, KeyCode::PageDown => f.write_str(keys::PAGEDOWN)?, KeyCode::Tab => f.write_str(keys::TAB)?, - KeyCode::BackTab => f.write_str(keys::BACKTAB)?, KeyCode::Delete => f.write_str(keys::DELETE)?, KeyCode::Insert => f.write_str(keys::INSERT)?, KeyCode::Null => f.write_str(keys::NULL)?, @@ -116,7 +114,6 @@ impl UnicodeWidthStr for KeyEvent { KeyCode::PageUp => keys::PAGEUP.len(), KeyCode::PageDown => keys::PAGEDOWN.len(), KeyCode::Tab => keys::TAB.len(), - KeyCode::BackTab => keys::BACKTAB.len(), KeyCode::Delete => keys::DELETE.len(), KeyCode::Insert => keys::INSERT.len(), KeyCode::Null => keys::NULL.len(), @@ -166,7 +163,6 @@ impl std::str::FromStr for KeyEvent { keys::PAGEUP => KeyCode::PageUp, keys::PAGEDOWN => KeyCode::PageDown, keys::TAB => KeyCode::Tab, - keys::BACKTAB => KeyCode::BackTab, keys::DELETE => KeyCode::Delete, keys::INSERT => KeyCode::Insert, keys::NULL => KeyCode::Null, @@ -220,12 +216,20 @@ impl<'de> Deserialize<'de> for KeyEvent { #[cfg(feature = "term")] impl From for KeyEvent { - fn from( - crossterm::event::KeyEvent { code, modifiers }: crossterm::event::KeyEvent, - ) -> KeyEvent { - KeyEvent { - code: code.into(), - modifiers: modifiers.into(), + fn from(crossterm::event::KeyEvent { code, modifiers }: crossterm::event::KeyEvent) -> Self { + if code == crossterm::event::KeyCode::BackTab { + // special case for BackTab -> Shift-Tab + let mut modifiers: KeyModifiers = modifiers.into(); + modifiers.insert(KeyModifiers::SHIFT); + Self { + code: KeyCode::Tab, + modifiers, + } + } else { + Self { + code: code.into(), + modifiers: modifiers.into(), + } } } } diff --git a/helix-view/src/keyboard.rs b/helix-view/src/keyboard.rs index 810aa063..f1717209 100644 --- a/helix-view/src/keyboard.rs +++ b/helix-view/src/keyboard.rs @@ -79,8 +79,6 @@ pub enum KeyCode { PageDown, /// Tab key. Tab, - /// Shift + Tab key. - BackTab, /// Delete key. Delete, /// Insert key. @@ -116,7 +114,6 @@ impl From for crossterm::event::KeyCode { KeyCode::PageUp => CKeyCode::PageUp, KeyCode::PageDown => CKeyCode::PageDown, KeyCode::Tab => CKeyCode::Tab, - KeyCode::BackTab => CKeyCode::BackTab, KeyCode::Delete => CKeyCode::Delete, KeyCode::Insert => CKeyCode::Insert, KeyCode::F(f_number) => CKeyCode::F(f_number), @@ -144,7 +141,7 @@ impl From for KeyCode { CKeyCode::PageUp => KeyCode::PageUp, CKeyCode::PageDown => KeyCode::PageDown, CKeyCode::Tab => KeyCode::Tab, - CKeyCode::BackTab => KeyCode::BackTab, + CKeyCode::BackTab => unreachable!("BackTab should have been handled on KeyEvent level"), CKeyCode::Delete => KeyCode::Delete, CKeyCode::Insert => KeyCode::Insert, CKeyCode::F(f_number) => KeyCode::F(f_number), -- cgit v1.2.3-70-g09d2 From 178cd5ecfc75280ae12810cf3c0aeb22284bfdf2 Mon Sep 17 00:00:00 2001 From: Omnikar Date: Mon, 6 Dec 2021 11:44:50 -0500 Subject: Add note to `keymap.md` regarding `format_selections` (#1230) --- book/src/keymap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 59353db9..e1b1bad8 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -69,7 +69,7 @@ | `"` `` | Select a register to yank to or paste from | `select_register` | | `>` | Indent selection | `indent` | | `<` | Unindent selection | `unindent` | -| `=` | Format selection (**LSP**) | `format_selections` | +| `=` | Format selection (currently nonfunctional/disabled) (**LSP**) | `format_selections` | | `d` | Delete selection | `delete_selection` | | `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` | | `c` | Change selection (delete and enter insert mode) | `change_selection` | -- cgit v1.2.3-70-g09d2 From 71292f9f11bd2b50568efd111239f693be26a36a Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Wed, 17 Nov 2021 19:00:11 +0530 Subject: docs: Auto generate command list --- .cargo/config | 2 + Cargo.lock | 7 ++++ Cargo.toml | 1 + README.md | 16 +------- book/src/SUMMARY.md | 3 +- book/src/commands.md | 5 +++ book/src/generated/typable-cmd.md | 43 ++++++++++++++++++++ docs/CONTRIBUTING.md | 37 +++++++++++++++++ helix-term/src/commands.rs | 8 ++-- xtask/Cargo.toml | 9 ++++ xtask/src/main.rs | 86 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 197 insertions(+), 20 deletions(-) create mode 100644 .cargo/config create mode 100644 book/src/commands.md create mode 100644 book/src/generated/typable-cmd.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs (limited to 'book/src') diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000..35049cbc --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" diff --git a/Cargo.lock b/Cargo.lock index 47a6c01e..b3032465 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1259,3 +1259,10 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xtask" +version = "0.5.0" +dependencies = [ + "helix-term", +] diff --git a/Cargo.toml b/Cargo.toml index 580cccd6..8c3ee671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "helix-tui", "helix-syntax", "helix-lsp", + "xtask", ] # Build helix-syntax in release mode to make the code path faster in development. diff --git a/README.md b/README.md index 3f4087b9..f651e30c 100644 --- a/README.md +++ b/README.md @@ -65,21 +65,7 @@ brew install helix # Contributing -Contributors are very welcome! **No contribution is too small and all contributions are valued.** - -Some suggestions to get started: - -- You can look at the [good first issue](https://github.com/helix-editor/helix/issues?q=is%3Aopen+label%3AE-easy+label%3AE-good-first-issue) label on the issue tracker. -- Help with packaging on various distributions needed! -- To use print debugging to the [Helix log file](https://github.com/helix-editor/helix/wiki/FAQ#access-the-log-file), you must: - * Print using `log::info!`, `warn!`, or `error!`. (`log::info!("helix!")`) - * Pass the appropriate verbosity level option for the desired log level. (`hx -v ` for info, more `v`s for higher severity inclusive) -- If your preferred language is missing, integrating a tree-sitter grammar for - it and defining syntax highlight queries for it is straight forward and - doesn't require much knowledge of the internals. - -We provide an [architecture.md](./docs/architecture.md) that should give you -a good overview of the internals. +Contributing guidelines can be found [here](./docs/CONTRIBUTING.md). # Getting help diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 8cadb663..4da79925 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -2,10 +2,11 @@ - [Installation](./install.md) - [Usage](./usage.md) + - [Keymap](./keymap.md) + - [Commands](./commands.md) - [Migrating from Vim](./from-vim.md) - [Configuration](./configuration.md) - [Themes](./themes.md) - - [Keymap](./keymap.md) - [Key Remapping](./remapping.md) - [Hooks](./hooks.md) - [Languages](./languages.md) diff --git a/book/src/commands.md b/book/src/commands.md new file mode 100644 index 00000000..4c4a5c05 --- /dev/null +++ b/book/src/commands.md @@ -0,0 +1,5 @@ +# Commands + +Command mode can be activated by pressing `:`, similar to vim. Built-in commands: + +{{#include ./generated/typable-cmd.md}} diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md new file mode 100644 index 00000000..5de5c787 --- /dev/null +++ b/book/src/generated/typable-cmd.md @@ -0,0 +1,43 @@ +| Name | Description | +| --- | --- | +| `:quit`, `:q` | Close the current view. | +| `:quit!`, `:q!` | Close the current view forcefully (ignoring unsaved changes). | +| `:open`, `:o` | Open a file from disk into the current view. | +| `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. | +| `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully (ignoring unsaved changes). | +| `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) | +| `:new`, `:n` | Create a new scratch buffer. | +| `:format`, `:fmt` | Format the file using the LSP formatter. | +| `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.) | +| `:line-ending` | Set the document's default line ending. Options: crlf, lf, cr, ff, nel. | +| `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. | +| `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. | +| `:write-quit`, `:wq`, `:x` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) | +| `:write-quit!`, `:wq!`, `:x!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) | +| `:write-all`, `:wa` | Write changes from all views to disk. | +| `:write-quit-all`, `:wqa`, `:xa` | Write changes from all views to disk and close all views. | +| `:write-quit-all!`, `:wqa!`, `:xa!` | Write changes from all views to disk and close all views forcefully (ignoring unsaved changes). | +| `:quit-all`, `:qa` | Close all views. | +| `:quit-all!`, `:qa!` | Close all views forcefully (ignoring unsaved changes). | +| `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). | +| `:theme` | Change the editor theme. | +| `:clipboard-yank` | Yank main selection into system clipboard. | +| `:clipboard-yank-join` | Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline. | +| `:primary-clipboard-yank` | Yank main selection into system primary clipboard. | +| `:primary-clipboard-yank-join` | Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline. | +| `:clipboard-paste-after` | Paste system clipboard after selections. | +| `:clipboard-paste-before` | Paste system clipboard before selections. | +| `:clipboard-paste-replace` | Replace selections with content of system clipboard. | +| `:primary-clipboard-paste-after` | Paste primary clipboard after selections. | +| `:primary-clipboard-paste-before` | Paste primary clipboard before selections. | +| `:primary-clipboard-paste-replace` | Replace selections with content of system primary clipboard. | +| `:show-clipboard-provider` | Show clipboard provider name in status bar. | +| `:change-current-directory`, `:cd` | Change the current working directory. | +| `:show-directory`, `:pwd` | Show the current working directory. | +| `:encoding` | Set encoding based on `https://encoding.spec.whatwg.org` | +| `:reload` | Discard changes and reload from the source file. | +| `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. | +| `:vsplit`, `:vs` | Open the file in a vertical split. | +| `:hsplit`, `:hs`, `:sp` | Open the file in a horizontal split. | +| `:tutor` | Open the tutorial. | +| `:goto`, `:g` | Go to line number. | diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 00000000..7b923db8 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,37 @@ +# Contributing + +Contributors are very welcome! **No contribution is too small and all contributions are valued.** + +Some suggestions to get started: + +- You can look at the [good first issue][good-first-issue] label on the issue tracker. +- Help with packaging on various distributions needed! +- To use print debugging to the [Helix log file][log-file], you must: + * Print using `log::info!`, `warn!`, or `error!`. (`log::info!("helix!")`) + * Pass the appropriate verbosity level option for the desired log level. (`hx -v ` for info, more `v`s for higher severity inclusive) +- If your preferred language is missing, integrating a tree-sitter grammar for + it and defining syntax highlight queries for it is straight forward and + doesn't require much knowledge of the internals. + +We provide an [architecture.md][architecture.md] that should give you +a good overview of the internals. + +# Auto generated documentation + +Some parts of [the book][docs] are autogenerated from the code itself, +like the list of `:commands` and supported languages. To generate these +files, run + +```shell +cargo xtask bookgen +``` + +inside the project. We use [xtask][xtask] as an ad-hoc task runner and +thus do not require any dependencies other than `cargo` (You don't have +to `cargo install` anything either). + +[good-first-issue]: https://github.com/helix-editor/helix/labels/E-easy +[log-file]: https://github.com/helix-editor/helix/wiki/FAQ#access-the-log-file +[architecture.md]: ./architecture.md +[docs]: https://docs.helix-editor.com/ +[xtask]: https://github.com/matklad/cargo-xtask diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 3e7ce712..4910790a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1949,7 +1949,7 @@ fn append_mode(cx: &mut Context) { doc.set_selection(view.id, selection); } -mod cmd { +pub mod cmd { use super::*; use std::collections::HashMap; @@ -2679,7 +2679,7 @@ mod cmd { TypableCommand { name: "format", aliases: &["fmt"], - doc: "Format the file using a formatter.", + doc: "Format the file using the LSP formatter.", fun: format, completer: None, }, @@ -2770,7 +2770,7 @@ mod cmd { TypableCommand { name: "theme", aliases: &[], - doc: "Change the theme of current view. Requires theme name as argument (:theme )", + doc: "Change the editor theme.", fun: theme, completer: Some(completers::theme), }, @@ -2854,7 +2854,7 @@ mod cmd { TypableCommand { name: "change-current-directory", aliases: &["cd"], - doc: "Change the current working directory (:cd ).", + doc: "Change the current working directory.", fun: change_current_directory, completer: Some(completers::directory), }, diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 00000000..cb890de9 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "xtask" +version = "0.5.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +helix-term = { version = "0.5", path = "../helix-term" } diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 00000000..4bf0ae9f --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,86 @@ +use std::env; + +pub mod md_gen { + use super::path; + use std::fs; + + use helix_term::commands::cmd::TYPABLE_COMMAND_LIST; + + pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md"; + + pub fn typable_commands() -> String { + let mut md = String::new(); + md.push_str("| Name | Description |\n"); + md.push_str("| --- | --- |\n"); + + let cmdify = |s: &str| format!("`:{}`", s); + + for cmd in TYPABLE_COMMAND_LIST { + let names = std::iter::once(&cmd.name) + .chain(cmd.aliases.iter()) + .map(|a| cmdify(a)) + .collect::>() + .join(", "); + + let entry = format!("| {} | {} |\n", names, cmd.doc); + md.push_str(&entry); + } + + md + } + + pub fn write(filename: &str, data: &str) { + let error = format!("Could not write to {}", filename); + let path = path::book_gen().join(filename); + fs::write(path, data).expect(&error); + } +} + +pub mod path { + use std::path::{Path, PathBuf}; + + pub fn project_root() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf() + } + + pub fn book_gen() -> PathBuf { + project_root().join("book/src/generated/") + } +} + +pub mod tasks { + use super::md_gen; + + pub fn bookgen() { + md_gen::write( + md_gen::TYPABLE_COMMANDS_MD_OUTPUT, + &md_gen::typable_commands(), + ); + } + + pub fn print_help() { + println!( + " +Usage: Run with `cargo xtask `, eg. `cargo xtask bookgen`. + + Tasks: + bookgen: Generate files to be included in the mdbook output. +" + ); + } +} + +fn main() -> Result<(), String> { + let task = env::args().nth(1); + match task { + None => tasks::print_help(), + Some(t) => match t.as_str() { + "bookgen" => tasks::bookgen(), + invalid => return Err(format!("Invalid task name: {}", invalid)), + }, + }; + Ok(()) +} -- cgit v1.2.3-70-g09d2 From a78b7894066b6ccf56c404b7543b45e2dfd99982 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 22 Nov 2021 00:25:08 +0530 Subject: Auto generate docs for language support --- Cargo.lock | 2 + book/src/SUMMARY.md | 1 + book/src/generated/lang-support.md | 41 +++++++ book/src/generated/typable-cmd.md | 2 +- book/src/lang-support.md | 10 ++ docs/CONTRIBUTING.md | 2 +- helix-core/src/indent.rs | 1 + helix-core/src/syntax.rs | 3 +- languages.toml | 40 +++++++ xtask/Cargo.toml | 2 + xtask/src/main.rs | 229 ++++++++++++++++++++++++++++++++++--- 11 files changed, 311 insertions(+), 22 deletions(-) create mode 100644 book/src/generated/lang-support.md create mode 100644 book/src/lang-support.md (limited to 'book/src') diff --git a/Cargo.lock b/Cargo.lock index b3032465..25b4f6cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1264,5 +1264,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" name = "xtask" version = "0.5.0" dependencies = [ + "helix-core", "helix-term", + "toml", ] diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 4da79925..a8f165c0 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -4,6 +4,7 @@ - [Usage](./usage.md) - [Keymap](./keymap.md) - [Commands](./commands.md) + - [Language Support](./lang-support.md) - [Migrating from Vim](./from-vim.md) - [Configuration](./configuration.md) - [Themes](./themes.md) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md new file mode 100644 index 00000000..729801ad --- /dev/null +++ b/book/src/generated/lang-support.md @@ -0,0 +1,41 @@ +| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP | +| --- | --- | --- | --- | --- | +| Bash | ✓ | | | `bash-language-server` | +| C | ✓ | | | `clangd` | +| C# | ✓ | | | | +| CMake | ✓ | | | `cmake-language-server` | +| C++ | ✓ | | | `clangd` | +| CSS | ✓ | | | | +| Elixir | ✓ | | | `elixir-ls` | +| GLSL | ✓ | | ✓ | | +| Go | ✓ | ✓ | ✓ | `gopls` | +| HTML | ✓ | | | | +| Java | ✓ | | | | +| JavaScript | ✓ | | ✓ | | +| JSON | ✓ | | ✓ | | +| Julia | ✓ | | | `julia` | +| LaTeX | ✓ | | | | +| Ledger | ✓ | | | | +| LLVM | ✓ | | | | +| Lua | ✓ | | ✓ | | +| Mint | | | | `mint` | +| Nix | ✓ | | ✓ | `rnix-lsp` | +| OCaml | ✓ | | ✓ | | +| OCaml-Interface | ✓ | | | | +| Perl | ✓ | ✓ | | | +| PHP | ✓ | | ✓ | | +| Prolog | | | | `swipl` | +| Protobuf | ✓ | | ✓ | | +| Python | ✓ | ✓ | ✓ | `pylsp` | +| Racket | | | | `racket` | +| Ruby | ✓ | | | `solargraph` | +| Rust | ✓ | ✓ | ✓ | `rust-analyzer` | +| Svelte | ✓ | | ✓ | `svelteserver` | +| TOML | ✓ | | | | +| TSQ | ✓ | | | | +| TSX | ✓ | | | `typescript-language-server` | +| TypeScript | ✓ | | ✓ | `typescript-language-server` | +| Vue | ✓ | | | | +| WGSL | ✓ | | | | +| YAML | ✓ | | ✓ | | +| Zig | ✓ | | ✓ | `zls` | diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index 5de5c787..bb21fd6b 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -1,5 +1,5 @@ | Name | Description | -| --- | --- | +| --- | --- | | `:quit`, `:q` | Close the current view. | | `:quit!`, `:q!` | Close the current view forcefully (ignoring unsaved changes). | | `:open`, `:o` | Open a file from disk into the current view. | diff --git a/book/src/lang-support.md b/book/src/lang-support.md new file mode 100644 index 00000000..3920f342 --- /dev/null +++ b/book/src/lang-support.md @@ -0,0 +1,10 @@ +# Language Support + +For more information like arguments passed to default LSP server, +extensions assosciated with a filetype, custom LSP settings, filetype +specific indent settings, etc see the default +[`languages.toml`][languages.toml] file. + +{{#include ./generated/lang-support.md}} + +[languages.toml]: https://github.com/helix-editor/helix/blob/master/languages.toml diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 7b923db8..bdd771aa 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -23,7 +23,7 @@ like the list of `:commands` and supported languages. To generate these files, run ```shell -cargo xtask bookgen +cargo xtask docgen ``` inside the project. We use [xtask][xtask] as an ad-hoc task runner and diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index b6f5081a..3ce3620a 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -452,6 +452,7 @@ where file_types: vec!["rs".to_string()], shebangs: vec![], language_id: "Rust".to_string(), + display_name: "Rust".to_string(), highlight_config: OnceCell::new(), config: None, // diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index ba78adaa..3c65ae33 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -50,7 +50,8 @@ pub struct Configuration { #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct LanguageConfiguration { #[serde(rename = "name")] - pub language_id: String, + pub language_id: String, // c-sharp, rust + pub display_name: String, // C#, Rust pub scope: String, // source.rust pub file_types: Vec, // filename ends_with? #[serde(default)] diff --git a/languages.toml b/languages.toml index 4208e4b6..ca339c98 100644 --- a/languages.toml +++ b/languages.toml @@ -1,5 +1,6 @@ [[language]] name = "rust" +display-name = "Rust" scope = "source.rust" injection-regex = "rust" file-types = ["rs"] @@ -14,6 +15,7 @@ procMacro = { enable = false } [[language]] name = "toml" +display-name = "TOML" scope = "source.toml" injection-regex = "toml" file-types = ["toml"] @@ -24,6 +26,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "protobuf" +display-name = "Protobuf" scope = "source.proto" injection-regex = "protobuf" file-types = ["proto"] @@ -34,6 +37,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "elixir" +display-name = "Elixir" scope = "source.elixir" injection-regex = "elixir" file-types = ["ex", "exs"] @@ -46,6 +50,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "mint" +display-name = "Mint" scope = "source.mint" injection-regex = "mint" file-types = ["mint"] @@ -58,6 +63,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "json" +display-name = "JSON" scope = "source.json" injection-regex = "json" file-types = ["json"] @@ -67,6 +73,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "c" +display-name = "C" scope = "source.c" injection-regex = "c" file-types = ["c"] # TODO: ["h"] @@ -78,6 +85,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "cpp" +display-name = "C++" scope = "source.cpp" injection-regex = "cpp" file-types = ["cc", "hh", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino"] @@ -89,6 +97,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "c-sharp" +display-name = "C#" scope = "source.csharp" injection-regex = "c-?sharp" file-types = ["cs"] @@ -99,6 +108,7 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "go" +display-name = "Go" scope = "source.go" injection-regex = "go" file-types = ["go"] @@ -112,6 +122,7 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "javascript" +display-name = "JavaScript" scope = "source.js" injection-regex = "^(js|javascript)$" file-types = ["js", "mjs"] @@ -124,6 +135,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "typescript" +display-name = "TypeScript" scope = "source.ts" injection-regex = "^(ts|typescript)$" file-types = ["ts"] @@ -136,6 +148,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "tsx" +display-name = "TSX" scope = "source.tsx" injection-regex = "^(tsx)$" # |typescript file-types = ["tsx"] @@ -147,6 +160,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "css" +display-name = "CSS" scope = "source.css" injection-regex = "css" file-types = ["css"] @@ -156,6 +170,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "html" +display-name = "HTML" scope = "text.html.basic" injection-regex = "html" file-types = ["html"] @@ -165,6 +180,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "python" +display-name = "Python" scope = "source.python" injection-regex = "python" file-types = ["py"] @@ -178,6 +194,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "nix" +display-name = "Nix" scope = "source.nix" injection-regex = "nix" file-types = ["nix"] @@ -190,6 +207,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "ruby" +display-name = "Ruby" scope = "source.ruby" injection-regex = "ruby" file-types = ["rb"] @@ -202,6 +220,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "bash" +display-name = "Bash" scope = "source.bash" injection-regex = "bash" file-types = ["sh", "bash"] @@ -214,6 +233,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "php" +display-name = "PHP" scope = "source.php" injection-regex = "php" file-types = ["php"] @@ -224,6 +244,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "latex" +display-name = "LaTeX" scope = "source.tex" injection-regex = "tex" file-types = ["tex"] @@ -234,6 +255,7 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "julia" +display-name = "Julia" scope = "source.julia" injection-regex = "julia" file-types = ["jl"] @@ -259,6 +281,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "java" +display-name = "Java" scope = "source.java" injection-regex = "java" file-types = ["java"] @@ -267,6 +290,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "ledger" +display-name = "Ledger" scope = "source.ledger" injection-regex = "ledger" file-types = ["ldg", "ledger", "journal"] @@ -276,6 +300,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "ocaml" +display-name = "OCaml" scope = "source.ocaml" injection-regex = "ocaml" file-types = ["ml"] @@ -286,6 +311,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "ocaml-interface" +display-name = "OCaml-Interface" scope = "source.ocaml.interface" file-types = ["mli"] shebangs = [] @@ -295,6 +321,7 @@ indent = { tab-width = 2, unit = " "} [[language]] name = "lua" +display-name = "Lua" scope = "source.lua" file-types = ["lua"] shebangs = ["lua"] @@ -304,6 +331,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "svelte" +display-name = "Svelte" scope = "source.svelte" injection-regex = "svelte" file-types = ["svelte"] @@ -314,6 +342,7 @@ language-server = { command = "svelteserver", args = ["--stdio"] } [[language]] name = "vue" +display-name = "Vue" scope = "source.vue" injection-regex = "vue" file-types = ["vue"] @@ -322,6 +351,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "yaml" +display-name = "YAML" scope = "source.yaml" file-types = ["yml", "yaml"] roots = [] @@ -330,6 +360,7 @@ indent = { tab-width = 2, unit = " " } # [[language]] # name = "haskell" +# display-name = "Haskell" # scope = "source.haskell" # injection-regex = "haskell" # file-types = ["hs"] @@ -340,6 +371,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "zig" +display-name = "Zig" scope = "source.zig" injection-regex = "zig" file-types = ["zig"] @@ -352,6 +384,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "prolog" +display-name = "Prolog" scope = "source.prolog" roots = [] file-types = ["pl", "prolog"] @@ -365,6 +398,7 @@ language-server = { command = "swipl", args = [ [[language]] name = "tsq" +display-name = "TSQ" scope = "source.tsq" file-types = ["scm"] roots = [] @@ -373,6 +407,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "cmake" +display-name = "CMake" scope = "source.cmake" file-types = ["cmake", "CMakeLists.txt"] roots = [] @@ -382,6 +417,7 @@ language-server = { command = "cmake-language-server" } [[language]] name = "glsl" +display-name = "GLSL" scope = "source.glsl" file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ] roots = [] @@ -390,6 +426,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "perl" +display-name = "Perl" scope = "source.perl" file-types = ["pl", "pm"] shebangs = ["perl"] @@ -399,6 +436,7 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "racket" +display-name = "Racket" scope = "source.rkt" roots = [] file-types = ["rkt"] @@ -408,6 +446,7 @@ language-server = { command = "racket", args = ["-l", "racket-langserver"] } [[language]] name = "wgsl" +display-name = "WGSL" scope = "source.wgsl" file-types = ["wgsl"] roots = [] @@ -416,6 +455,7 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "llvm" +display-name = "LLVM" scope = "source.llvm" roots = [] file-types = ["ll"] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index cb890de9..fe5d55d4 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,3 +7,5 @@ edition = "2021" [dependencies] helix-term = { version = "0.5", path = "../helix-term" } +helix-core = { version = "0.5", path = "../helix-core" } +toml = "0.5" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4bf0ae9f..37e70592 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,17 +1,138 @@ -use std::env; +use std::{env, error::Error}; + +type DynError = Box; + +pub mod helpers { + use std::{ + fmt::Display, + path::{Path, PathBuf}, + }; + + use crate::path; + use helix_core::syntax::Configuration as LangConfig; + + #[derive(Copy, Clone)] + pub enum TsFeature { + Highlight, + TextObjects, + AutoIndent, + } + + impl TsFeature { + pub fn all() -> &'static [Self] { + &[Self::Highlight, Self::TextObjects, Self::AutoIndent] + } + + pub fn runtime_filename(&self) -> &'static str { + match *self { + Self::Highlight => "highlights.scm", + Self::TextObjects => "textobjects.scm", + Self::AutoIndent => "indents.toml", + } + } + } + + impl Display for TsFeature { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match *self { + Self::Highlight => "Syntax Highlighting", + Self::TextObjects => "Treesitter Textobjects", + Self::AutoIndent => "Auto Indent", + } + ) + } + } + + /// Get the list of languages that support a particular tree-sitter + /// based feature. + pub fn ts_lang_support(feat: TsFeature) -> Vec { + let queries_dir = path::ts_queries(); + + find_files(&queries_dir, feat.runtime_filename()) + .iter() + .map(|f| { + // .../helix/runtime/queries/python/highlights.scm + let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm + let lang = tail.components().next().unwrap(); // python + lang.as_os_str().to_string_lossy().to_string() + }) + .collect() + } + + /// Get the list of languages that have any form of tree-sitter + /// queries defined in the runtime directory. + pub fn langs_with_ts_queries() -> Vec { + std::fs::read_dir(path::ts_queries()) + .unwrap() + .filter_map(|entry| { + let entry = entry.ok()?; + entry + .file_type() + .ok()? + .is_dir() + .then(|| entry.file_name().to_string_lossy().to_string()) + }) + .collect() + } + + // naive implementation, but suffices for our needs + pub fn find_files(dir: &Path, filename: &str) -> Vec { + std::fs::read_dir(dir) + .unwrap() + .filter_map(|entry| { + let path = entry.ok()?.path(); + if path.is_dir() { + Some(find_files(&path, filename)) + } else { + (path.file_name()?.to_string_lossy() == filename).then(|| vec![path]) + } + }) + .flatten() + .collect() + } + + pub fn lang_config() -> LangConfig { + let bytes = std::fs::read(path::lang_config()).unwrap(); + toml::from_slice(&bytes).unwrap() + } +} pub mod md_gen { - use super::path; + use crate::DynError; + + use crate::helpers; + use crate::path; use std::fs; use helix_term::commands::cmd::TYPABLE_COMMAND_LIST; pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md"; + pub const LANG_SUPPORT_MD_OUTPUT: &str = "lang-support.md"; + + fn md_table_heading(cols: &[String]) -> String { + let mut header = String::new(); + header += &md_table_row(cols); + header += &md_table_row(&vec!["---".to_string(); cols.len()]); + header + } + + fn md_table_row(cols: &[String]) -> String { + "| ".to_owned() + &cols.join(" | ") + " |\n" + } + + fn md_mono(s: &str) -> String { + format!("`{}`", s) + } - pub fn typable_commands() -> String { + pub fn typable_commands() -> Result { let mut md = String::new(); - md.push_str("| Name | Description |\n"); - md.push_str("| --- | --- |\n"); + md.push_str(&md_table_heading(&[ + "Name".to_owned(), + "Description".to_owned(), + ])); let cmdify = |s: &str| format!("`:{}`", s); @@ -22,11 +143,72 @@ pub mod md_gen { .collect::>() .join(", "); - let entry = format!("| {} | {} |\n", names, cmd.doc); - md.push_str(&entry); + md.push_str(&md_table_row(&[names.to_owned(), cmd.doc.to_owned()])); + } + + Ok(md) + } + + pub fn lang_features() -> Result { + let mut md = String::new(); + let ts_features = helpers::TsFeature::all(); + + let mut cols = vec!["Language".to_owned()]; + cols.append( + &mut ts_features + .iter() + .map(|t| t.to_string()) + .collect::>(), + ); + cols.push("Default LSP".to_owned()); + + md.push_str(&md_table_heading(&cols)); + let config = helpers::lang_config(); + + let mut langs = config + .language + .iter() + .map(|l| l.language_id.clone()) + .collect::>(); + langs.sort_unstable(); + + let mut ts_features_to_langs = Vec::new(); + for &feat in ts_features { + ts_features_to_langs.push((feat, helpers::ts_lang_support(feat))); } - md + let mut row = Vec::new(); + for lang in langs { + let lc = config + .language + .iter() + .find(|l| l.language_id == lang) + .unwrap(); // lang comes from config + row.push(lc.display_name.clone()); + + for (_feat, support_list) in &ts_features_to_langs { + row.push( + if support_list.contains(&lang) { + "✓" + } else { + "" + } + .to_owned(), + ); + } + row.push( + lc.language_server + .as_ref() + .map(|s| s.command.clone()) + .map(|c| md_mono(&c)) + .unwrap_or_default(), + ); + + md.push_str(&md_table_row(&row)); + row.clear(); + } + + Ok(md) } pub fn write(filename: &str, data: &str) { @@ -49,37 +231,46 @@ pub mod path { pub fn book_gen() -> PathBuf { project_root().join("book/src/generated/") } + + pub fn ts_queries() -> PathBuf { + project_root().join("runtime/queries") + } + + pub fn lang_config() -> PathBuf { + project_root().join("languages.toml") + } } pub mod tasks { - use super::md_gen; + use crate::md_gen; + use crate::DynError; - pub fn bookgen() { - md_gen::write( - md_gen::TYPABLE_COMMANDS_MD_OUTPUT, - &md_gen::typable_commands(), - ); + pub fn docgen() -> Result<(), DynError> { + use md_gen::*; + write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?); + write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?); + Ok(()) } pub fn print_help() { println!( " -Usage: Run with `cargo xtask `, eg. `cargo xtask bookgen`. +Usage: Run with `cargo xtask `, eg. `cargo xtask docgen`. Tasks: - bookgen: Generate files to be included in the mdbook output. + docgen: Generate files to be included in the mdbook output. " ); } } -fn main() -> Result<(), String> { +fn main() -> Result<(), DynError> { let task = env::args().nth(1); match task { None => tasks::print_help(), Some(t) => match t.as_str() { - "bookgen" => tasks::bookgen(), - invalid => return Err(format!("Invalid task name: {}", invalid)), + "docgen" => tasks::docgen()?, + invalid => return Err(format!("Invalid task name: {}", invalid).into()), }, }; Ok(()) -- cgit v1.2.3-70-g09d2 From d08bdfa838098769afc59146b62f9d613d4a7ff4 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 7 Dec 2021 21:27:21 +0530 Subject: Use same name used in config files for langs in docs --- book/src/generated/lang-support.md | 78 +++++++++++++++++++------------------- helix-core/src/indent.rs | 1 - helix-core/src/syntax.rs | 1 - languages.toml | 41 -------------------- xtask/src/main.rs | 2 +- 5 files changed, 40 insertions(+), 83 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 729801ad..96d9b6a0 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -1,41 +1,41 @@ | Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP | | --- | --- | --- | --- | --- | -| Bash | ✓ | | | `bash-language-server` | -| C | ✓ | | | `clangd` | -| C# | ✓ | | | | -| CMake | ✓ | | | `cmake-language-server` | -| C++ | ✓ | | | `clangd` | -| CSS | ✓ | | | | -| Elixir | ✓ | | | `elixir-ls` | -| GLSL | ✓ | | ✓ | | -| Go | ✓ | ✓ | ✓ | `gopls` | -| HTML | ✓ | | | | -| Java | ✓ | | | | -| JavaScript | ✓ | | ✓ | | -| JSON | ✓ | | ✓ | | -| Julia | ✓ | | | `julia` | -| LaTeX | ✓ | | | | -| Ledger | ✓ | | | | -| LLVM | ✓ | | | | -| Lua | ✓ | | ✓ | | -| Mint | | | | `mint` | -| Nix | ✓ | | ✓ | `rnix-lsp` | -| OCaml | ✓ | | ✓ | | -| OCaml-Interface | ✓ | | | | -| Perl | ✓ | ✓ | | | -| PHP | ✓ | | ✓ | | -| Prolog | | | | `swipl` | -| Protobuf | ✓ | | ✓ | | -| Python | ✓ | ✓ | ✓ | `pylsp` | -| Racket | | | | `racket` | -| Ruby | ✓ | | | `solargraph` | -| Rust | ✓ | ✓ | ✓ | `rust-analyzer` | -| Svelte | ✓ | | ✓ | `svelteserver` | -| TOML | ✓ | | | | -| TSQ | ✓ | | | | -| TSX | ✓ | | | `typescript-language-server` | -| TypeScript | ✓ | | ✓ | `typescript-language-server` | -| Vue | ✓ | | | | -| WGSL | ✓ | | | | -| YAML | ✓ | | ✓ | | -| Zig | ✓ | | ✓ | `zls` | +| bash | ✓ | | | `bash-language-server` | +| c | ✓ | | | `clangd` | +| c-sharp | ✓ | | | | +| cmake | ✓ | | | `cmake-language-server` | +| cpp | ✓ | | | `clangd` | +| css | ✓ | | | | +| elixir | ✓ | | | `elixir-ls` | +| glsl | ✓ | | ✓ | | +| go | ✓ | ✓ | ✓ | `gopls` | +| html | ✓ | | | | +| java | ✓ | | | | +| javascript | ✓ | | ✓ | | +| json | ✓ | | ✓ | | +| julia | ✓ | | | `julia` | +| latex | ✓ | | | | +| ledger | ✓ | | | | +| llvm | ✓ | | | | +| lua | ✓ | | ✓ | | +| mint | | | | `mint` | +| nix | ✓ | | ✓ | `rnix-lsp` | +| ocaml | ✓ | | ✓ | | +| ocaml-interface | ✓ | | | | +| perl | ✓ | ✓ | | | +| php | ✓ | | ✓ | | +| prolog | | | | `swipl` | +| protobuf | ✓ | | ✓ | | +| python | ✓ | ✓ | ✓ | `pylsp` | +| racket | | | | `racket` | +| ruby | ✓ | | | `solargraph` | +| rust | ✓ | ✓ | ✓ | `rust-analyzer` | +| svelte | ✓ | | ✓ | `svelteserver` | +| toml | ✓ | | | | +| tsq | ✓ | | | | +| tsx | ✓ | | | `typescript-language-server` | +| typescript | ✓ | | ✓ | `typescript-language-server` | +| vue | ✓ | | | | +| wgsl | ✓ | | | | +| yaml | ✓ | | ✓ | | +| zig | ✓ | | ✓ | `zls` | diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 3ce3620a..b6f5081a 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -452,7 +452,6 @@ where file_types: vec!["rs".to_string()], shebangs: vec![], language_id: "Rust".to_string(), - display_name: "Rust".to_string(), highlight_config: OnceCell::new(), config: None, // diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 3c65ae33..ef35fc75 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -51,7 +51,6 @@ pub struct Configuration { pub struct LanguageConfiguration { #[serde(rename = "name")] pub language_id: String, // c-sharp, rust - pub display_name: String, // C#, Rust pub scope: String, // source.rust pub file_types: Vec, // filename ends_with? #[serde(default)] diff --git a/languages.toml b/languages.toml index ca339c98..428051a7 100644 --- a/languages.toml +++ b/languages.toml @@ -1,6 +1,5 @@ [[language]] name = "rust" -display-name = "Rust" scope = "source.rust" injection-regex = "rust" file-types = ["rs"] @@ -15,7 +14,6 @@ procMacro = { enable = false } [[language]] name = "toml" -display-name = "TOML" scope = "source.toml" injection-regex = "toml" file-types = ["toml"] @@ -26,7 +24,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "protobuf" -display-name = "Protobuf" scope = "source.proto" injection-regex = "protobuf" file-types = ["proto"] @@ -37,7 +34,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "elixir" -display-name = "Elixir" scope = "source.elixir" injection-regex = "elixir" file-types = ["ex", "exs"] @@ -50,7 +46,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "mint" -display-name = "Mint" scope = "source.mint" injection-regex = "mint" file-types = ["mint"] @@ -63,7 +58,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "json" -display-name = "JSON" scope = "source.json" injection-regex = "json" file-types = ["json"] @@ -73,7 +67,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "c" -display-name = "C" scope = "source.c" injection-regex = "c" file-types = ["c"] # TODO: ["h"] @@ -85,7 +78,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "cpp" -display-name = "C++" scope = "source.cpp" injection-regex = "cpp" file-types = ["cc", "hh", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino"] @@ -97,7 +89,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "c-sharp" -display-name = "C#" scope = "source.csharp" injection-regex = "c-?sharp" file-types = ["cs"] @@ -108,7 +99,6 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "go" -display-name = "Go" scope = "source.go" injection-regex = "go" file-types = ["go"] @@ -122,7 +112,6 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "javascript" -display-name = "JavaScript" scope = "source.js" injection-regex = "^(js|javascript)$" file-types = ["js", "mjs"] @@ -135,7 +124,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "typescript" -display-name = "TypeScript" scope = "source.ts" injection-regex = "^(ts|typescript)$" file-types = ["ts"] @@ -148,7 +136,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "tsx" -display-name = "TSX" scope = "source.tsx" injection-regex = "^(tsx)$" # |typescript file-types = ["tsx"] @@ -160,7 +147,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "css" -display-name = "CSS" scope = "source.css" injection-regex = "css" file-types = ["css"] @@ -170,7 +156,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "html" -display-name = "HTML" scope = "text.html.basic" injection-regex = "html" file-types = ["html"] @@ -180,7 +165,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "python" -display-name = "Python" scope = "source.python" injection-regex = "python" file-types = ["py"] @@ -194,7 +178,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "nix" -display-name = "Nix" scope = "source.nix" injection-regex = "nix" file-types = ["nix"] @@ -207,7 +190,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "ruby" -display-name = "Ruby" scope = "source.ruby" injection-regex = "ruby" file-types = ["rb"] @@ -220,7 +202,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "bash" -display-name = "Bash" scope = "source.bash" injection-regex = "bash" file-types = ["sh", "bash"] @@ -233,7 +214,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "php" -display-name = "PHP" scope = "source.php" injection-regex = "php" file-types = ["php"] @@ -244,7 +224,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "latex" -display-name = "LaTeX" scope = "source.tex" injection-regex = "tex" file-types = ["tex"] @@ -255,7 +234,6 @@ indent = { tab-width = 4, unit = "\t" } [[language]] name = "julia" -display-name = "Julia" scope = "source.julia" injection-regex = "julia" file-types = ["jl"] @@ -271,7 +249,6 @@ language-server = { command = "julia", args = [ using Pkg; import StaticLint; env_path = dirname(Pkg.Types.Context().env.project_file); - server = LanguageServer.LanguageServerInstance(stdin, stdout, env_path, ""); server.runlinter = true; run(server); @@ -281,7 +258,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "java" -display-name = "Java" scope = "source.java" injection-regex = "java" file-types = ["java"] @@ -290,7 +266,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "ledger" -display-name = "Ledger" scope = "source.ledger" injection-regex = "ledger" file-types = ["ldg", "ledger", "journal"] @@ -300,7 +275,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "ocaml" -display-name = "OCaml" scope = "source.ocaml" injection-regex = "ocaml" file-types = ["ml"] @@ -311,7 +285,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "ocaml-interface" -display-name = "OCaml-Interface" scope = "source.ocaml.interface" file-types = ["mli"] shebangs = [] @@ -321,7 +294,6 @@ indent = { tab-width = 2, unit = " "} [[language]] name = "lua" -display-name = "Lua" scope = "source.lua" file-types = ["lua"] shebangs = ["lua"] @@ -331,7 +303,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "svelte" -display-name = "Svelte" scope = "source.svelte" injection-regex = "svelte" file-types = ["svelte"] @@ -342,7 +313,6 @@ language-server = { command = "svelteserver", args = ["--stdio"] } [[language]] name = "vue" -display-name = "Vue" scope = "source.vue" injection-regex = "vue" file-types = ["vue"] @@ -351,7 +321,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "yaml" -display-name = "YAML" scope = "source.yaml" file-types = ["yml", "yaml"] roots = [] @@ -360,7 +329,6 @@ indent = { tab-width = 2, unit = " " } # [[language]] # name = "haskell" -# display-name = "Haskell" # scope = "source.haskell" # injection-regex = "haskell" # file-types = ["hs"] @@ -371,7 +339,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "zig" -display-name = "Zig" scope = "source.zig" injection-regex = "zig" file-types = ["zig"] @@ -384,7 +351,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "prolog" -display-name = "Prolog" scope = "source.prolog" roots = [] file-types = ["pl", "prolog"] @@ -398,7 +364,6 @@ language-server = { command = "swipl", args = [ [[language]] name = "tsq" -display-name = "TSQ" scope = "source.tsq" file-types = ["scm"] roots = [] @@ -407,7 +372,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "cmake" -display-name = "CMake" scope = "source.cmake" file-types = ["cmake", "CMakeLists.txt"] roots = [] @@ -417,7 +381,6 @@ language-server = { command = "cmake-language-server" } [[language]] name = "glsl" -display-name = "GLSL" scope = "source.glsl" file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ] roots = [] @@ -426,7 +389,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "perl" -display-name = "Perl" scope = "source.perl" file-types = ["pl", "pm"] shebangs = ["perl"] @@ -436,7 +398,6 @@ indent = { tab-width = 2, unit = " " } [[language]] name = "racket" -display-name = "Racket" scope = "source.rkt" roots = [] file-types = ["rkt"] @@ -446,7 +407,6 @@ language-server = { command = "racket", args = ["-l", "racket-langserver"] } [[language]] name = "wgsl" -display-name = "WGSL" scope = "source.wgsl" file-types = ["wgsl"] roots = [] @@ -455,7 +415,6 @@ indent = { tab-width = 4, unit = " " } [[language]] name = "llvm" -display-name = "LLVM" scope = "source.llvm" roots = [] file-types = ["ll"] diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 37e70592..7256653a 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -184,7 +184,7 @@ pub mod md_gen { .iter() .find(|l| l.language_id == lang) .unwrap(); // lang comes from config - row.push(lc.display_name.clone()); + row.push(lc.language_id.clone()); for (_feat, support_list) in &ts_features_to_langs { row.push( -- cgit v1.2.3-70-g09d2 From a1e64815cbffe1a35d0692c61cd59cd777a77d67 Mon Sep 17 00:00:00 2001 From: Oskar Nehlin Date: Wed, 8 Dec 2021 16:26:33 +0100 Subject: Update book to include typable command remapping (#1240) * Update book to include typable command remapping * Add additional example--- book/src/remapping.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/remapping.md b/book/src/remapping.md index ad63b60b..1cdf9b1f 100644 --- a/book/src/remapping.md +++ b/book/src/remapping.md @@ -11,6 +11,8 @@ this: ```toml # At most one section each of 'keys.normal', 'keys.insert' and 'keys.select' [keys.normal] +C-s = ":w" # Maps the Control-s to the typable command :w which is an alias for :write (save file) +C-o = ":open ~/.config/helix/config.toml" # Maps the Control-o to opening of the helix config file a = "move_char_left" # Maps the 'a' key to the move_char_left command w = "move_line_up" # Maps the 'w' key move_line_up "C-S-esc" = "extend_line" # Maps Control-Shift-Escape to extend_line @@ -21,6 +23,7 @@ g = { a = "code_action" } # Maps `ga` to show possible code actions "A-x" = "normal_mode" # Maps Alt-X to enter normal mode j = { k = "normal_mode" } # Maps `jk` to exit insert mode ``` +> NOTE: Typable commands can also be remapped, remember to keep the `:` prefix to indicate it's a typable command. Control, Shift and Alt modifiers are encoded respectively with the prefixes `C-`, `S-` and `A-`. Special keys are encoded as follows: @@ -53,4 +56,4 @@ Control, Shift and Alt modifiers are encoded respectively with the prefixes Keys can be disabled by binding them to the `no_op` command. Commands can be found at [Keymap](https://docs.helix-editor.com/keymap.html) Commands. -> Commands can also be found in the source code at [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) at the invocation of `commands!` macro. +> Commands can also be found in the source code at [`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`. -- cgit v1.2.3-70-g09d2 From b66d3d3d9dccbb9c28d8611c4a0fc5d74ccb27d6 Mon Sep 17 00:00:00 2001 From: Omnikar Date: Thu, 9 Dec 2021 21:46:24 -0500 Subject: Add `save_selection` command (#1247) --- book/src/keymap.md | 1 + helix-term/src/commands.rs | 7 +++++++ helix-term/src/keymap.rs | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index e1b1bad8..5a804c3c 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -34,6 +34,7 @@ | `Ctrl-d` | Move half page down | `half_page_down` | | `Ctrl-i` | Jump forward on the jumplist | `jump_forward` | | `Ctrl-o` | Jump backward on the jumplist | `jump_backward` | +| `Ctrl-s` | Save the current selection to the jumplist | `save_selection` | | `v` | Enter [select (extend) mode](#select--extend-mode) | `select_mode` | | `g` | Enter [goto mode](#goto-mode) | N/A | | `m` | Enter [match mode](#match-mode) | N/A | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 1f7a2275..87c5a63f 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -362,6 +362,7 @@ impl MappableCommand { expand_selection, "Expand selection to parent syntax node", jump_forward, "Jump forward on jumplist", jump_backward, "Jump backward on jumplist", + save_selection, "Save the current selection to the jumplist", jump_view_right, "Jump to the split to the right", jump_view_left, "Jump to the split to the left", jump_view_up, "Jump to the split above", @@ -5285,6 +5286,12 @@ fn jump_backward(cx: &mut Context) { }; } +fn save_selection(cx: &mut Context) { + push_jump(cx.editor); + cx.editor + .set_status("Selection saved to jumplist".to_owned()); +} + fn rotate_view(cx: &mut Context) { cx.editor.focus_next() } diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 9debbbac..b1613252 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -641,7 +641,7 @@ impl Default for Keymaps { "tab" => jump_forward, // tab == "C-o" => jump_backward, - // "C-s" => save_selection, + "C-s" => save_selection, "space" => { "Space" "f" => file_picker, -- cgit v1.2.3-70-g09d2 From e91d357fae04766b9781fe51a0809d35175fe1cf Mon Sep 17 00:00:00 2001 From: Omnikar Date: Sun, 12 Dec 2021 07:16:48 -0500 Subject: Macros (#1234) * Macros WIP `helix_term::compositor::Callback` changed to take a `&mut Context` as a parameter for use by `play_macro` * Default to `@` register for macros * Import `KeyEvent` * Special-case shift-tab -> backtab in `KeyEvent` conversion * Move key recording to the compositor * Add comment * Add persistent display of macro recording status When macro recording is active, the pending keys display will be shifted 3 characters left, and the register being recorded to will be displayed between brackets — e.g., `[@]` — right of the pending keys display. * Fix/add documentation--- book/src/keymap.md | 2 ++ helix-term/src/commands.rs | 59 ++++++++++++++++++++++++++++++++++++++++++-- helix-term/src/compositor.rs | 9 +++++-- helix-term/src/keymap.rs | 3 +++ helix-term/src/ui/editor.rs | 22 +++++++++++++++-- helix-term/src/ui/menu.rs | 2 +- helix-term/src/ui/picker.rs | 2 +- helix-term/src/ui/popup.rs | 2 +- helix-term/src/ui/prompt.rs | 2 +- helix-view/src/editor.rs | 3 +++ helix-view/src/input.rs | 20 +++++++++++++++ 11 files changed, 116 insertions(+), 10 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 5a804c3c..f0a2cb30 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -77,6 +77,8 @@ | `Alt-c` | Change selection (delete and enter insert mode, without yanking) | `change_selection_noyank` | | `Ctrl-a` | Increment object (number) under cursor | `increment` | | `Ctrl-x` | Decrement object (number) under cursor | `decrement` | +| `q` | Start/stop macro recording to the selected register | `record_macro` | +| `Q` | Play back a recorded macro from the selected register | `play_macro` | #### Shell diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 314cd11f..50554731 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -70,7 +70,7 @@ pub struct Context<'a> { impl<'a> Context<'a> { /// Push a new component onto the compositor. pub fn push_layer(&mut self, component: Box) { - self.callback = Some(Box::new(|compositor: &mut Compositor| { + self.callback = Some(Box::new(|compositor: &mut Compositor, _| { compositor.push(component) })); } @@ -395,6 +395,8 @@ impl MappableCommand { rename_symbol, "Rename symbol", increment, "Increment", decrement, "Decrement", + record_macro, "Record macro", + play_macro, "Play macro", ); } @@ -3441,7 +3443,7 @@ fn apply_workspace_edit( fn last_picker(cx: &mut Context) { // TODO: last picker does not seem to work well with buffer_picker - cx.callback = Some(Box::new(|compositor: &mut Compositor| { + cx.callback = Some(Box::new(|compositor: &mut Compositor, _| { if let Some(picker) = compositor.last_picker.take() { compositor.push(picker); } @@ -5870,3 +5872,56 @@ fn increment_impl(cx: &mut Context, amount: i64) { doc.append_changes_to_history(view.id); } } + +fn record_macro(cx: &mut Context) { + if let Some((reg, mut keys)) = cx.editor.macro_recording.take() { + // Remove the keypress which ends the recording + keys.pop(); + let s = keys + .into_iter() + .map(|key| format!("{}", key)) + .collect::>() + .join(" "); + cx.editor.registers.get_mut(reg).write(vec![s]); + cx.editor + .set_status(format!("Recorded to register {}", reg)); + } else { + let reg = cx.register.take().unwrap_or('@'); + cx.editor.macro_recording = Some((reg, Vec::new())); + cx.editor + .set_status(format!("Recording to register {}", reg)); + } +} + +fn play_macro(cx: &mut Context) { + let reg = cx.register.unwrap_or('@'); + let keys = match cx + .editor + .registers + .get(reg) + .and_then(|reg| reg.read().get(0)) + .context("Register empty") + .and_then(|s| { + s.split_whitespace() + .map(str::parse::) + .collect::, _>>() + .context("Failed to parse macro") + }) { + Ok(keys) => keys, + Err(e) => { + cx.editor.set_error(format!("{}", e)); + return; + } + }; + let count = cx.count(); + + cx.callback = Some(Box::new( + move |compositor: &mut Compositor, cx: &mut compositor::Context| { + for _ in 0..count { + for &key in keys.iter() { + compositor.handle_event(crossterm::event::Event::Key(key.into()), cx); + } + } + }, + )); +} diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs index 30554ebb..321f56a5 100644 --- a/helix-term/src/compositor.rs +++ b/helix-term/src/compositor.rs @@ -7,7 +7,7 @@ use helix_view::graphics::{CursorKind, Rect}; use crossterm::event::Event; use tui::buffer::Buffer as Surface; -pub type Callback = Box; +pub type Callback = Box; // --> EventResult should have a callback that takes a context with methods like .popup(), // .prompt() etc. That way we can abstract it from the renderer. @@ -131,12 +131,17 @@ impl Compositor { } pub fn handle_event(&mut self, event: Event, cx: &mut Context) -> bool { + // If it is a key event and a macro is being recorded, push the key event to the recording. + if let (Event::Key(key), Some((_, keys))) = (event, &mut cx.editor.macro_recording) { + keys.push(key.into()); + } + // propagate events through the layers until we either find a layer that consumes it or we // run out of layers (event bubbling) for layer in self.layers.iter_mut().rev() { match layer.handle_event(event, cx) { EventResult::Consumed(Some(callback)) => { - callback(self); + callback(self, cx); return true; } EventResult::Consumed(None) => return true, diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index b1613252..257d5f29 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -593,6 +593,9 @@ impl Default for Keymaps { // paste_all "P" => paste_before, + "q" => record_macro, + "Q" => play_macro, + ">" => indent, "<" => unindent, "=" => format_selections, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 39ee15b4..bac1f171 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1100,13 +1100,31 @@ impl Component for EditorView { disp.push_str(&s); } } + let style = cx.editor.theme.get("ui.text"); + let macro_width = if cx.editor.macro_recording.is_some() { + 3 + } else { + 0 + }; surface.set_string( - area.x + area.width.saturating_sub(key_width), + area.x + area.width.saturating_sub(key_width + macro_width), area.y + area.height.saturating_sub(1), disp.get(disp.len().saturating_sub(key_width as usize)..) .unwrap_or(&disp), - cx.editor.theme.get("ui.text"), + style, ); + if let Some((reg, _)) = cx.editor.macro_recording { + let disp = format!("[{}]", reg); + let style = style + .fg(helix_view::graphics::Color::Yellow) + .add_modifier(Modifier::BOLD); + surface.set_string( + area.x + area.width.saturating_sub(3), + area.y + area.height.saturating_sub(1), + &disp, + style, + ); + } } if let Some(completion) = self.completion.as_mut() { diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index 9a885a36..69053db3 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -190,7 +190,7 @@ impl Component for Menu { _ => return EventResult::Ignored, }; - let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { + let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| { // remove the layer compositor.pop(); }))); diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 1c963f97..1ef94df0 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -404,7 +404,7 @@ impl Component for Picker { _ => return EventResult::Ignored, }; - let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { + let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| { // remove the layer compositor.last_picker = compositor.pop(); }))); diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs index c55f030f..bf7510a2 100644 --- a/helix-term/src/ui/popup.rs +++ b/helix-term/src/ui/popup.rs @@ -100,7 +100,7 @@ impl Component for Popup { _ => return EventResult::Ignored, }; - let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { + let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| { // remove the layer compositor.pop(); }))); diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index a7ef231c..07e1b33c 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -426,7 +426,7 @@ impl Component for Prompt { _ => return EventResult::Ignored, }; - let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { + let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| { // remove the layer compositor.pop(); }))); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 9034d12c..dcbcbe4f 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -2,6 +2,7 @@ use crate::{ clipboard::{get_clipboard_provider, ClipboardProvider}, document::SCRATCH_BUFFER_NAME, graphics::{CursorKind, Rect}, + input::KeyEvent, theme::{self, Theme}, tree::{self, Tree}, Document, DocumentId, View, ViewId, @@ -160,6 +161,7 @@ pub struct Editor { pub count: Option, pub selected_register: Option, pub registers: Registers, + pub macro_recording: Option<(char, Vec)>, pub theme: Theme, pub language_servers: helix_lsp::Registry, pub clipboard_provider: Box, @@ -203,6 +205,7 @@ impl Editor { documents: BTreeMap::new(), count: None, selected_register: None, + macro_recording: None, theme: theme_loader.default(), language_servers, syn_loader, diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs index b207c3ed..92caa517 100644 --- a/helix-view/src/input.rs +++ b/helix-view/src/input.rs @@ -234,6 +234,26 @@ impl From for KeyEvent { } } +#[cfg(feature = "term")] +impl From for crossterm::event::KeyEvent { + fn from(KeyEvent { code, modifiers }: KeyEvent) -> Self { + if code == KeyCode::Tab && modifiers.contains(KeyModifiers::SHIFT) { + // special case for Shift-Tab -> BackTab + let mut modifiers = modifiers; + modifiers.remove(KeyModifiers::SHIFT); + crossterm::event::KeyEvent { + code: crossterm::event::KeyCode::BackTab, + modifiers: modifiers.into(), + } + } else { + crossterm::event::KeyEvent { + code: code.into(), + modifiers: modifiers.into(), + } + } + } +} + #[cfg(test)] mod test { use super::*; -- cgit v1.2.3-70-g09d2 From 98ce2a301da25152563137047377026d72fd644c Mon Sep 17 00:00:00 2001 From: Omnikar Date: Sun, 14 Nov 2021 07:26:48 -0500 Subject: Load alt default theme if true color is not supported * Move `runtime/themes/base16_default_terminal.toml` to `base16_theme.toml` alongside `theme.toml` * Use `terminfo` crate to detect whether the terminal supports true color and, if the user has no theme configured and their terminal does not support true color, load the alt default theme instead of the normal default. Remove `terminfo` dependency, use `COLORTERM` env instead Prevent user from switching to an unsupported theme Add `true-color-override` option If the terminal is wrongly detected to not support true color, `true-color-override = true` will override the detection. Rename `true-color-override` to `true-color` --- base16_theme.toml | 41 +++++++++++++++++++++++++++++++++++++ book/src/configuration.md | 1 + helix-term/src/application.rs | 28 +++++++++++++++++-------- helix-term/src/commands.rs | 14 +++++++++++-- helix-term/src/lib.rs | 6 ++++++ helix-term/src/ui/mod.rs | 1 + helix-view/src/editor.rs | 12 +++-------- helix-view/src/theme.rs | 20 ++++++++++++++++++ runtime/themes/base16_terminal.toml | 41 ------------------------------------- 9 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 base16_theme.toml delete mode 100644 runtime/themes/base16_terminal.toml (limited to 'book/src') diff --git a/base16_theme.toml b/base16_theme.toml new file mode 100644 index 00000000..bf3c73f1 --- /dev/null +++ b/base16_theme.toml @@ -0,0 +1,41 @@ +# Author: NNB + +"ui.menu" = "black" +"ui.menu.selected" = { fg = "white", bg = "black" } +"ui.linenr" = { fg = "light-gray", bg = "black" } +"ui.popup" = { bg = "black" } +"ui.window" = { bg = "black" } +"ui.linenr.selected" = { fg = "white", bg = "black", modifiers = ["bold"] } +"ui.selection" = { fg = "gray", modifiers = ["reversed"] } +"comment" = { fg = "light-gray", modifiers = ["italic"] } +"ui.statusline" = { fg = "white", bg = "black" } +"ui.help" = { fg = "white", bg = "black" } +"ui.cursor" = { fg = "light-gray", modifiers = ["reversed"] } +"ui.cursor.primary" = { fg = "white", modifiers = ["reversed"] } #FIXME +"ui.text" = "white" #FIXME +"operator" = "white" #FIXME +"ui.text.focus" = "white" #FIXME +"variable" = "light-red" +"constant.numeric" = "yellow" +"constant" = "yellow" +"attributes" = "yellow" +"type" = "light-yellow" +"ui.cursor.match" = { fg = "light-yellow", modifiers = ["underlined"] } +"string" = "light-green" +"variable.other.member" = "light-green" +"constant.character.escape" = "light-cyan" +"function" = "light-blue" +"constructor" = "light-blue" +"special" = "light-blue" +"keyword" = "light-magenta" +"label" = "light-magenta" +"namespace" = "light-magenta" +"ui.popup" = { bg = "black" } +"ui.window" = { bg = "base00" } +"ui.help" = { fg = "white", bg = "black" } + +"info" = "light-gray" +"hint" = "light-gray" +"debug" = "light-gray" +"diagnostic" = "light-gray" +"error" = "light-magenta" diff --git a/book/src/configuration.md b/book/src/configuration.md index 2ed48d51..33a933b2 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -23,6 +23,7 @@ To override global configuration parameters, create a `config.toml` file located | `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` | | `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` | | `auto-info` | Whether to display infoboxes | `true` | +| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. | `false` | `[editor.filepicker]` section of the config. Sets options for file picker and global search. All but the last key listed in the default file-picker configuration below are IgnoreOptions: whether hidden files and files listed within ignore files are ignored by (not visible in) the helix file picker and global search. There is also one other key, `max-depth` available, which is not defined by default. diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 90330751..3e0b6d59 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -76,17 +76,27 @@ impl Application { None => Ok(def_lang_conf), }; - let theme = if let Some(theme) = &config.theme { - match theme_loader.load(theme) { - Ok(theme) => theme, - Err(e) => { - log::warn!("failed to load theme `{}` - {}", theme, e); + let true_color = config.editor.true_color || crate::true_color(); + let theme = config + .theme + .as_ref() + .and_then(|theme| { + theme_loader + .load(theme) + .map_err(|e| { + log::warn!("failed to load theme `{}` - {}", theme, e); + e + }) + .ok() + .filter(|theme| (true_color || theme.is_16_color())) + }) + .unwrap_or_else(|| { + if true_color { theme_loader.default() + } else { + theme_loader.base16_default() } - } - } else { - theme_loader.default() - }; + }); let syn_loader_conf: helix_core::syntax::Configuration = lang_conf .and_then(|conf| conf.try_into()) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 0ae225e9..22c23043 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2366,8 +2366,18 @@ pub mod cmd { args: &[Cow], _event: PromptEvent, ) -> anyhow::Result<()> { - let theme = args.first().context("theme not provided")?; - cx.editor.set_theme_from_name(theme) + let theme = args.first().context("Theme not provided")?; + let theme = cx + .editor + .theme_loader + .load(theme) + .with_context(|| format!("Failed setting theme {}", theme))?; + let true_color = cx.editor.config.true_color || crate::true_color(); + if !(true_color || theme.is_16_color()) { + bail!("Unsupported theme: theme requires true color support"); + } + cx.editor.set_theme(theme); + Ok(()) } fn yank_main_selection_to_clipboard( diff --git a/helix-term/src/lib.rs b/helix-term/src/lib.rs index f5e3a8cd..4fe76cd5 100644 --- a/helix-term/src/lib.rs +++ b/helix-term/src/lib.rs @@ -9,3 +9,9 @@ pub mod config; pub mod job; pub mod keymap; pub mod ui; + +fn true_color() -> bool { + std::env::var("COLORTERM") + .map(|v| matches!(v.as_str(), "truecolor" | "24bit")) + .unwrap_or(false) +} diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index cdf42311..f57e2e2b 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -186,6 +186,7 @@ pub mod completers { &helix_core::config_dir().join("themes"), )); names.push("default".into()); + names.push("base16_default".into()); let mut names: Vec<_> = names .into_iter() diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index dcbcbe4f..753defa1 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -105,6 +105,8 @@ pub struct Config { /// Whether to display infoboxes. Defaults to true. pub auto_info: bool, pub file_picker: FilePickerConfig, + /// Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. Defaults to `false`. + pub true_color: bool, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)] @@ -137,6 +139,7 @@ impl Default for Config { completion_trigger_len: 2, auto_info: true, file_picker: FilePickerConfig::default(), + true_color: false, } } } @@ -265,15 +268,6 @@ impl Editor { self._refresh(); } - pub fn set_theme_from_name(&mut self, theme: &str) -> anyhow::Result<()> { - let theme = self - .theme_loader - .load(theme.as_ref()) - .with_context(|| format!("failed setting theme `{}`", theme))?; - self.set_theme(theme); - Ok(()) - } - /// Refreshes the language server for a given document pub fn refresh_language_server(&mut self, doc_id: DocumentId) -> Option<()> { let doc = self.documents.get_mut(&doc_id)?; diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 47fc6262..ddcdad99 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -15,6 +15,10 @@ pub use crate::graphics::{Color, Modifier, Style}; pub static DEFAULT_THEME: Lazy = Lazy::new(|| { toml::from_slice(include_bytes!("../../theme.toml")).expect("Failed to parse default theme") }); +pub static BASE16_DEFAULT_THEME: Lazy = Lazy::new(|| { + toml::from_slice(include_bytes!("../../base16_theme.toml")) + .expect("Failed to parse base 16 default theme") +}); #[derive(Clone, Debug)] pub struct Loader { @@ -35,6 +39,9 @@ impl Loader { if name == "default" { return Ok(self.default()); } + if name == "base16_default" { + return Ok(self.base16_default()); + } let filename = format!("{}.toml", name); let user_path = self.user_dir.join(&filename); @@ -74,6 +81,11 @@ impl Loader { pub fn default(&self) -> Theme { DEFAULT_THEME.clone() } + + /// Returns the alternative 16-color default theme + pub fn base16_default(&self) -> Theme { + BASE16_DEFAULT_THEME.clone() + } } #[derive(Clone, Debug)] @@ -154,6 +166,14 @@ impl Theme { pub fn find_scope_index(&self, scope: &str) -> Option { self.scopes().iter().position(|s| s == scope) } + + pub fn is_16_color(&self) -> bool { + self.styles.iter().all(|(_, style)| { + [style.fg, style.bg] + .into_iter() + .all(|color| !matches!(color, Some(Color::Rgb(..)))) + }) + } } struct ThemePalette { diff --git a/runtime/themes/base16_terminal.toml b/runtime/themes/base16_terminal.toml deleted file mode 100644 index bf3c73f1..00000000 --- a/runtime/themes/base16_terminal.toml +++ /dev/null @@ -1,41 +0,0 @@ -# Author: NNB - -"ui.menu" = "black" -"ui.menu.selected" = { fg = "white", bg = "black" } -"ui.linenr" = { fg = "light-gray", bg = "black" } -"ui.popup" = { bg = "black" } -"ui.window" = { bg = "black" } -"ui.linenr.selected" = { fg = "white", bg = "black", modifiers = ["bold"] } -"ui.selection" = { fg = "gray", modifiers = ["reversed"] } -"comment" = { fg = "light-gray", modifiers = ["italic"] } -"ui.statusline" = { fg = "white", bg = "black" } -"ui.help" = { fg = "white", bg = "black" } -"ui.cursor" = { fg = "light-gray", modifiers = ["reversed"] } -"ui.cursor.primary" = { fg = "white", modifiers = ["reversed"] } #FIXME -"ui.text" = "white" #FIXME -"operator" = "white" #FIXME -"ui.text.focus" = "white" #FIXME -"variable" = "light-red" -"constant.numeric" = "yellow" -"constant" = "yellow" -"attributes" = "yellow" -"type" = "light-yellow" -"ui.cursor.match" = { fg = "light-yellow", modifiers = ["underlined"] } -"string" = "light-green" -"variable.other.member" = "light-green" -"constant.character.escape" = "light-cyan" -"function" = "light-blue" -"constructor" = "light-blue" -"special" = "light-blue" -"keyword" = "light-magenta" -"label" = "light-magenta" -"namespace" = "light-magenta" -"ui.popup" = { bg = "black" } -"ui.window" = { bg = "base00" } -"ui.help" = { fg = "white", bg = "black" } - -"info" = "light-gray" -"hint" = "light-gray" -"debug" = "light-gray" -"diagnostic" = "light-gray" -"error" = "light-magenta" -- cgit v1.2.3-70-g09d2 From 9bfb701c9446416a3e6f6500871ae4025001bd7c Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 15 Dec 2021 17:38:03 +0900 Subject: Update lang-support.md --- book/src/generated/lang-support.md | 1 + 1 file changed, 1 insertion(+) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 96d9b6a0..80fb28a5 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -18,6 +18,7 @@ | ledger | ✓ | | | | | llvm | ✓ | | | | | lua | ✓ | | ✓ | | +| markdown | ✓ | | | | | mint | | | | `mint` | | nix | ✓ | | ✓ | `rnix-lsp` | | ocaml | ✓ | | ✓ | | -- cgit v1.2.3-70-g09d2 From 40969ad4528bbb774e2b95dce0749b1dd3734ebf Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 15 Dec 2021 17:46:40 +0900 Subject: Partly fix latex highlights and add markup scope docs --- book/src/themes.md | 14 ++++++++++++++ runtime/queries/latex/highlights.scm | 26 +++++++++++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index fd3f5b1e..b6de7002 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -162,6 +162,20 @@ We use a similar set of scopes as - `namespace` +- `markup` + - `heading` + - `list` + - `unnumbered` + - `numbered` + - `bold` + - `italic` + - `underline` + - `link` + - `quote` + - `raw` + - `inline` + - `block` + #### Interface These scopes are used for theming the editor interface. diff --git a/runtime/queries/latex/highlights.scm b/runtime/queries/latex/highlights.scm index f045c82d..8406bd04 100644 --- a/runtime/queries/latex/highlights.scm +++ b/runtime/queries/latex/highlights.scm @@ -318,60 +318,60 @@ ["[" "]" "{" "}"] @punctuation.bracket ;"(" ")" is has no special meaning in LaTeX (chapter - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (part - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (section - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (subsection - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (subsubsection - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (paragraph - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) (subparagraph - text: (brace_group) @text.title) + text: (brace_group) @markup.heading) ((environment (begin name: (word) @_frame) (brace_group - child: (text) @text.title)) + child: (text) @markup.heading)) (#eq? @_frame "frame")) ((generic_command name:(generic_command_name) @_name arg: (brace_group - (text) @text.title)) + (text) @markup.heading)) (#eq? @_name "\\frametitle")) ;; Formatting ((generic_command name:(generic_command_name) @_name - arg: (_) @text.emphasis) + arg: (_) @markup.italic) (#eq? @_name "\\emph")) ((generic_command name:(generic_command_name) @_name - arg: (_) @text.emphasis) + arg: (_) @markup.italic) (#match? @_name "^(\\\\textit|\\\\mathit)$")) ((generic_command name:(generic_command_name) @_name - arg: (_) @text.strong) + arg: (_) @markup.bold) (#match? @_name "^(\\\\textbf|\\\\mathbf)$")) ((generic_command name:(generic_command_name) @_name . - arg: (_) @text.uri) + arg: (_) @markup.underline.link) (#match? @_name "^(\\\\url|\\\\href)$")) (ERROR) @error -- cgit v1.2.3-70-g09d2 From a8060c06d14935d18e27fcb64b8a58ae6dc5eaf3 Mon Sep 17 00:00:00 2001 From: ath3 Date: Fri, 17 Dec 2021 01:56:07 +0100 Subject: Add indents.toml to perl (#1280) --- book/src/generated/lang-support.md | 2 +- runtime/queries/perl/indents.toml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/perl/indents.toml (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 80fb28a5..80989e63 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -23,7 +23,7 @@ | nix | ✓ | | ✓ | `rnix-lsp` | | ocaml | ✓ | | ✓ | | | ocaml-interface | ✓ | | | | -| perl | ✓ | ✓ | | | +| perl | ✓ | ✓ | ✓ | | | php | ✓ | | ✓ | | | prolog | | | | `swipl` | | protobuf | ✓ | | ✓ | | diff --git a/runtime/queries/perl/indents.toml b/runtime/queries/perl/indents.toml new file mode 100644 index 00000000..365e0663 --- /dev/null +++ b/runtime/queries/perl/indents.toml @@ -0,0 +1,17 @@ +indent = [ + "function", + "identifier", + "method_invocation", + "if_statement", + "unless_statement", + "if_simple_statement", + "unless_simple_statement", + "variable_declaration", + "block", + "list_item", + "word_list_qw" +] + +outdent = [ + "}" +] -- cgit v1.2.3-70-g09d2 From 3ef115d4203fab93f7efe4f65d8dd63cc4535b91 Mon Sep 17 00:00:00 2001 From: Chetan Vardhan Date: Fri, 17 Dec 2021 20:16:32 +0530 Subject: Add instructions for Fedora Linux (#1270) * Add instructions for Fedora Linux * Update README.md * Update install.md--- book/src/install.md | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'book/src') diff --git a/book/src/install.md b/book/src/install.md index d831934c..1a5a9daa 100644 --- a/book/src/install.md +++ b/book/src/install.md @@ -27,6 +27,15 @@ Releases are available in the `community` repository. A [helix-git](https://aur.archlinux.org/packages/helix-git/) package is also available on the AUR, which builds the master branch. +### Fedora Linux + +You can install the COPR package for Helix via + +``` +sudo dnf copr enable varlad/helix +sudo dnf install helix +``` + ## Build from source ``` -- cgit v1.2.3-70-g09d2 From 016640f4fb6f620df13a2cab15e749d623197a51 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sat, 18 Dec 2021 08:25:40 +0530 Subject: Remove ui.cursor.primary and hashmap lookups --- book/src/themes.md | 1 - helix-term/src/ui/editor.rs | 17 ++++++++--------- helix-view/src/document.rs | 6 +++--- helix-view/src/editor.rs | 36 ++++++++++++++++++++++++------------ 4 files changed, 35 insertions(+), 25 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index ecbbb6e9..6b38fb43 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -173,7 +173,6 @@ These scopes are used for theming the editor interface. | `ui.cursor.insert` | | | `ui.cursor.select` | | | `ui.cursor.match` | Matching bracket etc. | -| `ui.cursor.primary` | Cursor with primary selection | | `ui.linenr` | | | `ui.linenr.selected` | | | `ui.statusline` | Statusline | diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 8ad54dbd..e8f8fd9b 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -233,24 +233,23 @@ impl EditorView { } .unwrap_or(base_cursor_scope); - let primary_cursor_scope = theme - .find_scope_index("ui.cursor.primary") - .unwrap_or(cursor_scope); let primary_selection_scope = theme .find_scope_index("ui.selection.primary") .unwrap_or(selection_scope); let mut spans: Vec<(usize, std::ops::Range)> = Vec::new(); for (i, range) in selection.iter().enumerate() { - let (cursor_scope, selection_scope) = if i == primary_idx { - (primary_cursor_scope, primary_selection_scope) + let selection_is_primary = i == primary_idx; + let selection_scope = if selection_is_primary { + primary_selection_scope } else { - (cursor_scope, selection_scope) + selection_scope }; // Special-case: cursor at end of the rope. if range.head == range.anchor && range.head == text.len_chars() { - if i != primary_idx { + if !selection_is_primary { + // Terminal cursor acts as the primary cursor spans.push((cursor_scope, range.head..range.head + 1)); } continue; @@ -261,13 +260,13 @@ impl EditorView { // Standard case. let cursor_start = prev_grapheme_boundary(text, range.head); spans.push((selection_scope, range.anchor..cursor_start)); - if i != primary_idx { + if !selection_is_primary { spans.push((cursor_scope, cursor_start..range.head)); } } else { // Reverse case. let cursor_end = next_grapheme_boundary(text, range.head); - if i != primary_idx { + if !selection_is_primary { spans.push((cursor_scope, range.head..cursor_end)); } spans.push((selection_scope, cursor_end..range.anchor)); diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 76b19a07..01975452 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -29,9 +29,9 @@ pub const SCRATCH_BUFFER_NAME: &str = "[scratch]"; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Mode { - Normal, - Select, - Insert, + Normal = 0, + Select = 1, + Insert = 2, } impl Display for Mode { diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index b558c183..a121a836 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -22,10 +22,10 @@ use anyhow::Error; pub use helix_core::diagnostic::Severity; pub use helix_core::register::Registers; -use helix_core::{hashmap, syntax}; +use helix_core::syntax; use helix_core::{Position, Selection}; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result where @@ -107,12 +107,28 @@ pub struct Config { pub cursor_shape: CursorShapeConfig, } -#[derive(Debug, Clone, PartialEq, Deserialize)] -#[serde(transparent)] -pub struct CursorShapeConfig(HashMap); +// Cursor shape is read and used on every rendered frame and so needs +// to be fast. Therefore we avoid a hashmap and use an enum indexed array. +#[derive(Debug, Clone, PartialEq)] +pub struct CursorShapeConfig([CursorKind; 3]); + +impl<'de> Deserialize<'de> for CursorShapeConfig { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let m = HashMap::::deserialize(deserializer)?; + let into_cursor = |mode: Mode| m.get(&mode).copied().unwrap_or_default(); + Ok(CursorShapeConfig([ + into_cursor(Mode::Normal), + into_cursor(Mode::Select), + into_cursor(Mode::Insert), + ])) + } +} impl std::ops::Deref for CursorShapeConfig { - type Target = HashMap; + type Target = [CursorKind; 3]; fn deref(&self) -> &Self::Target { &self.0 @@ -121,11 +137,7 @@ impl std::ops::Deref for CursorShapeConfig { impl Default for CursorShapeConfig { fn default() -> Self { - Self(hashmap!( - Mode::Insert => CursorKind::Block, - Mode::Normal => CursorKind::Block, - Mode::Select => CursorKind::Block, - )) + Self([CursorKind::Block; 3]) } } @@ -621,7 +633,7 @@ impl Editor { let cursorkind = self .config .cursor_shape - .get(&doc.mode()) + .get(doc.mode() as usize) .copied() .unwrap_or_default(); (Some(pos), cursorkind) -- cgit v1.2.3-70-g09d2 From 0683f0a20ae1c1ce3e7788e303c468767381e6fd Mon Sep 17 00:00:00 2001 From: Oliver Hechtl Date: Sat, 18 Dec 2021 05:40:34 +0100 Subject: Add scala syntax highlights (#1278) * add partial scala syntax highlights * ran cargo xtask docgen * updated tree-sitter-scala, fixed highlights * fix comments * move identifier to the end of the highlights * add indents--- book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-scala | 2 +- languages.toml | 9 ++ runtime/queries/scala/highlights.scm | 203 +++++++++++++++++++++++++++++++ runtime/queries/scala/indents.toml | 23 ++++ runtime/queries/scala/injections.scm | 1 + 6 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/scala/highlights.scm create mode 100644 runtime/queries/scala/indents.toml create mode 100644 runtime/queries/scala/injections.scm (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 80989e63..b7babd8c 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -31,6 +31,7 @@ | racket | | | | `racket` | | ruby | ✓ | | | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | +| scala | ✓ | | | `metals` | | svelte | ✓ | | ✓ | `svelteserver` | | toml | ✓ | | | | | tsq | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-scala b/helix-syntax/languages/tree-sitter-scala index fb23ed9a..0a3dd53a 160000 --- a/helix-syntax/languages/tree-sitter-scala +++ b/helix-syntax/languages/tree-sitter-scala @@ -1 +1 @@ -Subproject commit fb23ed9a99da012d86b7a5059b9d8928607cce29 +Subproject commit 0a3dd53a7fc4b352a538397d054380aaa28be54c diff --git a/languages.toml b/languages.toml index abb94acf..88882f3e 100644 --- a/languages.toml +++ b/languages.toml @@ -430,3 +430,12 @@ file-types = ["md"] roots = [] indent = { tab-width = 2, unit = " " } + +[[language]] +name = "scala" +scope = "source.scala" +roots = ["build.sbt"] +file-types = ["scala", "sbt"] +comment-token = "//" +indent = { tab-width = 2, unit = " " } +language-server = { command = "metals" } diff --git a/runtime/queries/scala/highlights.scm b/runtime/queries/scala/highlights.scm new file mode 100644 index 00000000..50a6e18a --- /dev/null +++ b/runtime/queries/scala/highlights.scm @@ -0,0 +1,203 @@ +; CREDITS @stumash (stuart.mashaal@gmail.com) + +;; variables + + +((identifier) @variable.builtin + (#match? @variable.builtin "^this$")) + +(interpolation) @none + +; Assume other uppercase names constants. +; NOTE: In order to distinguish constants we highlight +; all the identifiers that are uppercased. But this solution +; is not suitable for all occurrences e.g. it will highlight +; an uppercased method as a constant if used with no params. +; Introducing highlighting for those specific cases, is probably +; best way to resolve the issue. +((identifier) @constant (#match? @constant "^[A-Z]")) + +;; types + +(type_identifier) @type + +(class_definition + name: (identifier) @type) + +(object_definition + name: (identifier) @type) + +(trait_definition + name: (identifier) @type) + +(type_definition + name: (type_identifier) @type) + +; method definition + +(class_definition + body: (template_body + (function_definition + name: (identifier) @function.method))) +(object_definition + body: (template_body + (function_definition + name: (identifier) @function.method))) +(trait_definition + body: (template_body + (function_definition + name: (identifier) @function.method))) + +; imports + +(import_declaration + path: (identifier) @namespace) +((stable_identifier (identifier) @namespace)) + +((import_declaration + path: (identifier) @type) (#match? @type "^[A-Z]")) +((stable_identifier (identifier) @type) (#match? @type "^[A-Z]")) + +((import_selectors (identifier) @type) (#match? @type "^[A-Z]")) + +; method invocation + + +(call_expression + function: (identifier) @function) + +(call_expression + function: (field_expression + field: (identifier) @function.method)) + +((call_expression + function: (identifier) @variable.other.member) + (#match? @variable.other.member "^[A-Z]")) + +(generic_function + function: (identifier) @function) + +( + (identifier) @function.builtin + (#match? @function.builtin "^super$") +) + +; function definitions + +(function_definition + name: (identifier) @function) + +(parameter + name: (identifier) @variable.parameter) + +; expressions + + +(field_expression field: (identifier) @variable.other.member) +(field_expression value: (identifier) @type + (#match? @type "^[A-Z]")) + +(infix_expression operator: (identifier) @operator) +(infix_expression operator: (operator_identifier) @operator) +(infix_type operator: (operator_identifier) @operator) +(infix_type operator: (operator_identifier) @operator) + +; literals +(boolean_literal) @constant.builtin.boolean +(integer_literal) @constant.numeric.integer +(floating_point_literal) @constant.numeric.float + + +(symbol_literal) @string.special.symbol + +[ +(string) +(character_literal) +(interpolated_string_expression) +] @string + +(interpolation "$" @punctuation.special) + +;; keywords + +[ + "abstract" + "case" + "class" + "extends" + "final" + "finally" +;; `forSome` existential types not implemented yet + "implicit" + "lazy" +;; `macro` not implemented yet + "object" + "override" + "package" + "private" + "protected" + "sealed" + "trait" + "type" + "val" + "var" + "with" +] @keyword + +(null_literal) @constant.builtin +(wildcard) @keyword + +;; special keywords + +"new" @keyword.operator + +[ + "else" + "if" + "match" + "try" + "catch" + "throw" +] @keyword.control.conditional + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "." + "," +] @punctuation.delimiter + +[ + "do" + "for" + "while" + "yield" +] @keyword.control.repeat + +"def" @keyword.function + +[ + "=>" + "<-" + "@" +] @keyword.operator + +"import" @keyword.control.import + +"return" @keyword.control.return + +(comment) @comment + +;; `case` is a conditional keyword in case_block + +(case_block + (case_clause ("case") @keyword.control.conditional)) + +(identifier) @variable \ No newline at end of file diff --git a/runtime/queries/scala/indents.toml b/runtime/queries/scala/indents.toml new file mode 100644 index 00000000..6de54844 --- /dev/null +++ b/runtime/queries/scala/indents.toml @@ -0,0 +1,23 @@ + +indent = [ + "block", + "arguments", + "parameter", + "class_definition", + "trait_definition", + "object_definition", + "function_definition", + "val_definition", + "import_declaration", + "while_expression", + "do_while_expression", + "for_expression", + "try_expression", + "match_expression" +] + +outdent = [ + "}", + "]", + ")" +] diff --git a/runtime/queries/scala/injections.scm b/runtime/queries/scala/injections.scm new file mode 100644 index 00000000..4bb7d675 --- /dev/null +++ b/runtime/queries/scala/injections.scm @@ -0,0 +1 @@ +(comment) @comment -- cgit v1.2.3-70-g09d2 From a66833590c7dc87b5e015266bace900d46b98b34 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Sat, 18 Dec 2021 13:42:41 +0900 Subject: cargo xtask docgen --- book/src/generated/lang-support.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index b7babd8c..3255b9af 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -6,6 +6,7 @@ | cmake | ✓ | | | `cmake-language-server` | | cpp | ✓ | | | `clangd` | | css | ✓ | | | | +| dart | ✓ | | ✓ | `dart` | | elixir | ✓ | | | `elixir-ls` | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | @@ -31,7 +32,7 @@ | racket | | | | `racket` | | ruby | ✓ | | | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | -| scala | ✓ | | | `metals` | +| scala | ✓ | | ✓ | `metals` | | svelte | ✓ | | ✓ | `svelteserver` | | toml | ✓ | | | | | tsq | ✓ | | | | -- cgit v1.2.3-70-g09d2 From f174d27d0d1ab5d981c6902a54035db4ffde839f Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 18 Dec 2021 22:58:17 +0800 Subject: Change text for gg to explain gg (#1287) --- book/src/keymap.md | 2 +- helix-term/src/commands.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index f0a2cb30..d84b17b8 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -161,7 +161,7 @@ Jumps to various locations. | Key | Description | Command | | ----- | ----------- | ------- | -| `g` | Go to the start of the file | `goto_file_start` | +| `g` | Go to line number `` else start of file | `goto_file_start` | | `e` | Go to the end of the file | `goto_last_line` | | `f` | Go to files in the selection | `goto_file` | | `h` | Go to the start of the line | `goto_line_start` | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 48dccff2..28f955eb 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -287,7 +287,7 @@ impl MappableCommand { add_newline_below, "Add newline below", goto_type_definition, "Goto type definition", goto_implementation, "Goto implementation", - goto_file_start, "Goto file start/line", + goto_file_start, "Goto line number else file start", goto_file_end, "Goto file end", goto_file, "Goto files in selection", goto_file_hsplit, "Goto files in selection (hsplit)", -- cgit v1.2.3-70-g09d2 From 7c01d926536bcaacc92bbf4a2b1a06e96e6268a0 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sun, 19 Dec 2021 00:05:43 +0530 Subject: Add link and quote queries for markdown - Rename markup.underline.link to markup.link.url - Add markup.link.label - Add markup.quote (The constructor theme scope was missing from the docs, so unrelated to this commit). --- book/src/themes.md | 6 ++++-- runtime/queries/latex/highlights.scm | 2 +- runtime/queries/markdown/highlights.scm | 7 ++++--- runtime/queries/svelte/highlights.scm | 4 ++-- theme.toml | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index b6de7002..fce2c0ca 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -105,6 +105,7 @@ We use a similar set of scopes as - `type` - Types - `builtin` - Primitive types provided by the language (`int`, `usize`) +- `constructor` - `constant` (TODO: constant.other.placeholder for %v) - `builtin` Special constants provided by the language (`true`, `false`, `nil` etc) @@ -169,8 +170,9 @@ We use a similar set of scopes as - `numbered` - `bold` - `italic` - - `underline` - - `link` + - `link` + - `url` + - `label` - `quote` - `raw` - `inline` diff --git a/runtime/queries/latex/highlights.scm b/runtime/queries/latex/highlights.scm index 2e308f77..0a030b31 100644 --- a/runtime/queries/latex/highlights.scm +++ b/runtime/queries/latex/highlights.scm @@ -371,7 +371,7 @@ ((generic_command name:(generic_command_name) @_name . - arg: (_) @markup.underline.link) + arg: (_) @markup.link.url) (#match? @_name "^(\\\\url|\\\\href)$")) (ERROR) @error diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm index a102719b..a0bd3462 100644 --- a/runtime/queries/markdown/highlights.scm +++ b/runtime/queries/markdown/highlights.scm @@ -10,15 +10,16 @@ (fenced_code_block) ] @markup.raw.block +(block_quote) @markup.quote + (code_span) @markup.raw.inline (emphasis) @markup.italic (strong_emphasis) @markup.bold -(link_destination) @markup.underline.link - -; (link_label) @markup.label ; TODO: rename +(link_destination) @markup.link.url +(link_label) @markup.link.label [ (list_marker_plus) diff --git a/runtime/queries/svelte/highlights.scm b/runtime/queries/svelte/highlights.scm index f9eef6b5..22b0c551 100644 --- a/runtime/queries/svelte/highlights.scm +++ b/runtime/queries/svelte/highlights.scm @@ -20,12 +20,12 @@ ((element (start_tag (tag_name) @_tag) (text) @markup.inline) (#match? @_tag "^(code|kbd)$")) -((element (start_tag (tag_name) @_tag) (text) @markup.underline.link) +((element (start_tag (tag_name) @_tag) (text) @markup.link.url) (#eq? @_tag "a")) ((attribute (attribute_name) @_attr - (quoted_attribute_value (attribute_value) @markup.underline.link)) + (quoted_attribute_value (attribute_value) @markup.link.url)) (#match? @_attr "^(href|src)$")) (tag_name) @tag diff --git a/theme.toml b/theme.toml index 0a79861e..b316e814 100644 --- a/theme.toml +++ b/theme.toml @@ -31,7 +31,7 @@ label = "honey" "markup.heading" = "lilac" "markup.bold" = { modifiers = ["bold"] } "markup.italic" = { modifiers = ["italic"] } -"markup.underline.link" = { fg = "silver", modifiers = ["underlined"] } +"markup.link.url" = { fg = "silver", modifiers = ["underlined"] } "markup.raw" = "almond" # TODO: diferentiate doc comment -- cgit v1.2.3-70-g09d2 From e72786df8eae5684c0330be18f190a33f516da76 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Sun, 19 Dec 2021 08:56:56 -0600 Subject: Add tree-sitter-comment (#1300) * Add tree-sitter-comment Fix #1164 * fix precedence in tree-sitter-comment highlights connects https://github.com/helix-editor/helix/pull/1170 * set injection-regex for comment language * remove comment filetype * fix comment injections for neovim-style injections tags * add comment injections for elixir * remove f.comment * fix spacing in .gitmodules * run 'cargo xtask docgen' Co-authored-by: Ivan Tham --- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-comment | 1 + languages.toml | 9 ++++++++- runtime/queries/comment/highlights.scm | 30 ++++++++++++++++++++++++++++++ runtime/queries/elixir/injections.scm | 2 ++ runtime/queries/glsl/injections.scm | 6 ++++-- runtime/queries/julia/injections.scm | 8 +++++--- runtime/queries/ledger/injections.scm | 4 ++-- runtime/queries/python/injections.scm | 2 ++ runtime/queries/rust/injections.scm | 3 +++ runtime/queries/svelte/injections.scm | 4 ++-- runtime/queries/tsq/injections.scm | 2 ++ 13 files changed, 66 insertions(+), 10 deletions(-) create mode 160000 helix-syntax/languages/tree-sitter-comment create mode 100644 runtime/queries/comment/highlights.scm create mode 100644 runtime/queries/elixir/injections.scm create mode 100644 runtime/queries/python/injections.scm create mode 100644 runtime/queries/tsq/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index a899c778..c7b81336 100644 --- a/.gitmodules +++ b/.gitmodules @@ -142,6 +142,10 @@ path = helix-syntax/languages/tree-sitter-perl url = https://github.com/ganezdragon/tree-sitter-perl shallow = true +[submodule "helix-syntax/languages/tree-sitter-comment"] + path = helix-syntax/languages/tree-sitter-comment + url = https://github.com/stsewd/tree-sitter-comment + shallow = true [submodule "helix-syntax/languages/tree-sitter-wgsl"] path = helix-syntax/languages/tree-sitter-wgsl url = https://github.com/szebniok/tree-sitter-wgsl diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 3255b9af..cb91872b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -4,6 +4,7 @@ | c | ✓ | | | `clangd` | | c-sharp | ✓ | | | | | cmake | ✓ | | | `cmake-language-server` | +| comment | ✓ | | | | | cpp | ✓ | | | `clangd` | | css | ✓ | | | | | dart | ✓ | | ✓ | `dart` | diff --git a/helix-syntax/languages/tree-sitter-comment b/helix-syntax/languages/tree-sitter-comment new file mode 160000 index 00000000..5dd3c62f --- /dev/null +++ b/helix-syntax/languages/tree-sitter-comment @@ -0,0 +1 @@ +Subproject commit 5dd3c62f1bbe378b220fe16b317b85247898639e diff --git a/languages.toml b/languages.toml index 5c2bc8bb..0695022e 100644 --- a/languages.toml +++ b/languages.toml @@ -406,6 +406,13 @@ shebangs = ["racket"] comment-token = ";" language-server = { command = "racket", args = ["-l", "racket-langserver"] } +[[language]] +name = "comment" +scope = "scope.comment" +roots = [] +file-types = [] +injection-regex = "comment" + [[language]] name = "wgsl" scope = "source.wgsl" @@ -448,4 +455,4 @@ roots = ["build.sbt"] file-types = ["scala", "sbt"] comment-token = "//" indent = { tab-width = 2, unit = " " } -language-server = { command = "metals" } \ No newline at end of file +language-server = { command = "metals" } diff --git a/runtime/queries/comment/highlights.scm b/runtime/queries/comment/highlights.scm new file mode 100644 index 00000000..88685d59 --- /dev/null +++ b/runtime/queries/comment/highlights.scm @@ -0,0 +1,30 @@ +[ + "(" + ")" +] @punctuation.bracket + +":" @punctuation.delimiter + +((tag (name) @warning) + (#match? @warning "^(TODO|HACK|WARNING)$")) + +("text" @warning + (#match? @warning "^(TODO|HACK|WARNING)$")) + +((tag (name) @error) + (match? @error "^(FIXME|XXX|BUG)$")) + +("text" @error + (match? @error "^(FIXME|XXX|BUG)$")) + +(tag + (name) @ui.text + (user)? @constant) + +; Issue number (#123) +("text" @constant.numeric + (#match? @constant.numeric "^#[0-9]+$")) + +; User mention (@user) +("text" @tag + (#match? @tag "^[@][a-zA-Z0-9_-]+$")) diff --git a/runtime/queries/elixir/injections.scm b/runtime/queries/elixir/injections.scm new file mode 100644 index 00000000..321c90ad --- /dev/null +++ b/runtime/queries/elixir/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/glsl/injections.scm b/runtime/queries/glsl/injections.scm index 7d3323b1..b01b8b4b 100644 --- a/runtime/queries/glsl/injections.scm +++ b/runtime/queries/glsl/injections.scm @@ -1,3 +1,5 @@ -(preproc_arg) @glsl +((preproc_arg) @injection.content + (#set! injection.language "glsl")) -(comment) @comment +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/julia/injections.scm b/runtime/queries/julia/injections.scm index be2412c0..3cf7339f 100644 --- a/runtime/queries/julia/injections.scm +++ b/runtime/queries/julia/injections.scm @@ -1,5 +1,7 @@ ; TODO: re-add when markdown is added. -; ((triple_string) @markdown -; (#offset! @markdown 0 3 0 -3)) +; ((triple_string) @injection.content +; (#offset! @injection.content 0 3 0 -3) +; (#set! injection.language "markdown")) -(comment) @comment +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/ledger/injections.scm b/runtime/queries/ledger/injections.scm index 2d948141..c1714786 100644 --- a/runtime/queries/ledger/injections.scm +++ b/runtime/queries/ledger/injections.scm @@ -1,2 +1,2 @@ -(comment) @comment -(note) @comment +([(comment) (note)] @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/python/injections.scm b/runtime/queries/python/injections.scm new file mode 100644 index 00000000..321c90ad --- /dev/null +++ b/runtime/queries/python/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/rust/injections.scm b/runtime/queries/rust/injections.scm index 6035d418..d8382e49 100644 --- a/runtime/queries/rust/injections.scm +++ b/runtime/queries/rust/injections.scm @@ -1,3 +1,6 @@ +([(line_comment) (block_comment)] @injection.content + (#set! injection.language "comment")) + ((macro_invocation (token_tree) @injection.content) (#set! injection.language "rust") diff --git a/runtime/queries/svelte/injections.scm b/runtime/queries/svelte/injections.scm index 266f4701..04e860cf 100644 --- a/runtime/queries/svelte/injections.scm +++ b/runtime/queries/svelte/injections.scm @@ -26,5 +26,5 @@ (#set! injection.language "typescript") ) -(comment) @comment - +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/tsq/injections.scm b/runtime/queries/tsq/injections.scm new file mode 100644 index 00000000..321c90ad --- /dev/null +++ b/runtime/queries/tsq/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) -- cgit v1.2.3-70-g09d2 From 205dc8776b6ff4f5ab331df9c33b33e44caab12c Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Tue, 21 Dec 2021 03:02:53 +0100 Subject: Add fish highlighting (#1308) The highlights were copied and modified from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/fish/highlights.scm--- .gitmodules | 4 + book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-fish | 1 + languages.toml | 11 +++ runtime/queries/fish/highlights.scm | 156 ++++++++++++++++++++++++++++++++ runtime/queries/fish/indents.toml | 12 +++ runtime/queries/fish/injections.scm | 2 + runtime/queries/fish/textobjects.scm | 1 + 8 files changed, 188 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-fish create mode 100644 runtime/queries/fish/highlights.scm create mode 100644 runtime/queries/fish/indents.toml create mode 100644 runtime/queries/fish/injections.scm create mode 100644 runtime/queries/fish/textobjects.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index c7b81336..dcec2813 100644 --- a/.gitmodules +++ b/.gitmodules @@ -162,3 +162,7 @@ path = helix-syntax/languages/tree-sitter-dart url = https://github.com/UserNobody14/tree-sitter-dart.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-fish"] + path = helix-syntax/languages/tree-sitter-fish + url = https://github.com/ram02z/tree-sitter-fish + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index cb91872b..24b75b64 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -9,6 +9,7 @@ | css | ✓ | | | | | dart | ✓ | | ✓ | `dart` | | elixir | ✓ | | | `elixir-ls` | +| fish | ✓ | ✓ | ✓ | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-fish b/helix-syntax/languages/tree-sitter-fish new file mode 160000 index 00000000..04e54ab6 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-fish @@ -0,0 +1 @@ +Subproject commit 04e54ab6585dfd4fee6ddfe5849af56f101b6d4f diff --git a/languages.toml b/languages.toml index 0695022e..61eb47ec 100644 --- a/languages.toml +++ b/languages.toml @@ -45,6 +45,17 @@ comment-token = "#" language-server = { command = "elixir-ls" } indent = { tab-width = 2, unit = " " } +[[language]] +name = "fish" +scope = "source.fish" +injection-regex = "fish" +file-types = ["fish"] +shebangs = ["fish"] +roots = [] +comment-token = "#" + +indent = { tab-width = 4, unit = " " } + [[language]] name = "mint" scope = "source.mint" diff --git a/runtime/queries/fish/highlights.scm b/runtime/queries/fish/highlights.scm new file mode 100644 index 00000000..def53931 --- /dev/null +++ b/runtime/queries/fish/highlights.scm @@ -0,0 +1,156 @@ +;; Operators + +[ + "&&" + "||" + "|" + "&" + "=" + "!=" + ".." + "!" + (direction) + (stream_redirect) + (test_option) +] @operator + +[ + "not" + "and" + "or" +] @keyword.operator + +;; Conditionals + +(if_statement +[ + "if" + "end" +] @keyword.control.conditional) + +(switch_statement +[ + "switch" + "end" +] @keyword.control.conditional) + +(case_clause +[ + "case" +] @keyword.control.conditional) + +(else_clause +[ + "else" +] @keyword.control.conditional) + +(else_if_clause +[ + "else" + "if" +] @keyword.control.conditional) + +;; Loops/Blocks + +(while_statement +[ + "while" + "end" +] @keyword.control.repeat) + +(for_statement +[ + "for" + "end" +] @keyword.control.repeat) + +(begin_statement +[ + "begin" + "end" +] @keyword.control.repeat) + +;; Keywords + +[ + "in" + (break) + (continue) +] @keyword + +"return" @keyword.control.return + +;; Punctuation + +[ + "[" + "]" + "{" + "}" + "(" + ")" +] @punctuation.bracket + +"," @punctuation.delimiter + +;; Commands + +(command + argument: [ + (word) @variable.parameter (#match? @variable.parameter "^-") + ] +) + +; non-bultin command names +(command name: (word) @function) + +; derived from builtin -n (fish 3.2.2) +(command + name: [ + (word) @function.builtin + (#match? @function.builtin "^(\.|:|_|alias|argparse|bg|bind|block|breakpoint|builtin|cd|command|commandline|complete|contains|count|disown|echo|emit|eval|exec|exit|fg|functions|history|isatty|jobs|math|printf|pwd|random|read|realpath|set|set_color|source|status|string|test|time|type|ulimit|wait)$") + ] +) + +(test_command "test" @function.builtin) + +;; Functions + +(function_definition ["function" "end"] @keyword.function) + +(function_definition + name: [ + (word) (concatenation) + ] +@function) + +(function_definition + option: [ + (word) + (concatenation (word)) + ] @variable.parameter (#match? @variable.parameter "^-") +) + +;; Strings + +[(double_quote_string) (single_quote_string)] @string +(escape_sequence) @constant.character.escape + +;; Variables + +(variable_name) @variable +(variable_expansion) @constant + +;; Nodes + +(integer) @constant.numeric.integer +(float) @constant.numeric.float +(comment) @comment +(test_option) @string + +((word) @constant.builtin.boolean +(#match? @constant.builtin.boolean "^(true|false)$")) + +;; Error + +(ERROR) @error diff --git a/runtime/queries/fish/indents.toml b/runtime/queries/fish/indents.toml new file mode 100644 index 00000000..6f1e563a --- /dev/null +++ b/runtime/queries/fish/indents.toml @@ -0,0 +1,12 @@ +indent = [ + "function_definition", + "while_statement", + "for_statement", + "if_statement", + "begin_statement", + "switch_statement", +] + +outdent = [ + "end" +] diff --git a/runtime/queries/fish/injections.scm b/runtime/queries/fish/injections.scm new file mode 100644 index 00000000..321c90ad --- /dev/null +++ b/runtime/queries/fish/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/fish/textobjects.scm b/runtime/queries/fish/textobjects.scm new file mode 100644 index 00000000..67fd6614 --- /dev/null +++ b/runtime/queries/fish/textobjects.scm @@ -0,0 +1 @@ +(function_definition) @function.around -- cgit v1.2.3-70-g09d2 From 176fbe760a56945089de9f77e06f05f1639ba9be Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 21 Dec 2021 07:33:44 +0530 Subject: docs: Add note about tree-sitter query precedence (#1314) --- book/src/guides/adding_languages.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/guides/adding_languages.md b/book/src/guides/adding_languages.md index 9ad2c285..987ad088 100644 --- a/book/src/guides/adding_languages.md +++ b/book/src/guides/adding_languages.md @@ -42,7 +42,16 @@ These are the available keys and descriptions for the file. ## Queries -For a language to have syntax-highlighting and indentation among other things, you have to add queries. Add a directory for your language with the path `runtime/queries//`. The tree-sitter [website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries) gives more info on how to write queries. +For a language to have syntax-highlighting and indentation among +other things, you have to add queries. Add a directory for your +language with the path `runtime/queries//`. The tree-sitter +[website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries) +gives more info on how to write queries. + +> NOTE: When evaluating queries, the first matching query takes +precedence, which is different from other editors like neovim where +the last matching query supercedes the ones before it. See +[this issue][neovim-query-precedence] for an example. ## Common Issues @@ -58,3 +67,4 @@ For a language to have syntax-highlighting and indentation among other things, y [treesitter-language-injection]: https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection [languages.toml]: https://github.com/helix-editor/helix/blob/master/languages.toml +[neovim-query-precedence]: https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090 -- cgit v1.2.3-70-g09d2 From dba22c60ed7fc336ad619b1246333f0116b47bcd Mon Sep 17 00:00:00 2001 From: Midnight Exigent Date: Tue, 21 Dec 2021 10:22:15 +0100 Subject: Support dockerfiles (#1303) * allow language.config (in languages.toml) to be passed in as a toml object * Change config field for languages from json string to toml object * remove indents on languages.toml config * fix: remove patch version from serde_json import in helix-core * Use same tree-sitter-zig as upstream/master * fix(completion_popup): Fixes #1256 * Update helix-term/src/ui/completion.rs * feat(languages): Add support for `Dockerfile`s * docs(cargo-xtask-docgen): * improvement(langs-dockerfile): Add `injection-regex` to `languages.toml` for `Dockerfile` * improvement(langs-dockerfile): Add injections.scm * Update .gitmodules Co-authored-by: Blaž Hrastnik --- .gitmodules | 4 +++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-dockerfile | 1 + languages.toml | 11 ++++++ runtime/queries/dockerfile/highlights.scm | 51 +++++++++++++++++++++++++++ runtime/queries/dockerfile/injections.scm | 6 ++++ 6 files changed, 74 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-dockerfile create mode 100644 runtime/queries/dockerfile/highlights.scm create mode 100644 runtime/queries/dockerfile/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index dcec2813..edfe3c39 100644 --- a/.gitmodules +++ b/.gitmodules @@ -162,6 +162,10 @@ path = helix-syntax/languages/tree-sitter-dart url = https://github.com/UserNobody14/tree-sitter-dart.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-dockerfile"] + path = helix-syntax/languages/tree-sitter-dockerfile + url = https://github.com/camdencheek/tree-sitter-dockerfile.git + shallow = true [submodule "helix-syntax/languages/tree-sitter-fish"] path = helix-syntax/languages/tree-sitter-fish url = https://github.com/ram02z/tree-sitter-fish diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 24b75b64..c7054201 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -8,6 +8,7 @@ | cpp | ✓ | | | `clangd` | | css | ✓ | | | | | dart | ✓ | | ✓ | `dart` | +| dockerfile | ✓ | | | `docker-langserver` | | elixir | ✓ | | | `elixir-ls` | | fish | ✓ | ✓ | ✓ | | | glsl | ✓ | | ✓ | | diff --git a/helix-syntax/languages/tree-sitter-dockerfile b/helix-syntax/languages/tree-sitter-dockerfile new file mode 160000 index 00000000..7af32bc0 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-dockerfile @@ -0,0 +1 @@ +Subproject commit 7af32bc04a66ab196f5b9f92ac471f29372ae2ce diff --git a/languages.toml b/languages.toml index 61eb47ec..50c6f7f9 100644 --- a/languages.toml +++ b/languages.toml @@ -467,3 +467,14 @@ file-types = ["scala", "sbt"] comment-token = "//" indent = { tab-width = 2, unit = " " } language-server = { command = "metals" } + +[[language]] +name = "dockerfile" +scope = "source.dockerfile" +injection-regex = "docker|dockerfile" +roots = ["Dockerfile"] +file-types = ["Dockerfile"] +comment-token = "#" +indent = { tab-width = 2, unit = " " } +language-server = { command = "docker-langserver", args = ["--stdio"] } + diff --git a/runtime/queries/dockerfile/highlights.scm b/runtime/queries/dockerfile/highlights.scm new file mode 100644 index 00000000..5a945fb9 --- /dev/null +++ b/runtime/queries/dockerfile/highlights.scm @@ -0,0 +1,51 @@ +[ + "FROM" + "AS" + "RUN" + "CMD" + "LABEL" + "EXPOSE" + "ENV" + "ADD" + "COPY" + "ENTRYPOINT" + "VOLUME" + "USER" + "WORKDIR" + "ARG" + "ONBUILD" + "STOPSIGNAL" + "HEALTHCHECK" + "SHELL" + "MAINTAINER" + "CROSS_BUILD" +] @keyword + +[ + ":" + "@" +] @operator + +(comment) @comment + + +(image_spec + (image_tag + ":" @punctuation.special) + (image_digest + "@" @punctuation.special)) + +(double_quoted_string) @string + +(expansion + [ + "$" + "{" + "}" + ] @punctuation.special +) @none + +((variable) @constant + (#match? @constant "^[A-Z][A-Z_0-9]*$")) + + diff --git a/runtime/queries/dockerfile/injections.scm b/runtime/queries/dockerfile/injections.scm new file mode 100644 index 00000000..20396f1a --- /dev/null +++ b/runtime/queries/dockerfile/injections.scm @@ -0,0 +1,6 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +([(shell_command) (shell_fragment)] @injection.content + (#set! injection.language "bash")) + -- cgit v1.2.3-70-g09d2 From c0bbadcaaf42698d102fa03f6f9267021f3efec0 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Thu, 23 Dec 2021 11:56:52 +0530 Subject: Manually draw all block cursors --- book/src/themes.md | 1 + helix-syntax/languages/tree-sitter-scala | 2 +- helix-term/src/ui/editor.rs | 41 +++++++++++++++++++++----------- helix-view/src/editor.rs | 13 +++++----- 4 files changed, 36 insertions(+), 21 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index 40c14781..b6de7002 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -188,6 +188,7 @@ These scopes are used for theming the editor interface. | `ui.cursor.insert` | | | `ui.cursor.select` | | | `ui.cursor.match` | Matching bracket etc. | +| `ui.cursor.primary` | Cursor with primary selection | | `ui.linenr` | | | `ui.linenr.selected` | | | `ui.statusline` | Statusline | diff --git a/helix-syntax/languages/tree-sitter-scala b/helix-syntax/languages/tree-sitter-scala index fb23ed9a..0a3dd53a 160000 --- a/helix-syntax/languages/tree-sitter-scala +++ b/helix-syntax/languages/tree-sitter-scala @@ -1 +1 @@ -Subproject commit fb23ed9a99da012d86b7a5059b9d8928607cce29 +Subproject commit 0a3dd53a7fc4b352a538397d054380aaa28be54c diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 7d57e581..6b015171 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -17,6 +17,7 @@ use helix_core::{ }; use helix_view::{ document::{Mode, SCRATCH_BUFFER_NAME}, + editor::CursorShapeConfig, graphics::{CursorKind, Modifier, Rect, Style}, info::Info, input::KeyEvent, @@ -79,7 +80,7 @@ impl EditorView { let highlights: Box> = if is_focused { Box::new(syntax::merge( highlights, - Self::doc_selection_highlights(doc, view, theme), + Self::doc_selection_highlights(doc, view, theme, &config.cursor_shape), )) } else { Box::new(highlights) @@ -213,11 +214,16 @@ impl EditorView { doc: &Document, view: &View, theme: &Theme, + cursor_shape_config: &CursorShapeConfig, ) -> Vec<(usize, std::ops::Range)> { let text = doc.text().slice(..); let selection = doc.selection(view.id); let primary_idx = selection.primary_index(); + let mode = doc.mode(); + let cursorkind = cursor_shape_config.from_mode(mode); + let cursor_is_block = cursorkind == CursorKind::Block; + let selection_scope = theme .find_scope_index("ui.selection") .expect("could not find `ui.selection` scope in the theme!"); @@ -225,13 +231,16 @@ impl EditorView { .find_scope_index("ui.cursor") .unwrap_or(selection_scope); - let cursor_scope = match doc.mode() { + let cursor_scope = match mode { Mode::Insert => theme.find_scope_index("ui.cursor.insert"), Mode::Select => theme.find_scope_index("ui.cursor.select"), Mode::Normal => Some(base_cursor_scope), } .unwrap_or(base_cursor_scope); + let primary_cursor_scope = theme + .find_scope_index("ui.cursor.primary") + .unwrap_or(cursor_scope); let primary_selection_scope = theme .find_scope_index("ui.selection.primary") .unwrap_or(selection_scope); @@ -239,16 +248,20 @@ impl EditorView { let mut spans: Vec<(usize, std::ops::Range)> = Vec::new(); for (i, range) in selection.iter().enumerate() { let selection_is_primary = i == primary_idx; - let selection_scope = if selection_is_primary { - primary_selection_scope + let (cursor_scope, selection_scope) = if selection_is_primary { + (primary_cursor_scope, primary_selection_scope) } else { - selection_scope + (cursor_scope, selection_scope) }; // Special-case: cursor at end of the rope. if range.head == range.anchor && range.head == text.len_chars() { - if !selection_is_primary { - // Terminal cursor acts as the primary cursor + if !selection_is_primary || cursor_is_block { + // Bar and underline cursors are drawn by the terminal + // BUG: If the editor area loses focus while having a bar or + // underline cursor (eg. when a regex prompt has focus) then + // the primary cursor will be invisible. This doesn't happen + // with block cursors since we manually draw *all* cursors. spans.push((cursor_scope, range.head..range.head + 1)); } continue; @@ -259,13 +272,13 @@ impl EditorView { // Standard case. let cursor_start = prev_grapheme_boundary(text, range.head); spans.push((selection_scope, range.anchor..cursor_start)); - if !selection_is_primary { + if !selection_is_primary || cursor_is_block { spans.push((cursor_scope, cursor_start..range.head)); } } else { // Reverse case. let cursor_end = next_grapheme_boundary(text, range.head); - if !selection_is_primary { + if !selection_is_primary || cursor_is_block { spans.push((cursor_scope, range.head..cursor_end)); } spans.push((selection_scope, cursor_end..range.anchor)); @@ -1140,11 +1153,11 @@ impl Component for EditorView { } fn cursor(&self, _area: Rect, editor: &Editor) -> (Option, CursorKind) { - // match view.doc.mode() { - // Mode::Insert => write!(stdout, "\x1B[6 q"), - // mode => write!(stdout, "\x1B[2 q"), - // }; - editor.cursor() + match editor.cursor() { + // All block cursors are drawn manually + (pos, CursorKind::Block) => (pos, CursorKind::Hidden), + cursor => cursor, + } } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index fff4792d..d65c1fb2 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -116,6 +116,12 @@ pub struct Config { #[derive(Debug, Clone, PartialEq)] pub struct CursorShapeConfig([CursorKind; 3]); +impl CursorShapeConfig { + pub fn from_mode(&self, mode: Mode) -> CursorKind { + self.get(mode as usize).copied().unwrap_or_default() + } +} + impl<'de> Deserialize<'de> for CursorShapeConfig { fn deserialize(deserializer: D) -> Result where @@ -647,12 +653,7 @@ impl Editor { let inner = view.inner_area(); pos.col += inner.x as usize; pos.row += inner.y as usize; - let cursorkind = self - .config - .cursor_shape - .get(doc.mode() as usize) - .copied() - .unwrap_or_default(); + let cursorkind = self.config.cursor_shape.from_mode(doc.mode()); (Some(pos), cursorkind) } else { (None, CursorKind::default()) -- cgit v1.2.3-70-g09d2 From 0e7d757869bbae914a7e832e2511c2071eeacee5 Mon Sep 17 00:00:00 2001 From: Matouš Dzivjak Date: Sat, 25 Dec 2021 06:32:43 +0100 Subject: feat(lsp): configurable diagnostic severity (#1325) * feat(lsp): configurable diagnostic severity Allow severity of diagnostic messages to be configured. E.g. allow turning of Hint level diagnostics. Fixes: https://github.com/helix-editor/helix/issues/1007 * Use language_config() method * Add documentation for diagnostic_severity * Use unreachable for unknown severity level * fix: documentation for diagnostic_severity config--- book/src/guides/adding_languages.md | 25 +++++++++++++------------ book/src/languages.md | 1 - helix-core/src/diagnostic.rs | 15 +++++++++++---- helix-core/src/indent.rs | 2 ++ helix-core/src/syntax.rs | 3 +++ helix-term/src/application.rs | 31 ++++++++++++++++++++++--------- 6 files changed, 51 insertions(+), 26 deletions(-) (limited to 'book/src') diff --git a/book/src/guides/adding_languages.md b/book/src/guides/adding_languages.md index 987ad088..5844a48e 100644 --- a/book/src/guides/adding_languages.md +++ b/book/src/guides/adding_languages.md @@ -27,18 +27,19 @@ directory](../configuration.md). These are the available keys and descriptions for the file. -| Key | Description | -| ---- | ----------- | -| name | The name of the language | -| scope | A string like `source.js` that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually `source.` or `text.` in case of markup languages | -| injection-regex | regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential [language injection][treesitter-language-injection] site. | -| file-types | The filetypes of the language, for example `["yml", "yaml"]` | -| shebangs | The interpreters from the shebang line, for example `["sh", "bash"]` | -| roots | A set of marker files to look for when trying to find the workspace root. For example `Cargo.lock`, `yarn.lock` | -| auto-format | Whether to autoformat this language when saving | -| comment-token | The token to use as a comment-token | -| indent | The indent to use. Has sub keys `tab-width` and `unit` | -| config | Language server configuration | +| Key | Description | +| ---- | ----------- | +| name | The name of the language | +| scope | A string like `source.js` that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually `source.` or `text.` in case of markup languages | +| injection-regex | regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential [language injection][treesitter-language-injection] site. | +| file-types | The filetypes of the language, for example `["yml", "yaml"]` | +| shebangs | The interpreters from the shebang line, for example `["sh", "bash"]` | +| roots | A set of marker files to look for when trying to find the workspace root. For example `Cargo.lock`, `yarn.lock` | +| auto-format | Whether to autoformat this language when saving | +| diagnostic-severity | Minimal severity of diagnostic for it to be displayed. (Allowed values: `Error`, `Warning`, `Info`, `Hint`) | +| comment-token | The token to use as a comment-token | +| indent | The indent to use. Has sub keys `tab-width` and `unit` | +| config | Language server configuration | ## Queries diff --git a/book/src/languages.md b/book/src/languages.md index cef61501..4c4dc326 100644 --- a/book/src/languages.md +++ b/book/src/languages.md @@ -11,4 +11,3 @@ Changes made to the `languages.toml` file in a user's [configuration directory]( name = "rust" auto-format = false ``` - diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs index 4fcf51c9..210ad639 100644 --- a/helix-core/src/diagnostic.rs +++ b/helix-core/src/diagnostic.rs @@ -1,12 +1,19 @@ //! LSP diagnostic utility types. +use serde::{Deserialize, Serialize}; /// Describes the severity level of a [`Diagnostic`]. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)] pub enum Severity { - Error, - Warning, - Info, Hint, + Info, + Warning, + Error, +} + +impl Default for Severity { + fn default() -> Self { + Self::Hint + } } /// A range of `char`s within the text. diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index b6f5081a..c2baf3cc 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -442,6 +442,7 @@ where ); let doc = Rope::from(doc); + use crate::diagnostic::Severity; use crate::syntax::{ Configuration, IndentationConfiguration, LanguageConfiguration, Loader, }; @@ -459,6 +460,7 @@ where roots: vec![], comment_token: None, auto_format: false, + diagnostic_severity: Severity::Warning, language_server: None, indent: Some(IndentationConfiguration { tab_width: 4, diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index ef35fc75..cdae0210 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -1,5 +1,6 @@ use crate::{ chars::char_is_line_ending, + diagnostic::Severity, regex::Regex, transaction::{ChangeSet, Operation}, Rope, RopeSlice, Tendril, @@ -63,6 +64,8 @@ pub struct LanguageConfiguration { #[serde(default)] pub auto_format: bool, + #[serde(default)] + pub diagnostic_severity: Severity, // content_regex #[serde(default, skip_serializing, deserialize_with = "deserialize_regex")] diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 9a46a7fe..c7202feb 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -378,6 +378,7 @@ impl Application { let doc = self.editor.document_by_path_mut(&path); if let Some(doc) = doc { + let lang_conf = doc.language_config(); let text = doc.text(); let diagnostics = params @@ -415,19 +416,31 @@ impl Application { return None; }; + let severity = + diagnostic.severity.map(|severity| match severity { + DiagnosticSeverity::ERROR => Error, + DiagnosticSeverity::WARNING => Warning, + DiagnosticSeverity::INFORMATION => Info, + DiagnosticSeverity::HINT => Hint, + severity => unreachable!( + "unrecognized diagnostic severity: {:?}", + severity + ), + }); + + if let Some(lang_conf) = lang_conf { + if let Some(severity) = severity { + if severity < lang_conf.diagnostic_severity { + return None; + } + } + }; + Some(Diagnostic { range: Range { start, end }, line: diagnostic.range.start.line as usize, message: diagnostic.message, - severity: diagnostic.severity.map( - |severity| match severity { - DiagnosticSeverity::ERROR => Error, - DiagnosticSeverity::WARNING => Warning, - DiagnosticSeverity::INFORMATION => Info, - DiagnosticSeverity::HINT => Hint, - severity => unimplemented!("{:?}", severity), - }, - ), + severity, // code // source }) -- cgit v1.2.3-70-g09d2 From ec878e40114d8992c3ed1221f77271a4508d3cde Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Sat, 25 Dec 2021 16:10:19 +0100 Subject: Add textobjects and indents to cmake (#1307) --- book/src/generated/lang-support.md | 2 +- runtime/queries/cmake/indents.toml | 12 ++++++++++++ runtime/queries/cmake/textobjects.scm | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/cmake/indents.toml create mode 100644 runtime/queries/cmake/textobjects.scm (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index c7054201..2777dc4e 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -3,7 +3,7 @@ | bash | ✓ | | | `bash-language-server` | | c | ✓ | | | `clangd` | | c-sharp | ✓ | | | | -| cmake | ✓ | | | `cmake-language-server` | +| cmake | ✓ | ✓ | ✓ | `cmake-language-server` | | comment | ✓ | | | | | cpp | ✓ | | | `clangd` | | css | ✓ | | | | diff --git a/runtime/queries/cmake/indents.toml b/runtime/queries/cmake/indents.toml new file mode 100644 index 00000000..8b886a4f --- /dev/null +++ b/runtime/queries/cmake/indents.toml @@ -0,0 +1,12 @@ +indent = [ + "if_condition", + "foreach_loop", + "while_loop", + "function_def", + "macro_def", + "normal_command", +] + +outdent = [ + ")" +] diff --git a/runtime/queries/cmake/textobjects.scm b/runtime/queries/cmake/textobjects.scm new file mode 100644 index 00000000..b0d1b108 --- /dev/null +++ b/runtime/queries/cmake/textobjects.scm @@ -0,0 +1,3 @@ +(macro_def) @function.around + +(argument) @parameter.inside -- cgit v1.2.3-70-g09d2 From fd31662b70ee32d199950ba2873680fc9043c975 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Fri, 24 Dec 2021 12:44:45 -0600 Subject: add gitcommit grammar and language configuration --- .gitmodules | 6 +++++- book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-gitcommit | 1 + languages.toml | 8 ++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) create mode 160000 helix-syntax/languages/tree-sitter-gitcommit (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index edfe3c39..ad100a00 100644 --- a/.gitmodules +++ b/.gitmodules @@ -165,8 +165,12 @@ [submodule "helix-syntax/languages/tree-sitter-dockerfile"] path = helix-syntax/languages/tree-sitter-dockerfile url = https://github.com/camdencheek/tree-sitter-dockerfile.git - shallow = true + shallow = true [submodule "helix-syntax/languages/tree-sitter-fish"] path = helix-syntax/languages/tree-sitter-fish url = https://github.com/ram02z/tree-sitter-fish shallow = true +[submodule "helix-syntax/languages/tree-sitter-gitcommit"] + path = helix-syntax/languages/tree-sitter-gitcommit + url = https://github.com/the-mikedavis/tree-sitter-gitcommit.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 2777dc4e..d6e0d9af 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -11,6 +11,7 @@ | dockerfile | ✓ | | | `docker-langserver` | | elixir | ✓ | | | `elixir-ls` | | fish | ✓ | ✓ | ✓ | | +| gitcommit | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-gitcommit b/helix-syntax/languages/tree-sitter-gitcommit new file mode 160000 index 00000000..6a2ddbec --- /dev/null +++ b/helix-syntax/languages/tree-sitter-gitcommit @@ -0,0 +1 @@ +Subproject commit 6a2ddbecd49fa8e7e1fda24d43e363cfd9171ca0 diff --git a/languages.toml b/languages.toml index dd18fa19..f73011c8 100644 --- a/languages.toml +++ b/languages.toml @@ -473,3 +473,11 @@ file-types = ["Dockerfile", "dockerfile"] comment-token = "#" indent = { tab-width = 2, unit = " " } language-server = { command = "docker-langserver", args = ["--stdio"] } + +[[language]] +name = "gitcommit" +scope = "git.commitmsg" +roots = [] +file-types = ["COMMIT_EDITMSG"] +comment-token = "#" +indent = { tab-width = 2, unit = " " } -- cgit v1.2.3-70-g09d2 From c1f4c0e67acc65a263440fce98514c9e6de1940d Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 22 Dec 2021 09:58:51 -0600 Subject: add new scopes to themes docs --- book/src/themes.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index fce2c0ca..8eee334b 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -178,6 +178,12 @@ We use a similar set of scopes as - `inline` - `block` +- `diff` - version control changes + - `plus` - additions + - `minus` - deletions + - `delta` - modifications + - `moved` - renamed or moved files/changes + #### Interface These scopes are used for theming the editor interface. -- cgit v1.2.3-70-g09d2 From c3fb86cbaa5c6973fe014a4401c4e0d6f663384d Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Fri, 24 Dec 2021 16:49:27 -0600 Subject: tree-sitter-gitcommit->tree-sitter-git-commit --- .gitmodules | 6 +++--- book/src/generated/lang-support.md | 2 +- helix-syntax/languages/tree-sitter-git-commit | 1 + helix-syntax/languages/tree-sitter-gitcommit | 1 - languages.toml | 2 +- runtime/queries/git-commit/highlights.scm | 18 ++++++++++++++++++ runtime/queries/git-commit/injections.scm | 15 +++++++++++++++ runtime/queries/gitcommit/highlights.scm | 18 ------------------ runtime/queries/gitcommit/injections.scm | 15 --------------- 9 files changed, 39 insertions(+), 39 deletions(-) create mode 160000 helix-syntax/languages/tree-sitter-git-commit delete mode 160000 helix-syntax/languages/tree-sitter-gitcommit create mode 100644 runtime/queries/git-commit/highlights.scm create mode 100644 runtime/queries/git-commit/injections.scm delete mode 100644 runtime/queries/gitcommit/highlights.scm delete mode 100644 runtime/queries/gitcommit/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index ad100a00..d5bd61c9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -170,7 +170,7 @@ path = helix-syntax/languages/tree-sitter-fish url = https://github.com/ram02z/tree-sitter-fish shallow = true -[submodule "helix-syntax/languages/tree-sitter-gitcommit"] - path = helix-syntax/languages/tree-sitter-gitcommit - url = https://github.com/the-mikedavis/tree-sitter-gitcommit.git +[submodule "helix-syntax/languages/tree-sitter-git-commit"] + path = helix-syntax/languages/tree-sitter-git-commit + url = https://github.com/the-mikedavis/tree-sitter-git-commit.git shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index d6e0d9af..9c42005b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -11,7 +11,7 @@ | dockerfile | ✓ | | | `docker-langserver` | | elixir | ✓ | | | `elixir-ls` | | fish | ✓ | ✓ | ✓ | | -| gitcommit | ✓ | | | | +| git-commit | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-git-commit b/helix-syntax/languages/tree-sitter-git-commit new file mode 160000 index 00000000..5cd4776c --- /dev/null +++ b/helix-syntax/languages/tree-sitter-git-commit @@ -0,0 +1 @@ +Subproject commit 5cd4776c86c82d9d6afdc8c73a47a08057aef618 diff --git a/helix-syntax/languages/tree-sitter-gitcommit b/helix-syntax/languages/tree-sitter-gitcommit deleted file mode 160000 index 6a2ddbec..00000000 --- a/helix-syntax/languages/tree-sitter-gitcommit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6a2ddbecd49fa8e7e1fda24d43e363cfd9171ca0 diff --git a/languages.toml b/languages.toml index f73011c8..616ef234 100644 --- a/languages.toml +++ b/languages.toml @@ -475,7 +475,7 @@ indent = { tab-width = 2, unit = " " } language-server = { command = "docker-langserver", args = ["--stdio"] } [[language]] -name = "gitcommit" +name = "git-commit" scope = "git.commitmsg" roots = [] file-types = ["COMMIT_EDITMSG"] diff --git a/runtime/queries/git-commit/highlights.scm b/runtime/queries/git-commit/highlights.scm new file mode 100644 index 00000000..04d70416 --- /dev/null +++ b/runtime/queries/git-commit/highlights.scm @@ -0,0 +1,18 @@ +(subject) @markup.heading +(path) @string.special.path +(branch) @string.special.symbol +(commit) @constant +(item) @markup.link.url +(header) @tag + +(change kind: "new file" @diff.plus) +(change kind: "deleted" @diff.minus) +(change kind: "modified" @diff.delta) +(change kind: "renamed" @diff.delta.moved) + +[":" "->"] @punctuation.delimeter +(comment) @comment + +; once we have diff injections, @comment should become @none +((comment (scissors)) + (message)+ @comment) diff --git a/runtime/queries/git-commit/injections.scm b/runtime/queries/git-commit/injections.scm new file mode 100644 index 00000000..2837a586 --- /dev/null +++ b/runtime/queries/git-commit/injections.scm @@ -0,0 +1,15 @@ +; once a diff grammar is available, we can inject diff highlighting into the +; trailer after scissors (git commit --verbose) +; see https://github.com/helix-editor/helix/pull/1338#issuecomment-1000013539 +; +; ((comment (scissors)) +; (message) @injection.content +; (#set! injection.language "diff")) + +; --- + +; once a rebase grammar is available, we can inject rebase highlighting into +; interactive rebase summary sections like so: +; +; ((rebase_command) @injection.content +; (#set! injection.language "git-rebase")) diff --git a/runtime/queries/gitcommit/highlights.scm b/runtime/queries/gitcommit/highlights.scm deleted file mode 100644 index 04d70416..00000000 --- a/runtime/queries/gitcommit/highlights.scm +++ /dev/null @@ -1,18 +0,0 @@ -(subject) @markup.heading -(path) @string.special.path -(branch) @string.special.symbol -(commit) @constant -(item) @markup.link.url -(header) @tag - -(change kind: "new file" @diff.plus) -(change kind: "deleted" @diff.minus) -(change kind: "modified" @diff.delta) -(change kind: "renamed" @diff.delta.moved) - -[":" "->"] @punctuation.delimeter -(comment) @comment - -; once we have diff injections, @comment should become @none -((comment (scissors)) - (message)+ @comment) diff --git a/runtime/queries/gitcommit/injections.scm b/runtime/queries/gitcommit/injections.scm deleted file mode 100644 index 2837a586..00000000 --- a/runtime/queries/gitcommit/injections.scm +++ /dev/null @@ -1,15 +0,0 @@ -; once a diff grammar is available, we can inject diff highlighting into the -; trailer after scissors (git commit --verbose) -; see https://github.com/helix-editor/helix/pull/1338#issuecomment-1000013539 -; -; ((comment (scissors)) -; (message) @injection.content -; (#set! injection.language "diff")) - -; --- - -; once a rebase grammar is available, we can inject rebase highlighting into -; interactive rebase summary sections like so: -; -; ((rebase_command) @injection.content -; (#set! injection.language "git-rebase")) -- cgit v1.2.3-70-g09d2 From a306a1052a51c686b24a6f339190878b8029a894 Mon Sep 17 00:00:00 2001 From: Tamo Date: Sun, 26 Dec 2021 02:04:33 +0100 Subject: Update settings at runtime (#798) * feat: Update settings at runtime fix the clippy warning * update the documentation * use to_value instead of to_vec+from_value * drop the equal * remove an useless comment * apply suggestion--- book/src/generated/typable-cmd.md | 1 + helix-term/src/commands.rs | 37 +++++++++++++++++++++++++++++++++++++ helix-term/src/ui/mod.rs | 27 +++++++++++++++++++++++++++ helix-view/src/editor.rs | 20 ++++++++++++++++---- 4 files changed, 81 insertions(+), 4 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index bb21fd6b..f12082bb 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -41,3 +41,4 @@ | `:hsplit`, `:hs`, `:sp` | Open the file in a horizontal split. | | `:tutor` | Open the tutorial. | | `:goto`, `:g` | Go to line number. | +| `:set-option`, `:set` | Set a config option at runtime | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index ee6a5989..7b1235f8 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2637,6 +2637,36 @@ pub mod cmd { let (view, doc) = current!(cx.editor); view.ensure_cursor_in_view(doc, line); + Ok(()) + } + + fn setting( + cx: &mut compositor::Context, + args: &[Cow], + _event: PromptEvent, + ) -> anyhow::Result<()> { + let runtime_config = &mut cx.editor.config; + + if args.len() != 2 { + anyhow::bail!("Bad arguments. Usage: `:set key field`"); + } + + let (key, arg) = (&args[0].to_lowercase(), &args[1]); + + match key.as_ref() { + "scrolloff" => runtime_config.scrolloff = arg.parse()?, + "scroll-lines" => runtime_config.scroll_lines = arg.parse()?, + "mouse" => runtime_config.mouse = arg.parse()?, + "line-number" => runtime_config.line_number = arg.parse()?, + "middle-click_paste" => runtime_config.middle_click_paste = arg.parse()?, + "smart-case" => runtime_config.smart_case = arg.parse()?, + "auto-pairs" => runtime_config.auto_pairs = arg.parse()?, + "auto-completion" => runtime_config.auto_completion = arg.parse()?, + "completion-trigger-len" => runtime_config.completion_trigger_len = arg.parse()?, + "auto-info" => runtime_config.auto_info = arg.parse()?, + "true-color" => runtime_config.true_color = arg.parse()?, + _ => anyhow::bail!("Unknown key `{}`.", args[0]), + } Ok(()) } @@ -2928,6 +2958,13 @@ pub mod cmd { doc: "Go to line number.", fun: goto_line_number, completer: None, + }, + TypableCommand { + name: "set-option", + aliases: &["set"], + doc: "Set a config option at runtime", + fun: setting, + completer: Some(completers::setting), } ]; diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index f57e2e2b..9e096311 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -174,7 +174,9 @@ pub mod completers { use crate::ui::prompt::Completion; use fuzzy_matcher::skim::SkimMatcherV2 as Matcher; use fuzzy_matcher::FuzzyMatcher; + use helix_view::editor::Config; use helix_view::theme; + use once_cell::sync::Lazy; use std::borrow::Cow; use std::cmp::Reverse; @@ -208,6 +210,31 @@ pub mod completers { names } + pub fn setting(input: &str) -> Vec { + static KEYS: Lazy> = Lazy::new(|| { + serde_json::to_value(Config::default()) + .unwrap() + .as_object() + .unwrap() + .keys() + .cloned() + .collect() + }); + + let matcher = Matcher::default(); + + let mut matches: Vec<_> = KEYS + .iter() + .filter_map(|name| matcher.fuzzy_match(name, input).map(|score| (name, score))) + .collect(); + + matches.sort_unstable_by_key(|(_file, score)| Reverse(*score)); + matches + .into_iter() + .map(|(name, _)| ((0..), name.into())) + .collect() + } + pub fn filename(input: &str) -> Vec { filename_impl(input, |entry| { let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir()); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index fd6eb4d5..f4b0f73e 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -27,7 +27,7 @@ pub use helix_core::register::Registers; use helix_core::syntax; use helix_core::{Position, Selection}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result where @@ -37,7 +37,7 @@ where Ok(Duration::from_millis(millis)) } -#[derive(Debug, Clone, PartialEq, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] pub struct FilePickerConfig { /// IgnoreOptions @@ -77,7 +77,7 @@ impl Default for FilePickerConfig { } } -#[derive(Debug, Clone, PartialEq, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", default, deny_unknown_fields)] pub struct Config { /// Padding to keep between the edge of the screen and the cursor when scrolling. Defaults to 5. @@ -109,7 +109,7 @@ pub struct Config { pub true_color: bool, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum LineNumber { /// Show absolute line number @@ -119,6 +119,18 @@ pub enum LineNumber { Relative, } +impl std::str::FromStr for LineNumber { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "absolute" | "abs" => Ok(Self::Absolute), + "relative" | "rel" => Ok(Self::Relative), + _ => anyhow::bail!("Line number can only be `absolute` or `relative`."), + } + } +} + impl Default for Config { fn default() -> Self { Self { -- cgit v1.2.3-70-g09d2 From c7a59e24e6e1609dd65e5ee66fef52f76aabe9b7 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 12 Dec 2021 21:09:01 +0800 Subject: Switch macro Q and q --- book/src/keymap.md | 4 ++-- helix-term/src/keymap.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index d84b17b8..e1df545d 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -77,8 +77,8 @@ | `Alt-c` | Change selection (delete and enter insert mode, without yanking) | `change_selection_noyank` | | `Ctrl-a` | Increment object (number) under cursor | `increment` | | `Ctrl-x` | Decrement object (number) under cursor | `decrement` | -| `q` | Start/stop macro recording to the selected register | `record_macro` | -| `Q` | Play back a recorded macro from the selected register | `play_macro` | +| `Q` | Start/stop macro recording to the selected register | `record_macro` | +| `q` | Play back a recorded macro from the selected register | `play_macro` | #### Shell diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 257d5f29..917a0990 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -593,8 +593,8 @@ impl Default for Keymaps { // paste_all "P" => paste_before, - "q" => record_macro, - "Q" => play_macro, + "Q" => record_macro, + "q" => play_macro, ">" => indent, "<" => unindent, -- cgit v1.2.3-70-g09d2 From 9a32617b3093ce6ab3b925d9f1c6b17218c1b491 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 12 Dec 2021 21:51:57 +0800 Subject: Rename play macro to replay macro Macro needs to be defined first before playing so replay is more accurate. Also, replay have the same length as record which makes it looks nice. --- book/src/keymap.md | 2 +- helix-term/src/commands.rs | 6 +++--- helix-term/src/keymap.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index e1df545d..b7a1e54b 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -78,7 +78,7 @@ | `Ctrl-a` | Increment object (number) under cursor | `increment` | | `Ctrl-x` | Decrement object (number) under cursor | `decrement` | | `Q` | Start/stop macro recording to the selected register | `record_macro` | -| `q` | Play back a recorded macro from the selected register | `play_macro` | +| `q` | Play back a recorded macro from the selected register | `replay_macro` | #### Shell diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index e3944cd7..ac42682f 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -396,7 +396,7 @@ impl MappableCommand { increment, "Increment", decrement, "Decrement", record_macro, "Record macro", - play_macro, "Play macro", + replay_macro, "Replay macro", ); } @@ -6015,7 +6015,7 @@ fn record_macro(cx: &mut Context) { keys.pop(); let s = keys .into_iter() - .map(|key| format!("{}", key)) + .map(|key| key.to_string()) .collect::>() .join(" "); cx.editor.registers.get_mut(reg).write(vec![s]); @@ -6029,7 +6029,7 @@ fn record_macro(cx: &mut Context) { } } -fn play_macro(cx: &mut Context) { +fn replay_macro(cx: &mut Context) { let reg = cx.register.unwrap_or('@'); let keys: Vec = if let Some([keys]) = cx.editor.registers.read(reg) { match keys.split_whitespace().map(str::parse).collect() { diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 917a0990..08c8032b 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -594,7 +594,7 @@ impl Default for Keymaps { "P" => paste_before, "Q" => record_macro, - "q" => play_macro, + "q" => replay_macro, ">" => indent, "<" => unindent, -- cgit v1.2.3-70-g09d2 From b9cb3930e2838347a97f501e025ee52ea377ed52 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 12 Dec 2021 21:54:14 +0800 Subject: Mark macros as experimental in docs Given that currently macro does not integrate well with registers and the internal representation of macros is expected to be changed. --- book/src/keymap.md | 66 +++++++++++++++++++++++----------------------- helix-term/src/commands.rs | 1 + 2 files changed, 34 insertions(+), 33 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index b7a1e54b..581e70e9 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -46,39 +46,39 @@ ### Changes -| Key | Description | Command | -| ----- | ----------- | ------- | -| `r` | Replace with a character | `replace` | -| `R` | Replace with yanked text | `replace_with_yanked` | -| `~` | Switch case of the selected text | `switch_case` | -| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` | -| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` | -| `i` | Insert before selection | `insert_mode` | -| `a` | Insert after selection (append) | `append_mode` | -| `I` | Insert at the start of the line | `prepend_to_line` | -| `A` | Insert at the end of the line | `append_to_line` | -| `o` | Open new line below selection | `open_below` | -| `O` | Open new line above selection | `open_above` | -| `.` | Repeat last change | N/A | -| `u` | Undo change | `undo` | -| `U` | Redo change | `redo` | -| `Alt-u` | Move backward in history | `earlier` | -| `Alt-U` | Move forward in history | `later` | -| `y` | Yank selection | `yank` | -| `p` | Paste after selection | `paste_after` | -| `P` | Paste before selection | `paste_before` | -| `"` `` | Select a register to yank to or paste from | `select_register` | -| `>` | Indent selection | `indent` | -| `<` | Unindent selection | `unindent` | -| `=` | Format selection (currently nonfunctional/disabled) (**LSP**) | `format_selections` | -| `d` | Delete selection | `delete_selection` | -| `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` | -| `c` | Change selection (delete and enter insert mode) | `change_selection` | -| `Alt-c` | Change selection (delete and enter insert mode, without yanking) | `change_selection_noyank` | -| `Ctrl-a` | Increment object (number) under cursor | `increment` | -| `Ctrl-x` | Decrement object (number) under cursor | `decrement` | -| `Q` | Start/stop macro recording to the selected register | `record_macro` | -| `q` | Play back a recorded macro from the selected register | `replay_macro` | +| Key | Description | Command | +| ----- | ----------- | ------- | +| `r` | Replace with a character | `replace` | +| `R` | Replace with yanked text | `replace_with_yanked` | +| `~` | Switch case of the selected text | `switch_case` | +| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` | +| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` | +| `i` | Insert before selection | `insert_mode` | +| `a` | Insert after selection (append) | `append_mode` | +| `I` | Insert at the start of the line | `prepend_to_line` | +| `A` | Insert at the end of the line | `append_to_line` | +| `o` | Open new line below selection | `open_below` | +| `O` | Open new line above selection | `open_above` | +| `.` | Repeat last change | N/A | +| `u` | Undo change | `undo` | +| `U` | Redo change | `redo` | +| `Alt-u` | Move backward in history | `earlier` | +| `Alt-U` | Move forward in history | `later` | +| `y` | Yank selection | `yank` | +| `p` | Paste after selection | `paste_after` | +| `P` | Paste before selection | `paste_before` | +| `"` `` | Select a register to yank to or paste from | `select_register` | +| `>` | Indent selection | `indent` | +| `<` | Unindent selection | `unindent` | +| `=` | Format selection (currently nonfunctional/disabled) (**LSP**) | `format_selections` | +| `d` | Delete selection | `delete_selection` | +| `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` | +| `c` | Change selection (delete and enter insert mode) | `change_selection` | +| `Alt-c` | Change selection (delete and enter insert mode, without yanking) | `change_selection_noyank` | +| `Ctrl-a` | Increment object (number) under cursor | `increment` | +| `Ctrl-x` | Decrement object (number) under cursor | `decrement` | +| `Q` | Start/stop macro recording to the selected register (experimental) | `record_macro` | +| `q` | Play back a recorded macro from the selected register (experimental) | `replay_macro` | #### Shell diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index ac42682f..d0a94160 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -6031,6 +6031,7 @@ fn record_macro(cx: &mut Context) { fn replay_macro(cx: &mut Context) { let reg = cx.register.unwrap_or('@'); + // TODO: macro keys should be parsed one by one and not space delimited (see kak) let keys: Vec = if let Some([keys]) = cx.editor.registers.read(reg) { match keys.split_whitespace().map(str::parse).collect() { Ok(keys) => keys, -- cgit v1.2.3-70-g09d2 From 7001665342ade12823fba4f358a7e8efc2245a2b Mon Sep 17 00:00:00 2001 From: Stuart Hinson Date: Sun, 26 Dec 2021 23:07:09 -0500 Subject: Add ruby indents (#1372) * Add ruby indents * Include ruby in generated docs--- book/src/generated/lang-support.md | 2 +- runtime/queries/ruby/indents.toml | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/ruby/indents.toml (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 9c42005b..28094484 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -34,7 +34,7 @@ | protobuf | ✓ | | ✓ | | | python | ✓ | ✓ | ✓ | `pylsp` | | racket | | | | `racket` | -| ruby | ✓ | | | `solargraph` | +| ruby | ✓ | | ✓ | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | | svelte | ✓ | | ✓ | `svelteserver` | diff --git a/runtime/queries/ruby/indents.toml b/runtime/queries/ruby/indents.toml new file mode 100644 index 00000000..b417751f --- /dev/null +++ b/runtime/queries/ruby/indents.toml @@ -0,0 +1,25 @@ +indent = [ + "argument_list", + "array", + "begin", + "block", + "call", + "class", + "case", + "do_block", + "elsif", + "if", + "hash", + "method", + "module", + "singleton_class", + "singleton_method", +] + +outdent = [ + ")", + "}", + "]", + "end", + "when", +] -- cgit v1.2.3-70-g09d2 From a4641a8613bcbe4ad01d28d3d2a6f4509fef96a9 Mon Sep 17 00:00:00 2001 From: Matouš Dzivjak Date: Mon, 27 Dec 2021 05:11:06 +0100 Subject: feat(commands): sort command (#1288) * feat(commands): sort/rsort command Add basic implementation of sort command. * Sort by selections instead, implement reverse sort * Generate docs * Rename sort! to rsort--- book/src/generated/typable-cmd.md | 2 ++ helix-term/src/commands.rs | 66 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index f12082bb..45129cc1 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -42,3 +42,5 @@ | `:tutor` | Open the tutorial. | | `:goto`, `:g` | Go to line number. | | `:set-option`, `:set` | Set a config option at runtime | +| `:sort` | Sort ranges in selection. | +| `:rsort` | Sort ranges in selection in reverse order. | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 524c50ce..16a2cf35 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2671,6 +2671,56 @@ pub mod cmd { Ok(()) } + fn sort( + cx: &mut compositor::Context, + args: &[Cow], + _event: PromptEvent, + ) -> anyhow::Result<()> { + sort_impl(cx, args, false) + } + + fn sort_reverse( + cx: &mut compositor::Context, + args: &[Cow], + _event: PromptEvent, + ) -> anyhow::Result<()> { + sort_impl(cx, args, true) + } + + fn sort_impl( + cx: &mut compositor::Context, + _args: &[Cow], + reverse: bool, + ) -> anyhow::Result<()> { + let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); + + let selection = doc.selection(view.id); + + let mut fragments: Vec<_> = selection + .fragments(text) + .map(|fragment| Tendril::from_slice(&fragment)) + .collect(); + + fragments.sort_by(match reverse { + true => |a: &Tendril, b: &Tendril| b.cmp(a), + false => |a: &Tendril, b: &Tendril| a.cmp(b), + }); + + let transaction = Transaction::change( + doc.text(), + selection + .into_iter() + .zip(fragments) + .map(|(s, fragment)| (s.from(), s.to(), Some(fragment))), + ); + + doc.apply(&transaction, view.id); + doc.append_changes_to_history(view.id); + + Ok(()) + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -2965,7 +3015,21 @@ pub mod cmd { doc: "Set a config option at runtime", fun: setting, completer: Some(completers::setting), - } + }, + TypableCommand { + name: "sort", + aliases: &[], + doc: "Sort ranges in selection.", + fun: sort, + completer: None, + }, + TypableCommand { + name: "rsort", + aliases: &[], + doc: "Sort ranges in selection in reverse order.", + fun: sort_reverse, + completer: None, + }, ]; pub static TYPABLE_COMMAND_MAP: Lazy> = -- cgit v1.2.3-70-g09d2 From 8c29b76bccc51c19c90f7c9ee156fe2cb6f52e2c Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Wed, 29 Dec 2021 10:30:44 +0100 Subject: Improve llvm highlighting and queries (#1388) * Improve llvm highlighting and queries The llvm tree-sitter parser was updated to support scopes and more accurate highlighting. * Group highlight expressions better--- book/src/generated/lang-support.md | 2 +- helix-syntax/languages/tree-sitter-llvm | 2 +- runtime/queries/llvm/highlights.scm | 162 ++++++++++++++++++++++++++++++-- runtime/queries/llvm/indents.toml | 8 ++ runtime/queries/llvm/locals.scm | 14 +++ runtime/queries/llvm/textobjects.scm | 16 ++++ 6 files changed, 193 insertions(+), 11 deletions(-) create mode 100644 runtime/queries/llvm/indents.toml create mode 100644 runtime/queries/llvm/locals.scm create mode 100644 runtime/queries/llvm/textobjects.scm (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 28094484..5d172751 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -21,7 +21,7 @@ | julia | ✓ | | | `julia` | | latex | ✓ | | | | | ledger | ✓ | | | | -| llvm | ✓ | | | | +| llvm | ✓ | ✓ | ✓ | | | lua | ✓ | | ✓ | | | markdown | ✓ | | | | | mint | | | | `mint` | diff --git a/helix-syntax/languages/tree-sitter-llvm b/helix-syntax/languages/tree-sitter-llvm index d4f61bed..3b213925 160000 --- a/helix-syntax/languages/tree-sitter-llvm +++ b/helix-syntax/languages/tree-sitter-llvm @@ -1 +1 @@ -Subproject commit d4f61bed8ecb632addcd5e088c4f4cb9c1bf1c5b +Subproject commit 3b213925b9c4f42c1acfe2e10bfbb438d9c6834d diff --git a/runtime/queries/llvm/highlights.scm b/runtime/queries/llvm/highlights.scm index 73afe85e..cb705197 100644 --- a/runtime/queries/llvm/highlights.scm +++ b/runtime/queries/llvm/highlights.scm @@ -1,14 +1,158 @@ (type) @type -(statement) @keyword.operator +(type_keyword) @type.builtin + +(type [ + (local_var) + (global_var) + ] @type) + +(argument) @variable.parameter + +(_ inst_name: _ @keyword.operator) + +[ + "catch" + "filter" +] @keyword.operator + +[ + "to" + "nuw" + "nsw" + "exact" + "unwind" + "from" + "cleanup" + "swifterror" + "volatile" + "inbounds" + "inrange" + (icmp_cond) + (fcmp_cond) + (fast_math) +] @keyword.control + +(_ callee: _ @function) +(function_header name: _ @function) + +[ + "declare" + "define" + (calling_conv) +] @keyword.function + +[ + "target" + "triple" + "datalayout" + "source_filename" + "addrspace" + "blockaddress" + "align" + "syncscope" + "within" + "uselistorder" + "uselistorder_bb" + "module" + "asm" + "sideeffect" + "alignstack" + "inteldialect" + "unwind" + "type" + "global" + "constant" + "externally_initialized" + "alias" + "ifunc" + "section" + "comdat" + "thread_local" + "localdynamic" + "initialexec" + "localexec" + "any" + "exactmatch" + "largest" + "nodeduplicate" + "samesize" + "distinct" + "attributes" + "vscale" + "no_cfi" + (linkage_aux) + (dso_local) + (visibility) + (dll_storage_class) + (unnamed_addr) + (attribute_name) +] @keyword + + +(function_header [ + (linkage) + (calling_conv) + (unnamed_addr) + ] @keyword.function) + +[ + (string) + (cstring) +] @string + (number) @constant.numeric.integer (comment) @comment -(string) @string (label) @label -(keyword) @keyword -"ret" @keyword.control.return -(boolean) @constant.builtin.boolean +(_ inst_name: "ret" @keyword.control.return) (float) @constant.numeric.float -(constant) @constant -(identifier) @variable -(symbol) @punctuation.delimiter -(bracket) @punctuation.bracket + +[ + (local_var) + (global_var) +] @variable + +[ + (struct_value) + (array_value) + (vector_value) +] @constructor + +[ + "(" + ")" + "[" + "]" + "{" + "}" + "<" + ">" + "<{" + "}>" +] @punctuation.bracket + +[ + "," + ":" +] @punctuation.delimiter + +[ + "=" + "|" + "x" + "..." +] @operator + +[ + "true" + "false" +] @constant.builtin.boolean + +[ + "undef" + "poison" + "null" + "none" + "zeroinitializer" +] @constant.builtin + +(ERROR) @error diff --git a/runtime/queries/llvm/indents.toml b/runtime/queries/llvm/indents.toml new file mode 100644 index 00000000..8cd603c8 --- /dev/null +++ b/runtime/queries/llvm/indents.toml @@ -0,0 +1,8 @@ +indent = [ + "function_body", + "instruction", +] + +outdent = [ + "}", +] diff --git a/runtime/queries/llvm/locals.scm b/runtime/queries/llvm/locals.scm new file mode 100644 index 00000000..1946c287 --- /dev/null +++ b/runtime/queries/llvm/locals.scm @@ -0,0 +1,14 @@ +; Scopes + +(function_body) @local.scope + +; Definitions + +(argument + (value (var (local_var) @local.definition))) + +(instruction + (local_var) @local.definition) + +; References +(local_var) @local.reference diff --git a/runtime/queries/llvm/textobjects.scm b/runtime/queries/llvm/textobjects.scm new file mode 100644 index 00000000..3738a3bb --- /dev/null +++ b/runtime/queries/llvm/textobjects.scm @@ -0,0 +1,16 @@ +(define + body: (_) @function.inside) @function.around + +(struct_type + (struct_body) @class.inside) @class.around + +(packed_struct_type + (struct_body) @class.inside) @class.around + +(array_type + (array_vector_body) @class.inside) @class.around + +(vector_type + (array_vector_body) @class.inside) @class.around + +(argument) @parameter.inside -- cgit v1.2.3-70-g09d2 From bcf3808e9763bfe1bbf70f6053f890c80639d7c9 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 29 Dec 2021 09:31:23 -0600 Subject: Add tree-sitter-git-diff (#1373) * add submodule on tree-sitter-git-diff * add git-diff highlights * inject git-diff into git-commit * update tree-sitter-git-commit with fix for bad diff case * add git-diff to language support docs * include-children in diff injections This ensures that children nodes of $.message are included in the injection, such as $.user or issue/pr numbers. Without this change, diffs containing '#' or '@' characters can trip up the injection and be parsed separately. See https://github.com/helix-editor/helix/pull/1373#issuecomment-1001215629 * set diff language's scope as source.diff--- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-git-commit | 2 +- helix-syntax/languages/tree-sitter-git-diff | 1 + languages.toml | 9 +++++++++ runtime/queries/git-commit/highlights.scm | 4 ---- runtime/queries/git-commit/injections.scm | 13 ++++--------- runtime/queries/git-diff/highlights.scm | 6 ++++++ 8 files changed, 26 insertions(+), 14 deletions(-) create mode 160000 helix-syntax/languages/tree-sitter-git-diff create mode 100644 runtime/queries/git-diff/highlights.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index d5bd61c9..422671b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -174,3 +174,7 @@ path = helix-syntax/languages/tree-sitter-git-commit url = https://github.com/the-mikedavis/tree-sitter-git-commit.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-git-diff"] + path = helix-syntax/languages/tree-sitter-git-diff + url = https://github.com/the-mikedavis/tree-sitter-git-diff.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 5d172751..91575c62 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -12,6 +12,7 @@ | elixir | ✓ | | | `elixir-ls` | | fish | ✓ | ✓ | ✓ | | | git-commit | ✓ | | | | +| git-diff | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-git-commit b/helix-syntax/languages/tree-sitter-git-commit index 5cd4776c..066e395e 160000 --- a/helix-syntax/languages/tree-sitter-git-commit +++ b/helix-syntax/languages/tree-sitter-git-commit @@ -1 +1 @@ -Subproject commit 5cd4776c86c82d9d6afdc8c73a47a08057aef618 +Subproject commit 066e395e1107df17183cf3ae4230f1a1406cc972 diff --git a/helix-syntax/languages/tree-sitter-git-diff b/helix-syntax/languages/tree-sitter-git-diff new file mode 160000 index 00000000..c12e6ecb --- /dev/null +++ b/helix-syntax/languages/tree-sitter-git-diff @@ -0,0 +1 @@ +Subproject commit c12e6ecb54485f764250556ffd7ccb18f8e2942b diff --git a/languages.toml b/languages.toml index 616ef234..c3ae9f62 100644 --- a/languages.toml +++ b/languages.toml @@ -481,3 +481,12 @@ roots = [] file-types = ["COMMIT_EDITMSG"] comment-token = "#" indent = { tab-width = 2, unit = " " } + +[[language]] +name = "git-diff" +scope = "source.diff" +roots = [] +file-types = ["diff"] +injection-regex = "diff" +comment-token = "#" +indent = { tab-width = 2, unit = " " } diff --git a/runtime/queries/git-commit/highlights.scm b/runtime/queries/git-commit/highlights.scm index a74bb381..ffcc31ae 100644 --- a/runtime/queries/git-commit/highlights.scm +++ b/runtime/queries/git-commit/highlights.scm @@ -13,7 +13,3 @@ [":" "->"] @punctuation.delimeter (comment) @comment - -; once we have diff injections, @comment should become @none -((comment (scissors)) - (message)+ @comment) diff --git a/runtime/queries/git-commit/injections.scm b/runtime/queries/git-commit/injections.scm index 2837a586..bd96f1de 100644 --- a/runtime/queries/git-commit/injections.scm +++ b/runtime/queries/git-commit/injections.scm @@ -1,12 +1,7 @@ -; once a diff grammar is available, we can inject diff highlighting into the -; trailer after scissors (git commit --verbose) -; see https://github.com/helix-editor/helix/pull/1338#issuecomment-1000013539 -; -; ((comment (scissors)) -; (message) @injection.content -; (#set! injection.language "diff")) - -; --- +((comment (scissors)) + (message) @injection.content + (#set! injection.include-children) + (#set! injection.language "diff")) ; once a rebase grammar is available, we can inject rebase highlighting into ; interactive rebase summary sections like so: diff --git a/runtime/queries/git-diff/highlights.scm b/runtime/queries/git-diff/highlights.scm new file mode 100644 index 00000000..1c1a8829 --- /dev/null +++ b/runtime/queries/git-diff/highlights.scm @@ -0,0 +1,6 @@ +[(addition) (new_file)] @diff.plus +[(deletion) (old_file)] @diff.minus + +(commit) @constant +(location) @attribute +(command) @markup.bold -- cgit v1.2.3-70-g09d2 From 8fda87af2bb0625c502a23ddbd78a7447ada7bcb Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 30 Dec 2021 16:58:47 -0600 Subject: add tree-sitter-git-rebase (#1402) * add submodule on tree-sitter-rebase, add to languages * add basic highlights query * inject bash in execute statements * update tree-sitter-rebase * tree-sitter-rebase->tree-sitter-git-rebase * get injection working with tree-sitter-git-commit * set scope under source.gitrebase * unset include-children on commit message injections * Revert "unset include-children on commit message injections" This reverts commit 2ecee155ea8e229651920b291062c2ee84b47944. * fix generated language docs * use rebase_command scopes from tree-sitter-git-commit--- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-git-rebase | 1 + languages.toml | 9 +++++++++ runtime/queries/git-commit/highlights.scm | 1 - runtime/queries/git-commit/injections.scm | 8 +++----- runtime/queries/git-rebase/highlights.scm | 11 +++++++++++ runtime/queries/git-rebase/injections.scm | 4 ++++ 8 files changed, 33 insertions(+), 6 deletions(-) create mode 160000 helix-syntax/languages/tree-sitter-git-rebase create mode 100644 runtime/queries/git-rebase/highlights.scm create mode 100644 runtime/queries/git-rebase/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 422671b4..22f70c80 100644 --- a/.gitmodules +++ b/.gitmodules @@ -178,3 +178,7 @@ path = helix-syntax/languages/tree-sitter-git-diff url = https://github.com/the-mikedavis/tree-sitter-git-diff.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-git-rebase"] + path = helix-syntax/languages/tree-sitter-git-rebase + url = https://github.com/the-mikedavis/tree-sitter-git-rebase.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 91575c62..09284d46 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -13,6 +13,7 @@ | fish | ✓ | ✓ | ✓ | | | git-commit | ✓ | | | | | git-diff | ✓ | | | | +| git-rebase | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-git-rebase b/helix-syntax/languages/tree-sitter-git-rebase new file mode 160000 index 00000000..332dc528 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-git-rebase @@ -0,0 +1 @@ +Subproject commit 332dc528f27044bc4427024dbb33e6941fc131f2 diff --git a/languages.toml b/languages.toml index c3ae9f62..3d9bac7b 100644 --- a/languages.toml +++ b/languages.toml @@ -490,3 +490,12 @@ file-types = ["diff"] injection-regex = "diff" comment-token = "#" indent = { tab-width = 2, unit = " " } + +[[language]] +name = "git-rebase" +scope = "source.gitrebase" +roots = [] +file-types = ["git-rebase-todo"] +injection-regex = "git-rebase" +comment-token = "#" +indent = { tab-width = 2, unit = " " } diff --git a/runtime/queries/git-commit/highlights.scm b/runtime/queries/git-commit/highlights.scm index ffcc31ae..0b50d419 100644 --- a/runtime/queries/git-commit/highlights.scm +++ b/runtime/queries/git-commit/highlights.scm @@ -4,7 +4,6 @@ (commit) @constant (item) @markup.link.url (header) @tag -(rebase_command) @markup.raw (change kind: "new file" @diff.plus) (change kind: "deleted" @diff.minus) diff --git a/runtime/queries/git-commit/injections.scm b/runtime/queries/git-commit/injections.scm index bd96f1de..cf0657f7 100644 --- a/runtime/queries/git-commit/injections.scm +++ b/runtime/queries/git-commit/injections.scm @@ -3,8 +3,6 @@ (#set! injection.include-children) (#set! injection.language "diff")) -; once a rebase grammar is available, we can inject rebase highlighting into -; interactive rebase summary sections like so: -; -; ((rebase_command) @injection.content -; (#set! injection.language "git-rebase")) +((rebase_command) @injection.content + (#set! injection.include-children) + (#set! injection.language "git-rebase")) diff --git a/runtime/queries/git-rebase/highlights.scm b/runtime/queries/git-rebase/highlights.scm new file mode 100644 index 00000000..4f007037 --- /dev/null +++ b/runtime/queries/git-rebase/highlights.scm @@ -0,0 +1,11 @@ +(operation operator: ["p" "pick" "r" "reword" "e" "edit" "s" "squash" "m" "merge" "d" "drop" "b" "break" "x" "exec"] @keyword) +(operation operator: ["l" "label" "t" "reset"] @function) +(operation operator: ["f" "fixup"] @function.special) + +(option) @operator +(label) @string.special.symbol +(commit) @constant +"#" @punctuation.delimiter +(comment) @comment + +(ERROR) @error diff --git a/runtime/queries/git-rebase/injections.scm b/runtime/queries/git-rebase/injections.scm new file mode 100644 index 00000000..070129b6 --- /dev/null +++ b/runtime/queries/git-rebase/injections.scm @@ -0,0 +1,4 @@ +((operation + operator: ["x" "exec"] + (command) @injection.content) + (#set! injection.language "bash")) -- cgit v1.2.3-70-g09d2 From 8f2af713408b8b40cf71873bbc0ddc009a7b3da5 Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Mon, 3 Jan 2022 02:57:55 +0100 Subject: Add LLVM TableGen highlighting (#1409) Add a tree-sitter grammar and highlights for TableGen files. TableGen and its grammar are described here: https://llvm.org/docs/TableGen/index.html Co-authored-by: Blaž Hrastnik --- .gitmodules | 4 ++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-tablegen | 1 + languages.toml | 9 +++ runtime/queries/tablegen/highlights.scm | 90 +++++++++++++++++++++++++++++ runtime/queries/tablegen/indents.toml | 7 +++ runtime/queries/tablegen/injections.scm | 2 + runtime/queries/tablegen/textobjects.scm | 7 +++ 8 files changed, 121 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-tablegen create mode 100644 runtime/queries/tablegen/highlights.scm create mode 100644 runtime/queries/tablegen/indents.toml create mode 100644 runtime/queries/tablegen/injections.scm create mode 100644 runtime/queries/tablegen/textobjects.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 22f70c80..b617e60c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -178,6 +178,10 @@ path = helix-syntax/languages/tree-sitter-git-diff url = https://github.com/the-mikedavis/tree-sitter-git-diff.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-tablegen"] + path = helix-syntax/languages/tree-sitter-tablegen + url = https://github.com/Flakebi/tree-sitter-tablegen + shallow = true [submodule "helix-syntax/languages/tree-sitter-git-rebase"] path = helix-syntax/languages/tree-sitter-git-rebase url = https://github.com/the-mikedavis/tree-sitter-git-rebase.git diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 09284d46..73712ff2 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -40,6 +40,7 @@ | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | | svelte | ✓ | | ✓ | `svelteserver` | +| tablegen | ✓ | ✓ | ✓ | | | toml | ✓ | | | | | tsq | ✓ | | | | | tsx | ✓ | | | `typescript-language-server` | diff --git a/helix-syntax/languages/tree-sitter-tablegen b/helix-syntax/languages/tree-sitter-tablegen new file mode 160000 index 00000000..568dd8a9 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-tablegen @@ -0,0 +1 @@ +Subproject commit 568dd8a937347175fd58db83d4c4cdaeb6069bd2 diff --git a/languages.toml b/languages.toml index f088a3aa..7a895a60 100644 --- a/languages.toml +++ b/languages.toml @@ -436,6 +436,15 @@ file-types = ["ll"] comment-token = ";" indent = { tab-width = 2, unit = " " } +[[language]] +name = "tablegen" +scope = "source.tablegen" +roots = [] +file-types = ["td"] +comment-token = "//" +indent = { tab-width = 2, unit = " " } +injection-regex = "tablegen" + [[language]] name = "markdown" scope = "source.md" diff --git a/runtime/queries/tablegen/highlights.scm b/runtime/queries/tablegen/highlights.scm new file mode 100644 index 00000000..8ade5ba9 --- /dev/null +++ b/runtime/queries/tablegen/highlights.scm @@ -0,0 +1,90 @@ +[ + (comment) + (multiline_comment) +] @comment + +[ + "(" + ")" + "[" + "]" + "{" + "}" + "<" + ">" +] @punctuation.bracket + +[ + "," + ";" + "." +] @punctuation.delimiter + +[ + "#" + "-" + "..." + ":" +] @operator + +[ + "=" + "!cond" + (operator_keyword) +] @function + +[ + "true" + "false" +] @constant.builtin.boolean + +[ + "?" +] @constant.builtin + +(var) @variable + +(template_arg (identifier) @variable.parameter) + +(_ argument: (value (identifier) @variable.parameter)) + +(type) @type + +"code" @type.builtin + +(number) @constant.numeric.integer +[ + (string_string) + (code_string) +] @string + +(preprocessor) @keyword.directive + +[ + "class" + "field" + "let" + "defvar" + "def" + "defset" + "defvar" + "assert" +] @keyword + +[ + "let" + "in" + "foreach" + "if" + "then" + "else" +] @keyword.operator + +"include" @keyword.control.import + +[ + "multiclass" + "defm" +] @namespace + +(ERROR) @error diff --git a/runtime/queries/tablegen/indents.toml b/runtime/queries/tablegen/indents.toml new file mode 100644 index 00000000..43532f4d --- /dev/null +++ b/runtime/queries/tablegen/indents.toml @@ -0,0 +1,7 @@ +indent = [ + "statement", +] + +outdent = [ + "}", +] diff --git a/runtime/queries/tablegen/injections.scm b/runtime/queries/tablegen/injections.scm new file mode 100644 index 00000000..0b476f86 --- /dev/null +++ b/runtime/queries/tablegen/injections.scm @@ -0,0 +1,2 @@ +([ (comment) (multiline_comment)] @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/tablegen/textobjects.scm b/runtime/queries/tablegen/textobjects.scm new file mode 100644 index 00000000..2cb80268 --- /dev/null +++ b/runtime/queries/tablegen/textobjects.scm @@ -0,0 +1,7 @@ +(class + body: (_) @class.inside) @class.around + +(multiclass + body: (_) @class.inside) @class.around + +(_ argument: _ @parameter.inside) -- cgit v1.2.3-70-g09d2 From ed97ecceb8d1f53bd192deeb38a1bde36a45edc2 Mon Sep 17 00:00:00 2001 From: Omnikar Date: Sun, 2 Jan 2022 21:31:24 -0500 Subject: Add `:cquit!` command and prevent `:cquit` from ignoring unsaved changes (#1414) * Add `:cquit!` command and prevent `:cquit` from ignoring unsaved changes * `cargo xtask docgen`--- book/src/generated/typable-cmd.md | 1 + helix-term/src/commands.rs | 45 ++++++++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index 45129cc1..65b2dc5f 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -20,6 +20,7 @@ | `:quit-all`, `:qa` | Close all views. | | `:quit-all!`, `:qa!` | Close all views forcefully (ignoring unsaved changes). | | `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). | +| `:cquit!`, `:cq!` | Quit with exit code (default 1) forcefully (ignoring unsaved changes). Accepts an optional integer exit code (:cq! 2). | | `:theme` | Change the editor theme. | | `:clipboard-yank` | Yank main selection into system clipboard. | | `:clipboard-yank-join` | Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline. | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 842d8b60..ccc25c54 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2322,12 +2322,7 @@ pub mod cmd { write_all_impl(cx, args, event, true, true) } - fn quit_all_impl( - editor: &mut Editor, - _args: &[Cow], - _event: PromptEvent, - force: bool, - ) -> anyhow::Result<()> { + fn quit_all_impl(editor: &mut Editor, force: bool) -> anyhow::Result<()> { if !force { buffers_remaining_impl(editor)?; } @@ -2343,18 +2338,18 @@ pub mod cmd { fn quit_all( cx: &mut compositor::Context, - args: &[Cow], - event: PromptEvent, + _args: &[Cow], + _event: PromptEvent, ) -> anyhow::Result<()> { - quit_all_impl(cx.editor, args, event, false) + quit_all_impl(cx.editor, false) } fn force_quit_all( cx: &mut compositor::Context, - args: &[Cow], - event: PromptEvent, + _args: &[Cow], + _event: PromptEvent, ) -> anyhow::Result<()> { - quit_all_impl(cx.editor, args, event, true) + quit_all_impl(cx.editor, true) } fn cquit( @@ -2368,12 +2363,21 @@ pub mod cmd { .unwrap_or(1); cx.editor.exit_code = exit_code; - let views: Vec<_> = cx.editor.tree.views().map(|(view, _)| view.id).collect(); - for view_id in views { - cx.editor.close(view_id); - } + quit_all_impl(cx.editor, false) + } - Ok(()) + fn force_cquit( + cx: &mut compositor::Context, + args: &[Cow], + _event: PromptEvent, + ) -> anyhow::Result<()> { + let exit_code = args + .first() + .and_then(|code| code.parse::().ok()) + .unwrap_or(1); + cx.editor.exit_code = exit_code; + + quit_all_impl(cx.editor, true) } fn theme( @@ -2877,6 +2881,13 @@ pub mod cmd { fun: cquit, completer: None, }, + TypableCommand { + name: "cquit!", + aliases: &["cq!"], + doc: "Quit with exit code (default 1) forcefully (ignoring unsaved changes). Accepts an optional integer exit code (:cq! 2).", + fun: force_cquit, + completer: None, + }, TypableCommand { name: "theme", aliases: &[], -- cgit v1.2.3-70-g09d2 From 641255ccc83648d164bf6e8e8e4e93460591830b Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Tue, 4 Jan 2022 02:52:34 +0100 Subject: Add llvm-mir highlighting (#1398) * Add injection regex for more languages To support embedding them in other languages like markdown. * Add llvm-mir highlighting LLVM Machine IR is dumped as yaml files that can embed LLVM IR and Machine IR. To support this, add a llvm-mir-yaml language that uses the yaml parser, but uses different injections to highlight IR and MIR. * Update submodule with fixed multiline comments Co-authored-by: Blaž Hrastnik --- .gitmodules | 4 + book/src/generated/lang-support.md | 2 + helix-core/src/indent.rs | 1 + helix-core/src/syntax.rs | 13 ++- helix-syntax/languages/tree-sitter-llvm-mir | 1 + languages.toml | 22 +++++ runtime/queries/llvm-mir-yaml/highlights.scm | 1 + runtime/queries/llvm-mir-yaml/indents.toml | 3 + runtime/queries/llvm-mir-yaml/injections.scm | 9 ++ runtime/queries/llvm-mir/highlights.scm | 136 +++++++++++++++++++++++++++ runtime/queries/llvm-mir/indents.toml | 7 ++ runtime/queries/llvm-mir/injections.scm | 2 + runtime/queries/llvm-mir/textobjects.scm | 3 + runtime/queries/yaml/injections.scm | 2 + 14 files changed, 203 insertions(+), 3 deletions(-) create mode 160000 helix-syntax/languages/tree-sitter-llvm-mir create mode 100644 runtime/queries/llvm-mir-yaml/highlights.scm create mode 100644 runtime/queries/llvm-mir-yaml/indents.toml create mode 100644 runtime/queries/llvm-mir-yaml/injections.scm create mode 100644 runtime/queries/llvm-mir/highlights.scm create mode 100644 runtime/queries/llvm-mir/indents.toml create mode 100644 runtime/queries/llvm-mir/injections.scm create mode 100644 runtime/queries/llvm-mir/textobjects.scm create mode 100644 runtime/queries/yaml/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index b617e60c..9297708a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -174,6 +174,10 @@ path = helix-syntax/languages/tree-sitter-git-commit url = https://github.com/the-mikedavis/tree-sitter-git-commit.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-llvm-mir"] + path = helix-syntax/languages/tree-sitter-llvm-mir + url = https://github.com/Flakebi/tree-sitter-llvm-mir.git + shallow = true [submodule "helix-syntax/languages/tree-sitter-git-diff"] path = helix-syntax/languages/tree-sitter-git-diff url = https://github.com/the-mikedavis/tree-sitter-git-diff.git diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 73712ff2..ee719b56 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -24,6 +24,8 @@ | latex | ✓ | | | | | ledger | ✓ | | | | | llvm | ✓ | ✓ | ✓ | | +| llvm-mir | ✓ | ✓ | ✓ | | +| llvm-mir-yaml | ✓ | | ✓ | | | lua | ✓ | | ✓ | | | markdown | ✓ | | | | | mint | | | | `mint` | diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 28066aa6..1fc2b8a5 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -436,6 +436,7 @@ where comment_token: None, auto_format: false, diagnostic_severity: Severity::Warning, + tree_sitter_library: None, language_server: None, indent: Some(IndentationConfiguration { tab_width: 4, diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index cdae0210..5d37c219 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -67,6 +67,8 @@ pub struct LanguageConfiguration { #[serde(default)] pub diagnostic_severity: Severity, + pub tree_sitter_library: Option, // tree-sitter library name, defaults to language_id + // content_regex #[serde(default, skip_serializing, deserialize_with = "deserialize_regex")] pub injection_regex: Option, @@ -192,9 +194,14 @@ impl LanguageConfiguration { if highlights_query.is_empty() { None } else { - let language = get_language(&crate::RUNTIME_DIR, &self.language_id) - .map_err(|e| log::info!("{}", e)) - .ok()?; + let language = get_language( + &crate::RUNTIME_DIR, + self.tree_sitter_library + .as_deref() + .unwrap_or(&self.language_id), + ) + .map_err(|e| log::info!("{}", e)) + .ok()?; let config = HighlightConfiguration::new( language, &highlights_query, diff --git a/helix-syntax/languages/tree-sitter-llvm-mir b/helix-syntax/languages/tree-sitter-llvm-mir new file mode 160000 index 00000000..06fabca1 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-llvm-mir @@ -0,0 +1 @@ +Subproject commit 06fabca19454b2dc00c1b211a7cb7ad0bc2585f1 diff --git a/languages.toml b/languages.toml index 7a895a60..e8329fe7 100644 --- a/languages.toml +++ b/languages.toml @@ -334,6 +334,7 @@ file-types = ["yml", "yaml"] roots = [] comment-token = "#" indent = { tab-width = 2, unit = " " } +injection-regex = "yml|yaml" # [[language]] # name = "haskell" @@ -386,6 +387,7 @@ roots = [] comment-token = "#" indent = { tab-width = 2, unit = " " } language-server = { command = "cmake-language-server" } +injection-regex = "cmake" [[language]] name = "glsl" @@ -394,6 +396,7 @@ file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ] roots = [] comment-token = "//" indent = { tab-width = 4, unit = " " } +injection-regex = "glsl" [[language]] name = "perl" @@ -435,6 +438,25 @@ roots = [] file-types = ["ll"] comment-token = ";" indent = { tab-width = 2, unit = " " } +injection-regex = "llvm" + +[[language]] +name = "llvm-mir" +scope = "source.llvm_mir" +roots = [] +file-types = [] +comment-token = ";" +indent = { tab-width = 2, unit = " " } +injection-regex = "mir" + +[[language]] +name = "llvm-mir-yaml" +tree-sitter-library = "yaml" +scope = "source.yaml" +roots = [] +file-types = ["mir"] +comment-token = "#" +indent = { tab-width = 2, unit = " " } [[language]] name = "tablegen" diff --git a/runtime/queries/llvm-mir-yaml/highlights.scm b/runtime/queries/llvm-mir-yaml/highlights.scm new file mode 100644 index 00000000..4ba254e8 --- /dev/null +++ b/runtime/queries/llvm-mir-yaml/highlights.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/llvm-mir-yaml/indents.toml b/runtime/queries/llvm-mir-yaml/indents.toml new file mode 100644 index 00000000..ddc3578b --- /dev/null +++ b/runtime/queries/llvm-mir-yaml/indents.toml @@ -0,0 +1,3 @@ +indent = [ + "block_mapping_pair", +] diff --git a/runtime/queries/llvm-mir-yaml/injections.scm b/runtime/queries/llvm-mir-yaml/injections.scm new file mode 100644 index 00000000..b3243022 --- /dev/null +++ b/runtime/queries/llvm-mir-yaml/injections.scm @@ -0,0 +1,9 @@ +; inherits: yaml + +((document (block_node (block_scalar) @injection.content)) + (#set! injection.language "llvm")) + +((document (block_node (block_mapping (block_mapping_pair + key: (flow_node (plain_scalar (string_scalar))) ; "body" + value: (block_node (block_scalar) @injection.content))))) + (#set! injection.language "mir")) diff --git a/runtime/queries/llvm-mir/highlights.scm b/runtime/queries/llvm-mir/highlights.scm new file mode 100644 index 00000000..79234612 --- /dev/null +++ b/runtime/queries/llvm-mir/highlights.scm @@ -0,0 +1,136 @@ +[ + (label) + (bb_ref) +] @label + +[ + (comment) + (multiline_comment) +] @comment + +[ + "(" + ")" + "[" + "]" + "{" + "}" + "<" + ">" +] @punctuation.bracket + +[ + "," + ":" + "|" + "*" +] @punctuation.delimiter + +[ + "=" + "x" +] @operator + +[ + "true" + "false" +] @constant.builtin.boolean + +[ + "null" + "_" + "unknown-address" +] @constant.builtin + +[ + (stack_object) + (constant_pool_index) + (jump_table_index) + (var) + (physical_register) + (ir_block) + (external_symbol) + (global_var) + (ir_local_var) + (metadata_ref) + (mnemonic) +] @variable + +(low_level_type) @type + +[ + (immediate_type) + (primitive_type) +] @type.builtin + +(number) @constant.numeric.integer +(float) @constant.numeric.float +(string) @string + +(instruction name: _ @keyword.operator) + +[ + "successors" + "liveins" + "pre-instr-symbol" + "post-instr-symbol" + "heap-alloc-marker" + "debug-instr-number" + "debug-location" + "mcsymbol" + "tied-def" + "target-flags" + "CustomRegMask" + "same_value" + "def_cfa_register" + "restore" + "undefined" + "offset" + "rel_offset" + "def_cfa" + "llvm_def_aspace_cfa" + "register" + "escape" + "remember_state" + "restore_state" + "window_save" + "negate_ra_sign_state" + "intpred" + "floatpred" + "shufflemask" + "liveout" + "target-index" + "blockaddress" + "intrinsic" + "load" + "store" + "unknown-size" + "on" + "from" + "into" + "align" + "basealign" + "addrspace" + "call-entry" + "custom" + "constant-pool" + "stack" + "got" + "jump-table" + "syncscope" + "address-taken" + "landing-pad" + "inlineasm-br-indirect-target" + "ehfunclet-entry" + "bbsections" + + (intpred) + (floatpred) + (memory_operand_flag) + (atomic_ordering) + (register_flag) + (instruction_flag) + (float_keyword) +] @keyword + +(ERROR) @error diff --git a/runtime/queries/llvm-mir/indents.toml b/runtime/queries/llvm-mir/indents.toml new file mode 100644 index 00000000..6a70e5ad --- /dev/null +++ b/runtime/queries/llvm-mir/indents.toml @@ -0,0 +1,7 @@ +indent = [ + "basic_block", +] + +outdent = [ + "label", +] diff --git a/runtime/queries/llvm-mir/injections.scm b/runtime/queries/llvm-mir/injections.scm new file mode 100644 index 00000000..0b476f86 --- /dev/null +++ b/runtime/queries/llvm-mir/injections.scm @@ -0,0 +1,2 @@ +([ (comment) (multiline_comment)] @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/llvm-mir/textobjects.scm b/runtime/queries/llvm-mir/textobjects.scm new file mode 100644 index 00000000..73f6f772 --- /dev/null +++ b/runtime/queries/llvm-mir/textobjects.scm @@ -0,0 +1,3 @@ +(basic_block) @function.around + +(argument) @parameter.inside diff --git a/runtime/queries/yaml/injections.scm b/runtime/queries/yaml/injections.scm new file mode 100644 index 00000000..39bda293 --- /dev/null +++ b/runtime/queries/yaml/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) -- cgit v1.2.3-70-g09d2 From 5b1a628e81b7d2f198ef401d442ca7967c5a0135 Mon Sep 17 00:00:00 2001 From: Sebastian Neubauer Date: Tue, 4 Jan 2022 02:53:04 +0100 Subject: Add textobjects and indents to c and cpp (#1293) Indentation of single line statements doesn't work, i.e. for (;;) leads to for(;;) Only blocks with curly braces are indented.--- book/src/generated/lang-support.md | 4 ++-- runtime/queries/c/indents.toml | 16 ++++++++++++++++ runtime/queries/c/textobjects.scm | 13 +++++++++++++ runtime/queries/cpp/indents.toml | 17 +++++++++++++++++ runtime/queries/cpp/textobjects.scm | 7 +++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 runtime/queries/c/indents.toml create mode 100644 runtime/queries/c/textobjects.scm create mode 100644 runtime/queries/cpp/indents.toml create mode 100644 runtime/queries/cpp/textobjects.scm (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index ee719b56..a1fbf172 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -1,11 +1,11 @@ | Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP | | --- | --- | --- | --- | --- | | bash | ✓ | | | `bash-language-server` | -| c | ✓ | | | `clangd` | +| c | ✓ | ✓ | ✓ | `clangd` | | c-sharp | ✓ | | | | | cmake | ✓ | ✓ | ✓ | `cmake-language-server` | | comment | ✓ | | | | -| cpp | ✓ | | | `clangd` | +| cpp | ✓ | ✓ | ✓ | `clangd` | | css | ✓ | | | | | dart | ✓ | | ✓ | `dart` | | dockerfile | ✓ | | | `docker-langserver` | diff --git a/runtime/queries/c/indents.toml b/runtime/queries/c/indents.toml new file mode 100644 index 00000000..f4076e17 --- /dev/null +++ b/runtime/queries/c/indents.toml @@ -0,0 +1,16 @@ +indent = [ + "compound_statement", + "field_declaration_list", + "enumerator_list", + "parameter_list", + "init_declarator", + "case_statement", + "condition_clause", + "expression_statement", +] + +outdent = [ + "case", + "}", + "]", +] diff --git a/runtime/queries/c/textobjects.scm b/runtime/queries/c/textobjects.scm new file mode 100644 index 00000000..b0f03668 --- /dev/null +++ b/runtime/queries/c/textobjects.scm @@ -0,0 +1,13 @@ +(function_definition + body: (_) @function.inside) @function.around + +(struct_specifier + body: (_) @class.inside) @class.around + +(enum_specifier + body: (_) @class.inside) @class.around + +(union_specifier + body: (_) @class.inside) @class.around + +(parameter_declaration) @parameter.inside diff --git a/runtime/queries/cpp/indents.toml b/runtime/queries/cpp/indents.toml new file mode 100644 index 00000000..0ca2ed8b --- /dev/null +++ b/runtime/queries/cpp/indents.toml @@ -0,0 +1,17 @@ +indent = [ + "compound_statement", + "field_declaration_list", + "enumerator_list", + "parameter_list", + "init_declarator", + "case_statement", + "condition_clause", + "expression_statement", +] + +outdent = [ + "case", + "access_specifier", + "}", + "]", +] diff --git a/runtime/queries/cpp/textobjects.scm b/runtime/queries/cpp/textobjects.scm new file mode 100644 index 00000000..6e3de1a2 --- /dev/null +++ b/runtime/queries/cpp/textobjects.scm @@ -0,0 +1,7 @@ +; inherits: c + +(lambda_expression + body: (_) @function.inside) @function.around + +(class_specifier + body: (_) @class.inside) @class.around -- cgit v1.2.3-70-g09d2 From 2e02a1d6bc004212033b9c4e5ed0de0fd880796c Mon Sep 17 00:00:00 2001 From: Matouš Dzivjak Date: Thu, 6 Jan 2022 03:12:02 +0100 Subject: feat(commands): shrink_selection (#1340) * feat(commands): shrink_selection Add `shrink_selection` command that can be used to shrink previously expanded selection. To make `shrink_selection` work it was necessary to add selection history to the Document since we want to shrink the selection towards the syntax tree node that was initially selected. Selection history is cleared any time the user changes selection other way than by `expand_selection`. This ensures that we don't get some funky edge cases when user calls `shrink_selection`. Related: https://github.com/helix-editor/helix/discussions/1328 * Refactor shrink_selection, move history to view * Remove useless comment * Add default key mapping for extend&shrink selection * Rework contains_selection method * Shrink selection without expand selects first child--- book/src/keymap.md | 2 ++ helix-core/src/object.rs | 29 ++++++++++++++++++-- helix-core/src/selection.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++ helix-term/src/commands.rs | 36 ++++++++++++++++++++++++- helix-term/src/keymap.rs | 2 ++ helix-view/src/view.rs | 3 +++ 6 files changed, 133 insertions(+), 3 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 581e70e9..70ec13b3 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -261,6 +261,8 @@ Mappings in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaire | `]D` | Go to last diagnostic in document (**LSP**) | `goto_last_diag` | | `[space` | Add newline above | `add_newline_above` | | `]space` | Add newline below | `add_newline_below` | +| `]o` | Expand syntax tree object selection. | `expand_selection` | +| `[o` | Shrink syntax tree object selection. | `shrink_selection` | ## Insert Mode diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs index 717c5994..21fa24fb 100644 --- a/helix-core/src/object.rs +++ b/helix-core/src/object.rs @@ -1,7 +1,5 @@ use crate::{Range, RopeSlice, Selection, Syntax}; -// TODO: to contract_selection we'd need to store the previous ranges before expand. -// Maybe just contract to the first child node? pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection { let tree = syntax.tree(); @@ -34,3 +32,30 @@ pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) } }) } + +pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection { + let tree = syntax.tree(); + + selection.clone().transform(|range| { + let from = text.char_to_byte(range.from()); + let to = text.char_to_byte(range.to()); + + let descendant = match tree.root_node().descendant_for_byte_range(from, to) { + // find first child, if not possible, fallback to the node that contains selection + Some(descendant) => match descendant.child(0) { + Some(child) => child, + None => descendant, + }, + None => return range, + }; + + let from = text.byte_to_char(descendant.start_byte()); + let to = text.byte_to_char(descendant.end_byte()); + + if range.head < range.anchor { + Range::new(to, from) + } else { + Range::new(from, to) + } + }) +} diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index 06ea9d67..1515c4fc 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -140,6 +140,11 @@ impl Range { self.from() == other.from() || (self.to() > other.from() && other.to() > self.from()) } + #[inline] + pub fn contains_range(&self, other: &Self) -> bool { + self.from() <= other.from() && self.to() >= other.to() + } + pub fn contains(&self, pos: usize) -> bool { self.from() <= pos && pos < self.to() } @@ -544,6 +549,39 @@ impl Selection { pub fn len(&self) -> usize { self.ranges.len() } + + // returns true if self ⊇ other + pub fn contains(&self, other: &Selection) -> bool { + // can't contain other if it is larger + if other.len() > self.len() { + return false; + } + + let (mut iter_self, mut iter_other) = (self.iter(), other.iter()); + let (mut ele_self, mut ele_other) = (iter_self.next(), iter_other.next()); + + loop { + match (ele_self, ele_other) { + (Some(ra), Some(rb)) => { + if !ra.contains_range(rb) { + // `self` doesn't contain next element from `other`, advance `self`, we need to match all from `other` + ele_self = iter_self.next(); + } else { + // matched element from `other`, advance `other` + ele_other = iter_other.next(); + }; + } + (None, Some(_)) => { + // exhausted `self`, we can't match the reminder of `other` + return false; + } + (_, None) => { + // no elements from `other` left to match, `self` contains `other` + return true; + } + } + } + } } impl<'a> IntoIterator for &'a Selection { @@ -982,4 +1020,30 @@ mod test { &["", "abcd", "efg", "rs", "xyz"] ); } + #[test] + fn test_selection_contains() { + fn contains(a: Vec<(usize, usize)>, b: Vec<(usize, usize)>) -> bool { + let sela = Selection::new(a.iter().map(|a| Range::new(a.0, a.1)).collect(), 0); + let selb = Selection::new(b.iter().map(|b| Range::new(b.0, b.1)).collect(), 0); + sela.contains(&selb) + } + + // exact match + assert!(contains(vec!((1, 1)), vec!((1, 1)))); + + // larger set contains smaller + assert!(contains(vec!((1, 1), (2, 2), (3, 3)), vec!((2, 2)))); + + // multiple matches + assert!(contains(vec!((1, 1), (2, 2)), vec!((1, 1), (2, 2)))); + + // smaller set can't contain bigger + assert!(!contains(vec!((1, 1)), vec!((1, 1), (2, 2)))); + + assert!(contains( + vec!((1, 1), (2, 4), (5, 6), (7, 9), (10, 13)), + vec!((3, 4), (7, 9)) + )); + assert!(!contains(vec!((1, 1), (5, 6)), vec!((1, 6)))); + } } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index bf12b122..5c26a5b2 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -362,6 +362,7 @@ impl MappableCommand { rotate_selection_contents_forward, "Rotate selection contents forward", rotate_selection_contents_backward, "Rotate selections contents backward", expand_selection, "Expand selection to parent syntax node", + shrink_selection, "Shrink selection to previously expanded syntax node", jump_forward, "Jump forward on jumplist", jump_backward, "Jump backward on jumplist", save_selection, "Save the current selection to the jumplist", @@ -5467,6 +5468,7 @@ fn rotate_selection_contents(cx: &mut Context, direction: Direction) { doc.apply(&transaction, view.id); doc.append_changes_to_history(view.id); } + fn rotate_selection_contents_forward(cx: &mut Context) { rotate_selection_contents(cx, Direction::Forward) } @@ -5482,7 +5484,39 @@ fn expand_selection(cx: &mut Context) { if let Some(syntax) = doc.syntax() { let text = doc.text().slice(..); - let selection = object::expand_selection(syntax, text, doc.selection(view.id)); + + let current_selection = doc.selection(view.id); + + // save current selection so it can be restored using shrink_selection + view.object_selections.push(current_selection.clone()); + + let selection = object::expand_selection(syntax, text, current_selection); + doc.set_selection(view.id, selection); + } + }; + motion(cx.editor); + cx.editor.last_motion = Some(Motion(Box::new(motion))); +} + +fn shrink_selection(cx: &mut Context) { + let motion = |editor: &mut Editor| { + let (view, doc) = current!(editor); + let current_selection = doc.selection(view.id); + // try to restore previous selection + if let Some(prev_selection) = view.object_selections.pop() { + if current_selection.contains(&prev_selection) { + // allow shrinking the selection only if current selection contains the previous object selection + doc.set_selection(view.id, prev_selection); + return; + } else { + // clear existing selection as they can't be shrinked to anyway + view.object_selections.clear(); + } + } + // if not previous selection, shrink to first child + if let Some(syntax) = doc.syntax() { + let text = doc.text().slice(..); + let selection = object::shrink_selection(syntax, text, current_selection); doc.set_selection(view.id, selection); } }; diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 72833212..49f8469a 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -569,11 +569,13 @@ impl Default for Keymaps { "d" => goto_prev_diag, "D" => goto_first_diag, "space" => add_newline_above, + "o" => shrink_selection, }, "]" => { "Right bracket" "d" => goto_next_diag, "D" => goto_last_diag, "space" => add_newline_below, + "o" => expand_selection, }, "/" => search, diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 94d67acd..89a6c196 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -80,6 +80,8 @@ pub struct View { // uses two docs because we want to be able to swap between the // two last modified docs which we need to manually keep track of pub last_modified_docs: [Option; 2], + /// used to store previous selections of tree-sitter objecs + pub object_selections: Vec, } impl View { @@ -92,6 +94,7 @@ impl View { jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel last_accessed_doc: None, last_modified_docs: [None, None], + object_selections: Vec::new(), } } -- cgit v1.2.3-70-g09d2 From a8fd33ac012a79069ef1409503a2edcf3a585153 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 6 Jan 2022 09:00:00 -0600 Subject: add tree-sitter-regex (#1362) * add tree-sitter-regex * adapt regex highlights from upstream * inject regex into elixir sigil_r/2 and sigil_R/2 * generate lang-support docs * capture interesting nodes in character-ranges * make $.character_class captures more consistent * fix fallthrough behavior for character classes * capture pattern characters as 'string' * use latest tree-sitter-regex * set elixir regex injections as combined * add link to upstream queries * inject regex in rust into 'Regex::new' raw string literals--- .gitmodules | 4 +++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-regex | 1 + languages.toml | 7 +++++ runtime/queries/elixir/injections.scm | 7 +++++ runtime/queries/regex/highlights.scm | 53 ++++++++++++++++++++++++++++++++ runtime/queries/rust/injections.scm | 14 +++++++++ 7 files changed, 87 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-regex create mode 100644 runtime/queries/regex/highlights.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 9297708a..f6a0fdc4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -190,3 +190,7 @@ path = helix-syntax/languages/tree-sitter-git-rebase url = https://github.com/the-mikedavis/tree-sitter-git-rebase.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-regex"] + path = helix-syntax/languages/tree-sitter-regex + url = https://github.com/tree-sitter/tree-sitter-regex.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index a1fbf172..daf8b006 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -38,6 +38,7 @@ | protobuf | ✓ | | ✓ | | | python | ✓ | ✓ | ✓ | `pylsp` | | racket | | | | `racket` | +| regex | ✓ | | | | | ruby | ✓ | | ✓ | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | diff --git a/helix-syntax/languages/tree-sitter-regex b/helix-syntax/languages/tree-sitter-regex new file mode 160000 index 00000000..e1cfca3c --- /dev/null +++ b/helix-syntax/languages/tree-sitter-regex @@ -0,0 +1 @@ +Subproject commit e1cfca3c79896ff79842f057ea13e529b66af636 diff --git a/languages.toml b/languages.toml index e8329fe7..3e2e7b15 100644 --- a/languages.toml +++ b/languages.toml @@ -530,3 +530,10 @@ file-types = ["git-rebase-todo"] injection-regex = "git-rebase" comment-token = "#" indent = { tab-width = 2, unit = " " } + +[[language]] +name = "regex" +scope = "source.regex" +injection-regex = "regex" +file-types = ["regex"] +roots = [] diff --git a/runtime/queries/elixir/injections.scm b/runtime/queries/elixir/injections.scm index 321c90ad..8370a0d8 100644 --- a/runtime/queries/elixir/injections.scm +++ b/runtime/queries/elixir/injections.scm @@ -1,2 +1,9 @@ ((comment) @injection.content (#set! injection.language "comment")) + +((sigil + (sigil_name) @_sigil_name + (quoted_content) @injection.content) + (#match? @_sigil_name "^(r|R)$") + (#set! injection.language "regex") + (#set! injection.combined)) diff --git a/runtime/queries/regex/highlights.scm b/runtime/queries/regex/highlights.scm new file mode 100644 index 00000000..9376caa9 --- /dev/null +++ b/runtime/queries/regex/highlights.scm @@ -0,0 +1,53 @@ +; upstream: https://github.com/tree-sitter/tree-sitter-regex/blob/e1cfca3c79896ff79842f057ea13e529b66af636/queries/highlights.scm + +[ + "(" + ")" + "(?" + "(?:" + "(?<" + ">" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "*" + "+" + "|" + "=" + "<=" + "!" + ""` to your [`config.toml`](./configuration.md) at the very top of the file before the first section or select it during runtime using `:theme `. -To use a custom theme add `theme = ` to your [`config.toml`](./configuration.md) or override it during runtime using `:theme `. +## Creating a theme -The default theme.toml can be found [here](https://github.com/helix-editor/helix/blob/master/theme.toml), and user submitted themes [here](https://github.com/helix-editor/helix/blob/master/runtime/themes). +Create a file with the name of your theme as file name (i.e `mytheme.toml`) and place it in your `themes` directory (i.e `~/.config/helix/themes`). The directory might have to be created beforehand. -## Creating a theme +The names "default" and "base16_default" are reserved for the builtin themes and cannot be overridden by user defined themes. -First create a file with the name of your theme as file name (i.e `mytheme.toml`) and place it in your `themes` directory (i.e `~/.config/helix/themes`). +The default theme.toml can be found [here](https://github.com/helix-editor/helix/blob/master/theme.toml), and user submitted themes [here](https://github.com/helix-editor/helix/blob/master/runtime/themes). Each line in the theme file is specified as below: -- cgit v1.2.3-70-g09d2 From 5e2269486598645a6e9511ea25f87b3609511d77 Mon Sep 17 00:00:00 2001 From: Kevin Sjöberg Date: Sat, 8 Jan 2022 16:27:10 +0100 Subject: Add default language server for JavaScript (#1457) * Add default language server for JavaScript * Update lang support documentation--- book/src/generated/lang-support.md | 2 +- languages.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index daf8b006..384ba96b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -18,7 +18,7 @@ | go | ✓ | ✓ | ✓ | `gopls` | | html | ✓ | | | | | java | ✓ | | | | -| javascript | ✓ | | ✓ | | +| javascript | ✓ | | ✓ | `typescript-language-server` | | json | ✓ | | ✓ | | | julia | ✓ | | | `julia` | | latex | ✓ | | | | diff --git a/languages.toml b/languages.toml index 3e2e7b15..c8f9bab4 100644 --- a/languages.toml +++ b/languages.toml @@ -128,6 +128,7 @@ roots = [] comment-token = "//" # TODO: highlights-jsx, highlights-params +language-server = { command = "typescript-language-server", args = ["--stdio"] } indent = { tab-width = 2, unit = " " } [[language]] -- cgit v1.2.3-70-g09d2 From b799b0d50e7848cc084d913afbdc0fb3a25c1b97 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Sat, 8 Jan 2022 09:27:50 -0600 Subject: capture markdown link text as markup.link.text (#1456) --- book/src/themes.md | 5 +++-- runtime/queries/markdown/highlights.scm | 5 +++++ theme.toml | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index 7474122f..29d3926e 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -171,8 +171,9 @@ We use a similar set of scopes as - `bold` - `italic` - `link` - - `url` - - `label` + - `url` - urls pointed to by links + - `label` - non-url link references + - `text` - url and image descriptions in links - `quote` - `raw` - `inline` diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm index a0bd3462..f12254e9 100644 --- a/runtime/queries/markdown/highlights.scm +++ b/runtime/queries/markdown/highlights.scm @@ -21,6 +21,11 @@ (link_destination) @markup.link.url (link_label) @markup.link.label +[ + (link_text) + (image_description) +] @markup.link.text + [ (list_marker_plus) (list_marker_minus) diff --git a/theme.toml b/theme.toml index ca0b2805..d2c1fc32 100644 --- a/theme.toml +++ b/theme.toml @@ -32,6 +32,7 @@ label = "honey" "markup.bold" = { modifiers = ["bold"] } "markup.italic" = { modifiers = ["italic"] } "markup.link.url" = { fg = "silver", modifiers = ["underlined"] } +"markup.link.text" = "almond" "markup.raw" = "almond" "diff.plus" = "#35bf86" -- cgit v1.2.3-70-g09d2 From 1c6bc6d455595aa5b8d7d2aa27d025722f57c351 Mon Sep 17 00:00:00 2001 From: Eric Crosson Date: Mon, 3 Jan 2022 19:17:06 -0600 Subject: feat: add tree-sitter-make This commit adds syntax highlighting for GNU Make[^1] makefiles via tree-sitter-make[^2]. [^1]: https://www.gnu.org/software/make/ [^2]: https://github.com/alemuller/tree-sitter-make --- .gitmodules | 6 +- book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-make | 1 + languages.toml | 7 ++ runtime/queries/make/highlights.scm | 170 ++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 1 deletion(-) create mode 160000 helix-syntax/languages/tree-sitter-make create mode 100644 runtime/queries/make/highlights.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index f6a0fdc4..e6d9d654 100644 --- a/.gitmodules +++ b/.gitmodules @@ -177,7 +177,7 @@ [submodule "helix-syntax/languages/tree-sitter-llvm-mir"] path = helix-syntax/languages/tree-sitter-llvm-mir url = https://github.com/Flakebi/tree-sitter-llvm-mir.git - shallow = true + shallow = true [submodule "helix-syntax/languages/tree-sitter-git-diff"] path = helix-syntax/languages/tree-sitter-git-diff url = https://github.com/the-mikedavis/tree-sitter-git-diff.git @@ -194,3 +194,7 @@ path = helix-syntax/languages/tree-sitter-regex url = https://github.com/tree-sitter/tree-sitter-regex.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-make"] + path = helix-syntax/languages/tree-sitter-make + url = https://github.com/alemuller/tree-sitter-make + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 384ba96b..c093144f 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -27,6 +27,7 @@ | llvm-mir | ✓ | ✓ | ✓ | | | llvm-mir-yaml | ✓ | | ✓ | | | lua | ✓ | | ✓ | | +| make | ✓ | | | | | markdown | ✓ | | | | | mint | | | | `mint` | | nix | ✓ | | ✓ | `rnix-lsp` | diff --git a/helix-syntax/languages/tree-sitter-make b/helix-syntax/languages/tree-sitter-make new file mode 160000 index 00000000..a4b91874 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-make @@ -0,0 +1 @@ +Subproject commit a4b9187417d6be349ee5fd4b6e77b4172c6827dd diff --git a/languages.toml b/languages.toml index c8f9bab4..afee20aa 100644 --- a/languages.toml +++ b/languages.toml @@ -390,6 +390,13 @@ indent = { tab-width = 2, unit = " " } language-server = { command = "cmake-language-server" } injection-regex = "cmake" +[[language]] +name = "make" +scope = "source.make" +file-types = ["Makefile", "makefile", "justfile", ".justfile"] +roots =[] +comment-token = "#" + [[language]] name = "glsl" scope = "source.glsl" diff --git a/runtime/queries/make/highlights.scm b/runtime/queries/make/highlights.scm new file mode 100644 index 00000000..50380baf --- /dev/null +++ b/runtime/queries/make/highlights.scm @@ -0,0 +1,170 @@ +[ + "(" + ")" + "{" + "}" +] @punctuation.bracket + +[ + ":" + "&:" + "::" + "|" + ";" + "\"" + "'" + "," +] @punctuation.delimiter + +[ + "$" + "$$" +] @punctuation.special + +(automatic_variable + [ "@" "%" "<" "?" "^" "+" "/" "*" "D" "F"] @punctuation.special) + +(automatic_variable + "/" @error . ["D" "F"]) + +[ + "=" + ":=" + "::=" + "?=" + "+=" + "!=" + "@" + "-" + "+" +] @operator + +[ + (text) + (string) + (raw_text) +] @string + +(variable_assignment (word) @string) + +[ + "ifeq" + "ifneq" + "ifdef" + "ifndef" + "else" + "endif" + "if" + "or" ; boolean functions are conditional in make grammar + "and" +] @keyword.control.conditional + +"foreach" @keyword.control.repeat + +[ + "define" + "endef" + "vpath" + "undefine" + "export" + "unexport" + "override" + "private" +; "load" +] @keyword + +[ + "include" + "sinclude" + "-include" +] @keyword.control.import + +[ + "subst" + "patsubst" + "strip" + "findstring" + "filter" + "filter-out" + "sort" + "word" + "words" + "wordlist" + "firstword" + "lastword" + "dir" + "notdir" + "suffix" + "basename" + "addsuffix" + "addprefix" + "join" + "wildcard" + "realpath" + "abspath" + "call" + "eval" + "file" + "value" + "shell" +] @keyword.function + +[ + "error" + "warning" + "info" +] @keyword.control.exception + +;; Variable +(variable_assignment + name: (word) @variable) + +(variable_reference + (word) @variable) + +(comment) @comment + +((word) @clean @string.regexp + (#match? @clean "[%\*\?]")) + +(function_call + function: "error" + (arguments (text) @error)) + +(function_call + function: "warning" + (arguments (text) @warning)) + +(function_call + function: "info" + (arguments (text) @info)) + +;; Install Command Categories +;; Others special variables +;; Variables Used by Implicit Rules +[ + "VPATH" + ".RECIPEPREFIX" +] @constant.builtin + +(variable_assignment + name: (word) @clean @constant.builtin + (#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\.DEFAULT_GOAL|\.RECIPEPREFIX|\.EXTRA_PREREQS)$")) + +(variable_reference + (word) @clean @constant.builtin + (#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\.DEFAULT_GOAL|\.RECIPEPREFIX|\.EXTRA_PREREQS\.VARIABLES|\.FEATURES|\.INCLUDE_DIRS|\.LOADED)$")) + +;; Standart targets +(targets + (word) @constant.macro + (#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$")) + +(targets + (word) @constant.macro + (#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$")) + +;; Builtin targets +(targets + (word) @constant.macro + (#match? @constant.macro "^\.(PHONY|SUFFIXES|DEFAULT|PRECIOUS|INTERMEDIATE|SECONDARY|SECONDEXPANSION|DELETE_ON_ERROR|IGNORE|LOW_RESOLUTION_TIME|SILENT|EXPORT_ALL_VARIABLES|NOTPARALLEL|ONESHELL|POSIX)$")) -- cgit v1.2.3-70-g09d2 From 5b45bdd80f1b2bd456d247ed6d2d95e9efb9d304 Mon Sep 17 00:00:00 2001 From: Eric Crosson Date: Mon, 3 Jan 2022 20:31:17 -0600 Subject: docs: document @keyword.control.exception scope As identified in [this GitHub comment](https://github.com/helix-editor/helix/pull/1433#discussion_r777786140) --- book/src/themes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index 29d3926e..1325de8c 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -147,6 +147,7 @@ We use a similar set of scopes as - `repeat` - `for`, `while`, `loop` - `import` - `import`, `export` - `return` + - `exception` - `operator` - `or`, `in` - `directive` - Preprocessor directives (`#if` in C) - `function` - `fn`, `func` -- cgit v1.2.3-70-g09d2 From 97e12f5c5a26cbbc2eddffd91a2e506403d4d453 Mon Sep 17 00:00:00 2001 From: Cottser Date: Sat, 8 Jan 2022 21:45:54 -0500 Subject: docs: editor.filepicker -> editor.file-picker (#1465) --- book/src/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/configuration.md b/book/src/configuration.md index 33a933b2..be1a0809 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -25,7 +25,7 @@ To override global configuration parameters, create a `config.toml` file located | `auto-info` | Whether to display infoboxes | `true` | | `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. | `false` | -`[editor.filepicker]` section of the config. Sets options for file picker and global search. All but the last key listed in the default file-picker configuration below are IgnoreOptions: whether hidden files and files listed within ignore files are ignored by (not visible in) the helix file picker and global search. There is also one other key, `max-depth` available, which is not defined by default. +`[editor.file-picker]` section of the config. Sets options for file picker and global search. All but the last key listed in the default file-picker configuration below are IgnoreOptions: whether hidden files and files listed within ignore files are ignored by (not visible in) the helix file picker and global search. There is also one other key, `max-depth` available, which is not defined by default. | Key | Description | Default | |--|--|---------| -- cgit v1.2.3-70-g09d2 From e0a99ae51ac099e30dc1039f9ac1059bba90a806 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Sun, 9 Jan 2022 08:10:20 -0600 Subject: add tree-sitter-git-config (#1426) * add tree-sitter-git-config * add todo comment for improving filetype check--- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-git-config | 1 + languages.toml | 10 ++++++++++ runtime/queries/git-config/highlights.scm | 27 +++++++++++++++++++++++++++ 5 files changed, 43 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-git-config create mode 100644 runtime/queries/git-config/highlights.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index e6d9d654..3442652a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -198,3 +198,7 @@ path = helix-syntax/languages/tree-sitter-make url = https://github.com/alemuller/tree-sitter-make shallow = true +[submodule "helix-syntax/languages/tree-sitter-git-config"] + path = helix-syntax/languages/tree-sitter-git-config + url = https://github.com/the-mikedavis/tree-sitter-git-config.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index c093144f..8b599f6b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -12,6 +12,7 @@ | elixir | ✓ | | | `elixir-ls` | | fish | ✓ | ✓ | ✓ | | | git-commit | ✓ | | | | +| git-config | ✓ | | | | | git-diff | ✓ | | | | | git-rebase | ✓ | | | | | glsl | ✓ | | ✓ | | diff --git a/helix-syntax/languages/tree-sitter-git-config b/helix-syntax/languages/tree-sitter-git-config new file mode 160000 index 00000000..0e4f0baf --- /dev/null +++ b/helix-syntax/languages/tree-sitter-git-config @@ -0,0 +1 @@ +Subproject commit 0e4f0baf90b57e5aeb62dcdbf03062c6315d43ea diff --git a/languages.toml b/languages.toml index afee20aa..0a19bb04 100644 --- a/languages.toml +++ b/languages.toml @@ -545,3 +545,13 @@ scope = "source.regex" injection-regex = "regex" file-types = ["regex"] roots = [] + +[[language]] +name = "git-config" +scope = "source.gitconfig" +roots = [] +# TODO: allow specifying file-types as a regex so we can read directory names (e.g. `.git/config`) +file-types = [".gitmodules", ".gitconfig"] +injection-regex = "git-config" +comment-token = "#" +indent = { tab-width = 4, unit = "\t" } diff --git a/runtime/queries/git-config/highlights.scm b/runtime/queries/git-config/highlights.scm new file mode 100644 index 00000000..84767edc --- /dev/null +++ b/runtime/queries/git-config/highlights.scm @@ -0,0 +1,27 @@ +((section_name) @keyword.directive + (#eq? @keyword.directive "include")) + +((section_header + (section_name) @keyword.directive + (subsection_name)) + (#eq? @keyword.directive "includeIf")) + +(section_name) @markup.heading +(variable (name) @variable.other.member) +[(true) (false)] @constant.builtin.boolean +(integer) @constant.numeric.integer + +((string) @string.special.path + (#match? @string.special.path "^(~|./|/)")) + +[(string) (subsection_name)] @string + +[ + "[" + "]" + "\"" +] @punctuation.bracket + +"=" @punctuation.delimiter + +(comment) @comment -- cgit v1.2.3-70-g09d2 From f77dbc7c8350ccc3f5270cae4a7d53e47f36a06c Mon Sep 17 00:00:00 2001 From: NexiNov Date: Wed, 12 Jan 2022 21:13:03 +0530 Subject: Minor(book): Add `G` in normal mode (#1482) --- book/src/keymap.md | 1 + 1 file changed, 1 insertion(+) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 70ec13b3..ea890575 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -25,6 +25,7 @@ | `f` | Find next char | `find_next_char` | | `T` | Find 'till previous char | `till_prev_char` | | `F` | Find previous char | `find_prev_char` | +| `G` | Go to line number `` | `goto_line` | | `Alt-.` | Repeat last motion (`f`, `t` or `m`) | `repeat_last_motion` | | `Home` | Move to the start of the line | `goto_line_start` | | `End` | Move to the end of the line | `goto_line_end` | -- cgit v1.2.3-70-g09d2 From a7b0cc730c9d18d214ef194ff0cb5d2ccfa8b762 Mon Sep 17 00:00:00 2001 From: Kirawi Date: Sat, 15 Jan 2022 20:11:31 -0500 Subject: Re-enable haskell in languages.toml (#1520) --- book/src/generated/lang-support.md | 1 + languages.toml | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 8b599f6b..87347819 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -17,6 +17,7 @@ | git-rebase | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | +| haskell | ✓ | | | | | html | ✓ | | | | | java | ✓ | | | | | javascript | ✓ | | ✓ | `typescript-language-server` | diff --git a/languages.toml b/languages.toml index 78447578..e9d5af0e 100644 --- a/languages.toml +++ b/languages.toml @@ -337,15 +337,15 @@ comment-token = "#" indent = { tab-width = 2, unit = " " } injection-regex = "yml|yaml" -# [[language]] -# name = "haskell" -# scope = "source.haskell" -# injection-regex = "haskell" -# file-types = ["hs"] -# roots = [] -# comment-token = "--" -# -# indent = { tab-width = 2, unit = " " } +[[language]] +name = "haskell" +scope = "source.haskell" +injection-regex = "haskell" +file-types = ["hs"] +roots = [] +comment-token = "--" + +indent = { tab-width = 2, unit = " " } [[language]] name = "zig" -- cgit v1.2.3-70-g09d2 From 8ea5742b0899992cd7453c70a8a06cb76a703fdf Mon Sep 17 00:00:00 2001 From: Anders Christiansen Sørby Date: Mon, 17 Jan 2022 15:05:17 +0100 Subject: feat(languages): Lean experimental tree-sitter-lean (#1422) * Add experimental tree-sitter-lean * Run docgen * Copy over the queries from lean.nvim * Update .gitmodules Co-authored-by: Ivan Tham * Update lean highlights and run docgen * Update runtime/queries/lean/injections.scm Co-authored-by: Michael Davis * Lean: Move variable matcher to bottom * Update runtime/queries/lean/locals.scm Co-authored-by: Michael Davis Co-authored-by: Ivan Tham Co-authored-by: Michael Davis --- .gitmodules | 4 + book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-lean | 1 + languages.toml | 11 ++ runtime/queries/lean/folds.scm | 15 +++ runtime/queries/lean/highlights.scm | 217 ++++++++++++++++++++++++++++++++ runtime/queries/lean/injections.scm | 2 + runtime/queries/lean/locals.scm | 5 + 8 files changed, 256 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-lean create mode 100644 runtime/queries/lean/folds.scm create mode 100644 runtime/queries/lean/highlights.scm create mode 100644 runtime/queries/lean/injections.scm create mode 100644 runtime/queries/lean/locals.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 3442652a..1ccbe43b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -190,6 +190,10 @@ path = helix-syntax/languages/tree-sitter-git-rebase url = https://github.com/the-mikedavis/tree-sitter-git-rebase.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-lean"] + path = helix-syntax/languages/tree-sitter-lean + url = https://github.com/Julian/tree-sitter-lean + shallow = true [submodule "helix-syntax/languages/tree-sitter-regex"] path = helix-syntax/languages/tree-sitter-regex url = https://github.com/tree-sitter/tree-sitter-regex.git diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 87347819..fce14846 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -24,6 +24,7 @@ | json | ✓ | | ✓ | | | julia | ✓ | | | `julia` | | latex | ✓ | | | | +| lean | ✓ | | | `lean` | | ledger | ✓ | | | | | llvm | ✓ | ✓ | ✓ | | | llvm-mir | ✓ | ✓ | ✓ | | diff --git a/helix-syntax/languages/tree-sitter-lean b/helix-syntax/languages/tree-sitter-lean new file mode 160000 index 00000000..d9842610 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-lean @@ -0,0 +1 @@ +Subproject commit d98426109258b266e1e92358c5f11716d2e8f638 diff --git a/languages.toml b/languages.toml index af15c654..2896dd32 100644 --- a/languages.toml +++ b/languages.toml @@ -241,6 +241,17 @@ comment-token = "%" indent = { tab-width = 4, unit = "\t" } +[[language]] +name = "lean" +scope = "source.lean" +injection-regex = "lean" +file-types = ["lean"] +roots = [ "lakefile.lean" ] +comment-token = "--" +language-server = { command = "lean", args = [ "--server" ] } + +indent = { tab-width = 2, unit = " " } + [[language]] name = "julia" scope = "source.julia" diff --git a/runtime/queries/lean/folds.scm b/runtime/queries/lean/folds.scm new file mode 100644 index 00000000..2c2bbb33 --- /dev/null +++ b/runtime/queries/lean/folds.scm @@ -0,0 +1,15 @@ +[ + (namespace) + (section) + + (instance) + (def) + (theorem) + (example) + + (product) + (array) + (list) + + (string) +] @fold diff --git a/runtime/queries/lean/highlights.scm b/runtime/queries/lean/highlights.scm new file mode 100644 index 00000000..a64feb1d --- /dev/null +++ b/runtime/queries/lean/highlights.scm @@ -0,0 +1,217 @@ +(open + namespace: (identifier) @namespace) +(namespace + name: (identifier) @namespace) +(section + name: (identifier) @namespace) + +;; Identifier naming conventions +((identifier) @type + (#match? @type "^[A-Z]")) + +(arrow) @type +(product) @type + +;; Declarations + +[ + "abbrev" + "def" + "theorem" + "constant" + "instance" + "axiom" + "example" + "inductive" + "structure" + "class" + + "deriving" + + "section" + "namespace" +] @keyword + +(attributes + (identifier) @function) + +(abbrev + name: (identifier) @type) +(def + name: (identifier) @function) +(theorem + name: (identifier) @function) +(constant + name: (identifier) @type) +(instance + name: (identifier) @function) +(instance + type: (identifier) @type) +(axiom + name: (identifier) @function) +(structure + name: (identifier) @type) +(structure + extends: (identifier) @type) + +(where_decl + type: (identifier) @type) + +(proj + name: (identifier) @field) + +(binders + type: (identifier) @type) + +["if" "then" "else"] @keyword.control.conditional + +["for" "in" "do"] @keyword.control.repeat + +(import) @include + +; Tokens + +[ + "!" + "$" + "%" + "&&" + "*" + "*>" + "+" + "++" + "-" + "/" + "::" + ":=" + "<" + "<$>" + "<*" + "<*>" + "<=" + "<|" + "<|>" + "=" + "==" + "=>" + ">" + ">" + ">=" + ">>" + ">>=" + "@" + "^" + "|>" + "|>." + "||" + "←" + "→" + "↔" + "∘" + "∧" + "∨" + "≠" + "≤" + "≥" +] @operator + +[ + "@&" +] @operator + +[ + "attribute" + "by" + "end" + "export" + "extends" + "fun" + "let" + "have" + "match" + "open" + "return" + "universe" + "variable" + "where" + "with" + "λ" + (hash_command) + (prelude) + (sorry) +] @keyword + +[ + "prefix" + "infix" + "infixl" + "infixr" + "postfix" + "notation" + "macro_rules" + "syntax" + "elab" + "builtin_initialize" +] @keyword + +[ + "noncomputable" + "partial" + "private" + "protected" + "unsafe" +] @keyword + +[ + "apply" + "exact" + "rewrite" + "rw" + "simp" + (trivial) +] @keyword + +[ + "catch" + "finally" + "try" +] @exception + +((apply + name: (identifier) @exception) + (#match? @exception "throw")) + +[ + "unless" + "mut" +] @keyword + +[(true) (false)] @boolean + +(number) @constant.numeric.integer +(float) @constant.numeric.float + +(comment) @comment +(char) @character +(string) @string +(interpolated_string) @string +; (escape_sequence) @string.escape + +; Reset highlighing in string interpolation +(interpolation) @none + +(interpolation + "{" @punctuation.special + "}" @punctuation.special) + +["(" ")" "[" "]" "{" "}" "⟨" "⟩"] @punctuation.bracket + +["|" "," "." ":" ";"] @punctuation.delimiter + +(sorry) @error + +;; Error +(ERROR) @error + +; Variables +(identifier) @variable diff --git a/runtime/queries/lean/injections.scm b/runtime/queries/lean/injections.scm new file mode 100644 index 00000000..030714f1 --- /dev/null +++ b/runtime/queries/lean/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "markdown")) diff --git a/runtime/queries/lean/locals.scm b/runtime/queries/lean/locals.scm new file mode 100644 index 00000000..dd6c2036 --- /dev/null +++ b/runtime/queries/lean/locals.scm @@ -0,0 +1,5 @@ +[ + (module) + (namespace) + (section) +] @local.scope -- cgit v1.2.3-70-g09d2 From b2c8aa1ee709edcd5302b27f6d6467b7b624ca84 Mon Sep 17 00:00:00 2001 From: Jared Ramirez Date: Thu, 20 Jan 2022 07:47:23 -0800 Subject: feat(languages): Elm (#1514) * Add Elm language support * Fix docs gen * Updates based on PR feedback--- .gitmodules | 4 ++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-elm | 1 + languages.toml | 11 +++++ runtime/queries/elm/highlights.scm | 83 ++++++++++++++++++++++++++++++++++ runtime/queries/elm/injections.scm | 4 ++ runtime/queries/elm/locals.scm | 14 ++++++ runtime/queries/elm/tags.scm | 19 ++++++++ 8 files changed, 137 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-elm create mode 100644 runtime/queries/elm/highlights.scm create mode 100644 runtime/queries/elm/injections.scm create mode 100644 runtime/queries/elm/locals.scm create mode 100644 runtime/queries/elm/tags.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 1ccbe43b..118fa2d8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -206,3 +206,7 @@ path = helix-syntax/languages/tree-sitter-git-config url = https://github.com/the-mikedavis/tree-sitter-git-config.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-elm"] + path = helix-syntax/languages/tree-sitter-elm + url = https://github.com/elm-tooling/tree-sitter-elm + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index fce14846..bfaac97b 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -10,6 +10,7 @@ | dart | ✓ | | ✓ | `dart` | | dockerfile | ✓ | | | `docker-langserver` | | elixir | ✓ | | | `elixir-ls` | +| elm | ✓ | | | `elm-language-server` | | fish | ✓ | ✓ | ✓ | | | git-commit | ✓ | | | | | git-config | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-elm b/helix-syntax/languages/tree-sitter-elm new file mode 160000 index 00000000..bd50ccf6 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-elm @@ -0,0 +1 @@ +Subproject commit bd50ccf66b42c55252ac8efc1086af4ac6bab8cd diff --git a/languages.toml b/languages.toml index 2896dd32..ea93df3a 100644 --- a/languages.toml +++ b/languages.toml @@ -567,3 +567,14 @@ file-types = [".gitmodules", ".gitconfig"] injection-regex = "git-config" comment-token = "#" indent = { tab-width = 4, unit = "\t" } + +[[language]] +name = "elm" +scope = "source.elm" +injection-regex = "elm" +file-types = ["elm"] +roots = ["elm.json"] +auto-format = true +comment-token = "--" +language-server = { command = "elm-language-server" } +indent = { tab-width = 4, unit = " " } diff --git a/runtime/queries/elm/highlights.scm b/runtime/queries/elm/highlights.scm new file mode 100644 index 00000000..3c8fd12d --- /dev/null +++ b/runtime/queries/elm/highlights.scm @@ -0,0 +1,83 @@ +; Keywords +[ + "if" + "then" + "else" + "let" + "in" + ] @keyword.control +(case) @keyword.control +(of) @keyword.control + +(colon) @keyword.operator +(backslash) @keyword +(as) @keyword +(port) @keyword +(exposing) @keyword +(alias) @keyword +(infix) @keyword + +(arrow) @keyword.operator +(dot) @keyword.operator + +(port) @keyword + +(type_annotation(lower_case_identifier) @function) +(port_annotation(lower_case_identifier) @function) +(file (value_declaration (function_declaration_left(lower_case_identifier) @function))) + +(field name: (lower_case_identifier) @attribute) +(field_access_expr(lower_case_identifier) @attribute) + +(operator_identifier) @keyword.operator +(eq) @keyword.operator.assignment + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +"|" @keyword +"," @punctuation.delimiter + +[ + "|>" +] @keyword + + +(import) @keyword.contol.import +(module) @keyword.other + +(number_constant_expr) @constant.numeric + +(type) @type + +(type_declaration(upper_case_identifier) @type) +(type_ref) @type +(type_alias_declaration name: (upper_case_identifier) @type) + +(union_pattern constructor: (upper_case_qid (upper_case_identifier) @label (dot) (upper_case_identifier) @variable.other.member)) +(union_pattern constructor: (upper_case_qid (upper_case_identifier) @variable.other.member)) + +(union_variant(upper_case_identifier) @variable.other.member) +(value_expr name: (value_qid (upper_case_identifier) @label)) +(value_expr (upper_case_qid (upper_case_identifier) @label (dot) (upper_case_identifier) @variable.other.member)) +(value_expr(upper_case_qid(upper_case_identifier)) @variable.other.member) + +; comments +(line_comment) @comment +(block_comment) @comment + +; strings +(string_escape) @constant.character.escape + +(open_quote) @string +(close_quote) @string +(regular_string_part) @string + +(open_char) @constant.character +(close_char) @constant.character diff --git a/runtime/queries/elm/injections.scm b/runtime/queries/elm/injections.scm new file mode 100644 index 00000000..83f8245c --- /dev/null +++ b/runtime/queries/elm/injections.scm @@ -0,0 +1,4 @@ +; Parse glsl where defined + +((glsl_content) @injection.content + (#set! injection.language "glsl")) diff --git a/runtime/queries/elm/locals.scm b/runtime/queries/elm/locals.scm new file mode 100644 index 00000000..ab103115 --- /dev/null +++ b/runtime/queries/elm/locals.scm @@ -0,0 +1,14 @@ +(value_declaration) @local.scope +(type_alias_declaration) @local.scope +(type_declaration) @local.scope +(type_annotation) @local.scope +(port_annotation) @local.scope +(infix_declaration) @local.scope +(let_in_expr) @local.scope + +(function_declaration_left (lower_pattern (lower_case_identifier)) @local.definition) +(function_declaration_left (lower_case_identifier) @local.definition) + +(value_expr(value_qid(upper_case_identifier)) @local.reference) +(value_expr(value_qid(lower_case_identifier)) @local.reference) +(type_ref (upper_case_qid) @local.reference) diff --git a/runtime/queries/elm/tags.scm b/runtime/queries/elm/tags.scm new file mode 100644 index 00000000..03999fb1 --- /dev/null +++ b/runtime/queries/elm/tags.scm @@ -0,0 +1,19 @@ +(value_declaration (function_declaration_left (lower_case_identifier) @name)) @definition.function + +(function_call_expr (value_expr (value_qid) @name)) @reference.function +(exposed_value (lower_case_identifier) @name) @reference.function +(type_annotation ((lower_case_identifier) @name) (colon)) @reference.function + +(type_declaration ((upper_case_identifier) @name) ) @definition.type + +(type_ref (upper_case_qid (upper_case_identifier) @name)) @reference.type +(exposed_type (upper_case_identifier) @name) @reference.type + +(type_declaration (union_variant (upper_case_identifier) @name)) @definition.union + +(value_expr (upper_case_qid (upper_case_identifier) @name)) @reference.union + + +(module_declaration + (upper_case_qid (upper_case_identifier)) @name +) @definition.module -- cgit v1.2.3-70-g09d2 From 392dfa0841fb106300eedf26f8628e48a32d0ea4 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 20 Jan 2022 09:52:33 -0600 Subject: add select_next_sibling and select_prev_sibling commands (#1495) * add select_next_sibling and select_prev_sibling commands * refactor objects to use higher order functions * address clippy feedback * move selection cloning into commands * add default keybindings under left/right brackets * use [+t,]+t for selecting sibling syntax nodes * setup Alt-{j,k,h,l} default keymaps for syntax selection commands * reduce boilerplate of select_next/prev_sibling in commands * import tree-sitter Node type in commands--- book/src/keymap.md | 6 ++-- helix-core/src/object.rs | 90 +++++++++++++++++++++++++++------------------- helix-term/src/commands.rs | 34 ++++++++++++++++-- helix-term/src/keymap.rs | 7 ++-- 4 files changed, 94 insertions(+), 43 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index ea890575..905ec48f 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -119,6 +119,10 @@ | `Alt-K` | Remove selections matching the regex | `remove_selections` | | `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` | | `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` | +| `Alt-k` | Expand selection to parent syntax node | `expand_selection` | +| `Alt-j` | Shrink syntax tree object selection | `shrink_selection` | +| `Alt-h` | Select previous sibling node in syntax tree | `select_prev_sibling` | +| `Alt-l` | Select next sibling node in syntax tree | `select_next_sibling` | ### Search @@ -262,8 +266,6 @@ Mappings in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaire | `]D` | Go to last diagnostic in document (**LSP**) | `goto_last_diag` | | `[space` | Add newline above | `add_newline_above` | | `]space` | Add newline below | `add_newline_below` | -| `]o` | Expand syntax tree object selection. | `expand_selection` | -| `[o` | Shrink syntax tree object selection. | `shrink_selection` | ## Insert Mode diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs index 3363e20b..b06f4144 100644 --- a/helix-core/src/object.rs +++ b/helix-core/src/object.rs @@ -1,56 +1,72 @@ use crate::{Range, RopeSlice, Selection, Syntax}; +use tree_sitter::Node; -pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection { - let tree = syntax.tree(); - - selection.clone().transform(|range| { - let from = text.char_to_byte(range.from()); - let to = text.char_to_byte(range.to()); +pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { + select_node_impl(syntax, text, selection, |descendant, from, to| { + if descendant.start_byte() == from && descendant.end_byte() == to { + descendant.parent() + } else { + Some(descendant) + } + }) +} - // find parent of a descendant that matches the range - let parent = match tree - .root_node() - .descendant_for_byte_range(from, to) - .and_then(|node| { - if node.start_byte() == from && node.end_byte() == to { - node.parent() - } else { - Some(node) - } - }) { - Some(parent) => parent, - None => return range, - }; +pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { + select_node_impl(syntax, text, selection, |descendant, _from, _to| { + descendant.child(0).or(Some(descendant)) + }) +} - let from = text.byte_to_char(parent.start_byte()); - let to = text.byte_to_char(parent.end_byte()); +pub fn select_sibling( + syntax: &Syntax, + text: RopeSlice, + selection: Selection, + sibling_fn: &F, +) -> Selection +where + F: Fn(Node) -> Option, +{ + select_node_impl(syntax, text, selection, |descendant, _from, _to| { + find_sibling_recursive(descendant, sibling_fn) + }) +} - if range.head < range.anchor { - Range::new(to, from) - } else { - Range::new(from, to) - } +fn find_sibling_recursive(node: Node, sibling_fn: F) -> Option +where + F: Fn(Node) -> Option, +{ + sibling_fn(node).or_else(|| { + node.parent() + .and_then(|node| find_sibling_recursive(node, sibling_fn)) }) } -pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection { +fn select_node_impl( + syntax: &Syntax, + text: RopeSlice, + selection: Selection, + select_fn: F, +) -> Selection +where + F: Fn(Node, usize, usize) -> Option, +{ let tree = syntax.tree(); - selection.clone().transform(|range| { + selection.transform(|range| { let from = text.char_to_byte(range.from()); let to = text.char_to_byte(range.to()); - let descendant = match tree.root_node().descendant_for_byte_range(from, to) { - // find first child, if not possible, fallback to the node that contains selection - Some(descendant) => match descendant.child(0) { - Some(child) => child, - None => descendant, - }, + let node = match tree + .root_node() + .descendant_for_byte_range(from, to) + .and_then(|node| select_fn(node, from, to)) + { + Some(node) => node, None => return range, }; - let from = text.byte_to_char(descendant.start_byte()); - let to = text.byte_to_char(descendant.end_byte()); + let from = text.byte_to_char(node.start_byte()); + let to = text.byte_to_char(node.end_byte()); if range.head < range.anchor { Range::new(to, from) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 9ac12931..de4bfa49 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -11,6 +11,7 @@ use helix_core::{ object, pos_at_coords, regex::{self, Regex, RegexBuilder}, search, selection, shellwords, surround, textobject, + tree_sitter::Node, unicode::width::UnicodeWidthChar, LineEnding, Position, Range, Rope, RopeGraphemes, RopeSlice, Selection, SmallVec, Tendril, Transaction, @@ -363,6 +364,8 @@ impl MappableCommand { rotate_selection_contents_backward, "Rotate selections contents backward", expand_selection, "Expand selection to parent syntax node", shrink_selection, "Shrink selection to previously expanded syntax node", + select_next_sibling, "Select the next sibling in the syntax tree", + select_prev_sibling, "Select the previous sibling in the syntax tree", jump_forward, "Jump forward on jumplist", jump_backward, "Jump backward on jumplist", save_selection, "Save the current selection to the jumplist", @@ -5502,7 +5505,7 @@ fn expand_selection(cx: &mut Context) { // save current selection so it can be restored using shrink_selection view.object_selections.push(current_selection.clone()); - let selection = object::expand_selection(syntax, text, current_selection); + let selection = object::expand_selection(syntax, text, current_selection.clone()); doc.set_selection(view.id, selection); } }; @@ -5528,7 +5531,7 @@ fn shrink_selection(cx: &mut Context) { // if not previous selection, shrink to first child if let Some(syntax) = doc.syntax() { let text = doc.text().slice(..); - let selection = object::shrink_selection(syntax, text, current_selection); + let selection = object::shrink_selection(syntax, text, current_selection.clone()); doc.set_selection(view.id, selection); } }; @@ -5536,6 +5539,33 @@ fn shrink_selection(cx: &mut Context) { cx.editor.last_motion = Some(Motion(Box::new(motion))); } +fn select_sibling_impl(cx: &mut Context, sibling_fn: &'static F) +where + F: Fn(Node) -> Option, +{ + let motion = |editor: &mut Editor| { + let (view, doc) = current!(editor); + + if let Some(syntax) = doc.syntax() { + let text = doc.text().slice(..); + let current_selection = doc.selection(view.id); + let selection = + object::select_sibling(syntax, text, current_selection.clone(), sibling_fn); + doc.set_selection(view.id, selection); + } + }; + motion(cx.editor); + cx.editor.last_motion = Some(Motion(Box::new(motion))); +} + +fn select_next_sibling(cx: &mut Context) { + select_sibling_impl(cx, &|node| Node::next_sibling(&node)) +} + +fn select_prev_sibling(cx: &mut Context) { + select_sibling_impl(cx, &|node| Node::prev_sibling(&node)) +} + fn match_brackets(cx: &mut Context) { let (view, doc) = current!(cx.editor); diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 79a06206..e5990d72 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -552,6 +552,11 @@ impl Default for Keymaps { "S" => split_selection, ";" => collapse_selection, "A-;" => flip_selections, + "A-k" => expand_selection, + "A-j" => shrink_selection, + "A-h" => select_prev_sibling, + "A-l" => select_next_sibling, + "%" => select_all, "x" => extend_line, "X" => extend_to_line_bounds, @@ -569,13 +574,11 @@ impl Default for Keymaps { "d" => goto_prev_diag, "D" => goto_first_diag, "space" => add_newline_above, - "o" => shrink_selection, }, "]" => { "Right bracket" "d" => goto_next_diag, "D" => goto_last_diag, "space" => add_newline_below, - "o" => expand_selection, }, "/" => search, -- cgit v1.2.3-70-g09d2 From f453f8724dc9374d6a88c19d83ba84e7d74dcac2 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Fri, 21 Jan 2022 08:15:35 -0600 Subject: change show_subtree command into ':tree-sitter-subtree' typable command (#1524) * add default keymap for show_subtree command * remove space+t keymap * add a typable command ':show-subtree' * generate documentation for ':show-subtree' * remove non-typable show_subtree command * ':show-subtree'->':tree-sitter-subtree'--- book/src/generated/typable-cmd.md | 1 + helix-term/src/commands.rs | 78 +++++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 31 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index 65b2dc5f..aed75cbd 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -45,3 +45,4 @@ | `:set-option`, `:set` | Set a config option at runtime | | `:sort` | Sort ranges in selection. | | `:rsort` | Sort ranges in selection in reverse order. | +| `:tree-sitter-subtree`, `:ts-subtree` | Display tree sitter subtree under cursor, primarily for debugging queries. | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index de4bfa49..6123b7d2 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -403,7 +403,6 @@ impl MappableCommand { decrement, "Decrement", record_macro, "Record macro", replay_macro, "Replay macro", - show_subtree, "Show tree-sitter subtree under primary selection", ); } @@ -2766,6 +2765,46 @@ pub mod cmd { Ok(()) } + fn tree_sitter_subtree( + cx: &mut compositor::Context, + _args: &[Cow], + _event: PromptEvent, + ) -> anyhow::Result<()> { + let (view, doc) = current!(cx.editor); + + if let Some(syntax) = doc.syntax() { + let primary_selection = doc.selection(view.id).primary(); + let text = doc.text(); + let from = text.char_to_byte(primary_selection.from()); + let to = text.char_to_byte(primary_selection.to()); + if let Some(selected_node) = syntax + .tree() + .root_node() + .descendant_for_byte_range(from, to) + { + let contents = format!("```tsq\n{}\n```", selected_node.to_sexp()); + + let callback = async move { + let call: job::Callback = + Box::new(move |editor: &mut Editor, compositor: &mut Compositor| { + let contents = ui::Markdown::new(contents, editor.syn_loader.clone()); + let popup = Popup::new("hover", contents); + if let Some(doc_popup) = compositor.find_id("hover") { + *doc_popup = popup; + } else { + compositor.push(Box::new(popup)); + } + }); + Ok(call) + }; + + cx.jobs.callback(callback); + } + } + + Ok(()) + } + pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ TypableCommand { name: "quit", @@ -3082,6 +3121,13 @@ pub mod cmd { fun: sort_reverse, completer: None, }, + TypableCommand { + name: "tree-sitter-subtree", + aliases: &["ts-subtree"], + doc: "Display tree sitter subtree under cursor, primarily for debugging queries.", + fun: tree_sitter_subtree, + completer: None, + }, ]; pub static TYPABLE_COMMAND_MAP: Lazy> = @@ -6252,33 +6298,3 @@ fn replay_macro(cx: &mut Context) { }, )); } - -fn show_subtree(cx: &mut Context) { - let (view, doc) = current!(cx.editor); - - if let Some(syntax) = doc.syntax() { - let primary_selection = doc.selection(view.id).primary(); - let text = doc.text(); - let from = text.char_to_byte(primary_selection.from()); - let to = text.char_to_byte(primary_selection.to()); - if let Some(selected_node) = syntax - .tree() - .root_node() - .descendant_for_byte_range(from, to) - { - let contents = format!("```tsq\n{}\n```", selected_node.to_sexp()); - - cx.callback = Some(Box::new( - move |compositor: &mut Compositor, cx: &mut compositor::Context| { - let contents = ui::Markdown::new(contents, cx.editor.syn_loader.clone()); - let popup = Popup::new("hover", contents); - if let Some(doc_popup) = compositor.find_id("hover") { - *doc_popup = popup; - } else { - compositor.push(Box::new(popup)); - } - }, - )); - } - } -} -- cgit v1.2.3-70-g09d2 From 0b55b21f3069640d37d2fa34bd413986177c0cd7 Mon Sep 17 00:00:00 2001 From: Jared Ramirez Date: Fri, 21 Jan 2022 06:16:40 -0800 Subject: feat(languages): GraphQL (#1515) * Add Graphql language support * Fix docs gen * Add JS Graphql injection query * Updates based on PR feedback Co-authored-by: Blaž Hrastnik --- .gitmodules | 4 + book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-graphql | 1 + languages.toml | 8 ++ runtime/queries/graphql/highlights.scm | 163 +++++++++++++++++++++++++++++ runtime/queries/javascript/injections.scm | 8 ++ 6 files changed, 185 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-graphql create mode 100644 runtime/queries/graphql/highlights.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 118fa2d8..780d1b63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -206,6 +206,10 @@ path = helix-syntax/languages/tree-sitter-git-config url = https://github.com/the-mikedavis/tree-sitter-git-config.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-graphql"] + path = helix-syntax/languages/tree-sitter-graphql + url = https://github.com/bkegley/tree-sitter-graphql + shallow = true [submodule "helix-syntax/languages/tree-sitter-elm"] path = helix-syntax/languages/tree-sitter-elm url = https://github.com/elm-tooling/tree-sitter-elm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index bfaac97b..fa8aa3ef 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -18,6 +18,7 @@ | git-rebase | ✓ | | | | | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | +| graphql | ✓ | | | | | haskell | ✓ | | | | | html | ✓ | | | | | java | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-graphql b/helix-syntax/languages/tree-sitter-graphql new file mode 160000 index 00000000..5e66e961 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-graphql @@ -0,0 +1 @@ +Subproject commit 5e66e961eee421786bdda8495ed1db045e06b5fe diff --git a/languages.toml b/languages.toml index ea93df3a..f9362eac 100644 --- a/languages.toml +++ b/languages.toml @@ -568,6 +568,14 @@ injection-regex = "git-config" comment-token = "#" indent = { tab-width = 4, unit = "\t" } +[[language]] +name = "graphql" +scope = "source.graphql" +injection-regex = "graphql" +file-types = ["gql", "graphql"] +roots = [] +indent = { tab-width = 2, unit = " " } + [[language]] name = "elm" scope = "source.elm" diff --git a/runtime/queries/graphql/highlights.scm b/runtime/queries/graphql/highlights.scm new file mode 100644 index 00000000..9fab4051 --- /dev/null +++ b/runtime/queries/graphql/highlights.scm @@ -0,0 +1,163 @@ +; Types +;------ + +(scalar_type_definition + (name) @type) + +(object_type_definition + (name) @type) + +(interface_type_definition + (name) @type) + +(union_type_definition + (name) @type) + +(enum_type_definition + (name) @type) + +(input_object_type_definition + (name) @type) + +(directive_definition + (name) @type) + +(directive_definition + "@" @type) + +(scalar_type_extension + (name) @type) + +(object_type_extension + (name) @type) + +(interface_type_extension + (name) @type) + +(union_type_extension + (name) @type) + +(enum_type_extension + (name) @type) + +(input_object_type_extension + (name) @type) + +(named_type + (name) @type) + +(directive) @type + +; Properties +;----------- + +(field + (name) @variable.other.member) + +(field + (alias + (name) @variable.other.member)) + +(field_definition + (name) @variable.other.member) + +(object_value + (object_field + (name) @variable.other.member)) + +(enum_value + (name) @variable.other.member) + +; Variable Definitions and Arguments +;----------------------------------- + +(operation_definition + (name) @variable) + +(fragment_name + (name) @variable) + +(input_fields_definition + (input_value_definition + (name) @variable.parameter)) + +(argument + (name) @variable.parameter) + +(arguments_definition + (input_value_definition + (name) @variable.parameter)) + +(variable_definition + (variable) @variable.parameter) + +(argument + (value + (variable) @variable)) + +; Constants +;---------- + +(string_value) @string + +(int_value) @constants.numeric.integer + +(float_value) @constants.numeric.float + +(boolean_value) @constants.builtin.boolean + +; Literals +;--------- + +(description) @comment + +(comment) @comment + +(directive_location + (executable_directive_location) @type.builtin) + +(directive_location + (type_system_directive_location) @type.builtin) + +; Keywords +;---------- + +[ + "query" + "mutation" + "subscription" + "fragment" + "scalar" + "type" + "interface" + "union" + "enum" + "input" + "extend" + "directive" + "schema" + "on" + "repeatable" + "implements" +] @keyword + +; Punctuation +;------------ + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +"=" @operator + +"|" @punctuation.delimiter +"&" @punctuation.delimiter +":" @punctuation.delimiter + +"..." @punctuation.special +"!" @punctuation.special diff --git a/runtime/queries/javascript/injections.scm b/runtime/queries/javascript/injections.scm index 5539241a..e8429111 100644 --- a/runtime/queries/javascript/injections.scm +++ b/runtime/queries/javascript/injections.scm @@ -9,6 +9,14 @@ ] arguments: (template_string) @injection.content) +; Parse the contents of gql template literals + +((call_expression + function: (identifier) @_template_function_name + arguments: (template_string) @injection.content) + (#eq? @_template_function_name "gql") + (#set! injection.language "graphql")) + ; Parse regex syntax within regex literals ((regex_pattern) @injection.content -- cgit v1.2.3-70-g09d2 From b8cafee9f5399ffddcaebffe256035bc888eeaa7 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Sat, 22 Jan 2022 09:34:19 -0600 Subject: docs: Fix typo in book (#1537) * docs: Fix typo in book * Update book/src/usage.md Co-authored-by: Eric Crosson Co-authored-by: Blaž Hrastnik Co-authored-by: Eric Crosson --- book/src/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'book/src') diff --git a/book/src/usage.md b/book/src/usage.md index cf7d9d48..a76bfafc 100644 --- a/book/src/usage.md +++ b/book/src/usage.md @@ -42,7 +42,7 @@ helix. The keymappings have been inspired from [vim-sandwich](https://github.com `ms` acts on a selection, so select the text first and use `ms`. `mr` and `md` work on the closest pairs found and selections are not required; use counts to act in outer pairs. -It can also act on multiple seletions (yay!). For example, to change every occurance of `(use)` to `[use]`: +It can also act on multiple selections (yay!). For example, to change every occurrence of `(use)` to `[use]`: - `%` to select the whole file - `s` to split the selections on a search term -- cgit v1.2.3-70-g09d2 From a8e69e12f414b77824af9db4b0631f83d665effd Mon Sep 17 00:00:00 2001 From: Kyra Date: Sun, 23 Jan 2022 01:22:31 -0600 Subject: Add haskell-language-server-wrapper --lsp to default `languages.toml` (#1556) After the changes to upgrade and reenable tree-sitter-haskell #1417 for the purpose of enabling Haskell syntax highlighting #1384, we might as well take the final step.--- book/src/generated/lang-support.md | 2 +- languages.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index fa8aa3ef..e4070117 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -19,7 +19,7 @@ | glsl | ✓ | | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | graphql | ✓ | | | | -| haskell | ✓ | | | | +| haskell | ✓ | | | `haskell-language-server-wrapper` | | html | ✓ | | | | | java | ✓ | | | | | javascript | ✓ | | ✓ | `typescript-language-server` | diff --git a/languages.toml b/languages.toml index f9362eac..3c328610 100644 --- a/languages.toml +++ b/languages.toml @@ -355,7 +355,7 @@ injection-regex = "haskell" file-types = ["hs"] roots = [] comment-token = "--" - +language-server = { command = "haskell-language-server-wrapper", args = ["--lsp"] } indent = { tab-width = 2, unit = " " } [[language]] -- cgit v1.2.3-70-g09d2 From d49e5323f9230f3195d3ee4c5e682cd6d8c2cb1a Mon Sep 17 00:00:00 2001 From: CossonLeo Date: Mon, 24 Jan 2022 09:41:25 +0800 Subject: Use markup scopes for the Markdown component (#1363) --- book/src/themes.md | 12 ++ helix-term/src/commands.rs | 3 +- helix-term/src/ui/completion.rs | 9 +- helix-term/src/ui/markdown.rs | 313 +++++++++++++++++++++------------------- 4 files changed, 184 insertions(+), 153 deletions(-) (limited to 'book/src') diff --git a/book/src/themes.md b/book/src/themes.md index 1325de8c..9abcfe8c 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -190,6 +190,18 @@ We use a similar set of scopes as These scopes are used for theming the editor interface. +- `markup` + - `normal` + - `completion` - for completion doc popup ui + - `hover` - for hover popup ui + - `heading` + - `completion` - for completion doc popup ui + - `hover` - for hover popup ui + - `raw` + - `inline` + - `completion` - for completion doc popup ui + - `hover` - for hover popup ui + | Key | Notes | | --- | --- | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index fc0db6ed..7144ebb9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -5455,7 +5455,8 @@ fn hover(cx: &mut Context) { // skip if contents empty - let contents = ui::Markdown::new(contents, editor.syn_loader.clone()); + let contents = + ui::Markdown::new(contents, editor.syn_loader.clone()).style_group("hover"); let popup = Popup::new("hover", contents); if let Some(doc_popup) = compositor.find_id("hover") { *doc_popup = popup; diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index c9ed3b4a..35afe81e 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -304,6 +304,9 @@ impl Component for Completion { let cursor_pos = doc.selection(view.id).primary().cursor(text); let coords = helix_core::visual_coords_at_pos(text, cursor_pos, doc.tab_width()); let cursor_pos = (coords.row - view.offset.row) as u16; + + let markdown_ui = + |content, syn_loader| Markdown::new(content, syn_loader).style_group("completion"); let mut markdown_doc = match &option.documentation { Some(lsp::Documentation::String(contents)) | Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { @@ -311,7 +314,7 @@ impl Component for Completion { value: contents, })) => { // TODO: convert to wrapped text - Markdown::new( + markdown_ui( format!( "```{}\n{}\n```\n{}", language, @@ -326,7 +329,7 @@ impl Component for Completion { value: contents, })) => { // TODO: set language based on doc scope - Markdown::new( + markdown_ui( format!( "```{}\n{}\n```\n{}", language, @@ -340,7 +343,7 @@ impl Component for Completion { // TODO: copied from above // TODO: set language based on doc scope - Markdown::new( + markdown_ui( format!( "```{}\n{}\n```", language, diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index 00da2c11..003266d3 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -21,6 +21,10 @@ pub struct Markdown { contents: String, config_loader: Arc, + + text_style: String, + block_style: String, + heading_style: String, } // TODO: pre-render and self reference via Pin @@ -31,121 +35,139 @@ impl Markdown { Self { contents, config_loader, + text_style: "markup.normal".into(), + block_style: "markup.raw.inline".into(), + heading_style: "markup.heading".into(), } } -} -fn parse<'a>( - contents: &'a str, - theme: Option<&Theme>, - loader: Arc, -) -> tui::text::Text<'a> { - // // also 2021-03-04T16:33:58.553 helix_lsp::transport [INFO] <- {"contents":{"kind":"markdown","value":"\n```rust\ncore::num\n```\n\n```rust\npub const fn saturating_sub(self, rhs:Self) ->Self\n```\n\n---\n\n```rust\n```"},"range":{"end":{"character":61,"line":101},"start":{"character":47,"line":101}}} - // let text = "\n```rust\ncore::iter::traits::iterator::Iterator\n```\n\n```rust\nfn collect>(self) -> B\nwhere\n Self: Sized,\n```\n\n---\n\nTransforms an iterator into a collection.\n\n`collect()` can take anything iterable, and turn it into a relevant\ncollection. This is one of the more powerful methods in the standard\nlibrary, used in a variety of contexts.\n\nThe most basic pattern in which `collect()` is used is to turn one\ncollection into another. You take a collection, call [`iter`](https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html) on it,\ndo a bunch of transformations, and then `collect()` at the end.\n\n`collect()` can also create instances of types that are not typical\ncollections. For example, a [`String`](https://doc.rust-lang.org/nightly/core/iter/std/string/struct.String.html) can be built from [`char`](type@char)s,\nand an iterator of [`Result`](https://doc.rust-lang.org/nightly/core/result/enum.Result.html) items can be collected\ninto `Result, E>`. See the examples below for more.\n\nBecause `collect()` is so general, it can cause problems with type\ninference. As such, `collect()` is one of the few times you'll see\nthe syntax affectionately known as the 'turbofish': `::<>`. This\nhelps the inference algorithm understand specifically which collection\nyou're trying to collect into.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled: Vec = a.iter()\n .map(|&x| x * 2)\n .collect();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nNote that we needed the `: Vec` on the left-hand side. This is because\nwe could collect into, for example, a [`VecDeque`](https://doc.rust-lang.org/nightly/core/iter/std/collections/struct.VecDeque.html) instead:\n\n```rust\nuse std::collections::VecDeque;\n\nlet a = [1, 2, 3];\n\nlet doubled: VecDeque = a.iter().map(|&x| x * 2).collect();\n\nassert_eq!(2, doubled[0]);\nassert_eq!(4, doubled[1]);\nassert_eq!(6, doubled[2]);\n```\n\nUsing the 'turbofish' instead of annotating `doubled`:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled = a.iter().map(|x| x * 2).collect::>();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nBecause `collect()` only cares about what you're collecting into, you can\nstill use a partial type hint, `_`, with the turbofish:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled = a.iter().map(|x| x * 2).collect::>();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nUsing `collect()` to make a [`String`](https://doc.rust-lang.org/nightly/core/iter/std/string/struct.String.html):\n\n```rust\nlet chars = ['g', 'd', 'k', 'k', 'n'];\n\nlet hello: String = chars.iter()\n .map(|&x| x as u8)\n .map(|x| (x + 1) as char)\n .collect();\n\nassert_eq!(\"hello\", hello);\n```\n\nIf you have a list of [`Result`](https://doc.rust-lang.org/nightly/core/result/enum.Result.html)s, you can use `collect()` to\nsee if any of them failed:\n\n```rust\nlet results = [Ok(1), Err(\"nope\"), Ok(3), Err(\"bad\")];\n\nlet result: Result, &str> = results.iter().cloned().collect();\n\n// gives us the first error\nassert_eq!(Err(\"nope\"), result);\n\nlet results = [Ok(1), Ok(3)];\n\nlet result: Result, &str> = results.iter().cloned().collect();\n\n// gives us the list of answers\nassert_eq!(Ok(vec![1, 3]), result);\n```"; - - let mut options = Options::empty(); - options.insert(Options::ENABLE_STRIKETHROUGH); - let parser = Parser::new_ext(contents, options); - - // TODO: if possible, render links as terminal hyperlinks: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda - let mut tags = Vec::new(); - let mut spans = Vec::new(); - let mut lines = Vec::new(); - - fn to_span(text: pulldown_cmark::CowStr) -> Span { - use std::ops::Deref; - Span::raw::>(match text { - CowStr::Borrowed(s) => s.into(), - CowStr::Boxed(s) => s.to_string().into(), - CowStr::Inlined(s) => s.deref().to_owned().into(), - }) + pub fn style_group(mut self, suffix: &str) -> Self { + self.text_style = format!("markup.normal.{}", suffix); + self.block_style = format!("markup.raw.inline.{}", suffix); + self.heading_style = format!("markup.heading.{}", suffix); + self } - let text_style = theme.map(|theme| theme.get("ui.text")).unwrap_or_default(); - - // TODO: use better scopes for these, `markup.raw.block`, `markup.heading` - let code_style = theme - .map(|theme| theme.get("ui.text.focus")) - .unwrap_or_default(); // white - let heading_style = theme - .map(|theme| theme.get("ui.linenr.selected")) - .unwrap_or_default(); // lilac - - for event in parser { - match event { - Event::Start(tag) => tags.push(tag), - Event::End(tag) => { - tags.pop(); - match tag { - Tag::Heading(_, _, _) - | Tag::Paragraph - | Tag::CodeBlock(CodeBlockKind::Fenced(_)) => { - // whenever code block or paragraph closes, new line - let spans = std::mem::take(&mut spans); - if !spans.is_empty() { - lines.push(Spans::from(spans)); + fn parse(&self, theme: Option<&Theme>) -> tui::text::Text<'_> { + // // also 2021-03-04T16:33:58.553 helix_lsp::transport [INFO] <- {"contents":{"kind":"markdown","value":"\n```rust\ncore::num\n```\n\n```rust\npub const fn saturating_sub(self, rhs:Self) ->Self\n```\n\n---\n\n```rust\n```"},"range":{"end":{"character":61,"line":101},"start":{"character":47,"line":101}}} + // let text = "\n```rust\ncore::iter::traits::iterator::Iterator\n```\n\n```rust\nfn collect>(self) -> B\nwhere\n Self: Sized,\n```\n\n---\n\nTransforms an iterator into a collection.\n\n`collect()` can take anything iterable, and turn it into a relevant\ncollection. This is one of the more powerful methods in the standard\nlibrary, used in a variety of contexts.\n\nThe most basic pattern in which `collect()` is used is to turn one\ncollection into another. You take a collection, call [`iter`](https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html) on it,\ndo a bunch of transformations, and then `collect()` at the end.\n\n`collect()` can also create instances of types that are not typical\ncollections. For example, a [`String`](https://doc.rust-lang.org/nightly/core/iter/std/string/struct.String.html) can be built from [`char`](type@char)s,\nand an iterator of [`Result`](https://doc.rust-lang.org/nightly/core/result/enum.Result.html) items can be collected\ninto `Result, E>`. See the examples below for more.\n\nBecause `collect()` is so general, it can cause problems with type\ninference. As such, `collect()` is one of the few times you'll see\nthe syntax affectionately known as the 'turbofish': `::<>`. This\nhelps the inference algorithm understand specifically which collection\nyou're trying to collect into.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled: Vec = a.iter()\n .map(|&x| x * 2)\n .collect();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nNote that we needed the `: Vec` on the left-hand side. This is because\nwe could collect into, for example, a [`VecDeque`](https://doc.rust-lang.org/nightly/core/iter/std/collections/struct.VecDeque.html) instead:\n\n```rust\nuse std::collections::VecDeque;\n\nlet a = [1, 2, 3];\n\nlet doubled: VecDeque = a.iter().map(|&x| x * 2).collect();\n\nassert_eq!(2, doubled[0]);\nassert_eq!(4, doubled[1]);\nassert_eq!(6, doubled[2]);\n```\n\nUsing the 'turbofish' instead of annotating `doubled`:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled = a.iter().map(|x| x * 2).collect::>();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nBecause `collect()` only cares about what you're collecting into, you can\nstill use a partial type hint, `_`, with the turbofish:\n\n```rust\nlet a = [1, 2, 3];\n\nlet doubled = a.iter().map(|x| x * 2).collect::>();\n\nassert_eq!(vec![2, 4, 6], doubled);\n```\n\nUsing `collect()` to make a [`String`](https://doc.rust-lang.org/nightly/core/iter/std/string/struct.String.html):\n\n```rust\nlet chars = ['g', 'd', 'k', 'k', 'n'];\n\nlet hello: String = chars.iter()\n .map(|&x| x as u8)\n .map(|x| (x + 1) as char)\n .collect();\n\nassert_eq!(\"hello\", hello);\n```\n\nIf you have a list of [`Result`](https://doc.rust-lang.org/nightly/core/result/enum.Result.html)s, you can use `collect()` to\nsee if any of them failed:\n\n```rust\nlet results = [Ok(1), Err(\"nope\"), Ok(3), Err(\"bad\")];\n\nlet result: Result, &str> = results.iter().cloned().collect();\n\n// gives us the first error\nassert_eq!(Err(\"nope\"), result);\n\nlet results = [Ok(1), Ok(3)];\n\nlet result: Result, &str> = results.iter().cloned().collect();\n\n// gives us the list of answers\nassert_eq!(Ok(vec![1, 3]), result);\n```"; + + let mut options = Options::empty(); + options.insert(Options::ENABLE_STRIKETHROUGH); + let parser = Parser::new_ext(&self.contents, options); + + // TODO: if possible, render links as terminal hyperlinks: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda + let mut tags = Vec::new(); + let mut spans = Vec::new(); + let mut lines = Vec::new(); + + fn to_span(text: pulldown_cmark::CowStr) -> Span { + use std::ops::Deref; + Span::raw::>(match text { + CowStr::Borrowed(s) => s.into(), + CowStr::Boxed(s) => s.to_string().into(), + CowStr::Inlined(s) => s.deref().to_owned().into(), + }) + } + + macro_rules! get_theme { + ($s1: expr) => { + theme + .map(|theme| theme.try_get($s1.as_str())) + .flatten() + .unwrap_or_default() + }; + } + let text_style = get_theme!(self.text_style); + let code_style = get_theme!(self.block_style); + let heading_style = get_theme!(self.heading_style); + + for event in parser { + match event { + Event::Start(tag) => tags.push(tag), + Event::End(tag) => { + tags.pop(); + match tag { + Tag::Heading(_, _, _) + | Tag::Paragraph + | Tag::CodeBlock(CodeBlockKind::Fenced(_)) => { + // whenever code block or paragraph closes, new line + let spans = std::mem::take(&mut spans); + if !spans.is_empty() { + lines.push(Spans::from(spans)); + } + lines.push(Spans::default()); } - lines.push(Spans::default()); + _ => (), } - _ => (), } - } - Event::Text(text) => { - // TODO: temp workaround - if let Some(Tag::CodeBlock(CodeBlockKind::Fenced(language))) = tags.last() { - if let Some(theme) = theme { - let rope = Rope::from(text.as_ref()); - let syntax = loader - .language_configuration_for_injection_string(language) - .and_then(|config| config.highlight_config(theme.scopes())) - .map(|config| Syntax::new(&rope, config, loader.clone())); - - if let Some(syntax) = syntax { - // if we have a syntax available, highlight_iter and generate spans - let mut highlights = Vec::new(); - - for event in syntax.highlight_iter(rope.slice(..), None, None) { - match event.unwrap() { - HighlightEvent::HighlightStart(span) => { - highlights.push(span); - } - HighlightEvent::HighlightEnd => { - highlights.pop(); - } - HighlightEvent::Source { start, end } => { - let style = match highlights.first() { - Some(span) => theme.get(&theme.scopes()[span.0]), - None => text_style, - }; - - // TODO: replace tabs with indentation - - let mut slice = &text[start..end]; - // TODO: do we need to handle all unicode line endings - // here, or is just '\n' okay? - while let Some(end) = slice.find('\n') { - // emit span up to newline - let text = &slice[..end]; - let text = text.replace('\t', " "); // replace tabs - let span = Span::styled(text, style); - spans.push(span); - - // truncate slice to after newline - slice = &slice[end + 1..]; - - // make a new line - let spans = std::mem::take(&mut spans); - lines.push(Spans::from(spans)); + Event::Text(text) => { + // TODO: temp workaround + if let Some(Tag::CodeBlock(CodeBlockKind::Fenced(language))) = tags.last() { + if let Some(theme) = theme { + let rope = Rope::from(text.as_ref()); + let syntax = self + .config_loader + .language_configuration_for_injection_string(language) + .and_then(|config| config.highlight_config(theme.scopes())) + .map(|config| { + Syntax::new(&rope, config, self.config_loader.clone()) + }); + + if let Some(syntax) = syntax { + // if we have a syntax available, highlight_iter and generate spans + let mut highlights = Vec::new(); + + for event in syntax.highlight_iter(rope.slice(..), None, None) { + match event.unwrap() { + HighlightEvent::HighlightStart(span) => { + highlights.push(span); } + HighlightEvent::HighlightEnd => { + highlights.pop(); + } + HighlightEvent::Source { start, end } => { + let style = match highlights.first() { + Some(span) => theme.get(&theme.scopes()[span.0]), + None => text_style, + }; + + // TODO: replace tabs with indentation + + let mut slice = &text[start..end]; + // TODO: do we need to handle all unicode line endings + // here, or is just '\n' okay? + while let Some(end) = slice.find('\n') { + // emit span up to newline + let text = &slice[..end]; + let text = text.replace('\t', " "); // replace tabs + let span = Span::styled(text, style); + spans.push(span); + + // truncate slice to after newline + slice = &slice[end + 1..]; + + // make a new line + let spans = std::mem::take(&mut spans); + lines.push(Spans::from(spans)); + } - // if there's anything left, emit it too - if !slice.is_empty() { - let span = - Span::styled(slice.replace('\t', " "), style); - spans.push(span); + // if there's anything left, emit it too + if !slice.is_empty() { + let span = Span::styled( + slice.replace('\t', " "), + style, + ); + spans.push(span); + } } } } + } else { + for line in text.lines() { + let span = Span::styled(line.to_string(), code_style); + lines.push(Spans::from(span)); + } } } else { for line in text.lines() { @@ -153,68 +175,60 @@ fn parse<'a>( lines.push(Spans::from(span)); } } + } else if let Some(Tag::Heading(_, _, _)) = tags.last() { + let mut span = to_span(text); + span.style = heading_style; + spans.push(span); } else { - for line in text.lines() { - let span = Span::styled(line.to_string(), code_style); - lines.push(Spans::from(span)); - } + let mut span = to_span(text); + span.style = text_style; + spans.push(span); } - } else if let Some(Tag::Heading(_, _, _)) = tags.last() { - let mut span = to_span(text); - span.style = heading_style; - spans.push(span); - } else { + } + Event::Code(text) | Event::Html(text) => { let mut span = to_span(text); - span.style = text_style; + span.style = code_style; spans.push(span); } + Event::SoftBreak | Event::HardBreak => { + // let spans = std::mem::replace(&mut spans, Vec::new()); + // lines.push(Spans::from(spans)); + spans.push(Span::raw(" ")); + } + Event::Rule => { + let mut span = Span::raw("---"); + span.style = code_style; + lines.push(Spans::from(span)); + lines.push(Spans::default()); + } + // TaskListMarker(bool) true if checked + _ => { + log::warn!("unhandled markdown event {:?}", event); + } } - Event::Code(text) | Event::Html(text) => { - let mut span = to_span(text); - span.style = code_style; - spans.push(span); - } - Event::SoftBreak | Event::HardBreak => { - // let spans = std::mem::replace(&mut spans, Vec::new()); - // lines.push(Spans::from(spans)); - spans.push(Span::raw(" ")); - } - Event::Rule => { - let mut span = Span::raw("---"); - span.style = code_style; - lines.push(Spans::from(span)); - lines.push(Spans::default()); - } - // TaskListMarker(bool) true if checked - _ => { - log::warn!("unhandled markdown event {:?}", event); - } + // build up a vec of Paragraph tui widgets } - // build up a vec of Paragraph tui widgets - } - if !spans.is_empty() { - lines.push(Spans::from(spans)); - } + if !spans.is_empty() { + lines.push(Spans::from(spans)); + } - // if last line is empty, remove it - if let Some(line) = lines.last() { - if line.0.is_empty() { - lines.pop(); + // if last line is empty, remove it + if let Some(line) = lines.last() { + if line.0.is_empty() { + lines.pop(); + } } - } - Text::from(lines) + Text::from(lines) + } } + impl Component for Markdown { fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { use tui::widgets::{Paragraph, Widget, Wrap}; - let text = parse( - &self.contents, - Some(&cx.editor.theme), - self.config_loader.clone(), - ); + let text = self.parse(Some(&cx.editor.theme)); let par = Paragraph::new(text) .wrap(Wrap { trim: false }) @@ -232,7 +246,8 @@ impl Component for Markdown { if padding >= viewport.1 || padding >= viewport.0 { return None; } - let contents = parse(&self.contents, None, self.config_loader.clone()); + let contents = self.parse(None); + // TODO: account for tab width let max_text_width = (viewport.0 - padding).min(120); let mut text_width = 0; -- cgit v1.2.3-70-g09d2 From 7bce91556afd2430c336f2fe4a6ce3f7ce555be2 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 25 Jan 2022 00:50:34 -0600 Subject: add tree-sitter-iex (#1576) * add tree-sitter-iex * run docgen task * fix url for iex submodule--- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-iex | 1 + languages.toml | 7 +++++++ runtime/queries/iex/highlights.scm | 1 + runtime/queries/iex/injections.scm | 6 ++++++ 6 files changed, 20 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-iex create mode 100644 runtime/queries/iex/highlights.scm create mode 100644 runtime/queries/iex/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 780d1b63..247ac276 100644 --- a/.gitmodules +++ b/.gitmodules @@ -214,3 +214,7 @@ path = helix-syntax/languages/tree-sitter-elm url = https://github.com/elm-tooling/tree-sitter-elm shallow = true +[submodule "helix-syntax/languages/tree-sitter-iex"] + path = helix-syntax/languages/tree-sitter-iex + url = https://github.com/elixir-lang/tree-sitter-iex + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index e4070117..eff82226 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -21,6 +21,7 @@ | graphql | ✓ | | | | | haskell | ✓ | | | `haskell-language-server-wrapper` | | html | ✓ | | | | +| iex | ✓ | | | | | java | ✓ | | | | | javascript | ✓ | | ✓ | `typescript-language-server` | | json | ✓ | | ✓ | | diff --git a/helix-syntax/languages/tree-sitter-iex b/helix-syntax/languages/tree-sitter-iex new file mode 160000 index 00000000..3ec55082 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-iex @@ -0,0 +1 @@ +Subproject commit 3ec55082cf0be015d03148be8edfdfa8c56e77f9 diff --git a/languages.toml b/languages.toml index a589d7b8..02c64732 100644 --- a/languages.toml +++ b/languages.toml @@ -586,3 +586,10 @@ auto-format = true comment-token = "--" language-server = { command = "elm-language-server" } indent = { tab-width = 4, unit = " " } + +[[language]] +name = "iex" +scope = "source.iex" +injection-regex = "iex" +file-types = ["iex"] +roots = [] diff --git a/runtime/queries/iex/highlights.scm b/runtime/queries/iex/highlights.scm new file mode 100644 index 00000000..2847fbff --- /dev/null +++ b/runtime/queries/iex/highlights.scm @@ -0,0 +1 @@ +(prompt) @comment diff --git a/runtime/queries/iex/injections.scm b/runtime/queries/iex/injections.scm new file mode 100644 index 00000000..48863d9d --- /dev/null +++ b/runtime/queries/iex/injections.scm @@ -0,0 +1,6 @@ +((evaluation_block (prompt_line (expression) @injection.content)) + (#set! injection.language "elixir") + (#set! injection.combined)) + +((result) @injection.content + (#set! injection.language "elixir")) -- cgit v1.2.3-70-g09d2 From 333c2949c2b036f8aafa77be2286eb3c135ea269 Mon Sep 17 00:00:00 2001 From: Andrew Neth Date: Tue, 25 Jan 2022 09:18:01 -0600 Subject: feat(helix-view): dynamic line numbers (#1522) * feat(helix-view): dynamic line numbers * docs: describe editor.line-number in more detail * Make dynamic numbers the default behavior of `relative`--- book/src/configuration.md | 2 +- helix-view/src/editor.rs | 4 +++- helix-view/src/gutter.rs | 24 +++++++++++++----------- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'book/src') diff --git a/book/src/configuration.md b/book/src/configuration.md index 7f2a4acf..8048f548 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -34,7 +34,7 @@ hidden = false | `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"]` | -| `line-number` | Line number display (`absolute`, `relative`) | `absolute` | +| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers. | `absolute` | | `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` | | `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` | | `auto-completion` | Enable automatic pop up of auto-completion. | `true` | diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 82ef0cdc..aa2df6f7 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -170,7 +170,9 @@ impl Default for CursorShapeConfig { pub enum LineNumber { /// Show absolute line number Absolute, - /// Show relative line number to the primary cursor + + /// If focused and in normal/select mode, show relative line number to the primary cursor. + /// If unfocused or in insert mode, show absolute line number. Relative, } diff --git a/helix-view/src/gutter.rs b/helix-view/src/gutter.rs index af016c56..113da642 100644 --- a/helix-view/src/gutter.rs +++ b/helix-view/src/gutter.rs @@ -58,29 +58,31 @@ pub fn line_number<'doc>( .char_to_line(doc.selection(view.id).primary().cursor(text)); let config = config.line_number; + let mode = doc.mode; Box::new(move |line: usize, selected: bool, out: &mut String| { if line == last_line && !draw_last { write!(out, "{:>1$}", '~', width).unwrap(); Some(linenr) } else { - use crate::editor::LineNumber; - let line = match config { - LineNumber::Absolute => line + 1, - LineNumber::Relative => { - if current_line == line { - line + 1 - } else { - abs_diff(current_line, line) - } - } + use crate::{document::Mode, editor::LineNumber}; + + let relative = config == LineNumber::Relative + && mode != Mode::Insert + && is_focused + && current_line != line; + + let display_num = if relative { + abs_diff(current_line, line) + } else { + line + 1 }; let style = if selected && is_focused { linenr_select } else { linenr }; - write!(out, "{:>1$}", line, width).unwrap(); + write!(out, "{:>1$}", display_num, width).unwrap(); Some(style) } }) -- cgit v1.2.3-70-g09d2 From e2833b58533f3991fa68061a21486b1322239fe3 Mon Sep 17 00:00:00 2001 From: Daniel S Poulin Date: Sat, 29 Jan 2022 21:04:36 -0500 Subject: Add textobjects queries for php (#1601) * Add textobjects queries for php * Missing EOL fix * Update generated docs after adding textobjects to php--- book/src/generated/lang-support.md | 2 +- runtime/queries/php/textobjects.scm | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/php/textobjects.scm (limited to 'book/src') diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index eff82226..85371773 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -40,7 +40,7 @@ | ocaml | ✓ | | ✓ | | | ocaml-interface | ✓ | | | | | perl | ✓ | ✓ | ✓ | | -| php | ✓ | | ✓ | | +| php | ✓ | ✓ | ✓ | | | prolog | | | | `swipl` | | protobuf | ✓ | | ✓ | | | python | ✓ | ✓ | ✓ | `pylsp` | diff --git a/runtime/queries/php/textobjects.scm b/runtime/queries/php/textobjects.scm new file mode 100644 index 00000000..04ffefd2 --- /dev/null +++ b/runtime/queries/php/textobjects.scm @@ -0,0 +1,30 @@ +(class_declaration + body: (_) @class.inside) @class.around + +(interface_declaration + body: (_) @class.inside) @class.around + +(trait_declaration + body: (_) @class.inside) @class.around + +(enum_declaration + body: (_) @class.inside) @class.around + +(function_definition + body: (_) @function.inside) @function.around + +(method_declaration + body: (_) @function.inside) @function.around + +(arrow_function + body: (_) @function.inside) @function.around + +(anonymous_function_creation_expression + body: (_) @function.inside) @function.around + +(formal_parameters + [ + (simple_parameter) + (variadic_parameter) + (property_promotion_parameter) + ] @parameter.inside) -- cgit v1.2.3-70-g09d2 From d6b6ad879e297ff786ce520acd3ce9c4ff3c2e8e Mon Sep 17 00:00:00 2001 From: Daniel S Poulin Date: Mon, 31 Jan 2022 22:35:07 -0500 Subject: epocsquadron/add tree sitter twig (#1602) * Add tree-sitter-twig grammer and highlights The gammar itself is quite basic, but is much better than nothing for working with real files consisting mostly of html. * Docgen for newly added grammar--- .gitmodules | 4 ++++ book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-twig | 1 + languages.toml | 9 +++++++++ runtime/queries/twig/highlights.scm | 16 ++++++++++++++++ runtime/queries/twig/injections.scm | 3 +++ 6 files changed, 34 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-twig create mode 100644 runtime/queries/twig/highlights.scm create mode 100644 runtime/queries/twig/injections.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index 247ac276..d35b0f33 100644 --- a/.gitmodules +++ b/.gitmodules @@ -218,3 +218,7 @@ path = helix-syntax/languages/tree-sitter-iex url = https://github.com/elixir-lang/tree-sitter-iex shallow = true +[submodule "helix-syntax/languages/tree-sitter-twig"] + path = helix-syntax/languages/tree-sitter-twig + url = https://github.com/eirabben/tree-sitter-twig.git + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 85371773..d10b56f1 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -54,6 +54,7 @@ | toml | ✓ | | | | | tsq | ✓ | | | | | tsx | ✓ | | | `typescript-language-server` | +| twig | ✓ | | | | | typescript | ✓ | | ✓ | `typescript-language-server` | | vue | ✓ | | | | | wgsl | ✓ | | | | diff --git a/helix-syntax/languages/tree-sitter-twig b/helix-syntax/languages/tree-sitter-twig new file mode 160000 index 00000000..b7444181 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-twig @@ -0,0 +1 @@ +Subproject commit b7444181fb38e603e25ea8fcdac55f9492e49c27 diff --git a/languages.toml b/languages.toml index 02c64732..74c01da5 100644 --- a/languages.toml +++ b/languages.toml @@ -231,6 +231,15 @@ roots = [] indent = { tab-width = 4, unit = " " } +[[language]] +name = "twig" +scope = "source.twig" +injection-regex = "twig" +file-types = ["twig"] +roots = [] + +indent = { tab-width = 2, unit = " " } + [[language]] name = "latex" scope = "source.tex" diff --git a/runtime/queries/twig/highlights.scm b/runtime/queries/twig/highlights.scm new file mode 100644 index 00000000..2c95ab63 --- /dev/null +++ b/runtime/queries/twig/highlights.scm @@ -0,0 +1,16 @@ +(comment_directive) @comment + +[ + "{%" + "{%-" + "{%~" + "%}" + "-%}" + "~%}" + "{{" + "{{-" + "{{~" + "}}" + "-}}" + "~}}" +] @keyword diff --git a/runtime/queries/twig/injections.scm b/runtime/queries/twig/injections.scm new file mode 100644 index 00000000..f0822734 --- /dev/null +++ b/runtime/queries/twig/injections.scm @@ -0,0 +1,3 @@ +((content) @injection.content + (#set! injection.language "html") + (#set! injection.combined)) -- cgit v1.2.3-70-g09d2 From f5b95beef69bbd8e627b6b0e7ea69317fd12b763 Mon Sep 17 00:00:00 2001 From: Jared Ramirez Date: Sat, 5 Feb 2022 21:24:01 -0800 Subject: feat(languages): rescript (#1616) * Add rescript language support * cargo xtask docgen * Add textobjects & file line ending * Fix text objects & rerun docgen * Fix textobjects queries--- .gitmodules | 4 + book/src/generated/lang-support.md | 1 + helix-syntax/languages/tree-sitter-rescript | 1 + languages.toml | 11 ++ runtime/queries/rescript/highlights.scm | 179 ++++++++++++++++++++++++++++ runtime/queries/rescript/injections.scm | 8 ++ runtime/queries/rescript/textobjects.scm | 9 ++ 7 files changed, 213 insertions(+) create mode 160000 helix-syntax/languages/tree-sitter-rescript create mode 100644 runtime/queries/rescript/highlights.scm create mode 100644 runtime/queries/rescript/injections.scm create mode 100644 runtime/queries/rescript/textobjects.scm (limited to 'book/src') diff --git a/.gitmodules b/.gitmodules index d35b0f33..55ed97b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -222,3 +222,7 @@ path = helix-syntax/languages/tree-sitter-twig url = https://github.com/eirabben/tree-sitter-twig.git shallow = true +[submodule "helix-syntax/languages/tree-sitter-rescript"] + path = helix-syntax/languages/tree-sitter-rescript + url = https://github.com/jaredramirez/tree-sitter-rescript + shallow = true diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index d10b56f1..64dab6d3 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -46,6 +46,7 @@ | python | ✓ | ✓ | ✓ | `pylsp` | | racket | | | | `racket` | | regex | ✓ | | | | +| rescript | ✓ | ✓ | | `rescript-language-server` | | ruby | ✓ | | ✓ | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | diff --git a/helix-syntax/languages/tree-sitter-rescript b/helix-syntax/languages/tree-sitter-rescript new file mode 160000 index 00000000..761eb912 --- /dev/null +++ b/helix-syntax/languages/tree-sitter-rescript @@ -0,0 +1 @@ +Subproject commit 761eb9126b65e078b1b5770ac296b4af8870f933 diff --git a/languages.toml b/languages.toml index 74c01da5..041d1564 100644 --- a/languages.toml +++ b/languages.toml @@ -602,3 +602,14 @@ scope = "source.iex" injection-regex = "iex" file-types = ["iex"] roots = [] + +[[language]] +name = "rescript" +scope = "source.rescript" +injection-regex = "rescript" +file-types = ["res"] +roots = ["bsconfig.json"] +auto-format = true +comment-token = "//" +language-server = { command = "rescript-language-server", args = ["--stdio"] } +indent = { tab-width = 2, unit = " " } diff --git a/runtime/queries/rescript/highlights.scm b/runtime/queries/rescript/highlights.scm new file mode 100644 index 00000000..b9ab8ea6 --- /dev/null +++ b/runtime/queries/rescript/highlights.scm @@ -0,0 +1,179 @@ +(comment) @comment + +; Identifiers +;------------ + +; Escaped identifiers like \"+." +((value_identifier) @function.macro + (#match? @function.macro "^\\.*$")) + +[ + (type_identifier) + (unit_type) + "list" +] @type + +[ + (variant_identifier) + (polyvar_identifier) +] @constant + +(property_identifier) @variable.other.member +(module_identifier) @namespace + +(jsx_identifier) @tag +(jsx_attribute (property_identifier) @variable.parameter) + +; Parameters +;---------------- + +(list_pattern (value_identifier) @variable.parameter) +(spread_pattern (value_identifier) @variable.parameter) + +; String literals +;---------------- + +[ + (string) + (template_string) +] @string + +(template_substitution + "${" @punctuation.bracket + "}" @punctuation.bracket) @embedded + +(character) @constant.character +(escape_sequence) @constant.character.escape + +; Other literals +;--------------- + +[ + (true) + (false) +] @constant.builtin + +(number) @constant.numeric +(polyvar) @constant +(polyvar_string) @constant + +; Functions +;---------- + +[ + (formal_parameters (value_identifier)) + (positional_parameter (value_identifier)) + (labeled_parameter (value_identifier)) +] @variable.parameter + +(function parameter: (value_identifier) @variable.parameter) + +; Meta +;----- + +[ + "@" + "@@" + (decorator_identifier) +] @label + +(extension_identifier) @keyword +("%") @keyword + +; Misc +;----- + +(subscript_expression index: (string) @variable.other.member) +(polyvar_type_pattern "#" @constant) + +[ + ("include") + ("open") +] @keyword + +[ + "as" + "export" + "external" + "let" + "module" + "mutable" + "private" + "rec" + "type" + "and" +] @keyword + +[ + "if" + "else" + "switch" +] @keyword + +[ + "exception" + "try" + "catch" + "raise" +] @keyword + +[ + "." + "," + "|" +] @punctuation.delimiter + +[ + "++" + "+" + "+." + "-" + "-." + "*" + "*." + "/" + "/." + "<" + "<=" + "==" + "===" + "!" + "!=" + "!==" + ">" + ">=" + "&&" + "||" + "=" + ":=" + "->" + "|>" + ":>" + (uncurry) +] @operator + +[ + "(" + ")" + "{" + "}" + "[" + "]" +] @punctuation.bracket + +(polyvar_type + [ + "[" + "[>" + "[<" + "]" + ] @punctuation.bracket) + +[ + "~" + "?" + "=>" + "..." +] @punctuation + +(ternary_expression ["?" ":"] @operator) diff --git a/runtime/queries/rescript/injections.scm b/runtime/queries/rescript/injections.scm new file mode 100644 index 00000000..201cce75 --- /dev/null +++ b/runtime/queries/rescript/injections.scm @@ -0,0 +1,8 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +((raw_js) @injection.content + (#set! injection.language "javascript")) + +((raw_gql) @injection.content + (#set! injection.language "graphql")) diff --git a/runtime/queries/rescript/textobjects.scm b/runtime/queries/rescript/textobjects.scm new file mode 100644 index 00000000..7ee8cd1a --- /dev/null +++ b/runtime/queries/rescript/textobjects.scm @@ -0,0 +1,9 @@ +; Classes (modules) +;------------------ + +(module_declaration definition: ((_) @class.inside)) @class.around + +; Functions +;---------- + +(function body: (_) @function.inside) @function.around -- cgit v1.2.3-70-g09d2 From f0cd02d5ef90e549e5e9f5dfce1d2317ad978b72 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 8 Feb 2022 10:15:40 +0530 Subject: Update keybind docs for treesitter, view mode (#1628) --- book/src/keymap.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index 905ec48f..f7e5462f 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -89,6 +89,7 @@ | Alt-| | Pipe each selection into shell command, ignoring output | `shell_pipe_to` | | `!` | Run shell command, inserting output before each selection | `shell_insert_output` | | `Alt-!` | Run shell command, appending output after each selection | `shell_append_output` | +| `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` | ### Selection manipulation @@ -113,16 +114,14 @@ | `%` | Select entire file | `select_all` | | `x` | Select current line, if already selected, extend to next line | `extend_line` | | `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` | -| | Expand selection to parent syntax node TODO: pick a key (**TS**) | `expand_selection` | | `J` | Join lines inside selection | `join_selections` | | `K` | Keep selections matching the regex | `keep_selections` | | `Alt-K` | Remove selections matching the regex | `remove_selections` | -| `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` | | `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` | -| `Alt-k` | Expand selection to parent syntax node | `expand_selection` | -| `Alt-j` | Shrink syntax tree object selection | `shrink_selection` | -| `Alt-h` | Select previous sibling node in syntax tree | `select_prev_sibling` | -| `Alt-l` | Select next sibling node in syntax tree | `select_next_sibling` | +| `Alt-k` | Expand selection to parent syntax node (**TS**) | `expand_selection` | +| `Alt-j` | Shrink syntax tree object selection (**TS**) | `shrink_selection` | +| `Alt-h` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` | +| `Alt-l` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` | ### Search @@ -155,10 +154,10 @@ over text and not actively editing it). | `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` | | `j` , `down` | Scroll the view downwards | `scroll_down` | | `k` , `up` | Scroll the view upwards | `scroll_up` | -| `f` | Move page down | `page_down` | -| `b` | Move page up | `page_up` | -| `d` | Move half page down | `half_page_down` | -| `u` | Move half page up | `half_page_up` | +| `Ctrl-f` | Move page down | `page_down` | +| `Ctrl-b` | Move page up | `page_up` | +| `Ctrl-d` | Move half page down | `half_page_down` | +| `Ctrl-u` | Move half page up | `half_page_up` | #### Goto mode -- cgit v1.2.3-70-g09d2 From a19a6ca01e07a111c6a5ca21a6d65888240bc2f6 Mon Sep 17 00:00:00 2001 From: Maximilian Schoenenberg Date: Fri, 11 Feb 2022 15:55:59 +0100 Subject: Added docs for `ensure_selections_forward` (#1651) --- book/src/keymap.md | 1 + 1 file changed, 1 insertion(+) (limited to 'book/src') diff --git a/book/src/keymap.md b/book/src/keymap.md index f7e5462f..19fd21bb 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -27,6 +27,7 @@ | `F` | Find previous char | `find_prev_char` | | `G` | Go to line number `` | `goto_line` | | `Alt-.` | Repeat last motion (`f`, `t` or `m`) | `repeat_last_motion` | +| `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` | | `Home` | Move to the start of the line | `goto_line_start` | | `End` | Move to the end of the line | `goto_line_end` | | `PageUp` | Move page up | `page_up` | -- cgit v1.2.3-70-g09d2