From b365f2d6143c7a73de703425e00b32b8184d6a02 Mon Sep 17 00:00:00 2001 From: Erin van der Veen Date: Wed, 22 Jun 2022 13:01:54 +0200 Subject: [PATCH 001/584] update tree-sitter-nickel to include ' in ident (#2859) see https://github.com/nickel-lang/tree-sitter-nickel/pull/9 and https://github.com/tweag/nickel/pull/737 --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index ba9419b3e6959..e0a57080573ff 100644 --- a/languages.toml +++ b/languages.toml @@ -425,7 +425,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "nickel" -source = { git = "https://github.com/nickel-lang/tree-sitter-nickel", rev = "c4dd1420b6cfeb6103d38eb1ce5195eb81197edc" } +source = { git = "https://github.com/nickel-lang/tree-sitter-nickel", rev = "9a502ea2e774df3d743a48310bb40e1cc097c86e" } [[language]] name = "nix" From 301065fe4d062dacc2b23b0f55780b3b6f2f52b5 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Wed, 22 Jun 2022 23:30:12 +0530 Subject: [PATCH 002/584] Fix scrollbar length proportional to total menu items (#2860) The scrollbar length used to increase with more entries in the menu, which was counter-intuitive to how scrollbars worked in most applications. Turns out there was a typo in the floor division implementation :) --- helix-term/src/ui/menu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index d67a429e37f3e..477b218ad63da 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -288,7 +288,7 @@ impl Component for Menu { let win_height = area.height as usize; const fn div_ceil(a: usize, b: usize) -> usize { - (a + b - 1) / a + (a + b - 1) / b } let scroll_height = std::cmp::min(div_ceil(win_height.pow(2), len), win_height as usize); From c107f4ea49edd61a3c6e8b971b20604cdab96325 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Wed, 22 Jun 2022 11:53:36 -0700 Subject: [PATCH 003/584] fixes #2856 by resetting style on diagnostic (#2861) --- helix-term/src/ui/editor.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index dc6362c6e5b68..debce9b4412b7 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -665,15 +665,13 @@ impl EditorView { let mut lines = Vec::new(); for diagnostic in diagnostics { - let text = Text::styled( - &diagnostic.message, - match diagnostic.severity { - Some(Severity::Error) => error, - Some(Severity::Warning) | None => warning, - Some(Severity::Info) => info, - Some(Severity::Hint) => hint, - }, - ); + let style = Style::reset().patch(match diagnostic.severity { + Some(Severity::Error) => error, + Some(Severity::Warning) | None => warning, + Some(Severity::Info) => info, + Some(Severity::Hint) => hint, + }); + let text = Text::styled(&diagnostic.message, style); lines.extend(text.lines); } From 886cff3bcc5f8e1d81e55afdbbf7ad8ff00ffc7b Mon Sep 17 00:00:00 2001 From: farwyler <1705805+farwyler@users.noreply.github.com> Date: Fri, 24 Jun 2022 15:56:18 +0200 Subject: [PATCH 004/584] Redetect indent and line endings after language server replaces documents (#2778) * redetect indent and line endings after language server replaces document * removes nested if * always redetect indent and line endings after format This reverts commit 764d14f55894dc7213e48022dfa0f91829b8ef59. --- helix-term/src/commands.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index a07b51091b8c2..43bc0c7c592c5 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2343,6 +2343,7 @@ async fn make_format_callback( if doc.version() == doc_version { doc.apply(&Transaction::from(format), view_id); doc.append_changes_to_history(view_id); + doc.detect_indent_and_line_ending(); if let Modified::SetUnmodified = modified { doc.reset_modified(); } From d948ace67b10f162fd00106b9be2c1c680f33861 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Fri, 24 Jun 2022 08:58:04 -0500 Subject: [PATCH 005/584] check selection's visible width when copying on mouse click (#2711) * check selection's visible width when copying on mouse click Mouse-click-up copies the selection produced by dragging. The event is ignored if the selection has a width of 1 though so you don't copy when clicking rather than dragging. The current check copies text when it has a visible width of 1 but is actually multiple characters in the rope like a CRLF line-ending. With this change we check the unicode width of the character(s) in the selection rather than the range length, so clicking on a CRLF line-ending does not copy. * use range.fragment to simplify getting the primary selection width --- helix-term/src/ui/editor.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index debce9b4412b7..70f60070805c1 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1127,9 +1127,14 @@ impl EditorView { } let (view, doc) = current!(cxt.editor); - let range = doc.selection(view.id).primary(); - if range.to() - range.from() <= 1 { + if doc + .selection(view.id) + .primary() + .fragment(doc.text().slice(..)) + .width() + <= 1 + { return EventResult::Ignored(None); } From 3dbad0442fc3038dd0b0f6bd07ba0e40d2d92000 Mon Sep 17 00:00:00 2001 From: Saber Haj Rabiee Date: Fri, 24 Jun 2022 08:14:48 -0700 Subject: [PATCH 006/584] fixes showing the last prompt on empty input (#2870) --- helix-core/src/register.rs | 4 ++++ helix-term/src/ui/prompt.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/helix-core/src/register.rs b/helix-core/src/register.rs index 7fa34644bde7f..1cff77ba3717a 100644 --- a/helix-core/src/register.rs +++ b/helix-core/src/register.rs @@ -73,6 +73,10 @@ impl Registers { self.read(name).and_then(|entries| entries.first()) } + pub fn last(&self, name: char) -> Option<&String> { + self.read(name).and_then(|entries| entries.last()) + } + pub fn inner(&self) -> &HashMap { &self.inner } diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index beba8ce9a06bf..55b08032dfc97 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -443,7 +443,7 @@ impl Prompt { let input: Cow = if self.line.is_empty() { // latest value in the register list self.history_register - .and_then(|reg| cx.editor.registers.first(reg)) + .and_then(|reg| cx.editor.registers.last(reg)) .map(|entry| entry.into()) .unwrap_or_else(|| Cow::from("")) } else { @@ -522,7 +522,7 @@ impl Component for Prompt { let input: Cow = if self.line.is_empty() { // latest value in the register list self.history_register - .and_then(|reg| cx.editor.registers.first(reg).cloned()) + .and_then(|reg| cx.editor.registers.last(reg).cloned()) .map(|entry| entry.into()) .unwrap_or_else(|| Cow::from("")) } else { From 33e6df870710a48e89875b6f7471b9ee5f54af50 Mon Sep 17 00:00:00 2001 From: Hekno25 <87552206+Hekno25@users.noreply.github.com> Date: Fri, 24 Jun 2022 16:21:26 -0500 Subject: [PATCH 007/584] feat: add wgsl_analyzer as wgsl language server (#2872) --- book/src/generated/lang-support.md | 2 +- languages.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 0ed4062d41e07..7d0ac20202dd8 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -98,6 +98,6 @@ | vala | ✓ | | | `vala-language-server` | | verilog | ✓ | ✓ | | `svlangserver` | | vue | ✓ | | | `vls` | -| wgsl | ✓ | | | | +| wgsl | ✓ | | | `wgsl_analyzer` | | yaml | ✓ | | ✓ | `yaml-language-server` | | zig | ✓ | | ✓ | `zls` | diff --git a/languages.toml b/languages.toml index e0a57080573ff..62513141ca2a4 100644 --- a/languages.toml +++ b/languages.toml @@ -787,6 +787,7 @@ scope = "source.wgsl" file-types = ["wgsl"] roots = [] comment-token = "//" +language-server = { command = "wgsl_analyzer" } indent = { tab-width = 4, unit = " " } [[grammar]] From 18435899b2310f5605153acfb7108e01f70caa79 Mon Sep 17 00:00:00 2001 From: two-six Date: Sat, 25 Jun 2022 19:09:04 +0200 Subject: [PATCH 008/584] [Theme] Acme (#2876) --- runtime/themes/acme.toml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 runtime/themes/acme.toml diff --git a/runtime/themes/acme.toml b/runtime/themes/acme.toml new file mode 100644 index 0000000000000..263cbf90eb57c --- /dev/null +++ b/runtime/themes/acme.toml @@ -0,0 +1,28 @@ +# Author: Two-Six + +"ui.background" = {bg="acme_bg"} +"ui.text" = "black" +"ui.selection" = {bg="selected"} +"ui.statusline" = {bg="acme_bar_bg"} +"ui.statusline.inactive" = {bg="acme_bar_inactive"} +"ui.virtual" = "indent" +"ui.cursor.match" = {bg="acme_bar_bg"} +"ui.cursor" = {bg="cursor", fg="white"} +"string" = "red" +"comment" = "green" +"ui.menu.selected" = {bg="selected"} +"diagnostic.error" = {bg="white", modifiers=["bold"]} +"diagnostic.warning" = {bg="white", modifiers=["bold"]} +"diagnostic.hint" = {bg="white", modifiers=["bold"]} + +[palette] +white = "#ffffff" +acme_bg = "#ffffea" +black = "#000000" +selected = "#eeee9e" +acme_bar_bg = "#aeeeee" +acme_bar_inactive = "#eaffff" +cursor = "#444444" +red = "#a0342f" +green = "#065905" +indent = "#aaaaaa" From e1b1a5ebc01311ff1ef34e205015570a2856481d Mon Sep 17 00:00:00 2001 From: Triton171 Date: Sat, 25 Jun 2022 20:12:30 +0200 Subject: [PATCH 009/584] Fix edge-case in tree-sitter expand_selection selection command (#2877) Co-authored-by: Triton171 --- helix-core/src/object.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs index b06f4144459bb..d2d4fe70ac028 100644 --- a/helix-core/src/object.rs +++ b/helix-core/src/object.rs @@ -2,12 +2,11 @@ use crate::{Range, RopeSlice, Selection, Syntax}; use tree_sitter::Node; 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) + select_node_impl(syntax, text, selection, |mut node, from, to| { + while node.start_byte() == from && node.end_byte() == to { + node = node.parent()?; } + Some(node) }) } From ba85779902877340d17f27dce1aeced98abfaeb6 Mon Sep 17 00:00:00 2001 From: Amit Beka Date: Sat, 25 Jun 2022 23:28:26 +0300 Subject: [PATCH 010/584] book: fix the description of dot repeat (#2878) Co-authored-by: amitbeka <---> --- book/src/keymap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index 7efbdd23705ea..e6abb9c928ca3 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -52,7 +52,7 @@ | `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 | +| `.` | Repeat last insert | N/A | | `u` | Undo change | `undo` | | `U` | Redo change | `redo` | | `Alt-u` | Move backward in history | `earlier` | From 16ccc7ead88faf060236cbff72dee52c58e37156 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sun, 26 Jun 2022 14:26:35 +0530 Subject: [PATCH 011/584] Add single width left margin for completion popup (#2728) * Add single width left margin for completion popup * Clear with ui.menu style before rendering menu When rendering a completion popup, the popup component will clear the area with ui.popup and then the menu component would draw over it using a table component. We remove the left edge of the area before passing it to the table component (so that it will be left as padding), and the table component uses ui.menu as the style. If ui.menu and ui.popup are different the left edge of the popup will look different from the rest of the popup. We avoid this by clearing the whole area with ui.menu in Menu::render --- helix-term/src/ui/menu.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index 477b218ad63da..fa56008d6912e 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -48,6 +48,8 @@ pub struct Menu { } impl Menu { + const LEFT_PADDING: usize = 1; + // TODO: it's like a slimmed down picker, share code? (picker = menu + prompt with different // rendering) pub fn new( @@ -150,6 +152,7 @@ impl Menu { len += 1; // +1: reserve some space for scrollbar } + len += Self::LEFT_PADDING; let width = len.min(viewport.0 as usize); self.widths = max_lens @@ -271,6 +274,7 @@ impl Component for Menu { .try_get("ui.menu") .unwrap_or_else(|| theme.get("ui.text")); let selected = theme.get("ui.menu.selected"); + surface.clear_with(area, style); let scroll = self.scroll; @@ -306,7 +310,7 @@ impl Component for Menu { use tui::widgets::TableState; table.render_table( - area, + area.clip_left(Self::LEFT_PADDING as u16), surface, &mut TableState { offset: scroll, @@ -314,6 +318,12 @@ impl Component for Menu { }, ); + if let Some(cursor) = self.cursor { + let offset_from_top = cursor - scroll; + let cell = &mut surface[(area.x, area.y + offset_from_top as u16)]; + cell.set_style(selected); + } + let fits = len <= win_height; for (i, _) in (scroll..(scroll + win_height).min(len)).enumerate() { From 24351c20d41c26df0c695940e6790525858ab1c1 Mon Sep 17 00:00:00 2001 From: Kihaya Sugiura Date: Mon, 27 Jun 2022 02:04:53 +0900 Subject: [PATCH 012/584] languages: Fix ruby rakefile and gemfile file type (#2875) --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 62513141ca2a4..aba5fd44c29b9 100644 --- a/languages.toml +++ b/languages.toml @@ -446,7 +446,7 @@ source = { git = "https://github.com/cstrahan/tree-sitter-nix", rev = "6b71a810c name = "ruby" scope = "source.ruby" injection-regex = "ruby" -file-types = ["rb", "rake", "rakefile", "irb", "gemfile", "gemspec"] +file-types = ["rb", "rake", "rakefile", "irb", "gemfile", "gemspec", "Rakefile", "Gemfile"] shebangs = ["ruby"] roots = [] comment-token = "#" From c113531db9f9dbe522adea584b4c18083af578e7 Mon Sep 17 00:00:00 2001 From: Ramojus <41536253+Ramojus@users.noreply.github.com> Date: Mon, 27 Jun 2022 07:40:08 +0300 Subject: [PATCH 013/584] add meliora theme (#2884) --- runtime/themes/meliora.toml | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 runtime/themes/meliora.toml diff --git a/runtime/themes/meliora.toml b/runtime/themes/meliora.toml new file mode 100644 index 0000000000000..fa474abbb14f9 --- /dev/null +++ b/runtime/themes/meliora.toml @@ -0,0 +1,90 @@ +# Author: Ramojus + +"comment" = { fg = "comment" } +"constant" = { fg = "magenta" } +"function" = { fg = "blue" } +"keyword.control.import" = { fg = "orange" } +"keyword.control" = { fg = "red" } +"keyword.function" = { fg = "red" } +"keyword" = { fg = "orange" } +"operator" = { fg = "secondary_white" } +"punctuation" = { fg = "secondary_white" } +"string" = { fg = "yellow" } +"string.regexp" = { fg = "orange" } +"tag" = { fg = "red" } +"type" = { fg = "secondary_white" } +"namespace" = { fg = "blue" } +"variable" = { fg = "white" } +"label" = { fg = "orange" } + +"diff.plus" = { fg = "blue" } +"diff.delta" = { fg = "magenta" } +"diff.minus" = { fg = "red" } + +"ui.cursor" = { bg = "light_grey", fg = "black"} +"ui.cursor.match" = { bg = "dark_grey" } +"ui.cursor.primary" = { bg = "secondary_white", fg = "black" } + +"ui.linenr" = { fg = "grey", bg = "dark_black"} +"ui.linenr.selected" = { fg = "dark_white", bg = "dark_black"} +"ui.gutter" = { bg = "dark_black" } + +"ui.background" = { fg = "light_grey", bg = "black" } +"ui.background.separator" = { fg = "dark_grey" } +"ui.help" = { fg = "white", bg = "light_black2" } +"ui.menu" = { fg = "dark_white", bg = "light_black" } +"ui.menu.selected" = { bg = "orange" , fg = "black" } +"ui.popup" = { fg = "dark_white", bg = "light_black" } +"ui.window" = { fg = "light_black2" } + +"ui.selection" = { bg = "light_black2" } +"ui.selection.primary" = { bg = "light_black2" } + +"ui.statusline" = { fg = "dark_white", bg = "light_black2" } +"ui.statusline.inactive" = { fg = "dark_white2", bg = "light_black" } + +"ui.text" = { fg = "white" } +"ui.text.focus" = { fg = "orange" } + +"ui.virtual.ruler" = { bg = "light_black" } +"ui.virtual.indent-guide" = { fg = "light_black" } +"ui.virtual.whitespace" = { fg = "dark_grey" } + +"diagnostic" = { modifiers = ["underlined"] } +"error" = { fg = "red" } +"warning" = { fg = "orange" } +"info" = { fg = "blue" } +"hint" = { fg = "magenta" } +"special" = { fg = "yellow" } + +"markup.heading" = { fg = "orange" } +"markup.list" = { fg = "blue" } +"markup.bold" = { fg = "magenta" } +"markup.italic" = { fg = "blue" } +"markup.link.url" = { fg = "comment" , modifiers = ["underlined"] } +"markup.link.text" = { fg = "comment" } +"markup.quote" = { fg = "yellow" } +"markup.raw" = { fg = "blue" } + +[palette] +red = "#d29595" +orange = "#cbab8a" +yellow = "#c9b58e" +blue = "#a49db9" +magenta = "#b494af" + +comment = "#707035" + +black = "#1c1917" +light_black = "#292725" +light_black2 = "#302D2B" +dark_black = "#191514" +dark_light_black = "#211d1c" + +white = "#dad7d5" +dark_white = "#aaa7a6" +dark_white2 = "#949290" +dark_grey = "#4c4b49" +grey = "#605e5d" +light_grey = "#6a6867" +secondary_white = "#c2b4a8" From a26943de4e421a453371aa53b3bb11a2baabff56 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 27 Jun 2022 13:22:31 +0530 Subject: [PATCH 014/584] Right align scrollbar with track in completion popup (#2754) - Align the scollbar to the right edge of the popup rather than at a margin of one. - Add a scrollbar track and a new scope `ui.menu.scroll`. --- book/src/themes.md | 1 + helix-term/src/ui/menu.rs | 26 +++++++++++++++++++------- runtime/themes/onedark.toml | 1 + theme.toml | 1 + 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 57a8d5d1f7605..ea52835d499ce 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -231,6 +231,7 @@ These scopes are used for theming the editor interface. | `ui.virtual.indent-guide` | Vertical indent width guides | | `ui.menu` | Code and command completion menus | | `ui.menu.selected` | Selected autocomplete item | +| `ui.menu.scroll` | `fg` sets thumb color, `bg` sets track color of scrollbar | | `ui.selection` | For selections in the editing area | | `ui.selection.primary` | | | `warning` | Diagnostics warning (gutter) | diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index fa56008d6912e..0519374a3c634 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -310,7 +310,7 @@ impl Component for Menu { use tui::widgets::TableState; table.render_table( - area.clip_left(Self::LEFT_PADDING as u16), + area.clip_left(Self::LEFT_PADDING as u16).clip_right(1), surface, &mut TableState { offset: scroll, @@ -320,20 +320,32 @@ impl Component for Menu { if let Some(cursor) = self.cursor { let offset_from_top = cursor - scroll; - let cell = &mut surface[(area.x, area.y + offset_from_top as u16)]; - cell.set_style(selected); + let left = &mut surface[(area.left(), area.y + offset_from_top as u16)]; + left.set_style(selected); + let right = &mut surface[( + area.right().saturating_sub(1), + area.y + offset_from_top as u16, + )]; + right.set_style(selected); } let fits = len <= win_height; + let scroll_style = theme.get("ui.menu.scroll"); for (i, _) in (scroll..(scroll + win_height).min(len)).enumerate() { + let cell = &mut surface[(area.x + area.width - 1, area.y + i as u16)]; + + if !fits { + // Draw scroll track + cell.set_symbol("▐"); // right half block + cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset)); + } + let is_marked = i >= scroll_line && i < scroll_line + scroll_height; if !fits && is_marked { - let cell = &mut surface[(area.x + area.width - 2, area.y + i as u16)]; - cell.set_symbol("▐"); - // cell.set_style(selected); - // cell.set_style(if is_marked { selected } else { style }); + // Draw scroll thumb + cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset)); } } } diff --git a/runtime/themes/onedark.toml b/runtime/themes/onedark.toml index d0cbb9494cdc8..a4d05ca8eb3d0 100644 --- a/runtime/themes/onedark.toml +++ b/runtime/themes/onedark.toml @@ -73,6 +73,7 @@ diagnostic = { modifiers = ["underlined"] } "ui.window" = { bg = "gray" } "ui.menu" = { fg = "white", bg = "gray" } "ui.menu.selected" = { fg = "black", bg = "blue" } +"ui.menu.scroll" = { fg = "white", bg = "light-gray" } [palette] diff --git a/theme.toml b/theme.toml index 8e550f922e131..3fc694e4cdbfa 100644 --- a/theme.toml +++ b/theme.toml @@ -69,6 +69,7 @@ label = "honey" "ui.menu" = { fg = "lavender", bg = "revolver" } "ui.menu.selected" = { fg = "revolver", bg = "white" } +"ui.menu.scroll" = { fg = "lavender", bg = "comet" } diagnostic = { modifiers = ["underlined"] } # "diagnostic.hint" = { fg = "revolver", bg = "lilac" } From 8dc86beabd9334d013291656313cb33a88754c42 Mon Sep 17 00:00:00 2001 From: Tobias Menzi Date: Mon, 27 Jun 2022 10:09:34 +0200 Subject: [PATCH 015/584] Implement cursorline (#2170) * Implement cursorline * Binary search possible lines --- book/src/configuration.md | 1 + helix-term/src/ui/editor.rs | 41 +++++++++++++++++++++++++++++++++++++ helix-view/src/editor.rs | 3 +++ 3 files changed, 45 insertions(+) diff --git a/book/src/configuration.md b/book/src/configuration.md index 3fa9b307ab385..af85379f8ff39 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -37,6 +37,7 @@ hidden = false | `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` 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` | +| `cursorline` | Highlight all lines with a cursor. | `false` | | `gutters` | Gutters to display: Available are `diagnostics` and `line-numbers`, note that `diagnostics` also includes other features like breakpoints | `["diagnostics", "line-numbers"]` | | `auto-completion` | Enable automatic pop up of auto-completion. | `true` | | `auto-format` | Enable automatic formatting on save. | `true` | diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 70f60070805c1..2f44dae9cb3fe 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -112,6 +112,10 @@ impl EditorView { } } + if editor.config().cursorline { + Self::highlight_cursorline(doc, view, surface, theme); + } + let highlights = Self::doc_syntax_highlights(doc, view.offset, inner.height, theme); let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme)); let highlights: Box> = if is_focused { @@ -686,6 +690,43 @@ impl EditorView { ); } + /// Apply the highlighting on the lines where a cursor is active + pub fn highlight_cursorline(doc: &Document, view: &View, surface: &mut Surface, theme: &Theme) { + let text = doc.text().slice(..); + let last_line = view.last_line(doc); + + let primary_line = doc.selection(view.id).primary().cursor_line(text); + + // The secondary_lines do contain the primary_line, it doesn't matter + // as the else-if clause in the loop later won't test for the + // secondary_lines if primary_line == line. + // It's used inside a loop so the collect isn't needless: + // https://github.com/rust-lang/rust-clippy/issues/6164 + #[allow(clippy::needless_collect)] + let secondary_lines: Vec<_> = doc + .selection(view.id) + .iter() + .map(|range| range.cursor_line(text)) + .collect(); + + let primary_style = theme.get("ui.cursorline.primary"); + let secondary_style = theme.get("ui.cursorline.secondary"); + + for line in view.offset.row..(last_line + 1) { + let area = Rect::new( + view.area.x, + view.area.y + (line - view.offset.row) as u16, + view.area.width, + 1, + ); + if primary_line == line { + surface.set_style(area, primary_style); + } else if secondary_lines.binary_search(&line).is_ok() { + surface.set_style(area, secondary_style); + } + } + } + pub fn render_statusline( &self, doc: &Document, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index c5a458d7f7db5..a9741a33ff1b7 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -121,6 +121,8 @@ pub struct Config { pub shell: Vec, /// Line number mode. pub line_number: LineNumber, + /// Highlight the lines cursors are currently on. Defaults to false. + pub cursorline: bool, /// Gutters. Default ["diagnostics", "line-numbers"] pub gutters: Vec, /// Middle click paste support. Defaults to true. @@ -394,6 +396,7 @@ impl Default for Config { vec!["sh".to_owned(), "-c".to_owned()] }, line_number: LineNumber::Absolute, + cursorline: false, gutters: vec![GutterType::Diagnostics, GutterType::LineNumbers], middle_click_paste: true, auto_pairs: AutoPairConfig::default(), From 33d287a9ad4e72311cf74c7070406626f8cad4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 27 Jun 2022 17:27:24 +0900 Subject: [PATCH 016/584] Add a default cursorline style for the primary selection --- theme.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/theme.toml b/theme.toml index 3fc694e4cdbfa..ab7c995a8c1f9 100644 --- a/theme.toml +++ b/theme.toml @@ -65,6 +65,7 @@ label = "honey" "ui.cursor.insert" = { bg = "white" } "ui.cursor.match" = { fg = "#212121", bg = "#6C6999" } "ui.cursor" = { modifiers = ["reversed"] } +"ui.cursorline.primary" = { bg = "bossanova" } "ui.highlight" = { bg = "bossanova" } "ui.menu" = { fg = "lavender", bg = "revolver" } From 24f03097e3b4aef62aa56bb27e0853b60a4cb417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 27 Jun 2022 17:27:44 +0900 Subject: [PATCH 017/584] Remove some more unwraps --- helix-lsp/src/client.rs | 6 +++--- helix-lsp/src/jsonrpc.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index 8ee9c9d713191..cf6706b5867f7 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -271,8 +271,8 @@ impl Client { // ------------------------------------------------------------------------------------------- pub(crate) async fn initialize(&self) -> Result { - if self.config.is_some() { - log::info!("Using custom LSP config: {}", self.config.as_ref().unwrap()); + if let Some(config) = &self.config { + log::info!("Using custom LSP config: {}", config); } #[allow(deprecated)] @@ -896,8 +896,8 @@ impl Client { Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (), // None | Some(false) _ => { + log::warn!("rename_symbol failed: The server does not support rename"); let err = "The server does not support rename"; - log::warn!("rename_symbol failed: {}", err); return Err(anyhow!(err)); } }; diff --git a/helix-lsp/src/jsonrpc.rs b/helix-lsp/src/jsonrpc.rs index b9b3fd2c0e1a7..ed63da137e89c 100644 --- a/helix-lsp/src/jsonrpc.rs +++ b/helix-lsp/src/jsonrpc.rs @@ -310,7 +310,7 @@ fn method_call_serialize() { id: Id::Num(1), }; - let serialized = serde_json::to_string(&m).unwrap(); + let serialized = serde_json::json!(&m); assert_eq!( serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1}"# @@ -327,7 +327,7 @@ fn notification_serialize() { params: Params::Array(vec![Value::from(1), Value::from(2)]), }; - let serialized = serde_json::to_string(&n).unwrap(); + let serialized = serde_json::json!(&n); assert_eq!( serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2]}"# From 425de09d217002d3b7c6cad864015277cfe041a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 27 Jun 2022 17:35:23 +0900 Subject: [PATCH 018/584] Fix tests again --- helix-lsp/src/jsonrpc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helix-lsp/src/jsonrpc.rs b/helix-lsp/src/jsonrpc.rs index ed63da137e89c..b9b3fd2c0e1a7 100644 --- a/helix-lsp/src/jsonrpc.rs +++ b/helix-lsp/src/jsonrpc.rs @@ -310,7 +310,7 @@ fn method_call_serialize() { id: Id::Num(1), }; - let serialized = serde_json::json!(&m); + let serialized = serde_json::to_string(&m).unwrap(); assert_eq!( serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1}"# @@ -327,7 +327,7 @@ fn notification_serialize() { params: Params::Array(vec![Value::from(1), Value::from(2)]), }; - let serialized = serde_json::json!(&n); + let serialized = serde_json::to_string(&n).unwrap(); assert_eq!( serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2]}"# From fde9e034d4a7bd16d3c9780600874323e4e91628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 27 Jun 2022 17:51:22 +0900 Subject: [PATCH 019/584] Only draw cursorline in the currently focused buffer --- helix-term/src/ui/editor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 2f44dae9cb3fe..f71f716ec17fc 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -112,7 +112,7 @@ impl EditorView { } } - if editor.config().cursorline { + if is_focused && editor.config().cursorline { Self::highlight_cursorline(doc, view, surface, theme); } From 096abdd19bb422cba607d43d05b195b37a7f95e9 Mon Sep 17 00:00:00 2001 From: lazytanuki <43273245+lazytanuki@users.noreply.github.com> Date: Mon, 27 Jun 2022 13:19:56 +0200 Subject: [PATCH 020/584] feat: highlight / select symbol under cursor using LSP textDocument/documentHighlight (#2738) * feat: highlight symbol under cursor using LSP textDocument/documentHighlight * fix: please clippy * fix: shorter description and code style --- helix-lsp/src/client.rs | 20 +++++++++++++++ helix-term/src/commands.rs | 1 + helix-term/src/commands/lsp.rs | 43 ++++++++++++++++++++++++++++++++ helix-term/src/keymap/default.rs | 1 + 4 files changed, 65 insertions(+) diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index cf6706b5867f7..aa83354142636 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -759,6 +759,26 @@ impl Client { Ok(response.unwrap_or_default()) } + pub fn text_document_document_highlight( + &self, + text_document: lsp::TextDocumentIdentifier, + position: lsp::Position, + work_done_token: Option, + ) -> impl Future> { + let params = lsp::DocumentHighlightParams { + text_document_position_params: lsp::TextDocumentPositionParams { + text_document, + position, + }, + work_done_progress_params: lsp::WorkDoneProgressParams { work_done_token }, + partial_result_params: lsp::PartialResultParams { + partial_result_token: None, + }, + }; + + self.call::(params) + } + fn goto_request< T: lsp::request::Request< Params = lsp::GotoDefinitionParams, diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 43bc0c7c592c5..0a28444bdc09d 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -263,6 +263,7 @@ impl MappableCommand { code_action, "Perform code action", buffer_picker, "Open buffer picker", symbol_picker, "Open symbol picker", + select_references_to_symbol_under_cursor, "Select symbol references", workspace_symbol_picker, "Open workspace symbol picker", last_picker, "Open last picker", prepend_to_line, "Insert at start of line", diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 6f75fb497143b..c1cdb164219a4 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -655,6 +655,7 @@ pub fn signature_help(cx: &mut Context) { }, ); } + pub fn hover(cx: &mut Context) { let (view, doc) = current!(cx.editor); let language_server = language_server!(cx.editor, doc); @@ -704,6 +705,7 @@ pub fn hover(cx: &mut Context) { }, ); } + pub fn rename_symbol(cx: &mut Context) { ui::prompt( cx, @@ -729,3 +731,44 @@ pub fn rename_symbol(cx: &mut Context) { }, ); } + +pub fn select_references_to_symbol_under_cursor(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + let language_server = language_server!(cx.editor, doc); + let offset_encoding = language_server.offset_encoding(); + + let pos = doc.position(view.id, offset_encoding); + + let future = language_server.text_document_document_highlight(doc.identifier(), pos, None); + + cx.callback( + future, + move |editor, _compositor, response: Option>| { + let document_highlights = match response { + Some(highlights) if !highlights.is_empty() => highlights, + _ => return, + }; + let (view, doc) = current!(editor); + let language_server = language_server!(editor, doc); + let offset_encoding = language_server.offset_encoding(); + let text = doc.text(); + let pos = doc.selection(view.id).primary().head; + + // We must find the range that contains our primary cursor to prevent our primary cursor to move + let mut primary_index = 0; + let ranges = document_highlights + .iter() + .filter_map(|highlight| lsp_range_to_range(text, highlight.range, offset_encoding)) + .enumerate() + .map(|(i, range)| { + if range.contains(pos) { + primary_index = i; + } + range + }) + .collect(); + let selection = Selection::new(ranges, primary_index); + doc.set_selection(view.id, selection); + }, + ); +} diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index c36951172306b..e5bb0482d0a31 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -259,6 +259,7 @@ pub fn default() -> HashMap { "/" => global_search, "k" => hover, "r" => rename_symbol, + "h" => select_references_to_symbol_under_cursor, "?" => command_palette, }, "z" => { "View" From db2aa57074c1eeab45899b270b660d12953915b8 Mon Sep 17 00:00:00 2001 From: ramojus <41536253+Ramojus@users.noreply.github.com> Date: Mon, 27 Jun 2022 15:49:09 +0300 Subject: [PATCH 021/584] update meliora theme (#2890) --- runtime/themes/meliora.toml | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/runtime/themes/meliora.toml b/runtime/themes/meliora.toml index fa474abbb14f9..72ade8ac52b66 100644 --- a/runtime/themes/meliora.toml +++ b/runtime/themes/meliora.toml @@ -26,30 +26,31 @@ "ui.cursor.primary" = { bg = "secondary_white", fg = "black" } "ui.linenr" = { fg = "grey", bg = "dark_black"} -"ui.linenr.selected" = { fg = "dark_white", bg = "dark_black"} +"ui.linenr.selected" = { fg = "dark_white", bg = "dark_light_black"} "ui.gutter" = { bg = "dark_black" } "ui.background" = { fg = "light_grey", bg = "black" } "ui.background.separator" = { fg = "dark_grey" } -"ui.help" = { fg = "white", bg = "light_black2" } +"ui.help" = { fg = "white", bg = "light_black3" } "ui.menu" = { fg = "dark_white", bg = "light_black" } "ui.menu.selected" = { bg = "orange" , fg = "black" } "ui.popup" = { fg = "dark_white", bg = "light_black" } -"ui.window" = { fg = "light_black2" } +"ui.window" = { fg = "light_black3" } -"ui.selection" = { bg = "light_black2" } -"ui.selection.primary" = { bg = "light_black2" } +"ui.selection" = { bg = "light_black3" } +"ui.selection.primary" = { bg = "light_black3", modifiers = ["bold"] } +"ui.cursorline.primary" = { bg = "light_black" } -"ui.statusline" = { fg = "dark_white", bg = "light_black2" } +"ui.statusline" = { fg = "dark_white", bg = "light_black3" } "ui.statusline.inactive" = { fg = "dark_white2", bg = "light_black" } "ui.text" = { fg = "white" } "ui.text.focus" = { fg = "orange" } -"ui.virtual.ruler" = { bg = "light_black" } -"ui.virtual.indent-guide" = { fg = "light_black" } -"ui.virtual.whitespace" = { fg = "dark_grey" } - +"ui.virtual.ruler" = { bg = "light_black2" } +"ui.virtual.indent-guide" = { fg = "dark_grey2" } +"ui.virtual.whitespace" = { fg = "grey" } + "diagnostic" = { modifiers = ["underlined"] } "error" = { fg = "red" } "warning" = { fg = "orange" } @@ -75,16 +76,18 @@ magenta = "#b494af" comment = "#707035" +light_black = "#252220" +light_black2 = "#292725" +light_black3 = "#302D2B" black = "#1c1917" -light_black = "#292725" -light_black2 = "#302D2B" dark_black = "#191514" dark_light_black = "#211d1c" white = "#dad7d5" dark_white = "#aaa7a6" dark_white2 = "#949290" -dark_grey = "#4c4b49" -grey = "#605e5d" light_grey = "#6a6867" +grey = "#605e5d" +dark_grey = "#4c4b49" +dark_grey2 = "#383735" secondary_white = "#c2b4a8" From 23ce5f1837d34649d1c973d3cd55b7a1a49885b2 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 27 Jun 2022 21:06:41 +0530 Subject: [PATCH 022/584] Add cursorline scope for onedark theme (#2892) --- runtime/themes/onedark.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/themes/onedark.toml b/runtime/themes/onedark.toml index a4d05ca8eb3d0..aec7ba960f02e 100644 --- a/runtime/themes/onedark.toml +++ b/runtime/themes/onedark.toml @@ -58,6 +58,7 @@ diagnostic = { modifiers = ["underlined"] } "ui.selection" = { bg = "light-gray" } "ui.selection.primary" = { bg = "gray" } +"ui.cursorline.primary" = { bg = "light-black" } "ui.linenr" = { fg = "linenr" } "ui.linenr.selected" = { fg = "white" } From 3108a11d350ab89f827d30664b9c00ca751b6abc Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 27 Jun 2022 21:35:07 +0530 Subject: [PATCH 023/584] Refactor handling of mouse events (#2893) - Simplified match statements by destructuring MouseEvent struct at the top and then matching on event.kind. - Extracted out closures for calculating (1) position and view of mouse click and (2) gutter coordinates and view of mouse click. --- helix-term/src/ui/editor.rs | 107 +++++++++++++----------------------- 1 file changed, 38 insertions(+), 69 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index f71f716ec17fc..32f70c8b1fad3 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1051,22 +1051,33 @@ impl EditorView { cxt: &mut commands::Context, ) -> EventResult { let config = cxt.editor.config(); - match event { - MouseEvent { - kind: MouseEventKind::Down(MouseButton::Left), - row, - column, - modifiers, - .. - } => { - let editor = &mut cxt.editor; + let MouseEvent { + kind, + row, + column, + modifiers, + .. + } = event; + + let pos_and_view = |editor: &Editor, row, column| { + editor.tree.views().find_map(|(view, _focus)| { + view.pos_at_screen_coords(&editor.documents[&view.doc], row, column) + .map(|pos| (pos, view.id)) + }) + }; + + let gutter_coords_and_view = |editor: &Editor, row, column| { + editor.tree.views().find_map(|(view, _focus)| { + view.gutter_coords_at_screen_coords(row, column) + .map(|coords| (coords, view.id)) + }) + }; - let result = editor.tree.views().find_map(|(view, _focus)| { - view.pos_at_screen_coords(&editor.documents[&view.doc], row, column) - .map(|pos| (pos, view.id)) - }); + match kind { + MouseEventKind::Down(MouseButton::Left) => { + let editor = &mut cxt.editor; - if let Some((pos, view_id)) = result { + if let Some((pos, view_id)) = pos_and_view(editor, row, column) { let doc = editor.document_mut(editor.tree.get(view_id).doc).unwrap(); if modifiers == crossterm::event::KeyModifiers::ALT { @@ -1081,12 +1092,7 @@ impl EditorView { return EventResult::Consumed(None); } - let result = editor.tree.views().find_map(|(view, _focus)| { - view.gutter_coords_at_screen_coords(row, column) - .map(|coords| (coords, view.id)) - }); - - if let Some((coords, view_id)) = result { + if let Some((coords, view_id)) = gutter_coords_and_view(editor, row, column) { editor.tree.focus = view_id; let view = editor.tree.get(view_id); @@ -1107,12 +1113,7 @@ impl EditorView { EventResult::Ignored(None) } - MouseEvent { - kind: MouseEventKind::Drag(MouseButton::Left), - row, - column, - .. - } => { + MouseEventKind::Drag(MouseButton::Left) => { let (view, doc) = current!(cxt.editor); let pos = match view.pos_at_screen_coords(doc, row, column) { @@ -1124,15 +1125,11 @@ impl EditorView { let primary = selection.primary_mut(); *primary = primary.put_cursor(doc.text().slice(..), pos, true); doc.set_selection(view.id, selection); + EventResult::Consumed(None) } - MouseEvent { - kind: MouseEventKind::ScrollUp | MouseEventKind::ScrollDown, - row, - column, - .. - } => { + MouseEventKind::ScrollUp | MouseEventKind::ScrollDown => { let current_view = cxt.editor.tree.focus; let direction = match event.kind { @@ -1141,13 +1138,8 @@ impl EditorView { _ => unreachable!(), }; - let result = cxt.editor.tree.views().find_map(|(view, _focus)| { - view.pos_at_screen_coords(&cxt.editor.documents[&view.doc], row, column) - .map(|_| view.id) - }); - - match result { - Some(view_id) => cxt.editor.tree.focus = view_id, + match pos_and_view(cxt.editor, row, column) { + Some((_, view_id)) => cxt.editor.tree.focus = view_id, None => return EventResult::Ignored(None), } @@ -1159,10 +1151,7 @@ impl EditorView { EventResult::Consumed(None) } - MouseEvent { - kind: MouseEventKind::Up(MouseButton::Left), - .. - } => { + MouseEventKind::Up(MouseButton::Left) => { if !config.middle_click_paste { return EventResult::Ignored(None); } @@ -1184,19 +1173,8 @@ impl EditorView { EventResult::Consumed(None) } - MouseEvent { - kind: MouseEventKind::Up(MouseButton::Right), - row, - column, - modifiers, - .. - } => { - let result = cxt.editor.tree.views().find_map(|(view, _focus)| { - view.gutter_coords_at_screen_coords(row, column) - .map(|coords| (coords, view.id)) - }); - - if let Some((coords, view_id)) = result { + MouseEventKind::Up(MouseButton::Right) => { + if let Some((coords, view_id)) = gutter_coords_and_view(cxt.editor, row, column) { cxt.editor.tree.focus = view_id; let view = cxt.editor.tree.get(view_id); @@ -1213,16 +1191,11 @@ impl EditorView { return EventResult::Consumed(None); } } + EventResult::Ignored(None) } - MouseEvent { - kind: MouseEventKind::Up(MouseButton::Middle), - row, - column, - modifiers, - .. - } => { + MouseEventKind::Up(MouseButton::Middle) => { let editor = &mut cxt.editor; if !config.middle_click_paste { return EventResult::Ignored(None); @@ -1235,16 +1208,12 @@ impl EditorView { return EventResult::Consumed(None); } - let result = editor.tree.views().find_map(|(view, _focus)| { - view.pos_at_screen_coords(&editor.documents[&view.doc], row, column) - .map(|pos| (pos, view.id)) - }); - - if let Some((pos, view_id)) = result { + if let Some((pos, view_id)) = pos_and_view(editor, row, column) { let doc = editor.document_mut(editor.tree.get(view_id).doc).unwrap(); doc.set_selection(view_id, Selection::point(pos)); editor.tree.focus = view_id; commands::MappableCommand::paste_primary_clipboard_before.execute(cxt); + return EventResult::Consumed(None); } From fd644ccfa24b8141c1b8ea32349a0844fe7c884a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 07:52:27 +0800 Subject: [PATCH 024/584] build(deps): bump tree-sitter from 0.20.4 to 0.20.8 (#2895) Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.4 to 0.20.8. - [Release notes](https://github.com/tree-sitter/tree-sitter/releases) - [Commits](https://github.com/tree-sitter/tree-sitter/commits) --- updated-dependencies: - dependency-name: tree-sitter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af08f905e920b..0567a4af111c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1215,9 +1215,9 @@ dependencies = [ [[package]] name = "tree-sitter" -version = "0.20.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e34327f8eac545e3f037382471b2b19367725a242bba7bc45edb9efb49fe39a" +checksum = "268bf3e3ca0c09e5d21b59c2638e12cb6dcf7ea2681250a696a2d0936cb57ba0" dependencies = [ "cc", "regex", From 6f932375bf47ebc1d4da1e5445fdbc82ea53453f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 07:55:25 +0800 Subject: [PATCH 025/584] build(deps): bump serde_json from 1.0.79 to 1.0.81 (#2896) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.79 to 1.0.81. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.79...v1.0.81) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0567a4af111c0..11b2697392122 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -939,9 +939,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", From 64cf4c859b67c98042e2d66f26be0ce4a7afc6e0 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 27 Jun 2022 22:18:38 -0500 Subject: [PATCH 026/584] support Bazel languages (#2903) --- book/src/generated/lang-support.md | 1 + languages.toml | 12 +++++++++++- runtime/queries/starlark/highlights.scm | 1 + runtime/queries/starlark/injections.scm | 2 ++ runtime/queries/starlark/textobjects.scm | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/starlark/highlights.scm create mode 100644 runtime/queries/starlark/injections.scm create mode 100644 runtime/queries/starlark/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 7d0ac20202dd8..5ea18ae848458 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -85,6 +85,7 @@ | solidity | ✓ | | | `solc` | | sql | ✓ | | | | | sshclientconfig | ✓ | | | | +| starlark | ✓ | ✓ | | | | svelte | ✓ | | ✓ | `svelteserver` | | swift | ✓ | | | `sourcekit-lsp` | | tablegen | ✓ | ✓ | ✓ | | diff --git a/languages.toml b/languages.toml index aba5fd44c29b9..0e6cbb9cbe31a 100644 --- a/languages.toml +++ b/languages.toml @@ -461,7 +461,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-ruby", rev = "dfff6 name = "bash" scope = "source.bash" injection-regex = "bash" -file-types = ["sh", "bash", "zsh", ".bash_login", ".bash_logout", ".bash_profile", ".bashrc", ".profile", ".zshenv", ".zlogin", ".zlogout", ".zprofile", ".zshrc", "APKBUILD", "PKGBUILD", "eclass", "ebuild"] +file-types = ["sh", "bash", "zsh", ".bash_login", ".bash_logout", ".bash_profile", ".bashrc", ".profile", ".zshenv", ".zlogin", ".zlogout", ".zprofile", ".zshrc", "APKBUILD", "PKGBUILD", "eclass", "ebuild", "bazelrc"] shebangs = ["sh", "bash", "dash"] roots = [] comment-token = "#" @@ -1478,3 +1478,13 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "clojure" source = { git = "https://github.com/sogaiu/tree-sitter-clojure", rev = "e57c569ae332ca365da623712ae1f50f84daeae2" } + +[[language]] +name = "starlark" +scope = "source.starlark" +injection-regex = "(starlark|bzl|bazel)" +file-types = ["bzl", "bazel", "BUILD"] +roots = [] +comment-token = "#" +indent = { tab-width = 4, unit = " " } +grammar = "python" diff --git a/runtime/queries/starlark/highlights.scm b/runtime/queries/starlark/highlights.scm new file mode 100644 index 0000000000000..0b920cbf91caa --- /dev/null +++ b/runtime/queries/starlark/highlights.scm @@ -0,0 +1 @@ +; inherits: python diff --git a/runtime/queries/starlark/injections.scm b/runtime/queries/starlark/injections.scm new file mode 100644 index 0000000000000..321c90add3710 --- /dev/null +++ b/runtime/queries/starlark/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/starlark/textobjects.scm b/runtime/queries/starlark/textobjects.scm new file mode 100644 index 0000000000000..0b920cbf91caa --- /dev/null +++ b/runtime/queries/starlark/textobjects.scm @@ -0,0 +1 @@ +; inherits: python From 64de0b7288036c5ad759e6ce2dfdef9d40d267ad Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 27 Jun 2022 22:25:09 -0500 Subject: [PATCH 027/584] add docs for cursorline scopes (#2904) --- book/src/themes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/book/src/themes.md b/book/src/themes.md index ea52835d499ce..6c6393de031df 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -234,6 +234,8 @@ These scopes are used for theming the editor interface. | `ui.menu.scroll` | `fg` sets thumb color, `bg` sets track color of scrollbar | | `ui.selection` | For selections in the editing area | | `ui.selection.primary` | | +| `ui.cursorline.primary` | The line of the primary cursor | +| `ui.cursorline.secondary` | The lines of any other cursors | | `warning` | Diagnostics warning (gutter) | | `error` | Diagnostics error (gutter) | | `info` | Diagnostics info (gutter) | From 2963fdbed157b4b967dd371c9e436b88d71cd424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 18:25:08 +0900 Subject: [PATCH 028/584] build(deps): bump cc from 1.0.72 to 1.0.73 (#2897) Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.72 to 1.0.73. - [Release notes](https://github.com/alexcrichton/cc-rs/releases) - [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.72...1.0.73) --- updated-dependencies: - dependency-name: cc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11b2697392122..97aa3ea059b13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,9 +66,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" From 247ebd6689a5477eef73d69d54648ee8d66bd2c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 18:25:17 +0900 Subject: [PATCH 029/584] build(deps): bump indoc from 1.0.3 to 1.0.6 (#2898) Bumps [indoc](https://github.com/dtolnay/indoc) from 1.0.3 to 1.0.6. - [Release notes](https://github.com/dtolnay/indoc/releases) - [Commits](https://github.com/dtolnay/indoc/compare/1.0.3...1.0.6) --- updated-dependencies: - dependency-name: indoc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 13 ++----------- helix-term/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97aa3ea059b13..78e5cccdcd2ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -558,12 +558,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136" -dependencies = [ - "unindent", -] +checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e" [[package]] name = "instant" @@ -1280,12 +1277,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" -[[package]] -name = "unindent" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" - [[package]] name = "url" version = "2.2.2" diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index f1903f04b2c34..3da5a74ec2d46 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -77,5 +77,5 @@ helix-loader = { version = "0.6", path = "../helix-loader" } [dev-dependencies] smallvec = "1.8" -indoc = "1.0.3" +indoc = "1.0.6" tempfile = "3.3.0" From d900b8bb23d0c962b2b0321adeb607394dc1ad70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 19:36:28 +0900 Subject: [PATCH 030/584] build(deps): bump thiserror from 1.0.30 to 1.0.31 (#2899) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.30 to 1.0.31. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.30...1.0.31) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78e5cccdcd2ec..b8d78497097d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1108,18 +1108,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", From ac1d8fa505e926d981682317e4e3d289bec4eb49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 19:36:38 +0900 Subject: [PATCH 031/584] build(deps): bump smallvec from 1.8.0 to 1.8.1 (#2901) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.8.0 to 1.8.1. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.8.0...v1.8.1) --- updated-dependencies: - dependency-name: smallvec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8d78497097d5..6d94b6d7bdfb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1021,9 +1021,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" [[package]] name = "smartstring" From 030de46e6b9568f27fd89b1543d978b21da7464e Mon Sep 17 00:00:00 2001 From: PabloMansanet Date: Tue, 28 Jun 2022 21:30:27 +0900 Subject: [PATCH 032/584] Fix recursive macro crash and empty macro lockout (#2902) --- helix-term/src/commands.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 0a28444bdc09d..d1bec0cef6e88 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4655,8 +4655,6 @@ fn replay_macro(cx: &mut Context) { return; } - cx.editor.macro_replaying.push(reg); - let keys: Vec = if let Some([keys_str]) = cx.editor.registers.read(reg) { match helix_view::input::parse_macro(keys_str) { Ok(keys) => keys, @@ -4670,6 +4668,10 @@ fn replay_macro(cx: &mut Context) { return; }; + // Once the macro has been fully validated, it's marked as being under replay + // to ensure we don't fall into infinite recursion. + cx.editor.macro_replaying.push(reg); + let count = cx.count(); cx.callback = Some(Box::new(move |compositor, cx| { for _ in 0..count { @@ -4677,7 +4679,9 @@ fn replay_macro(cx: &mut Context) { compositor.handle_event(crossterm::event::Event::Key(key.into()), cx); } } + // The macro under replay is cleared at the end of the callback, not in the + // macro replay context, or it will not correctly protect the user from + // replaying recursively. + cx.editor.macro_replaying.pop(); })); - - cx.editor.macro_replaying.pop(); } From 07e7a13a9e6b0a6c0bb456504b62572ec6be9eb2 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Tue, 28 Jun 2022 10:59:10 -0400 Subject: [PATCH 033/584] fixes background reset (#2900) * fixes background reset * moves creation of default style out of loop * patches with background_style * removes commented code --- helix-term/src/ui/editor.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 32f70c8b1fad3..948803eb0a837 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -668,13 +668,16 @@ impl EditorView { let hint = theme.get("hint"); let mut lines = Vec::new(); + let background_style = theme.get("ui.background"); for diagnostic in diagnostics { - let style = Style::reset().patch(match diagnostic.severity { - Some(Severity::Error) => error, - Some(Severity::Warning) | None => warning, - Some(Severity::Info) => info, - Some(Severity::Hint) => hint, - }); + let style = Style::reset() + .patch(background_style) + .patch(match diagnostic.severity { + Some(Severity::Error) => error, + Some(Severity::Warning) | None => warning, + Some(Severity::Info) => info, + Some(Severity::Hint) => hint, + }); let text = Text::styled(&diagnostic.message, style); lines.extend(text.lines); } From bf1db737d4ab9030e56283c45bba525ef81e1daa Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 29 Jun 2022 03:53:56 -0500 Subject: [PATCH 034/584] nix: update nixCargoIntegration (#2907) This fixes the aarch64-darwin build - the newer revision uses the cCompiler override to compile tree-sitter with clang instead of gcc (which fails). --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index df059e4765727..4f0841a7fc6da 100644 --- a/flake.lock +++ b/flake.lock @@ -19,11 +19,11 @@ "devshell": { "flake": false, "locked": { - "lastModified": 1654858401, - "narHash": "sha256-53bw34DtVJ2bnF6WEwy6Tym+qY0pNEiEwARUlvmTZjs=", + "lastModified": 1655976588, + "narHash": "sha256-VreHyH6ITkf/1EX/8h15UqhddJnUleb0HgbC3gMkAEQ=", "owner": "numtide", "repo": "devshell", - "rev": "f55e05c6d3bbe9acc7363bc8fc739518b2f02976", + "rev": "899ca4629020592a13a46783587f6e674179d1db", "type": "github" }, "original": { @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1655826285, - "narHash": "sha256-dyrNTVBefSZWKdFNnAW+zUkO5bVo1colvLje4l1XXwA=", + "lastModified": 1655975833, + "narHash": "sha256-g8sdfuglIZ24oWVbntVzniNTJW+Z3n9DNL9w9Tt+UCE=", "owner": "nix-community", "repo": "dream2nix", - "rev": "f23add2b9c313c63dea5cff71523a850d29ffddb", + "rev": "4e75e665ec3a1cddae5266bed0dd72fce0b74a23", "type": "github" }, "original": { @@ -113,11 +113,11 @@ ] }, "locked": { - "lastModified": 1655826649, - "narHash": "sha256-C4/7CdB/mzuD9ayWvEA3Jcog6INCq+oUJZxUsIP/GvE=", + "lastModified": 1656453541, + "narHash": "sha256-ZCPVnS6zJOZJvIlwU3rKR8MBVm6A3F4/0mA7G1lQ3D0=", "owner": "yusdacra", "repo": "nix-cargo-integration", - "rev": "5cf1685c021c47631a2fb16533c00c8d68afd09e", + "rev": "9eb74345b30cd2e536d9dac9d4435d3c475605c7", "type": "github" }, "original": { From 6ac6080969dcd344597995c4b98a43406658aa8a Mon Sep 17 00:00:00 2001 From: Stuart Hinson Date: Wed, 29 Jun 2022 10:08:05 -0400 Subject: [PATCH 035/584] primary cursorline for Dracula theme (#2915) --- runtime/themes/dracula.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/themes/dracula.toml b/runtime/themes/dracula.toml index 72b37d02741cc..6cc037b8ebc70 100644 --- a/runtime/themes/dracula.toml +++ b/runtime/themes/dracula.toml @@ -23,6 +23,7 @@ "ui.cursor" = { fg = "background", bg = "orange", modifiers = ["dim"] } "ui.cursor.match" = { fg = "green", modifiers = ["underlined"] } "ui.cursor.primary" = { fg = "background", bg = "cyan", modifier = ["dim"] } +"ui.cursorline.primary" = { bg = "background_dark" } "ui.help" = { fg = "foreground", bg = "background_dark" } "ui.linenr" = { fg = "comment" } "ui.linenr.selected" = { fg = "foreground" } From 15ac1142cf28196fc1b7749f5eae0c04186305d9 Mon Sep 17 00:00:00 2001 From: Ben Lee-Cohen Date: Wed, 29 Jun 2022 10:13:49 -0400 Subject: [PATCH 036/584] Adding a cursorline for the Nord theme (#2916) --- runtime/themes/nord.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/themes/nord.toml b/runtime/themes/nord.toml index 3b994bb59e507..f7ef079b0c4df 100644 --- a/runtime/themes/nord.toml +++ b/runtime/themes/nord.toml @@ -1,6 +1,7 @@ # Author : RayGervais "ui.linenr.selected" = { fg = "nord4" } +"ui.cursorline.primary" = { bg = "nord1" } "ui.text.focus" = { fg = "nord8", modifiers= ["bold"] } "ui.menu" = { fg = "nord6", bg = "#232d38" } "ui.menu.selected" = { fg = "nord8", bg = "nord2" } From 94fc41a41920fc705f01637e7902f06a1c32d998 Mon Sep 17 00:00:00 2001 From: Jens Getreu Date: Wed, 29 Jun 2022 21:14:16 +0200 Subject: [PATCH 037/584] Add cursorline to Autumn theme (#2918) Co-authored-by: Jens Getreu --- runtime/themes/autumn.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtime/themes/autumn.toml b/runtime/themes/autumn.toml index 68e41f5af0797..c4e0cfd62ce12 100644 --- a/runtime/themes/autumn.toml +++ b/runtime/themes/autumn.toml @@ -13,13 +13,15 @@ "ui.linenr" = { fg = "my_gray4", bg = "my_gray2" } "ui.popup" = { bg = "my_gray2" } "ui.window" = { fg = "my_gray4", bg = "my_gray2" } -"ui.linenr.selected" = { fg = "my_gray6", bg = "my_gray2", modifiers = ["bold"]} +"ui.linenr.selected" = { fg = "my_gray6", bg = "my_gray1"} "ui.selection" = { bg = "my_gray3" } "comment" = { fg = "my_gray4", modifiers = ["italic"] } "ui.statusline" = { fg = "my_gray6", bg = "my_gray2" } "ui.statusline.inactive" = { fg = 'my_gray4', bg = 'my_gray2' } "ui.cursor" = { fg = "my_gray5", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "my_white", modifiers = ["reversed"] } +"ui.cursorline.primary" = { bg = "my_black" } +"ui.cursorline.secondary" = { bg = "my_black" } "ui.text" = "my_white" "operator" = "my_white" "ui.text.focus" = "my_white" @@ -64,6 +66,7 @@ "error" = "my_red" [palette] +my_black = "#242424" # Cursorline my_gray0 = "#292929" # Default Background my_gray1 = "#2e2e2e" # Ruler my_gray2 = "#3a3a3a" # Lighter Background (Used for status bars, line number and folding marks) From ed89f8897eab84bf7614a718d5d1e3ec5c57086c Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Thu, 30 Jun 2022 11:16:18 +0200 Subject: [PATCH 038/584] Add workspace and document diagnostics picker (#2013) * Add workspace and document diagnostics picker fixes #1891 * Fix some of @archseer's annotations * Add From<&Spans> impl for String * More descriptive parameter names. * Adding From> impls for Span and Spans * Add new keymap entries to docs * Avoid some clones * Fix api change * Update helix-term/src/application.rs Co-authored-by: Bjorn Ove Hay Andersen * Fix a clippy hint * Sort diagnostics first by URL and then by severity. * Sort diagnostics first by URL and then by severity. * Ignore missing lsp severity entries * Add truncated filepath * Typo * Strip cwd from paths and use url-path without schema * Make tests a doctest * Better variable names Co-authored-by: Falco Hirschenberger Co-authored-by: Bjorn Ove Hay Andersen --- book/src/keymap.md | 2 + helix-core/src/path.rs | 51 ++++++++++++ helix-term/src/application.rs | 28 +++++-- helix-term/src/commands.rs | 12 +-- helix-term/src/commands/lsp.rs | 135 ++++++++++++++++++++++++++++++- helix-term/src/keymap/default.rs | 2 + helix-term/src/ui/mod.rs | 4 +- helix-term/src/ui/picker.rs | 61 +++++++------- helix-tui/src/text.rs | 23 +++++- helix-tui/src/widgets/block.rs | 2 +- helix-view/src/editor.rs | 3 + xtask/src/main.rs | 2 +- 12 files changed, 273 insertions(+), 52 deletions(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index e6abb9c928ca3..b979cfd89491c 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -241,6 +241,8 @@ This layer is a kludge of mappings, mostly pickers. | `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` | | `s` | Open document symbol picker (**LSP**) | `symbol_picker` | | `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` | +| `g` | Open document diagnosics picker (**LSP**) | `diagnostics_picker` | +| `G` | Open workspace diagnostics picker (**LSP**) | `workspace_diagnosics_picker` | `r` | Rename symbol (**LSP**) | `rename_symbol` | | `a` | Apply code action (**LSP**) | `code_action` | | `'` | Open last fuzzy picker | `last_picker` | diff --git a/helix-core/src/path.rs b/helix-core/src/path.rs index cb50e136c23e0..d59a6baad604d 100644 --- a/helix-core/src/path.rs +++ b/helix-core/src/path.rs @@ -90,3 +90,54 @@ pub fn get_relative_path(path: &Path) -> PathBuf { }; fold_home_dir(path) } + +/// Returns a truncated filepath where the basepart of the path is reduced to the first +/// char of the folder and the whole filename appended. +/// +/// Also strip the current working directory from the beginning of the path. +/// Note that this function does not check if the truncated path is unambiguous. +/// +/// ``` +/// use helix_core::path::get_truncated_path; +/// use std::path::Path; +/// +/// assert_eq!( +/// get_truncated_path("/home/cnorris/documents/jokes.txt").as_path(), +/// Path::new("/h/c/d/jokes.txt") +/// ); +/// assert_eq!( +/// get_truncated_path("jokes.txt").as_path(), +/// Path::new("jokes.txt") +/// ); +/// assert_eq!( +/// get_truncated_path("/jokes.txt").as_path(), +/// Path::new("/jokes.txt") +/// ); +/// assert_eq!( +/// get_truncated_path("/h/c/d/jokes.txt").as_path(), +/// Path::new("/h/c/d/jokes.txt") +/// ); +/// assert_eq!(get_truncated_path("").as_path(), Path::new("")); +/// ``` +/// +pub fn get_truncated_path>(path: P) -> PathBuf { + let cwd = std::env::current_dir().unwrap_or_default(); + let path = path + .as_ref() + .strip_prefix(cwd) + .unwrap_or_else(|_| path.as_ref()); + let file = path.file_name().unwrap_or_default(); + let base = path.parent().unwrap_or_else(|| Path::new("")); + let mut ret = PathBuf::new(); + for d in base { + ret.push( + d.to_string_lossy() + .chars() + .next() + .unwrap_or_default() + .to_string(), + ); + } + ret.push(file); + ret +} diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 48e9c2758737c..23f4610f6ad55 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -495,7 +495,7 @@ impl Application { )); } } - Notification::PublishDiagnostics(params) => { + Notification::PublishDiagnostics(mut params) => { let path = params.uri.to_file_path().unwrap(); let doc = self.editor.document_by_path_mut(&path); @@ -505,12 +505,9 @@ impl Application { let diagnostics = params .diagnostics - .into_iter() + .iter() .filter_map(|diagnostic| { - use helix_core::{ - diagnostic::{Range, Severity::*}, - Diagnostic, - }; + use helix_core::diagnostic::{Diagnostic, Range, Severity::*}; use lsp::DiagnosticSeverity; let language_server = doc.language_server().unwrap(); @@ -561,7 +558,7 @@ impl Application { Some(Diagnostic { range: Range { start, end }, line: diagnostic.range.start.line as usize, - message: diagnostic.message, + message: diagnostic.message.clone(), severity, // code // source @@ -571,6 +568,23 @@ impl Application { doc.set_diagnostics(diagnostics); } + + // Sort diagnostics first by URL and then by severity. + // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order + params.diagnostics.sort_unstable_by(|a, b| { + if let (Some(a), Some(b)) = (a.severity, b.severity) { + a.partial_cmp(&b).unwrap() + } else { + std::cmp::Ordering::Equal + } + }); + + // Insert the original lsp::Diagnostics here because we may have no open document + // for diagnosic message and so we can't calculate the exact position. + // When using them later in the diagnostics picker, we calculate them on-demand. + self.editor + .diagnostics + .insert(params.uri, params.diagnostics); } Notification::ShowMessage(params) => { log::warn!("unhandled window/showMessage: {:?}", params); diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index d1bec0cef6e88..bc8e65302f9bc 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4,6 +4,7 @@ pub(crate) mod typed; pub use dap::*; pub use lsp::*; +use tui::text::Spans; pub use typed::*; use helix_core::{ @@ -265,6 +266,8 @@ impl MappableCommand { symbol_picker, "Open symbol picker", select_references_to_symbol_under_cursor, "Select symbol references", workspace_symbol_picker, "Open workspace symbol picker", + diagnostics_picker, "Open diagnostic picker", + workspace_diagnostics_picker, "Open workspace diagnostic picker", last_picker, "Open last picker", prepend_to_line, "Insert at start of line", append_to_line, "Insert at end of line", @@ -2170,7 +2173,7 @@ fn buffer_picker(cx: &mut Context) { } impl BufferMeta { - fn format(&self) -> Cow { + fn format(&self) -> Spans { let path = self .path .as_deref() @@ -2193,7 +2196,7 @@ fn buffer_picker(cx: &mut Context) { } else { format!(" ({})", flags.join("")) }; - Cow::Owned(format!("{} {}{}", self.id, path, flag)) + format!("{} {}{}", self.id, path, flag).into() } } @@ -2260,10 +2263,9 @@ pub fn command_palette(cx: &mut Context) { let picker = Picker::new( commands, move |command| match command { - MappableCommand::Typable { doc, name, .. } => match keymap.get(name as &String) - { + MappableCommand::Typable { doc, name, .. } => match keymap.get(name) { Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), - None => doc.into(), + None => doc.as_str().into(), }, MappableCommand::Static { doc, name, .. } => match keymap.get(*name) { Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index c1cdb164219a4..d11c44cd42878 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -1,20 +1,25 @@ use helix_lsp::{ - block_on, lsp, + block_on, + lsp::{self, DiagnosticSeverity, NumberOrString}, util::{diagnostic_to_lsp_diagnostic, lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range}, OffsetEncoding, }; +use tui::text::{Span, Spans}; use super::{align_view, push_jump, Align, Context, Editor}; -use helix_core::Selection; -use helix_view::editor::Action; +use helix_core::{path, Selection}; +use helix_view::{ + editor::Action, + theme::{Modifier, Style}, +}; use crate::{ compositor::{self, Compositor}, ui::{self, overlay::overlayed, FileLocation, FilePicker, Popup, PromptEvent}, }; -use std::borrow::Cow; +use std::{borrow::Cow, collections::BTreeMap}; /// Gets the language server that is attached to a document, and /// if it's not active displays a status message. Using this macro @@ -145,6 +150,97 @@ fn sym_picker( .truncate_start(false) } +fn diag_picker( + cx: &Context, + diagnostics: BTreeMap>, + current_path: Option, + offset_encoding: OffsetEncoding, +) -> FilePicker<(lsp::Url, lsp::Diagnostic)> { + // TODO: drop current_path comparison and instead use workspace: bool flag? + + // flatten the map to a vec of (url, diag) pairs + let mut flat_diag = Vec::new(); + for (url, diags) in diagnostics { + flat_diag.reserve(diags.len()); + for diag in diags { + flat_diag.push((url.clone(), diag)); + } + } + + let hint = cx.editor.theme.get("hint"); + let info = cx.editor.theme.get("info"); + let warning = cx.editor.theme.get("warning"); + let error = cx.editor.theme.get("error"); + + FilePicker::new( + flat_diag, + move |(url, diag)| { + let mut style = diag + .severity + .map(|s| match s { + DiagnosticSeverity::HINT => hint, + DiagnosticSeverity::INFORMATION => info, + DiagnosticSeverity::WARNING => warning, + DiagnosticSeverity::ERROR => error, + _ => Style::default(), + }) + .unwrap_or_default(); + + // remove background as it is distracting in the picker list + style.bg = None; + + let code = diag + .code + .as_ref() + .map(|c| match c { + NumberOrString::Number(n) => n.to_string(), + NumberOrString::String(s) => s.to_string(), + }) + .unwrap_or_default(); + + let truncated_path = path::get_truncated_path(url.path()) + .to_string_lossy() + .into_owned(); + + Spans::from(vec![ + Span::styled( + diag.source.clone().unwrap_or_default(), + style.add_modifier(Modifier::BOLD), + ), + Span::raw(": "), + Span::styled(truncated_path, style), + Span::raw(" - "), + Span::styled(code, style.add_modifier(Modifier::BOLD)), + Span::raw(": "), + Span::styled(&diag.message, style), + ]) + }, + move |cx, (url, diag), action| { + if current_path.as_ref() == Some(url) { + let (view, doc) = current!(cx.editor); + push_jump(view, doc); + } else { + let path = url.to_file_path().unwrap(); + cx.editor.open(&path, action).expect("editor.open failed"); + } + + let (view, doc) = current!(cx.editor); + + if let Some(range) = lsp_range_to_range(doc.text(), diag.range, offset_encoding) { + // we flip the range so that the cursor sits on the start of the symbol + // (for example start of the function). + doc.set_selection(view.id, Selection::single(range.head, range.anchor)); + align_view(doc, view, Align::Center); + } + }, + move |_editor, (url, diag)| { + let location = lsp::Location::new(url.clone(), diag.range); + Some(location_to_file_location(&location)) + }, + ) + .truncate_start(false) +} + pub fn symbol_picker(cx: &mut Context) { fn nested_to_flat( list: &mut Vec, @@ -215,6 +311,37 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ) } +pub fn diagnostics_picker(cx: &mut Context) { + let doc = doc!(cx.editor); + let language_server = language_server!(cx.editor, doc); + if let Some(current_url) = doc.url() { + let offset_encoding = language_server.offset_encoding(); + let diagnostics = cx + .editor + .diagnostics + .get(¤t_url) + .cloned() + .unwrap_or_default(); + let picker = diag_picker( + cx, + [(current_url.clone(), diagnostics)].into(), + Some(current_url), + offset_encoding, + ); + cx.push_layer(Box::new(overlayed(picker))); + } +} + +pub fn workspace_diagnostics_picker(cx: &mut Context) { + let doc = doc!(cx.editor); + let language_server = language_server!(cx.editor, doc); + let current_url = doc.url(); + let offset_encoding = language_server.offset_encoding(); + let diagnostics = cx.editor.diagnostics.clone(); + let picker = diag_picker(cx, diagnostics, current_url, offset_encoding); + cx.push_layer(Box::new(overlayed(picker))); +} + impl ui::menu::Item for lsp::CodeActionOrCommand { fn label(&self) -> &str { match self { diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index e5bb0482d0a31..29b0b670690ce 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -207,6 +207,8 @@ pub fn default() -> HashMap { "b" => buffer_picker, "s" => symbol_picker, "S" => workspace_symbol_picker, + "g" => diagnostics_picker, + "G" => workspace_diagnostics_picker, "a" => code_action, "'" => last_picker, "d" => { "Debug (experimental)" sticky=true diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 47a68a18fa558..c1e5c98897ab1 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -23,6 +23,8 @@ pub use text::Text; use helix_core::regex::Regex; use helix_core::regex::RegexBuilder; use helix_view::{Document, Editor, View}; +use tui; +use tui::text::Spans; use std::path::PathBuf; @@ -172,7 +174,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi files, move |path: &PathBuf| { // format_fn - path.strip_prefix(&root).unwrap_or(path).to_string_lossy() + Spans::from(path.strip_prefix(&root).unwrap_or(path).to_string_lossy()) }, move |cx, path: &PathBuf, action| { if let Err(e) = cx.editor.open(path, action) { diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index ebff98274df30..1581b0a15c3e4 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -6,6 +6,7 @@ use crate::{ use crossterm::event::Event; use tui::{ buffer::Buffer as Surface, + text::Spans, widgets::{Block, BorderType, Borders}, }; @@ -15,7 +16,6 @@ use tui::widgets::Widget; use std::time::Instant; use std::{ - borrow::Cow, cmp::Reverse, collections::HashMap, io::Read, @@ -87,7 +87,7 @@ impl Preview<'_, '_> { impl FilePicker { pub fn new( options: Vec, - format_fn: impl Fn(&T) -> Cow + 'static, + format_fn: impl Fn(&T) -> Spans + 'static, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, preview_fn: impl Fn(&Editor, &T) -> Option + 'static, ) -> Self { @@ -299,14 +299,14 @@ pub struct Picker { /// Whether to truncate the start (default true) pub truncate_start: bool, - format_fn: Box Cow>, + format_fn: Box Spans>, callback_fn: Box, } impl Picker { pub fn new( options: Vec, - format_fn: impl Fn(&T) -> Cow + 'static, + format_fn: impl Fn(&T) -> Spans + 'static, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, ) -> Self { let prompt = Prompt::new( @@ -372,9 +372,8 @@ impl Picker { self.matches.retain_mut(|(index, score)| { let option = &self.options[*index]; // TODO: maybe using format_fn isn't the best idea here - let text = (self.format_fn)(option); - - match self.matcher.fuzzy_match(&text, pattern) { + let line: String = (self.format_fn)(option).into(); + match self.matcher.fuzzy_match(&line, pattern) { Some(s) => { // Update the score *score = s; @@ -401,10 +400,10 @@ impl Picker { } // TODO: maybe using format_fn isn't the best idea here - let text = (self.format_fn)(option); + let line: String = (self.format_fn)(option).into(); self.matcher - .fuzzy_match(&text, pattern) + .fuzzy_match(&line, pattern) .map(|score| (index, score)) }), ); @@ -611,30 +610,34 @@ impl Component for Picker { surface.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected); } - let formatted = (self.format_fn)(option); - + let spans = (self.format_fn)(option); let (_score, highlights) = self .matcher - .fuzzy_indices(&formatted, self.prompt.line()) + .fuzzy_indices(&String::from(&spans), self.prompt.line()) .unwrap_or_default(); - surface.set_string_truncated( - inner.x, - inner.y + i as u16, - &formatted, - inner.width as usize, - |idx| { - if highlights.contains(&idx) { - highlighted - } else if is_active { - selected - } else { - text_style - } - }, - true, - self.truncate_start, - ); + spans.0.into_iter().fold(inner, |pos, span| { + let new_x = surface + .set_string_truncated( + pos.x, + pos.y + i as u16, + &span.content, + pos.width as usize, + |idx| { + if highlights.contains(&idx) { + highlighted.patch(span.style) + } else if is_active { + selected.patch(span.style) + } else { + text_style.patch(span.style) + } + }, + true, + self.truncate_start, + ) + .0; + pos.clip_left(new_x - pos.x) + }); } } diff --git a/helix-tui/src/text.rs b/helix-tui/src/text.rs index 8a974ddba465b..b4278c864b307 100644 --- a/helix-tui/src/text.rs +++ b/helix-tui/src/text.rs @@ -194,6 +194,12 @@ impl<'a> From<&'a str> for Span<'a> { } } +impl<'a> From> for Span<'a> { + fn from(s: Cow<'a, str>) -> Span<'a> { + Span::raw(s) + } +} + /// A string composed of clusters of graphemes, each with their own style. #[derive(Debug, Default, Clone, PartialEq)] pub struct Spans<'a>(pub Vec>); @@ -229,6 +235,12 @@ impl<'a> From<&'a str> for Spans<'a> { } } +impl<'a> From> for Spans<'a> { + fn from(s: Cow<'a, str>) -> Spans<'a> { + Spans(vec![Span::raw(s)]) + } +} + impl<'a> From>> for Spans<'a> { fn from(spans: Vec>) -> Spans<'a> { Spans(spans) @@ -243,10 +255,13 @@ impl<'a> From> for Spans<'a> { impl<'a> From> for String { fn from(line: Spans<'a>) -> String { - line.0.iter().fold(String::new(), |mut acc, s| { - acc.push_str(s.content.as_ref()); - acc - }) + line.0.iter().map(|s| &*s.content).collect() + } +} + +impl<'a> From<&Spans<'a>> for String { + fn from(line: &Spans<'a>) -> String { + line.0.iter().map(|s| &*s.content).collect() } } diff --git a/helix-tui/src/widgets/block.rs b/helix-tui/src/widgets/block.rs index 3c05a2a3c8aa6..bd025a3167ff2 100644 --- a/helix-tui/src/widgets/block.rs +++ b/helix-tui/src/widgets/block.rs @@ -77,7 +77,7 @@ impl<'a> Block<'a> { )] pub fn title_style(mut self, style: Style) -> Block<'a> { if let Some(t) = self.title { - let title = String::from(t); + let title = String::from(&t); self.title = Some(Spans::from(Span::styled(title, style))); } self diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index a9741a33ff1b7..c160dd3771416 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -39,6 +39,7 @@ use helix_core::{ Change, }; use helix_dap as dap; +use helix_lsp::lsp; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; @@ -462,6 +463,7 @@ pub struct Editor { pub macro_replaying: Vec, pub theme: Theme, pub language_servers: helix_lsp::Registry, + pub diagnostics: BTreeMap>, pub debugger: Option, pub debugger_events: SelectAll>, @@ -533,6 +535,7 @@ impl Editor { macro_replaying: Vec::new(), theme: theme_loader.default(), language_servers, + diagnostics: BTreeMap::new(), debugger: None, debugger_events: SelectAll::new(), breakpoints: HashMap::new(), diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a4c69d701166e..f66fb4f4237a5 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -106,7 +106,7 @@ pub mod md_gen { .collect::>() .join(", "); - let doc = cmd.doc.replace("\n", "
"); + let doc = cmd.doc.replace('\n', "
"); md.push_str(&md_table_row(&[names.to_owned(), doc.to_owned()])); } From d06800f1dd47315f5738c529d40d1e0952ee2115 Mon Sep 17 00:00:00 2001 From: Mathspy Date: Thu, 30 Jun 2022 05:26:00 -0400 Subject: [PATCH 039/584] Add mode specific styles (#2676) * Add mode specific styles In similar vein to neovim's lualine and similar statusline packages this allows helix users to style their mode based on which mode it is thus making each mode more visually distinct at a glance * Add an example based on rosepine * Add editor.colors-mode config * Document statusline mode styles --- book/src/configuration.md | 1 + book/src/themes.md | 7 +++++-- helix-term/src/ui/editor.rs | 21 ++++++++++++++------- helix-view/src/editor.rs | 3 +++ runtime/themes/rose_pine.toml | 3 +++ 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index af85379f8ff39..1cc8602adac11 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -46,6 +46,7 @@ hidden = false | `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` | | `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file. | `[]` | +| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` | ### `[editor.lsp]` Section diff --git a/book/src/themes.md b/book/src/themes.md index 6c6393de031df..06f920d3ccb59 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -219,6 +219,9 @@ These scopes are used for theming the editor interface. | `ui.linenr.selected` | Line number for the line the cursor is on | | `ui.statusline` | Statusline | | `ui.statusline.inactive` | Statusline (unfocused document) | +| `ui.statusline.normal` | Statusline mode during normal mode ([only if `editor.color-modes` is enabled][editor-section]) | +| `ui.statusline.insert` | Statusline mode during insert mode ([only if `editor.color-modes` is enabled][editor-section]) | +| `ui.statusline.select` | Statusline mode during select mode ([only if `editor.color-modes` is enabled][editor-section]) | | `ui.popup` | Documentation popups (e.g space-k) | | `ui.popup.info` | Prompt for multiple key options | | `ui.window` | Border lines separating splits | @@ -226,7 +229,7 @@ These scopes are used for theming the editor interface. | `ui.text` | Command prompts, popup text, etc. | | `ui.text.focus` | | | `ui.text.info` | The key: command text in `ui.popup.info` boxes | -| `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][rulers-config])| +| `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][editor-section])| | `ui.virtual.whitespace` | Visible white-space characters | | `ui.virtual.indent-guide` | Vertical indent width guides | | `ui.menu` | Code and command completion menus | @@ -246,4 +249,4 @@ These scopes are used for theming the editor interface. | `diagnostic.warning` | Diagnostics warning (editing area) | | `diagnostic.error` | Diagnostics error (editing area) | -[rulers-config]: ./configuration.md#editor-section +[editor-section]: ./configuration.md#editor-section diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 948803eb0a837..a7c67a219b33f 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -161,7 +161,7 @@ impl EditorView { .area .clip_top(view.area.height.saturating_sub(1)) .clip_bottom(1); // -1 from bottom to remove commandline - self.render_statusline(doc, view, statusline_area, surface, theme, is_focused); + self.render_statusline(editor, doc, view, statusline_area, surface, is_focused); } pub fn render_rulers( @@ -732,11 +732,11 @@ impl EditorView { pub fn render_statusline( &self, + editor: &Editor, doc: &Document, view: &View, viewport: Rect, surface: &mut Surface, - theme: &Theme, is_focused: bool, ) { use tui::text::{Span, Spans}; @@ -745,10 +745,11 @@ impl EditorView { // Left side of the status line. //------------------------------- - let mode = match doc.mode() { - Mode::Insert => "INS", - Mode::Select => "SEL", - Mode::Normal => "NOR", + let theme = &editor.theme; + let (mode, mode_style) = match doc.mode() { + Mode::Insert => (" INS ", theme.get("ui.statusline.insert")), + Mode::Select => (" SEL ", theme.get("ui.statusline.select")), + Mode::Normal => (" NOR ", theme.get("ui.statusline.normal")), }; let progress = doc .language_server() @@ -767,7 +768,13 @@ impl EditorView { // statusline surface.set_style(viewport.with_height(1), base_style); if is_focused { - surface.set_string(viewport.x + 1, viewport.y, mode, base_style); + let color_modes = editor.config().color_modes; + surface.set_string( + viewport.x, + viewport.y, + mode, + if color_modes { mode_style } else { base_style }, + ); } surface.set_string(viewport.x + 5, viewport.y, progress, base_style); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index c160dd3771416..1ed27e996eafc 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -161,6 +161,8 @@ pub struct Config { pub whitespace: WhitespaceConfig, /// Vertical indent width guides. pub indent_guides: IndentGuidesConfig, + /// Whether to color modes with different colors. Defaults to `false`. + pub color_modes: bool, } #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] @@ -414,6 +416,7 @@ impl Default for Config { rulers: Vec::new(), whitespace: WhitespaceConfig::default(), indent_guides: IndentGuidesConfig::default(), + color_modes: false, } } } diff --git a/runtime/themes/rose_pine.toml b/runtime/themes/rose_pine.toml index 09b1e25c9ab3d..fd53abd58cb9f 100644 --- a/runtime/themes/rose_pine.toml +++ b/runtime/themes/rose_pine.toml @@ -9,6 +9,9 @@ "ui.selection" = { bg = "highlight" } "comment" = "subtle" "ui.statusline" = {fg = "foam", bg = "surface" } +"ui.statusline.insert" = {fg = "base", bg = "foam", modifiers = ["bold"]} +"ui.statusline.normal" = {fg = "base", bg = "rose", modifiers = ["bold"]} +"ui.statusline.select" = {fg = "base", bg = "iris", modifiers = ["bold"]} "ui.statusline.inactive" = { fg = "iris", bg = "surface" } "ui.cursor" = { fg = "rose", modifiers = ["reversed"] } "ui.text" = { fg = "text" } From f2768da1f6312efe6f87f80a6541da5225c2fc7c Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Thu, 30 Jun 2022 17:52:31 -0400 Subject: [PATCH 040/584] add mode colors to solarized (#2926) --- runtime/themes/solarized_dark.toml | 6 +++++- runtime/themes/solarized_light.toml | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/runtime/themes/solarized_dark.toml b/runtime/themes/solarized_dark.toml index d8126f6ea6765..002e99bc701d7 100644 --- a/runtime/themes/solarized_dark.toml +++ b/runtime/themes/solarized_dark.toml @@ -48,6 +48,10 @@ # 状态栏 "ui.statusline" = { fg = "base03", bg = "base0" } +"ui.statusline.normal" = { bg = "blue" } +"ui.statusline.insert" = { bg = "green" } +"ui.statusline.select" = { bg = "yellow" } + # 非活动状态栏 "ui.statusline.inactive" = { fg = "base1", bg = "base01" } @@ -55,7 +59,7 @@ "ui.popup" = { bg = "base02" } # 影响 补全选中 cmd弹出信息选中 "ui.menu.selected" = { fg = "base02", bg = "base2"} -"ui.menu" = { fg = "base1" } +"ui.menu" = { fg = "base0", bg = "base02" } # ?? "ui.window" = { fg = "base3" } # 命令行 补全的帮助信息 diff --git a/runtime/themes/solarized_light.toml b/runtime/themes/solarized_light.toml index cd1028bda7976..fa58cc8cfc580 100644 --- a/runtime/themes/solarized_light.toml +++ b/runtime/themes/solarized_light.toml @@ -52,6 +52,10 @@ # 状态栏 # status bar "ui.statusline" = { fg = "base03", bg = "base0" } +"ui.statusline.normal" = { bg = "blue" } +"ui.statusline.insert" = { bg = "green" } +"ui.statusline.select" = { bg = "yellow" } + # 非活动状态栏 # inactive status bar "ui.statusline.inactive" = { fg = "base1", bg = "base01" } From 26501afe13bcb513a5dec764daccdcfd166a7114 Mon Sep 17 00:00:00 2001 From: Sora Date: Fri, 1 Jul 2022 00:14:55 +0200 Subject: [PATCH 041/584] Update cursorline for tokyonight + tokyonight_storm (#2927) Co-authored-by: s0LA1337 --- runtime/themes/tokyonight.toml | 1 + runtime/themes/tokyonight_storm.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/runtime/themes/tokyonight.toml b/runtime/themes/tokyonight.toml index 14cc40e2d9d02..4f1ea1cfe26fa 100644 --- a/runtime/themes/tokyonight.toml +++ b/runtime/themes/tokyonight.toml @@ -30,6 +30,7 @@ "ui.cursor" = { modifiers = ["reversed"] } "ui.cursor.match" = { fg = "orange", modifiers = ["bold"] } "ui.cursor.primary" = { modifiers = ["reversed"] } +"ui.cursorline.primary" = { bg = "background_menu" } "ui.help" = { fg = "foreground", bg = "background_menu" } "ui.linenr" = { fg = "foreground_gutter" } "ui.linenr.selected" = { fg = "foreground" } diff --git a/runtime/themes/tokyonight_storm.toml b/runtime/themes/tokyonight_storm.toml index 6c6fd9c8dfbd9..c47ac54bad26c 100644 --- a/runtime/themes/tokyonight_storm.toml +++ b/runtime/themes/tokyonight_storm.toml @@ -30,6 +30,7 @@ "ui.cursor" = { modifiers = ["reversed"] } "ui.cursor.match" = { fg = "orange", modifiers = ["bold"] } "ui.cursor.primary" = { modifiers = ["reversed"] } +"ui.cursorline.primary" = { bg = "background_menu" } "ui.help" = { fg = "foreground", bg = "background_menu" } "ui.linenr" = { fg = "foreground_gutter" } "ui.linenr.selected" = { fg = "foreground" } From d523280e8533e8d57eda0b9fbc0f076b07002a2b Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 14 Jun 2022 09:39:45 -0500 Subject: [PATCH 042/584] erlang: highlight nullary macros as constants --- runtime/queries/erlang/highlights.scm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index 0cb60ca999778..94f1e9f5a0247 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -38,8 +38,8 @@ (arguments . [ - (atom) @keyword.directive - (variable) @keyword.directive + (atom) @constant + (variable) @constant (call function: [(variable) (atom)] @keyword.directive) @@ -99,6 +99,11 @@ (comment) @comment ; Macros +(macro + "?"+ @constant + name: (_) @constant + !arguments) + (macro "?"+ @keyword.directive name: (_) @keyword.directive) From bd527c84e64f8a30bb1ae8c4dd634d6deba20825 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 15 Jun 2022 15:25:11 -0500 Subject: [PATCH 043/584] erlang: highlight unary '#' as punctuation.bracket The '#' character may either be interpreted as a map when used like so: %% Example 1 #{a => b} Or as an operator which updates an existing map when the left-hand side is an expression: %% Example 2 MyMap#{a => b} This commit changes the highlight to `punctuation.bracket` when used as a character in a literal map (example 1) and keeps the `operator` highlight when used for updating (example 2). --- runtime/queries/erlang/highlights.scm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index 94f1e9f5a0247..ce84697b572bc 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -92,7 +92,7 @@ (binary_operator operator: _ @operator) (unary_operator operator: _ @operator) -["/" ":" "#" "->"] @operator +["/" ":" "->"] @operator (tripledot) @comment.discard @@ -123,6 +123,6 @@ ; Punctuation ["," "." "-" ";"] @punctuation.delimiter -["(" ")" "{" "}" "[" "]" "<<" ">>"] @punctuation.bracket +["(" ")" "#" "{" "}" "[" "]" "<<" ">>"] @punctuation.bracket ; (ERROR) @error From ca82cd86e62392f74d86d2abc647a6fc84d56539 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:09:12 -0500 Subject: [PATCH 044/584] markdown: highlight punctuation --- runtime/queries/markdown/highlights.scm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm index 44b19741c512b..aee568c8d5701 100644 --- a/runtime/queries/markdown/highlights.scm +++ b/runtime/queries/markdown/highlights.scm @@ -47,3 +47,7 @@ (hard_line_break) ] @constant.character.escape +(thematic_break) @punctuation.delimiter + +(inline_link ["[" "]" "(" ")"] @punctuation.bracket) +(image ["[" "]" "(" ")"] @punctuation.bracket) From beb19fe1bd52abd32b56f51d47bf54f744a0d19f Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:09:30 -0500 Subject: [PATCH 045/584] bash: expand injection-regex to common shells --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 0e6cbb9cbe31a..7a4b28c4c8a0f 100644 --- a/languages.toml +++ b/languages.toml @@ -460,7 +460,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-ruby", rev = "dfff6 [[language]] name = "bash" scope = "source.bash" -injection-regex = "bash" +injection-regex = "(shell|bash|zsh|sh)" file-types = ["sh", "bash", "zsh", ".bash_login", ".bash_logout", ".bash_profile", ".bashrc", ".profile", ".zshenv", ".zlogin", ".zlogout", ".zprofile", ".zshrc", "APKBUILD", "PKGBUILD", "eclass", "ebuild", "bazelrc"] shebangs = ["sh", "bash", "dash"] roots = [] From 78c944ebc3c62c673f203785cdb39498e52115b7 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:10:19 -0500 Subject: [PATCH 046/584] rust: fix highlight corner-cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add punctuation highlights for commas as in function parameters * remove stray `variable.parameter` highlight * I couldn't find any regressions from this and it fixes an edge case I ran into (but sadly did not record 😓) * highlight `fn` as `keyword.function` * the theme docs have `fn` as an example so it seems fitting --- runtime/queries/rust/highlights.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/queries/rust/highlights.scm b/runtime/queries/rust/highlights.scm index 4b0c018e2e05e..5897991ee52b6 100644 --- a/runtime/queries/rust/highlights.scm +++ b/runtime/queries/rust/highlights.scm @@ -57,6 +57,7 @@ "::" "." ";" + "," ] @punctuation.delimiter [ @@ -95,8 +96,6 @@ value: (identifier)? @variable field: (field_identifier) @variable.other.member)) -(arguments - (identifier) @variable.parameter) (parameter pattern: (identifier) @variable.parameter) (closure_parameters @@ -141,7 +140,6 @@ "mod" "extern" - "fn" "struct" "enum" "impl" @@ -160,6 +158,8 @@ "async" ] @keyword +"fn" @keyword.function + (mutable_specifier) @keyword.storage.modifier.mut (reference_type "&" @keyword.storage.modifier.ref) From 7cf88f2bacb92e1054294137cc4d82792f4b60a4 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 22 Jun 2022 08:57:22 -0500 Subject: [PATCH 047/584] edoc: prevent rogue punctuation highlights Punctuation highlights would show up outside of where they were valid, for example using parentheses in some text. This change prevents that by gating the captures to being under the named nodes in which they are valid. --- runtime/queries/edoc/highlights.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/queries/edoc/highlights.scm b/runtime/queries/edoc/highlights.scm index 3a309960fe80c..4267cb9e0b1f1 100644 --- a/runtime/queries/edoc/highlights.scm +++ b/runtime/queries/edoc/highlights.scm @@ -39,9 +39,9 @@ ; could be @constant.numeric.integer but this looks similar to a capture (arity) @operator -[":" "/"] @operator -["(" ")"] @punctuation.delimiter -["{" "}"] @function.macro +(expression [":" "/"] @operator) +(expression ["(" ")"] @punctuation.delimiter) +(macro ["{" "}"] @function.macro) [ (quote_marker) From 016e97314cd37c245368678179f1157f83a13821 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 10:09:42 -0500 Subject: [PATCH 048/584] html: highlight punctuation * `/>` as in self-closing tags like `
` * `=` as in the separator between attribute name and value `` --- runtime/queries/html/highlights.scm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/runtime/queries/html/highlights.scm b/runtime/queries/html/highlights.scm index 2c70a9c3e6d56..fff015b5c6749 100644 --- a/runtime/queries/html/highlights.scm +++ b/runtime/queries/html/highlights.scm @@ -2,11 +2,18 @@ (erroneous_end_tag_name) @tag.error (doctype) @constant (attribute_name) @attribute -(attribute_value) @string (comment) @comment +[ + "\"" + (attribute_value) +] @string + [ "<" ">" "" ] @punctuation.bracket + +"=" @punctuation.delimiter From e4e8a39bf79734e70248303782d9b97ef4b3540d Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 13:08:31 -0500 Subject: [PATCH 049/584] replace module captures with namespace `module` is undocumented and does not exist in other themes. The equivalent existing scope based on usage (Elixir for example) is `namespace`. --- runtime/queries/erlang/highlights.scm | 10 +++++----- runtime/queries/heex/highlights.scm | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index ce84697b572bc..f491b9c5f29e2 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -2,14 +2,14 @@ ; module declaration (attribute name: (atom) @keyword - (arguments (atom) @module) + (arguments (atom) @namespace) (#eq? @keyword "module")) (attribute name: (atom) @keyword (arguments . - (atom) @module) + (atom) @namespace) (#eq? @keyword "import")) (attribute @@ -54,15 +54,15 @@ (attribute name: (atom) @keyword - module: (atom) @module (#eq? @keyword "(spec|callback)")) + module: (atom) @namespace ; Functions (function_clause name: (atom) @function) -(call module: (atom) @module) +(call module: (atom) @namespace) (call function: (atom) @function) (stab_clause name: (atom) @function) -(function_capture module: (atom) @module) +(function_capture module: (atom) @namespace) (function_capture function: (atom) @function) ; Records diff --git a/runtime/queries/heex/highlights.scm b/runtime/queries/heex/highlights.scm index c42a689fc4c62..6d8816de97e27 100644 --- a/runtime/queries/heex/highlights.scm +++ b/runtime/queries/heex/highlights.scm @@ -55,7 +55,7 @@ ; HEEx components are highlighted as Elixir modules and functions (component_name [ - (module) @module + (module) @namespace (function) @function "." @punctuation.delimiter ]) From 4a0dab8bc28ba674822a69cff72440773890a7e4 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 13:08:59 -0500 Subject: [PATCH 050/584] erlang: fix '#match?' for specs/callbacks --- runtime/queries/erlang/highlights.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index f491b9c5f29e2..31a594b696c6b 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -54,8 +54,8 @@ (attribute name: (atom) @keyword - (#eq? @keyword "(spec|callback)")) module: (atom) @namespace + (#match? @keyword "(spec|callback)")) ; Functions (function_clause name: (atom) @function) From 199a2460cabaf2e876d58f3549c4fbfe5ddf16e0 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 16:19:48 -0500 Subject: [PATCH 051/584] make: add injection-regex --- languages.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 7a4b28c4c8a0f..f1b6c980ccb67 100644 --- a/languages.toml +++ b/languages.toml @@ -727,7 +727,8 @@ source = { git = "https://github.com/uyha/tree-sitter-cmake", rev = "f6616f1e417 name = "make" scope = "source.make" file-types = ["Makefile", "makefile", "mk", "justfile", ".justfile"] -roots =[] +injection-regex = "(make|makefile|Makefile|mk|just)" +roots = [] comment-token = "#" indent = { tab-width = 4, unit = "\t" } From d8f036f0a9fd7248e53ff965f7f9f950a672808b Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:08:09 -0500 Subject: [PATCH 052/584] erlang: update parser for fix on remote calls --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index f1b6c980ccb67..2f209b4ff160c 100644 --- a/languages.toml +++ b/languages.toml @@ -1052,7 +1052,7 @@ language-server = { command = "erlang_ls" } [[grammar]] name = "erlang" -source = { git = "https://github.com/the-mikedavis/tree-sitter-erlang", rev = "c0ebc82600caaf4339f2b00691f958e9df97c065" } +source = { git = "https://github.com/the-mikedavis/tree-sitter-erlang", rev = "0e7d677d11a7379686c53c616825714ccb728059" } [[language]] name = "kotlin" From a890c4a64dee8521bc80adfe77c56e703a7e4512 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:31:11 -0500 Subject: [PATCH 053/584] tsq: update parser to fix escaping double quotes This includes a fix for the new HTML highlights introduced a few parent commits back: ["\"" (attribute_name)] @string Would get tripped up and the entire line would be highlighted as a string. Now `\"` is a valid escape. I'm switching to my fork as the primary repo as the upstream hasn't been touched in over a year (mostly because stability afaict) but it has no watchers currently so I'm not hopeful that my PR will be merged. --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 2f209b4ff160c..b8581080a503e 100644 --- a/languages.toml +++ b/languages.toml @@ -707,7 +707,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "tsq" -source = { git = "https://github.com/tree-sitter/tree-sitter-tsq", rev = "b665659d3238e6036e22ed0e24935e60efb39415" } +source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "ea68fc2b571ca1c8f70936855130c380f518ff35" } [[language]] name = "cmake" From bf1aa8876c5e9e7ccf6ab4ae66997c45ac3c4b95 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 28 Jun 2022 20:59:03 -0500 Subject: [PATCH 054/584] git-commit: fix highlight edge cases * branch message with current branch and diverged branch has been added to the parser * scissors used in verbose commits are marked as a punctuation delimiter * we could use comment instead since they're visually the same but IMO this works better --- languages.toml | 2 +- runtime/queries/git-commit/highlights.scm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/languages.toml b/languages.toml index b8581080a503e..122cadfe80d70 100644 --- a/languages.toml +++ b/languages.toml @@ -908,7 +908,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "git-commit" -source = { git = "https://github.com/the-mikedavis/tree-sitter-git-commit", rev = "7ae23de633de41f8f5b802f6f05b6596df6d00c1" } +source = { git = "https://github.com/the-mikedavis/tree-sitter-git-commit", rev = "318dd72abfaa7b8044c1d1fbeabcd06deaaf038f" } [[language]] name = "git-diff" diff --git a/runtime/queries/git-commit/highlights.scm b/runtime/queries/git-commit/highlights.scm index 0b50d41908f54..bdb776d6dd6ab 100644 --- a/runtime/queries/git-commit/highlights.scm +++ b/runtime/queries/git-commit/highlights.scm @@ -10,5 +10,5 @@ (change kind: "modified" @diff.delta) (change kind: "renamed" @diff.delta.moved) -[":" "->"] @punctuation.delimeter +[":" "->" (scissors)] @punctuation.delimeter (comment) @comment From 19acbfe02d6a6ff9496d46e02661b67e65b94923 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 29 Jun 2022 08:55:00 -0500 Subject: [PATCH 055/584] erlang: highlight records with macro names You might use a macro like `?MODULE` to name a record: -record(?MODULE, {a, b, c}). With this fix, the record fields correctly get `variable.other.member` highlights. --- runtime/queries/erlang/highlights.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index 31a594b696c6b..cb128905ab2ed 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -16,7 +16,7 @@ name: (atom) @keyword (arguments . - (atom) @type + [(atom) @type (macro)] [ (tuple (atom) @variable.other.member) (tuple From c8dba2f4c699b50384802a0fb4e0dadf87ea1677 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 29 Jun 2022 12:44:01 -0500 Subject: [PATCH 056/584] erlang: highlight modules in behaviour attributes --- runtime/queries/erlang/highlights.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/queries/erlang/highlights.scm b/runtime/queries/erlang/highlights.scm index cb128905ab2ed..8e4a640d6ecbe 100644 --- a/runtime/queries/erlang/highlights.scm +++ b/runtime/queries/erlang/highlights.scm @@ -3,7 +3,7 @@ (attribute name: (atom) @keyword (arguments (atom) @namespace) - (#eq? @keyword "module")) + (#match? @keyword "(module|behaviou?r)")) (attribute name: (atom) @keyword From c5600c9c0154df1ed20eb0eb16dfaa8c09447a2f Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 30 Jun 2022 17:46:34 -0500 Subject: [PATCH 057/584] markdown: limit raw block highlight to code fence content --- languages.toml | 2 +- runtime/queries/markdown/highlights.scm | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/languages.toml b/languages.toml index 122cadfe80d70..0b4a1dec545a4 100644 --- a/languages.toml +++ b/languages.toml @@ -855,7 +855,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "markdown" -source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "ad8c32917a16dfbb387d1da567bf0c3fb6fffde2" } +source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "ab15701d8f3f68aeb74e30573b7d669a6ef2a7ed" } [[language]] name = "dart" diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm index aee568c8d5701..096c29542622c 100644 --- a/runtime/queries/markdown/highlights.scm +++ b/runtime/queries/markdown/highlights.scm @@ -8,11 +8,9 @@ (atx_heading (atx_h5_marker) @markup.heading.marker (heading_content) @markup.heading.5) (atx_heading (atx_h6_marker) @markup.heading.marker (heading_content) @markup.heading.6) -(code_fence_content) @none - [ (indented_code_block) - (fenced_code_block) + (code_fence_content) ] @markup.raw.block (block_quote) @markup.quote @@ -26,6 +24,8 @@ (link_destination) @markup.link.url (link_label) @markup.link.label +(info_string) @label + [ (link_text) (image_description) @@ -51,3 +51,4 @@ (inline_link ["[" "]" "(" ")"] @punctuation.bracket) (image ["[" "]" "(" ")"] @punctuation.bracket) +(fenced_code_block_delimiter) @punctuation.bracket From 7baa8e837b8d1174289ea1594560f7f91974dd0c Mon Sep 17 00:00:00 2001 From: Jens Getreu Date: Fri, 1 Jul 2022 11:06:16 +0200 Subject: [PATCH 058/584] Add `color-modes` to Autumn theme (#2928) Co-authored-by: Jens Getreu --- runtime/themes/autumn.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/themes/autumn.toml b/runtime/themes/autumn.toml index c4e0cfd62ce12..d96d32eaa76a3 100644 --- a/runtime/themes/autumn.toml +++ b/runtime/themes/autumn.toml @@ -18,6 +18,9 @@ "comment" = { fg = "my_gray4", modifiers = ["italic"] } "ui.statusline" = { fg = "my_gray6", bg = "my_gray2" } "ui.statusline.inactive" = { fg = 'my_gray4', bg = 'my_gray2' } +"ui.statusline.insert" = {fg = "my_black", bg = "my_gray5", modifiers = ["bold"]} +"ui.statusline.normal" = {fg = "my_gray6", bg = "my_gray2"} +"ui.statusline.select" = {fg = "my_gray6", bg = "my_black", modifiers = ["bold"]} "ui.cursor" = { fg = "my_gray5", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "my_white", modifiers = ["reversed"] } "ui.cursorline.primary" = { bg = "my_black" } From 051a7f06064a545d05276a2aae622e54548a095a Mon Sep 17 00:00:00 2001 From: Erasin Date: Fri, 1 Jul 2022 17:07:46 +0800 Subject: [PATCH 059/584] add cursorline to one light theme (#2925) --- runtime/themes/onelight.toml | 61 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/runtime/themes/onelight.toml b/runtime/themes/onelight.toml index c89e20f9387f4..82121108f25c7 100644 --- a/runtime/themes/onelight.toml +++ b/runtime/themes/onelight.toml @@ -4,15 +4,15 @@ "attribute" = { fg = "yellow" } "comment" = { fg = "gray", modifiers = ["italic"] } -"constant" = { fg = "red" } +"constant" = { fg = "cyan" } "constant.numeric" = { fg = "gold" } "constant.builtin" = { fg = "gold" } "constant.character.escape" = { fg = "gold" } -"constructor" = { fg = "blue" } +"constructor" = { fg = "yellow" } -"function" = { fg = "light-blue" } -"function.builtin" = { fg = "gray" } +"function" = { fg = "blue" } +"function.builtin" = { fg = "cyan" } "function.macro" = { fg = "red" } "keyword" = { fg = "purple" } @@ -21,7 +21,7 @@ "keyword.directive" = { fg = "purple" } "keyword.operator" = { fg = "purple" } -"tag" = "yellow" +"tag" = "cyan" "label" = { fg = "cyan" } "namespace" = { fg = "red" } "operator" = { fg = "red" } @@ -31,15 +31,15 @@ "module" = { fg = "cyan" } "type" = { fg = "yellow" } -"type.builtin" = "blue" +"type.builtin" = { fg = "purple" } -"punctuation" = "gray" -"punctuation.delimiter" = "black" -# "punctuation.bracket" = "black" +"punctuation" = { fg = "gray" } +"punctuation.delimiter" = { fg = "black" } +# "punctuation.bracket" = { fg="black" } -# "variable" = { fg = "blue" } +"variable" = { fg = "black" } "variable.builtin" = { fg = "light-blue" } -"variable.parameter" = { fg = "blue" } +"variable.parameter" = { fg = "red" } "variable.other.member" = { fg = "red" } "markup.heading" = { fg = "red" } @@ -52,11 +52,11 @@ "markup.link.url" = { fg = "cyan", modifiers = ["underlined"] } "markup.link.text" = { fg = "light-blue" } "markup.heading.1" = { fg = "red", modifiers = ["bold"] } -"markup.heading.2" = { fg = "glod", modifiers = ["bold"] } +"markup.heading.2" = { fg = "gold", modifiers = ["bold"] } "markup.heading.3" = { fg = "yellow", modifiers = ["bold"] } "markup.heading.4" = { fg = "green", modifiers = ["bold"] } "markup.heading.5" = { fg = "blue", modifiers = ["bold"] } -"markup.heading.6" = { fg = "black", modifiers = ["bold"] } +"markup.heading.6" = { fg = "purple", modifiers = ["bold"] } "diff.plus" = "green" "diff.delta" = "gold" @@ -70,20 +70,24 @@ "ui.background" = { bg = "white" } -"ui.cursor" = { fg = "white", bg = "black" } +"ui.cursor" = { fg = "white", bg = "gray" } "ui.cursor.primary" = { fg = "white", bg = "black" } -"ui.cursor.match" = { fg = "white", bg = "purple" } +"ui.cursor.match" = { bg = "light-gray" } + +"ui.cursorline.primary" = { fg = "white", bg = "grey-200" } +"ui.cursorline.secondary" = { fg = "white", bg = "light-white" } "ui.highlight" = { bg = "light-white" } -"ui.selection" = { bg = "light-white" } -"ui.selection.primary" = { bg = "light-white", modifiers = ["dim"] } +"ui.selection" = { modifiers = ["reversed"] } +"ui.selection.primary" = { bg = "light-white" } -"ui.virtual" = { fg = "light-white"} +"ui.virtual" = { fg = "light-white" } +"ui.virtual.indent-guide" = { fg = "grey-500" } "ui.virtual.ruler" = { bg = "light-white" } -"ui.virtual.whitespace" = {fg = "light-white" } +"ui.virtual.whitespace" = { fg = "light-white" } -"ui.linenr" = { fg = "linenr" } +"ui.linenr" = { fg = "grey-500" } "ui.linenr.selected" = { fg = "black", modifiers = ["reversed"] } "ui.statusline" = { fg = "black", bg = "light-white" } @@ -93,22 +97,23 @@ "ui.text.focus" = { fg = "red", bg = "light-white", modifiers = ["bold"] } "ui.help" = { fg = "black", bg = "light-white" } -"ui.popup" = { bg = "light-white" } -"ui.window" = { bg = "light-white" } -"ui.menu" = { fg = "black", bg = "light-white" } +"ui.popup" = { fg = "black", bg = "grey-200" } +"ui.window" = { fg = "black", bg = "grey-200" } +"ui.menu" = { fg = "black", bg = "grey-200" } "ui.menu.selected" = { fg = "white", bg = "light-blue" } [palette] white = "#FAFAFA" yellow = "#A06600" -blue = "#5556FF" -light-blue = "#2F77FA" +blue = "#0061FF" +light-blue = "#1877F2" red = "#DC003F" purple = "#B500A9" green = "#24A443" -gold = "#D19A66" +gold = "#D35400" cyan = "#0086C1" black = "#282C34" -light-white = "#EAEAEB" +light-white = "#E0E0E0" gray = "#5C6370" -linenr = "#9D9D9F" +grey-200 = "#EEEEEE" +grey-500 = "#9E9E9E" From 444bc24a261ce02618cb73425d3847e554c83156 Mon Sep 17 00:00:00 2001 From: two-six Date: Fri, 1 Jul 2022 11:08:27 +0200 Subject: [PATCH 060/584] [Theme] Nord Light (#2908) * add theme * updated nord_light * update to colors * last update to colors --- runtime/themes/nord_light.toml | 67 ++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 runtime/themes/nord_light.toml diff --git a/runtime/themes/nord_light.toml b/runtime/themes/nord_light.toml new file mode 100644 index 0000000000000..9afb1dee42883 --- /dev/null +++ b/runtime/themes/nord_light.toml @@ -0,0 +1,67 @@ +# Author: Two-Six + +"ui.background" = {bg="nord6"} +"ui.text" = "nord0" +"ui.selection" = {bg="nord7", fg="nord6"} +"ui.statusline" = {bg="nord4"} +"ui.statusline.inactive" = {bg="nord8"} +"ui.virtual" = "nord8" +"ui.cursor.match" = {bg="nord8"} +"ui.cursor" = {bg="nord10", fg="nord6"} +"ui.cursorline.primary" = {bg="nord5"} +"ui.linenr" = {fg="nord7"} +"ui.linenr.selected" = {fg="nord0", bg="nord5"} +"ui.menu" = {bg="nord4"} +"ui.menu.selected" = {bg="nord5"} +"ui.popup" = {bg="nord4"} + +"diagnostic.error" = {fg="nord11", modifiers=["bold"]} +"diagnostic.warning" = {bg="nord13", modifiers=["bold"]} +"diagnostic.hint" = {fg="nord13", modifiers=["bold"]} + +"constant.numeric" = {fg="nord15"} +"constant.builtin" = {fg="nord15"} + +"keyword" = {fg="nord2"} +"keyword.control" = {fg="nord2"} +"keyword.function" = {fg="nord2"} + +"function" = {fg="nord3"} +"function.macro" = {fg="nord10", modifiers=["bold"]} +"function.method" = {fg="nord0"} +"function.builtin" = {fg="nord10"} + +"variable.builtin" = {fg="nord3"} +"variable.other" = {fg="nord3"} +"variable" = {fg="nord0"} + +"string" = "nord14" +"comment" = "nord7" +"namespace" = {fg="nord10"} +"attribute" = {fg="nord10"} +"type" = {fg="nord10"} + +"markup.heading" = {fg="nord0", modifiers=["bold"]} +"markup.raw" = {fg="nord10"} +"markup.link.url" = {fg="nord3"} +"markup.link.text" = {fg="nord12"} +"markup.quote" = {fg="nord3", modifiers=["italic"]} + + +[palette] +nord0 = "#2E3440" +nord1 = "#3B4252" +nord2 = "#434C5E" +nord3 = "#4C566A" +nord4 = "#D8DEE9" +nord5 = "#E5E9F0" +nord6 = "#ECEFF4" +nord7 = "#8FBCBB" +nord8 = "#88C0D0" +nord9 = "#81A1C1" +nord10 = "#5E81AC" +nord11 = "#BF616A" +nord12 = "#D08770" +nord13 = "#EBCB8B" +nord14 = "#A3BE8C" +nord15 = "#B48EAD" From edee2f4c347c53c4ba0ee7d8e4624e12e64d90fe Mon Sep 17 00:00:00 2001 From: Sora Date: Fri, 1 Jul 2022 11:08:48 +0200 Subject: [PATCH 061/584] Fix backwards character deletion on other whitespaces (#2855) * delete_backwards_char accepts any type of whitespace * Fix inconsistency, where unicode whitespaces are treated as normal whitespaces * Changed back to direct whitespace match * Only accept explicit whitespace / tabs Co-authored-by: s0LA1337 --- helix-term/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index bc8e65302f9bc..59ca2e3bd2d09 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2948,7 +2948,7 @@ pub mod insert { let line_start_pos = text.line_to_char(range.cursor_line(text)); // consider to delete by indent level if all characters before `pos` are indent units. let fragment = Cow::from(text.slice(line_start_pos..pos)); - if !fragment.is_empty() && fragment.chars().all(|ch| ch.is_whitespace()) { + if !fragment.is_empty() && fragment.chars().all(|ch| ch == ' ' || ch == '\t') { if text.get_char(pos.saturating_sub(1)) == Some('\t') { // fast path, delete one char ( From 15d96c843aca5b87fde26faf6c556265402c32c1 Mon Sep 17 00:00:00 2001 From: Benjamin Rich Date: Fri, 1 Jul 2022 05:27:18 -0400 Subject: [PATCH 062/584] Add new key bindings to view mode (#2803) * Make view mode more pager-like Addresses #2721 * Remove view mode bindings for J and K --- helix-term/src/keymap/default.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 29b0b670690ce..9b1447581b985 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -273,8 +273,13 @@ pub fn default() -> HashMap { "j" | "down" => scroll_down, "C-b" | "pageup" => page_up, "C-f" | "pagedown" => page_down, - "C-u" => half_page_up, - "C-d" => half_page_down, + "C-u" | "backspace" => half_page_up, + "C-d" | "space" => half_page_down, + + "/" => search, + "?" => rsearch, + "n" => search_next, + "N" => search_prev, }, "Z" => { "View" sticky=true "z" | "c" => align_view_center, @@ -285,8 +290,13 @@ pub fn default() -> HashMap { "j" | "down" => scroll_down, "C-b" | "pageup" => page_up, "C-f" | "pagedown" => page_down, - "C-u" => half_page_up, - "C-d" => half_page_down, + "C-u" | "backspace" => half_page_up, + "C-d" | "space" => half_page_down, + + "/" => search, + "?" => rsearch, + "n" => search_next, + "N" => search_prev, }, "\"" => select_register, From f10b6f6ee2bbf4d6d9356e27be25b25bdb85b9cd Mon Sep 17 00:00:00 2001 From: plexom <48958093+plexom@users.noreply.github.com> Date: Fri, 1 Jul 2022 11:27:32 +0200 Subject: [PATCH 063/584] adds --vsplit and --hsplit arguments (#2773) * adds --vsplit and --hsplit arguments * moved comment * fixed lint (third time's a charm) * changed vsplit and hsplit from two separate bools to type Option, and some cleanup --- contrib/completion/hx.bash | 2 +- contrib/completion/hx.fish | 3 ++- contrib/completion/hx.zsh | 2 ++ helix-term/src/application.rs | 21 ++++++++++++++++++--- helix-term/src/args.rs | 4 ++++ helix-term/src/main.rs | 2 ++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/contrib/completion/hx.bash b/contrib/completion/hx.bash index 6371bedb67bb6..87c340284f6e3 100644 --- a/contrib/completion/hx.bash +++ b/contrib/completion/hx.bash @@ -16,7 +16,7 @@ _hx() { COMPREPLY=($(compgen -W "$languages" -- $2)) ;; *) - COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar" -- $2)) + COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit" -- $2)) ;; esac } && complete -F _hx hx diff --git a/contrib/completion/hx.fish b/contrib/completion/hx.fish index 4ec690d8b0b85..df2fb500c935f 100644 --- a/contrib/completion/hx.fish +++ b/contrib/completion/hx.fish @@ -9,4 +9,5 @@ complete -c hx -l health -x -a "$langs" -d "Checks for errors in editor setup" complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetches or builds tree-sitter grammars" complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity" complete -c hx -s V -l version -d "Prints version information" - +complete -c hx -l vsplit -d "Splits all given files vertically into different windows" +complete -c hx -l hsplit -d "Splits all given files horizontally into different windows" diff --git a/contrib/completion/hx.zsh b/contrib/completion/hx.zsh index 16631519bc461..f9d58d3c6569b 100644 --- a/contrib/completion/hx.zsh +++ b/contrib/completion/hx.zsh @@ -14,6 +14,8 @@ _hx() { "--health[Checks for errors in editor setup]:language:->health" \ "-g[Fetches or builds tree-sitter grammars]:action:->grammar" \ "--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \ + "--vsplit[Splits all given files vertically into different windows]" \ + "--hsplit[Splits all given files horizontally into different windows]" \ "*:file:_files" case "$state" in diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 23f4610f6ad55..805f660f6d925 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -5,7 +5,7 @@ use helix_core::{ pos_at_coords, syntax, Selection, }; use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap}; -use helix_view::{align_view, editor::ConfigEvent, theme, Align, Editor}; +use helix_view::{align_view, editor::ConfigEvent, theme, tree::Layout, Align, Editor}; use serde_json::json; use crate::{ @@ -158,16 +158,31 @@ impl Application { } else { let nr_of_files = args.files.len(); editor.open(first, Action::VerticalSplit)?; - for (file, pos) in args.files { + // Because the line above already opens the first file, we can + // simply skip opening it a second time by using .skip(1) here. + for (file, pos) in args.files.into_iter().skip(1) { if file.is_dir() { return Err(anyhow::anyhow!( "expected a path to file, found a directory. (to open a directory pass it as first argument)" )); } else { + // If the user passes in either `--vsplit` or + // `--hsplit` as a command line argument, all the given + // files will be opened according to the selected + // option. If neither of those two arguments are passed + // in, just load the files normally. + let action = match args.split { + Some(Layout::Vertical) => Action::VerticalSplit, + Some(Layout::Horizontal) => Action::HorizontalSplit, + None => Action::Load, + }; let doc_id = editor - .open(&file, Action::Load) + .open(&file, action) .context(format!("open '{}'", file.to_string_lossy()))?; // with Action::Load all documents have the same view + // NOTE: this isn't necessarily true anymore. If + // `--vsplit` or `--hsplit` are used, the file which is + // opened last is focused on. let view_id = editor.tree.focus; let doc = editor.document_mut(doc_id).unwrap(); let pos = Selection::point(pos_at_coords(doc.text().slice(..), pos, true)); diff --git a/helix-term/src/args.rs b/helix-term/src/args.rs index b99c7d1a27687..c3019ea7c875b 100644 --- a/helix-term/src/args.rs +++ b/helix-term/src/args.rs @@ -1,5 +1,6 @@ use anyhow::Result; use helix_core::Position; +use helix_view::tree::Layout; use std::path::{Path, PathBuf}; #[derive(Default)] @@ -11,6 +12,7 @@ pub struct Args { pub load_tutor: bool, pub fetch_grammars: bool, pub build_grammars: bool, + pub split: Option, pub verbosity: u64, pub files: Vec<(PathBuf, Position)>, } @@ -28,6 +30,8 @@ impl Args { "--version" => args.display_version = true, "--help" => args.display_help = true, "--tutor" => args.load_tutor = true, + "--vsplit" => args.split = Some(Layout::Vertical), + "--hsplit" => args.split = Some(Layout::Horizontal), "--health" => { args.health = true; args.health_arg = argv.next_if(|opt| !opt.starts_with('-')); diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs index 7b26fb119457c..eb186d78e2acf 100644 --- a/helix-term/src/main.rs +++ b/helix-term/src/main.rs @@ -67,6 +67,8 @@ FLAGS: -v Increases logging verbosity each use for up to 3 times (default file: {}) -V, --version Prints version information + --vsplit Splits all given files vertically into different windows + --hsplit Splits all given files horizontally into different windows ", env!("CARGO_PKG_NAME"), env!("VERSION_AND_GIT_HASH"), From d8abd1eaf398f462122efbc937cda9d8178a5754 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Fri, 1 Jul 2022 10:33:52 +0100 Subject: [PATCH 064/584] Sort themes, language & files by score & then name (#2675) * Sort themes by score & then name Previously the themes were appearing unordered after typing ':theme '. This sorts them first by fuzzy score and then by name so that they generally appear in a more ordered fashion in the initial list. The sort by name does not really pay off when there is a score so an alternative approach would be to sort by name if there is string to fuzzy match against and otherwise sort by score. I've lowercased the names as that avoids lower case & upper case letters being sorted into separate groups. There might be a preferable approach to that though. * Sort language & files by score then name And change to use sort_unstable_by instead of sort_unstable_by_key as it allows us to avoid some allocations. I don't fully understand the flow of the 'filename_impl' function but this seems to deliver the desired results. * Remove unnecessary reference Co-authored-by: Michael Davis Co-authored-by: Michael Davis --- helix-term/src/ui/mod.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index c1e5c98897ab1..948a5f2b67dfd 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -257,7 +257,9 @@ pub mod completers { }) .collect(); - matches.sort_unstable_by_key(|(_file, score)| Reverse(*score)); + matches.sort_unstable_by(|(name1, score1), (name2, score2)| { + (Reverse(*score1), name1).cmp(&(Reverse(*score2), name2)) + }); names = matches.into_iter().map(|(name, _)| ((0..), name)).collect(); names @@ -312,7 +314,9 @@ pub mod completers { }) .collect(); - matches.sort_unstable_by_key(|(_language, score)| Reverse(*score)); + matches.sort_unstable_by(|(language1, score1), (language2, score2)| { + (Reverse(*score1), language1).cmp(&(Reverse(*score2), language2)) + }); matches .into_iter() @@ -428,13 +432,18 @@ pub mod completers { let range = (input.len().saturating_sub(file_name.len()))..; - matches.sort_unstable_by_key(|(_file, score)| Reverse(*score)); + matches.sort_unstable_by(|(file1, score1), (file2, score2)| { + (Reverse(*score1), file1).cmp(&(Reverse(*score2), file2)) + }); + files = matches .into_iter() .map(|(file, _)| (range.clone(), file)) .collect(); // TODO: complete to longest common match + } else { + files.sort_unstable_by(|(_, path1), (_, path2)| path1.cmp(path2)); } files From 9ae70cc410bd042b5cf119c571db323436caf08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 1 Jul 2022 19:16:16 +0900 Subject: [PATCH 065/584] Disable tree-sitter python indents, use fallback for now There's been a lot of complaints about the state of python indentation and the fallback actually works better until the solution proposed in https://github.com/helix-editor/helix/issues/763#issuecomment-1137894973= is implemented. --- runtime/queries/python/{indents.scm => indents.scm_} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename runtime/queries/python/{indents.scm => indents.scm_} (100%) diff --git a/runtime/queries/python/indents.scm b/runtime/queries/python/indents.scm_ similarity index 100% rename from runtime/queries/python/indents.scm rename to runtime/queries/python/indents.scm_ From 8a19196ad55cd8461b0a621ecfe373b0b3407ec5 Mon Sep 17 00:00:00 2001 From: nosa <96927121+n0s4@users.noreply.github.com> Date: Fri, 1 Jul 2022 11:18:39 +0100 Subject: [PATCH 066/584] Updated for #2676 , but I took the opportunity to do some other changes. (#2929) - Misspelling of 'modifiers' for markdown.heading.1 and 2. - Errors are now just underlined instead of in red. - Diagnostics are dimmed, as well as whitespace. - Add constant.builtin. --- runtime/themes/night_owl.toml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/runtime/themes/night_owl.toml b/runtime/themes/night_owl.toml index 337fae86e9c46..d992735588232 100644 --- a/runtime/themes/night_owl.toml +++ b/runtime/themes/night_owl.toml @@ -1,11 +1,11 @@ # Author : Joe Mckay joemckay3006@gmail.com # Palette from https://github.com/haishanh/night-owl.vim -'warning' = { fg = 'peach' } -'error' = { fg = 'red' } -'info' = { fg = 'blue' } -'hint' = { fg = 'paleblue' } -'diagnostic' = { fg = 'background', bg = 'red' } +'warning' = { fg = 'peach', modifiers = ['dim'] } +'error' = { fg = 'red', modifiers = ['dim'] } +'info' = { fg = 'blue', modifiers = ['dim'] } +'hint' = { fg = 'paleblue', modifiers = ['dim'] } +'diagnostic' = { modifiers = ['underlined'] } # UI 'ui.background' = { fg = 'foreground', bg = 'background' } @@ -22,18 +22,22 @@ 'ui.linenr.selected' = { fg = 'greyE', bg = 'background2' } 'ui.statusline' = { fg = 'greyE', bg = 'background2' } 'ui.statusline.inactive' = { fg = 'grey7', bg = 'background2' } +'ui.statusline.normal' = { bg = 'slate' } +'ui.statusline.insert' = { bg = 'peach' } +'ui.statusline.select' = { bg = 'green' } 'ui.menu' = { fg = 'foreground', bg = 'selection' } 'ui.menu.selected' = { fg = 'foreground', bg = 'pink' } 'ui.popup' = { fg = 'foreground', bg = 'background2' } 'ui.popup.info' = { fg = 'gold', bg = 'background2'} 'ui.help' = { fg = 'gold', bg = 'background2'} 'ui.virtual.ruler' = { bg = 'grey4' } -'ui.virtual.whitespace' = { fg = 'slate' } +'ui.virtual.whitespace' = { fg = 'grey4' } # SYNTAX 'type' = { fg = 'green' } 'constructor' = { fg = 'blue' } 'constant' = { fg = 'foreground' } +'constant.builtin' = { fg = 'paleblue' } 'constant.character.escape' = { fg = 'peach' } 'string' = { fg = 'gold' } 'string.regexp' = { fg = 'green' } @@ -63,8 +67,8 @@ # MARKUP 'markup.heading' = { fg = 'blue', modifiers = ['bold'] } 'markup.heading.marker' = { fg = 'grey4', modifiers = ['dim'] } -'markup.heading.1' = { fg = 'blue', modifers = ['bold'] } -'markup.heading.2' = { fg = 'paleblue', modifers = ['bold'] } +'markup.heading.1' = { fg = 'blue', modifiers = ['bold'] } +'markup.heading.2' = { fg = 'paleblue', modifiers = ['bold'] } 'markup.heading.3' = { fg = 'green', modifiers = ['bold'] } 'markup.heading.4' = { fg = 'pink', modifiers = ['bold'] } 'markup.heading.5' = { fg = 'peach', modifiers = ['bold'] } From a1c1abca2b2bbe82e76bbc2c0a8bc522aacbe0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Fri, 1 Jul 2022 21:24:10 +0900 Subject: [PATCH 067/584] fix CI --- book/src/generated/lang-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 5ea18ae848458..c82a6443bff45 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -71,7 +71,7 @@ | prisma | ✓ | | | `prisma-language-server` | | prolog | | | | `swipl` | | protobuf | ✓ | | ✓ | | -| python | ✓ | ✓ | ✓ | `pylsp` | +| python | ✓ | ✓ | | `pylsp` | | r | ✓ | | | `R` | | racket | | | | `racket` | | regex | ✓ | | | | From cc3aded1858189941cd0d78e32b267c66abfcee3 Mon Sep 17 00:00:00 2001 From: ramojus <41536253+Ramojus@users.noreply.github.com> Date: Fri, 1 Jul 2022 15:24:33 +0300 Subject: [PATCH 068/584] add statusline mode colors to meliora theme (#2933) --- runtime/themes/meliora.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtime/themes/meliora.toml b/runtime/themes/meliora.toml index 72ade8ac52b66..ecc19f46eebb2 100644 --- a/runtime/themes/meliora.toml +++ b/runtime/themes/meliora.toml @@ -1,4 +1,4 @@ -# Author: Ramojus +# Author: Ramojus Lapinskas "comment" = { fg = "comment" } "constant" = { fg = "magenta" } @@ -43,6 +43,9 @@ "ui.statusline" = { fg = "dark_white", bg = "light_black3" } "ui.statusline.inactive" = { fg = "dark_white2", bg = "light_black" } +"ui.statusline.normal" = { bg = "dark_white2", fg = "black" } +"ui.statusline.insert" = { bg = "blue", fg = "black" } +"ui.statusline.select" = { bg = "orange", fg = "black" } "ui.text" = { fg = "white" } "ui.text.focus" = { fg = "orange" } From 1fde77ad9d8cbb91440ad19204a42e8c1709985a Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Fri, 1 Jul 2022 17:06:14 +0100 Subject: [PATCH 069/584] Sort themes, language & files by score & then name (#2675) Co-authored-by: Michael Davis From 290b3ebbbe0c365eee436b9de9d6d6fc2b4339e9 Mon Sep 17 00:00:00 2001 From: nosa <96927121+n0s4@users.noreply.github.com> Date: Fri, 1 Jul 2022 20:09:59 +0100 Subject: [PATCH 070/584] Update night_owl for cursorline (#2938) --- runtime/themes/night_owl.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/themes/night_owl.toml b/runtime/themes/night_owl.toml index d992735588232..825bd4120d33d 100644 --- a/runtime/themes/night_owl.toml +++ b/runtime/themes/night_owl.toml @@ -32,6 +32,7 @@ 'ui.help' = { fg = 'gold', bg = 'background2'} 'ui.virtual.ruler' = { bg = 'grey4' } 'ui.virtual.whitespace' = { fg = 'grey4' } +'ui.cursorline.primary' = { bg = 'background2' } # SYNTAX 'type' = { fg = 'green' } From 6e2aaed5c2cbcedc9ee4e225510cae4f357888aa Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sat, 2 Jul 2022 16:51:27 +0530 Subject: [PATCH 071/584] Reuse menu::Item trait in picker (#2814) * Refactor menu::Item to accomodate external state Will be useful for storing editor state when reused by pickers. * Add some type aliases for readability * Reuse menu::Item trait in picker This opens the way for merging the menu and picker code in the future, since a picker is essentially a menu + prompt. More excitingly, this change will also allow aligning items in the picker, which would be useful (for example) in the command palette for aligning the descriptions to the left and the keybinds to the right in two separate columns. The item formatting of each picker has been kept as is, even though there is room for improvement now that we can format the data into columns, since that is better tackled in a separate PR. * Rename menu::Item::EditorData to Data * Call and inline filter_text() in sort_text() completion * Rename diagnostic picker's Item::Data --- helix-dap/src/client.rs | 2 +- helix-dap/src/types.rs | 2 + helix-term/src/commands.rs | 149 +++++++++++++-------- helix-term/src/commands/dap.rs | 54 +++++--- helix-term/src/commands/lsp.rs | 222 +++++++++++++++++++------------- helix-term/src/keymap.rs | 11 +- helix-term/src/ui/completion.rs | 23 ++-- helix-term/src/ui/menu.rs | 54 +++++--- helix-term/src/ui/mod.rs | 7 +- helix-term/src/ui/picker.rs | 38 +++--- helix-tui/src/text.rs | 6 + 11 files changed, 350 insertions(+), 218 deletions(-) diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs index 9498c64c141ef..371cf3032e96f 100644 --- a/helix-dap/src/client.rs +++ b/helix-dap/src/client.rs @@ -34,7 +34,7 @@ pub struct Client { pub caps: Option, // thread_id -> frames pub stack_frames: HashMap>, - pub thread_states: HashMap, + pub thread_states: ThreadStates, pub thread_id: Option, /// Currently active frame for the current thread. pub active_frame: Option, diff --git a/helix-dap/src/types.rs b/helix-dap/src/types.rs index 2c3df9c335bb0..fd8456a430e5d 100644 --- a/helix-dap/src/types.rs +++ b/helix-dap/src/types.rs @@ -14,6 +14,8 @@ impl std::fmt::Display for ThreadId { } } +pub type ThreadStates = HashMap; + pub trait Request { type Arguments: serde::de::DeserializeOwned + serde::Serialize; type Result: serde::de::DeserializeOwned + serde::Serialize; diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 59ca2e3bd2d09..df4867fc76c5c 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -45,6 +45,7 @@ use movement::Movement; use crate::{ args, compositor::{self, Component, Compositor}, + keymap::ReverseKeymap, ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent}, }; @@ -1744,8 +1745,42 @@ fn search_selection(cx: &mut Context) { } fn global_search(cx: &mut Context) { - let (all_matches_sx, all_matches_rx) = - tokio::sync::mpsc::unbounded_channel::<(usize, PathBuf)>(); + #[derive(Debug)] + struct FileResult { + path: PathBuf, + /// 0 indexed lines + line_num: usize, + } + + impl FileResult { + fn new(path: &Path, line_num: usize) -> Self { + Self { + path: path.to_path_buf(), + line_num, + } + } + } + + impl ui::menu::Item for FileResult { + type Data = Option; + + fn label(&self, current_path: &Self::Data) -> Spans { + let relative_path = helix_core::path::get_relative_path(&self.path) + .to_string_lossy() + .into_owned(); + if current_path + .as_ref() + .map(|p| p == &self.path) + .unwrap_or(false) + { + format!("{} (*)", relative_path).into() + } else { + relative_path.into() + } + } + } + + let (all_matches_sx, all_matches_rx) = tokio::sync::mpsc::unbounded_channel::(); let config = cx.editor.config(); let smart_case = config.search.smart_case; let file_picker_config = config.file_picker.clone(); @@ -1809,7 +1844,7 @@ fn global_search(cx: &mut Context) { entry.path(), sinks::UTF8(|line_num, _| { all_matches_sx - .send((line_num as usize - 1, entry.path().to_path_buf())) + .send(FileResult::new(entry.path(), line_num as usize - 1)) .unwrap(); Ok(true) @@ -1836,7 +1871,7 @@ fn global_search(cx: &mut Context) { let current_path = doc_mut!(cx.editor).path().cloned(); let show_picker = async move { - let all_matches: Vec<(usize, PathBuf)> = + let all_matches: Vec = UnboundedReceiverStream::new(all_matches_rx).collect().await; let call: job::Callback = Box::new(move |editor: &mut Editor, compositor: &mut Compositor| { @@ -1847,17 +1882,8 @@ fn global_search(cx: &mut Context) { let picker = FilePicker::new( all_matches, - move |(_line_num, path)| { - let relative_path = helix_core::path::get_relative_path(path) - .to_string_lossy() - .into_owned(); - if current_path.as_ref().map(|p| p == path).unwrap_or(false) { - format!("{} (*)", relative_path).into() - } else { - relative_path.into() - } - }, - move |cx, (line_num, path), action| { + current_path, + move |cx, FileResult { path, line_num }, action| { match cx.editor.open(path, action) { Ok(_) => {} Err(e) => { @@ -1879,7 +1905,9 @@ fn global_search(cx: &mut Context) { doc.set_selection(view.id, Selection::single(start, end)); align_view(doc, view, Align::Center); }, - |_editor, (line_num, path)| Some((path.clone(), Some((*line_num, *line_num)))), + |_editor, FileResult { path, line_num }| { + Some((path.clone(), Some((*line_num, *line_num)))) + }, ); compositor.push(Box::new(overlayed(picker))); }); @@ -2172,8 +2200,10 @@ fn buffer_picker(cx: &mut Context) { is_current: bool, } - impl BufferMeta { - fn format(&self) -> Spans { + impl ui::menu::Item for BufferMeta { + type Data = (); + + fn label(&self, _data: &Self::Data) -> Spans { let path = self .path .as_deref() @@ -2213,7 +2243,7 @@ fn buffer_picker(cx: &mut Context) { .iter() .map(|(_, doc)| new_meta(doc)) .collect(), - BufferMeta::format, + (), |cx, meta, action| { cx.editor.switch(meta.id, action); }, @@ -2230,6 +2260,38 @@ fn buffer_picker(cx: &mut Context) { cx.push_layer(Box::new(overlayed(picker))); } +impl ui::menu::Item for MappableCommand { + type Data = ReverseKeymap; + + fn label(&self, keymap: &Self::Data) -> Spans { + // formats key bindings, multiple bindings are comma separated, + // individual key presses are joined with `+` + let fmt_binding = |bindings: &Vec>| -> String { + bindings + .iter() + .map(|bind| { + bind.iter() + .map(|key| key.to_string()) + .collect::>() + .join("+") + }) + .collect::>() + .join(", ") + }; + + match self { + MappableCommand::Typable { doc, name, .. } => match keymap.get(name as &String) { + Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), + None => doc.as_str().into(), + }, + MappableCommand::Static { doc, name, .. } => match keymap.get(*name) { + Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), + None => (*doc).into(), + }, + } + } +} + pub fn command_palette(cx: &mut Context) { cx.callback = Some(Box::new( move |compositor: &mut Compositor, cx: &mut compositor::Context| { @@ -2246,44 +2308,17 @@ pub fn command_palette(cx: &mut Context) { } })); - // formats key bindings, multiple bindings are comma separated, - // individual key presses are joined with `+` - let fmt_binding = |bindings: &Vec>| -> String { - bindings - .iter() - .map(|bind| { - bind.iter() - .map(|key| key.key_sequence_format()) - .collect::() - }) - .collect::>() - .join(", ") - }; - - let picker = Picker::new( - commands, - move |command| match command { - MappableCommand::Typable { doc, name, .. } => match keymap.get(name) { - Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), - None => doc.as_str().into(), - }, - MappableCommand::Static { doc, name, .. } => match keymap.get(*name) { - Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(), - None => (*doc).into(), - }, - }, - move |cx, command, _action| { - let mut ctx = Context { - register: None, - count: std::num::NonZeroUsize::new(1), - editor: cx.editor, - callback: None, - on_next_key_callback: None, - jobs: cx.jobs, - }; - command.execute(&mut ctx); - }, - ); + let picker = Picker::new(commands, keymap, move |cx, command, _action| { + let mut ctx = Context { + register: None, + count: std::num::NonZeroUsize::new(1), + editor: cx.editor, + callback: None, + on_next_key_callback: None, + jobs: cx.jobs, + }; + command.execute(&mut ctx); + }); compositor.push(Box::new(overlayed(picker))); }, )); diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index b897b2d5852b3..9f6f4c15cd325 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -4,13 +4,15 @@ use crate::{ job::{Callback, Jobs}, ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent, Text}, }; -use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion}; +use dap::{StackFrame, Thread, ThreadStates}; +use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion, DebugTemplate}; use helix_dap::{self as dap, Client}; use helix_lsp::block_on; use helix_view::editor::Breakpoint; use serde_json::{to_value, Value}; use tokio_stream::wrappers::UnboundedReceiverStream; +use tui::text::Spans; use std::collections::HashMap; use std::future::Future; @@ -20,6 +22,38 @@ use anyhow::{anyhow, bail}; use helix_view::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select_thread_id}; +impl ui::menu::Item for StackFrame { + type Data = (); + + fn label(&self, _data: &Self::Data) -> Spans { + self.name.as_str().into() // TODO: include thread_states in the label + } +} + +impl ui::menu::Item for DebugTemplate { + type Data = (); + + fn label(&self, _data: &Self::Data) -> Spans { + self.name.as_str().into() + } +} + +impl ui::menu::Item for Thread { + type Data = ThreadStates; + + fn label(&self, thread_states: &Self::Data) -> Spans { + format!( + "{} ({})", + self.name, + thread_states + .get(&self.id) + .map(|state| state.as_str()) + .unwrap_or("unknown") + ) + .into() + } +} + fn thread_picker( cx: &mut Context, callback_fn: impl Fn(&mut Editor, &dap::Thread) + Send + 'static, @@ -41,17 +75,7 @@ fn thread_picker( let thread_states = debugger.thread_states.clone(); let picker = FilePicker::new( threads, - move |thread| { - format!( - "{} ({})", - thread.name, - thread_states - .get(&thread.id) - .map(|state| state.as_str()) - .unwrap_or("unknown") - ) - .into() - }, + thread_states, move |cx, thread, _action| callback_fn(cx.editor, thread), move |editor, thread| { let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?; @@ -243,7 +267,7 @@ pub fn dap_launch(cx: &mut Context) { cx.push_layer(Box::new(overlayed(Picker::new( templates, - |template| template.name.as_str().into(), + (), |cx, template, _action| { let completions = template.completion.clone(); let name = template.name.clone(); @@ -475,7 +499,7 @@ pub fn dap_variables(cx: &mut Context) { for scope in scopes.iter() { // use helix_view::graphics::Style; - use tui::text::{Span, Spans}; + use tui::text::Span; let response = block_on(debugger.variables(scope.variables_reference)); variables.push(Spans::from(Span::styled( @@ -652,7 +676,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) { let picker = FilePicker::new( frames, - |frame| frame.name.as_str().into(), // TODO: include thread_states in the label + (), move |cx, frame, _action| { let debugger = debugger!(cx.editor); // TODO: this should be simpler to find diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index d11c44cd42878..7f82394ac6226 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -19,7 +19,8 @@ use crate::{ ui::{self, overlay::overlayed, FileLocation, FilePicker, Popup, PromptEvent}, }; -use std::{borrow::Cow, collections::BTreeMap}; +use std::collections::BTreeMap; +use std::{borrow::Cow, path::PathBuf}; /// Gets the language server that is attached to a document, and /// if it's not active displays a status message. Using this macro @@ -39,6 +40,112 @@ macro_rules! language_server { }; } +impl ui::menu::Item for lsp::Location { + /// Current working directory. + type Data = PathBuf; + + fn label(&self, cwdir: &Self::Data) -> Spans { + let file: Cow<'_, str> = (self.uri.scheme() == "file") + .then(|| { + self.uri + .to_file_path() + .map(|path| { + // strip root prefix + path.strip_prefix(&cwdir) + .map(|path| path.to_path_buf()) + .unwrap_or(path) + }) + .map(|path| Cow::from(path.to_string_lossy().into_owned())) + .ok() + }) + .flatten() + .unwrap_or_else(|| self.uri.as_str().into()); + let line = self.range.start.line; + format!("{}:{}", file, line).into() + } +} + +impl ui::menu::Item for lsp::SymbolInformation { + /// Path to currently focussed document + type Data = Option; + + fn label(&self, current_doc_path: &Self::Data) -> Spans { + if current_doc_path.as_ref() == Some(&self.location.uri) { + self.name.as_str().into() + } else { + match self.location.uri.to_file_path() { + Ok(path) => { + let relative_path = helix_core::path::get_relative_path(path.as_path()) + .to_string_lossy() + .into_owned(); + format!("{} ({})", &self.name, relative_path).into() + } + Err(_) => format!("{} ({})", &self.name, &self.location.uri).into(), + } + } + } +} + +struct DiagnosticStyles { + hint: Style, + info: Style, + warning: Style, + error: Style, +} + +struct PickerDiagnostic { + url: lsp::Url, + diag: lsp::Diagnostic, +} + +impl ui::menu::Item for PickerDiagnostic { + type Data = DiagnosticStyles; + + fn label(&self, styles: &Self::Data) -> Spans { + let mut style = self + .diag + .severity + .map(|s| match s { + DiagnosticSeverity::HINT => styles.hint, + DiagnosticSeverity::INFORMATION => styles.info, + DiagnosticSeverity::WARNING => styles.warning, + DiagnosticSeverity::ERROR => styles.error, + _ => Style::default(), + }) + .unwrap_or_default(); + + // remove background as it is distracting in the picker list + style.bg = None; + + let code = self + .diag + .code + .as_ref() + .map(|c| match c { + NumberOrString::Number(n) => n.to_string(), + NumberOrString::String(s) => s.to_string(), + }) + .unwrap_or_default(); + + let truncated_path = path::get_truncated_path(self.url.path()) + .to_string_lossy() + .into_owned(); + + Spans::from(vec![ + Span::styled( + self.diag.source.clone().unwrap_or_default(), + style.add_modifier(Modifier::BOLD), + ), + Span::raw(": "), + Span::styled(truncated_path, style), + Span::raw(" - "), + Span::styled(code, style.add_modifier(Modifier::BOLD)), + Span::raw(": "), + Span::styled(&self.diag.message, style), + ]) + } +} + fn location_to_file_location(location: &lsp::Location) -> FileLocation { let path = location.uri.to_file_path().unwrap(); let line = Some(( @@ -93,29 +200,14 @@ fn sym_picker( offset_encoding: OffsetEncoding, ) -> FilePicker { // TODO: drop current_path comparison and instead use workspace: bool flag? - let current_path2 = current_path.clone(); FilePicker::new( symbols, - move |symbol| { - if current_path.as_ref() == Some(&symbol.location.uri) { - symbol.name.as_str().into() - } else { - match symbol.location.uri.to_file_path() { - Ok(path) => { - let relative_path = helix_core::path::get_relative_path(path.as_path()) - .to_string_lossy() - .into_owned(); - format!("{} ({})", &symbol.name, relative_path).into() - } - Err(_) => format!("{} ({})", &symbol.name, &symbol.location.uri).into(), - } - } - }, + current_path.clone(), move |cx, symbol, action| { let (view, doc) = current!(cx.editor); push_jump(view, doc); - if current_path2.as_ref() != Some(&symbol.location.uri) { + if current_path.as_ref() != Some(&symbol.location.uri) { let uri = &symbol.location.uri; let path = match uri.to_file_path() { Ok(path) => path, @@ -155,7 +247,7 @@ fn diag_picker( diagnostics: BTreeMap>, current_path: Option, offset_encoding: OffsetEncoding, -) -> FilePicker<(lsp::Url, lsp::Diagnostic)> { +) -> FilePicker { // TODO: drop current_path comparison and instead use workspace: bool flag? // flatten the map to a vec of (url, diag) pairs @@ -163,59 +255,24 @@ fn diag_picker( for (url, diags) in diagnostics { flat_diag.reserve(diags.len()); for diag in diags { - flat_diag.push((url.clone(), diag)); + flat_diag.push(PickerDiagnostic { + url: url.clone(), + diag, + }); } } - let hint = cx.editor.theme.get("hint"); - let info = cx.editor.theme.get("info"); - let warning = cx.editor.theme.get("warning"); - let error = cx.editor.theme.get("error"); + let styles = DiagnosticStyles { + hint: cx.editor.theme.get("hint"), + info: cx.editor.theme.get("info"), + warning: cx.editor.theme.get("warning"), + error: cx.editor.theme.get("error"), + }; FilePicker::new( flat_diag, - move |(url, diag)| { - let mut style = diag - .severity - .map(|s| match s { - DiagnosticSeverity::HINT => hint, - DiagnosticSeverity::INFORMATION => info, - DiagnosticSeverity::WARNING => warning, - DiagnosticSeverity::ERROR => error, - _ => Style::default(), - }) - .unwrap_or_default(); - - // remove background as it is distracting in the picker list - style.bg = None; - - let code = diag - .code - .as_ref() - .map(|c| match c { - NumberOrString::Number(n) => n.to_string(), - NumberOrString::String(s) => s.to_string(), - }) - .unwrap_or_default(); - - let truncated_path = path::get_truncated_path(url.path()) - .to_string_lossy() - .into_owned(); - - Spans::from(vec![ - Span::styled( - diag.source.clone().unwrap_or_default(), - style.add_modifier(Modifier::BOLD), - ), - Span::raw(": "), - Span::styled(truncated_path, style), - Span::raw(" - "), - Span::styled(code, style.add_modifier(Modifier::BOLD)), - Span::raw(": "), - Span::styled(&diag.message, style), - ]) - }, - move |cx, (url, diag), action| { + styles, + move |cx, PickerDiagnostic { url, diag }, action| { if current_path.as_ref() == Some(url) { let (view, doc) = current!(cx.editor); push_jump(view, doc); @@ -233,7 +290,7 @@ fn diag_picker( align_view(doc, view, Align::Center); } }, - move |_editor, (url, diag)| { + move |_editor, PickerDiagnostic { url, diag }| { let location = lsp::Location::new(url.clone(), diag.range); Some(location_to_file_location(&location)) }, @@ -343,10 +400,11 @@ pub fn workspace_diagnostics_picker(cx: &mut Context) { } impl ui::menu::Item for lsp::CodeActionOrCommand { - fn label(&self) -> &str { + type Data = (); + fn label(&self, _data: &Self::Data) -> Spans { match self { - lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str(), - lsp::CodeActionOrCommand::Command(command) => command.title.as_str(), + lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str().into(), + lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(), } } } @@ -391,7 +449,7 @@ pub fn code_action(cx: &mut Context) { return; } - let mut picker = ui::Menu::new(actions, move |editor, code_action, event| { + let mut picker = ui::Menu::new(actions, (), move |editor, code_action, event| { if event != PromptEvent::Validate { return; } @@ -619,6 +677,7 @@ pub fn apply_workspace_edit( } } } + fn goto_impl( editor: &mut Editor, compositor: &mut Compositor, @@ -637,26 +696,7 @@ fn goto_impl( _locations => { let picker = FilePicker::new( locations, - move |location| { - let file: Cow<'_, str> = (location.uri.scheme() == "file") - .then(|| { - location - .uri - .to_file_path() - .map(|path| { - // strip root prefix - path.strip_prefix(&cwdir) - .map(|path| path.to_path_buf()) - .unwrap_or(path) - }) - .map(|path| Cow::from(path.to_string_lossy().into_owned())) - .ok() - }) - .flatten() - .unwrap_or_else(|| location.uri.as_str().into()); - let line = location.range.start.line; - format!("{}:{}", file, line).into() - }, + cwdir, move |cx, location, action| { jump_to_location(cx.editor, location, offset_encoding, action) }, diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index db95883308555..5920488981741 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -208,18 +208,17 @@ pub struct Keymap { root: KeyTrie, } +/// A map of command names to keybinds that will execute the command. +pub type ReverseKeymap = HashMap>>; + impl Keymap { pub fn new(root: KeyTrie) -> Self { Keymap { root } } - pub fn reverse_map(&self) -> HashMap>> { + pub fn reverse_map(&self) -> ReverseKeymap { // recursively visit all nodes in keymap - fn map_node( - cmd_map: &mut HashMap>>, - node: &KeyTrie, - keys: &mut Vec, - ) { + fn map_node(cmd_map: &mut ReverseKeymap, node: &KeyTrie, keys: &mut Vec) { match node { KeyTrie::Leaf(cmd) => match cmd { MappableCommand::Typable { name, .. } => { diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index 38005aad033b9..a36374154ac7a 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -2,6 +2,7 @@ use crate::compositor::{Component, Context, EventResult}; use crossterm::event::{Event, KeyCode, KeyEvent}; use helix_view::editor::CompleteAction; use tui::buffer::Buffer as Surface; +use tui::text::Spans; use std::borrow::Cow; @@ -15,19 +16,25 @@ use helix_lsp::{lsp, util}; use lsp::CompletionItem; impl menu::Item for CompletionItem { - fn sort_text(&self) -> &str { - self.filter_text.as_ref().unwrap_or(&self.label).as_str() + type Data = (); + fn sort_text(&self, data: &Self::Data) -> Cow { + self.filter_text(data) } - fn filter_text(&self) -> &str { - self.filter_text.as_ref().unwrap_or(&self.label).as_str() + #[inline] + fn filter_text(&self, _data: &Self::Data) -> Cow { + self.filter_text + .as_ref() + .unwrap_or(&self.label) + .as_str() + .into() } - fn label(&self) -> &str { - self.label.as_str() + fn label(&self, _data: &Self::Data) -> Spans { + self.label.as_str().into() } - fn row(&self) -> menu::Row { + fn row(&self, _data: &Self::Data) -> menu::Row { menu::Row::new(vec![ menu::Cell::from(self.label.as_str()), menu::Cell::from(match self.kind { @@ -85,7 +92,7 @@ impl Completion { start_offset: usize, trigger_offset: usize, ) -> Self { - let menu = Menu::new(items, move |editor: &mut Editor, item, event| { + let menu = Menu::new(items, (), move |editor: &mut Editor, item, event| { fn item_to_transaction( doc: &Document, item: &CompletionItem, diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index 0519374a3c634..6bb64139155a4 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -1,9 +1,11 @@ +use std::{borrow::Cow, path::PathBuf}; + use crate::{ compositor::{Callback, Component, Compositor, Context, EventResult}, ctrl, key, shift, }; use crossterm::event::Event; -use tui::{buffer::Buffer as Surface, widgets::Table}; +use tui::{buffer::Buffer as Surface, text::Spans, widgets::Table}; pub use tui::widgets::{Cell, Row}; @@ -14,22 +16,41 @@ use helix_view::{graphics::Rect, Editor}; use tui::layout::Constraint; pub trait Item { - fn label(&self) -> &str; + /// Additional editor state that is used for label calculation. + type Data; + + fn label(&self, data: &Self::Data) -> Spans; + + fn sort_text(&self, data: &Self::Data) -> Cow { + let label: String = self.label(data).into(); + label.into() + } - fn sort_text(&self) -> &str { - self.label() + fn filter_text(&self, data: &Self::Data) -> Cow { + let label: String = self.label(data).into(); + label.into() } - fn filter_text(&self) -> &str { - self.label() + + fn row(&self, data: &Self::Data) -> Row { + Row::new(vec![Cell::from(self.label(data))]) } +} - fn row(&self) -> Row { - Row::new(vec![Cell::from(self.label())]) +impl Item for PathBuf { + /// Root prefix to strip. + type Data = PathBuf; + + fn label(&self, root_path: &Self::Data) -> Spans { + self.strip_prefix(&root_path) + .unwrap_or(self) + .to_string_lossy() + .into() } } pub struct Menu { options: Vec, + editor_data: T::Data, cursor: Option, @@ -54,10 +75,12 @@ impl Menu { // rendering) pub fn new( options: Vec, + editor_data: ::Data, callback_fn: impl Fn(&mut Editor, Option<&T>, MenuEvent) + 'static, ) -> Self { let mut menu = Self { options, + editor_data, matcher: Box::new(Matcher::default()), matches: Vec::new(), cursor: None, @@ -83,16 +106,17 @@ impl Menu { .iter() .enumerate() .filter_map(|(index, option)| { - let text = option.filter_text(); + let text: String = option.filter_text(&self.editor_data).into(); // TODO: using fuzzy_indices could give us the char idx for match highlighting self.matcher - .fuzzy_match(text, pattern) + .fuzzy_match(&text, pattern) .map(|score| (index, score)) }), ); // matches.sort_unstable_by_key(|(_, score)| -score); - self.matches - .sort_unstable_by_key(|(index, _score)| self.options[*index].sort_text()); + self.matches.sort_unstable_by_key(|(index, _score)| { + self.options[*index].sort_text(&self.editor_data) + }); // reset cursor position self.cursor = None; @@ -127,10 +151,10 @@ impl Menu { let n = self .options .first() - .map(|option| option.row().cells.len()) + .map(|option| option.row(&self.editor_data).cells.len()) .unwrap_or_default(); let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| { - let row = option.row(); + let row = option.row(&self.editor_data); // maintain max for each column for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) { let width = cell.content.width(); @@ -300,7 +324,7 @@ impl Component for Menu { let scroll_line = (win_height - scroll_height) * scroll / std::cmp::max(1, len.saturating_sub(win_height)); - let rows = options.iter().map(|option| option.row()); + let rows = options.iter().map(|option| option.row(&self.editor_data)); let table = Table::new(rows) .style(style) .highlight_style(selected) diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 948a5f2b67dfd..8d2bd32511253 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -23,8 +23,6 @@ pub use text::Text; use helix_core::regex::Regex; use helix_core::regex::RegexBuilder; use helix_view::{Document, Editor, View}; -use tui; -use tui::text::Spans; use std::path::PathBuf; @@ -172,10 +170,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi FilePicker::new( files, - move |path: &PathBuf| { - // format_fn - Spans::from(path.strip_prefix(&root).unwrap_or(path).to_string_lossy()) - }, + root, move |cx, path: &PathBuf, action| { if let Err(e) = cx.editor.open(path, action) { let err = if let Some(err) = e.source() { diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 1581b0a15c3e4..01fea71867560 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -6,7 +6,6 @@ use crate::{ use crossterm::event::Event; use tui::{ buffer::Buffer as Surface, - text::Spans, widgets::{Block, BorderType, Borders}, }; @@ -30,6 +29,8 @@ use helix_view::{ Document, Editor, }; +use super::menu::Item; + pub const MIN_AREA_WIDTH_FOR_PREVIEW: u16 = 72; /// Biggest file size to preview in bytes pub const MAX_FILE_SIZE_FOR_PREVIEW: u64 = 10 * 1024 * 1024; @@ -37,7 +38,7 @@ pub const MAX_FILE_SIZE_FOR_PREVIEW: u64 = 10 * 1024 * 1024; /// File path and range of lines (used to align and highlight lines) pub type FileLocation = (PathBuf, Option<(usize, usize)>); -pub struct FilePicker { +pub struct FilePicker { picker: Picker, pub truncate_start: bool, /// Caches paths to documents @@ -84,15 +85,15 @@ impl Preview<'_, '_> { } } -impl FilePicker { +impl FilePicker { pub fn new( options: Vec, - format_fn: impl Fn(&T) -> Spans + 'static, + editor_data: T::Data, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, preview_fn: impl Fn(&Editor, &T) -> Option + 'static, ) -> Self { let truncate_start = true; - let mut picker = Picker::new(options, format_fn, callback_fn); + let mut picker = Picker::new(options, editor_data, callback_fn); picker.truncate_start = truncate_start; Self { @@ -163,7 +164,7 @@ impl FilePicker { } } -impl Component for FilePicker { +impl Component for FilePicker { fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { // +---------+ +---------+ // |prompt | |preview | @@ -280,8 +281,9 @@ impl Component for FilePicker { } } -pub struct Picker { +pub struct Picker { options: Vec, + editor_data: T::Data, // filter: String, matcher: Box, /// (index, score) @@ -299,14 +301,13 @@ pub struct Picker { /// Whether to truncate the start (default true) pub truncate_start: bool, - format_fn: Box Spans>, callback_fn: Box, } -impl Picker { +impl Picker { pub fn new( options: Vec, - format_fn: impl Fn(&T) -> Spans + 'static, + editor_data: T::Data, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, ) -> Self { let prompt = Prompt::new( @@ -318,6 +319,7 @@ impl Picker { let mut picker = Self { options, + editor_data, matcher: Box::new(Matcher::default()), matches: Vec::new(), filters: Vec::new(), @@ -325,7 +327,6 @@ impl Picker { prompt, previous_pattern: String::new(), truncate_start: true, - format_fn: Box::new(format_fn), callback_fn: Box::new(callback_fn), completion_height: 0, }; @@ -371,9 +372,9 @@ impl Picker { #[allow(unstable_name_collisions)] self.matches.retain_mut(|(index, score)| { let option = &self.options[*index]; - // TODO: maybe using format_fn isn't the best idea here - let line: String = (self.format_fn)(option).into(); - match self.matcher.fuzzy_match(&line, pattern) { + let text = option.sort_text(&self.editor_data); + + match self.matcher.fuzzy_match(&text, pattern) { Some(s) => { // Update the score *score = s; @@ -399,11 +400,10 @@ impl Picker { self.filters.binary_search(&index).ok()?; } - // TODO: maybe using format_fn isn't the best idea here - let line: String = (self.format_fn)(option).into(); + let text = option.filter_text(&self.editor_data); self.matcher - .fuzzy_match(&line, pattern) + .fuzzy_match(&text, pattern) .map(|score| (index, score)) }), ); @@ -477,7 +477,7 @@ impl Picker { // - on input change: // - score all the names in relation to input -impl Component for Picker { +impl Component for Picker { fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { self.completion_height = viewport.1.saturating_sub(4); Some(viewport) @@ -610,7 +610,7 @@ impl Component for Picker { surface.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected); } - let spans = (self.format_fn)(option); + let spans = option.label(&self.editor_data); let (_score, highlights) = self .matcher .fuzzy_indices(&String::from(&spans), self.prompt.line()) diff --git a/helix-tui/src/text.rs b/helix-tui/src/text.rs index b4278c864b307..602090e557efe 100644 --- a/helix-tui/src/text.rs +++ b/helix-tui/src/text.rs @@ -402,6 +402,12 @@ impl<'a> From<&'a str> for Text<'a> { } } +impl<'a> From> for Text<'a> { + fn from(s: Cow<'a, str>) -> Text<'a> { + Text::raw(s) + } +} + impl<'a> From> for Text<'a> { fn from(span: Span<'a>) -> Text<'a> { Text { From 9f43dbc45d254ff860f7d33db201b2f0a6073195 Mon Sep 17 00:00:00 2001 From: ChrHorn Date: Sat, 2 Jul 2022 13:59:46 +0200 Subject: [PATCH 072/584] Highlight whole row in picker menus (#2939) --- helix-term/src/ui/picker.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 01fea71867560..f4dd234a44d67 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -607,7 +607,16 @@ impl Component for Picker { for (i, (_index, option)) in files.take(rows as usize).enumerate() { let is_active = i == (self.cursor - offset); if is_active { - surface.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected); + surface.set_string( + inner.x.saturating_sub(3), + inner.y + i as u16, + " > ", + selected, + ); + surface.set_style( + Rect::new(inner.x, inner.y + i as u16, inner.width, 1), + selected, + ); } let spans = option.label(&self.editor_data); From 4c30a3609aa8fbcca97609d281f5df449c234674 Mon Sep 17 00:00:00 2001 From: rsteube Date: Sun, 3 Jul 2022 23:19:12 +0200 Subject: [PATCH 073/584] languages: added elvish (#2948) --- book/src/generated/lang-support.md | 1 + languages.toml | 14 +++++ runtime/queries/elvish/highlights.scm | 76 +++++++++++++++++++++++++++ runtime/queries/elvish/injections.scm | 2 + 4 files changed, 93 insertions(+) create mode 100644 runtime/queries/elvish/highlights.scm create mode 100644 runtime/queries/elvish/injections.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index c82a6443bff45..3c56a6f40ad65 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -18,6 +18,7 @@ | ejs | ✓ | | | | | elixir | ✓ | ✓ | | `elixir-ls` | | elm | ✓ | | | `elm-language-server` | +| elvish | ✓ | | | `elvish` | | erb | ✓ | | | | | erlang | ✓ | ✓ | | `erlang_ls` | | fish | ✓ | ✓ | ✓ | | diff --git a/languages.toml b/languages.toml index 0b4a1dec545a4..c9ecc76fdabac 100644 --- a/languages.toml +++ b/languages.toml @@ -1489,3 +1489,17 @@ roots = [] comment-token = "#" indent = { tab-width = 4, unit = " " } grammar = "python" + +[[language]] +name = "elvish" +scope = "source.elvish" +file-types = ["elv"] +roots = [] +comment-token = "#" +indent = { tab-width = 2, unit = " " } +language-server = { command = "elvish", args = ["-lsp"] } +grammar = "elvish" + +[[grammar]] +name = "elvish" +source = { git = "https://github.com/ckafi/tree-sitter-elvish", rev = "e50787cadd3bc54f6d9c0704493a79078bb8a4e5" } diff --git a/runtime/queries/elvish/highlights.scm b/runtime/queries/elvish/highlights.scm new file mode 100644 index 0000000000000..fd70488dfb3da --- /dev/null +++ b/runtime/queries/elvish/highlights.scm @@ -0,0 +1,76 @@ +;; SPDX-License-Identifier: 0BSD +;; SPDX-FileCopyrightText: 2022 Tobias Frilling + +(comment) @comment + +(if "if" @keyword.control.conditional) +(if (elif "elif" @keyword.control.conditional)) +(if (else "else" @keyword.control.conditional)) + +(while "while" @keyword.control.repeat) +(while (else "else" @keyword.control.repeat)) +(for "for" @keyword.control.repeat) +(for (else "else" @keyword.control.repeat)) + +(try "try" @keyword.control.exception) +(try (catch "catch" @keyword.control.exception)) +(try (else "else" @keyword.control.exception)) +(try (finally "finally" @keyword.control.exception)) + +(import "use" @keyword.control.import) +(import (bareword) @string.special) + +(wildcard ["*" "**" "?"] @string.special) + +(command argument: (bareword) @variable.parameter) +(command head: (identifier) @function) +((command head: (identifier) @keyword.control.return) + (#eq? @keyword.control.return "return")) +((command (identifier) @keyword.operator) + (#match? @keyword.operator "(and|or|coalesce)")) +((command head: _ @function) + (#match? @function "([+]|[-]|[*]|[/]|[%]|[<]|[<][=]|[=][=]|[!][=]|[>]|[>][=]|[<][s]|[<][=][s]|[=][=][s]|[!][=][s]|[>][s]|[>][=][s])")) + +(pipeline "|" @operator) +(redirection [">" "<" ">>" "<>"] @operator) + +(io_port) @constant.numeric + +(function_definition + "fn" @keyword.function + (identifier) @function) + +(parameter_list) @variable.parameter +(parameter_list "|" @punctuation.bracket) + +(variable_declaration + "var" @keyword + (lhs (identifier) @variable)) + +(variable_assignment + "set" @keyword + (lhs (identifier) @variable)) + +(temporary_assignment + "tmp" @keyword + (lhs (identifier) @variable)) + +(variable_deletion + "del" @keyword + (identifier) @variable) + + +(number) @constant.numeric +(string) @string + +((variable (identifier) @function) + (#match? @function ".+\\~$")) +((variable (identifier) @constant.builtin.boolean) + (#match? @constant.builtin.boolean "(true|false)")) +((variable (identifier) @constant.builtin) + (#match? @constant.builtin "(_|after-chdir|args|before-chdir|buildinfo|nil|notify-bg-job-success|num-bg-jobs|ok|paths|pid|pwd|value-out-indicator|version)")) +(variable (identifier) @variable) + +["$" "@"] @punctuation.special +["(" ")" "[" "]" "{" "}"] @punctuation.bracket +";" @punctuation.delimiter diff --git a/runtime/queries/elvish/injections.scm b/runtime/queries/elvish/injections.scm new file mode 100644 index 0000000000000..321c90add3710 --- /dev/null +++ b/runtime/queries/elvish/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) From e58d28a9728fd5d451c98c48bd20c57fb9eec7dc Mon Sep 17 00:00:00 2001 From: 0rphee <79347623+0rphee@users.noreply.github.com> Date: Sun, 3 Jul 2022 22:44:17 -0500 Subject: [PATCH 074/584] Add Haskell roots (#2954) --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index c9ecc76fdabac..7c63c051ab11a 100644 --- a/languages.toml +++ b/languages.toml @@ -660,7 +660,7 @@ name = "haskell" scope = "source.haskell" injection-regex = "haskell" file-types = ["hs"] -roots = [] +roots = ["Setup.hs", "stack.yaml", "*.cabal"] comment-token = "--" language-server = { command = "haskell-language-server-wrapper", args = ["--lsp"] } indent = { tab-width = 2, unit = " " } From 244825b9e1959939e1c08fe942a288d10eb6da69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=9D=E7=94=B0=20=E6=81=B5=E6=B0=8F=20=28Kawada=20Keis?= =?UTF-8?q?hi=20a=2Ek=2Ea=20megumish=29?= Date: Tue, 5 Jul 2022 02:32:46 +0900 Subject: [PATCH 075/584] Add runtime `xcopy` command on powershell in docs (#2958) --- README.md | 9 +++++---- book/src/install.md | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 032ecf6759610..48c24de7c7547 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,11 @@ tree-sitter grammars may be manually fetched and built with `hx --grammar fetch` Helix also needs its runtime files so make sure to copy/symlink the `runtime/` directory into the config directory (for example `~/.config/helix/runtime` on Linux/macOS, or `%AppData%/helix/runtime` on Windows). -| OS | command | -|-----------|-----------| -|windows |`xcopy runtime %AppData%/helix/runtime`| -|linux/macos|`ln -s $PWD/runtime ~/.config/helix/runtime` +| OS | command | +|-------------------|-----------| +|windows(cmd.exe) |`xcopy runtime %AppData%/helix/runtime` | +|windows(powershell)|`xcopy runtime $Env:AppData\helix\runtime` | +|linux/macos |`ln -s $PWD/runtime ~/.config/helix/runtime`| This location can be overridden via the `HELIX_RUNTIME` environment variable. diff --git a/book/src/install.md b/book/src/install.md index bf59ea2345efd..045e225563ea3 100644 --- a/book/src/install.md +++ b/book/src/install.md @@ -61,10 +61,11 @@ Helix also needs it's runtime files so make sure to copy/symlink the `runtime/` config directory (for example `~/.config/helix/runtime` on Linux/macOS). This location can be overridden via the `HELIX_RUNTIME` environment variable. -| OS | command | -|-----------|-----------| -|windows |`xcopy runtime %AppData%/helix/runtime`| -|linux/macos|`ln -s $PWD/runtime ~/.config/helix/runtime` +| OS | command | +|-------------------|-----------| +|windows(cmd.exe) |`xcopy runtime %AppData%/helix/runtime` | +|windows(powershell)|`xcopy runtime $Env:AppData\helix\runtime` | +|linux/macos |`ln -s $PWD/runtime ~/.config/helix/runtime`| ## Finishing up the installation From 2ac1de305e10238a2e7ed8c0d66f3fa78566dbaa Mon Sep 17 00:00:00 2001 From: A-Walrus <58790821+A-Walrus@users.noreply.github.com> Date: Tue, 5 Jul 2022 01:51:15 +0300 Subject: [PATCH 076/584] Fix backwards selection duplication widening bug (#2945) * Fix backwards selection duplication widening bug * Add integration tests * Make tests line-ending agnostic Make tests line-ending agnostic Use indoc to fix tests Fix line-ending on test input --- helix-term/src/commands.rs | 8 +++---- helix-term/tests/test/commands.rs | 40 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index df4867fc76c5c..c9e350628e533 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1411,16 +1411,16 @@ fn copy_selection_on_line(cx: &mut Context, direction: Direction) { let is_primary = *range == selection.primary(); // The range is always head exclusive - let head = if range.anchor < range.head { - range.head - 1 + let (head, anchor) = if range.anchor < range.head { + (range.head - 1, range.anchor) } else { - range.head + (range.head, range.anchor - 1) }; let tab_width = doc.tab_width(); let head_pos = visual_coords_at_pos(text, head, tab_width); - let anchor_pos = visual_coords_at_pos(text, range.anchor, tab_width); + let anchor_pos = visual_coords_at_pos(text, anchor, tab_width); let height = std::cmp::max(head_pos.row, anchor_pos.row) - std::cmp::min(head_pos.row, anchor_pos.row) diff --git a/helix-term/tests/test/commands.rs b/helix-term/tests/test/commands.rs index 0cd79bc7f3070..f7ce9af081710 100644 --- a/helix-term/tests/test/commands.rs +++ b/helix-term/tests/test/commands.rs @@ -91,3 +91,43 @@ async fn test_buffer_close_concurrent() -> anyhow::Result<()> { Ok(()) } + +#[tokio::test] +async fn test_selection_duplication() -> anyhow::Result<()> { + // Forward + test(( + platform_line(indoc! {"\ + #[lo|]#rem + ipsum + dolor + "}) + .as_str(), + "CC", + platform_line(indoc! {"\ + #(lo|)#rem + #(ip|)#sum + #[do|]#lor + "}) + .as_str(), + )) + .await?; + + // Backward + test(( + platform_line(indoc! {"\ + #[|lo]#rem + ipsum + dolor + "}) + .as_str(), + "CC", + platform_line(indoc! {"\ + #(|lo)#rem + #(|ip)#sum + #[|do]#lor + "}) + .as_str(), + )) + .await?; + Ok(()) +} From f392e354399c5158ad5e6d94b7170ac5040f30c6 Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Mon, 4 Jul 2022 19:06:44 -0400 Subject: [PATCH 077/584] feat(theme): solarized: add cursorline, ruler, indent guide (#2962) --- runtime/themes/solarized_dark.toml | 7 +++++++ runtime/themes/solarized_light.toml | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/runtime/themes/solarized_dark.toml b/runtime/themes/solarized_dark.toml index 002e99bc701d7..aa6dbbf8dbec6 100644 --- a/runtime/themes/solarized_dark.toml +++ b/runtime/themes/solarized_dark.toml @@ -80,9 +80,15 @@ # 主光标/selectio "ui.cursor.primary" = { fg = "base03", bg = "base1" } "ui.cursor.select" = { fg = "base02", bg = "cyan" } +"ui.cursorline.primary" = { bg = "base02" } +"ui.cursorline.secondary" = { bg = "base025" } + "ui.selection" = { bg = "base0175" } "ui.selection.primary" = { bg = "base015" } +"ui.virtual.indent-guide" = { fg = "base02" } +"ui.virtual.ruler" = { fg = "red" } + # normal模式的光标 "ui.cursor" = {fg = "base02", bg = "cyan"} "ui.cursor.insert" = {fg = "base03", bg = "base3"} @@ -98,6 +104,7 @@ [palette] # 深色 越来越深 base03 = "#002b36" +base025 = "#03303b" base02 = "#073642" base0175 = "#16404b" base015 = "#2c4f59" diff --git a/runtime/themes/solarized_light.toml b/runtime/themes/solarized_light.toml index fa58cc8cfc580..79fd83642da49 100644 --- a/runtime/themes/solarized_light.toml +++ b/runtime/themes/solarized_light.toml @@ -94,9 +94,16 @@ # main cursor/selection "ui.cursor.primary" = { fg = "base03", bg = "base1" } "ui.cursor.select" = { fg = "base02", bg = "cyan" } + +"ui.cursorline.primary" = { bg = "base02" } +"ui.cursorline.secondary" = { bg = "base025" } + "ui.selection" = { bg = "base0175" } "ui.selection.primary" = { bg = "base015" } +"ui.virtual.indent-guide" = { fg = "base02" } +"ui.virtual.ruler" = { fg = "red" } + # normal模式的光标 # normal mode cursor "ui.cursor" = {fg = "base02", bg = "cyan"} @@ -135,4 +142,5 @@ base01 = '#93a1a1' base015 = '#c5c8bd' base0175 = '#dddbcc' base02 = '#eee8d5' +base025 = '#f5eedb' base03 = '#fdf6e3' From a679efa8ce068ffa8f62b164f4a6ce958f6bb99c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 08:20:12 +0530 Subject: [PATCH 078/584] build(deps): bump serde from 1.0.136 to 1.0.138 (#2967) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.138. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.138) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d94b6d7bdfb1..cfcb9fe02052a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -772,11 +772,11 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -916,18 +916,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" dependencies = [ "proc-macro2", "quote", @@ -1072,13 +1072,13 @@ checksum = "9d9199fa80c817e074620be84374a520062ebac833f358d74b37060ce4a0f2c0" [[package]] name = "syn" -version = "1.0.86" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1241,6 +1241,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1218098468b8085b19a2824104c70d976491d247ce194bbd9dc77181150cdfd6" +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + [[package]] name = "unicode-linebreak" version = "0.1.2" @@ -1271,12 +1277,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "url" version = "2.2.2" From c88d736d5c1384f0d3391295a4876892d79dba51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 11:04:03 +0800 Subject: [PATCH 079/584] build(deps): bump once_cell from 1.12.0 to 1.13.0 (#2969) Bumps [once_cell](https://github.com/matklad/once_cell) from 1.12.0 to 1.13.0. - [Release notes](https://github.com/matklad/once_cell/releases) - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.12.0...v1.13.0) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- helix-core/Cargo.toml | 2 +- helix-loader/Cargo.toml | 2 +- helix-term/Cargo.toml | 2 +- helix-view/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cfcb9fe02052a..a4720f71213d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -725,9 +725,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "parking_lot" diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index 5eb3b621a6857..3ce0e48321706 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -26,7 +26,7 @@ unicode-general-category = "0.5" # slab = "0.4.2" slotmap = "1.0" tree-sitter = "0.20" -once_cell = "1.12" +once_cell = "1.13" arc-swap = "1" regex = "1" diff --git a/helix-loader/Cargo.toml b/helix-loader/Cargo.toml index 3d8a697cc5c8f..46144a30953aa 100644 --- a/helix-loader/Cargo.toml +++ b/helix-loader/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0", features = ["derive"] } toml = "0.5" etcetera = "0.4" tree-sitter = "0.20" -once_cell = "1.12" +once_cell = "1.13" log = "0.4" # TODO: these two should be on !wasm32 only diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index 3da5a74ec2d46..29c34e4040a48 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -31,7 +31,7 @@ helix-dap = { version = "0.6", path = "../helix-dap" } helix-loader = { version = "0.6", path = "../helix-loader" } anyhow = "1" -once_cell = "1.12" +once_cell = "1.13" which = "4.2" diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index 77634ce583bb5..6d0811ba563bb 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -22,7 +22,7 @@ helix-dap = { version = "0.6", path = "../helix-dap" } crossterm = { version = "0.23", optional = true } # Conversion traits -once_cell = "1.12" +once_cell = "1.13" url = "2" arc-swap = { version = "1.5.0" } From 700431d6652988784d7914c501451ef9d2fbae15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:19:27 +0900 Subject: [PATCH 080/584] build(deps): bump encoding_rs from 0.8.30 to 0.8.31 (#2963) Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.30 to 0.8.31. - [Release notes](https://github.com/hsivonen/encoding_rs/releases) - [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.30...v0.8.31) --- updated-dependencies: - dependency-name: encoding_rs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4720f71213d0..7617d2dbe9fde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,9 +184,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.30" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if", ] From b98567f248cbdc623b3fea03b8193542173a74c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:24:07 +0900 Subject: [PATCH 081/584] build(deps): bump which from 4.2.4 to 4.2.5 (#2964) Bumps [which](https://github.com/harryfei/which-rs) from 4.2.4 to 4.2.5. - [Release notes](https://github.com/harryfei/which-rs/releases) - [Commits](https://github.com/harryfei/which-rs/compare/4.2.4...4.2.5) --- updated-dependencies: - dependency-name: which dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7617d2dbe9fde..2c2d8f5f35e93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1321,9 +1321,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "4.2.4" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" dependencies = [ "either", "lazy_static", From 1fc8cbeb688c25b17f6471a9688cf78df07c4581 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:24:37 +0900 Subject: [PATCH 082/584] build(deps): bump log from 0.4.14 to 0.4.17 (#2965) Bumps [log](https://github.com/rust-lang/log) from 0.4.14 to 0.4.17. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.14...0.4.17) --- updated-dependencies: - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c2d8f5f35e93..7e81b4648fd81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,9 +610,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] From ba255e3e3e550e1e3bac95e592e6c7df7746a4de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:25:56 +0900 Subject: [PATCH 083/584] build(deps): bump serde_json from 1.0.81 to 1.0.82 (#2966) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.81...v1.0.82) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e81b4648fd81..c11429c102f69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,9 +936,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "itoa", "ryu", From f3467399b7a454a6fc8f42a87f898e37a6c0abad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:30:33 +0900 Subject: [PATCH 084/584] build(deps): bump crossterm from 0.23.0 to 0.24.0 (#2968) Bumps [crossterm](https://github.com/crossterm-rs/crossterm) from 0.23.0 to 0.24.0. - [Release notes](https://github.com/crossterm-rs/crossterm/releases) - [Changelog](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossterm-rs/crossterm/compare/0.23...0.24) --- updated-dependencies: - dependency-name: crossterm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 45 +++++++------------------------------------ helix-term/Cargo.toml | 2 +- helix-tui/Cargo.toml | 2 +- helix-view/Cargo.toml | 2 +- 4 files changed, 10 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c11429c102f69..f3b2bc8e759a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,15 +131,15 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b75a27dc8d220f1f8521ea69cd55a34d720a200ebb3a624d9aa19193d3b432" +checksum = "ab9f7409c70a38a56216480fba371ee460207dd8926ccf5b4160591759559170" dependencies = [ "bitflags", "crossterm_winapi", "futures-core", "libc", - "mio 0.7.14", + "mio", "parking_lot", "signal-hook", "signal-hook-mio", @@ -651,19 +651,6 @@ dependencies = [ "libc", ] -[[package]] -name = "mio" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "winapi", -] - [[package]] name = "mio" version = "0.8.3" @@ -676,24 +663,6 @@ dependencies = [ "windows-sys 0.36.1", ] -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - [[package]] name = "num-integer" version = "0.1.44" @@ -968,12 +937,12 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" dependencies = [ "libc", - "mio 0.7.14", + "mio", "signal-hook", ] @@ -1168,7 +1137,7 @@ dependencies = [ "bytes", "libc", "memchr", - "mio 0.8.3", + "mio", "num_cpus", "once_cell", "parking_lot", diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index 29c34e4040a48..4c2c2da72ad04 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -37,7 +37,7 @@ which = "4.2" tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] } tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] } -crossterm = { version = "0.23", features = ["event-stream"] } +crossterm = { version = "0.24", features = ["event-stream"] } signal-hook = "0.3" tokio-stream = "0.1" futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false } diff --git a/helix-tui/Cargo.toml b/helix-tui/Cargo.toml index e4cfbe4cdf409..25e32b500003c 100644 --- a/helix-tui/Cargo.toml +++ b/helix-tui/Cargo.toml @@ -19,7 +19,7 @@ default = ["crossterm"] bitflags = "1.3" cassowary = "0.3" unicode-segmentation = "1.9" -crossterm = { version = "0.23", optional = true } +crossterm = { version = "0.24", optional = true } serde = { version = "1", "optional" = true, features = ["derive"]} helix-view = { version = "0.6", path = "../helix-view", features = ["term"] } helix-core = { version = "0.6", path = "../helix-core" } diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index 6d0811ba563bb..91921dd3ce68e 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -19,7 +19,7 @@ anyhow = "1" helix-core = { version = "0.6", path = "../helix-core" } helix-lsp = { version = "0.6", path = "../helix-lsp" } helix-dap = { version = "0.6", path = "../helix-dap" } -crossterm = { version = "0.23", optional = true } +crossterm = { version = "0.24", optional = true } # Conversion traits once_cell = "1.13" From f3e8b0f34bcf4a66dabeef40998442ef8f95967a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:31:01 +0900 Subject: [PATCH 085/584] build(deps): bump smallvec from 1.8.1 to 1.9.0 (#2976) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.8.1 to 1.9.0. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.8.1...v1.9.0) --- updated-dependencies: - dependency-name: smallvec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- helix-core/Cargo.toml | 2 +- helix-term/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3b2bc8e759a2..00d8c47550d53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -990,9 +990,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "smartstring" diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index 3ce0e48321706..b7a1f33230d31 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -18,7 +18,7 @@ integration = [] helix-loader = { version = "0.6", path = "../helix-loader" } ropey = { version = "1.5", default-features = false, features = ["simd"] } -smallvec = "1.8" +smallvec = "1.9" smartstring = "1.0.1" unicode-segmentation = "1.9" unicode-width = "0.1" diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index 4c2c2da72ad04..c94e6502f4b60 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -76,6 +76,6 @@ signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } helix-loader = { version = "0.6", path = "../helix-loader" } [dev-dependencies] -smallvec = "1.8" +smallvec = "1.9" indoc = "1.0.6" tempfile = "3.3.0" From 2e709859c4ab35237374e3c8e64c9d3767be4134 Mon Sep 17 00:00:00 2001 From: Jens Getreu Date: Tue, 5 Jul 2022 08:08:35 +0200 Subject: [PATCH 086/584] Autumn theme: slightly adjust contrast --- runtime/themes/autumn.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/themes/autumn.toml b/runtime/themes/autumn.toml index d96d32eaa76a3..024ca650121cc 100644 --- a/runtime/themes/autumn.toml +++ b/runtime/themes/autumn.toml @@ -69,13 +69,13 @@ "error" = "my_red" [palette] -my_black = "#242424" # Cursorline -my_gray0 = "#292929" # Default Background -my_gray1 = "#2e2e2e" # Ruler -my_gray2 = "#3a3a3a" # Lighter Background (Used for status bars, line number and folding marks) -my_gray3 = "#525252" # Selection Background +my_black = "#212121" # Cursorline +my_gray0 = "#262626" # Default Background +my_gray1 = "#2b2b2b" # Ruler +my_gray2 = "#323232" # Lighter Background (Used for status bars, line number and folding marks) +my_gray3 = "#505050" # Selection Background my_gray4 = "#7c7c7c" # Comments, Invisibles, Line Highlighting -my_gray5 = "#aaaaaa" # Dark Foreground (Used for status bars) +my_gray5 = "#a8a8a8" # Dark Foreground (Used for status bars) my_gray6 = "#c0c0c0" # Light Foreground (Not often used) my_gray7 = "#e8e8e8" # Light Background (Not often used) my_white = "#F3F2CC" # Default Foreground, Caret, Delimiters, Operators From 936ed3a226a5b94c470f5b40ad7df1b0a3ae4793 Mon Sep 17 00:00:00 2001 From: Jens Getreu Date: Tue, 5 Jul 2022 08:21:33 +0200 Subject: [PATCH 087/584] Add Autumn night theme Under some light conditions, one prefers a high contrast theme. --- runtime/themes/autumn_night.toml | 90 ++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 runtime/themes/autumn_night.toml diff --git a/runtime/themes/autumn_night.toml b/runtime/themes/autumn_night.toml new file mode 100644 index 0000000000000..381e21d982010 --- /dev/null +++ b/runtime/themes/autumn_night.toml @@ -0,0 +1,90 @@ +# The structure is based on `base16_default_dark` by Ray Gervais. Most of +# the colors come from the so called Autumn theme, a color scheme inspired by +# the colors you can find in the autumn. Originally it was designed as a +# color scheme for the Komodo IDE and then ported to Vim by Kenneth Love +# and Chris Jones. Later, Yorick Peterse improved their work. See: +# +# Jens Getreu ported and optimised the color theme for the Helix editor. +# Author: Jens Getreu + +"ui.background" = { bg = "my_gray0" } +"ui.menu" = { fg = "my_white", bg = "my_gray2" } +"ui.menu.selected" = { fg = "my_gray2", bg = "my_gray5" } +"ui.linenr" = { fg = "my_gray4", bg = "my_gray2" } +"ui.popup" = { bg = "my_gray2" } +"ui.window" = { fg = "my_gray4", bg = "my_gray2" } +"ui.linenr.selected" = { fg = "my_gray6", bg = "my_gray1"} +"ui.selection" = { bg = "my_gray3" } +"comment" = { fg = "my_gray4", modifiers = ["italic"] } +"ui.statusline" = { fg = "my_gray6", bg = "my_gray2" } +"ui.statusline.inactive" = { fg = 'my_gray4', bg = 'my_gray2' } +"ui.statusline.insert" = {fg = "my_black", bg = "my_gray5", modifiers = ["bold"]} +"ui.statusline.normal" = {fg = "my_gray6", bg = "my_gray2"} +"ui.statusline.select" = {fg = "my_gray6", bg = "my_black", modifiers = ["bold"]} +"ui.cursor" = { fg = "my_gray5", modifiers = ["reversed"] } +"ui.cursor.primary" = { fg = "my_white", modifiers = ["reversed"] } +"ui.cursorline.primary" = { bg = "my_black" } +"ui.cursorline.secondary" = { bg = "my_black" } +"ui.text" = "my_white" +"operator" = "my_white" +"ui.text.focus" = "my_white" +"variable" = "my_white3" +"constant.numeric" = "my_turquoise" +"constant" = "my_white3" +"attributes" = "my_turquoise" +"type" = { fg = "my_white3", modifiers = ["italic"] } +"ui.cursor.match" = { fg = "my_white3", modifiers = ["underlined"] } +"string" = "my_green" +"variable.other.member" = "my_brown" +"constant.character.escape" = "my_turquoise" +"function" = "my_yellow1" +"constructor" = "my_yellow1" +"special" = "my_yellow1" +"keyword" = "my_red" +"label" = "my_red" +"namespace" = "my_white3" +"ui.help" = { fg = "my_gray6", bg = "my_gray2" } +"ui.virtual.whitespace" = { fg = "my_gray5" } +"ui.virtual.ruler" = { bg = "my_gray1" } + +"markup.heading" = "my_yellow1" +"markup.list" = "my_white2" +"markup.bold" = { modifiers = ["bold"] } +"markup.italic" = { modifiers = ["italic"] } +"markup.link.url" = "my_turquoise2" +"markup.link.text" = "my_white2" +"markup.quote" = "my_brown" +"markup.raw" = "my_green" + +"diff.plus" = "my_green" +"diff.delta" = "my_white" +"diff.minus" = "my_red" + +"diagnostic" = { modifiers = ["underlined"] } +"ui.gutter" = { bg = "my_gray2" } +"hint" = "my_gray5" +"debug" = "my_yellow2" +"info" = "my_yellow2" +"warning" = "my_yellow2" +"error" = "my_red" + +[palette] +my_black = "#111111" # Cursorline +my_gray0 = "#090909" # Default Background +my_gray1 = "#0e0e0e" # Ruler +my_gray2 = "#1a1a1a" # Lighter Background (Used for status bars, line number and folding marks) +my_gray3 = "#323232" # Selection Background +my_gray4 = "#7c7c7c" # Comments, Invisibles, Line Highlighting +my_gray5 = "#aaaaaa" # Dark Foreground (Used for status bars) +my_gray6 = "#c0c0c0" # Light Foreground (Not often used) +my_gray7 = "#e8e8e8" # Light Background (Not often used) +my_white = "#F3F2CC" # Default Foreground, Caret, Delimiters, Operators +my_white2 = "#F3F2CC" # Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +my_white3 = "#F3F2CC" # Classes, Markup Bold, Search Text Background +my_turquoise = "#86c1b9" # Support, Regular Expressions, Escape Characters +my_turquoise2 = "#72a59e" # URL +my_green = "#99be70" # Strings, Inherited Class, Markup Code, Diff Inserted +my_brown = "#cfba8b" # Member variables, Quotes +my_yellow1 = "#FAD566" # Functions, Methods, Attribute IDs, Headings +my_yellow2 = "#ffff9f" # Debug, Info +my_red = "#F05E48" # Keywords, Storage, Selector, Diff Changed From 44f596334aeda7c540fbe12d2653c86dae686470 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 4 Jul 2022 09:30:36 -0500 Subject: [PATCH 088/584] DAP: Skip serializing `Option`s when `None` DAP follows the same strict TypeScript interface syntax as LSP which states: > The document uses TypeScript interfaces in strict mode to describe > these. This means for example that a `null` value has to be explicitly > listed and that a mandatory property must be listed even if a falsify > value might exist. So we have to skip serializing any fields that end in `?` instead of passing `null`. --- helix-dap/src/types.rs | 174 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 6 deletions(-) diff --git a/helix-dap/src/types.rs b/helix-dap/src/types.rs index fd8456a430e5d..71b2aa8347a3c 100644 --- a/helix-dap/src/types.rs +++ b/helix-dap/src/types.rs @@ -27,9 +27,11 @@ pub trait Request { pub struct ColumnDescriptor { pub attribute_name: String, pub label: String, + #[serde(skip_serializing_if = "Option::is_none")] pub format: Option, - #[serde(rename = "type")] + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub ty: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub width: Option, } @@ -38,52 +40,94 @@ pub struct ColumnDescriptor { pub struct ExceptionBreakpointsFilter { pub filter: String, pub label: String, + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub default: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_condition: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub condition_description: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct DebuggerCapabilities { + #[serde(skip_serializing_if = "Option::is_none")] pub supports_configuration_done_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_function_breakpoints: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_conditional_breakpoints: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_hit_conditional_breakpoints: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_evaluate_for_hovers: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_step_back: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_set_variable: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_restart_frame: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_goto_targets_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_step_in_targets_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_completions_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_modules_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_restart_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_exception_options: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_value_formatting_options: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_exception_info_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub support_terminate_debuggee: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub support_suspend_debuggee: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_delayed_stack_trace_loading: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_loaded_sources_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_log_points: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_terminate_threads_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_set_expression: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_terminate_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_data_breakpoints: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_read_memory_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_write_memory_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_disassemble_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_cancel_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_breakpoint_locations_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_clipboard_context: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_stepping_granularity: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_instruction_breakpoints: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_exception_filter_options: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub exception_breakpoint_filters: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub completion_trigger_characters: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub additional_module_columns: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub supported_checksum_algorithms: Option>, } @@ -97,13 +141,21 @@ pub struct Checksum { #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Source { + #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub source_reference: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub presentation_hint: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub origin: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub sources: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub adapter_data: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub checksums: Option>, } @@ -111,36 +163,56 @@ pub struct Source { #[serde(rename_all = "camelCase")] pub struct SourceBreakpoint { pub line: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub condition: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub hit_condition: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub log_message: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Breakpoint { + #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, pub verified: bool, + #[serde(skip_serializing_if = "Option::is_none")] pub message: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub end_line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub end_column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub instruction_reference: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub offset: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct StackFrameFormat { + #[serde(skip_serializing_if = "Option::is_none")] pub parameters: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub parameter_types: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub parameter_names: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub parameter_values: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub module: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub include_all: Option, } @@ -149,14 +221,21 @@ pub struct StackFrameFormat { pub struct StackFrame { pub id: usize, pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, pub line: usize, pub column: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub end_line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub end_column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub can_restart: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub instruction_pointer_reference: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub module_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub presentation_hint: Option, } @@ -171,29 +250,41 @@ pub struct Thread { #[serde(rename_all = "camelCase")] pub struct Scope { pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] pub presentation_hint: Option, pub variables_reference: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub named_variables: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub indexed_variables: Option, pub expensive: bool, + #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub end_line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub end_column: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ValueFormat { + #[serde(skip_serializing_if = "Option::is_none")] pub hex: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct VariablePresentationHint { + #[serde(skip_serializing_if = "Option::is_none")] pub kind: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub attributes: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub visibility: Option, } @@ -202,13 +293,18 @@ pub struct VariablePresentationHint { pub struct Variable { pub name: String, pub value: String, - #[serde(rename = "type")] + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub ty: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub presentation_hint: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub evaluate_name: Option, pub variables_reference: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub named_variables: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub indexed_variables: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub memory_reference: Option, } @@ -217,13 +313,21 @@ pub struct Variable { pub struct Module { pub id: String, // TODO: || number pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub is_optimized: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub is_user_code: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub version: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub symbol_status: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub symbol_file_path: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub date_time_stamp: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub address_range: Option, } @@ -232,22 +336,31 @@ pub mod requests { #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct InitializeArguments { - #[serde(rename = "clientID")] + #[serde(rename = "clientID", skip_serializing_if = "Option::is_none")] pub client_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub client_name: Option, #[serde(rename = "adapterID")] pub adapter_id: String, + #[serde(skip_serializing_if = "Option::is_none")] pub locale: Option, - #[serde(rename = "linesStartAt1")] + #[serde(rename = "linesStartAt1", skip_serializing_if = "Option::is_none")] pub lines_start_at_one: Option, - #[serde(rename = "columnsStartAt1")] + #[serde(rename = "columnsStartAt1", skip_serializing_if = "Option::is_none")] pub columns_start_at_one: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub path_format: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_variable_type: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_variable_paging: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_run_in_terminal_request: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_memory_references: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_progress_reporting: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supports_invalidated_event: Option, } @@ -300,14 +413,17 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct SetBreakpointsArguments { pub source: Source, + #[serde(skip_serializing_if = "Option::is_none")] pub breakpoints: Option>, // lines is deprecated + #[serde(skip_serializing_if = "Option::is_none")] pub source_modified: Option, } #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct SetBreakpointsResponse { + #[serde(skip_serializing_if = "Option::is_none")] pub breakpoints: Option>, } @@ -329,6 +445,7 @@ pub mod requests { #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ContinueResponse { + #[serde(skip_serializing_if = "Option::is_none")] pub all_threads_continued: Option, } @@ -345,14 +462,18 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct StackTraceArguments { pub thread_id: ThreadId, + #[serde(skip_serializing_if = "Option::is_none")] pub start_frame: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub levels: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub format: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct StackTraceResponse { + #[serde(skip_serializing_if = "Option::is_none")] pub total_frames: Option, pub stack_frames: Vec, } @@ -406,9 +527,13 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct VariablesArguments { pub variables_reference: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub filter: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub start: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub count: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub format: Option, } @@ -431,7 +556,9 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct StepInArguments { pub thread_id: ThreadId, + #[serde(skip_serializing_if = "Option::is_none")] pub target_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub granularity: Option, } @@ -448,6 +575,7 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct StepOutArguments { pub thread_id: ThreadId, + #[serde(skip_serializing_if = "Option::is_none")] pub granularity: Option, } @@ -464,6 +592,7 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct NextArguments { pub thread_id: ThreadId, + #[serde(skip_serializing_if = "Option::is_none")] pub granularity: Option, } @@ -495,8 +624,11 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct EvaluateArguments { pub expression: String, + #[serde(skip_serializing_if = "Option::is_none")] pub frame_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub context: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub format: Option, } @@ -504,12 +636,16 @@ pub mod requests { #[serde(rename_all = "camelCase")] pub struct EvaluateResponse { pub result: String, - #[serde(rename = "type")] + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub ty: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub presentation_hint: Option, pub variables_reference: usize, + #[serde(skip_serializing_if = "Option::is_none")] pub named_variables: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub indexed_variables: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub memory_reference: Option, } @@ -533,6 +669,7 @@ pub mod requests { #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct SetExceptionBreakpointsResponse { + #[serde(skip_serializing_if = "Option::is_none")] pub breakpoints: Option>, } @@ -550,17 +687,23 @@ pub mod requests { #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct RunInTerminalResponse { + #[serde(skip_serializing_if = "Option::is_none")] pub process_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub shell_process_id: Option, } #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct RunInTerminalArguments { + #[serde(skip_serializing_if = "Option::is_none")] pub kind: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub cwd: Option, pub args: Vec, + #[serde(skip_serializing_if = "Option::is_none")] pub env: Option>>, } @@ -607,11 +750,17 @@ pub mod events { #[serde(rename_all = "camelCase")] pub struct Stopped { pub reason: String, + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub thread_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub preserve_focus_hint: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub text: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub all_threads_stopped: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub hit_breakpoint_ids: Option>, } @@ -619,6 +768,7 @@ pub mod events { #[serde(rename_all = "camelCase")] pub struct Continued { pub thread_id: ThreadId, + #[serde(skip_serializing_if = "Option::is_none")] pub all_threads_continued: Option, } @@ -631,6 +781,7 @@ pub mod events { #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Terminated { + #[serde(skip_serializing_if = "Option::is_none")] pub restart: Option, } @@ -645,12 +796,19 @@ pub mod events { #[serde(rename_all = "camelCase")] pub struct Output { pub output: String, + #[serde(skip_serializing_if = "Option::is_none")] pub category: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub group: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub line: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub column: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub variables_reference: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub data: Option, } @@ -679,9 +837,13 @@ pub mod events { #[serde(rename_all = "camelCase")] pub struct Process { pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] pub system_process_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub is_local_process: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub start_method: Option, // TODO: use enum + #[serde(skip_serializing_if = "Option::is_none")] pub pointer_size: Option, } From 85411bed83615895f4138fa080c07c257631d7f7 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 4 Jul 2022 09:32:28 -0500 Subject: [PATCH 089/584] DAP: Make `cwd` required in RunTerminalArguments The spec has `cwd` in `RunInTerminalRequestArguments` as non-optional: https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal --- helix-dap/src/types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helix-dap/src/types.rs b/helix-dap/src/types.rs index 71b2aa8347a3c..45f45cca5cdc7 100644 --- a/helix-dap/src/types.rs +++ b/helix-dap/src/types.rs @@ -700,8 +700,7 @@ pub mod requests { pub kind: Option, #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub cwd: Option, + pub cwd: String, pub args: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub env: Option>>, From b26e7e2e8fc900b5637d9772ecb74874e8794ecc Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 5 Jul 2022 06:44:16 -0400 Subject: [PATCH 090/584] Add live preview to theme picker (#1798) * Add theme picker with live preview * Add live theme preview to :theme command * cargo fmt * Fix clippy warnings * Remove picker variant * Remove unused import * Cleanup * Change current_theme to last_theme * Fix accidental comment flash deletion * Typo * Remove theme cache * Add some comments * Refactor some theme handling TIL flatmap on Option is called and_then * Remove unnecessary renames * Constrain last_theme theme preview lifecycle * Switch to bitflag implementation * Better handling of last_theme * Sort theme names * Better memory juggling * Missed a branch * Remove name from theme, switch bitand to & * cargo fmt * Update helix-view/src/editor.rs * Switch boolean to enum * Remove bitflag impl * cargo fmt * Remove un-needed type arg * cargo fmt --- helix-term/src/application.rs | 16 +- helix-term/src/commands/typed.rs | 472 ++++++++++++++++++++++++------- helix-term/src/ui/mod.rs | 1 + helix-term/src/ui/picker.rs | 2 +- helix-view/src/editor.rs | 41 ++- helix-view/src/theme.rs | 8 + 6 files changed, 422 insertions(+), 118 deletions(-) diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 805f660f6d925..df14f5e3de79d 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -108,13 +108,7 @@ impl Application { .ok() .filter(|theme| (true_color || theme.is_16_color())) }) - .unwrap_or_else(|| { - if true_color { - theme_loader.default() - } else { - theme_loader.base16_default() - } - }); + .unwrap_or_else(|| theme_loader.default_theme(true_color)); let syn_loader_conf = user_syntax_loader().unwrap_or_else(|err| { eprintln!("Bad language config: {}", err); @@ -373,13 +367,7 @@ impl Application { }) .ok() .filter(|theme| (true_color || theme.is_16_color())) - .unwrap_or_else(|| { - if true_color { - self.theme_loader.default() - } else { - self.theme_loader.base16_default() - } - }), + .unwrap_or_else(|| self.theme_loader.default_theme(true_color)), ); } diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 70f5fa9fed82c..4e1ac0da9a9ce 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -15,11 +15,11 @@ pub struct TypableCommand { pub completer: Option, } -fn quit( - cx: &mut compositor::Context, - args: &[Cow], - _event: PromptEvent, -) -> anyhow::Result<()> { +fn quit(cx: &mut compositor::Context, args: &[Cow], event: PromptEvent) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(args.is_empty(), ":quit takes no arguments"); // last view and we have unsaved changes @@ -35,8 +35,12 @@ fn quit( fn force_quit( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(args.is_empty(), ":quit! takes no arguments"); cx.editor.close(view!(cx.editor).id); @@ -44,11 +48,11 @@ fn force_quit( Ok(()) } -fn open( - cx: &mut compositor::Context, - args: &[Cow], - _event: PromptEvent, -) -> anyhow::Result<()> { +fn open(cx: &mut compositor::Context, args: &[Cow], event: PromptEvent) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(!args.is_empty(), "wrong argument count"); for arg in args { let (path, pos) = args::parse_file(arg); @@ -114,8 +118,12 @@ fn buffer_gather_paths_impl(editor: &mut Editor, args: &[Cow]) -> Vec], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_paths_impl(cx.editor, args); buffer_close_by_ids_impl(cx.editor, &document_ids, false) } @@ -123,8 +131,12 @@ fn buffer_close( fn force_buffer_close( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_paths_impl(cx.editor, args); buffer_close_by_ids_impl(cx.editor, &document_ids, true) } @@ -141,8 +153,12 @@ fn buffer_gather_others_impl(editor: &mut Editor) -> Vec { fn buffer_close_others( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_others_impl(cx.editor); buffer_close_by_ids_impl(cx.editor, &document_ids, false) } @@ -150,8 +166,12 @@ fn buffer_close_others( fn force_buffer_close_others( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_others_impl(cx.editor); buffer_close_by_ids_impl(cx.editor, &document_ids, true) } @@ -163,8 +183,12 @@ fn buffer_gather_all_impl(editor: &mut Editor) -> Vec { fn buffer_close_all( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_all_impl(cx.editor); buffer_close_by_ids_impl(cx.editor, &document_ids, false) } @@ -172,8 +196,12 @@ fn buffer_close_all( fn force_buffer_close_all( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let document_ids = buffer_gather_all_impl(cx.editor); buffer_close_by_ids_impl(cx.editor, &document_ids, true) } @@ -181,8 +209,12 @@ fn force_buffer_close_all( fn buffer_next( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + goto_buffer(cx.editor, Direction::Forward); Ok(()) } @@ -190,8 +222,12 @@ fn buffer_next( fn buffer_previous( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + goto_buffer(cx.editor, Direction::Backward); Ok(()) } @@ -242,24 +278,36 @@ fn write_impl( fn write( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_impl(cx, args.first(), false) } fn force_write( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_impl(cx, args.first(), true) } fn new_file( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor.new_file(Action::Replace); Ok(()) @@ -268,8 +316,12 @@ fn new_file( fn format( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let doc = doc!(cx.editor); if let Some(format) = doc.format() { let callback = @@ -282,8 +334,12 @@ fn format( fn set_indent_style( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + use IndentStyle::*; // If no argument, report current indent style. @@ -321,8 +377,12 @@ fn set_indent_style( fn set_line_ending( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + use LineEnding::*; // If no argument, report current line ending setting. @@ -391,8 +451,12 @@ fn set_line_ending( fn earlier( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let uk = args.join(" ").parse::().map_err(|s| anyhow!(s))?; let (view, doc) = current!(cx.editor); @@ -407,8 +471,12 @@ fn earlier( fn later( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let uk = args.join(" ").parse::().map_err(|s| anyhow!(s))?; let (view, doc) = current!(cx.editor); let success = doc.later(view.id, uk); @@ -424,6 +492,10 @@ fn write_quit( args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_impl(cx, args.first(), false)?; helix_lsp::block_on(cx.jobs.finish())?; quit(cx, &[], event) @@ -434,6 +506,10 @@ fn force_write_quit( args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_impl(cx, args.first(), true)?; force_quit(cx, &[], event) } @@ -463,10 +539,14 @@ pub(super) fn buffers_remaining_impl(editor: &mut Editor) -> anyhow::Result<()> fn write_all_impl( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, quit: bool, force: bool, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let mut errors = String::new(); let auto_format = cx.editor.config().auto_format; let jobs = &mut cx.jobs; @@ -520,6 +600,10 @@ fn write_all( args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_all_impl(cx, args, event, false, false) } @@ -528,6 +612,10 @@ fn write_all_quit( args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_all_impl(cx, args, event, true, false) } @@ -536,6 +624,10 @@ fn force_write_all_quit( args: &[Cow], event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + write_all_impl(cx, args, event, true, true) } @@ -556,24 +648,36 @@ fn quit_all_impl(editor: &mut Editor, force: bool) -> anyhow::Result<()> { fn quit_all( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + quit_all_impl(cx.editor, false) } fn force_quit_all( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + quit_all_impl(cx.editor, true) } fn cquit( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let exit_code = args .first() .and_then(|code| code.parse::().ok()) @@ -586,8 +690,12 @@ fn cquit( fn force_cquit( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let exit_code = args .first() .and_then(|code| code.parse::().ok()) @@ -600,35 +708,61 @@ fn force_cquit( fn theme( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, -) -> anyhow::Result<()> { - 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); + event: PromptEvent, +) -> anyhow::Result<()> { + let true_color = cx.editor.config.load().true_color || crate::true_color(); + match event { + PromptEvent::Abort => { + cx.editor.unset_theme_preview(); + } + PromptEvent::Update => { + if let Some(theme_name) = args.first() { + if let Ok(theme) = cx.editor.theme_loader.load(theme_name) { + if !(true_color || theme.is_16_color()) { + bail!("Unsupported theme: theme requires true color support"); + } + cx.editor.set_theme_preview(theme); + }; + }; + } + PromptEvent::Validate => { + let theme_name = args.first().with_context(|| "Theme name not provided")?; + let theme = cx + .editor + .theme_loader + .load(theme_name) + .with_context(|| "Theme does not exist")?; + 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( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Clipboard) } fn yank_joined_to_clipboard( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let doc = doc!(cx.editor); let default_sep = Cow::Borrowed(doc.line_ending.as_str()); let separator = args.first().unwrap_or(&default_sep); @@ -638,16 +772,24 @@ fn yank_joined_to_clipboard( fn yank_main_selection_to_primary_clipboard( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + yank_main_selection_to_clipboard_impl(cx.editor, ClipboardType::Selection) } fn yank_joined_to_primary_clipboard( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let doc = doc!(cx.editor); let default_sep = Cow::Borrowed(doc.line_ending.as_str()); let separator = args.first().unwrap_or(&default_sep); @@ -657,32 +799,48 @@ fn yank_joined_to_primary_clipboard( fn paste_clipboard_after( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + paste_clipboard_impl(cx.editor, Paste::After, ClipboardType::Clipboard, 1) } fn paste_clipboard_before( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + paste_clipboard_impl(cx.editor, Paste::Before, ClipboardType::Clipboard, 1) } fn paste_primary_clipboard_after( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + paste_clipboard_impl(cx.editor, Paste::After, ClipboardType::Selection, 1) } fn paste_primary_clipboard_before( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + paste_clipboard_impl(cx.editor, Paste::Before, ClipboardType::Selection, 1) } @@ -710,24 +868,36 @@ fn replace_selections_with_clipboard_impl( fn replace_selections_with_clipboard( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + replace_selections_with_clipboard_impl(cx, ClipboardType::Clipboard) } fn replace_selections_with_primary_clipboard( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + replace_selections_with_clipboard_impl(cx, ClipboardType::Selection) } fn show_clipboard_provider( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor .set_status(cx.editor.clipboard_provider.name().to_string()); Ok(()) @@ -736,8 +906,12 @@ fn show_clipboard_provider( fn change_current_directory( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let dir = helix_core::path::expand_tilde( args.first() .context("target directory not provided")? @@ -760,8 +934,12 @@ fn change_current_directory( fn show_current_directory( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let cwd = std::env::current_dir().context("Couldn't get the new working directory")?; cx.editor .set_status(format!("Current working directory is {}", cwd.display())); @@ -772,8 +950,12 @@ fn show_current_directory( fn set_encoding( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let doc = doc_mut!(cx.editor); if let Some(label) = args.first() { doc.set_encoding(label) @@ -788,8 +970,12 @@ fn set_encoding( fn reload( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let scrolloff = cx.editor.config().scrolloff; let (view, doc) = current!(cx.editor); doc.reload(view.id).map(|_| { @@ -800,8 +986,12 @@ fn reload( fn tree_sitter_scopes( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let (view, doc) = current!(cx.editor); let text = doc.text().slice(..); @@ -814,8 +1004,12 @@ fn tree_sitter_scopes( fn vsplit( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let id = view!(cx.editor).doc; if args.is_empty() { @@ -833,8 +1027,12 @@ fn vsplit( fn hsplit( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let id = view!(cx.editor).doc; if args.is_empty() { @@ -852,8 +1050,12 @@ fn hsplit( fn vsplit_new( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor.new_file(Action::VerticalSplit); Ok(()) @@ -862,8 +1064,12 @@ fn vsplit_new( fn hsplit_new( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor.new_file(Action::HorizontalSplit); Ok(()) @@ -872,8 +1078,12 @@ fn hsplit_new( fn debug_eval( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + if let Some(debugger) = cx.editor.debugger.as_mut() { let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) { (Some(frame), Some(thread_id)) => (frame, thread_id), @@ -894,8 +1104,12 @@ fn debug_eval( fn debug_start( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let mut args = args.to_owned(); let name = match args.len() { 0 => None, @@ -907,8 +1121,12 @@ fn debug_start( fn debug_remote( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let mut args = args.to_owned(); let address = match args.len() { 0 => None, @@ -924,8 +1142,12 @@ fn debug_remote( fn tutor( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let path = helix_loader::runtime_dir().join("tutor.txt"); cx.editor.open(&path, Action::Replace)?; // Unset path to prevent accidentally saving to the original tutor file. @@ -936,8 +1158,12 @@ fn tutor( pub(super) fn goto_line_number( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(!args.is_empty(), "Line number required"); let line = args[0].parse::()?; @@ -954,8 +1180,12 @@ pub(super) fn goto_line_number( fn get_option( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + if args.len() != 1 { anyhow::bail!("Bad arguments. Usage: `:get key`"); } @@ -976,8 +1206,12 @@ fn get_option( fn set_option( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + if args.len() != 2 { anyhow::bail!("Bad arguments. Usage: `:set key field`"); } @@ -1009,8 +1243,12 @@ fn set_option( fn language( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + if args.len() != 1 { anyhow::bail!("Bad arguments. Usage: `:set-language language`"); } @@ -1023,19 +1261,23 @@ fn language( Ok(()) } -fn sort( - cx: &mut compositor::Context, - args: &[Cow], - _event: PromptEvent, -) -> anyhow::Result<()> { +fn sort(cx: &mut compositor::Context, args: &[Cow], event: PromptEvent) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + sort_impl(cx, args, false) } fn sort_reverse( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + sort_impl(cx, args, true) } @@ -1076,8 +1318,12 @@ fn sort_impl( fn reflow( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let (view, doc) = current!(cx.editor); const DEFAULT_MAX_LEN: usize = 79; @@ -1115,8 +1361,12 @@ fn reflow( fn tree_sitter_subtree( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let (view, doc) = current!(cx.editor); if let Some(syntax) = doc.syntax() { @@ -1151,8 +1401,12 @@ fn tree_sitter_subtree( fn open_config( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor .open(&helix_loader::config_file(), Action::Replace)?; Ok(()) @@ -1161,8 +1415,12 @@ fn open_config( fn open_log( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor.open(&helix_loader::log_file(), Action::Replace)?; Ok(()) } @@ -1170,8 +1428,12 @@ fn open_log( fn refresh_config( cx: &mut compositor::Context, _args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + cx.editor.config_events.0.send(ConfigEvent::Refresh)?; Ok(()) } @@ -1179,8 +1441,12 @@ fn refresh_config( fn append_output( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(!args.is_empty(), "Shell command required"); shell(cx, &args.join(" "), &ShellBehavior::Append); Ok(()) @@ -1189,18 +1455,22 @@ fn append_output( fn insert_output( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(!args.is_empty(), "Shell command required"); shell(cx, &args.join(" "), &ShellBehavior::Insert); Ok(()) } -fn pipe( - cx: &mut compositor::Context, - args: &[Cow], - _event: PromptEvent, -) -> anyhow::Result<()> { +fn pipe(cx: &mut compositor::Context, args: &[Cow], event: PromptEvent) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + ensure!(!args.is_empty(), "Shell command required"); shell(cx, &args.join(" "), &ShellBehavior::Replace); Ok(()) @@ -1209,8 +1479,12 @@ fn pipe( fn run_shell_command( cx: &mut compositor::Context, args: &[Cow], - _event: PromptEvent, + event: PromptEvent, ) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + let shell = &cx.editor.config().shell; let (output, success) = shell_impl(shell, &args.join(" "), None)?; if success { @@ -1270,14 +1544,14 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ aliases: &["bc", "bclose"], doc: "Close the current buffer.", fun: buffer_close, - completer: Some(completers::buffer), + completer: Some(completers::buffer), }, TypableCommand { name: "buffer-close!", aliases: &["bc!", "bclose!"], doc: "Close the current buffer forcefully (ignoring unsaved changes).", fun: force_buffer_close, - completer: Some(completers::buffer), + completer: Some(completers::buffer), }, TypableCommand { name: "buffer-close-others", @@ -1561,7 +1835,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ doc: "Display tree sitter scopes, primarily for theming and development.", fun: tree_sitter_scopes, completer: None, - }, + }, TypableCommand { name: "debug-start", aliases: &["dbg"], @@ -1787,10 +2061,6 @@ pub fn command_mode(cx: &mut Context) { } }, // completion move |cx: &mut compositor::Context, input: &str, event: PromptEvent| { - if event != PromptEvent::Validate { - return; - } - let parts = input.split_whitespace().collect::>(); if parts.is_empty() { return; @@ -1811,10 +2081,10 @@ pub fn command_mode(cx: &mut Context) { if let Err(e) = (cmd.fun)(cx, &args[1..], event) { cx.editor.set_error(format!("{}", e)); } - } else { + } else if event == PromptEvent::Validate { cx.editor .set_error(format!("no such command: '{}'", parts[0])); - }; + } }, ); prompt.doc_fn = Box::new(|input: &str| { diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 8d2bd32511253..ca4cedb55de3b 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -237,6 +237,7 @@ pub mod completers { )); names.push("default".into()); names.push("base16_default".into()); + names.sort(); let mut names: Vec<_> = names .into_iter() diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index f4dd234a44d67..375723e560ae0 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -490,7 +490,7 @@ impl Component for Picker { _ => return EventResult::Ignored(None), }; - let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| { + let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _cx| { // remove the layer compositor.last_picker = compositor.pop(); }))); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 1ed27e996eafc..a2943af98182d 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -464,7 +464,6 @@ pub struct Editor { pub registers: Registers, pub macro_recording: Option<(char, Vec)>, pub macro_replaying: Vec, - pub theme: Theme, pub language_servers: helix_lsp::Registry, pub diagnostics: BTreeMap>, @@ -476,6 +475,12 @@ pub struct Editor { pub syn_loader: Arc, pub theme_loader: Arc, + /// last_theme is used for theme previews. We store the current theme here, + /// and if previewing is cancelled, we can return to it. + pub last_theme: Option, + /// The currently applied editor theme. While previewing a theme, the previewed theme + /// is set here. + pub theme: Theme, pub status_msg: Option<(Cow<'static, str>, Severity)>, pub autoinfo: Option, @@ -500,6 +505,11 @@ pub enum ConfigEvent { Update(Box), } +enum ThemeAction { + Set, + Preview, +} + #[derive(Debug, Clone)] pub struct CompleteAction { pub trigger_offset: usize, @@ -544,6 +554,7 @@ impl Editor { breakpoints: HashMap::new(), syn_loader, theme_loader, + last_theme: None, registers: Registers::default(), clipboard_provider: get_clipboard_provider(), status_msg: None, @@ -613,7 +624,22 @@ impl Editor { .unwrap_or(false) } + pub fn unset_theme_preview(&mut self) { + if let Some(last_theme) = self.last_theme.take() { + self.set_theme(last_theme); + } + // None likely occurs when the user types ":theme" and then exits before previewing + } + + pub fn set_theme_preview(&mut self, theme: Theme) { + self.set_theme_impl(theme, ThemeAction::Preview); + } + pub fn set_theme(&mut self, theme: Theme) { + self.set_theme_impl(theme, ThemeAction::Set); + } + + fn set_theme_impl(&mut self, theme: Theme, preview: ThemeAction) { // `ui.selection` is the only scope required to be able to render a theme. if theme.find_scope_index("ui.selection").is_none() { self.set_error("Invalid theme: `ui.selection` required"); @@ -623,7 +649,18 @@ impl Editor { let scopes = theme.scopes(); self.syn_loader.set_scopes(scopes.to_vec()); - self.theme = theme; + match preview { + ThemeAction::Preview => { + let last_theme = std::mem::replace(&mut self.theme, theme); + // only insert on first preview: this will be the last theme the user has saved + self.last_theme.get_or_insert(last_theme); + } + ThemeAction::Set => { + self.last_theme = None; + self.theme = theme; + } + } + self._refresh(); } diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 3f45aac6ea3f9..fa5fa702804b0 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -77,6 +77,14 @@ impl Loader { names } + pub fn default_theme(&self, true_color: bool) -> Theme { + if true_color { + self.default() + } else { + self.base16_default() + } + } + /// Returns the default theme pub fn default(&self) -> Theme { DEFAULT_THEME.clone() From d78354c537e00ddb0976efad1df49c90a224f107 Mon Sep 17 00:00:00 2001 From: Matthew Toohey Date: Tue, 5 Jul 2022 07:00:38 -0400 Subject: [PATCH 091/584] add language `idris` (#2971) --- book/src/generated/lang-support.md | 1 + languages.toml | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 3c56a6f40ad65..85e42b15996ea 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -40,6 +40,7 @@ | hcl | ✓ | | ✓ | `terraform-ls` | | heex | ✓ | | | | | html | ✓ | | | `vscode-html-language-server` | +| idris | | | | `idris2-lsp` | | iex | ✓ | | | | | java | ✓ | | | `jdtls` | | javascript | ✓ | | ✓ | `typescript-language-server` | diff --git a/languages.toml b/languages.toml index 7c63c051ab11a..9da454a0824ba 100644 --- a/languages.toml +++ b/languages.toml @@ -1503,3 +1503,14 @@ grammar = "elvish" [[grammar]] name = "elvish" source = { git = "https://github.com/ckafi/tree-sitter-elvish", rev = "e50787cadd3bc54f6d9c0704493a79078bb8a4e5" } + +[[language]] +name = "idris" +scope = "source.idr" +injection-regex = "idr" +file-types = ["idr"] +shebangs = [] +roots = [] +comment-token = "--" +indent = { tab-width = 2, unit = " " } +language-server = { command = "idris2-lsp" } From aacd0c8aa542ac0316569ae062966362222ff4bf Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 5 Jul 2022 06:01:05 -0500 Subject: [PATCH 092/584] Update TSQ queries (#2960) A few changes to make TSQ highlights better: * A parsing error has been fixed in the grammar itself * Previously tree-sitter-tsq did not parse the variables in predicates like `(#set! injection.language "javascript")` * Theme nodes as `tag` * The newly added node to the parser (from the above fix) is `variable` which takes over the `variable` capture from nodes * Highlight known predicates as `function` and unsupported predicates as `error` * This may help when translating queries from nvim-treesitter. For example `#any-of?` is a common one used in nvim-treesitter queries but not implemented in Helix or tree-sitter-cli. * Inject tree-sitter-regex into `#match?` predicates --- languages.toml | 2 +- runtime/queries/tsq/highlights.scm | 9 ++++++--- runtime/queries/tsq/injections.scm | 6 ++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/languages.toml b/languages.toml index 9da454a0824ba..f8b2d579de0af 100644 --- a/languages.toml +++ b/languages.toml @@ -707,7 +707,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "tsq" -source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "ea68fc2b571ca1c8f70936855130c380f518ff35" } +source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "48b5e9f82ae0a4727201626f33a17f69f8e0ff86" } [[language]] name = "cmake" diff --git a/runtime/queries/tsq/highlights.scm b/runtime/queries/tsq/highlights.scm index fd5917fb1f6f6..c655b994f7518 100644 --- a/runtime/queries/tsq/highlights.scm +++ b/runtime/queries/tsq/highlights.scm @@ -6,7 +6,7 @@ ; highlight inheritance comments ((query . (comment) @keyword.directive) - (#match? @keyword.directive "^;\ +inherits *:")) + (#match? @keyword.directive "^; +inherits *:")) [ "(" @@ -40,8 +40,11 @@ (capture) @label -(predicate_name) @function +((predicate_name) @function + (#match? @function "^#(eq\\?|match\\?|is\\?|is-not\\?|not-same-line\\?|not-kind-eq\\?|set!|select-adjacent!|strip!)$")) +(predicate_name) @error (escape_sequence) @constant.character.escape -(node_name) @variable +(node_name) @tag +(variable) @variable diff --git a/runtime/queries/tsq/injections.scm b/runtime/queries/tsq/injections.scm index 321c90add3710..644045570626a 100644 --- a/runtime/queries/tsq/injections.scm +++ b/runtime/queries/tsq/injections.scm @@ -1,2 +1,8 @@ ((comment) @injection.content (#set! injection.language "comment")) + +((predicate + (predicate_name) @_predicate + (string) @injection.content) + (#eq? @_predicate "#match?") + (#set! injection.language "regex")) From b61221107068160c241858a530f6fa4144566122 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Tue, 5 Jul 2022 22:12:28 +0800 Subject: [PATCH 093/584] Update tree-sitter-ledger (#2936) --- languages.toml | 2 +- runtime/queries/ledger/highlights.scm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index f8b2d579de0af..d7462bb8c583b 100644 --- a/languages.toml +++ b/languages.toml @@ -570,7 +570,7 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "ledger" -source = { git = "https://github.com/cbarrete/tree-sitter-ledger", rev = "0cdeb0e51411a3ba5493662952c3039de08939ca" } +source = { git = "https://github.com/cbarrete/tree-sitter-ledger", rev = "1f864fb2bf6a87fe1b48545cc6adc6d23090adf7" } [[language]] name = "ocaml" diff --git a/runtime/queries/ledger/highlights.scm b/runtime/queries/ledger/highlights.scm index 02a9ea9a79a4c..301076c79479c 100644 --- a/runtime/queries/ledger/highlights.scm +++ b/runtime/queries/ledger/highlights.scm @@ -11,6 +11,7 @@ ((account) @variable.other.member) ((commodity) @text.literal) +((tag) @tag) "include" @keyword.local.import From 1378b911b63f4fdab7beba77de6d54f1dd070553 Mon Sep 17 00:00:00 2001 From: A-Walrus <58790821+A-Walrus@users.noreply.github.com> Date: Wed, 6 Jul 2022 05:49:54 +0300 Subject: [PATCH 094/584] Fix some typos (#2978) --- book/src/keymap.md | 4 ++-- docs/architecture.md | 2 +- helix-core/src/indent.rs | 2 +- helix-term/src/ui/markdown.rs | 2 +- runtime/queries/elm/highlights.scm | 2 +- runtime/queries/git-commit/highlights.scm | 2 +- runtime/queries/kotlin/highlights.scm | 2 +- runtime/queries/lean/highlights.scm | 2 +- runtime/queries/make/highlights.scm | 2 +- runtime/queries/solidity/highlights.scm | 6 +++--- runtime/queries/verilog/highlights.scm | 2 +- runtime/queries/verilog/textobjects.scm | 2 +- runtime/themes/nord.toml | 2 +- runtime/themes/pop-dark.toml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index b979cfd89491c..5daeec3fa3b5e 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -241,8 +241,8 @@ This layer is a kludge of mappings, mostly pickers. | `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` | | `s` | Open document symbol picker (**LSP**) | `symbol_picker` | | `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` | -| `g` | Open document diagnosics picker (**LSP**) | `diagnostics_picker` | -| `G` | Open workspace diagnostics picker (**LSP**) | `workspace_diagnosics_picker` +| `g` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` | +| `G` | Open workspace diagnostics picker (**LSP**) | `workspace_diagnostics_picker` | `r` | Rename symbol (**LSP**) | `rename_symbol` | | `a` | Apply code action (**LSP**) | `code_action` | | `'` | Open last fuzzy picker | `last_picker` | diff --git a/docs/architecture.md b/docs/architecture.md index 74f973b0d9cf1..5d33cbac06b7b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -32,7 +32,7 @@ represented by a `Selection`. Each `Range` in the selection consists of a moving a selection with a single range, with the head and the anchor in the same position. -Ropes are modified by constructing an OT-like `Transaction`. It's represents +Ropes are modified by constructing an OT-like `Transaction`. It represents a single coherent change to the document and can be applied to the rope. A transaction can be inverted to produce an undo. Selections and marks can be mapped over a transaction to translate to a position in the new text state after diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs index 529139b81e252..137b8822d0495 100644 --- a/helix-core/src/indent.rs +++ b/helix-core/src/indent.rs @@ -453,7 +453,7 @@ fn query_indents( /// /// ```ignore /// some_function( -/// parm1, +/// param1, /// || { /// // Here we get 2 indent levels because the 'parameters' and the 'block' node begin on different lines /// }, diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index e3ce2cd5d1e11..a5c78c41d32d2 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -204,7 +204,7 @@ impl Markdown { tags.push(Tag::Item); - // get the approriate bullet for the current list + // get the appropriate bullet for the current list let bullet = list_stack .last() .unwrap_or(&None) // use the '- ' bullet in case the list stack would be empty diff --git a/runtime/queries/elm/highlights.scm b/runtime/queries/elm/highlights.scm index 3c8fd12d87a98..d02b3a5c69d16 100644 --- a/runtime/queries/elm/highlights.scm +++ b/runtime/queries/elm/highlights.scm @@ -49,7 +49,7 @@ ] @keyword -(import) @keyword.contol.import +(import) @keyword.control.import (module) @keyword.other (number_constant_expr) @constant.numeric diff --git a/runtime/queries/git-commit/highlights.scm b/runtime/queries/git-commit/highlights.scm index bdb776d6dd6ab..20f58ee579661 100644 --- a/runtime/queries/git-commit/highlights.scm +++ b/runtime/queries/git-commit/highlights.scm @@ -10,5 +10,5 @@ (change kind: "modified" @diff.delta) (change kind: "renamed" @diff.delta.moved) -[":" "->" (scissors)] @punctuation.delimeter +[":" "->" (scissors)] @punctuation.delimiter (comment) @comment diff --git a/runtime/queries/kotlin/highlights.scm b/runtime/queries/kotlin/highlights.scm index 7b90fcf929ad3..208a673f31538 100644 --- a/runtime/queries/kotlin/highlights.scm +++ b/runtime/queries/kotlin/highlights.scm @@ -217,7 +217,7 @@ (function_declaration . (simple_identifier) @function) -; TODO: Seperate labeled returns/breaks/continue/super/this +; TODO: Separate labeled returns/breaks/continue/super/this ; Must be implemented in the parser first (label) @label diff --git a/runtime/queries/lean/highlights.scm b/runtime/queries/lean/highlights.scm index a64feb1d390d1..ca19b8353f26e 100644 --- a/runtime/queries/lean/highlights.scm +++ b/runtime/queries/lean/highlights.scm @@ -197,7 +197,7 @@ (interpolated_string) @string ; (escape_sequence) @string.escape -; Reset highlighing in string interpolation +; Reset highlighting in string interpolation (interpolation) @none (interpolation diff --git a/runtime/queries/make/highlights.scm b/runtime/queries/make/highlights.scm index 50380bafa9dd8..5aef8e0f69c45 100644 --- a/runtime/queries/make/highlights.scm +++ b/runtime/queries/make/highlights.scm @@ -155,7 +155,7 @@ (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 +;; Standard 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)$")) diff --git a/runtime/queries/solidity/highlights.scm b/runtime/queries/solidity/highlights.scm index 61c89ac8ad06c..544cf3d94d1af 100644 --- a/runtime/queries/solidity/highlights.scm +++ b/runtime/queries/solidity/highlights.scm @@ -50,7 +50,7 @@ name: (identifier) @function) (yul_evm_builtin) @function.builtin -; Use contructor coloring for special functions +; Use constructor coloring for special functions (constructor_definition "constructor" @constructor) (fallback_receive_definition "receive" @constructor) (fallback_receive_definition "fallback" @constructor) @@ -64,7 +64,7 @@ (call_expression . (identifier) @function) ; Function parameters -(event_paramater name: (identifier) @variable.parameter) +(event_paramater name: (identifier) @variable.parameter) ; TODO fix spelling once fixed upstream (function_definition function_name: (identifier) @variable.parameter) @@ -131,7 +131,7 @@ (import_directive "as" @keyword) (import_directive "from" @keyword) -(event_paramater "indexed" @keyword) +(event_paramater "indexed" @keyword) ; TODO fix spelling once fixed upstream ; Punctuation diff --git a/runtime/queries/verilog/highlights.scm b/runtime/queries/verilog/highlights.scm index 97ec06e3a0223..a194ac33b6aec 100644 --- a/runtime/queries/verilog/highlights.scm +++ b/runtime/queries/verilog/highlights.scm @@ -1,7 +1,7 @@ ; Keywords [ - ; block delimeters + ; block delimiters (module_keyword) "endmodule" "program" diff --git a/runtime/queries/verilog/textobjects.scm b/runtime/queries/verilog/textobjects.scm index 3b1c0fe50c1cd..f940832ab77cb 100644 --- a/runtime/queries/verilog/textobjects.scm +++ b/runtime/queries/verilog/textobjects.scm @@ -3,4 +3,4 @@ (function_body_declaration (function_identifier (function_identifier - (simple_identifier) @function.inside)))) @funtions.around \ No newline at end of file + (simple_identifier) @function.inside)))) @function.around \ No newline at end of file diff --git a/runtime/themes/nord.toml b/runtime/themes/nord.toml index f7ef079b0c4df..11195ece3c509 100644 --- a/runtime/themes/nord.toml +++ b/runtime/themes/nord.toml @@ -41,7 +41,7 @@ "constant.builtin" = "nord4" "namespace" = "nord4" -# nord5 - suble UI text +# nord5 - subtle UI text # nord6 - base text, punctuation "ui.text" = { fg = "nord6" } diff --git a/runtime/themes/pop-dark.toml b/runtime/themes/pop-dark.toml index e662f9575010a..172e8391a4d9c 100644 --- a/runtime/themes/pop-dark.toml +++ b/runtime/themes/pop-dark.toml @@ -71,7 +71,7 @@ namespace = { fg = 'orangeL' } 'variable.other.member' = { fg = 'orangeH' } 'variable.function' = { fg = 'blueL' } 'punctuation' = { fg = 'blueL' } -'punctuation.delimeter' = { fg = 'blueH' } +'punctuation.delimiter' = { fg = 'blueH' } 'punctuation.bracket' = { fg = 'orangeN' } 'keyword' = { fg = 'blueH' } 'keyword.control' = { fg = 'blueL' } From e0cf19c61205ff3589fe60550e64d4102d6a2dc5 Mon Sep 17 00:00:00 2001 From: Erin van der Veen Date: Wed, 6 Jul 2022 13:05:51 +0200 Subject: [PATCH 095/584] Update tree-sitter-nickel (#2987) --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index d7462bb8c583b..56abf3f8af8cd 100644 --- a/languages.toml +++ b/languages.toml @@ -425,7 +425,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "nickel" -source = { git = "https://github.com/nickel-lang/tree-sitter-nickel", rev = "9a502ea2e774df3d743a48310bb40e1cc097c86e" } +source = { git = "https://github.com/nickel-lang/tree-sitter-nickel", rev = "9d83db400b6c11260b9106f131f93ddda8131933" } [[language]] name = "nix" From c4e022971df6179647206592b6d7e452c12161d0 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 5 Jul 2022 09:05:11 +0530 Subject: [PATCH 096/584] Remove source from diagnostic picker display It is usually the name of the LSP and doesn't add much useful information. --- helix-term/src/commands/lsp.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 7f82394ac6226..2378ef16f41ad 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -132,11 +132,6 @@ impl ui::menu::Item for PickerDiagnostic { .into_owned(); Spans::from(vec![ - Span::styled( - self.diag.source.clone().unwrap_or_default(), - style.add_modifier(Modifier::BOLD), - ), - Span::raw(": "), Span::styled(truncated_path, style), Span::raw(" - "), Span::styled(code, style.add_modifier(Modifier::BOLD)), From 2c37e25cb552f1b64ad6815bb03c40d6d5aacb24 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 5 Jul 2022 09:16:47 +0530 Subject: [PATCH 097/584] Display diagnostic text before code in picker --- helix-term/src/commands/lsp.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 2378ef16f41ad..81e16b22f7681 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -132,11 +132,12 @@ impl ui::menu::Item for PickerDiagnostic { .into_owned(); Spans::from(vec![ - Span::styled(truncated_path, style), - Span::raw(" - "), - Span::styled(code, style.add_modifier(Modifier::BOLD)), + Span::raw(truncated_path), Span::raw(": "), Span::styled(&self.diag.message, style), + Span::raw(" ("), + Span::styled(code, style.add_modifier(Modifier::BOLD)), + Span::raw(")"), ]) } } From 0c104685c024a03cd857c0adcedea55b694eb604 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 5 Jul 2022 17:42:14 +0530 Subject: [PATCH 098/584] Sub sort diagnostics by line number --- helix-term/src/application.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index df14f5e3de79d..d3899075c7524 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -572,15 +572,11 @@ impl Application { doc.set_diagnostics(diagnostics); } - // Sort diagnostics first by URL and then by severity. + // Sort diagnostics first by severity and then by line numbers. // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order - params.diagnostics.sort_unstable_by(|a, b| { - if let (Some(a), Some(b)) = (a.severity, b.severity) { - a.partial_cmp(&b).unwrap() - } else { - std::cmp::Ordering::Equal - } - }); + params + .diagnostics + .sort_unstable_by_key(|d| (d.severity, d.range.start)); // Insert the original lsp::Diagnostics here because we may have no open document // for diagnosic message and so we can't calculate the exact position. From a43bcc876568b87f0e326612f5385d8c4922cb14 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 5 Jul 2022 17:54:57 +0530 Subject: [PATCH 099/584] Display error code only if not none --- helix-term/src/commands/lsp.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 81e16b22f7681..a73148cc3b26e 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -125,6 +125,7 @@ impl ui::menu::Item for PickerDiagnostic { NumberOrString::Number(n) => n.to_string(), NumberOrString::String(s) => s.to_string(), }) + .map(|code| format!(" ({})", code)) .unwrap_or_default(); let truncated_path = path::get_truncated_path(self.url.path()) @@ -135,9 +136,7 @@ impl ui::menu::Item for PickerDiagnostic { Span::raw(truncated_path), Span::raw(": "), Span::styled(&self.diag.message, style), - Span::raw(" ("), - Span::styled(code, style.add_modifier(Modifier::BOLD)), - Span::raw(")"), + Span::styled(code, style), ]) } } From af35c624070e3db5746c35601e98f346d91df280 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Tue, 5 Jul 2022 18:31:25 +0530 Subject: [PATCH 100/584] Show file path only in workspace diagnostic picker --- helix-term/src/commands/lsp.rs | 42 +++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index a73148cc3b26e..630c47e13a188 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -9,10 +9,7 @@ use tui::text::{Span, Spans}; use super::{align_view, push_jump, Align, Context, Editor}; use helix_core::{path, Selection}; -use helix_view::{ - editor::Action, - theme::{Modifier, Style}, -}; +use helix_view::{editor::Action, theme::Style}; use crate::{ compositor::{self, Compositor}, @@ -99,9 +96,9 @@ struct PickerDiagnostic { } impl ui::menu::Item for PickerDiagnostic { - type Data = DiagnosticStyles; + type Data = (DiagnosticStyles, DiagnosticsFormat); - fn label(&self, styles: &Self::Data) -> Spans { + fn label(&self, (styles, format): &Self::Data) -> Spans { let mut style = self .diag .severity @@ -128,13 +125,18 @@ impl ui::menu::Item for PickerDiagnostic { .map(|code| format!(" ({})", code)) .unwrap_or_default(); - let truncated_path = path::get_truncated_path(self.url.path()) - .to_string_lossy() - .into_owned(); + let path = match format { + DiagnosticsFormat::HideSourcePath => String::new(), + DiagnosticsFormat::ShowSourcePath => { + let path = path::get_truncated_path(self.url.path()) + .to_string_lossy() + .into_owned(); + format!("{}: ", path) + } + }; Spans::from(vec![ - Span::raw(truncated_path), - Span::raw(": "), + Span::raw(path), Span::styled(&self.diag.message, style), Span::styled(code, style), ]) @@ -237,10 +239,17 @@ fn sym_picker( .truncate_start(false) } +#[derive(Copy, Clone, PartialEq)] +enum DiagnosticsFormat { + ShowSourcePath, + HideSourcePath, +} + fn diag_picker( cx: &Context, diagnostics: BTreeMap>, current_path: Option, + format: DiagnosticsFormat, offset_encoding: OffsetEncoding, ) -> FilePicker { // TODO: drop current_path comparison and instead use workspace: bool flag? @@ -266,7 +275,7 @@ fn diag_picker( FilePicker::new( flat_diag, - styles, + (styles, format), move |cx, PickerDiagnostic { url, diag }, action| { if current_path.as_ref() == Some(url) { let (view, doc) = current!(cx.editor); @@ -378,6 +387,7 @@ pub fn diagnostics_picker(cx: &mut Context) { cx, [(current_url.clone(), diagnostics)].into(), Some(current_url), + DiagnosticsFormat::HideSourcePath, offset_encoding, ); cx.push_layer(Box::new(overlayed(picker))); @@ -390,7 +400,13 @@ pub fn workspace_diagnostics_picker(cx: &mut Context) { let current_url = doc.url(); let offset_encoding = language_server.offset_encoding(); let diagnostics = cx.editor.diagnostics.clone(); - let picker = diag_picker(cx, diagnostics, current_url, offset_encoding); + let picker = diag_picker( + cx, + diagnostics, + current_url, + DiagnosticsFormat::ShowSourcePath, + offset_encoding, + ); cx.push_layer(Box::new(overlayed(picker))); } From e35abe38f31149785ea04dc8a8fc1d2649ba70af Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Wed, 6 Jul 2022 20:35:36 +0800 Subject: [PATCH 101/584] Remove broken ledger tag highlight (#2988) --- runtime/queries/ledger/highlights.scm | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/queries/ledger/highlights.scm b/runtime/queries/ledger/highlights.scm index 301076c79479c..02a9ea9a79a4c 100644 --- a/runtime/queries/ledger/highlights.scm +++ b/runtime/queries/ledger/highlights.scm @@ -11,7 +11,6 @@ ((account) @variable.other.member) ((commodity) @text.literal) -((tag) @tag) "include" @keyword.local.import From 230ba264bf78d9b4ecd42440f0cbb20529f9c235 Mon Sep 17 00:00:00 2001 From: Jake Langford Date: Wed, 6 Jul 2022 13:54:07 +0000 Subject: [PATCH 102/584] Introduce storage highlighting for typescript/javascript (#2961) --- book/src/themes.md | 4 +++- runtime/queries/javascript/highlights.scm | 19 +++++++++++++------ runtime/queries/typescript/highlights.scm | 16 +++++++++++----- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 06f920d3ccb59..ad8864b20d579 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -151,7 +151,9 @@ We use a similar set of scopes as - `operator` - `or`, `in` - `directive` - Preprocessor directives (`#if` in C) - `function` - `fn`, `func` - - `storage` - Keywords that affect the storage of a variable, function or data structure `static`, `mut`, `const`, `ref` + - `storage` - Keywords describing how things are stored + - `type` - The type of something, `class`, `function`, `var`, `let`, etc. + - `modifier` - Storage modifiers like `static`, `mut`, `const`, `ref`, etc. - `operator` - `||`, `+=`, `>` diff --git a/runtime/queries/javascript/highlights.scm b/runtime/queries/javascript/highlights.scm index 2616dffa1dcf7..9a759081a9b00 100644 --- a/runtime/queries/javascript/highlights.scm +++ b/runtime/queries/javascript/highlights.scm @@ -163,19 +163,14 @@ [ "as" "async" - "class" - "const" "debugger" "delete" - "export" "extends" "from" "function" "get" - "import" "in" "instanceof" - "let" "new" "of" "set" @@ -183,11 +178,17 @@ "target" "try" "typeof" - "var" "void" "with" ] @keyword +[ + "class" + "let" + "const" + "var" +] @keyword.storage.type + [ "switch" "case" @@ -206,3 +207,9 @@ "do" "await" ] @keyword.control + +[ + "import" + "export" +] @keyword.control.import + diff --git a/runtime/queries/typescript/highlights.scm b/runtime/queries/typescript/highlights.scm index a3212a3dbcd77..a424d100f94f4 100644 --- a/runtime/queries/typescript/highlights.scm +++ b/runtime/queries/typescript/highlights.scm @@ -22,15 +22,21 @@ [ "abstract" "declare" - "enum" "export" "implements" - "interface" "keyof" "namespace" +] @keyword + +[ + "type" + "interface" + "enum" +] @keyword.storage.type + +[ + "public" "private" "protected" - "public" - "type" "readonly" -] @keyword +] @keyword.storage.modifier \ No newline at end of file From b7a3531b8f6aa0f7423293fbf071488b1ef12da2 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sat, 9 Jul 2022 01:54:09 +0530 Subject: [PATCH 103/584] theme(onedark): Remove bg for window separator (#3011) --- runtime/themes/onedark.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/themes/onedark.toml b/runtime/themes/onedark.toml index aec7ba960f02e..b4cc6f8b128bf 100644 --- a/runtime/themes/onedark.toml +++ b/runtime/themes/onedark.toml @@ -71,7 +71,7 @@ diagnostic = { modifiers = ["underlined"] } "ui.help" = { bg = "gray" } "ui.popup" = { bg = "gray" } -"ui.window" = { bg = "gray" } +"ui.window" = { fg = "gray" } "ui.menu" = { fg = "white", bg = "gray" } "ui.menu.selected" = { fg = "black", bg = "blue" } "ui.menu.scroll" = { fg = "white", bg = "light-gray" } From 21b66ba0686e745c7e32a4b79cc7edcc3b3fa349 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Sat, 9 Jul 2022 04:01:15 +0530 Subject: [PATCH 104/584] lsp: Add workspace/applyEdit to client capabilites (#3012) The functionality already existed, but the capability wasn't being reported correctly to the server: https://github.com/helix-editor/helix/blob/230ba264bf78d9b4ecd42440f0cbb20529f9c235/helix-term/src/application.rs#L716-L728 --- helix-lsp/src/client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index aa83354142636..9187a61ecd115 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -294,6 +294,7 @@ impl Client { dynamic_registration: Some(false), }), workspace_folders: Some(true), + apply_edit: Some(true), ..Default::default() }), text_document: Some(lsp::TextDocumentClientCapabilities { From 6100b1ba082db5c9fddd74d0ffea044231004920 Mon Sep 17 00:00:00 2001 From: Amit Beka Date: Sat, 9 Jul 2022 19:08:47 +0300 Subject: [PATCH 105/584] book: add wiki links to the title page and install page (#3017) Co-authored-by: amitbeka <---> --- book/src/install.md | 7 ++++++- book/src/title-page.md | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/book/src/install.md b/book/src/install.md index 045e225563ea3..3006c389c15e8 100644 --- a/book/src/install.md +++ b/book/src/install.md @@ -76,8 +76,13 @@ hx --health For more information on the information displayed in the healthcheck results refer to [Healthcheck](https://github.com/helix-editor/helix/wiki/Healthcheck). -## Building tree-sitter grammars +### Building tree-sitter grammars Tree-sitter grammars must be fetched and compiled if not pre-packaged. Fetch grammars with `hx --grammar fetch` (requires `git`) and compile them with `hx --grammar build` (requires a C++ compiler). + +### Installing language servers + +Language servers can optionally be installed if you want their features (auto-complete, diagnostics etc.). +Follow the [instructions on the wiki page](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers) to add your language servers of choice. diff --git a/book/src/title-page.md b/book/src/title-page.md index c182a753c830c..f24d3d33f7e80 100644 --- a/book/src/title-page.md +++ b/book/src/title-page.md @@ -6,6 +6,7 @@ Docs for bleeding edge master can be found at See the [usage] section for a quick overview of the editor, [keymap] section for all available keybindings and the [configuration] section for defining custom keybindings, setting themes, etc. +For everything else (e.g., how to install supported language servers), see the [Helix Wiki]. Refer the [FAQ] for common questions. @@ -13,3 +14,4 @@ Refer the [FAQ] for common questions. [usage]: ./usage.md [keymap]: ./keymap.md [configuration]: ./configuration.md +[Helix Wiki]: https://github.com/helix-editor/helix/wiki \ No newline at end of file From fefa4d8c5938c4e74b6eb01c6fb8379548c20ab4 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sat, 9 Jul 2022 09:09:37 -0700 Subject: [PATCH 106/584] nix flake: make the binary cache "just work" (#2999) --- book/src/install.md | 8 ++++++-- flake.nix | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/book/src/install.md b/book/src/install.md index 3006c389c15e8..ea46976f2a99f 100644 --- a/book/src/install.md +++ b/book/src/install.md @@ -22,8 +22,12 @@ the project root. The flake can also be used to spin up a reproducible developme shell for working on Helix with `nix develop`. Flake outputs are cached for each push to master using -[Cachix](https://www.cachix.org/). With Cachix -[installed](https://docs.cachix.org/installation), `cachix use helix` will +[Cachix](https://www.cachix.org/). The flake is configured to +automatically make use of this cache assuming the user accepts +the new settings on first use. + +If you are using a version of Nix without flakes enabled you can +[install Cachix cli](https://docs.cachix.org/installation); `cachix use helix` will configure Nix to use cached outputs when possible. ### Arch Linux diff --git a/flake.nix b/flake.nix index c8bd02aa7828b..d0d454af16601 100644 --- a/flake.nix +++ b/flake.nix @@ -96,4 +96,9 @@ }; }; }; + + nixConfig = { + extra-substituters = ["https://helix.cachix.org"]; + extra-trusted-public-keys = ["helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs="]; + }; } From 718c3baebecf4a970bc32724c564fa506ed40065 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Sat, 9 Jul 2022 09:17:44 -0700 Subject: [PATCH 107/584] nix: pass makeWrapperArgs to wrapProgram (#3003) --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index d0d454af16601..fdeed2aaf2993 100644 --- a/flake.nix +++ b/flake.nix @@ -63,7 +63,7 @@ postFixup = '' if [ -f "$out/bin/hx" ]; then - wrapProgram "$out/bin/hx" --set HELIX_RUNTIME "${runtimeDir}" + wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}" fi ''; }; From e109022bfd34b9297905b9da5904f6aa2279e74f Mon Sep 17 00:00:00 2001 From: Slug <106496265+GreasySlug@users.noreply.github.com> Date: Sun, 10 Jul 2022 17:54:06 +0900 Subject: [PATCH 108/584] fix: error that caused usize to overflow (#3024) * fix: error that caused usize to overflow * update: changed check_sub to saturating_sub --- helix-term/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c9e350628e533..193d5d405fb21 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1414,7 +1414,7 @@ fn copy_selection_on_line(cx: &mut Context, direction: Direction) { let (head, anchor) = if range.anchor < range.head { (range.head - 1, range.anchor) } else { - (range.head, range.anchor - 1) + (range.head, range.anchor.saturating_sub(1)) }; let tab_width = doc.tab_width(); From 0cb0c306183be94b9d42c3fae22b805850f87584 Mon Sep 17 00:00:00 2001 From: Austen LeBeau Date: Sun, 10 Jul 2022 11:27:44 -0500 Subject: [PATCH 109/584] add fortran language (#3025) --- book/src/generated/lang-support.md | 1 + languages.toml | 14 ++ runtime/queries/fortran/folds.scm | 11 ++ runtime/queries/fortran/highlights.scm | 171 +++++++++++++++++++++++++ runtime/queries/fortran/indents.scm | 27 ++++ 5 files changed, 224 insertions(+) create mode 100644 runtime/queries/fortran/folds.scm create mode 100644 runtime/queries/fortran/highlights.scm create mode 100644 runtime/queries/fortran/indents.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 85e42b15996ea..085d92a8ffc7d 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -22,6 +22,7 @@ | erb | ✓ | | | | | erlang | ✓ | ✓ | | `erlang_ls` | | fish | ✓ | ✓ | ✓ | | +| fortran | ✓ | | ✓ | `fortls` | | gdscript | ✓ | | ✓ | | | git-attributes | ✓ | | | | | git-commit | ✓ | | | | diff --git a/languages.toml b/languages.toml index 56abf3f8af8cd..3be20ab358553 100644 --- a/languages.toml +++ b/languages.toml @@ -1514,3 +1514,17 @@ roots = [] comment-token = "--" indent = { tab-width = 2, unit = " " } language-server = { command = "idris2-lsp" } + +[[language]] +name = "fortran" +scope = "source.fortran" +injection-regex = "fortran" +file-types = ["f", "for", "f90", "f95", "f03"] +roots = ["fpm.toml"] +comment-token = "!" +indent = { tab-width = 4, unit = " "} +language-server = { command = "fortls", args = ["--lowercase_intrinsics"] } + +[[grammar]] +name = "fortran" +source = { git = "https://github.com/stadelmanma/tree-sitter-fortran", rev = "f0f2f100952a353e64e26b0fa710b4c296d7af13" } \ No newline at end of file diff --git a/runtime/queries/fortran/folds.scm b/runtime/queries/fortran/folds.scm new file mode 100644 index 0000000000000..f62d9dd7bf052 --- /dev/null +++ b/runtime/queries/fortran/folds.scm @@ -0,0 +1,11 @@ +;; by @oponkork +[ + (if_statement) + (where_statement) + (enum_statement) + (do_loop_statement) + (derived_type_definition) + (function) + (subroutine) + (interface) +] @fold \ No newline at end of file diff --git a/runtime/queries/fortran/highlights.scm b/runtime/queries/fortran/highlights.scm new file mode 100644 index 0000000000000..90f4ecd0eb644 --- /dev/null +++ b/runtime/queries/fortran/highlights.scm @@ -0,0 +1,171 @@ +[ + (intrinsic_type) + "dimension" + "intent" + "in" + "out" + "inout" + "type" + "endtype" + "attributes" + "global" + "device" + "host" + "grid_global" + "pointer" +] @keyword.storage.modifier + +[ + "contains" + "public" + "private" +] @keyword.directive + +[ +"implicit" +(none) +] @attribute + +[ + "function" + "endfunction" + "endprogram" + "subroutine" + "endsubroutine" +] @keyword.storage + +[ + "module" + "endmodule" + "bind" + "call" + "class" + "continue" + "cycle" + "enumerator" + "equivalence" + "exit" + "format" + "goto" + "include" + "interface" + "endinterface" + "only" + "parameter" + "procedure" + "print" + "program" + "endprogram" + "read" + "return" + "result" + "stop" + "use" + "write" + "enum" + "endenum" + (default) + (procedure_qualifier) +] @keyword + +[ + "if" + "then" + "else" + "elseif" + "endif" + "where" + "endwhere" +] @keyword.control.conditional + +[ + "do" + "enddo" + "while" + "forall" +] @keyword.control.repeat + +[ + "*" + "**" + "+" + "-" + "/" + "=" + "<" + ">" + "<=" + ">=" + "==" + "/=" +] @operator + +[ + "\\.and\\." + "\\.or\\." + "\\.lt\\." + "\\.gt\\." + "\\.ge\\." + "\\.le\\." + "\\.eq\\." + "\\.eqv\\." + "\\.neqv\\." +] @keyword.operator + + ;; Brackets + [ + "(" + ")" + "[" + "]" + ] @punctuation.bracket + + ;; Delimiter + [ + "::" + "," + "%" + ] @punctuation.delimiter + +(parameters + (identifier) @variable.parameter) + +(program_statement + (name) @namespace) + +(module_statement + (name) @namespace) + +(function_statement + (name) @function) + +(subroutine_statement + (name) @function) + +(end_program_statement + (name) @namespace) + +(end_module_statement + (name) @namespace) + +(end_function_statement + (name) @function) + +(end_subroutine_statement + (name) @function) + +(subroutine_call + (name) @function) + +(keyword_argument + name: (identifier) @keyword) + +(derived_type_member_expression + (type_member) @variable.other.member) + +(identifier) @variable +(string_literal) @string +(number_literal) @constant.numeric +(boolean_literal) @constant.builtin.boolean +(comment) @comment + diff --git a/runtime/queries/fortran/indents.scm b/runtime/queries/fortran/indents.scm new file mode 100644 index 0000000000000..daa8bac1042bc --- /dev/null +++ b/runtime/queries/fortran/indents.scm @@ -0,0 +1,27 @@ +[ + (module) + (program) + (subroutine) + (function) + ; (interface) + (if_statement) + (do_loop_statement) + (where_statement) + (derived_type_definition) + (enum) +] @indent + +[ + (end_module_statement) + (end_program_statement) + (end_subroutine_statement) + (end_function_statement) + ; (end_interface_statement) + (end_if_statement) + (end_do_loop_statement) + (else_clause) + (elseif_clause) + (end_type_statement) + (end_enum_statement) + (end_where_statement) +] @outdent \ No newline at end of file From 930f98053ec88c07ccf4256ee8a5e6f14147e1b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Jul 2022 07:44:00 +0530 Subject: [PATCH 110/584] build(deps): bump serde from 1.0.138 to 1.0.139 (#3040) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00d8c47550d53..a70b6e731274c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -885,18 +885,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" dependencies = [ "proc-macro2", "quote", From fb625697854e3a9d99aa4cfe952f2050b7e82ce0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Jul 2022 11:17:24 +0900 Subject: [PATCH 111/584] build(deps): bump regex from 1.5.5 to 1.6.0 (#3041) Bumps [regex](https://github.com/rust-lang/regex) from 1.5.5 to 1.6.0. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.5.5...1.6.0) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a70b6e731274c..237768b40e38a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -816,9 +816,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -833,9 +833,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" From e97b8607c18c16f14ab17825ac20739c4d83b779 Mon Sep 17 00:00:00 2001 From: Philipp Mildenberger Date: Tue, 12 Jul 2022 17:06:53 +0200 Subject: [PATCH 112/584] Added ungrammar language support (#3048) --- book/src/generated/lang-support.md | 1 + languages.toml | 15 ++++++++++++++- runtime/queries/ungrammar/highlights.scm | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/ungrammar/highlights.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 085d92a8ffc7d..978f42a710a24 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -98,6 +98,7 @@ | tsx | ✓ | | | `typescript-language-server` | | twig | ✓ | | | | | typescript | ✓ | | ✓ | `typescript-language-server` | +| ungrammar | ✓ | | | | | v | ✓ | | | `vls` | | vala | ✓ | | | `vala-language-server` | | verilog | ✓ | ✓ | | `svlangserver` | diff --git a/languages.toml b/languages.toml index 3be20ab358553..20493e4c15057 100644 --- a/languages.toml +++ b/languages.toml @@ -1527,4 +1527,17 @@ language-server = { command = "fortls", args = ["--lowercase_intrinsics"] } [[grammar]] name = "fortran" -source = { git = "https://github.com/stadelmanma/tree-sitter-fortran", rev = "f0f2f100952a353e64e26b0fa710b4c296d7af13" } \ No newline at end of file +source = { git = "https://github.com/stadelmanma/tree-sitter-fortran", rev = "f0f2f100952a353e64e26b0fa710b4c296d7af13" } + +[[language]] +name = "ungrammar" +scope = "source.ungrammar" +injection-regex = "ungrammar" +file-types = ["ungram", "ungrammar"] +roots = [] +comment-token = "//" +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "ungrammar" +source = { git = "https://github.com/Philipp-M/tree-sitter-ungrammar", rev = "0113de880a58ea14f2a75802e9b99fcc25003d9c" } diff --git a/runtime/queries/ungrammar/highlights.scm b/runtime/queries/ungrammar/highlights.scm new file mode 100644 index 0000000000000..cffbdbfdb930f --- /dev/null +++ b/runtime/queries/ungrammar/highlights.scm @@ -0,0 +1,17 @@ +(ERROR) @error + +(line_comment) @comment + +(identifier) @variable + +(token) @string + +[ + "=" + "|" + ":" + "(" + ")" + "?" + "*" +] @operator From 5f69beb87f611a339b5a95aa80d19947eeef8f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=2E=20Szczygie=C5=82?= Date: Tue, 12 Jul 2022 17:13:57 +0200 Subject: [PATCH 113/584] Add textobjects.scm to GLSL (#3051) --- book/src/generated/lang-support.md | 2 +- runtime/queries/glsl/textobjects.scm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/glsl/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 978f42a710a24..64cb32c311bdc 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -31,7 +31,7 @@ | git-ignore | ✓ | | | | | git-rebase | ✓ | | | | | gleam | ✓ | ✓ | | | -| glsl | ✓ | | ✓ | | +| glsl | ✓ | ✓ | ✓ | | | go | ✓ | ✓ | ✓ | `gopls` | | gomod | ✓ | | | `gopls` | | gowork | ✓ | | | `gopls` | diff --git a/runtime/queries/glsl/textobjects.scm b/runtime/queries/glsl/textobjects.scm new file mode 100644 index 0000000000000..a5a5208ca9c7c --- /dev/null +++ b/runtime/queries/glsl/textobjects.scm @@ -0,0 +1 @@ +; inherits: c From 7951ebfd4d790b5dce39eb30944f5542eba80ea0 Mon Sep 17 00:00:00 2001 From: 0rphee <79347623+0rphee@users.noreply.github.com> Date: Tue, 12 Jul 2022 12:42:17 -0500 Subject: [PATCH 114/584] [Theme] Noctis (#3043) --- runtime/themes/noctis.toml | 197 +++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 runtime/themes/noctis.toml diff --git a/runtime/themes/noctis.toml b/runtime/themes/noctis.toml new file mode 100644 index 0000000000000..fe598cf418e38 --- /dev/null +++ b/runtime/themes/noctis.toml @@ -0,0 +1,197 @@ +# Author : 0rphee <0rph3e@proton.me> + +# Template written with the help of https://github.com/n0s4/helix-theme-template +# Keep in mind that I made this to fit Haskell and Python syntax, it may not work so well with other languages. + +## GENERAL ============================== + +"warning" = { fg ="yellow", modifiers = ["bold"] } # Editor warnings. +"error" = { fg = "red", modifiers = ["bold"] } # Editor errors, like mis-typing a command. +"info" = { fg = "mid-blue", bg = "mid-green" } # Code diagnostic info in gutter (LSP). +# ? Difference between info and hint ? +"hint" = { fg = "light-green", modifiers = ["bold"] } # Code diagnostics hint in gutter (LSP). +"diagnostic" = { modifiers = ["underlined"] } # Code diagnostics in editing area (LSP). + +# UI ============================== +# For styling helix itself. + +'ui.background' = { bg = "dark-green"} # Default background color. +'ui.window' = { fg = "mid-green" } # Window border between splits. + +'ui.gutter' = { } # Left gutter for diagnostics and breakpoints. + +'ui.text' = { fg = "white" } # Default text color. +'ui.text.focus' = { fg = "white", bg = "mid-green", modifiers = ["bold"] } # Selection highlight in buffer-picker or file-picker. +'ui.text.info' = { } # Info popup contents (space mode menu). + +'ui.cursor' = { fg = "light-blue", modifiers = ["reversed"] } # Fallback cursor colour, non-primary cursors when there are multiple (shift-c). +'ui.cursor.primary' = { fg = "light-blue", modifiers = ["reversed"] } # The primary cursor when there are multiple (shift-c). +'ui.cursor.insert' = { fg = "light-blue" } # The cursor in insert mode (i). +'ui.cursor.select' = { fg = "light-blue" } # The cursor in select mode (v). +'ui.cursor.match' = { fg = "red", modifiers = ["bold", "reversed"] } # The matching parentheses of that under the cursor. + +'ui.selection' = { bg = "mid-green" } # All currently selected text. +'ui.selection.primary' = { bg = "mid-green" } # The primary selection when there are multiple. +'ui.cursorline.primary' = { bg = 'mid-green' } + +'ui.linenr' = { bg = "dark-green", fg = "gray" } # Line numbers. +'ui.linenr.selected' = { bg = "mid-green", fg = "light-green", modifiers = [ "bold" ] } # Current line number. + +'ui.virtual' = { fg = "mid-green" } # Namespace for additions to the editing area. +'ui.virtual.ruler' = { bg = "mid-green" } # Vertical rulers (colored columns in editing area). +'ui.virtual.whitespace' = { fg = "gray"} # Whitespace markers in editing area. +'ui.virtual.indent-guide' = { fg = "gray" } # Indentation guides. + +'ui.statusline' = { fg = "white", bg = "autocomp-green"} # Status line. +'ui.statusline.inactive' = { fg = "white", bg = "mid-green"} # Status line in unfocused windows. + +'ui.help' = { bg = "mid-green", fg = "white"} # `:command` descriptions above the command line. + +'ui.highlight' = { bg = "mid-green"} # selected contents of symbol pickers (spc-s, spc-S) and current line in buffer picker (spc-b). + +'ui.menu' = { fg = "gray", bg = "mid-green" } # Autocomplete menu. +'ui.menu.selected' = { fg = "white", bg = "autocomp-green" } # Selected autocomplete item. + +'ui.popup' = { bg = "mid-green" } # Documentation popups (space-k). +# 'ui.ppopup.info' = { bg = "midgreen", fg = "gray", modifiers = ["bold"] } # Info popups box (space mode menu). + +# SYNTAX HIGHLIGHTING ============================== +# All the keys here are Treesitter scopes. + +'property' = { fg = "red" } # Regex group names. +'special' = { fg = "mid-blue"} # Special symbols e.g `?` in Rust, `...` in Hare. +'attribute' = { fg = "yellow" } # Class attributes, html tag attributes. + +'type' = { fg = "orange"} # Variable type, like integer or string, including program defined classes, structs etc.. +#'type.builtin' = { } # Primitive types of the language (string, int, float). +#'type.enum.variant' = { } # A variant of an enum. + +'constructor' = { fg = "mid-blue", modifiers = ["bold"]} # Constructor method for a class or struct. And in some cases applies to module names + +'constant' = { fg = "light-blue" } # Constant value +'constant.builtin' = { fg = "mid-blue", modifiers = ["bold"] } # Special constants like `true`, `false`, `none`, etc. +'constant.builtin.boolean' = { } # True or False. +'constant.character' = { fg = "light-green"} # Constant of character type. +'constant.character.escape' = { fg = "purple", modifiers = ["bold"] } # escape codes like \n. +'constant.numeric' = { fg = "purple"} # constant integer or float value. +# 'constant.numeric.integer' = { } # constant integer value. +# 'constant.numeric.float' = { } # constant float value. + +'string' = { fg = "light-green" } # String literal. +'string.regexp' = { } # Regular expression literal. +'string.special' = { fg = "light-blue" } # Strings containing a path, URL, etc. +'string.special.path' = { } # String containing a file path. +'string.special.url' = { } # String containing a web URL. +'string.special.symbol' = { } # Erlang/Elixir atoms, Ruby symbols, Clojure keywords. + +'comment' = { fg = "gray", modifiers = ["italic"] } # This is a comment. +'comment.line' = { } # Line comments, like this. +'comment.block' = { } # Block comments, like /* this */ in some languages. +'comment.block.documentation' = { } # Doc comments, e.g '///' in rust. + +'variable' = { fg = "white" } # Variable names. +'variable.builtin' = { } # Language reserved variables: `this`, `self`, `super`, etc. +'variable.parameter' = { } # Funtion parameters. +'variable.other.member' = { } # Fields of composite data types (e.g. structs, unions). +'variable.function' = { } # ? + +'label' = { fg = "purple" } # Loop labels in rust. + +'punctuation' = { fg = "yellow", modifiers = ["bold"] } # (){}[]:;,. +# 'punctuation.delimeter' = { fg = "yellow" } # Commas and colons. +# 'punctuation.bracket' = { fg = "yellow" } # Parentheses, angle brackets, etc. + +'keyword' = { fg = "pink", modifiers = ["bold"] } # Language reserved keywords. +'keyword.control' = { fg = "pink", modifiers = ["bold"] } # Control keywords. +'keyword.control.conditional' = { fg = "pink", modifiers = ["bold"] } # 'if', 'else', 'elif'. +'keyword.control.repeat' = { } # 'for', 'while', 'loop'. +'keyword.control.import' = { fg = "pink", modifiers = ["italic"] } # 'import', 'export' ('use'?). +'keyword.control.return' = { } # 'return' in most languages. +'keyword.control.exception' = {fg = "pink", modifiers = ["bold"] } # 'raise' in python. +'keyword.operator' = { } # 'or', 'and', 'in'. +'keyword.directive' = { fg = "purple" } # Preprocessor directives (#if in C). +'keyword.function' = { } # The keyword to define a funtion: 'def', 'fun', 'fn'. + +'operator' = { fg = "pink", modifiers = ["bold"] } # Logical (&&, ||) and - I assume - Mathematical (+, %) operators + +'function' = { fg = "dark-blue"} +'function.builtin' = { fg = "dark-blue" } +'function.method' = { fg = "dark-blue" } # Class / Struct methods. +'function.macro' = { fg = "purple" } # Like macros in rust. +# 'function.special' = { fg = "yellow" } # Preprocessor in C. + +'tag' = { fg = "yellow"} # As in for html. + +'namespace' = { fg = "mid-blue" } # * Namespace keyword in java, C#, etc. + + +# Markup ============================== +# Colors for markup languages, like Markdown or XML. + +'markup.heading' = { } # Markdown headings +'markup.heading.1' = { } # Markdown heading 1 color. +'markup.heading.2' = { } # Markdown heading 2 color. +'markup.heading.3' = { } # Markdown heading 3 color. +'markup.heading.4' = { } # Markdown heading 4 color. +'markup.heading.5' = { } # Markdown heading 5 color. +'markup.heading.6' = { } # Markdown heading 6 color. +'markup.heading.marker' = { fg = "red" } # Hashtag color on Markdown headings. + +'markup.list' = { fg = "red" } +'markup.list.numbered' = { } # Numbered list. +'markup.list.unnumbered' = { } # Bullet point list. + +'markup.bold' = { modifiers = ["bold"] } # Bold text. +'markup.italic' = { modifiers = ["italic"] } # Italicised text. + +'markup.link' = { fg = "light-blue", modifiers = ["underlined"] } +'markup.link.url' = { } # Urls pointed to by links. +'markup.link.label' = { } # Non-URL link references. +'markup.link.text' = { fg = "purple"} # URL and image descriptions in links. + +'markup.quote' = { } # `> Quotes` in Markdown. + + +# Markup - Interface ============================== +# "These scopes are used for theming the editor interface." + +'markup.normal' = { } +'markup.normal.completion' = { } # For completion doc popup ui. +'markup.normal.raw' = { } # For hover popup ui. + +'markup.heading.completion' = { } # Headings for completion doc popup ui. +'markup.heading.raw' = { } # Headings for hover popup ui. + +'markup.raw' = { } # Code block in Markdown. +'markup.raw.block' = { } # Multiline (```) codeblock in Markdown. +'markup.raw.inline' = { } # `Inline code block` in Markdown. +'markup.raw.inline.completion' = { } # ? +'markup.raw.inline.hover' = { } # ? + +# Diff ============================== +# Version control changes. + +'diff.plus' = "light-green" # { } # Additions. +'diff.minus' = "yelllow" # { } # Deletions. +'diff.delta' = "red" # { } # Modifications. +'diff.delta.moved' = { } # Renamed or moved files / changes. + + +[palette] # Define your custom colors here. +dark-green = "#00262a" # backgrounds +mid-green = "#073a40" # highlights +autocomp-green = "#0d6772" # lighter than mid-green +light-green = "#48e9a7" # strings + +pink = "#df769b" +yellow = "#ffd800" +purple = "#6f60ea" +white = "#b1cace" +orange = "#e4b782" +gray = "#5b858b" # mainly for comments/background text +red = "#e34e1b" + +dark-blue = "#19a2b7" +mid-blue = "#47ace8" +light-blue = "#87efff" + From 3cced1e3c825b0ae527f43358b29d9595c54065b Mon Sep 17 00:00:00 2001 From: Termina94 <47091253+Termina94@users.noreply.github.com> Date: Tue, 12 Jul 2022 21:18:41 +0100 Subject: [PATCH 115/584] Add cursorline colour to darkplus theme (#3054) Co-authored-by: Dean Revell --- runtime/themes/dark_plus.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/themes/dark_plus.toml b/runtime/themes/dark_plus.toml index 957ca61d486f7..b622df2f916d7 100644 --- a/runtime/themes/dark_plus.toml +++ b/runtime/themes/dark_plus.toml @@ -72,6 +72,7 @@ "ui.linenr" = { fg = "dark_gray" } "ui.linenr.selected" = { fg = "light_gray2" } +"ui.cursorline.primary" = { bg = "dark_gray3" } "ui.statusline" = { fg = "white", bg = "blue" } "ui.statusline.inactive" = { fg = "white", bg = "blue" } @@ -100,6 +101,7 @@ light_gray2 = "#c6c6c6" light_gray3 = "#eeeeee" dark_gray = "#858585" dark_gray2 = "#1e1e1e" +dark_gray3= "#282828" blue = "#007acc" blue2 = "#569CD6" blue3 = "#6796E6" From e6a6e251c5cb2c373584187c3d4d17b3eaac6b6a Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 13 Jul 2022 23:00:24 +0800 Subject: [PATCH 116/584] respect count for repeating motion (#3057) --- helix-term/src/commands.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 193d5d405fb21..cb223faf07cfa 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1224,9 +1224,12 @@ fn extend_prev_char(cx: &mut Context) { } fn repeat_last_motion(cx: &mut Context) { + let count = cx.count(); let last_motion = cx.editor.last_motion.take(); if let Some(m) = &last_motion { - m.run(cx.editor); + for _ in 0..count { + m.run(cx.editor); + } cx.editor.last_motion = last_motion; } } From 4418924ec34c28e43ce34809edaac4ce4fd9f72c Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 13 Jul 2022 23:01:42 +0800 Subject: [PATCH 117/584] respect count for selecting next/previous match (#3056) --- helix-term/src/commands.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index cb223faf07cfa..dad3db8693a82 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1687,6 +1687,7 @@ fn searcher(cx: &mut Context, direction: Direction) { } fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Direction) { + let count = cx.count(); let config = cx.editor.config(); let scrolloff = config.scrolloff; let (view, doc) = current!(cx.editor); @@ -1705,16 +1706,18 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir .multi_line(true) .build() { - search_impl( - doc, - view, - &contents, - ®ex, - movement, - direction, - scrolloff, - wrap_around, - ); + for _ in 0..count { + search_impl( + doc, + view, + &contents, + ®ex, + movement, + direction, + scrolloff, + wrap_around, + ); + } } else { let error = format!("Invalid regex: {}", query); cx.editor.set_error(error); From 8681fb6d9ee06610fac2baafb4ca34f93f9c7f4d Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 14 Jul 2022 08:08:09 +0800 Subject: [PATCH 118/584] respect count in treesitter movement (#3058) --- helix-core/src/movement.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs index 2155f77a42a46..fa8cdf3ad1e0b 100644 --- a/helix-core/src/movement.rs +++ b/helix-core/src/movement.rs @@ -396,9 +396,9 @@ pub fn goto_treesitter_object( dir: Direction, slice_tree: Node, lang_config: &LanguageConfiguration, - _count: usize, + count: usize, ) -> Range { - let get_range = move || -> Option { + let get_range = move |range: Range| -> Option { let byte_pos = slice.char_to_byte(range.cursor(slice)); let cap_name = |t: TextObject| format!("{}.{}", object_name, t); @@ -436,7 +436,7 @@ pub fn goto_treesitter_object( // head of range should be at beginning Some(Range::new(end_char, start_char)) }; - get_range().unwrap_or(range) + (0..count).fold(range, |range, _| get_range(range).unwrap_or(range)) } #[cfg(test)] From 333ab278374863296ebef5154340f33482e13edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Cortier?= Date: Fri, 15 Jul 2022 09:59:00 -0400 Subject: [PATCH 119/584] feat(term): uniformize word-wise movement and deletion (#2500) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ctrl-based shortcuts are common in numerous applications. This change: - Adds Ctrl+{Left/Right/Backspace/Delete} for word-wise movement/deletion in prompt, picker, … - Removes Alt-Left and Alt-Right in prompt, picker, … - Adds Alt-Delete in insert mode for forward word deletion In some terminals, Alt-Backspace might not work because it is ambigous. See: https://github.com/helix-editor/helix/pull/2193#issuecomment-1105042501 Hence, Alt alternative is not removed. --- book/src/keymap.md | 93 ++++++++++++++++---------------- helix-term/src/application.rs | 2 +- helix-term/src/keymap/default.rs | 1 + helix-term/src/ui/prompt.rs | 8 +-- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index 5daeec3fa3b5e..de2980376dc4d 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -298,30 +298,30 @@ convenience. These can be helpful for making simple modifications without escaping to normal mode, but beware that you will not have an undo-able "save point" until you return to normal mode. -| Key | Description | Command | -| ----- | ----------- | ------- | -| `Escape` | Switch to normal mode | `normal_mode` | -| `Ctrl-x` | Autocomplete | `completion` | -| `Ctrl-r` | Insert a register content | `insert_register` | -| `Ctrl-w`, `Alt-Backspace` | Delete previous word | `delete_word_backward` | -| `Alt-d` | Delete next word | `delete_word_forward` | -| `Alt-b`, `Ctrl-Left` | Backward a word | `move_prev_word_end` | -| `Ctrl-b`, `Left` | Backward a char | `move_char_left` | -| `Alt-f`, `Ctrl-Right` | Forward a word | `move_next_word_start` | -| `Ctrl-f`, `Right` | Forward a char | `move_char_right` | -| `Ctrl-e`, `End` | Move to line end | `goto_line_end_newline` | -| `Ctrl-a`, `Home` | Move to line start | `goto_line_start` | -| `Ctrl-u` | Delete to start of line | `kill_to_line_start` | -| `Ctrl-k` | Delete to end of line | `kill_to_line_end` | -| `Ctrl-j`, `Enter` | Insert new line | `insert_newline` | -| `Backspace`, `Ctrl-h` | Delete previous char | `delete_char_backward` | -| `Delete`, `Ctrl-d` | Delete next char | `delete_char_forward` | -| `Ctrl-p`, `Up` | Move to previous line | `move_line_up` | -| `Ctrl-n`, `Down` | Move to next line | `move_line_down` | -| `PageUp` | Move one page up | `page_up` | -| `PageDown` | Move one page down | `page_down` | -| `Alt->` | Go to end of buffer | `goto_file_end` | -| `Alt-<` | Go to start of buffer | `goto_file_start` | +| Key | Description | Command | +| ----- | ----------- | ------- | +| `Escape` | Switch to normal mode | `normal_mode` | +| `Ctrl-x` | Autocomplete | `completion` | +| `Ctrl-r` | Insert a register content | `insert_register` | +| `Ctrl-w`, `Alt-Backspace`, `Ctrl-Backspace` | Delete previous word | `delete_word_backward` | +| `Alt-d`, `Alt-Delete`, `Ctrl-Delete` | Delete next word | `delete_word_forward` | +| `Alt-b`, `Ctrl-Left` | Backward a word | `move_prev_word_end` | +| `Ctrl-b`, `Left` | Backward a char | `move_char_left` | +| `Alt-f`, `Ctrl-Right` | Forward a word | `move_next_word_start` | +| `Ctrl-f`, `Right` | Forward a char | `move_char_right` | +| `Ctrl-e`, `End` | Move to line end | `goto_line_end_newline` | +| `Ctrl-a`, `Home` | Move to line start | `goto_line_start` | +| `Ctrl-u` | Delete to start of line | `kill_to_line_start` | +| `Ctrl-k` | Delete to end of line | `kill_to_line_end` | +| `Ctrl-j`, `Enter` | Insert new line | `insert_newline` | +| `Backspace`, `Ctrl-h` | Delete previous char | `delete_char_backward` | +| `Delete`, `Ctrl-d` | Delete next char | `delete_char_forward` | +| `Ctrl-p`, `Up` | Move to previous line | `move_line_up` | +| `Ctrl-n`, `Down` | Move to next line | `move_line_down` | +| `PageUp` | Move one page up | `page_up` | +| `PageDown` | Move one page down | `page_down` | +| `Alt->` | Go to end of buffer | `goto_file_end` | +| `Alt-<` | Go to start of buffer | `goto_file_start` | ## Select / extend mode @@ -358,26 +358,25 @@ Keys to use within picker. Remapping currently not supported. Keys to use within prompt, Remapping currently not supported. -| Key | Description | -| ----- | ------------- | -| `Escape`, `Ctrl-c` | Close prompt | -| `Alt-b`, `Alt-Left` | Backward a word | -| `Ctrl-b`, `Left` | Backward a char | -| `Alt-f`, `Alt-Right` | Forward a word | -| `Ctrl-f`, `Right` | Forward a char | -| `Ctrl-e`, `End` | Move prompt end | -| `Ctrl-a`, `Home` | Move prompt start | -| `Ctrl-w` | Delete previous word | -| `Alt-d` | Delete next word | -| `Ctrl-u` | Delete to start of line | -| `Ctrl-k` | Delete to end of line | -| `backspace`, `Ctrl-h` | Delete previous char | -| `delete`, `Ctrl-d` | Delete next char | -| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later | -| `Ctrl-p`, `Up` | Select previous history | -| `Ctrl-n`, `Down` | Select next history | -| `Ctrl-r` | Insert the content of the register selected by following input char | -| `Tab` | Select next completion item | -| `BackTab` | Select previous completion item | -| `Enter` | Open selected | - +| Key | Description | +| ----- | ------------- | +| `Escape`, `Ctrl-c` | Close prompt | +| `Alt-b`, `Ctrl-Left` | Backward a word | +| `Ctrl-b`, `Left` | Backward a char | +| `Alt-f`, `Ctrl-Right` | Forward a word | +| `Ctrl-f`, `Right` | Forward a char | +| `Ctrl-e`, `End` | Move prompt end | +| `Ctrl-a`, `Home` | Move prompt start | +| `Ctrl-w`, `Alt-Backspace`, `Ctrl-Backspace` | Delete previous word | +| `Alt-d`, `Alt-Delete`, `Ctrl-Delete` | Delete next word | +| `Ctrl-u` | Delete to start of line | +| `Ctrl-k` | Delete to end of line | +| `backspace`, `Ctrl-h` | Delete previous char | +| `delete`, `Ctrl-d` | Delete next char | +| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later | +| `Ctrl-p`, `Up` | Select previous history | +| `Ctrl-n`, `Down` | Select next history | +| `Ctrl-r` | Insert the content of the register selected by following input char | +| `Tab` | Select next completion item | +| `BackTab` | Select previous completion item | +| `Enter` | Open selected | diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index d3899075c7524..f4f0876cf6f1c 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -350,7 +350,7 @@ impl Application { } fn refresh_config(&mut self) { - let config = Config::load(helix_loader::config_file()).unwrap_or_else(|err| { + let config = Config::load_default().unwrap_or_else(|err| { self.editor.set_error(err.to_string()); Config::default() }); diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 9b1447581b985..b8c1a4007f236 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -351,6 +351,7 @@ pub fn default() -> HashMap { "C-w" => delete_word_backward, "A-backspace" => delete_word_backward, "A-d" => delete_word_forward, + "A-del" => delete_word_forward, "C-s" => commit_undo_checkpoint, "left" => move_char_left, diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index 55b08032dfc97..36ee62c357ea8 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -477,14 +477,14 @@ impl Component for Prompt { (self.callback_fn)(cx, &self.line, PromptEvent::Abort); return close_fn; } - alt!('b') | alt!(Left) => self.move_cursor(Movement::BackwardWord(1)), - alt!('f') | alt!(Right) => self.move_cursor(Movement::ForwardWord(1)), + alt!('b') | ctrl!(Left) => self.move_cursor(Movement::BackwardWord(1)), + alt!('f') | ctrl!(Right) => self.move_cursor(Movement::ForwardWord(1)), ctrl!('b') | key!(Left) => self.move_cursor(Movement::BackwardChar(1)), ctrl!('f') | key!(Right) => self.move_cursor(Movement::ForwardChar(1)), ctrl!('e') | key!(End) => self.move_end(), ctrl!('a') | key!(Home) => self.move_start(), - ctrl!('w') => self.delete_word_backwards(cx), - alt!('d') => self.delete_word_forwards(cx), + ctrl!('w') | alt!(Backspace) | ctrl!(Backspace) => self.delete_word_backwards(cx), + alt!('d') | alt!(Delete) | ctrl!(Delete) => self.delete_word_forwards(cx), ctrl!('k') => self.kill_to_end_of_line(cx), ctrl!('u') => self.kill_to_start_of_line(cx), ctrl!('h') | key!(Backspace) => { From bcacc703d737300e3e315b0b8a4716cdf306da87 Mon Sep 17 00:00:00 2001 From: Alex Kim <45559664+alex-kim-dev@users.noreply.github.com> Date: Fri, 15 Jul 2022 19:51:34 +0500 Subject: [PATCH 120/584] fix wrong value for cursor shape config in the docs (#3081) --- book/src/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 1cc8602adac11..0a6e5fdd089e1 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -60,7 +60,7 @@ 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. -Valid values for these options are `block`, `bar`, `underline`, or `none`. +Valid values for these options are `block`, `bar`, `underline`, or `hidden`. | Key | Description | Default | | --- | ----------- | ------- | From 0c9594e41ea18f71a0b1de386396575e6f73fc12 Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 17 Jul 2022 05:55:20 -0400 Subject: [PATCH 121/584] Add SCSS language support (#3074) --- book/src/generated/lang-support.md | 1 + languages.toml | 13 +++++ runtime/queries/scss/highlights.scm | 86 +++++++++++++++++++++++++++++ runtime/queries/scss/injections.scm | 2 + 4 files changed, 102 insertions(+) create mode 100644 runtime/queries/scss/highlights.scm create mode 100644 runtime/queries/scss/injections.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 64cb32c311bdc..aecf80acb305e 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -85,6 +85,7 @@ | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | | scheme | ✓ | | | | +| scss | ✓ | | | `vscode-css-language-server` | | solidity | ✓ | | | `solc` | | sql | ✓ | | | | | sshclientconfig | ✓ | | | | diff --git a/languages.toml b/languages.toml index 20493e4c15057..cd87d79bac6d4 100644 --- a/languages.toml +++ b/languages.toml @@ -381,6 +381,19 @@ indent = { tab-width = 2, unit = " " } name = "css" source = { git = "https://github.com/tree-sitter/tree-sitter-css", rev = "94e10230939e702b4fa3fa2cb5c3bc7173b95d07" } +[[language]] +name = "scss" +scope = "source.scss" +injection-regex = "scss" +file-types = ["scss"] +roots = [] +language-server = { command = "vscode-css-language-server", args = ["--stdio"] } +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "scss" +source = { git = "https://github.com/serenadeai/tree-sitter-scss.git", rev = "c478c6868648eff49eb04a4df90d703dc45b312a" } + [[language]] name = "html" scope = "text.html.basic" diff --git a/runtime/queries/scss/highlights.scm b/runtime/queries/scss/highlights.scm new file mode 100644 index 0000000000000..89cce49442c2c --- /dev/null +++ b/runtime/queries/scss/highlights.scm @@ -0,0 +1,86 @@ +(comment) @comment + +"~" @operator +">" @operator +"+" @operator +"-" @operator +"*" @operator +"/" @operator +"=" @operator +"^=" @operator +"|=" @operator +"~=" @operator +"$=" @operator +"*=" @operator + +"in" @operator +"and" @operator +"or" @operator +"not" @operator +"only" @operator + +"@apply" @constant.builtin +"@at-root" @constant.builtin +"@charset" @constant.builtin +"@debug" @constant.builtin +"@each" @keyword.control.repeat +"@else" @keyword.control.conditional +"@error" @constant.builtin +"@extend" @constant.builtin +"@for" @keyword.control.repeat +"@forward" @keyword.control.import +"@function" @function.method +"@if" @keyword.control.conditional +"@import" @keyword.control.import +"@include" @keyword.control.import +"@keyframes" @constant.builtin +"@media" @constant.builtin +"@mixin" @constant.builtin +"@namespace" @namespace +"@return" @keyword.control.return +"@supports" @constant.builtin +"@use" @keyword.control.import +"@warn" @constant.builtin +"@while" @keyword.control.repeat + +((property_name) @variable + (match? @variable "^--")) +((plain_value) @variable + (match? @variable "^--")) + +(tag_name) @tag +(universal_selector) @tag +(attribute_selector (plain_value) @string) +(nesting_selector) @variable.other.member +(pseudo_element_selector) @attribute +(pseudo_class_selector) @attribute + +(identifier) @variable +(class_name) @variable +(id_name) @variable +(namespace_name) @variable +(property_name) @variable.other.member +(feature_name) @variable +(variable) @variable +(variable_name) @variable.other.member +(variable_value) @variable.other.member +(argument_name) @variable.parameter +(selectors) @variable.other.member + +(attribute_name) @attribute + +(function_name) @function + +(to) @keyword +(from) @keyword +(important) @keyword + +(string_value) @string +(color_value) @string.special + +(integer_value) @constant.numeric.integer +(float_value) @constant.numeric.float +(unit) @type + +"#" @punctuation.delimiter +"," @punctuation.delimiter diff --git a/runtime/queries/scss/injections.scm b/runtime/queries/scss/injections.scm new file mode 100644 index 0000000000000..321c90add3710 --- /dev/null +++ b/runtime/queries/scss/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) From 43761d426cb0c508bfcea93c4bf1d08949e6c7c1 Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 17 Jul 2022 12:11:05 -0400 Subject: [PATCH 122/584] Remove .git extension from SCSS tree-sitter repo url (#3089) --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index cd87d79bac6d4..f9dac467ea2c0 100644 --- a/languages.toml +++ b/languages.toml @@ -392,7 +392,7 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "scss" -source = { git = "https://github.com/serenadeai/tree-sitter-scss.git", rev = "c478c6868648eff49eb04a4df90d703dc45b312a" } +source = { git = "https://github.com/serenadeai/tree-sitter-scss", rev = "c478c6868648eff49eb04a4df90d703dc45b312a" } [[language]] name = "html" From dbf68e0370981dc4ad0fa74596b57347f7048fab Mon Sep 17 00:00:00 2001 From: "Mr. E" <2804556+etienne-k@users.noreply.github.com> Date: Mon, 18 Jul 2022 02:57:01 +0200 Subject: [PATCH 123/584] Customizable/configurable status line (#2434) * feat(statusline): add the file type (language id) to the status line * refactor(statusline): move the statusline implementation into an own struct * refactor(statusline): split the statusline implementation into different functions * refactor(statusline): Append elements using a consistent API This is a preparation for the configurability which is about to be implemented. * refactor(statusline): implement render_diagnostics() This avoid cluttering the render() function and will simplify configurability. * feat(statusline): make the status line configurable * refactor(statusline): make clippy happy * refactor(statusline): avoid intermediate StatusLineObject Use a more functional approach to obtain render functions and write to the buffers, and avoid an intermediate StatusLineElement object. * fix(statusline): avoid rendering the left elements twice * refactor(statusline): make clippy happy again * refactor(statusline): rename `buffer` into `parts` * refactor(statusline): ensure the match is exhaustive * fix(statusline): avoid an overflow when calculating the maximal center width * chore(statusline): Describe the statusline configurability in the book * chore(statusline): Correct and add documentation * refactor(statusline): refactor some code following the code review Avoid very small helper functions for the diagnositcs and inline them instead. Rename the config field `status_line` to `statusline` to remain consistent with `bufferline`. * chore(statusline): adjust documentation following the config field refactoring * revert(statusline): revert regression introduced by c0a1870 * chore(statusline): slight adjustment in the configuration documentation * feat(statusline): integrate changes from #2676 after rebasing * refactor(statusline): remove the StatusLine struct Because none of the functions need `Self` and all of them are in an own file, there is no explicit need for the struct. * fix(statusline): restore the configurability of color modes The configuration was ignored after reintegrating the changes of #2676 in 8d28f95. * fix(statusline): remove the spinner padding * refactor(statusline): remove unnecessary format!() --- book/src/configuration.md | 32 +++- helix-term/src/ui/editor.rs | 163 +---------------- helix-term/src/ui/mod.rs | 1 + helix-term/src/ui/statusline.rs | 310 ++++++++++++++++++++++++++++++++ helix-view/src/editor.rs | 51 ++++++ 5 files changed, 401 insertions(+), 156 deletions(-) create mode 100644 helix-term/src/ui/statusline.rs diff --git a/book/src/configuration.md b/book/src/configuration.md index 0a6e5fdd089e1..4c849f2625b14 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -48,13 +48,43 @@ hidden = false | `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file. | `[]` | | `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` | +### `[editor.statusline]` Section + +Allows configuring the statusline at the bottom of the editor. + +The configuration distinguishes between three areas of the status line: + +`[ ... ... LEFT ... ... | ... ... ... ... CENTER ... ... ... ... | ... ... RIGHT ... ... ]` + +Statusline elements can be defined as follows: + +```toml +[editor.statusline] +left = ["mode", "spinner"] +center = ["file-name"] +right = ["diagnostics", "selections", "position", "file-encoding", "file-type"] +``` + +The following elements can be configured: + +| Key | Description | +| ------ | ----------- | +| `mode` | The current editor mode (`NOR`/`INS`/`SEL`) | +| `spinner` | A progress spinner indicating LSP activity | +| `file-name` | The path/name of the opened file | +| `file-encoding` | The encoding of the opened file if it differs from UTF-8 | +| `file-type` | The type of the opened file | +| `diagnostics` | The number of warnings and/or errors | +| `selections` | The number of active selections | +| `position` | The cursor position | + ### `[editor.lsp]` Section | Key | Description | Default | | --- | ----------- | ------- | | `display-messages` | Display LSP progress messages below statusline[^1] | `false` | -[^1]: A progress spinner is always shown in the statusline beside the file path. +[^1]: By default, a progress spinner is shown in the statusline beside the file path. ### `[editor.cursor-shape]` Section diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index a7c67a219b33f..9b8bf8eb593d9 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -7,7 +7,6 @@ use crate::{ }; use helix_core::{ - coords_at_pos, encoding, graphemes::{ ensure_grapheme_boundary_next_byte, next_grapheme_boundary, prev_grapheme_boundary, }, @@ -17,7 +16,7 @@ use helix_core::{ LineEnding, Position, Range, Selection, Transaction, }; use helix_view::{ - document::{Mode, SCRATCH_BUFFER_NAME}, + document::Mode, editor::{CompleteAction, CursorShapeConfig}, graphics::{Color, CursorKind, Modifier, Rect, Style}, input::KeyEvent, @@ -29,6 +28,8 @@ use std::borrow::Cow; use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind}; use tui::buffer::Buffer as Surface; +use super::statusline; + pub struct EditorView { pub keymaps: Keymaps, on_next_key: Option>, @@ -161,7 +162,11 @@ impl EditorView { .area .clip_top(view.area.height.saturating_sub(1)) .clip_bottom(1); // -1 from bottom to remove commandline - self.render_statusline(editor, doc, view, statusline_area, surface, is_focused); + + let mut context = + statusline::RenderContext::new(editor, doc, view, is_focused, &self.spinners); + + statusline::render(&mut context, statusline_area, surface); } pub fn render_rulers( @@ -730,158 +735,6 @@ impl EditorView { } } - pub fn render_statusline( - &self, - editor: &Editor, - doc: &Document, - view: &View, - viewport: Rect, - surface: &mut Surface, - is_focused: bool, - ) { - use tui::text::{Span, Spans}; - - //------------------------------- - // Left side of the status line. - //------------------------------- - - let theme = &editor.theme; - let (mode, mode_style) = match doc.mode() { - Mode::Insert => (" INS ", theme.get("ui.statusline.insert")), - Mode::Select => (" SEL ", theme.get("ui.statusline.select")), - Mode::Normal => (" NOR ", theme.get("ui.statusline.normal")), - }; - let progress = doc - .language_server() - .and_then(|srv| { - self.spinners - .get(srv.id()) - .and_then(|spinner| spinner.frame()) - }) - .unwrap_or(""); - - let base_style = if is_focused { - theme.get("ui.statusline") - } else { - theme.get("ui.statusline.inactive") - }; - // statusline - surface.set_style(viewport.with_height(1), base_style); - if is_focused { - let color_modes = editor.config().color_modes; - surface.set_string( - viewport.x, - viewport.y, - mode, - if color_modes { mode_style } else { base_style }, - ); - } - surface.set_string(viewport.x + 5, viewport.y, progress, base_style); - - //------------------------------- - // Right side of the status line. - //------------------------------- - - let mut right_side_text = Spans::default(); - - // Compute the individual info strings and add them to `right_side_text`. - - // Diagnostics - let diags = doc.diagnostics().iter().fold((0, 0), |mut counts, diag| { - use helix_core::diagnostic::Severity; - match diag.severity { - Some(Severity::Warning) => counts.0 += 1, - Some(Severity::Error) | None => counts.1 += 1, - _ => {} - } - counts - }); - let (warnings, errors) = diags; - let warning_style = theme.get("warning"); - let error_style = theme.get("error"); - for i in 0..2 { - let (count, style) = match i { - 0 => (warnings, warning_style), - 1 => (errors, error_style), - _ => unreachable!(), - }; - if count == 0 { - continue; - } - let style = base_style.patch(style); - right_side_text.0.push(Span::styled("●", style)); - right_side_text - .0 - .push(Span::styled(format!(" {} ", count), base_style)); - } - - // Selections - let sels_count = doc.selection(view.id).len(); - right_side_text.0.push(Span::styled( - format!( - " {} sel{} ", - sels_count, - if sels_count == 1 { "" } else { "s" } - ), - base_style, - )); - - // Position - let pos = coords_at_pos( - doc.text().slice(..), - doc.selection(view.id) - .primary() - .cursor(doc.text().slice(..)), - ); - right_side_text.0.push(Span::styled( - format!(" {}:{} ", pos.row + 1, pos.col + 1), // Convert to 1-indexing. - base_style, - )); - - let enc = doc.encoding(); - if enc != encoding::UTF_8 { - right_side_text - .0 - .push(Span::styled(format!(" {} ", enc.name()), base_style)); - } - - // Render to the statusline. - surface.set_spans( - viewport.x - + viewport - .width - .saturating_sub(right_side_text.width() as u16), - viewport.y, - &right_side_text, - right_side_text.width() as u16, - ); - - //------------------------------- - // Middle / File path / Title - //------------------------------- - let title = { - let rel_path = doc.relative_path(); - let path = rel_path - .as_ref() - .map(|p| p.to_string_lossy()) - .unwrap_or_else(|| SCRATCH_BUFFER_NAME.into()); - format!("{}{}", path, if doc.is_modified() { "[+]" } else { "" }) - }; - - surface.set_string_truncated( - viewport.x + 8, // 8: 1 space + 3 char mode string + 1 space + 1 spinner + 1 space - viewport.y, - &title, - viewport - .width - .saturating_sub(6) - .saturating_sub(right_side_text.width() as u16 + 1) as usize, // "+ 1": a space between the title and the selection info - |_| base_style, - true, - true, - ); - } - /// Handle events by looking them up in `self.keymaps`. Returns None /// if event was handled (a command was executed or a subkeymap was /// activated). Only KeymapResult::{NotFound, Cancelled} is returned diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index ca4cedb55de3b..c7d409e9653ab 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -8,6 +8,7 @@ mod picker; mod popup; mod prompt; mod spinner; +mod statusline; mod text; pub use completion::Completion; diff --git a/helix-term/src/ui/statusline.rs b/helix-term/src/ui/statusline.rs new file mode 100644 index 0000000000000..895043cd1154c --- /dev/null +++ b/helix-term/src/ui/statusline.rs @@ -0,0 +1,310 @@ +use helix_core::{coords_at_pos, encoding}; +use helix_view::{ + document::{Mode, SCRATCH_BUFFER_NAME}, + graphics::Rect, + theme::Style, + Document, Editor, View, +}; + +use crate::ui::ProgressSpinners; + +use helix_view::editor::StatusLineElement as StatusLineElementID; +use tui::buffer::Buffer as Surface; +use tui::text::{Span, Spans}; + +pub struct RenderContext<'a> { + pub editor: &'a Editor, + pub doc: &'a Document, + pub view: &'a View, + pub focused: bool, + pub spinners: &'a ProgressSpinners, + pub parts: RenderBuffer<'a>, +} + +impl<'a> RenderContext<'a> { + pub fn new( + editor: &'a Editor, + doc: &'a Document, + view: &'a View, + focused: bool, + spinners: &'a ProgressSpinners, + ) -> Self { + RenderContext { + editor, + doc, + view, + focused, + spinners, + parts: RenderBuffer::default(), + } + } +} + +#[derive(Default)] +pub struct RenderBuffer<'a> { + pub left: Spans<'a>, + pub center: Spans<'a>, + pub right: Spans<'a>, +} + +pub fn render(context: &mut RenderContext, viewport: Rect, surface: &mut Surface) { + let base_style = if context.focused { + context.editor.theme.get("ui.statusline") + } else { + context.editor.theme.get("ui.statusline.inactive") + }; + + surface.set_style(viewport.with_height(1), base_style); + + let write_left = |context: &mut RenderContext, text, style| { + append(&mut context.parts.left, text, &base_style, style) + }; + let write_center = |context: &mut RenderContext, text, style| { + append(&mut context.parts.center, text, &base_style, style) + }; + let write_right = |context: &mut RenderContext, text, style| { + append(&mut context.parts.right, text, &base_style, style) + }; + + // Left side of the status line. + + let element_ids = &context.editor.config().statusline.left; + element_ids + .iter() + .map(|element_id| get_render_function(*element_id)) + .for_each(|render| render(context, write_left)); + + surface.set_spans( + viewport.x, + viewport.y, + &context.parts.left, + context.parts.left.width() as u16, + ); + + // Right side of the status line. + + let element_ids = &context.editor.config().statusline.right; + element_ids + .iter() + .map(|element_id| get_render_function(*element_id)) + .for_each(|render| render(context, write_right)); + + surface.set_spans( + viewport.x + + viewport + .width + .saturating_sub(context.parts.right.width() as u16), + viewport.y, + &context.parts.right, + context.parts.right.width() as u16, + ); + + // Center of the status line. + + let element_ids = &context.editor.config().statusline.center; + element_ids + .iter() + .map(|element_id| get_render_function(*element_id)) + .for_each(|render| render(context, write_center)); + + // Width of the empty space between the left and center area and between the center and right area. + let spacing = 1u16; + + let edge_width = context.parts.left.width().max(context.parts.right.width()) as u16; + let center_max_width = viewport.width.saturating_sub(2 * edge_width + 2 * spacing); + let center_width = center_max_width.min(context.parts.center.width() as u16); + + surface.set_spans( + viewport.x + viewport.width / 2 - center_width / 2, + viewport.y, + &context.parts.center, + center_width, + ); +} + +fn append(buffer: &mut Spans, text: String, base_style: &Style, style: Option