From 8493b5fca68097efd258ff0ffbcb6863e0c362c9 Mon Sep 17 00:00:00 2001 From: midnightexigent <36641328+midnightexigent@users.noreply.github.com> Date: Wed, 18 May 2022 21:49:50 +0200 Subject: [PATCH 01/28] Add tree-sitter ssh client config queries (#2498) Co-authored-by: Michael Davis --- book/src/generated/lang-support.md | 1 + languages.toml | 10 + .../queries/sshclientconfig/highlights.scm | 324 ++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 runtime/queries/sshclientconfig/highlights.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 95cf91a433877..f857fc0d495f2 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -78,6 +78,7 @@ | scala | ✓ | | ✓ | `metals` | | solidity | ✓ | | | `solc` | | sql | ✓ | | | | +| sshclientconfig | ✓ | | | | | svelte | ✓ | | ✓ | `svelteserver` | | swift | ✓ | | | `sourcekit-lsp` | | tablegen | ✓ | ✓ | ✓ | | diff --git a/languages.toml b/languages.toml index 46b6074721aa0..ed406a7184de7 100644 --- a/languages.toml +++ b/languages.toml @@ -1355,3 +1355,13 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "meson" source = { git = "https://github.com/bearcove/tree-sitter-meson", rev = "feea83be9225842490066522ced2d13eb9cce0bd" } + +[[language]] +name = "sshclientconfig" +scope = "source.sshclientconfig" +file-types = [".ssh/config", "/etc/ssh/ssh_config"] +roots = [] + +[[grammar]] +name = "sshclientconfig" +source = { git = "https://github.com/metio/tree-sitter-ssh-client-config", rev = "769d7a01a2e5493b4bb5a51096c6bf4be130b024" } diff --git a/runtime/queries/sshclientconfig/highlights.scm b/runtime/queries/sshclientconfig/highlights.scm new file mode 100644 index 0000000000000..83a212a20a42d --- /dev/null +++ b/runtime/queries/sshclientconfig/highlights.scm @@ -0,0 +1,324 @@ +(host) @keyword +(host_value) @identifier + +(match) @keyword +(match_value) @identifier + +(add_keys_to_agent) @keyword +(add_keys_to_agent_value) @boolean + +(address_family) @keyword +(address_family_value) @type + +(batch_mode) @keyword +(batch_mode_value) @boolean + +(bind_address) @keyword +(bind_address_value) @string + +(bind_interface) @keyword +(bind_interface_value) @string + +(canonical_domains) @keyword +(canonical_domains_value) @identifier + +(canonicalize_fallback_local) @keyword +(canonicalize_fallback_local_value) @boolean + +(canonicalize_hostname) @keyword +(canonicalize_hostname_value) @boolean + +(canonicalize_max_dots) @keyword +(canonicalize_max_dots_value) @number + +(canonicalize_permitted_cnames) @keyword +(canonicalize_permitted_cnames_value) @identifier + +(ca_signature_algorithms) @keyword +(ca_signature_algorithms_value) @identifier + +(certificate_file) @keyword +(certificate_file_value) @file + +(challenge_response_authentication) @keyword +(challenge_response_authentication_value) @boolean + +(check_host_ip) @keyword +(check_host_ip_value) @boolean + +(cipher) @keyword +(cipher_value) @identifier + +(ciphers) @keyword +(ciphers_value) @identifier + +(clear_all_forwardings) @keyword +(clear_all_forwardings_value) @boolean + +(comment) @comment + +(compression) @keyword +(compression_value) @boolean + +(connect_timeout) @keyword +(connect_timeout_value) @number + +(connection_attempts) @keyword +(connection_attempts_value) @number + +(control_master) @keyword +(control_master_value) @type + +(control_path) @keyword +(control_path_value) @file + +(control_persist) @keyword +(control_persist_value) @type + +(dynamic_forward) @keyword +(dynamic_forward_value) @string + +(enable_ssh_keysign) @keyword +(enable_ssh_keysign_value) @boolean + +(escape_char) @keyword +(escape_char_value) @string + +(exit_on_forward_failure) @keyword +(exit_on_forward_failure_value) @boolean + +(fingerprint_hash) @keyword +(fingerprint_hash_value) @identifier + +(fork_after_authentication) @keyword +(fork_after_authentication_value) @boolean + +(forward_agent) @keyword +(forward_agent_value) @boolean + +(forward_x11) @keyword +(forward_x11_value) @boolean + +(forward_x11_timeout) @keyword +(forward_x11_timeout_value) @time + +(forward_x11_trusted) @keyword +(forward_x11_trusted_value) @boolean + +(gateway_ports) @keyword +(gateway_ports_value) @boolean + +(global_known_hosts_file) @keyword +(global_known_hosts_file_value) @file + +(gssapi_authentication) @keyword +(gssapi_authentication_value) @boolean + +(gssapi_client_identity) @keyword +(gssapi_client_identity_value) @string + +(gssapi_delegate_credentials) @keyword +(gssapi_delegate_credentials_value) @boolean + +(gssapi_kex_algorithms) @keyword +(gssapi_kex_algorithms_value) @identifier + +(gssapi_key_exchange) @keyword +(gssapi_key_exchange_value) @boolean + +(gssapi_renewal_forces_rekey) @keyword +(gssapi_renewal_forces_rekey_value) @boolean + +(gssapi_server_identity) @keyword +(gssapi_server_identity_value) @string + +(gssapi_trust_dns) @keyword +(gssapi_trust_dns_value) @boolean + +(hash_known_hosts) @keyword +(hash_known_hosts_value) @boolean + +(host_key_algorithms) @keyword +(host_key_algorithms_value) @identifier + +(host_key_alias) @keyword +(host_key_alias_value) @string + +(hostbased_accepted_algorithms) @keyword +(hostbased_accepted_algorithms_value) @identifier + +(hostbased_authentication) @keyword +(hostbased_authentication_value) @boolean + +(hostname) @keyword +(hostname_value) @string + +(identities_only) @keyword +(identities_only_value) @boolean + +(identity_agent) @keyword +(identity_agent_value) @string + +(identity_file) @keyword +(identity_file_value) @file + +(ignore_unknown) @keyword +(ignore_unknown_value) @string + +(include) @keyword +(include_value) @file + +(ip_qos) @keyword +(ip_qos_value) @type + +(kbd_interactive_authentication) @keyword +(kbd_interactive_authentication_value) @boolean + +(kbd_interactive_devices) @keyword +(kbd_interactive_devices_value) @type + +(kex_algorithms) @keyword +(kex_algorithms_value) @identifier + +(known_hosts_command) @keyword +(known_hosts_command_value) @string + +(local_command) @keyword +(local_command_value) @string + +(local_forward) @keyword +(local_forward_value) @string + +(log_level) @keyword +(log_level_value) @type + +(log_verbose) @keyword +(log_verbose_value) @string + +(macs) @keyword +(macs_value) @identifier + +(no_host_authentication_for_localhost) @keyword +(no_host_authentication_for_localhost_value) @boolean + +(number_of_password_prompts) @keyword +(number_of_password_prompts_value) @number + +(password_authentication) @keyword +(password_authentication_value) @boolean + +(permit_local_command) @keyword +(permit_local_command_value) @boolean + +(permit_remote_open) @keyword +(permit_remote_open_value) @string + +(pkcs11_provider) @keyword +(pkcs11_provider_value) @string + +(port) @keyword +(port_value) @number + +(preferred_authentications) @keyword +(preferred_authentications_value) @type + +(protocol) @keyword +(protocol_value) @number + +(proxy_command) @keyword +(proxy_command_value) @string + +(proxy_jump) @keyword +(proxy_jump_value) @string + +(proxy_use_fdpass) @keyword +(proxy_use_fdpass_value) @boolean + +(pubkey_accepted_algorithms) @keyword +(pubkey_accepted_algorithms_value) @identifier + +(pubkey_accepted_key_types) @keyword +(pubkey_accepted_key_types_value) @identifier + +(pubkey_authentication) @keyword +(pubkey_authentication_value) @boolean + +(rekey_limit) @keyword +(rekey_limit_value) @string + +(remote_command) @keyword +(remote_command_value) @string + +(remote_forward) @keyword +(remote_forward_value) @string + +(request_tty) @keyword +(request_tty_value) @type + +(revoked_host_keys) @keyword +(revoked_host_keys_value) @file + +(security_key_provider) @keyword +(security_key_provider_value) @string + +(send_env) @keyword +(send_env_value) @string + +(server_alive_count_max) @keyword +(server_alive_count_max_value) @number + +(server_alive_interval) @keyword +(server_alive_interval_value) @number + +(session_type) @keyword +(session_type_value) @type + +(set_env) @keyword +(set_env_value) @string + +(stdin_null) @keyword +(stdin_null_value) @boolean + +(stream_local_bind_mask) @keyword +(stream_local_bind_mask_value) @string + +(stream_local_bind_unlink) @keyword +(stream_local_bind_unlink_value) @boolean + +(strict_host_key_checking) @keyword +(strict_host_key_checking_value) @type + +(syslog_facility) @keyword +(syslog_facility_value) @type + +(tcp_keep_alive) @keyword +(tcp_keep_alive_value) @boolean +(keep_alive) @keyword +(keep_alive_value) @boolean + +(tunnel) @keyword +(tunnel_value) @type + +(tunnel_device) @keyword +(tunnel_device_value) @string + +(update_host_keys) @keyword +(update_host_keys_value) @type + +(use_keychain) @keyword +(use_keychain_value) @boolean + +(user) @keyword +(user_value) @string + +(user_known_hosts_file) @keyword +(user_known_hosts_file_value) @file + +(verify_host_key_dns) @keyword +(verify_host_key_dns_value) @type + +(visual_host_key) @keyword +(visual_host_key_value) @boolean + +(xauth_location) @keyword +(xauth_location_value) @file From 301ed9b48f3a331233a4d707a728e1a572702233 Mon Sep 17 00:00:00 2001 From: Alexis Kalabura <55039048+axdank@users.noreply.github.com> Date: Thu, 19 May 2022 21:18:19 -0400 Subject: [PATCH 02/28] deletion of lines affecting popup scrolling (#2497) --- helix-term/src/ui/popup.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs index 069a22f45b9ba..185ec15daa0b5 100644 --- a/helix-term/src/ui/popup.rs +++ b/helix-term/src/ui/popup.rs @@ -88,8 +88,6 @@ impl Popup { pub fn scroll(&mut self, offset: usize, direction: bool) { if direction { - self.scroll += offset; - let max_offset = self.child_size.1.saturating_sub(self.size.1); self.scroll = (self.scroll + offset).min(max_offset as usize); } else { From 62fd1f699988bdf7bba4a9ada511b5303b01d328 Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Fri, 20 May 2022 05:19:46 +0400 Subject: [PATCH 03/28] Include macro attributes to impls, structs, enums, functions etc. textobjects (#2494) --- helix-core/src/syntax.rs | 52 ++++++++++++----------- runtime/queries/rust/textobjects.scm | 63 ++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index b20d9092fae08..1cfa04e7c194e 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -234,6 +234,7 @@ pub struct TextObjectQuery { pub query: Query, } +#[derive(Debug)] pub enum CapturedNode<'a> { Single(Node<'a>), /// Guaranteed to be not empty @@ -268,12 +269,12 @@ impl TextObjectQuery { /// and support for this is partial and could use improvement. /// /// ```query - /// ;; supported: /// (comment)+ @capture /// - /// ;; unsupported: + /// ; OR /// ( - /// (comment)+ + /// (comment)* + /// . /// (function) /// ) @capture /// ``` @@ -299,28 +300,29 @@ impl TextObjectQuery { let capture_idx = capture_names .iter() .find_map(|cap| self.query.capture_index_for_name(cap))?; - let captures = cursor.matches(&self.query, node, RopeProvider(slice)); - - let nodes = captures.flat_map(move |mat| { - let captures = mat.captures.iter().filter(move |c| c.index == capture_idx); - let nodes = captures.map(|c| c.node); - let pattern_idx = mat.pattern_index; - let quantifier = self.query.capture_quantifiers(pattern_idx)[capture_idx as usize]; - - let iter: Box> = match quantifier { - CaptureQuantifier::OneOrMore | CaptureQuantifier::ZeroOrMore => { - let nodes: Vec = nodes.collect(); - if nodes.is_empty() { - Box::new(std::iter::empty()) - } else { - Box::new(std::iter::once(CapturedNode::Grouped(nodes))) - } + + let nodes = cursor + .captures(&self.query, node, RopeProvider(slice)) + .filter_map(move |(mat, _)| { + let nodes: Vec<_> = mat + .captures + .iter() + .filter_map(|x| { + if x.index == capture_idx { + Some(x.node) + } else { + None + } + }) + .collect(); + + if nodes.len() > 1 { + Some(CapturedNode::Grouped(nodes)) + } else { + nodes.into_iter().map(CapturedNode::Single).next() } - _ => Box::new(nodes.map(CapturedNode::Single)), - }; + }); - iter - }); Some(nodes) } } @@ -1122,8 +1124,8 @@ pub(crate) fn generate_edits( use std::sync::atomic::{AtomicUsize, Ordering}; use std::{iter, mem, ops, str, usize}; use tree_sitter::{ - CaptureQuantifier, Language as Grammar, Node, Parser, Point, Query, QueryCaptures, QueryCursor, - QueryError, QueryMatch, Range, TextProvider, Tree, + Language as Grammar, Node, Parser, Point, Query, QueryCaptures, QueryCursor, QueryError, + QueryMatch, Range, TextProvider, Tree, }; const CANCELLATION_CHECK_INTERVAL: usize = 100; diff --git a/runtime/queries/rust/textobjects.scm b/runtime/queries/rust/textobjects.scm index 086db67ae4f60..99b5eb4d912f1 100644 --- a/runtime/queries/rust/textobjects.scm +++ b/runtime/queries/rust/textobjects.scm @@ -1,23 +1,62 @@ -(function_item - body: (_) @function.inside) @function.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (function_item + body: (_) @function.inside)) @function.around -(struct_item - body: (_) @class.inside) @class.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (struct_item + body: (_) @class.inside)) @class.around -(enum_item - body: (_) @class.inside) @class.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (enum_item + body: (_) @class.inside)) @class.around -(union_item - body: (_) @class.inside) @class.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (union_item + body: (_) @class.inside)) @class.around -(trait_item - body: (_) @class.inside) @class.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (trait_item + body: (_) @class.inside)) @class.around -(impl_item - body: (_) @class.inside) @class.around +( + [ + (attribute_item)+ + (line_comment)+ + ]* + . + (impl_item + body: (_) @class.inside)) @class.around (parameters (_) @parameter.inside) + +(type_parameters + (_) @parameter.inside) (closure_parameters (_) @parameter.inside) From 8958bf0a926a6e6afc63f0c59f3fa6761f5da709 Mon Sep 17 00:00:00 2001 From: Roland Kovacs Date: Fri, 20 May 2022 03:25:04 +0200 Subject: [PATCH 04/28] Implement view transpose (#2461) Change the layout of existing split view from horizontal to vertical and vica-versa. It only effects the focused view and its siblings, i.e. not recursive. Command is mapped to 't' or 'C-t' under the Window menus. --- helix-term/src/commands.rs | 5 +++++ helix-term/src/keymap/default.rs | 2 ++ helix-view/src/editor.rs | 4 ++++ helix-view/src/tree.rs | 12 ++++++++++++ 4 files changed, 23 insertions(+) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index f0b54e0b7fa49..855f2d7dcb16c 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -360,6 +360,7 @@ impl MappableCommand { jump_view_left, "Jump to the split to the left", jump_view_up, "Jump to the split above", jump_view_down, "Jump to the split below", + transpose_view, "Transpose splits", rotate_view, "Goto next window", hsplit, "Horizontal bottom split", hsplit_new, "Horizontal bottom split scratch buffer", @@ -3863,6 +3864,10 @@ fn jump_view_down(cx: &mut Context) { cx.editor.focus_down() } +fn transpose_view(cx: &mut Context) { + cx.editor.transpose_view() +} + // split helper, clear it later fn split(cx: &mut Context, action: Action) { let (view, doc) = current!(cx.editor); diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index a8ff8be91bf6e..124517d4a8f7c 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -171,6 +171,7 @@ pub fn default() -> HashMap { "C-w" | "w" => rotate_view, "C-s" | "s" => hsplit, "C-v" | "v" => vsplit, + "C-t" | "t" => transpose_view, "f" => goto_file_hsplit, "F" => goto_file_vsplit, "C-q" | "q" => wclose, @@ -226,6 +227,7 @@ pub fn default() -> HashMap { "C-w" | "w" => rotate_view, "C-s" | "s" => hsplit, "C-v" | "v" => vsplit, + "C-t" | "t" => transpose_view, "f" => goto_file_hsplit, "F" => goto_file_vsplit, "C-q" | "q" => wclose, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index f4a48ba65da3c..1ad210592edaa 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -885,6 +885,10 @@ impl Editor { self.tree.focus_direction(tree::Direction::Down); } + pub fn transpose_view(&mut self) { + self.tree.transpose(); + } + pub fn should_close(&self) -> bool { self.tree.is_empty() } diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs index b068f4c7e3ca9..522a79d786ac5 100644 --- a/helix-view/src/tree.rs +++ b/helix-view/src/tree.rs @@ -526,6 +526,18 @@ impl Tree { } } + pub fn transpose(&mut self) { + let focus = self.focus; + let parent = self.nodes[focus].parent; + if let Content::Container(container) = &mut self.nodes[parent].content { + container.layout = match container.layout { + Layout::Vertical => Layout::Horizontal, + Layout::Horizontal => Layout::Vertical, + }; + self.recalculate(); + } + } + pub fn area(&self) -> Rect { self.area } From 6462542fc50078e41074b70d0e70d52f351959fa Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 20 May 2022 09:27:59 +0800 Subject: [PATCH 05/28] support insert register in prompt (#2458) * support insert register in prompt * use next_char_handler instead of a flag * Fix clippy issue * show autoinfo when inserting register * Revert "show autoinfo when inserting register" This reverts commit 5488344de1c607d44bdf8693287a85b92cb32518. * use completion instead of autoinfo autoinfo is overlapped when using prompt * recalculate_completion after inserting register * Update helix-term/src/ui/prompt.rs Co-authored-by: Ivan Tham Co-authored-by: Ivan Tham --- book/src/keymap.md | 1 + helix-term/src/ui/prompt.rs | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/book/src/keymap.md b/book/src/keymap.md index 9d5d084177898..e56eeefc41ec6 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -367,6 +367,7 @@ Keys to use within prompt, Remapping currently not supported. | `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/ui/prompt.rs b/helix-term/src/ui/prompt.rs index ef08edf2d836f..c3c502e0d80d3 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -16,6 +16,7 @@ use helix_view::{ }; pub type Completion = (RangeFrom, Cow<'static, str>); +type PromptCharHandler = Box; pub struct Prompt { prompt: Cow<'static, str>, @@ -28,6 +29,7 @@ pub struct Prompt { completion_fn: Box Vec>, callback_fn: Box, pub doc_fn: Box Option>>, + next_char_handler: Option, } #[derive(Clone, Copy, PartialEq)] @@ -78,6 +80,7 @@ impl Prompt { completion_fn: Box::new(completion_fn), callback_fn: Box::new(callback_fn), doc_fn: Box::new(|_| None), + next_char_handler: None, } } @@ -191,6 +194,13 @@ impl Prompt { } pub fn insert_char(&mut self, c: char, cx: &Context) { + if let Some(handler) = &self.next_char_handler.take() { + handler(self, c, cx); + + self.next_char_handler = None; + return; + } + self.line.insert(self.cursor, c); let mut cursor = GraphemeCursor::new(self.cursor, self.line.len(), false); if let Ok(Some(pos)) = cursor.next_boundary(&self.line, 0) { @@ -538,6 +548,35 @@ impl Component for Prompt { (self.callback_fn)(cx, &self.line, PromptEvent::Update) } ctrl!('q') => self.exit_selection(), + ctrl!('r') => { + self.completion = cx + .editor + .registers + .inner() + .iter() + .map(|(ch, reg)| { + let content = reg + .read() + .get(0) + .and_then(|s| s.lines().next().to_owned()) + .unwrap_or_default(); + (0.., format!("{} {}", ch, &content).into()) + }) + .collect(); + self.next_char_handler = Some(Box::new(|prompt, c, context| { + prompt.insert_str( + context + .editor + .registers + .read(c) + .and_then(|r| r.first()) + .map_or("", |r| r.as_str()), + ); + prompt.recalculate_completion(context.editor); + })); + (self.callback_fn)(cx, &self.line, PromptEvent::Update); + return EventResult::Consumed(None); + } // any char event that's not mapped to any other combo KeyEvent { code: KeyCode::Char(c), From a6da99a14483c2c18c8fa83c5291b2ae866bbbca Mon Sep 17 00:00:00 2001 From: Zeddicus414 <31261142+Zeddicus414@users.noreply.github.com> Date: Mon, 9 May 2022 22:50:00 -0500 Subject: [PATCH 06/28] Change python highlights.scm to more fully utilize the themes. Create type keywords Allow _CONSTANTS to start with _ Highlight constants before constructors Move some keywords into @keyword.control --- runtime/queries/python/highlights.scm | 51 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index 9131acc5b58bb..88d9755cacc26 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -1,10 +1,19 @@ ; Identifier naming conventions +((identifier) @constant + (#match? @constant "^[A-Z_]*$")) + ((identifier) @constructor (#match? @constructor "^[A-Z]")) -((identifier) @constant - (#match? @constant "^[A-Z][A-Z_]*$")) +; Types + +((identifier) @type + (#match? + @type + "^(bool|bytes|dict|float|frozenset|int|list|set|str|tuple)$")) + +(type (identifier)) @type ; Builtin functions @@ -12,7 +21,7 @@ function: (identifier) @function.builtin) (#match? @function.builtin - "^(abs|all|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|vars|zip|__import__)$")) + "^(abs|all|any|ascii|bin|breakpoint|bytearray|callable|chr|classmethod|compile|complex|delattr|dir|divmod|enumerate|eval|exec|filter|format|getattr|globals|hasattr|hash|help|hex|id|input|isinstance|issubclass|iter|len|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|setattr|slice|sorted|staticmethod|sum|super|type|vars|zip|__import__)$")) ; Function calls @@ -30,7 +39,6 @@ (identifier) @variable (attribute attribute: (identifier) @variable.other.member) -(type (identifier) @type) ; Literals @@ -81,41 +89,48 @@ ">>" "|" "~" - "and" - "in" - "is" - "not" - "or" ] @operator [ "as" "assert" - "async" "await" "break" - "class" "continue" - "def" - "del" "elif" "else" "except" - "exec" "finally" "for" "from" - "global" "if" "import" - "lambda" - "nonlocal" "pass" - "print" "raise" "return" "try" "while" "with" "yield" +] @keyword.control + +(for_statement "in" @keyword.control) +(for_in_clause "in" @keyword.control) + +[ + "and" + "async" + "class" + "def" + "del" + "exec" + "global" + "in" + "is" + "lambda" + "nonlocal" + "not" + "or" + "print" ] @keyword + From 8e8d4ba27f7610f228595e84e7c201c29ffa447c Mon Sep 17 00:00:00 2001 From: Zeddicus414 <31261142+Zeddicus414@users.noreply.github.com> Date: Mon, 9 May 2022 22:50:31 -0500 Subject: [PATCH 07/28] dark_plus theme constructor should be green. --- runtime/themes/dark_plus.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/themes/dark_plus.toml b/runtime/themes/dark_plus.toml index 6c9d59194c5b4..c785dd3888393 100644 --- a/runtime/themes/dark_plus.toml +++ b/runtime/themes/dark_plus.toml @@ -6,7 +6,7 @@ "type" = { fg = "type" } "type.builtin" = { fg = "type" } "type.enum.variant" = { fg = "constant" } -"constructor" = { fg = "constant" } +"constructor" = { fg = "type" } "variable.other.member" = { fg = "variable" } "keyword" = { fg = "blue2" } From abef250c58620fb0a439b13b9f857a5b661e325f Mon Sep 17 00:00:00 2001 From: Paul Scott Date: Fri, 13 May 2022 16:21:38 +1000 Subject: [PATCH 08/28] Python highlight improvements: type, parameter etc * str, list, etc. handled as @function.builtin and @type.builtin * None and non-conforming type indentifiers as @type in type hints * class identifiers treated as @type * @constructor used for constructor definitions and calls rather than as a catch-all for type-like things * Parameters highlighted * self and cls as @variable.builtin * improved decorator highlighting as part of @function Re-ordering of some statements to give more accurate priority. --- runtime/queries/python/highlights.scm | 74 +++++++++++++++++++-------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index 88d9755cacc26..fa622435a46a1 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -1,44 +1,78 @@ -; Identifier naming conventions - -((identifier) @constant - (#match? @constant "^[A-Z_]*$")) - -((identifier) @constructor - (#match? @constructor "^[A-Z]")) - -; Types - -((identifier) @type - (#match? - @type - "^(bool|bytes|dict|float|frozenset|int|list|set|str|tuple)$")) - -(type (identifier)) @type - ; Builtin functions ((call function: (identifier) @function.builtin) (#match? @function.builtin - "^(abs|all|any|ascii|bin|breakpoint|bytearray|callable|chr|classmethod|compile|complex|delattr|dir|divmod|enumerate|eval|exec|filter|format|getattr|globals|hasattr|hash|help|hex|id|input|isinstance|issubclass|iter|len|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|setattr|slice|sorted|staticmethod|sum|super|type|vars|zip|__import__)$")) + "^(abs|all|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|vars|zip|__import__)$")) ; Function calls -(decorator) @function +(call + function: (attribute attribute: (identifier) @constructor) + (#match? @constructor "^[A-Z]")) +(call + function: (identifier) @constructor + (#match? @constructor "^[A-Z]")) (call function: (attribute attribute: (identifier) @function.method)) + (call function: (identifier) @function) ; Function definitions +(function_definition + name: (identifier) @constructor + (#match? @constructor "^(__new__|__init__)$")) + (function_definition name: (identifier) @function) -(identifier) @variable +; Decorators + +(decorator) @function +(decorator (identifier) @function) + +; Parameters + +((identifier) @variable.builtin + (#match? @variable.builtin "^(self|cls)$")) + +(parameters (identifier) @variable.parameter) +(parameters (typed_parameter (identifier) @variable.parameter)) + +; Types + +((identifier) @type.builtin + (#match? + @type.builtin + "^(bool|bytes|dict|float|frozenset|int|list|set|str|tuple)$")) + +; In type hints make everything types to catch non-conforming identifiers +; (e.g., datetime.datetime) and None +(type [(identifier) (none)] @type) +; Handle [] . and | nesting 4 levels deep +(type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type))))) + +(class_definition name: (identifier) @type) +(class_definition superclasses: (argument_list (identifier) @type)) + +; Variables + +((identifier) @constant + (#match? @constant "^[A-Z_]{2,}$")) + +((identifier) @type + (#match? @type "^[A-Z]")) + (attribute attribute: (identifier) @variable.other.member) +(identifier) @variable ; Literals From e680f9644d485bcb5b9518515739f682d5a683f6 Mon Sep 17 00:00:00 2001 From: Paul Scott Date: Sat, 14 May 2022 12:39:36 +1000 Subject: [PATCH 09/28] Python handling highlighting parameters with defaults --- runtime/queries/python/highlights.scm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index fa622435a46a1..75e76c6853c60 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -42,6 +42,8 @@ (parameters (identifier) @variable.parameter) (parameters (typed_parameter (identifier) @variable.parameter)) +(parameters (default_parameter name: (identifier) @variable.parameter)) +(parameters (typed_default_parameter name: (identifier) @variable.parameter)) ; Types From 2a2030142f1d5cb8a130b0541399860d0e0cae15 Mon Sep 17 00:00:00 2001 From: Paul Scott Date: Sat, 14 May 2022 12:50:08 +1000 Subject: [PATCH 10/28] Python highlight keyword argument as parameter --- runtime/queries/python/highlights.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index 75e76c6853c60..352940727630c 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -44,6 +44,7 @@ (parameters (typed_parameter (identifier) @variable.parameter)) (parameters (default_parameter name: (identifier) @variable.parameter)) (parameters (typed_default_parameter name: (identifier) @variable.parameter)) +(keyword_argument name: (identifier) @variable.parameter) ; Types From 09f9f70576830c328af37b73f96286d80ecf20f9 Mon Sep 17 00:00:00 2001 From: Paul Scott Date: Sun, 15 May 2022 00:03:53 +1000 Subject: [PATCH 11/28] Python highlight decorator attribute --- runtime/queries/python/highlights.scm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm index 352940727630c..93e08d58482be 100644 --- a/runtime/queries/python/highlights.scm +++ b/runtime/queries/python/highlights.scm @@ -34,6 +34,9 @@ (decorator) @function (decorator (identifier) @function) +(decorator (attribute attribute: (identifier) @function)) +(decorator (call + function: (attribute attribute: (identifier) @function))) ; Parameters From 776686ab2471419b9c9aac8507e8d301f450389a Mon Sep 17 00:00:00 2001 From: Robert Walter <26892280+RobWalt@users.noreply.github.com> Date: Fri, 20 May 2022 03:30:28 +0200 Subject: [PATCH 12/28] Separate colors for different diagnostics types (#2437) * feat(theme): add separate diagnostic colors This commit adds separate diagnostic highlight colors for the different types of LSP severities. If the severity type doesn't exist or is unknown, we use some fallback coloring which was in use before this commit. Some initial color options were also added in the theme.toml Resolves issue #2157 * feat(theme): add docs for new diagnostic options * feat(theme): adjust defaults & reduce redundancy - the different colors for different diagnostic severities are now disabled in the default theme, instead diagnostics are just generally underlined (as prior to the changes of this feature) - the theme querying is now done once instead of every iteration in the loop of processing every diagnostic message --- book/src/themes.md | 6 +++++- helix-term/src/ui/editor.rs | 25 ++++++++++++++++++++++--- theme.toml | 4 ++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index e73aedc944306..97955cb71a9ce 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -234,6 +234,10 @@ These scopes are used for theming the editor interface. | `error` | Diagnostics error (gutter) | | `info` | Diagnostics info (gutter) | | `hint` | Diagnostics hint (gutter) | -| `diagnostic` | For text in editing area | +| `diagnostic` | Diagnostics fallback style (editing area) | +| `diagnostic.hint` | Diagnostics hint (editing area) | +| `diagnostic.info` | Diagnostics info (editing area) | +| `diagnostic.warning` | Diagnostics warning (editing area) | +| `diagnostic.error` | Diagnostics error (editing area) | [rulers-config]: ./configuration.md#editor-section diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 52e581632d7a4..85028e2ff1237 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -247,17 +247,36 @@ impl EditorView { doc: &Document, theme: &Theme, ) -> Vec<(usize, std::ops::Range)> { - let diagnostic_scope = theme - .find_scope_index("diagnostic") + use helix_core::diagnostic::Severity; + let get_scope_of = |scope| { + theme + .find_scope_index(scope) + // get one of the themes below as fallback values + .or_else(|| theme.find_scope_index("diagnostic")) .or_else(|| theme.find_scope_index("ui.cursor")) .or_else(|| theme.find_scope_index("ui.selection")) .expect( "at least one of the following scopes must be defined in the theme: `diagnostic`, `ui.cursor`, or `ui.selection`", - ); + ) + }; + + // basically just queries the theme color defined in the config + let hint = get_scope_of("diagnostic.hint"); + let info = get_scope_of("diagnostic.info"); + let warning = get_scope_of("diagnostic.warning"); + let error = get_scope_of("diagnostic.error"); + let r#default = get_scope_of("diagnostic"); // this is a bit redundant but should be fine doc.diagnostics() .iter() .map(|diagnostic| { + let diagnostic_scope = match diagnostic.severity { + Some(Severity::Info) => info, + Some(Severity::Hint) => hint, + Some(Severity::Warning) => warning, + Some(Severity::Error) => error, + _ => r#default, + }; ( diagnostic_scope, diagnostic.range.start..diagnostic.range.end, diff --git a/theme.toml b/theme.toml index 31ecd32e41ed1..2e6da866d90c5 100644 --- a/theme.toml +++ b/theme.toml @@ -67,6 +67,10 @@ label = "honey" "ui.menu.selected" = { fg = "revolver", bg = "white" } diagnostic = { modifiers = ["underlined"] } +# "diagnostic.hint" = { fg = "revolver", bg = "lilac" } +# "diagnostic.info" = { fg = "revolver", bg = "lavender" } +# "diagnostic.warning" = { fg = "revolver", bg = "honey" } +# "diagnostic.error" = { fg = "revolver", bg = "apricot" } warning = "lightning" error = "apricot" From 82fb217b6a99548065899b8405198eb08442803a Mon Sep 17 00:00:00 2001 From: Christoph Horn Date: Wed, 4 May 2022 11:13:13 +0200 Subject: [PATCH 13/28] use ui.menu instead of ui.statusline for command completion menu theme --- helix-term/src/ui/prompt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs index c3c502e0d80d3..a5be33ffebe23 100644 --- a/helix-term/src/ui/prompt.rs +++ b/helix-term/src/ui/prompt.rs @@ -340,7 +340,7 @@ impl Prompt { pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut Context) { let theme = &cx.editor.theme; let prompt_color = theme.get("ui.text"); - let completion_color = theme.get("ui.statusline"); + let completion_color = theme.get("ui.menu"); let selected_color = theme.get("ui.menu.selected"); // completion @@ -368,7 +368,7 @@ impl Prompt { if !self.completion.is_empty() { let area = completion_area; - let background = theme.get("ui.statusline"); + let background = theme.get("ui.menu"); let items = height as usize * cols as usize; From e7e13dcf0681999fcc601aab54c45ddf9b3f22d3 Mon Sep 17 00:00:00 2001 From: Christoph Horn Date: Thu, 5 May 2022 09:55:37 +0200 Subject: [PATCH 14/28] add `ui.menu` to default theme --- theme.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/theme.toml b/theme.toml index 2e6da866d90c5..55e859c82d9e4 100644 --- a/theme.toml +++ b/theme.toml @@ -64,6 +64,7 @@ label = "honey" "ui.cursor" = { modifiers = ["reversed"] } "ui.highlight" = { bg = "bossanova" } +"ui.menu" = { fg = "lilac", bg = "revolver" } "ui.menu.selected" = { fg = "revolver", bg = "white" } diagnostic = { modifiers = ["underlined"] } From 9be810fd01f495c795ab5e5b7240a32708d19f5c Mon Sep 17 00:00:00 2001 From: Christoph Horn Date: Fri, 6 May 2022 14:07:22 +0200 Subject: [PATCH 15/28] add missing `ui.menu` to themes, fix issues with some themes --- runtime/themes/bogster.toml | 4 +++- runtime/themes/ingrid.toml | 1 + runtime/themes/monokai.toml | 6 ++++-- runtime/themes/monokai_pro.toml | 1 + runtime/themes/monokai_pro_machine.toml | 1 + runtime/themes/monokai_pro_octagon.toml | 1 + runtime/themes/monokai_pro_ristretto.toml | 1 + runtime/themes/monokai_pro_spectrum.toml | 1 + runtime/themes/nord.toml | 1 + runtime/themes/onedark.toml | 1 + runtime/themes/onelight.toml | 3 ++- theme.toml | 2 +- 12 files changed, 18 insertions(+), 5 deletions(-) diff --git a/runtime/themes/bogster.toml b/runtime/themes/bogster.toml index af952071bf561..df3a7f3153062 100644 --- a/runtime/themes/bogster.toml +++ b/runtime/themes/bogster.toml @@ -59,7 +59,9 @@ # "ui.cursor.match" # TODO might want to override this because dimmed is not widely supported "ui.cursor.match" = { fg = "#313f4e", bg = "#dc7759" } "ui.cursor" = { fg = "#ABB2BF", modifiers = ["reversed"] } -"ui.menu.selected" = { fg = "#e5ded6", bg = "#313f4e" } + +"ui.menu" = { fg = "#e5ded6bg", bg = "#232d38" } +"ui.menu.selected" = { bg = "#313f4e" } "warning" = "#dc7759" "error" = "#dc597f" diff --git a/runtime/themes/ingrid.toml b/runtime/themes/ingrid.toml index da8730cc1c9b1..79b749b14d93c 100644 --- a/runtime/themes/ingrid.toml +++ b/runtime/themes/ingrid.toml @@ -57,6 +57,7 @@ "ui.selection" = { bg = "#540099" } # "ui.cursor.match" # TODO might want to override this because dimmed is not widely supported +"ui.menu" = { fg = "#7B91B3", bg = "#F3EAE9" } "ui.menu.selected" = { fg = "#D74E50", bg = "#F3EAE9" } "warning" = "#D4A520" diff --git a/runtime/themes/monokai.toml b/runtime/themes/monokai.toml index a714827287d74..3fb1fadc30f47 100644 --- a/runtime/themes/monokai.toml +++ b/runtime/themes/monokai.toml @@ -59,7 +59,8 @@ "ui.window" = { bg = "widget" } "ui.popup" = { bg = "widget" } "ui.help" = { bg = "widget" } -"ui.menu.selected" = { bg = "widget" } +"ui.menu" = { bg = "widget" } +"ui.menu.selected" = { bg = "#414339" } "ui.cursor" = { fg = "cursor", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "cursor", modifiers = ["reversed"] } @@ -71,7 +72,7 @@ "ui.linenr" = { fg = "#90908a" } "ui.linenr.selected" = { fg = "#c2c2bf" } -"ui.statusline" = { fg = "active_text", bg = "#75715e" } +"ui.statusline" = { fg = "active_text", bg = "#414339" } "ui.statusline.inactive" = { fg = "active_text", bg = "#75715e" } "ui.text" = { fg = "text", bg = "background" } @@ -98,3 +99,4 @@ active_text = "#ffffff" cursor = "#a6a6a6" inactive_cursor = "#878b91" widget = "#1e1f1c" +selection = "#414339" diff --git a/runtime/themes/monokai_pro.toml b/runtime/themes/monokai_pro.toml index b28f700cde5f7..5580a33c62712 100644 --- a/runtime/themes/monokai_pro.toml +++ b/runtime/themes/monokai_pro.toml @@ -4,6 +4,7 @@ "ui.linenr.selected" = { bg = "base3" } "ui.text.focus" = { fg = "yellow", modifiers= ["bold"] } +"ui.menu" = { fg = "base8", bg = "base3" } "ui.menu.selected" = { fg = "base2", bg = "yellow" } "ui.virtual" = "base5" diff --git a/runtime/themes/monokai_pro_machine.toml b/runtime/themes/monokai_pro_machine.toml index 4a2e53e425676..abbe5bdca9511 100644 --- a/runtime/themes/monokai_pro_machine.toml +++ b/runtime/themes/monokai_pro_machine.toml @@ -4,6 +4,7 @@ "ui.linenr.selected" = { bg = "base3" } "ui.text.focus" = { fg = "yellow", modifiers= ["bold"] } +"ui.menu" = { fg = "base8", bg = "base3" } "ui.menu.selected" = { fg = "base2", bg = "yellow" } "ui.virtual" = "base5" diff --git a/runtime/themes/monokai_pro_octagon.toml b/runtime/themes/monokai_pro_octagon.toml index 48709145e19b8..b249cfe21fb29 100644 --- a/runtime/themes/monokai_pro_octagon.toml +++ b/runtime/themes/monokai_pro_octagon.toml @@ -4,6 +4,7 @@ "ui.linenr.selected" = { bg = "base3" } "ui.text.focus" = { fg = "yellow", modifiers= ["bold"] } +"ui.menu" = { fg = "base8", bg = "base3" } "ui.menu.selected" = { fg = "base2", bg = "yellow" } "ui.virtual" = "base5" diff --git a/runtime/themes/monokai_pro_ristretto.toml b/runtime/themes/monokai_pro_ristretto.toml index f7c370949d036..cd4cbd8e9db6f 100644 --- a/runtime/themes/monokai_pro_ristretto.toml +++ b/runtime/themes/monokai_pro_ristretto.toml @@ -4,6 +4,7 @@ "ui.linenr.selected" = { bg = "base3" } "ui.text.focus" = { fg = "yellow", modifiers= ["bold"] } +"ui.menu" = { fg = "base8", bg = "base3" } "ui.menu.selected" = { fg = "base2", bg = "yellow" } "ui.virtual" = "base5" diff --git a/runtime/themes/monokai_pro_spectrum.toml b/runtime/themes/monokai_pro_spectrum.toml index 80e2a88d45253..4160a15e102c9 100644 --- a/runtime/themes/monokai_pro_spectrum.toml +++ b/runtime/themes/monokai_pro_spectrum.toml @@ -4,6 +4,7 @@ "ui.linenr.selected" = { bg = "base3" } "ui.text.focus" = { fg = "yellow", modifiers= ["bold"] } +"ui.menu" = { fg = "base8", bg = "base3" } "ui.menu.selected" = { fg = "base2", bg = "yellow" } "ui.virtual" = "base5" diff --git a/runtime/themes/nord.toml b/runtime/themes/nord.toml index a6384d1b34add..a61c17157f333 100644 --- a/runtime/themes/nord.toml +++ b/runtime/themes/nord.toml @@ -2,6 +2,7 @@ "ui.linenr.selected" = { fg = "nord4" } "ui.text.focus" = { fg = "nord8", modifiers= ["bold"] } +"ui.menu" = { fg = "nord6", bg = "#232d38" } "ui.menu.selected" = { fg = "nord8", bg = "nord2" } "ui.virtual" = "gray" diff --git a/runtime/themes/onedark.toml b/runtime/themes/onedark.toml index 573a635d77b02..280f6914da48b 100644 --- a/runtime/themes/onedark.toml +++ b/runtime/themes/onedark.toml @@ -69,6 +69,7 @@ diagnostic = { modifiers = ["underlined"] } "ui.help" = { bg = "gray" } "ui.popup" = { bg = "gray" } "ui.window" = { bg = "gray" } +"ui.menu" = { fg = "white", bg = "gray" } "ui.menu.selected" = { fg = "black", bg = "blue" } [palette] diff --git a/runtime/themes/onelight.toml b/runtime/themes/onelight.toml index 3674e821e7bbb..c89e20f9387f4 100644 --- a/runtime/themes/onelight.toml +++ b/runtime/themes/onelight.toml @@ -92,9 +92,10 @@ "ui.text" = { fg = "black" } "ui.text.focus" = { fg = "red", bg = "light-white", modifiers = ["bold"] } -"ui.help" = { bg = "light-white" } +"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.menu.selected" = { fg = "white", bg = "light-blue" } [palette] diff --git a/theme.toml b/theme.toml index 55e859c82d9e4..a0186e92aa726 100644 --- a/theme.toml +++ b/theme.toml @@ -64,7 +64,7 @@ label = "honey" "ui.cursor" = { modifiers = ["reversed"] } "ui.highlight" = { bg = "bossanova" } -"ui.menu" = { fg = "lilac", bg = "revolver" } +"ui.menu" = { fg = "lavender", bg = "revolver" } "ui.menu.selected" = { fg = "revolver", bg = "white" } diagnostic = { modifiers = ["underlined"] } From e04bb8b8915bfe1df1a5ee7a8750f2589f2aae06 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 19 May 2022 22:16:11 -0500 Subject: [PATCH 16/28] address rust 1.61.0 clippy lints (#2514) --- helix-term/src/commands.rs | 4 ++-- helix-term/src/ui/picker.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 855f2d7dcb16c..c3c7d224ea9dd 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1225,11 +1225,11 @@ fn replace(cx: &mut Context) { // need to wait for next key cx.on_next_key(move |cx, event| { let (view, doc) = current!(cx.editor); - let ch = match event { + let ch: Option<&str> = match event { KeyEvent { code: KeyCode::Char(ch), .. - } => Some(&ch.encode_utf8(&mut buf[..])[..]), + } => Some(ch.encode_utf8(&mut buf[..])), KeyEvent { code: KeyCode::Enter, .. diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 3ca6965cfd626..49d91be61247d 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -366,6 +366,7 @@ impl Picker { ); } else if pattern.starts_with(&self.previous_pattern) { // TODO: remove when retain_mut is in stable rust + #[allow(unused_imports)] use retain_mut::RetainMut; // optimization: if the pattern is a more specific version of the previous one From e8e252648f0287ccd503c59ea2c1fd7a155dafb5 Mon Sep 17 00:00:00 2001 From: Jacob Thompson Date: Fri, 20 May 2022 00:17:46 -0600 Subject: [PATCH 17/28] Added a default lsp server for Java in languages.toml (#2511) * Added a default lsp server for Java in languages.toml * Added a default lsp server for Java in languages.toml cont. Co-authored-by: Jacob Thompson --- 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 f857fc0d495f2..2e670807ce48a 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -38,7 +38,7 @@ | heex | ✓ | | | | | html | ✓ | | | `vscode-html-language-server` | | iex | ✓ | | | | -| java | ✓ | | | | +| java | ✓ | | | `jdtls` | | javascript | ✓ | | ✓ | `typescript-language-server` | | json | ✓ | | ✓ | `vscode-json-language-server` | | jsx | ✓ | | ✓ | `typescript-language-server` | diff --git a/languages.toml b/languages.toml index ed406a7184de7..5deed357619c4 100644 --- a/languages.toml +++ b/languages.toml @@ -551,6 +551,7 @@ scope = "source.java" injection-regex = "java" file-types = ["java"] roots = ["pom.xml"] +language-server = { command = "jdtls" } indent = { tab-width = 4, unit = " " } [[grammar]] From 3f10473d30eec79e135ea74fa2bc4cc996426128 Mon Sep 17 00:00:00 2001 From: Roland Kovacs Date: Mon, 9 May 2022 21:12:01 +0200 Subject: [PATCH 18/28] Implement view swapping * add Tree::swap_split_in_direction() * add swap_view_{left,down,up,right} commands, bound to H,J,K,L respectively in the Window menu(s) * add test for view swapping --- helix-term/src/commands.rs | 20 +++++ helix-term/src/keymap/default.rs | 8 ++ helix-view/src/editor.rs | 16 ++++ helix-view/src/tree.rs | 147 +++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c3c7d224ea9dd..2839f495c5cbe 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -360,6 +360,10 @@ impl MappableCommand { jump_view_left, "Jump to the split to the left", jump_view_up, "Jump to the split above", jump_view_down, "Jump to the split below", + swap_view_right, "Swap with the split to the right", + swap_view_left, "Swap with the split to the left", + swap_view_up, "Swap with the split above", + swap_view_down, "Swap with the split below", transpose_view, "Transpose splits", rotate_view, "Goto next window", hsplit, "Horizontal bottom split", @@ -3864,6 +3868,22 @@ fn jump_view_down(cx: &mut Context) { cx.editor.focus_down() } +fn swap_view_right(cx: &mut Context) { + cx.editor.swap_right() +} + +fn swap_view_left(cx: &mut Context) { + cx.editor.swap_left() +} + +fn swap_view_up(cx: &mut Context) { + cx.editor.swap_up() +} + +fn swap_view_down(cx: &mut Context) { + cx.editor.swap_down() +} + fn transpose_view(cx: &mut Context) { cx.editor.transpose_view() } diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 124517d4a8f7c..a887f4b3f9671 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -180,6 +180,10 @@ pub fn default() -> HashMap { "C-j" | "j" | "down" => jump_view_down, "C-k" | "k" | "up" => jump_view_up, "C-l" | "l" | "right" => jump_view_right, + "L" => swap_view_right, + "K" => swap_view_up, + "H" => swap_view_left, + "J" => swap_view_down, "n" => { "New split scratch buffer" "C-s" | "s" => hsplit_new, "C-v" | "v" => vsplit_new, @@ -236,6 +240,10 @@ pub fn default() -> HashMap { "C-j" | "j" | "down" => jump_view_down, "C-k" | "k" | "up" => jump_view_up, "C-l" | "l" | "right" => jump_view_right, + "H" => swap_view_left, + "J" => swap_view_down, + "K" => swap_view_up, + "L" => swap_view_right, "n" => { "New split scratch buffer" "C-s" | "s" => hsplit_new, "C-v" | "v" => vsplit_new, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 1ad210592edaa..3ba6fea8766a9 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -885,6 +885,22 @@ impl Editor { self.tree.focus_direction(tree::Direction::Down); } + pub fn swap_right(&mut self) { + self.tree.swap_split_in_direction(tree::Direction::Right); + } + + pub fn swap_left(&mut self) { + self.tree.swap_split_in_direction(tree::Direction::Left); + } + + pub fn swap_up(&mut self) { + self.tree.swap_split_in_direction(tree::Direction::Up); + } + + pub fn swap_down(&mut self) { + self.tree.swap_split_in_direction(tree::Direction::Down); + } + pub fn transpose_view(&mut self) { self.tree.transpose(); } diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs index 522a79d786ac5..2aa35dee8980c 100644 --- a/helix-view/src/tree.rs +++ b/helix-view/src/tree.rs @@ -538,6 +538,24 @@ impl Tree { } } + pub fn swap_split_in_direction(&mut self, direction: Direction) { + if let Some(id) = self.find_split_in_direction(self.focus, direction) { + if let Some([focused, target]) = self.nodes.get_disjoint_mut([self.focus, id]) { + match (&mut focused.content, &mut target.content) { + (Content::View(focused), Content::View(target)) => { + std::mem::swap(&mut focused.doc, &mut target.doc); + std::mem::swap(&mut focused.id, &mut target.id); + self.focus = id; + } + // self.focus always points to a view which has a content of Content::View + // and find_split_in_direction() only returns a view which has content of + // Content::View. + _ => unreachable!(), + } + } + } + } + pub fn area(&self) -> Rect { self.area } @@ -649,4 +667,133 @@ mod test { assert_eq!(None, tree.find_split_in_direction(r0, Direction::Right)); assert_eq!(None, tree.find_split_in_direction(r0, Direction::Up)); } + + #[test] + fn swap_split_in_direction() { + let mut tree = Tree::new(Rect { + x: 0, + y: 0, + width: 180, + height: 80, + }); + + let doc_l0 = DocumentId::default(); + let mut view = View::new( + doc_l0, + vec![GutterType::Diagnostics, GutterType::LineNumbers], + ); + view.area = Rect::new(0, 0, 180, 80); + tree.insert(view); + + let l0 = tree.focus; + + let doc_r0 = DocumentId::default(); + let view = View::new( + doc_r0, + vec![GutterType::Diagnostics, GutterType::LineNumbers], + ); + tree.split(view, Layout::Vertical); + let r0 = tree.focus; + + tree.focus = l0; + + let doc_l1 = DocumentId::default(); + let view = View::new( + doc_l1, + vec![GutterType::Diagnostics, GutterType::LineNumbers], + ); + tree.split(view, Layout::Horizontal); + let l1 = tree.focus; + + tree.focus = l0; + + let doc_l2 = DocumentId::default(); + let view = View::new( + doc_l2, + vec![GutterType::Diagnostics, GutterType::LineNumbers], + ); + tree.split(view, Layout::Vertical); + let l2 = tree.focus; + + // Views in test + // | L0 | L2 | | + // | L1 | R0 | + + // Document IDs in test + // | l0 | l2 | | + // | l1 | r0 | + + fn doc_id(tree: &Tree, view_id: ViewId) -> Option { + if let Content::View(view) = &tree.nodes[view_id].content { + Some(view.doc) + } else { + None + } + } + + tree.focus = l0; + // `*` marks the view in focus from view table (here L0) + // | l0* | l2 | | + // | l1 | r0 | + tree.swap_split_in_direction(Direction::Down); + // | l1 | l2 | | + // | l0* | r0 | + assert_eq!(tree.focus, l1); + assert_eq!(doc_id(&tree, l0), Some(doc_l1)); + assert_eq!(doc_id(&tree, l1), Some(doc_l0)); + assert_eq!(doc_id(&tree, l2), Some(doc_l2)); + assert_eq!(doc_id(&tree, r0), Some(doc_r0)); + + tree.swap_split_in_direction(Direction::Right); + + // | l1 | l2 | | + // | r0 | l0* | + assert_eq!(tree.focus, r0); + assert_eq!(doc_id(&tree, l0), Some(doc_l1)); + assert_eq!(doc_id(&tree, l1), Some(doc_r0)); + assert_eq!(doc_id(&tree, l2), Some(doc_l2)); + assert_eq!(doc_id(&tree, r0), Some(doc_l0)); + + // cannot swap, nothing changes + tree.swap_split_in_direction(Direction::Up); + // | l1 | l2 | | + // | r0 | l0* | + assert_eq!(tree.focus, r0); + assert_eq!(doc_id(&tree, l0), Some(doc_l1)); + assert_eq!(doc_id(&tree, l1), Some(doc_r0)); + assert_eq!(doc_id(&tree, l2), Some(doc_l2)); + assert_eq!(doc_id(&tree, r0), Some(doc_l0)); + + // cannot swap, nothing changes + tree.swap_split_in_direction(Direction::Down); + // | l1 | l2 | | + // | r0 | l0* | + assert_eq!(tree.focus, r0); + assert_eq!(doc_id(&tree, l0), Some(doc_l1)); + assert_eq!(doc_id(&tree, l1), Some(doc_r0)); + assert_eq!(doc_id(&tree, l2), Some(doc_l2)); + assert_eq!(doc_id(&tree, r0), Some(doc_l0)); + + tree.focus = l2; + // | l1 | l2* | | + // | r0 | l0 | + + tree.swap_split_in_direction(Direction::Down); + // | l1 | r0 | | + // | l2* | l0 | + assert_eq!(tree.focus, l1); + assert_eq!(doc_id(&tree, l0), Some(doc_l1)); + assert_eq!(doc_id(&tree, l1), Some(doc_l2)); + assert_eq!(doc_id(&tree, l2), Some(doc_r0)); + assert_eq!(doc_id(&tree, r0), Some(doc_l0)); + + tree.swap_split_in_direction(Direction::Up); + // | l2* | r0 | | + // | l1 | l0 | + assert_eq!(tree.focus, l0); + assert_eq!(doc_id(&tree, l0), Some(doc_l2)); + assert_eq!(doc_id(&tree, l1), Some(doc_l1)); + assert_eq!(doc_id(&tree, l2), Some(doc_r0)); + assert_eq!(doc_id(&tree, r0), Some(doc_l0)); + } } From 6bd8924436636c252ec2bfcd02986771665f0c02 Mon Sep 17 00:00:00 2001 From: Roland Kovacs Date: Wed, 11 May 2022 21:12:59 +0200 Subject: [PATCH 19/28] Move Tree nodes on view swap Instead of moving the Node contents on view swap if they have the same parent reorder them to keep traversal order otherwise re-parent them. --- helix-view/src/tree.rs | 90 +++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs index 2aa35dee8980c..e6dba9163f26d 100644 --- a/helix-view/src/tree.rs +++ b/helix-view/src/tree.rs @@ -538,20 +538,72 @@ impl Tree { } } - pub fn swap_split_in_direction(&mut self, direction: Direction) { - if let Some(id) = self.find_split_in_direction(self.focus, direction) { - if let Some([focused, target]) = self.nodes.get_disjoint_mut([self.focus, id]) { - match (&mut focused.content, &mut target.content) { - (Content::View(focused), Content::View(target)) => { - std::mem::swap(&mut focused.doc, &mut target.doc); - std::mem::swap(&mut focused.id, &mut target.id); - self.focus = id; - } - // self.focus always points to a view which has a content of Content::View - // and find_split_in_direction() only returns a view which has content of - // Content::View. - _ => unreachable!(), + pub fn swap_split_in_direction(&mut self, direction: Direction) -> Option<()> { + let focus = self.focus; + let target = self.find_split_in_direction(focus, direction)?; + let focus_parent = self.nodes[focus].parent; + let target_parent = self.nodes[target].parent; + + if focus_parent == target_parent { + let parent = focus_parent; + let [parent, focus, target] = self.nodes.get_disjoint_mut([parent, focus, target])?; + match (&mut parent.content, &mut focus.content, &mut target.content) { + ( + Content::Container(parent), + Content::View(focus_view), + Content::View(target_view), + ) => { + let focus_pos = parent.children.iter().position(|id| focus_view.id == *id)?; + let target_pos = parent + .children + .iter() + .position(|id| target_view.id == *id)?; + // swap node positions so that traversal order is kept + parent.children[focus_pos] = target_view.id; + parent.children[target_pos] = focus_view.id; + // swap area so that views rendered at the correct location + std::mem::swap(&mut focus_view.area, &mut target_view.area); + + Some(()) } + _ => unreachable!(), + } + } else { + let [focus_parent, target_parent, focus, target] = + self.nodes + .get_disjoint_mut([focus_parent, target_parent, focus, target])?; + match ( + &mut focus_parent.content, + &mut target_parent.content, + &mut focus.content, + &mut target.content, + ) { + ( + Content::Container(focus_parent), + Content::Container(target_parent), + Content::View(focus_view), + Content::View(target_view), + ) => { + let focus_pos = focus_parent + .children + .iter() + .position(|id| focus_view.id == *id)?; + let target_pos = target_parent + .children + .iter() + .position(|id| target_view.id == *id)?; + // re-parent target and focus nodes + std::mem::swap( + &mut focus_parent.children[focus_pos], + &mut target_parent.children[target_pos], + ); + std::mem::swap(&mut focus.parent, &mut target.parent); + // swap area so that views rendered at the correct location + std::mem::swap(&mut focus_view.area, &mut target_view.area); + + Some(()) + } + _ => unreachable!(), } } } @@ -738,7 +790,7 @@ mod test { tree.swap_split_in_direction(Direction::Down); // | l1 | l2 | | // | l0* | r0 | - assert_eq!(tree.focus, l1); + assert_eq!(tree.focus, l0); assert_eq!(doc_id(&tree, l0), Some(doc_l1)); assert_eq!(doc_id(&tree, l1), Some(doc_l0)); assert_eq!(doc_id(&tree, l2), Some(doc_l2)); @@ -748,7 +800,7 @@ mod test { // | l1 | l2 | | // | r0 | l0* | - assert_eq!(tree.focus, r0); + assert_eq!(tree.focus, l0); assert_eq!(doc_id(&tree, l0), Some(doc_l1)); assert_eq!(doc_id(&tree, l1), Some(doc_r0)); assert_eq!(doc_id(&tree, l2), Some(doc_l2)); @@ -758,7 +810,7 @@ mod test { tree.swap_split_in_direction(Direction::Up); // | l1 | l2 | | // | r0 | l0* | - assert_eq!(tree.focus, r0); + assert_eq!(tree.focus, l0); assert_eq!(doc_id(&tree, l0), Some(doc_l1)); assert_eq!(doc_id(&tree, l1), Some(doc_r0)); assert_eq!(doc_id(&tree, l2), Some(doc_l2)); @@ -768,7 +820,7 @@ mod test { tree.swap_split_in_direction(Direction::Down); // | l1 | l2 | | // | r0 | l0* | - assert_eq!(tree.focus, r0); + assert_eq!(tree.focus, l0); assert_eq!(doc_id(&tree, l0), Some(doc_l1)); assert_eq!(doc_id(&tree, l1), Some(doc_r0)); assert_eq!(doc_id(&tree, l2), Some(doc_l2)); @@ -781,7 +833,7 @@ mod test { tree.swap_split_in_direction(Direction::Down); // | l1 | r0 | | // | l2* | l0 | - assert_eq!(tree.focus, l1); + assert_eq!(tree.focus, l2); assert_eq!(doc_id(&tree, l0), Some(doc_l1)); assert_eq!(doc_id(&tree, l1), Some(doc_l2)); assert_eq!(doc_id(&tree, l2), Some(doc_r0)); @@ -790,7 +842,7 @@ mod test { tree.swap_split_in_direction(Direction::Up); // | l2* | r0 | | // | l1 | l0 | - assert_eq!(tree.focus, l0); + assert_eq!(tree.focus, l2); assert_eq!(doc_id(&tree, l0), Some(doc_l2)); assert_eq!(doc_id(&tree, l1), Some(doc_l1)); assert_eq!(doc_id(&tree, l2), Some(doc_r0)); From d25bae844c2a13f9d91c34a9016c3c6fd5cc26dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 22 May 2022 00:00:05 +0900 Subject: [PATCH 20/28] Add Scheme support Skipped scm for now :/ it overlaps with tree-sitter-tsq --- languages.toml | 13 ++++ runtime/queries/scheme/highlights.scm | 100 ++++++++++++++++++++++++++ runtime/queries/scheme/injections.scm | 5 ++ 3 files changed, 118 insertions(+) create mode 100644 runtime/queries/scheme/highlights.scm create mode 100644 runtime/queries/scheme/injections.scm diff --git a/languages.toml b/languages.toml index 5deed357619c4..d3c4ef4353d6f 100644 --- a/languages.toml +++ b/languages.toml @@ -1366,3 +1366,16 @@ roots = [] [[grammar]] name = "sshclientconfig" source = { git = "https://github.com/metio/tree-sitter-ssh-client-config", rev = "769d7a01a2e5493b4bb5a51096c6bf4be130b024" } + +[[language]] +name = "scheme" +scope = "source.scheme" +injection-regex = "scheme" +file-types = ["ss", "rkt"] # "scm", +roots = [] +comment-token = ";" +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "scheme" +source = { git = "https://github.com/6cdh/tree-sitter-scheme", rev = "27fb77db05f890c2823b4bd751c6420378df146b" } diff --git a/runtime/queries/scheme/highlights.scm b/runtime/queries/scheme/highlights.scm new file mode 100644 index 0000000000000..3b7a42755b1b4 --- /dev/null +++ b/runtime/queries/scheme/highlights.scm @@ -0,0 +1,100 @@ +(number) @constant.numeric +(character) @constant.character +(boolean) @constant.builtin.boolean + +[(string) + (character)] @string + +(escape_sequence) @constant.character.escape + +[(comment) + (block_comment) + (directive)] @comment + +[(boolean) + (character)] @constant + +((symbol) @function.builtin + (#match? @function.builtin "^(eqv\\?|eq\\?|equal\\?)")) ; TODO + +; keywords + +((symbol) @keyword.conditional + (#match? @keyword.conditional "^(if|cond|case|when|unless)$")) + +((symbol) @keyword + (#match? @keyword + "^(define|lambda|begin|do|define-syntax|and|or|if|cond|case|when|unless|else|=>|let|let*|let-syntax|let-values|let*-values|letrec|letrec*|letrec-syntax|set!|syntax-rules|identifier-syntax|quote|unquote|quote-splicing|quasiquote|unquote-splicing|delay|assert|library|export|import|rename|only|except|prefix)$")) + +; special forms + +(list + "[" + (symbol)+ @variable + "]") + +(list + . + (symbol) @_f + . + (list + (symbol) @variable) + (#eq? @_f "lambda")) + +(list + . + (symbol) @_f + . + (list + (list + (symbol) @variable)) + (#match? @_f + "^(let|let\\*|let-syntax|let-values|let\\*-values|letrec|letrec\\*|letrec-syntax)$")) + +; operators + +(list + . + (symbol) @operator + (#match? @operator "^([+*/<>=-]|(<=)|(>=))$")) + +; quote + +(abbreviation + "'" (symbol)) @constant + +(list + . + (symbol) @_f + (#eq? @_f "quote")) @symbol + +; library + +(list + . + (symbol) @_lib + . + (symbol) @namespace + + (#eq? @_lib "library")) + +; procedure + +(list + . + (symbol) @function) + +;; variables + +((symbol) @variable.builtin + (#eq? @variable.builtin "...")) + +(symbol) @variable +((symbol) @variable.builtin + (#eq? @variable.builtin ".")) + +(symbol) @variable + + +["(" ")" "[" "]" "{" "}"] @punctuation.bracket + diff --git a/runtime/queries/scheme/injections.scm b/runtime/queries/scheme/injections.scm new file mode 100644 index 0000000000000..aebb54d935482 --- /dev/null +++ b/runtime/queries/scheme/injections.scm @@ -0,0 +1,5 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +((block_comment) @injection.content + (#set! injection.language "comment")) From 8df8ff27c2f95864a426a48839d065b237622bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Sun, 22 May 2022 00:20:45 +0900 Subject: [PATCH 21/28] cargo xtask docgen --- book/src/generated/lang-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 2e670807ce48a..df4d36b5c58dd 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -76,6 +76,7 @@ | ruby | ✓ | ✓ | ✓ | `solargraph` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` | | scala | ✓ | | ✓ | `metals` | +| scheme | ✓ | | | | | solidity | ✓ | | | `solc` | | sql | ✓ | | | | | sshclientconfig | ✓ | | | | From 5c864922d88a88898ab7525f8ebd33f8f5096c59 Mon Sep 17 00:00:00 2001 From: Leoi Hung Kin Date: Sun, 22 May 2022 09:24:32 +0800 Subject: [PATCH 22/28] Fix panic when reloading a shrunk file (#2506) * fix panic when reloading a shrunk file * linting * use scrolloff --- helix-term/src/commands/typed.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 74ab73bef8f55..5121eaa183a00 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -781,8 +781,11 @@ fn reload( _args: &[Cow], _event: PromptEvent, ) -> anyhow::Result<()> { + let scrolloff = cx.editor.config().scrolloff; let (view, doc) = current!(cx.editor); - doc.reload(view.id) + doc.reload(view.id).map(|_| { + view.ensure_cursor_in_view(doc, scrolloff); + }) } fn tree_sitter_scopes( From bfc4ff4dcfd9135924d90bb822f2e23ae9cb2420 Mon Sep 17 00:00:00 2001 From: kyrime Date: Sun, 22 May 2022 02:24:51 +0100 Subject: [PATCH 23/28] Add theme key for picker separator (#2523) Co-authored-by: ky <> --- book/src/themes.md | 69 +++++++++++++++++++------------------ helix-term/src/ui/picker.rs | 4 +-- theme.toml | 1 + 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 97955cb71a9ce..7562b2056bef6 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -205,39 +205,40 @@ These scopes are used for theming the editor interface. - `hover` - for hover popup ui -| Key | Notes | -| --- | --- | -| `ui.background` | | -| `ui.cursor` | | -| `ui.cursor.insert` | | -| `ui.cursor.select` | | -| `ui.cursor.match` | Matching bracket etc. | -| `ui.cursor.primary` | Cursor with primary selection | -| `ui.linenr` | Line numbers | -| `ui.linenr.selected` | Line number for the line the cursor is on | -| `ui.statusline` | Statusline | -| `ui.statusline.inactive` | Statusline (unfocused document) | -| `ui.popup` | Documentation popups (e.g space-k) | -| `ui.popup.info` | Prompt for multiple key options | -| `ui.window` | Border lines separating splits | -| `ui.help` | Description box for commands | -| `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.whitespace` | Visible white-space characters | -| `ui.menu` | Code and command completion menus | -| `ui.menu.selected` | Selected autocomplete item | -| `ui.selection` | For selections in the editing area | -| `ui.selection.primary` | | -| `warning` | Diagnostics warning (gutter) | -| `error` | Diagnostics error (gutter) | -| `info` | Diagnostics info (gutter) | -| `hint` | Diagnostics hint (gutter) | -| `diagnostic` | Diagnostics fallback style (editing area) | -| `diagnostic.hint` | Diagnostics hint (editing area) | -| `diagnostic.info` | Diagnostics info (editing area) | -| `diagnostic.warning` | Diagnostics warning (editing area) | -| `diagnostic.error` | Diagnostics error (editing area) | +| Key | Notes | +| --- | --- | +| `ui.background` | | +| `ui.background.separator` | Picker separator below input line | +| `ui.cursor` | | +| `ui.cursor.insert` | | +| `ui.cursor.select` | | +| `ui.cursor.match` | Matching bracket etc. | +| `ui.cursor.primary` | Cursor with primary selection | +| `ui.linenr` | Line numbers | +| `ui.linenr.selected` | Line number for the line the cursor is on | +| `ui.statusline` | Statusline | +| `ui.statusline.inactive` | Statusline (unfocused document) | +| `ui.popup` | Documentation popups (e.g space-k) | +| `ui.popup.info` | Prompt for multiple key options | +| `ui.window` | Border lines separating splits | +| `ui.help` | Description box for commands | +| `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.whitespace` | Visible white-space characters | +| `ui.menu` | Code and command completion menus | +| `ui.menu.selected` | Selected autocomplete item | +| `ui.selection` | For selections in the editing area | +| `ui.selection.primary` | | +| `warning` | Diagnostics warning (gutter) | +| `error` | Diagnostics error (gutter) | +| `info` | Diagnostics info (gutter) | +| `hint` | Diagnostics hint (gutter) | +| `diagnostic` | Diagnostics fallback style (editing area) | +| `diagnostic.hint` | Diagnostics hint (editing area) | +| `diagnostic.info` | Diagnostics info (editing area) | +| `diagnostic.warning` | Diagnostics warning (editing area) | +| `diagnostic.error` | Diagnostics error (editing area) | [rulers-config]: ./configuration.md#editor-section diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 49d91be61247d..181c2077da707 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -26,7 +26,7 @@ use crate::ui::{Prompt, PromptEvent}; use helix_core::{movement::Direction, Position}; use helix_view::{ editor::Action, - graphics::{Color, CursorKind, Margin, Modifier, Rect, Style}, + graphics::{CursorKind, Margin, Modifier, Rect}, Document, Editor, }; @@ -587,7 +587,7 @@ impl Component for Picker { self.prompt.render(area, surface, cx); // -- Separator - let sep_style = Style::default().fg(Color::Rgb(90, 89, 119)); + let sep_style = cx.editor.theme.get("ui.background.separator"); let borders = BorderType::line_symbols(BorderType::Plain); for x in inner.left()..inner.right() { if let Some(cell) = surface.get_mut(x, inner.y + 1) { diff --git a/theme.toml b/theme.toml index a0186e92aa726..ecd4ebe54720d 100644 --- a/theme.toml +++ b/theme.toml @@ -43,6 +43,7 @@ label = "honey" # concat (ERROR) @error.syntax and "MISSING ;" selectors for errors "ui.background" = { bg = "midnight" } +"ui.background.separator" = { fg = "comet" } "ui.linenr" = { fg = "comet" } "ui.linenr.selected" = { fg = "lilac" } "ui.statusline" = { fg = "lilac", bg = "revolver" } From 1837b5e4a61f0230b3cd382ed487fa09be7b2b68 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 14 May 2022 22:28:37 +0800 Subject: [PATCH 24/28] Refactor Block with Default and bitflags Specifying empty for bitflags is not recommended, it is now removed and added Default. For BorderType, it now defaults to plain. --- helix-tui/src/widgets/block.rs | 21 ++++++++------------- helix-tui/src/widgets/mod.rs | 11 +++++------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/helix-tui/src/widgets/block.rs b/helix-tui/src/widgets/block.rs index 26223c3ebbb19..3c05a2a3c8aa6 100644 --- a/helix-tui/src/widgets/block.rs +++ b/helix-tui/src/widgets/block.rs @@ -6,6 +6,7 @@ use crate::{ }; use helix_view::graphics::{Rect, Style}; +/// Border render type. Defaults to [`BorderType::Plain`]. #[derive(Debug, Clone, Copy, PartialEq)] pub enum BorderType { Plain, @@ -25,6 +26,12 @@ impl BorderType { } } +impl Default for BorderType { + fn default() -> BorderType { + BorderType::Plain + } +} + /// Base widget to be used with all upper level ones. It may be used to display a box border around /// the widget and/or add a title. /// @@ -40,7 +47,7 @@ impl BorderType { /// .border_type(BorderType::Rounded) /// .style(Style::default().bg(Color::Black)); /// ``` -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Default, Clone, PartialEq)] pub struct Block<'a> { /// Optional title place on the upper left of the block title: Option>, @@ -55,18 +62,6 @@ pub struct Block<'a> { style: Style, } -impl<'a> Default for Block<'a> { - fn default() -> Block<'a> { - Block { - title: None, - borders: Borders::NONE, - border_style: Default::default(), - border_type: BorderType::Plain, - style: Default::default(), - } - } -} - impl<'a> Block<'a> { pub fn title(mut self, title: T) -> Block<'a> where diff --git a/helix-tui/src/widgets/mod.rs b/helix-tui/src/widgets/mod.rs index e5608a79e8039..c0c3a994ab883 100644 --- a/helix-tui/src/widgets/mod.rs +++ b/helix-tui/src/widgets/mod.rs @@ -27,17 +27,16 @@ use helix_view::graphics::Rect; bitflags! { /// Bitflags that can be composed to set the visible borders essentially on the block widget. + #[derive(Default)] pub struct Borders: u32 { - /// Show no border (default) - const NONE = 0b0000_0001; /// Show the top border - const TOP = 0b0000_0010; + const TOP = 0b0000_0001; /// Show the right border - const RIGHT = 0b0000_0100; + const RIGHT = 0b0000_0010; /// Show the bottom border - const BOTTOM = 0b000_1000; + const BOTTOM = 0b000_0100; /// Show the left border - const LEFT = 0b0001_0000; + const LEFT = 0b0000_1000; /// Show all borders const ALL = Self::TOP.bits | Self::RIGHT.bits | Self::BOTTOM.bits | Self::LEFT.bits; } From 5bcb31a6dfb007b31b6ba38c5a1455727904ba27 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 22 May 2022 00:25:20 +0800 Subject: [PATCH 25/28] Make Borders u8 --- helix-tui/src/widgets/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-tui/src/widgets/mod.rs b/helix-tui/src/widgets/mod.rs index c0c3a994ab883..8946ef05643dc 100644 --- a/helix-tui/src/widgets/mod.rs +++ b/helix-tui/src/widgets/mod.rs @@ -28,7 +28,7 @@ use helix_view::graphics::Rect; bitflags! { /// Bitflags that can be composed to set the visible borders essentially on the block widget. #[derive(Default)] - pub struct Borders: u32 { + pub struct Borders: u8 { /// Show the top border const TOP = 0b0000_0001; /// Show the right border From 0c05447d49103e96fc21910d336bdc75ab96338d Mon Sep 17 00:00:00 2001 From: Daniel S Poulin Date: Sat, 21 May 2022 21:33:11 -0400 Subject: [PATCH 26/28] Add shrink equivalent of extend_to_line_bounds (#2450) * Add shrink equivalent of extend_to_line_bounds * Add a check for being past rope end in end position calc * Include the EOL character in calculations * Bind to `A-x` for now * Document new keybind --- book/src/keymap.md | 1 + helix-term/src/commands.rs | 42 ++++++++++++++++++++++++++++++++ helix-term/src/keymap/default.rs | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/book/src/keymap.md b/book/src/keymap.md index e56eeefc41ec6..25280d711974b 100644 --- a/book/src/keymap.md +++ b/book/src/keymap.md @@ -107,6 +107,7 @@ | `%` | Select entire file | `select_all` | | `x` | Select current line, if already selected, extend to next line | `extend_line` | | `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` | +| `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` | | `J` | Join lines inside selection | `join_selections` | | `K` | Keep selections matching the regex | `keep_selections` | | `Alt-K` | Remove selections matching the regex | `remove_selections` | diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 2839f495c5cbe..8024e3f034620 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -247,6 +247,7 @@ impl MappableCommand { extend_line, "Select current line, if already selected, extend to next line", extend_line_above, "Select current line, if already selected, extend to previous line", extend_to_line_bounds, "Extend selection to line bounds (line-wise selection)", + shrink_to_line_bounds, "Shrink selection to line bounds (line-wise selection)", delete_selection, "Delete selection", delete_selection_noyank, "Delete selection, without yanking", change_selection, "Change selection (delete and enter insert mode)", @@ -1942,6 +1943,47 @@ fn extend_to_line_bounds(cx: &mut Context) { ); } +fn shrink_to_line_bounds(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + + doc.set_selection( + view.id, + doc.selection(view.id).clone().transform(|range| { + let text = doc.text(); + + let (start_line, end_line) = range.line_range(text.slice(..)); + + // Do nothing if the selection is within one line to prevent + // conditional logic for the behavior of this command + if start_line == end_line { + return range; + } + + let mut start = text.line_to_char(start_line); + + // line_to_char gives us the start position of the line, so + // we need to get the start position of the next line. In + // the editor, this will correspond to the cursor being on + // the EOL whitespace charactor, which is what we want. + let mut end = text.line_to_char((end_line + 1).min(text.len_lines())); + + if start != range.from() { + start = text.line_to_char((start_line + 1).min(text.len_lines())); + } + + if end != range.to() { + end = text.line_to_char(end_line); + } + + if range.anchor <= range.head { + Range::new(start, end) + } else { + Range::new(end, start) + } + }), + ); +} + enum Operation { Delete, Change, diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index a887f4b3f9671..0f0b09dd5160f 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -87,7 +87,7 @@ pub fn default() -> HashMap { "%" => select_all, "x" => extend_line, "X" => extend_to_line_bounds, - // crop_to_whole_line + "A-x" => shrink_to_line_bounds, "m" => { "Match" "m" => match_brackets, From 0018545263b6a8416b0b8b943be236ea0abb7a67 Mon Sep 17 00:00:00 2001 From: Joel Date: Sun, 22 May 2022 15:10:01 +1000 Subject: [PATCH 27/28] fix: remove duplicated `ui.help` in themes the bottom value is used, so i've removed the top `ui.help` values from all themes also, the values are not merged, so: ```toml "ui.help" = { modifiers = ["reversed"] } "ui.help" = { fg = "white", bg = "black" } ``` is equal to: ```toml "ui.help" = { fg = "white", bg = "black" } ``` --- base16_theme.toml | 1 - runtime/themes/autumn.toml | 1 - runtime/themes/base16_default_dark.toml | 1 - runtime/themes/base16_default_light.toml | 1 - runtime/themes/rose_pine.toml | 1 - runtime/themes/rose_pine_dawn.toml | 1 - 6 files changed, 6 deletions(-) diff --git a/base16_theme.toml b/base16_theme.toml index 42e02a98a295b..5c0c253e18a93 100644 --- a/base16_theme.toml +++ b/base16_theme.toml @@ -10,7 +10,6 @@ "comment" = { fg = "gray" } "ui.statusline" = { fg = "black", bg = "white" } "ui.statusline.inactive" = { fg = "gray", bg = "white" } -"ui.help" = { modifiers = ["reversed"] } "ui.cursor" = { fg = "white", modifiers = ["reversed"] } "variable" = "red" "constant.numeric" = "yellow" diff --git a/runtime/themes/autumn.toml b/runtime/themes/autumn.toml index 032e773ac7501..afcc1a1135ca1 100644 --- a/runtime/themes/autumn.toml +++ b/runtime/themes/autumn.toml @@ -17,7 +17,6 @@ "ui.selection" = { bg = "my_gray3" } "comment" = { fg = "my_gray4", modifiers = ["italic"] } "ui.statusline" = { fg = "my_gray5", bg = "my_gray2" } -"ui.help" = { fg = "my_gray5", bg = "my_gray2" } "ui.cursor" = { fg = "my_gray5", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "my_white", modifiers = ["reversed"] } "ui.text" = "my_white" diff --git a/runtime/themes/base16_default_dark.toml b/runtime/themes/base16_default_dark.toml index 6074c450e4c20..7516e492ea125 100644 --- a/runtime/themes/base16_default_dark.toml +++ b/runtime/themes/base16_default_dark.toml @@ -11,7 +11,6 @@ "ui.selection" = { bg = "base02" } "comment" = { fg = "base03", modifiers = ["italic"] } "ui.statusline" = { fg = "base04", bg = "base01" } -"ui.help" = { fg = "base04", bg = "base01" } "ui.cursor" = { fg = "base04", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "base05", modifiers = ["reversed"] } "ui.text" = "base05" diff --git a/runtime/themes/base16_default_light.toml b/runtime/themes/base16_default_light.toml index 2273c19125cfd..3684745910474 100644 --- a/runtime/themes/base16_default_light.toml +++ b/runtime/themes/base16_default_light.toml @@ -10,7 +10,6 @@ "ui.selection" = { bg = "base02" } "comment" = { fg = "base03", modifiers = ["italic"] } "ui.statusline" = { fg = "base04", bg = "base01" } -"ui.help" = { fg = "base04", bg = "base01" } "ui.cursor" = { fg = "base04", modifiers = ["reversed"] } "ui.cursor.primary" = { fg = "base05", modifiers = ["reversed"] } "ui.virtual" = "base03" diff --git a/runtime/themes/rose_pine.toml b/runtime/themes/rose_pine.toml index d005ac8ad6d52..f05758801ae5a 100644 --- a/runtime/themes/rose_pine.toml +++ b/runtime/themes/rose_pine.toml @@ -10,7 +10,6 @@ "comment" = "subtle" "ui.statusline" = {fg = "foam", bg = "surface" } "ui.statusline.inactive" = { fg = "iris", bg = "surface" } -"ui.help" = { fg = "foam", bg = "surface" } "ui.cursor" = { fg = "rose", modifiers = ["reversed"] } "ui.text" = { fg = "text" } "ui.text.focus" = { fg = "foam", modifiers = ["bold"]} diff --git a/runtime/themes/rose_pine_dawn.toml b/runtime/themes/rose_pine_dawn.toml index 1a9ac7df2bdc6..5ad304e389497 100644 --- a/runtime/themes/rose_pine_dawn.toml +++ b/runtime/themes/rose_pine_dawn.toml @@ -10,7 +10,6 @@ "comment" = "subtle" "ui.statusline" = {fg = "foam", bg = "surface" } "ui.statusline.inactive" = { fg = "iris", bg = "surface" } -"ui.help" = { fg = "foam", bg = "surface" } "ui.cursor" = { fg = "rose", modifiers = ["reversed"] } "ui.text" = { fg = "text" } "ui.text.focus" = { fg = "foam", modifiers = ["bold"]} From 682bcc3a32d90bfb58872610af20f47ee4089c83 Mon Sep 17 00:00:00 2001 From: Joel Date: Sun, 22 May 2022 15:12:46 +1000 Subject: [PATCH 28/28] fix: missing quotes around `variable.other.member` --- theme.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme.toml b/theme.toml index ecd4ebe54720d..7a518b2fe4063 100644 --- a/theme.toml +++ b/theme.toml @@ -6,7 +6,7 @@ punctuation = "lavender" "punctuation.delimiter" = "lavender" operator = "lilac" special = "honey" -variable.other.member = "white" +"variable.other.member" = "white" variable = "lavender" # variable = "almond" # TODO: metavariables only # "variable.parameter" = { fg = "lavender", modifiers = ["underlined"] }