From 76e512f9445b2a26655248b46cf13413f9a6bbba Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 16 Feb 2024 15:43:14 +0100 Subject: [PATCH 01/24] Remove unwrap on line option, preventing DAP crash (#9632) * Remove unwrap on line option, preventing DAP crash, ref #4683 * Update to fall back to existing values for option fields --- helix-view/src/handlers/dap.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/helix-view/src/handlers/dap.rs b/helix-view/src/handlers/dap.rs index e1437bef7..a5fa0c29c 100644 --- a/helix-view/src/handlers/dap.rs +++ b/helix-view/src/handlers/dap.rs @@ -226,10 +226,15 @@ impl Editor { breakpoints.iter().position(|b| b.id == breakpoint.id) { breakpoints[i].verified = breakpoint.verified; - breakpoints[i].message = breakpoint.message.clone(); - breakpoints[i].line = - breakpoint.line.unwrap().saturating_sub(1); // TODO: no unwrap - breakpoints[i].column = breakpoint.column; + breakpoints[i].message = breakpoint + .message + .clone() + .or_else(|| breakpoints[i].message.take()); + breakpoints[i].line = breakpoint + .line + .map_or(breakpoints[i].line, |line| line.saturating_sub(1)); + breakpoints[i].column = + breakpoint.column.or(breakpoints[i].column); } } } From 6ffe09e873821c7232d1da23ea4642214e42a1e7 Mon Sep 17 00:00:00 2001 From: Nick Condron Date: Sat, 17 Feb 2024 11:08:18 -0500 Subject: [PATCH 02/24] Fix Sonokai theme to better match original (#5379) * Make sonokai palette perfectfully faithful * Amend theme to better match original sonokai Changes based on the following references: (1) https://www.sainnhe.dev/post/contributing-guide/#sonokai (2) https://github.com/sainnhe/sonokai/blob/master/colors/sonokai.vim * Make constants white (1) * Make builtin variables purple (1) * Make members orange (1) * Make labels red (2) * Make operators red (1) * Make all punctuation grey (2) * Make builtin functions and macros green (2) * Make diff delta blue (2) * Make cursor match bg4 (2) * Make visible whitespace bg4 (2) * Make Sonokai special punctuation yellow --- runtime/themes/sonokai.toml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/runtime/themes/sonokai.toml b/runtime/themes/sonokai.toml index f586be28d..4bbdb4dbe 100644 --- a/runtime/themes/sonokai.toml +++ b/runtime/themes/sonokai.toml @@ -6,24 +6,23 @@ # License: MIT License "type" = "blue" -"constant" = "purple" +"constant" = "fg" "constant.numeric" = "purple" "constant.character.escape" = "orange" "string" = "yellow" "comment" = "grey" "variable" = "fg" -"variable.builtin" = "orange" +"variable.builtin" = "purple" "variable.parameter" = "fg" -"variable.other.member" = "fg" -"label" = "orange" +"variable.other.member" = "orange" +"label" = "red" "punctuation" = "grey" -"punctuation.delimiter" = "grey" -"punctuation.bracket" = "fg" +"punctuation.special" = "yellow" "keyword" = "red" -"operator" = "orange" +"operator" = "red" "function" = "green" -"function.builtin" = "blue" -"function.macro" = "purple" +"function.builtin" = "green" +"function.macro" = "green" "tag" = "yellow" "namespace" = "blue" "attribute" = "purple" @@ -48,12 +47,12 @@ "markup.raw" = "green" "diff.plus" = "green" -"diff.delta" = "orange" +"diff.delta" = "blue" "diff.minus" = "red" "ui.background" = { bg = "bg0" } "ui.cursor" = { modifiers = ['reversed'] } -"ui.cursor.match" = { fg = "orange", bg = "diff_yellow" } +"ui.cursor.match" = { bg = "bg4" } "ui.cursor.insert" = { fg = "black", bg = "grey" } "ui.cursor.select" = { fg = "bg0", bg = "blue" } "ui.selection" = { bg = "bg5" } @@ -73,7 +72,7 @@ "ui.text.focus" = "green" "ui.menu" = { fg = "fg", bg = "bg2" } "ui.menu.selected" = { fg = "bg0", bg = "green" } -"ui.virtual.whitespace" = { fg = "grey_dim" } +"ui.virtual.whitespace" = "bg4" "ui.virtual.ruler" = { bg = "bg3" } "ui.virtual.inlay-hint" = { fg = "grey_dim" } @@ -92,11 +91,12 @@ error = { fg = 'red', bg = 'bg2', modifiers = ['bold'] } [palette] black = "#181819" +bg_dim = "#222327" bg0 = "#2c2e34" bg1 = "#33353f" bg2 = "#363944" bg3 = "#3b3e48" -bg4 = "#5C606A" +bg4 = "#414550" bg5 = "#444852" bg_red = "#ff6077" diff_red = "#55393d" From 3e963b3c1b5eb4b5cd7f33b8ef6d6642de210a9b Mon Sep 17 00:00:00 2001 From: Vivek Kethineni <35619837+uek-1@users.noreply.github.com> Date: Sat, 17 Feb 2024 10:08:44 -0600 Subject: [PATCH 03/24] Add Rust fields as argument textobject (#9637) * added field_declaration_list and field_initializer_list as parameter textobjects * removed field_declaration_listt from textobjects.scm --- runtime/queries/rust/textobjects.scm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/queries/rust/textobjects.scm b/runtime/queries/rust/textobjects.scm index 837f981e7..df26331d8 100644 --- a/runtime/queries/rust/textobjects.scm +++ b/runtime/queries/rust/textobjects.scm @@ -34,6 +34,9 @@ (arguments ((_) @parameter.inside . ","? @parameter.around) @parameter.around) +(field_initializer_list + ((_) @parameter.inside . ","? @parameter.around) @parameter.around) + [ (line_comment) (block_comment) From 78c34194b5c83beb26ca04f12bf9d53fd5aba801 Mon Sep 17 00:00:00 2001 From: melted-brownie <66597133+melted-brownie@users.noreply.github.com> Date: Sat, 17 Feb 2024 16:09:21 +0000 Subject: [PATCH 04/24] Improve textobjects for parameter/argument for Dart (#9644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sébastien Blondiau --- runtime/queries/dart/textobjects.scm | 29 ++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/runtime/queries/dart/textobjects.scm b/runtime/queries/dart/textobjects.scm index 028276156..b88b97bc9 100644 --- a/runtime/queries/dart/textobjects.scm +++ b/runtime/queries/dart/textobjects.scm @@ -56,9 +56,34 @@ (documentation_comment)+ @comment.around -(formal_parameter) @parameter.inside +(formal_parameter_list + ( + (formal_parameter) @parameter.inside . ","? @parameter.around + ) @parameter.around +) + +(optional_formal_parameters + ( + (formal_parameter) @parameter.inside . ","? @parameter.around + ) @parameter.around +) + +(arguments + ( + [ + (argument) @parameter.inside + (named_argument (label) . (_)* @parameter.inside) + ] + . ","? @parameter.around + ) @parameter.around +) -(formal_parameter_list) @parameter.around +(type_arguments + ( + ((_) . ("." . (_) @parameter.inside @parameter.around)?) @parameter.inside + . ","? @parameter.around + ) @parameter.around +) (expression_statement ((identifier) @_name (#any-of? @_name "test" "testWidgets")) From 64326698225999016300423c4b90f8a8c7b8f38b Mon Sep 17 00:00:00 2001 From: Vince Varga Date: Sun, 18 Feb 2024 15:55:21 +0100 Subject: [PATCH 05/24] Add tmux.conf as a bash file type (#9653) * Add conf as a bash file type Tmux and tmux.conf is used widely in software developer circles. Having the tmux.conf file not have any syntax highlighting by default is (IMO) not ideal for an editor that otherwise "just works". * Use tmux.conf glob instead of simply conf for tmux Co-authored-by: Michael Davis --------- Co-authored-by: Michael Davis --- languages.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/languages.toml b/languages.toml index bfa33bf58..78078ca58 100644 --- a/languages.toml +++ b/languages.toml @@ -860,6 +860,7 @@ file-types = [ "tcshrc", "bashrc_Apple_Terminal", "zshrc_Apple_Terminal", + { glob = "tmux.conf" }, { glob = ".bash_history" }, { glob = ".bash_login" }, { glob = ".bash_logout" }, From 9ab3f9d01a8ea4967f5a7e64a3f6c8f350674c18 Mon Sep 17 00:00:00 2001 From: AlexanderDickie <75994927+AlexanderDickie@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:13:04 +0000 Subject: [PATCH 06/24] Scroll cursor and page together (neovim-like scrolling) (#8015) * neovim like scroll function * clear line annotations outside of move_vertically/_visual * add nvim scroll function to commands * assign nvim-scroll to C-d and C-u (half page scrolls) * dont remove backspace and space mapping * move non-softwrap logic to seperate function, call this in nvim-scroll fn * Revert "move non-softwrap logic to seperate function, call this in nvim-scroll fn" This reverts commit e4905729c338a2260e6981f1d8fac022897b4191. * Revert "clear line annotations outside of move_vertically/_visual" This reverts commit 1df3fefe55afc840d1ab5094b2116d1127fc363f. * add TODO for when inline diagnostics gets merged * move nvim-scroll logic into scroll(), dont respect scrolloff * run cargo fmt * run cargo clippy * update documenation for Ctrl-d and Ctrl-u remap --- book/src/keymap.md | 28 ++++++------- helix-term/src/commands.rs | 68 ++++++++++++++++++++++++++++---- helix-term/src/keymap/default.rs | 12 +++--- helix-term/src/ui/editor.rs | 2 +- 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index a3e41666f..ac84147cd 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -53,8 +53,8 @@ Normal mode is the default mode when you launch helix. You can return to it from | `End` | Move to the end of the line | `goto_line_end` | | `Ctrl-b`, `PageUp` | Move page up | `page_up` | | `Ctrl-f`, `PageDown` | Move page down | `page_down` | -| `Ctrl-u` | Move half page up | `half_page_up` | -| `Ctrl-d` | Move half page down | `half_page_down` | +| `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` | +| `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` | | `Ctrl-i` | Jump forward on the jumplist | `jump_forward` | | `Ctrl-o` | Jump backward on the jumplist | `jump_backward` | | `Ctrl-s` | Save the current selection to the jumplist | `save_selection` | @@ -182,18 +182,18 @@ normal mode) is persistent and can be exited using the escape key. This is useful when you're simply looking over text and not actively editing it. -| Key | Description | Command | -| ----- | ----------- | ------- | -| `z`, `c` | Vertically center the line | `align_view_center` | -| `t` | Align the line to the top of the screen | `align_view_top` | -| `b` | Align the line to the bottom of the screen | `align_view_bottom` | -| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` | -| `j`, `down` | Scroll the view downwards | `scroll_down` | -| `k`, `up` | Scroll the view upwards | `scroll_up` | -| `Ctrl-f`, `PageDown` | Move page down | `page_down` | -| `Ctrl-b`, `PageUp` | Move page up | `page_up` | -| `Ctrl-d` | Move half page down | `half_page_down` | -| `Ctrl-u` | Move half page up | `half_page_up` | +| Key | Description | Command | +| ----- | ----------- | ------- | +| `z`, `c` | Vertically center the line | `align_view_center` | +| `t` | Align the line to the top of the screen | `align_view_top` | +| `b` | Align the line to the bottom of the screen | `align_view_bottom` | +| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` | +| `j`, `down` | Scroll the view downwards | `scroll_down` | +| `k`, `up` | Scroll the view upwards | `scroll_up` | +| `Ctrl-f`, `PageDown` | Move page down | `page_down` | +| `Ctrl-b`, `PageUp` | Move page up | `page_up` | +| `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` | +| `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` | #### Goto mode diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index e46109c0f..51a1ede9b 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -277,6 +277,10 @@ impl MappableCommand { page_down, "Move page down", half_page_up, "Move half page up", half_page_down, "Move half page down", + page_cursor_up, "Move page and cursor up", + page_cursor_down, "Move page and cursor down", + page_cursor_half_up, "Move page and cursor half up", + page_cursor_half_down, "Move page and cursor half down", select_all, "Select whole document", select_regex, "Select all regex matches inside selections", split_selection, "Split selections on regex matches", @@ -1608,7 +1612,7 @@ fn switch_to_lowercase(cx: &mut Context) { }); } -pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { +pub fn scroll(cx: &mut Context, offset: usize, direction: Direction, sync_cursor: bool) { use Direction::*; let config = cx.editor.config(); let (view, doc) = current!(cx.editor); @@ -1628,7 +1632,7 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { let doc_text = doc.text().slice(..); let viewport = view.inner_area(doc); let text_fmt = doc.text_format(viewport.width, None); - let annotations = view.text_annotations(doc, None); + let mut annotations = view.text_annotations(doc, None); (view.offset.anchor, view.offset.vertical_offset) = char_idx_at_visual_offset( doc_text, view.offset.anchor, @@ -1638,6 +1642,30 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { &annotations, ); + if sync_cursor { + let movement = match cx.editor.mode { + Mode::Select => Movement::Extend, + _ => Movement::Move, + }; + // TODO: When inline diagnostics gets merged- 1. move_vertically_visual removes + // line annotations/diagnostics so the cursor may jump further than the view. + // 2. If the cursor lands on a complete line of virtual text, the cursor will + // jump a different distance than the view. + let selection = doc.selection(view.id).clone().transform(|range| { + move_vertically_visual( + doc_text, + range, + direction, + offset.unsigned_abs(), + movement, + &text_fmt, + &mut annotations, + ) + }); + doc.set_selection(view.id, selection); + return; + } + let mut head; match direction { Forward => { @@ -1688,25 +1716,49 @@ pub fn scroll(cx: &mut Context, offset: usize, direction: Direction) { fn page_up(cx: &mut Context) { let view = view!(cx.editor); let offset = view.inner_height(); - scroll(cx, offset, Direction::Backward); + scroll(cx, offset, Direction::Backward, false); } fn page_down(cx: &mut Context) { let view = view!(cx.editor); let offset = view.inner_height(); - scroll(cx, offset, Direction::Forward); + scroll(cx, offset, Direction::Forward, false); } fn half_page_up(cx: &mut Context) { let view = view!(cx.editor); let offset = view.inner_height() / 2; - scroll(cx, offset, Direction::Backward); + scroll(cx, offset, Direction::Backward, false); } fn half_page_down(cx: &mut Context) { let view = view!(cx.editor); let offset = view.inner_height() / 2; - scroll(cx, offset, Direction::Forward); + scroll(cx, offset, Direction::Forward, false); +} + +fn page_cursor_up(cx: &mut Context) { + let view = view!(cx.editor); + let offset = view.inner_height(); + scroll(cx, offset, Direction::Backward, true); +} + +fn page_cursor_down(cx: &mut Context) { + let view = view!(cx.editor); + let offset = view.inner_height(); + scroll(cx, offset, Direction::Forward, true); +} + +fn page_cursor_half_up(cx: &mut Context) { + let view = view!(cx.editor); + let offset = view.inner_height() / 2; + scroll(cx, offset, Direction::Backward, true); +} + +fn page_cursor_half_down(cx: &mut Context) { + let view = view!(cx.editor); + let offset = view.inner_height() / 2; + scroll(cx, offset, Direction::Forward, true); } #[allow(deprecated)] @@ -4856,11 +4908,11 @@ fn align_view_middle(cx: &mut Context) { } fn scroll_up(cx: &mut Context) { - scroll(cx, cx.count(), Direction::Backward); + scroll(cx, cx.count(), Direction::Backward, false); } fn scroll_down(cx: &mut Context) { - scroll(cx, cx.count(), Direction::Forward); + scroll(cx, cx.count(), Direction::Forward, false); } fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direction) { diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 763ed4ae7..92d6b5906 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -178,8 +178,8 @@ pub fn default() -> HashMap { "esc" => normal_mode, "C-b" | "pageup" => page_up, "C-f" | "pagedown" => page_down, - "C-u" => half_page_up, - "C-d" => half_page_down, + "C-u" => page_cursor_half_up, + "C-d" => page_cursor_half_down, "C-w" => { "Window" "C-w" | "w" => rotate_view, @@ -287,8 +287,8 @@ pub fn default() -> HashMap { "j" | "down" => scroll_down, "C-b" | "pageup" => page_up, "C-f" | "pagedown" => page_down, - "C-u" | "backspace" => half_page_up, - "C-d" | "space" => half_page_down, + "C-u" | "backspace" => page_cursor_half_up, + "C-d" | "space" => page_cursor_half_down, "/" => search, "?" => rsearch, @@ -304,8 +304,8 @@ pub fn default() -> HashMap { "j" | "down" => scroll_down, "C-b" | "pageup" => page_up, "C-f" | "pagedown" => page_down, - "C-u" | "backspace" => half_page_up, - "C-d" | "space" => half_page_down, + "C-u" | "backspace" => page_cursor_half_up, + "C-d" | "space" => page_cursor_half_down, "/" => search, "?" => rsearch, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index bb749d2e7..a87e6cbca 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1156,7 +1156,7 @@ impl EditorView { } let offset = config.scroll_lines.unsigned_abs(); - commands::scroll(cxt, offset, direction); + commands::scroll(cxt, offset, direction, false); cxt.editor.tree.focus = current_view; cxt.editor.ensure_cursor_in_view(current_view); From b950dea003750120f6e764afd5afd7b738aa6410 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Sun, 18 Feb 2024 18:19:26 -0500 Subject: [PATCH 07/24] add monokai soda theme (#9651) --- runtime/themes/monokai_soda.toml | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 runtime/themes/monokai_soda.toml diff --git a/runtime/themes/monokai_soda.toml b/runtime/themes/monokai_soda.toml new file mode 100644 index 000000000..7e43247e3 --- /dev/null +++ b/runtime/themes/monokai_soda.toml @@ -0,0 +1,120 @@ +# Monokai Soda port for Helix (https://helix-editor.com) +# Author : Jimmy Zelinskie + +# Syntax + +## Constants +"constant" = "white" +"constant.builtin" = "pink" +"constant.character.escape" = "blue" +"constant.numeric" = "purple" + +## Diagnostics +"diagnostic" = { modifiers = ["underlined"] } +"diagnostic.error" = { underline = { style = "curl", color = "pink" } } +"diagnostic.warning" = { underline = { style = "curl", color = "orange" } } +"diagnostic.info" = { underline = { style = "curl", color = "white" } } + +## Diffs +"diff.plus" = "green" +"diff.delta" = "orange" +"diff.minus" = "pink" +"diff.delta.moved" = "orange" + +## Functions +"function" = "green" +"function.macro" = "blue" +"function.builtin" = "pink" +"constructor" = "blue" + +## Keywords +"keyword" = "pink" +"keyword.directive" = "blue" + +## Punctuation +"punctuation" = "gray" + +## Strings +"string" = "yellow" + +## Types +"type" = "blue" +"type.builtin" = "pink" + +## Variables +"variable" = "white" +"variable.builtin" = "pink" +"variable.other.member" = "white" +"variable.parameter" = "softorange" + +## Markup +"markup.heading" = "green" +"markup.bold" = { fg = "orange", modifiers = ["bold"] } +"markup.italic" = { fg = "orange", modifiers = ["italic"] } +"markup.link.url" = { fg = "orange", modifiers = ["underlined"] } +"markup.link.text" = "yellow" +"markup.quote" = "green" + +## Misc +"attribute" = "blue" +"comment" = { fg = "gray", modifiers = ["italic"] } +"error" = "pink" +"hint" = "white" +"info" = "white" +"label" = "yellow" +"module" = "softorange" +"namespace" = "pink" +"operator" = "pink" +"special" = "softorange" +"warning" = "orange" + +# Editor UI + +## Main +"ui.background" = { bg = "background" } +"ui.text" = "white" +"ui.window" = { bg = "darkgray" } + +## Debug (TODO) + +## Menus +"ui.menu" = { fg = "white", bg = "darkgray" } +"ui.menu.selected" = { modifiers = ["reversed"] } +"ui.popup" = { bg = "darkgray" } +"ui.help" = { fg = "white", bg = "darkgray" } + +## Gutter +"ui.linenr" = "darkgray" +"ui.linenr.selected" = "orange" + +## Cursor +"ui.cursor.primary" = { fg = "white", modifiers = ["reversed"] } +"ui.cursor.match" = { fg = "white", modifiers = ["reversed"] } +"ui.selection" = { bg = "darkgray" } + +## Statusline +"ui.statusline" = { bg = "darkgray" } +"ui.statusline.inactive" = { fg = "white", bg = "darkgray" } +"ui.statusline.normal" = { fg = "white", bg = "blue" } +"ui.statusline.insert" = { fg = "white", bg = "green" } +"ui.statusline.select" = { fg = "white", bg = "purple" } + +"ui.text.focus" = { fg = "yellow", modifiers = ["bold"] } +"ui.virtual" = "darkgray" +"ui.virtual.ruler" = { bg = "darkgray" } + +# Palette + +[palette] +"purple" = "#AE81FF" +"yellow" = "#E6DB74" +"pink" = "#f92a72" +"white" = "#cfcfc2" +"gray" = "#75715e" +"darkgray" = "#444444" +"black" = "#222222" +"blue" = "#66d9ef" +"green" = "#a6e22e" +"softorange" = "#f59762" +"orange" = "#fd971f" +"background" = "#191919" From c72426cc874c70bfb5660b2866e634927e5fb4fd Mon Sep 17 00:00:00 2001 From: Malpha Date: Sun, 18 Feb 2024 23:19:44 +0000 Subject: [PATCH 08/24] Add docker-compose language (#9661) * languages: add docker-compose language it uses docker-compose-langserver as lsp And yaml for syntax highlighting, indents and injections * languages: add luajit as a shebang of lua This helps to provide syntax highlighting and other lua goodies when writing luajit * book(update): run cargo xtask docgen * since #8006 full filenames uses glob --- book/src/generated/lang-support.md | 1 + languages.toml | 13 ++++++++++++- runtime/queries/docker-compose/highlights.scm | 1 + runtime/queries/docker-compose/indents.scm | 1 + runtime/queries/docker-compose/injections.scm | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/docker-compose/highlights.scm create mode 100644 runtime/queries/docker-compose/indents.scm create mode 100644 runtime/queries/docker-compose/injections.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index bfe6d6b1e..a37e165f2 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -30,6 +30,7 @@ | devicetree | ✓ | | | | | dhall | ✓ | ✓ | | `dhall-lsp-server` | | diff | ✓ | | | | +| docker-compose | ✓ | | ✓ | `docker-compose-langserver` | | dockerfile | ✓ | | | `docker-langserver` | | dot | ✓ | | | `dot-language-server` | | dtd | ✓ | | | | diff --git a/languages.toml b/languages.toml index 78078ca58..e52dcabbc 100644 --- a/languages.toml +++ b/languages.toml @@ -23,6 +23,7 @@ cuelsp = { command = "cuelsp" } dart = { command = "dart", args = ["language-server", "--client-id=helix"] } dhall-lsp-server = { command = "dhall-lsp-server" } docker-langserver = { command = "docker-langserver", args = ["--stdio"] } +docker-compose-langserver = { command = "docker-compose-langserver", args = ["--stdio"]} dot-language-server = { command = "dot-language-server", args = ["--stdio"] } elixir-ls = { command = "elixir-ls", config = { elixirLS.dialyzerEnabled = false } } elm-language-server = { command = "elm-language-server" } @@ -1092,7 +1093,7 @@ name = "lua" injection-regex = "lua" scope = "source.lua" file-types = ["lua"] -shebangs = ["lua"] +shebangs = ["lua", "luajit"] roots = [".luarc.json", ".luacheckrc", ".stylua.toml", "selene.toml", ".git"] comment-token = "--" indent = { tab-width = 2, unit = " " } @@ -1460,6 +1461,16 @@ language-servers = [ "docker-langserver" ] name = "dockerfile" source = { git = "https://github.com/camdencheek/tree-sitter-dockerfile", rev = "8ee3a0f7587b2bd8c45c8cb7d28bd414604aec62" } +[[language]] +name = "docker-compose" +scope = "source.yaml.docker-compose" +roots = ["docker-compose.yaml", "docker-compose.yml"] +language-servers = [ "docker-compose-langserver" ] +file-types = [{ glob = "docker-compose.yaml" }, { glob = "docker-compose.yml" }] +comment-token = "#" +indent = { tab-width = 2, unit = " " } +grammar = "yaml" + [[language]] name = "git-commit" scope = "git.commitmsg" diff --git a/runtime/queries/docker-compose/highlights.scm b/runtime/queries/docker-compose/highlights.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/docker-compose/highlights.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/docker-compose/indents.scm b/runtime/queries/docker-compose/indents.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/docker-compose/indents.scm @@ -0,0 +1 @@ +; inherits: yaml diff --git a/runtime/queries/docker-compose/injections.scm b/runtime/queries/docker-compose/injections.scm new file mode 100644 index 000000000..4ba254e82 --- /dev/null +++ b/runtime/queries/docker-compose/injections.scm @@ -0,0 +1 @@ +; inherits: yaml From 2dc9ce68ec84fd26e1489e3bac76fc5114d0023e Mon Sep 17 00:00:00 2001 From: Jaakko Paju Date: Mon, 19 Feb 2024 01:46:13 +0200 Subject: [PATCH 09/24] Add textobject queries for Nix (#9659) * Add textobject queries for Nix * Add to lang-support.md --- book/src/generated/lang-support.md | 2 +- runtime/queries/nix/textobjects.scm | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/nix/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index a37e165f2..09ed4dac5 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -112,7 +112,7 @@ | nasm | ✓ | ✓ | | | | nickel | ✓ | | ✓ | `nls` | | nim | ✓ | ✓ | ✓ | `nimlangserver` | -| nix | ✓ | | | `nil` | +| nix | ✓ | ✓ | | `nil` | | nu | ✓ | | | `nu` | | nunjucks | ✓ | | | | | ocaml | ✓ | | ✓ | `ocamllsp` | diff --git a/runtime/queries/nix/textobjects.scm b/runtime/queries/nix/textobjects.scm new file mode 100644 index 000000000..1508d4c2b --- /dev/null +++ b/runtime/queries/nix/textobjects.scm @@ -0,0 +1,9 @@ +(comment) @comment.inside +(comment)+ @comment.around + +(formals + ((_) @parameter.inside . ","? @parameter.around) @parameter.around) + +(function_expression + body: (_) @function.inside) @function.around + From ebf155d6351a84dec010447af88b8246103537da Mon Sep 17 00:00:00 2001 From: Jaakko Paju Date: Mon, 19 Feb 2024 01:46:32 +0200 Subject: [PATCH 10/24] Add textobject queries for HCL (#9658) * Add textobject queries for HCL * Add to lang-support.md --- book/src/generated/lang-support.md | 2 +- runtime/queries/hcl/textobjects.scm | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/hcl/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 09ed4dac5..f46c9f5e2 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -68,7 +68,7 @@ | hare | ✓ | | | | | haskell | ✓ | ✓ | | `haskell-language-server-wrapper` | | haskell-persistent | ✓ | | | | -| hcl | ✓ | | ✓ | `terraform-ls` | +| hcl | ✓ | ✓ | ✓ | `terraform-ls` | | heex | ✓ | ✓ | | `elixir-ls` | | hocon | ✓ | | ✓ | | | hoon | ✓ | | | | diff --git a/runtime/queries/hcl/textobjects.scm b/runtime/queries/hcl/textobjects.scm new file mode 100644 index 000000000..1e6505876 --- /dev/null +++ b/runtime/queries/hcl/textobjects.scm @@ -0,0 +1,6 @@ +(comment) @comment.inside +(comment)+ @comment.around + +(function_arguments + ((_) @parameter.inside . ","? @parameter.around) @parameter.around) + From 787cc36092a5d1a575697287d1d6ba08336a8a96 Mon Sep 17 00:00:00 2001 From: nkitsaini <74284503+nkitsaini@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:28:17 +0530 Subject: [PATCH 11/24] fix LSP ComplitionTriggerKind value for `TriggerKind::Auto` (#9660) --- helix-term/src/handlers/completion.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/helix-term/src/handlers/completion.rs b/helix-term/src/handlers/completion.rs index d71fd24fc..491ca5638 100644 --- a/helix-term/src/handlers/completion.rs +++ b/helix-term/src/handlers/completion.rs @@ -221,9 +221,17 @@ fn request_completion( .iter() .find(|&trigger| trigger_text.ends_with(trigger)) }); - lsp::CompletionContext { - trigger_kind: lsp::CompletionTriggerKind::TRIGGER_CHARACTER, - trigger_character: trigger_char.cloned(), + + if trigger_char.is_some() { + lsp::CompletionContext { + trigger_kind: lsp::CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: trigger_char.cloned(), + } + } else { + lsp::CompletionContext { + trigger_kind: lsp::CompletionTriggerKind::INVOKED, + trigger_character: None, + } } }; From cdef4f8a701f921c29fdfe66f104a2edac7fe05c Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Mon, 19 Feb 2024 22:08:26 +0900 Subject: [PATCH 12/24] Make mouse click extend selection in select mode (#5436) * Make mouse click extend selection in select mode * chore: better readability with `Option::take()` --- helix-term/src/ui/editor.rs | 40 ++++++++++++++++++++++++++----------- helix-view/src/editor.rs | 7 +++++-- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index a87e6cbca..66f290a22 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1088,6 +1088,15 @@ impl EditorView { if modifiers == KeyModifiers::ALT { let selection = doc.selection(view_id).clone(); doc.set_selection(view_id, selection.push(Range::point(pos))); + } else if editor.mode == Mode::Select { + // Discards non-primary selections for consistent UX with normal mode + let primary = doc.selection(view_id).primary().put_cursor( + doc.text().slice(..), + pos, + true, + ); + editor.mouse_down_range = Some(primary); + doc.set_selection(view_id, Selection::single(primary.anchor, primary.head)); } else { doc.set_selection(view_id, Selection::point(pos)); } @@ -1171,19 +1180,26 @@ impl EditorView { let (view, doc) = current!(cxt.editor); - if doc - .selection(view.id) - .primary() - .slice(doc.text().slice(..)) - .len_chars() - <= 1 - { - return EventResult::Ignored(None); - } - - commands::MappableCommand::yank_main_selection_to_primary_clipboard.execute(cxt); + let should_yank = match cxt.editor.mouse_down_range.take() { + Some(down_range) => doc.selection(view.id).primary() != down_range, + None => { + // This should not happen under normal cases. We fall back to the original + // behavior of yanking on non-single-char selections. + doc.selection(view.id) + .primary() + .slice(doc.text().slice(..)) + .len_chars() + > 1 + } + }; - EventResult::Consumed(None) + if should_yank { + commands::MappableCommand::yank_main_selection_to_primary_clipboard + .execute(cxt); + EventResult::Consumed(None) + } else { + EventResult::Ignored(None) + } } MouseEventKind::Up(MouseButton::Right) => { diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 68b74cf00..fffbe6207 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -42,7 +42,7 @@ pub use helix_core::diagnostic::Severity; use helix_core::{ auto_pairs::AutoPairs, syntax::{self, AutoPairConfig, IndentationHeuristic, LanguageServerFeature, SoftWrap}, - Change, LineEnding, Position, Selection, NATIVE_LINE_ENDING, + Change, LineEnding, Position, Range, Selection, NATIVE_LINE_ENDING, }; use helix_dap as dap; use helix_lsp::lsp; @@ -964,6 +964,8 @@ pub struct Editor { /// times during rendering and should not be set by other functions. pub cursor_cache: Cell>>, pub handlers: Handlers, + + pub mouse_down_range: Option, } pub type Motion = Box; @@ -1080,6 +1082,7 @@ impl Editor { needs_redraw: false, cursor_cache: Cell::new(None), handlers, + mouse_down_range: None, } } @@ -1978,7 +1981,7 @@ impl Editor { /// Switches the editor into normal mode. pub fn enter_normal_mode(&mut self) { - use helix_core::{graphemes, Range}; + use helix_core::graphemes; if self.mode == Mode::Normal { return; From 990378a46be2138b2f74799d1af8955390360c4e Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi Date: Mon, 19 Feb 2024 19:37:02 +0200 Subject: [PATCH 13/24] Add Groovy grammar (#9350) * Add Groovy grammar * Rewrite Neovim captures into Helix for Groovy * Simplify Groovy injections Co-authored-by: Michael Davis * Remove Neovim's spell from Groovy highlights Co-authored-by: Michael Davis * Apply suggestions to languages.toml * Escape backslash in groovy highlights.scm --------- Co-authored-by: Michael Davis --- book/src/generated/lang-support.md | 1 + languages.toml | 13 ++++ runtime/queries/groovy/highlights.scm | 96 +++++++++++++++++++++++++++ runtime/queries/groovy/injections.scm | 2 + 4 files changed, 112 insertions(+) create mode 100644 runtime/queries/groovy/highlights.scm create mode 100644 runtime/queries/groovy/injections.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index f46c9f5e2..7aec37778 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -65,6 +65,7 @@ | gotmpl | ✓ | | | `gopls` | | gowork | ✓ | | | `gopls` | | graphql | ✓ | | | `graphql-lsp` | +| groovy | ✓ | | | | | hare | ✓ | | | | | haskell | ✓ | ✓ | | `haskell-language-server-wrapper` | | haskell-persistent | ✓ | | | | diff --git a/languages.toml b/languages.toml index e52dcabbc..1c4c61267 100644 --- a/languages.toml +++ b/languages.toml @@ -3125,3 +3125,16 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "pkl" source = { git = "https://github.com/apple/tree-sitter-pkl", rev = "c03f04a313b712f8ab00a2d862c10b37318699ae" } + +[[language]] +name = "groovy" +language-id = "groovy" +scope = "source.groovy" +file-types = ["groovy", "jenkinsfile", { glob = "Jenkinsfile" }, { glob = "Jenkinsfile.*" }] +shebangs = ["groovy"] +comment-token = "//" +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "groovy" +source = { git = "https://github.com/Decodetalkers/tree-sitter-groovy", rev = "7e023227f46fee428b16a0288eeb0f65ee2523ec" } diff --git a/runtime/queries/groovy/highlights.scm b/runtime/queries/groovy/highlights.scm new file mode 100644 index 000000000..4e94ccd3a --- /dev/null +++ b/runtime/queries/groovy/highlights.scm @@ -0,0 +1,96 @@ +(unit + (identifier) @variable) + +(string + (identifier) @variable) + +(escape_sequence) @constant.character.escape + +(block + (unit + (identifier) @namespace)) + +(func + (identifier) @function) + +(number) @constant.numeric + +((identifier) @constant.builtin.boolean + (#any-of? @constant.builtin.boolean "true" "false")) + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + +((identifier) @constant.builtin + (#eq? @constant.builtin "null")) + +((identifier) @type + (#any-of? @type + "String" + "Map" + "Object" + "Boolean" + "Integer" + "List")) + +((identifier) @function.builtin + (#any-of? @function.builtin + "void" + "id" + "version" + "apply" + "implementation" + "testImplementation" + "androidTestImplementation" + "debugImplementation")) + +((identifier) @keyword.storage.modifier + (#eq? @keyword.storage.modifier "static")) + +((identifier) @keyword.storage.type + (#any-of? @keyword.storage.type "class" "def" "interface")) + +((identifier) @keyword + (#any-of? @keyword + "assert" + "new" + "extends" + "implements" + "instanceof")) + +((identifier) @keyword.control.import + (#any-of? @keyword.control.import "import" "package")) + +((identifier) @keyword.storage.modifier + (#any-of? @keyword.storage.modifier + "abstract" + "protected" + "private" + "public")) + +((identifier) @keyword.control.exception + (#any-of? @keyword.control.exception + "throw" + "finally" + "try" + "catch")) + +(string) @string + +[ + (line_comment) + (block_comment) +] @comment + +((block_comment) @comment.block.documentation + (#match? @comment.block.documentation "^/[*][*][^*](?s:.)*[*]/$")) + +((line_comment) @comment.block.documentation + (#match? @comment.block.documentation "^///[^/]*.*$")) + +[ + (operators) + (leading_key) +] @operator + +["(" ")" "[" "]" "{" "}"] @punctuation.bracket diff --git a/runtime/queries/groovy/injections.scm b/runtime/queries/groovy/injections.scm new file mode 100644 index 000000000..e4509a5fd --- /dev/null +++ b/runtime/queries/groovy/injections.scm @@ -0,0 +1,2 @@ +([(line_comment) (block_comment)] @injection.content + (#set! injection.language "comment")) From 27335476edc22c2da652c4636d9b1bae751fe22d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:06:40 +0100 Subject: [PATCH 14/24] build(deps): bump chrono from 0.4.33 to 0.4.34 (#9673) Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.33 to 0.4.34. - [Release notes](https://github.com/chronotope/chrono/releases) - [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md) - [Commits](https://github.com/chronotope/chrono/compare/v0.4.33...v0.4.34) --- updated-dependencies: - dependency-name: chrono 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 6f38f0034..2f8b1f97d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", From d2aacb3e36d59fb6cef42cdc5bd317a3d15d1a0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:06:58 +0100 Subject: [PATCH 15/24] build(deps): bump anyhow from 1.0.79 to 1.0.80 (#9675) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.80. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.79...1.0.80) --- updated-dependencies: - dependency-name: anyhow 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 2f8b1f97d..32b5ad84a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,9 +62,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arc-swap" From cad0209e202a7513105639daa36c82578db4032d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:07:16 +0100 Subject: [PATCH 16/24] build(deps): bump textwrap from 0.16.0 to 0.16.1 (#9674) Bumps [textwrap](https://github.com/mgeisler/textwrap) from 0.16.0 to 0.16.1. - [Release notes](https://github.com/mgeisler/textwrap/releases) - [Changelog](https://github.com/mgeisler/textwrap/blob/master/CHANGELOG.md) - [Commits](https://github.com/mgeisler/textwrap/compare/0.16.0...0.16.1) --- updated-dependencies: - dependency-name: textwrap 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 ++-- helix-core/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32b5ad84a..2b8a25c85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2231,9 +2231,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index ca2f505c6..0b0dd7452 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -48,7 +48,7 @@ encoding_rs = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] } etcetera = "0.8" -textwrap = "0.16.0" +textwrap = "0.16.1" nucleo.workspace = true parking_lot = "0.12" From eca537615a554e3b1e379ba53d9f3e0654e67c70 Mon Sep 17 00:00:00 2001 From: Benedikt Ritter Date: Wed, 21 Feb 2024 15:46:31 +0100 Subject: [PATCH 17/24] Use groovy support when editing Gradle files (#9681) The Gradle build tool provides two DSLs for configuring builds. On is based on Groovy and Gradle build files written in Gradle Groovy DSL use *.gradle file ending. This change adds `gradle` to the supported file types of the groovy language configuration. --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 1c4c61267..b158606b0 100644 --- a/languages.toml +++ b/languages.toml @@ -3130,7 +3130,7 @@ source = { git = "https://github.com/apple/tree-sitter-pkl", rev = "c03f04a313b7 name = "groovy" language-id = "groovy" scope = "source.groovy" -file-types = ["groovy", "jenkinsfile", { glob = "Jenkinsfile" }, { glob = "Jenkinsfile.*" }] +file-types = ["gradle", "groovy", "jenkinsfile", { glob = "Jenkinsfile" }, { glob = "Jenkinsfile.*" }] shebangs = ["groovy"] comment-token = "//" indent = { tab-width = 2, unit = " " } From 98ebeeebd8c7462409f82d34ff4ac0a7ae9116c7 Mon Sep 17 00:00:00 2001 From: Abderrahmane TAHRI JOUTI <302837+atahrijouti@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:47:14 +0100 Subject: [PATCH 18/24] Cyan Light theme : Add License and Author (#9688) * Cyan Light theme : Add License and Author * Add License Copy license from https://github.com/OlyaB/CyanTheme/blob/master/LICENSE * better credits to original author --- runtime/themes/cyan_light.toml | 10 +++++++--- runtime/themes/licenses/cyan_light.LICENSE | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 runtime/themes/licenses/cyan_light.LICENSE diff --git a/runtime/themes/cyan_light.toml b/runtime/themes/cyan_light.toml index 45cb6539d..a35ad5847 100644 --- a/runtime/themes/cyan_light.toml +++ b/runtime/themes/cyan_light.toml @@ -1,6 +1,10 @@ -# An approximation/port of the Cyan Light Theme from Jetbrains -# -# Original Color Scheme here https://plugins.jetbrains.com/plugin/12102-cyan-light-theme +# Cyan Light +# Adapted from JetBrains' Cyan Light Theme https://plugins.jetbrains.com/plugin/12102-cyan-light-theme +# Author: Abderrahmane Tahri Jouti + +# Original Author : Olga Berdnikova +# LICENSE : MIT +# Source: https://github.com/OlyaB/CyanTheme "attribute" = "blue" "type" = "shade07" diff --git a/runtime/themes/licenses/cyan_light.LICENSE b/runtime/themes/licenses/cyan_light.LICENSE new file mode 100644 index 000000000..3a4a2fb87 --- /dev/null +++ b/runtime/themes/licenses/cyan_light.LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 CloudCannon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From b7b6f300841bb61d8833fee1c58d0e3670849b61 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 19 Feb 2024 10:07:03 -0500 Subject: [PATCH 19/24] Use a hook for resolving completion items Previously we used the IdleTimeout event to trigger LSP `completion/resolveItem` requests. We can now refactor this to use an event system hook instead and lower the timeout. --- helix-lsp/src/client.rs | 5 +- helix-term/src/ui/completion.rs | 156 ++++++++++++++++++++------------ helix-term/src/ui/editor.rs | 8 -- 3 files changed, 100 insertions(+), 69 deletions(-) diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index 0d3a2a56e..8d03d7992 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -1017,7 +1017,7 @@ impl Client { pub fn resolve_completion_item( &self, completion_item: lsp::CompletionItem, - ) -> Option>> { + ) -> Option>> { let capabilities = self.capabilities.get().unwrap(); // Return early if the server does not support resolving completion items. @@ -1029,7 +1029,8 @@ impl Client { _ => return None, } - Some(self.call::(completion_item)) + let res = self.call::(completion_item); + Some(async move { Ok(serde_json::from_value(res.await?)?) }) } pub fn resolve_code_action( diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index 48d97fbd8..6cbb5b109 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -1,7 +1,9 @@ use crate::{ compositor::{Component, Context, Event, EventResult}, handlers::trigger_auto_completion, + job, }; +use helix_event::AsyncHook; use helix_view::{ document::SavePoint, editor::CompleteAction, @@ -10,14 +12,14 @@ use helix_view::{ theme::{Modifier, Style}, ViewId, }; +use tokio::time::Instant; use tui::{buffer::Buffer as Surface, text::Span}; -use std::{borrow::Cow, sync::Arc}; +use std::{borrow::Cow, sync::Arc, time::Duration}; use helix_core::{chars, Change, Transaction}; use helix_view::{graphics::Rect, Document, Editor}; -use crate::commands; use crate::ui::{menu, Markdown, Menu, Popup, PromptEvent}; use helix_lsp::{lsp, util, OffsetEncoding}; @@ -102,6 +104,7 @@ pub struct Completion { #[allow(dead_code)] trigger_offset: usize, filter: String, + resolve_handler: tokio::sync::mpsc::Sender, } impl Completion { @@ -368,6 +371,7 @@ impl Completion { // TODO: expand nucleo api to allow moving straight to a Utf32String here // and avoid allocation during matching filter: String::from(fragment), + resolve_handler: ResolveHandler::default().spawn(), }; // need to recompute immediately in case start_offset != trigger_offset @@ -379,6 +383,8 @@ impl Completion { completion } + /// Synchronously resolve the given completion item. This is used when + /// accepting a completion. fn resolve_completion_item( language_server: &helix_lsp::Client, completion_item: lsp::CompletionItem, @@ -386,7 +392,7 @@ impl Completion { let future = language_server.resolve_completion_item(completion_item)?; let response = helix_lsp::block_on(future); match response { - Ok(value) => serde_json::from_value(value).ok(), + Ok(item) => Some(item), Err(err) => { log::error!("Failed to resolve completion item: {}", err); None @@ -420,62 +426,6 @@ impl Completion { self.popup.contents_mut().replace_option(old_item, new_item); } - /// Asynchronously requests that the currently selection completion item is - /// resolved through LSP `completionItem/resolve`. - pub fn ensure_item_resolved(&mut self, cx: &mut commands::Context) -> bool { - // > If computing full completion items is expensive, servers can additionally provide a - // > handler for the completion item resolve request. ... - // > A typical use case is for example: the `textDocument/completion` request doesn't fill - // > in the `documentation` property for returned completion items since it is expensive - // > to compute. When the item is selected in the user interface then a - // > 'completionItem/resolve' request is sent with the selected completion item as a parameter. - // > The returned completion item should have the documentation property filled in. - // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion - let current_item = match self.popup.contents().selection() { - Some(item) if !item.resolved => item.clone(), - _ => return false, - }; - - let Some(language_server) = cx - .editor - .language_server_by_id(current_item.language_server_id) - else { - return false; - }; - - // This method should not block the compositor so we handle the response asynchronously. - let Some(future) = language_server.resolve_completion_item(current_item.item.clone()) - else { - return false; - }; - - cx.callback( - future, - move |_editor, compositor, response: Option| { - let resolved_item = match response { - Some(item) => item, - None => return, - }; - - if let Some(completion) = &mut compositor - .find::() - .unwrap() - .completion - { - let resolved_item = CompletionItem { - item: resolved_item, - language_server_id: current_item.language_server_id, - resolved: true, - }; - - completion.replace_item(current_item, resolved_item); - } - }, - ); - - true - } - pub fn area(&mut self, viewport: Rect, editor: &Editor) -> Rect { self.popup.area(viewport, editor) } @@ -498,6 +448,9 @@ impl Component for Completion { Some(option) => option, None => return, }; + if !option.resolved { + helix_event::send_blocking(&self.resolve_handler, option.clone()); + } // need to render: // option.detail // --- @@ -599,3 +552,88 @@ impl Component for Completion { markdown_doc.render(doc_area, surface, cx); } } + +/// A hook for resolving incomplete completion items. +/// +/// From the [LSP spec](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion): +/// +/// > If computing full completion items is expensive, servers can additionally provide a +/// > handler for the completion item resolve request. ... +/// > A typical use case is for example: the `textDocument/completion` request doesn't fill +/// > in the `documentation` property for returned completion items since it is expensive +/// > to compute. When the item is selected in the user interface then a +/// > 'completionItem/resolve' request is sent with the selected completion item as a parameter. +/// > The returned completion item should have the documentation property filled in. +#[derive(Debug, Default)] +struct ResolveHandler { + trigger: Option, + request: Option, +} + +impl AsyncHook for ResolveHandler { + type Event = CompletionItem; + + fn handle_event( + &mut self, + item: Self::Event, + timeout: Option, + ) -> Option { + if self + .trigger + .as_ref() + .is_some_and(|trigger| trigger == &item) + { + timeout + } else { + self.trigger = Some(item); + self.request = None; + Some(Instant::now() + Duration::from_millis(150)) + } + } + + fn finish_debounce(&mut self) { + let Some(item) = self.trigger.take() else { return }; + let (tx, rx) = helix_event::cancelation(); + self.request = Some(tx); + job::dispatch_blocking(move |editor, _| resolve_completion_item(editor, item, rx)) + } +} + +fn resolve_completion_item( + editor: &mut Editor, + item: CompletionItem, + cancel: helix_event::CancelRx, +) { + let Some(language_server) = editor.language_server_by_id(item.language_server_id) else { + return; + }; + + let Some(future) = language_server.resolve_completion_item(item.item.clone()) else { + return; + }; + + tokio::spawn(async move { + match helix_event::cancelable_future(future, cancel).await { + Some(Ok(resolved_item)) => { + job::dispatch(move |_, compositor| { + if let Some(completion) = &mut compositor + .find::() + .unwrap() + .completion + { + let resolved_item = CompletionItem { + item: resolved_item, + language_server_id: item.language_server_id, + resolved: true, + }; + + completion.replace_item(item, resolved_item); + }; + }) + .await + } + Some(Err(err)) => log::error!("completion resolve request failed: {err}"), + None => (), + } + }); +} diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 66f290a22..15a7262a8 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1027,14 +1027,6 @@ impl EditorView { pub fn handle_idle_timeout(&mut self, cx: &mut commands::Context) -> EventResult { commands::compute_inlay_hints_for_all_views(cx.editor, cx.jobs); - if let Some(completion) = &mut self.completion { - return if completion.ensure_item_resolved(cx) { - EventResult::Consumed(None) - } else { - EventResult::Ignored(None) - }; - } - EventResult::Ignored(None) } } From 7100ed4efc2207a9d7a45ce6e9550564e091f508 Mon Sep 17 00:00:00 2001 From: wr7 Date: Fri, 23 Feb 2024 09:46:41 -0600 Subject: [PATCH 20/24] Properly handle spaces in filenames in bash autocomplete (#9702) --- contrib/completion/hx.bash | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contrib/completion/hx.bash b/contrib/completion/hx.bash index 01b42deb6..6ef0329e4 100644 --- a/contrib/completion/hx.bash +++ b/contrib/completion/hx.bash @@ -5,19 +5,20 @@ _hx() { # $1 command name # $2 word being completed # $3 word preceding - COMPREPLY=() case "$3" in -g | --grammar) - COMPREPLY=($(compgen -W "fetch build" -- $2)) + COMPREPLY="$(compgen -W "fetch build" -- $2)" ;; --health) local languages=$(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g') - COMPREPLY=($(compgen -W "$languages" -- $2)) + COMPREPLY="$(compgen -W "$languages" -- $2)" ;; *) - COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- $2)) + COMPREPLY="$(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- $2)" ;; esac -} && complete -o filenames -F _hx hx + local IFS=$'\n' + COMPREPLY=($COMPREPLY) +} && complete -o filenames -F _hx hx From 03623f2f407d592c38d21e085ae1fb2e1aa1ea22 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Fri, 23 Feb 2024 18:53:16 -0800 Subject: [PATCH 21/24] Add osm and osc extensions to xml language filetypes (#9697) --- languages.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/languages.toml b/languages.toml index b158606b0..ad2e66589 100644 --- a/languages.toml +++ b/languages.toml @@ -2371,6 +2371,8 @@ file-types = [ "menu", "mxml", "nuspec", + "osc", + "osm", "pt", "publishsettings", "pubxml", From 38484f33e5298b2764eb9afd3bf6a60f1facc260 Mon Sep 17 00:00:00 2001 From: wr7 Date: Fri, 23 Feb 2024 20:54:40 -0600 Subject: [PATCH 22/24] Completely fix bash autocomplete handling of filenames with spaces (#9708) --- contrib/completion/hx.bash | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/completion/hx.bash b/contrib/completion/hx.bash index 6ef0329e4..62ca029bf 100644 --- a/contrib/completion/hx.bash +++ b/contrib/completion/hx.bash @@ -8,14 +8,14 @@ _hx() { case "$3" in -g | --grammar) - COMPREPLY="$(compgen -W "fetch build" -- $2)" + COMPREPLY="$(compgen -W 'fetch build' -- $2)" ;; --health) local languages=$(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g') - COMPREPLY="$(compgen -W "$languages" -- $2)" + COMPREPLY="$(compgen -W """$languages""" -- $2)" ;; *) - COMPREPLY="$(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- $2)" + COMPREPLY="$(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- """$2""")" ;; esac From ec9efdef3b2f613a86098058f5705e7863e375e2 Mon Sep 17 00:00:00 2001 From: DS/Charlie <82801887+ds-cbo@users.noreply.github.com> Date: Sat, 24 Feb 2024 04:28:25 +0100 Subject: [PATCH 23/24] Bump tree-sitter-sql (#9634) --- languages.toml | 2 +- runtime/queries/sql/highlights.scm | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/languages.toml b/languages.toml index ad2e66589..112333ea9 100644 --- a/languages.toml +++ b/languages.toml @@ -1825,7 +1825,7 @@ injection-regex = "sql" [[grammar]] name = "sql" -source = { git = "https://github.com/DerekStride/tree-sitter-sql", rev = "25be0b8f17e9189ad9e1b875869d025c5aec1286" } +source = { git = "https://github.com/DerekStride/tree-sitter-sql", rev = "da2d1eff425b146d3c8cab7be8dfa98b11d896dc" } [[language]] name = "gdscript" diff --git a/runtime/queries/sql/highlights.scm b/runtime/queries/sql/highlights.scm index 09b07489e..e575debc5 100644 --- a/runtime/queries/sql/highlights.scm +++ b/runtime/queries/sql/highlights.scm @@ -24,20 +24,20 @@ (term alias: (identifier) @variable.parameter) -(term +((term value: (cast name: (keyword_cast) @function.builtin - parameter: [(literal)]?)) + parameter: [(literal)]?))) (literal) @string (comment) @comment.line (marginalia) @comment.block ((literal) @constant.numeric.integer - (#match? @constant.numeric.integer "^-?\\d+$")) + (#match? @constant.numeric.integer "^[-+]?\\d+$")) ((literal) @constant.numeric.float - (#match? @constant.numeric.float "^-?\\d*\\.\\d*$")) + (#match? @constant.numeric.float "^[-+]?\\d*\\.\\d*$")) (parameter) @variable.parameter From 6db666fce1fb4627c06d147554b8e1eb9970619e Mon Sep 17 00:00:00 2001 From: Mo <76752051+mo8it@users.noreply.github.com> Date: Sat, 24 Feb 2024 16:59:11 +0100 Subject: [PATCH 24/24] Optimization of tilde expansion (#9709) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use next and avoid a redundant prefix strip * Avoid allocations Especially when `expand_tilde` is claled on a path that doesn't contain a tilde. * Add a test * Use Into> * Put the expand_tilde test at the end of the file * Remove unused importsw --- helix-loader/src/lib.rs | 2 +- helix-stdx/src/path.rs | 59 +++++++++++++++++++++++++------- helix-term/src/commands/typed.rs | 14 ++++---- helix-term/src/ui/mod.rs | 4 +-- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/helix-loader/src/lib.rs b/helix-loader/src/lib.rs index f8fac6703..93488e452 100644 --- a/helix-loader/src/lib.rs +++ b/helix-loader/src/lib.rs @@ -53,7 +53,7 @@ fn prioritize_runtime_dirs() -> Vec { rt_dirs.push(conf_rt_dir); if let Ok(dir) = std::env::var("HELIX_RUNTIME") { - let dir = path::expand_tilde(dir); + let dir = path::expand_tilde(Path::new(&dir)); rt_dirs.push(path::normalize(dir)); } diff --git a/helix-stdx/src/path.rs b/helix-stdx/src/path.rs index 5746657c3..1dc4d0b24 100644 --- a/helix-stdx/src/path.rs +++ b/helix-stdx/src/path.rs @@ -1,6 +1,9 @@ pub use etcetera::home_dir; -use std::path::{Component, Path, PathBuf}; +use std::{ + borrow::Cow, + path::{Component, Path, PathBuf}, +}; use crate::env::current_working_dir; @@ -19,19 +22,22 @@ pub fn fold_home_dir(path: &Path) -> PathBuf { /// Expands tilde `~` into users home directory if available, otherwise returns the path /// unchanged. The tilde will only be expanded when present as the first component of the path /// and only slash follows it. -pub fn expand_tilde(path: impl AsRef) -> PathBuf { - let path = path.as_ref(); - let mut components = path.components().peekable(); - if let Some(Component::Normal(c)) = components.peek() { - if c == &"~" { - if let Ok(home) = home_dir() { - // it's ok to unwrap, the path starts with `~` - return home.join(path.strip_prefix("~").unwrap()); +pub fn expand_tilde<'a, P>(path: P) -> Cow<'a, Path> +where + P: Into>, +{ + let path = path.into(); + let mut components = path.components(); + if let Some(Component::Normal(c)) = components.next() { + if c == "~" { + if let Ok(mut buf) = home_dir() { + buf.push(components); + return Cow::Owned(buf); } } } - path.to_path_buf() + path } /// Normalize a path without resolving symlinks. @@ -109,9 +115,9 @@ pub fn normalize(path: impl AsRef) -> PathBuf { /// This function is used instead of [`std::fs::canonicalize`] because we don't want to verify /// here if the path exists, just normalize it's components. pub fn canonicalize(path: impl AsRef) -> PathBuf { - let path = expand_tilde(path); + let path = expand_tilde(path.as_ref()); let path = if path.is_relative() { - current_working_dir().join(path) + Cow::Owned(current_working_dir().join(path)) } else { path }; @@ -183,3 +189,32 @@ pub fn get_truncated_path(path: impl AsRef) -> PathBuf { ret.push(file); ret } + +#[cfg(test)] +mod tests { + use std::{ + ffi::OsStr, + path::{Component, Path}, + }; + + use crate::path; + + #[test] + fn expand_tilde() { + for path in ["~", "~/foo"] { + let expanded = path::expand_tilde(Path::new(path)); + + let tilde = Component::Normal(OsStr::new("~")); + + let mut component_count = 0; + for component in expanded.components() { + // No tilde left. + assert_ne!(component, tilde); + component_count += 1; + } + + // The path was at least expanded to something. + assert_ne!(component_count, 0); + } + } +} diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index b7ceeba59..3d7ea3fc8 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -110,14 +110,14 @@ fn open(cx: &mut compositor::Context, args: &[Cow], event: PromptEvent) -> ensure!(!args.is_empty(), "wrong argument count"); for arg in args { let (path, pos) = args::parse_file(arg); - let path = helix_stdx::path::expand_tilde(&path); + let path = helix_stdx::path::expand_tilde(path); // If the path is a directory, open a file picker on that directory and update the status // message if let Ok(true) = std::fs::canonicalize(&path).map(|p| p.is_dir()) { let callback = async move { let call: job::Callback = job::Callback::EditorCompositor(Box::new( move |editor: &mut Editor, compositor: &mut Compositor| { - let picker = ui::file_picker(path, &editor.config()); + let picker = ui::file_picker(path.into_owned(), &editor.config()); compositor.push(Box::new(overlaid(picker))); }, )); @@ -1078,11 +1078,11 @@ fn change_current_directory( return Ok(()); } - let dir = helix_stdx::path::expand_tilde( - args.first() - .context("target directory not provided")? - .as_ref(), - ); + let dir = args + .first() + .context("target directory not provided")? + .as_ref(); + let dir = helix_stdx::path::expand_tilde(Path::new(dir)); helix_stdx::env::set_current_working_dir(dir)?; diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index d27e83553..0873116cb 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -428,9 +428,9 @@ pub mod completers { path } else { match path.parent() { - Some(path) if !path.as_os_str().is_empty() => path.to_path_buf(), + Some(path) if !path.as_os_str().is_empty() => Cow::Borrowed(path), // Path::new("h")'s parent is Some("")... - _ => helix_stdx::env::current_working_dir(), + _ => Cow::Owned(helix_stdx::env::current_working_dir()), } };