Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why not a Helix Mode, to go along with Vi and Emacs? #639

Open
luccahuguet opened this issue Sep 26, 2023 · 5 comments
Open

Why not a Helix Mode, to go along with Vi and Emacs? #639

luccahuguet opened this issue Sep 26, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@luccahuguet
Copy link

I think a helix-mode would go a long way into making the reedline experience more complete, now targeting the three major modal editors.

Helix's philosophy is a bit like this (a small excerpt from their vision page on github):

Selection -> Action, not Verb -> Object. Interaction models aren't linguistics, and "selection first" lets you see what you're doing (among other benefits).
We aren't playing code golf. It's more important for the keymap to be consistent and easy to memorize than it is to save a key stroke or two when editing.

helix also has multi-cursors but we could add it later.

Also important to note that helix is heavily inspired by kakoune, so this would be satisfying for that group of users too.

I added a comment in the keybinding discussion: #69 (comment)

and if needed a could open an issue in nushell's main repo.

@luccahuguet luccahuguet added the enhancement New feature or request label Sep 26, 2023
@fdncred
Copy link
Collaborator

fdncred commented Sep 26, 2023

Helix mode would be fun. All it takes is someone to come in and contribute it.

@luccahuguet
Copy link
Author

@fdncred Terrific!

I hope someone picks this up

@crabdancing
Copy link

I just wanted to say I would LOVE a Helix editing mode! I actually already find myself unconsciously trying to use Helix keybindings to edit the prompt line in Nushell when I'm tired. :P

@luccahuguet
Copy link
Author

luccahuguet commented Jan 25, 2024

@sholderbach added some helpful comments in the draft by @savente93 on what is probably needed before a PR concerning this issue can be done: #642 (comment)

Just putting this here to make it easier to track. It's been a while, maybe there's been progress in some of the items..

The conditions are as follows:

I think what I would gather as a reasonable point where it makes sense to go ahead with helix mode without impacting the effort to getting the rest of the modes nice would be:

  • We have maybe reduced the number of EditCommand implementations that do essentially the same in slight variations: Move/Cut/Delete:
    EditCommand::MoveToStart => self.line_buffer.move_to_start(),
    EditCommand::MoveToLineStart => self.line_buffer.move_to_line_start(),
    EditCommand::MoveToEnd => self.line_buffer.move_to_end(),
    EditCommand::MoveToLineEnd => self.line_buffer.move_to_line_end(),
    EditCommand::MoveToPosition(pos) => self.line_buffer.set_insertion_point(*pos),
    EditCommand::MoveLeft => self.line_buffer.move_left(),
    EditCommand::MoveRight => self.line_buffer.move_right(),
    EditCommand::MoveWordLeft => self.line_buffer.move_word_left(),
    EditCommand::MoveBigWordLeft => self.line_buffer.move_big_word_left(),
    EditCommand::MoveWordRight => self.line_buffer.move_word_right(),
    EditCommand::MoveWordRightStart => self.line_buffer.move_word_right_start(),
    EditCommand::MoveBigWordRightStart => self.line_buffer.move_big_word_right_start(),
    EditCommand::MoveWordRightEnd => self.line_buffer.move_word_right_end(),
    EditCommand::MoveBigWordRightEnd => self.line_buffer.move_big_word_right_end(),
    EditCommand::InsertChar(c) => self.line_buffer.insert_char(*c),
    EditCommand::Complete => {}
    EditCommand::InsertString(str) => self.line_buffer.insert_str(str),
    EditCommand::InsertNewline => self.line_buffer.insert_newline(),
    EditCommand::ReplaceChar(chr) => self.replace_char(*chr),
    EditCommand::ReplaceChars(n_chars, str) => self.replace_chars(*n_chars, str),
    EditCommand::Backspace => self.line_buffer.delete_left_grapheme(),
    EditCommand::Delete => self.line_buffer.delete_right_grapheme(),
    EditCommand::CutChar => self.cut_char(),
    EditCommand::BackspaceWord => self.line_buffer.delete_word_left(),
    EditCommand::DeleteWord => self.line_buffer.delete_word_right(),
    EditCommand::Clear => self.line_buffer.clear(),
    EditCommand::ClearToLineEnd => self.line_buffer.clear_to_line_end(),
    EditCommand::CutCurrentLine => self.cut_current_line(),
    EditCommand::CutFromStart => self.cut_from_start(),
    EditCommand::CutFromLineStart => self.cut_from_line_start(),
    EditCommand::CutToEnd => self.cut_from_end(),
    EditCommand::CutToLineEnd => self.cut_to_line_end(),
    EditCommand::CutWordLeft => self.cut_word_left(),
    EditCommand::CutBigWordLeft => self.cut_big_word_left(),
    EditCommand::CutWordRight => self.cut_word_right(),
    EditCommand::CutBigWordRight => self.cut_big_word_right(),
    EditCommand::CutWordRightToNext => self.cut_word_right_to_next(),
    EditCommand::CutBigWordRightToNext => self.cut_big_word_right_to_next(),
    EditCommand::PasteCutBufferBefore => self.insert_cut_buffer_before(),
    EditCommand::PasteCutBufferAfter => self.insert_cut_buffer_after(),
    EditCommand::UppercaseWord => self.line_buffer.uppercase_word(),
    EditCommand::LowercaseWord => self.line_buffer.lowercase_word(),
    EditCommand::SwitchcaseChar => self.line_buffer.switchcase_char(),
    EditCommand::CapitalizeChar => self.line_buffer.capitalize_char(),
    EditCommand::SwapWords => self.line_buffer.swap_words(),
    EditCommand::SwapGraphemes => self.line_buffer.swap_graphemes(),
    EditCommand::Undo => self.undo(),
    EditCommand::Redo => self.redo(),
    EditCommand::CutRightUntil(c) => self.cut_right_until_char(*c, false, true),
    EditCommand::CutRightBefore(c) => self.cut_right_until_char(*c, true, true),
    EditCommand::MoveRightUntil(c) => self.move_right_until_char(*c, false, true),
    EditCommand::MoveRightBefore(c) => self.move_right_until_char(*c, true, true),
    EditCommand::CutLeftUntil(c) => self.cut_left_until_char(*c, false, true),
    EditCommand::CutLeftBefore(c) => self.cut_left_until_char(*c, true, true),
    EditCommand::MoveLeftUntil(c) => self.move_left_until_char(*c, false, true),
    EditCommand::MoveLeftBefore(c) => self.move_left_until_char(*c, true, true),
  • We have a selection implementation in at least one of the existing modes (be it visual mode for vim or Shift-Arrow for the non modal emacs-like mode)
  • We are happy with how you configure movements that can affect both the buffer and the general UI (e.g. up/down for history, completion or other menus) We currently have this UntilFound logic that has some implicit rules in how you need to order things and has some edge cases (multiplier motions in vi, left and right movements while in the history scrollback). This is not super critical for the helix implementation concerns itself but I think it makes sense that we have some clarity in how things should be configured on the nushell side so we can drop helix mode in when it is ready (potentially after we stabilize a config format for 1.0)

@luccahuguet
Copy link
Author

I will also leave this here: a vscode extension that adds some helix commands. This could bring some insight

https://github.com/jasonwilliams/vscode-helix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants