Merge remote-tracking branch 'origin/master' into debug

This commit is contained in:
Dmitry Sharshakov 2021-08-28 14:59:26 +03:00
commit e315394631
No known key found for this signature in database
GPG Key ID: 471FD32E15FD8473
20 changed files with 520 additions and 224 deletions

4
.gitmodules vendored
View File

@ -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

View File

@ -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 |
| ----- | ------------- |

View File

@ -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` | |

View File

@ -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};

View File

@ -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
}

View File

@ -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 {

View File

@ -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);
}

@ -0,0 +1 @@
Subproject commit 049162bea8a44e1a4acd01b06e1c8672d9231a86

View File

@ -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(

View File

@ -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),

View File

@ -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,

View File

@ -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)
};

View File

@ -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;

View File

@ -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| {

View 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);
}
_ => (),
};

View File

@ -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;

View File

@ -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,
}
}

View File

@ -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 = " " }

View 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

View File

@ -0,0 +1,12 @@
indent = [
"block",
"match_block",
"arguments",
"parameters"
]
outdent = [
"}",
"]",
")"
]