Merge remote-tracking branch 'origin/master' into debug
This commit is contained in:
commit
e315394631
20 changed files with 520 additions and 224 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -102,3 +102,7 @@
|
|||
path = helix-syntax/languages/tree-sitter-protobuf
|
||||
url = https://github.com/yusdacra/tree-sitter-protobuf.git
|
||||
shallow = true
|
||||
[submodule "helix-syntax/languages/tree-sitter-zig"]
|
||||
path = helix-syntax/languages/tree-sitter-zig
|
||||
url = https://github.com/maxxnino/tree-sitter-zig
|
||||
shallow = true
|
||||
|
|
|
@ -6,121 +6,121 @@
|
|||
|
||||
> NOTE: `f`, `F`, `t` and `T` are not confined to the current line.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `h`, `Left` | Move left |
|
||||
| `j`, `Down` | Move down |
|
||||
| `k`, `Up` | Move up |
|
||||
| `l`, `Right` | Move right |
|
||||
| `w` | Move next word start |
|
||||
| `b` | Move previous word start |
|
||||
| `e` | Move next word end |
|
||||
| `W` | Move next WORD start |
|
||||
| `B` | Move previous WORD start |
|
||||
| `E` | Move next WORD end |
|
||||
| `t` | Find 'till next char |
|
||||
| `f` | Find next char |
|
||||
| `T` | Find 'till previous char |
|
||||
| `F` | Find previous char |
|
||||
| `Home` | Move to the start of the line |
|
||||
| `End` | Move to the end of the line |
|
||||
| `PageUp` | Move page up |
|
||||
| `PageDown` | Move page down |
|
||||
| `Ctrl-u` | Move half page up |
|
||||
| `Ctrl-d` | Move half page down |
|
||||
| `Ctrl-i` | Jump forward on the jumplist TODO: conflicts tab |
|
||||
| `Ctrl-o` | Jump backward on the jumplist |
|
||||
| `v` | Enter [select (extend) mode](#select--extend-mode) |
|
||||
| `g` | Enter [goto mode](#goto-mode) |
|
||||
| `m` | Enter [match mode](#match-mode) |
|
||||
| `:` | Enter command mode |
|
||||
| `z` | Enter [view mode](#view-mode) |
|
||||
| `Ctrl-w` | Enter [window mode](#window-mode) (maybe will be remove for spc w w later) |
|
||||
| `Space` | Enter [space mode](#space-mode) |
|
||||
| `K` | Show documentation for the item under the cursor |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `h`, `Left` | Move left | `move_char_left` |
|
||||
| `j`, `Down` | Move down | `move_char_right` |
|
||||
| `k`, `Up` | Move up | `move_line_up` |
|
||||
| `l`, `Right` | Move right | `move_line_down` |
|
||||
| `w` | Move next word start | `move_next_word_start` |
|
||||
| `b` | Move previous word start | `move_prev_word_start` |
|
||||
| `e` | Move next word end | `move_next_word_end` |
|
||||
| `W` | Move next WORD start | `move_next_long_word_start` |
|
||||
| `B` | Move previous WORD start | `move_prev_long_word_start` |
|
||||
| `E` | Move next WORD end | `move_next_long_word_end` |
|
||||
| `t` | Find 'till next char | `find_till_char` |
|
||||
| `f` | Find next char | `find_next_char` |
|
||||
| `T` | Find 'till previous char | `till_prev_char` |
|
||||
| `F` | Find previous char | `find_prev_char` |
|
||||
| `Home` | Move to the start of the line | `goto_line_start` |
|
||||
| `End` | Move to the end of the line | `goto_line_end` |
|
||||
| `PageUp` | Move page up | `page_up` |
|
||||
| `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-i` | Jump forward on the jumplist TODO: conflicts tab | `jump_forward` |
|
||||
| `Ctrl-o` | Jump backward on the jumplist | `jump_backward` |
|
||||
| `v` | Enter [select (extend) mode](#select--extend-mode) | `select_mode` |
|
||||
| `g` | Enter [goto mode](#goto-mode) | N/A |
|
||||
| `m` | Enter [match mode](#match-mode) | N/A |
|
||||
| `:` | Enter command mode | `command_mode` |
|
||||
| `z` | Enter [view mode](#view-mode) | N/A |
|
||||
| `Ctrl-w` | Enter [window mode](#window-mode) (maybe will be remove for spc w w later) | N/A |
|
||||
| `Space` | Enter [space mode](#space-mode) | N/A |
|
||||
| `K` | Show documentation for the item under the cursor | `hover` |
|
||||
|
||||
### Changes
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `r` | Replace with a character |
|
||||
| `R` | Replace with yanked text |
|
||||
| `~` | Switch case of the selected text |
|
||||
| `` ` `` | Set the selected text to lower case |
|
||||
| `` Alt-` `` | Set the selected text to upper case |
|
||||
| `i` | Insert before selection |
|
||||
| `a` | Insert after selection (append) |
|
||||
| `I` | Insert at the start of the line |
|
||||
| `A` | Insert at the end of the line |
|
||||
| `o` | Open new line below selection |
|
||||
| `O` | Open new line above selection |
|
||||
| `u` | Undo change |
|
||||
| `U` | Redo change |
|
||||
| `y` | Yank selection |
|
||||
| `p` | Paste after selection |
|
||||
| `P` | Paste before selection |
|
||||
| `"` `<reg>` | Select a register to yank to or paste from |
|
||||
| `>` | Indent selection |
|
||||
| `<` | Unindent selection |
|
||||
| `=` | Format selection |
|
||||
| `d` | Delete selection |
|
||||
| `c` | Change selection (delete and enter insert mode) |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `r` | Replace with a character | `replace` |
|
||||
| `R` | Replace with yanked text | `replace_with_yanked` |
|
||||
| `~` | Switch case of the selected text | `switch_case` |
|
||||
| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` |
|
||||
| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` |
|
||||
| `i` | Insert before selection | `insert_mode` |
|
||||
| `a` | Insert after selection (append) | `append_mode` |
|
||||
| `I` | Insert at the start of the line | `prepend_to_line` |
|
||||
| `A` | Insert at the end of the line | `append_to_line` |
|
||||
| `o` | Open new line below selection | `open_below` |
|
||||
| `O` | Open new line above selection | `open_above` |
|
||||
| `u` | Undo change | `undo` |
|
||||
| `U` | Redo change | `redo` |
|
||||
| `y` | Yank selection | `yank` |
|
||||
| `p` | Paste after selection | `paste_after` |
|
||||
| `P` | Paste before selection | `paste_before` |
|
||||
| `"` `<reg>` | Select a register to yank to or paste from | `select_register` |
|
||||
| `>` | Indent selection | `indent` |
|
||||
| `<` | Unindent selection | `unindent` |
|
||||
| `=` | Format selection | `format_selections` |
|
||||
| `d` | Delete selection | `delete_selection` |
|
||||
| `c` | Change selection (delete and enter insert mode) | `change_selection` |
|
||||
|
||||
### Selection manipulation
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `s` | Select all regex matches inside selections |
|
||||
| `S` | Split selection into subselections on regex matches |
|
||||
| `Alt-s` | Split selection on newlines |
|
||||
| `;` | Collapse selection onto a single cursor |
|
||||
| `Alt-;` | Flip selection cursor and anchor |
|
||||
| `C` | Copy selection onto the next line |
|
||||
| `Alt-C` | Copy selection onto the previous line |
|
||||
| `(` | Rotate main selection forward |
|
||||
| `)` | Rotate main selection backward |
|
||||
| `Alt-(` | Rotate selection contents forward |
|
||||
| `Alt-)` | Rotate selection contents backward |
|
||||
| `%` | Select entire file |
|
||||
| `x` | Select current line, if already selected, extend to next line |
|
||||
| `X` | Extend selection to line bounds (line-wise selection) |
|
||||
| | Expand selection to parent syntax node TODO: pick a key |
|
||||
| `J` | Join lines inside selection |
|
||||
| `K` | Keep selections matching the regex TODO: overlapped by hover help |
|
||||
| `Space` | Keep only the primary selection TODO: overlapped by space mode |
|
||||
| `Ctrl-c` | Comment/uncomment the selections |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `s` | Select all regex matches inside selections | `select_regex` |
|
||||
| `S` | Split selection into subselections on regex matches | `split_selection` |
|
||||
| `Alt-s` | Split selection on newlines | `split_selection_on_newline` |
|
||||
| `;` | Collapse selection onto a single cursor | `collapse_selection` |
|
||||
| `Alt-;` | Flip selection cursor and anchor | `flip_selections` |
|
||||
| `C` | Copy selection onto the next line | `copy_selection_on_next_line` |
|
||||
| `Alt-C` | Copy selection onto the previous line | `copy_selection_on_prev_line` |
|
||||
| `(` | Rotate main selection forward | `rotate_selections_backward` |
|
||||
| `)` | Rotate main selection backward | `rotate_selections_forward` |
|
||||
| `Alt-(` | Rotate selection contents forward | `rotate_selection_contents_backward` |
|
||||
| `Alt-)` | Rotate selection contents backward | `rotate_selection_contents_forward` |
|
||||
| `%` | Select entire file | `select_all` |
|
||||
| `x` | Select current line, if already selected, extend to next line | `extend_line` |
|
||||
| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` |
|
||||
| | Expand selection to parent syntax node TODO: pick a key | `expand_selection` |
|
||||
| `J` | Join lines inside selection | `join_selections` |
|
||||
| `K` | Keep selections matching the regex TODO: overlapped by hover help | `keep_selections` |
|
||||
| `Space` | Keep only the primary selection TODO: overlapped by space mode | `keep_primary_selection` |
|
||||
| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` |
|
||||
|
||||
### Insert Mode
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `Escape` | Switch to normal mode |
|
||||
| `Ctrl-x` | Autocomplete |
|
||||
| `Ctrl-w` | Delete previous word |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `Escape` | Switch to normal mode | `normal_mode` |
|
||||
| `Ctrl-x` | Autocomplete | `completion` |
|
||||
| `Ctrl-w` | Delete previous word | `delete_word_backward` |
|
||||
|
||||
### Search
|
||||
|
||||
> TODO: The search implementation isn't ideal yet -- we don't support searching
|
||||
in reverse, or searching via smartcase.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `/` | Search for regex pattern |
|
||||
| `n` | Select next search match |
|
||||
| `N` | Add next search match to selection |
|
||||
| `*` | Use current selection as the search pattern |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `/` | Search for regex pattern | `search` |
|
||||
| `n` | Select next search match | `search_next` |
|
||||
| `N` | Add next search match to selection | `extend_search_next` |
|
||||
| `*` | Use current selection as the search pattern | `search_selection` |
|
||||
|
||||
### Diagnostics
|
||||
|
||||
> NOTE: `[` and `]` will likely contain more pair mappings in the style of
|
||||
> [vim-unimpaired](https://github.com/tpope/vim-unimpaired)
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `[d` | Go to previous diagnostic |
|
||||
| `]d` | Go to next diagnostic |
|
||||
| `[D` | Go to first diagnostic in document |
|
||||
| `]D` | Go to last diagnostic in document |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `[d` | Go to previous diagnostic | `goto_prev_diag` |
|
||||
| `]d` | Go to next diagnostic | `goto_next_diag` |
|
||||
| `[D` | Go to first diagnostic in document | `goto_first_diag` |
|
||||
| `]D` | Go to last diagnostic in document | `goto_last_diag` |
|
||||
|
||||
## Select / extend mode
|
||||
|
||||
|
@ -135,14 +135,14 @@ commands to extend the existing selection instead of replacing it.
|
|||
View mode is intended for scrolling and manipulating the view without changing
|
||||
the selection.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `z` , `c` | Vertically center the line |
|
||||
| `t` | Align the line to the top of the screen |
|
||||
| `b` | Align the line to the bottom of the screen |
|
||||
| `m` | Align the line to the middle of the screen (horizontally) |
|
||||
| `j` | Scroll the view downwards |
|
||||
| `k` | Scroll the view upwards |
|
||||
| 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` | Scroll the view downwards | `scroll_down` |
|
||||
| `k` | Scroll the view upwards | `scroll_up` |
|
||||
|
||||
## Goto mode
|
||||
|
||||
|
@ -150,21 +150,21 @@ Jumps to various locations.
|
|||
|
||||
> NOTE: Some of these features are only available with the LSP present.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `g` | Go to the start of the file |
|
||||
| `e` | Go to the end of the file |
|
||||
| `h` | Go to the start of the line |
|
||||
| `l` | Go to the end of the line |
|
||||
| `s` | Go to first non-whitespace character of the line |
|
||||
| `t` | Go to the top of the screen |
|
||||
| `m` | Go to the middle of the screen |
|
||||
| `b` | Go to the bottom of the screen |
|
||||
| `d` | Go to definition |
|
||||
| `y` | Go to type definition |
|
||||
| `r` | Go to references |
|
||||
| `i` | Go to implementation |
|
||||
| `a` | Go to the last accessed/alternate file |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `g` | Go to the start of the file | `goto_file_start` |
|
||||
| `e` | Go to the end of the file | `goto_last_line` |
|
||||
| `h` | Go to the start of the line | `goto_line_start` |
|
||||
| `l` | Go to the end of the line | `goto_line_end` |
|
||||
| `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` |
|
||||
| `t` | Go to the top of the screen | `goto_window_top` |
|
||||
| `m` | Go to the middle of the screen | `goto_window_middle` |
|
||||
| `b` | Go to the bottom of the screen | `goto_window_bottom` |
|
||||
| `d` | Go to definition | `goto_definition` |
|
||||
| `y` | Go to type definition | `goto_type_definition` |
|
||||
| `r` | Go to references | `goto_reference` |
|
||||
| `i` | Go to implementation | `goto_implementation` |
|
||||
| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
|
||||
|
||||
## Match mode
|
||||
|
||||
|
@ -172,14 +172,14 @@ Enter this mode using `m` from normal mode. See the relavant section
|
|||
in [Usage](./usage.md) for an explanation about [surround](./usage.md#surround)
|
||||
and [textobject](./usage.md#textobject) usage.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `m` | Goto matching bracket |
|
||||
| `s` `<char>` | Surround current selection with `<char>` |
|
||||
| `r` `<from><to>` | Replace surround character `<from>` with `<to>` |
|
||||
| `d` `<char>` | Delete surround character `<char>` |
|
||||
| `a` `<object>` | Select around textobject |
|
||||
| `i` `<object>` | Select inside textobject |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `m` | Goto matching bracket | `match_brackets` |
|
||||
| `s` `<char>` | Surround current selection with `<char>` | `surround_add` |
|
||||
| `r` `<from><to>` | Replace surround character `<from>` with `<to>` | `surround_replace` |
|
||||
| `d` `<char>` | Delete surround character `<char>` | `surround_delete` |
|
||||
| `a` `<object>` | Select around textobject | `select_textobject_around` |
|
||||
| `i` `<object>` | Select inside textobject | `select_textobject_inner` |
|
||||
|
||||
## Object mode
|
||||
|
||||
|
@ -189,35 +189,35 @@ TODO: Mappings for selecting syntax nodes (a superset of `[`).
|
|||
|
||||
This layer is similar to vim keybindings as kakoune does not support window.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ------------- |
|
||||
| `w`, `Ctrl-w` | Switch to next window |
|
||||
| `v`, `Ctrl-v` | Vertical right split |
|
||||
| `h`, `Ctrl-h` | Horizontal bottom split |
|
||||
| `q`, `Ctrl-q` | Close current window |
|
||||
| Key | Description | Command |
|
||||
| ----- | ------------- | ------- |
|
||||
| `w`, `Ctrl-w` | Switch to next window | `rotate_view` |
|
||||
| `v`, `Ctrl-v` | Vertical right split | `vsplit` |
|
||||
| `h`, `Ctrl-h` | Horizontal bottom split | `hsplit` |
|
||||
| `q`, `Ctrl-q` | Close current window | `wclose` |
|
||||
|
||||
## Space mode
|
||||
|
||||
This layer is a kludge of mappings I had under leader key in neovim.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ----------- |
|
||||
| `f` | Open file picker |
|
||||
| `b` | Open buffer picker |
|
||||
| `s` | Open symbol picker (current document) |
|
||||
| `a` | Apply code action |
|
||||
| `'` | Open last fuzzy picker |
|
||||
| `w` | Enter [window mode](#window-mode) |
|
||||
| `space` | Keep primary selection TODO: it's here because space mode replaced it |
|
||||
| `p` | Paste system clipboard after selections |
|
||||
| `P` | Paste system clipboard before selections |
|
||||
| `y` | Join and yank selections to clipboard |
|
||||
| `Y` | Yank main selection to clipboard |
|
||||
| `R` | Replace selections by clipboard contents |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `f` | Open file picker | `file_picker` |
|
||||
| `b` | Open buffer picker | `buffer_picker` |
|
||||
| `s` | Open symbol picker (current document) | `symbol_picker` |
|
||||
| `a` | Apply code action | `code_action` |
|
||||
| `'` | Open last fuzzy picker | `last_picker` |
|
||||
| `w` | Enter [window mode](#window-mode) | N/A |
|
||||
| `space` | Keep primary selection TODO: it's here because space mode replaced it | `keep_primary_selection` |
|
||||
| `p` | Paste system clipboard after selections | `paste_clipboard_after` |
|
||||
| `P` | Paste system clipboard before selections | `paste_clipboard_before` |
|
||||
| `y` | Join and yank selections to clipboard | `yank_joined_to_clipboard` |
|
||||
| `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` |
|
||||
| `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` |
|
||||
|
||||
# Picker
|
||||
|
||||
Keys to use within picker.
|
||||
Keys to use within picker. Remapping currently not supported.
|
||||
|
||||
| Key | Description |
|
||||
| ----- | ------------- |
|
||||
|
|
|
@ -91,6 +91,9 @@ Possible keys:
|
|||
| `ui.help` | |
|
||||
| `ui.text` | |
|
||||
| `ui.text.focus` | |
|
||||
| `ui.info` | |
|
||||
| `ui.info.text` | |
|
||||
| `ui.menu` | |
|
||||
| `ui.menu.selected` | |
|
||||
| `ui.selection` | For selections in the editing area |
|
||||
| `ui.selection.primary` | |
|
||||
|
|
|
@ -98,6 +98,89 @@ pub fn cache_dir() -> std::path::PathBuf {
|
|||
path
|
||||
}
|
||||
|
||||
// right overrides left
|
||||
pub fn merge_toml_values(left: toml::Value, right: toml::Value) -> toml::Value {
|
||||
use toml::Value;
|
||||
|
||||
fn get_name(v: &Value) -> Option<&str> {
|
||||
v.get("name").and_then(Value::as_str)
|
||||
}
|
||||
|
||||
match (left, right) {
|
||||
(Value::Array(mut left_items), Value::Array(right_items)) => {
|
||||
left_items.reserve(right_items.len());
|
||||
for rvalue in right_items {
|
||||
let lvalue = get_name(&rvalue)
|
||||
.and_then(|rname| left_items.iter().position(|v| get_name(v) == Some(rname)))
|
||||
.map(|lpos| left_items.remove(lpos));
|
||||
let mvalue = match lvalue {
|
||||
Some(lvalue) => merge_toml_values(lvalue, rvalue),
|
||||
None => rvalue,
|
||||
};
|
||||
left_items.push(mvalue);
|
||||
}
|
||||
Value::Array(left_items)
|
||||
}
|
||||
(Value::Table(mut left_map), Value::Table(right_map)) => {
|
||||
for (rname, rvalue) in right_map {
|
||||
match left_map.remove(&rname) {
|
||||
Some(lvalue) => {
|
||||
let merged_value = merge_toml_values(lvalue, rvalue);
|
||||
left_map.insert(rname, merged_value);
|
||||
}
|
||||
None => {
|
||||
left_map.insert(rname, rvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Table(left_map)
|
||||
}
|
||||
// Catch everything else we didn't handle, and use the right value
|
||||
(_, value) => value,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod merge_toml_tests {
|
||||
use super::merge_toml_values;
|
||||
|
||||
#[test]
|
||||
fn language_tomls() {
|
||||
use toml::Value;
|
||||
|
||||
const USER: &str = "
|
||||
[[language]]
|
||||
name = \"nix\"
|
||||
test = \"bbb\"
|
||||
indent = { tab-width = 4, unit = \" \", test = \"aaa\" }
|
||||
";
|
||||
|
||||
let base: Value = toml::from_slice(include_bytes!("../../languages.toml"))
|
||||
.expect("Couldn't parse built-in langauges config");
|
||||
let user: Value = toml::from_str(USER).unwrap();
|
||||
|
||||
let merged = merge_toml_values(base, user);
|
||||
let languages = merged.get("language").unwrap().as_array().unwrap();
|
||||
let nix = languages
|
||||
.iter()
|
||||
.find(|v| v.get("name").unwrap().as_str().unwrap() == "nix")
|
||||
.unwrap();
|
||||
let nix_indent = nix.get("indent").unwrap();
|
||||
|
||||
// We changed tab-width and unit in indent so check them if they are the new values
|
||||
assert_eq!(
|
||||
nix_indent.get("tab-width").unwrap().as_integer().unwrap(),
|
||||
4
|
||||
);
|
||||
assert_eq!(nix_indent.get("unit").unwrap().as_str().unwrap(), " ");
|
||||
// We added a new keys, so check them
|
||||
assert_eq!(nix.get("test").unwrap().as_str().unwrap(), "bbb");
|
||||
assert_eq!(nix_indent.get("test").unwrap().as_str().unwrap(), "aaa");
|
||||
// We didn't change comment-token so it should be same
|
||||
assert_eq!(nix.get("comment-token").unwrap().as_str().unwrap(), "#");
|
||||
}
|
||||
}
|
||||
|
||||
pub use etcetera::home_dir;
|
||||
|
||||
use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{Rope, Selection};
|
||||
|
||||
/// A state represents the current editor state of a single buffer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct State {
|
||||
pub doc: Rope,
|
||||
|
@ -15,27 +14,4 @@ impl State {
|
|||
selection: Selection::point(0),
|
||||
}
|
||||
}
|
||||
|
||||
// update/transact:
|
||||
// update(desc) => transaction ? transaction.doc() for applied doc
|
||||
// transaction.apply(doc)
|
||||
// doc.transact(fn -> ... end)
|
||||
|
||||
// replaceSelection (transaction that replaces selection)
|
||||
// changeByRange
|
||||
// changes
|
||||
// slice
|
||||
//
|
||||
// getters:
|
||||
// tabSize
|
||||
// indentUnit
|
||||
// languageDataAt()
|
||||
//
|
||||
// config:
|
||||
// indentation
|
||||
// tabSize
|
||||
// lineUnit
|
||||
// syntax
|
||||
// foldable
|
||||
// changeFilter/transactionFilter
|
||||
}
|
||||
|
|
|
@ -1831,15 +1831,14 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_input_edits() {
|
||||
use crate::State;
|
||||
use tree_sitter::InputEdit;
|
||||
|
||||
let state = State::new("hello world!\ntest 123".into());
|
||||
let doc = Rope::from("hello world!\ntest 123");
|
||||
let transaction = Transaction::change(
|
||||
&state.doc,
|
||||
&doc,
|
||||
vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
|
||||
);
|
||||
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
||||
let edits = LanguageLayer::generate_edits(doc.slice(..), transaction.changes());
|
||||
// transaction.apply(&mut state);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -1865,13 +1864,13 @@ mod test {
|
|||
);
|
||||
|
||||
// Testing with the official example from tree-sitter
|
||||
let mut state = State::new("fn test() {}".into());
|
||||
let mut doc = Rope::from("fn test() {}");
|
||||
let transaction =
|
||||
Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
|
||||
let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
|
||||
transaction.apply(&mut state.doc);
|
||||
Transaction::change(&doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
|
||||
let edits = LanguageLayer::generate_edits(doc.slice(..), transaction.changes());
|
||||
transaction.apply(&mut doc);
|
||||
|
||||
assert_eq!(state.doc, "fn test(a: u32) {}");
|
||||
assert_eq!(doc, "fn test(a: u32) {}");
|
||||
assert_eq!(
|
||||
edits,
|
||||
&[InputEdit {
|
||||
|
|
|
@ -125,7 +125,7 @@ impl ChangeSet {
|
|||
/// In other words, If `this` goes `docA` → `docB` and `other` represents `docB` → `docC`, the
|
||||
/// returned value will represent the change `docA` → `docC`.
|
||||
pub fn compose(self, other: Self) -> Self {
|
||||
debug_assert!(self.len_after == other.len);
|
||||
assert!(self.len_after == other.len);
|
||||
|
||||
// composing fails in weird ways if one of the sets is empty
|
||||
// a: [] len: 0 len_after: 1 | b: [Insert(Tendril<UTF8>(inline: "\n")), Retain(1)] len 1
|
||||
|
@ -689,21 +689,21 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn transaction_change() {
|
||||
let mut state = State::new("hello world!\ntest 123".into());
|
||||
let mut doc = Rope::from("hello world!\ntest 123");
|
||||
let transaction = Transaction::change(
|
||||
&state.doc,
|
||||
&doc,
|
||||
// (1, 1, None) is a useless 0-width delete
|
||||
vec![(1, 1, None), (6, 11, Some("void".into())), (12, 17, None)].into_iter(),
|
||||
);
|
||||
transaction.apply(&mut state.doc);
|
||||
assert_eq!(state.doc, Rope::from_str("hello void! 123"));
|
||||
transaction.apply(&mut doc);
|
||||
assert_eq!(doc, Rope::from_str("hello void! 123"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_iter() {
|
||||
let state = State::new("hello world!\ntest 123".into());
|
||||
let doc = Rope::from("hello world!\ntest 123");
|
||||
let changes = vec![(6, 11, Some("void".into())), (12, 17, None)];
|
||||
let transaction = Transaction::change(&state.doc, changes.clone().into_iter());
|
||||
let transaction = Transaction::change(&doc, changes.clone().into_iter());
|
||||
assert_eq!(transaction.changes_iter().collect::<Vec<_>>(), changes);
|
||||
}
|
||||
|
||||
|
|
1
helix-syntax/languages/tree-sitter-zig
Submodule
1
helix-syntax/languages/tree-sitter-zig
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 049162bea8a44e1a4acd01b06e1c8672d9231a86
|
|
@ -1,4 +1,4 @@
|
|||
use helix_core::{syntax, Range, Selection};
|
||||
use helix_core::{merge_toml_values, syntax, Range, Selection};
|
||||
use helix_dap::Payload;
|
||||
use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
|
||||
use helix_view::{theme, Editor};
|
||||
|
@ -66,11 +66,16 @@ impl Application {
|
|||
let theme_loader =
|
||||
std::sync::Arc::new(theme::Loader::new(&conf_dir, &helix_core::runtime_dir()));
|
||||
|
||||
// load $HOME/.config/helix/languages.toml, fallback to default config
|
||||
let lang_conf = std::fs::read(conf_dir.join("languages.toml"));
|
||||
let lang_conf = lang_conf
|
||||
.as_deref()
|
||||
.unwrap_or(include_bytes!("../../languages.toml"));
|
||||
// load default and user config, and merge both
|
||||
let def_lang_conf: toml::Value = toml::from_slice(include_bytes!("../../languages.toml"))
|
||||
.expect("Could not parse built-in languages.toml, something must be very wrong");
|
||||
let user_lang_conf: Option<toml::Value> = std::fs::read(conf_dir.join("languages.toml"))
|
||||
.ok()
|
||||
.map(|raw| toml::from_slice(&raw).expect("Could not parse user languages.toml"));
|
||||
let lang_conf = match user_lang_conf {
|
||||
Some(value) => merge_toml_values(def_lang_conf, value),
|
||||
None => def_lang_conf,
|
||||
};
|
||||
|
||||
let theme = if let Some(theme) = &config.theme {
|
||||
match theme_loader.load(theme) {
|
||||
|
@ -84,7 +89,9 @@ impl Application {
|
|||
theme_loader.default()
|
||||
};
|
||||
|
||||
let syn_loader_conf = toml::from_slice(lang_conf).expect("Could not parse languages.toml");
|
||||
let syn_loader_conf: helix_core::syntax::Configuration = lang_conf
|
||||
.try_into()
|
||||
.expect("Could not parse merged (built-in + user) languages.toml");
|
||||
let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf));
|
||||
|
||||
let mut editor = Editor::new(
|
||||
|
|
|
@ -2369,7 +2369,7 @@ mod cmd {
|
|||
},
|
||||
TypableCommand {
|
||||
name: "vsplit",
|
||||
alias: Some("vsp"),
|
||||
alias: Some("vs"),
|
||||
doc: "Open the file in a vertical split.",
|
||||
fun: vsplit,
|
||||
completer: Some(completers::filename),
|
||||
|
|
|
@ -541,6 +541,8 @@ impl Default for Keymaps {
|
|||
"home" => goto_line_start,
|
||||
"end" => goto_line_end,
|
||||
"esc" => exit_select_mode,
|
||||
|
||||
"v" => normal_mode,
|
||||
}));
|
||||
let insert = keymap!({ "Insert mode"
|
||||
"esc" => normal_mode,
|
||||
|
|
|
@ -508,7 +508,13 @@ impl EditorView {
|
|||
} else {
|
||||
let line = match config.line_number {
|
||||
LineNumber::Absolute => line + 1,
|
||||
LineNumber::Relative => abs_diff(current_line, line),
|
||||
LineNumber::Relative => {
|
||||
if current_line == line {
|
||||
line + 1
|
||||
} else {
|
||||
abs_diff(current_line, line)
|
||||
}
|
||||
}
|
||||
};
|
||||
format!("{:>5}", line)
|
||||
};
|
||||
|
|
|
@ -259,8 +259,11 @@ impl<T: Item + 'static> Component for Menu<T> {
|
|||
// TODO: required size should re-trigger when we filter items so we can draw a smaller menu
|
||||
|
||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
||||
let style = cx.editor.theme.get("ui.text");
|
||||
let selected = cx.editor.theme.get("ui.menu.selected");
|
||||
let theme = &cx.editor.theme;
|
||||
let style = theme
|
||||
.try_get("ui.menu")
|
||||
.unwrap_or_else(|| theme.get("ui.text"));
|
||||
let selected = theme.get("ui.menu.selected");
|
||||
|
||||
let scroll = self.scroll;
|
||||
|
||||
|
|
|
@ -228,7 +228,8 @@ pub mod completers {
|
|||
|
||||
let end = input.len()..;
|
||||
|
||||
let mut files: Vec<_> = WalkBuilder::new(dir.clone())
|
||||
let mut files: Vec<_> = WalkBuilder::new(&dir)
|
||||
.hidden(false)
|
||||
.max_depth(Some(1))
|
||||
.build()
|
||||
.filter_map(|file| {
|
||||
|
|
|
@ -400,18 +400,6 @@ impl Component for Prompt {
|
|||
})));
|
||||
|
||||
match event {
|
||||
// char or shift char
|
||||
KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
}
|
||||
| KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers: KeyModifiers::SHIFT,
|
||||
} => {
|
||||
self.insert_char(c);
|
||||
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
|
||||
}
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('c'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
|
@ -539,6 +527,14 @@ impl Component for Prompt {
|
|||
code: KeyCode::Char('q'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => self.exit_selection(),
|
||||
// any char event that's not combined with control or mapped to any other combo
|
||||
KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers,
|
||||
} if !modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
self.insert_char(c);
|
||||
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ pub struct Document {
|
|||
language_server: Option<Arc<helix_lsp::Client>>,
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
use std::{fmt, mem};
|
||||
impl fmt::Debug for Document {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Document")
|
||||
|
@ -301,20 +301,13 @@ pub async fn to_writer<'a, W: tokio::io::AsyncWriteExt + Unpin + ?Sized>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Like std::mem::replace() except it allows the replacement value to be mapped from the
|
||||
/// original value.
|
||||
fn take_with<T, F>(mut_ref: &mut T, closure: F)
|
||||
fn take_with<T, F>(mut_ref: &mut T, f: F)
|
||||
where
|
||||
T: Default,
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
use std::{panic, ptr};
|
||||
|
||||
unsafe {
|
||||
let old_t = ptr::read(mut_ref);
|
||||
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| closure(old_t)))
|
||||
.unwrap_or_else(|_| ::std::process::abort());
|
||||
ptr::write(mut_ref, new_t);
|
||||
}
|
||||
let t = mem::take(mut_ref);
|
||||
let _ = mem::replace(mut_ref, f(t));
|
||||
}
|
||||
|
||||
use helix_lsp::lsp;
|
||||
|
|
|
@ -15,10 +15,10 @@ pub struct KeyEvent {
|
|||
}
|
||||
|
||||
impl KeyEvent {
|
||||
/// If a character was pressed (without modifiers), return it.
|
||||
/// If a character was pressed, return it.
|
||||
pub fn char(&self) -> Option<char> {
|
||||
match self.code {
|
||||
KeyCode::Char(ch) if self.modifiers.is_empty() => Some(ch),
|
||||
KeyCode::Char(ch) => Some(ch),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,3 +311,15 @@ indent = { tab-width = 4, unit = " " }
|
|||
# comment-token = "--"
|
||||
#
|
||||
# indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "zig"
|
||||
scope = "source.zig"
|
||||
injection-regex = "zig"
|
||||
file-types = ["zig"]
|
||||
roots = ["build.zig"]
|
||||
auto-format = true
|
||||
comment-token = "//"
|
||||
|
||||
language-server = { command = "zls" }
|
||||
indent = { tab-width = 4, unit = " " }
|
||||
|
|
198
runtime/queries/zig/highlights.scm
Normal file
198
runtime/queries/zig/highlights.scm
Normal file
|
@ -0,0 +1,198 @@
|
|||
[
|
||||
(container_doc_comment)
|
||||
(doc_comment)
|
||||
(line_comment)
|
||||
] @comment
|
||||
|
||||
; field in top level decl, and in struct, union...
|
||||
(ContainerField
|
||||
(IDENTIFIER) @property
|
||||
(SuffixExpr (IDENTIFIER) @type)?
|
||||
)
|
||||
|
||||
; error.OutOfMemory;
|
||||
(SuffixExpr
|
||||
"error"
|
||||
"."
|
||||
(IDENTIFIER) @constant
|
||||
)
|
||||
|
||||
; var x: IDENTIFIER
|
||||
type: (SuffixExpr (IDENTIFIER) @type)
|
||||
|
||||
; IDENTIFIER{}
|
||||
constructor: (SuffixExpr (IDENTIFIER) @constructor)
|
||||
|
||||
; fields
|
||||
(FieldInit (IDENTIFIER) @property)
|
||||
|
||||
; foo.bar.baz.function() calls
|
||||
(
|
||||
(SuffixOp
|
||||
(IDENTIFIER) @function
|
||||
)
|
||||
.
|
||||
(FnCallArguments)
|
||||
)
|
||||
|
||||
; function() calls
|
||||
(
|
||||
(
|
||||
(IDENTIFIER) @function
|
||||
)
|
||||
.
|
||||
(FnCallArguments)
|
||||
)
|
||||
|
||||
; functionn decl
|
||||
(FnProto
|
||||
(IDENTIFIER) @function
|
||||
(SuffixExpr (IDENTIFIER) @type)?
|
||||
("!")? @function.macro
|
||||
)
|
||||
|
||||
; function parameters and types
|
||||
(ParamDecl
|
||||
(IDENTIFIER) @variable.parameter
|
||||
":"
|
||||
[
|
||||
(ParamType (SuffixExpr (IDENTIFIER) @type))
|
||||
(ParamType)
|
||||
]
|
||||
)
|
||||
|
||||
; switch
|
||||
(SwitchItem
|
||||
(SuffixExpr
|
||||
"."
|
||||
.
|
||||
(IDENTIFIER) @constant
|
||||
)
|
||||
)
|
||||
|
||||
(INTEGER) @number
|
||||
|
||||
(FLOAT) @number
|
||||
|
||||
[
|
||||
(STRINGLITERAL)
|
||||
(STRINGLITERALSINGLE)
|
||||
] @string
|
||||
|
||||
(CHAR_LITERAL) @string
|
||||
|
||||
[
|
||||
"allowzero"
|
||||
"volatile"
|
||||
"anytype"
|
||||
"anyframe"
|
||||
(BuildinTypeExpr)
|
||||
] @type.builtin
|
||||
|
||||
(BreakLabel (IDENTIFIER) @label)
|
||||
(BlockLabel (IDENTIFIER) @label)
|
||||
|
||||
[
|
||||
"true"
|
||||
"false"
|
||||
"undefined"
|
||||
"unreachable"
|
||||
"null"
|
||||
] @constant.builtin
|
||||
|
||||
[
|
||||
"else"
|
||||
"if"
|
||||
"switch"
|
||||
"for"
|
||||
"while"
|
||||
"return"
|
||||
"break"
|
||||
"continue"
|
||||
"defer"
|
||||
"errdefer"
|
||||
"async"
|
||||
"nosuspend"
|
||||
"await"
|
||||
"suspend"
|
||||
"resume"
|
||||
"try"
|
||||
"catch"
|
||||
] @keyword.control
|
||||
|
||||
[
|
||||
"struct"
|
||||
"enum"
|
||||
"union"
|
||||
"error"
|
||||
"packed"
|
||||
"opaque"
|
||||
"test"
|
||||
"usingnamespace"
|
||||
"export"
|
||||
"extern"
|
||||
"const"
|
||||
"var"
|
||||
"comptime"
|
||||
"threadlocal"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
"pub"
|
||||
"fn"
|
||||
] @keyword.function
|
||||
|
||||
; PrecProc
|
||||
[
|
||||
"inline"
|
||||
"noinline"
|
||||
"asm"
|
||||
"callconv"
|
||||
"noalias"
|
||||
] @attribute
|
||||
|
||||
[
|
||||
(BUILTINIDENTIFIER)
|
||||
"linksection"
|
||||
"align"
|
||||
] @function.builtin
|
||||
|
||||
[
|
||||
(CompareOp)
|
||||
(BitwiseOp)
|
||||
(BitShiftOp)
|
||||
(AdditionOp)
|
||||
(MultiplyOp)
|
||||
(PrefixOp)
|
||||
"or"
|
||||
"and"
|
||||
"orelse"
|
||||
"*"
|
||||
"**"
|
||||
"->"
|
||||
"=>"
|
||||
".?"
|
||||
".*"
|
||||
"="
|
||||
] @operator
|
||||
|
||||
[
|
||||
";"
|
||||
"."
|
||||
","
|
||||
":"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
".."
|
||||
"..."
|
||||
"["
|
||||
"]"
|
||||
"("
|
||||
")"
|
||||
"{"
|
||||
"}"
|
||||
(Payload "|")
|
||||
(PtrPayload "|")
|
||||
(PtrIndexPayload "|")
|
||||
] @punctuation
|
12
runtime/queries/zig/indents.toml
Normal file
12
runtime/queries/zig/indents.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
indent = [
|
||||
"block",
|
||||
"match_block",
|
||||
"arguments",
|
||||
"parameters"
|
||||
]
|
||||
|
||||
outdent = [
|
||||
"}",
|
||||
"]",
|
||||
")"
|
||||
]
|
Loading…
Add table
Reference in a new issue