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

Enable visual snippets for vim #359

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

superle3
Copy link
Contributor

@superle3 superle3 commented Dec 5, 2024

This PR tries to somewhat implement #44 by adding a keybinding to swap between keymap vim-insert and vim-visual without losing the current selection.
It's implemented as a setting instead of an hotkey such that more complex commands like <C-g><C-g> are possible.
The setting is turned off by default and can only be turned on if obsidians vim mode is on.

Its referred to as SelectMode in the settings, because vim's selectmode is something similair to selecting in vim-insert in codemirror, but not the same. For example visualblock and visualline are not retained after switching only the selection and maybe more things, but just tries to expose the vim-insert keymap while in vim-visual, not emulating vim's actual selectmode.

The vim object is behind untyped objects from obsidian so I copied the types from the original codemirror vim project (https://github.com/replit/codemirror-vim), but these have a lot of any in them so its not that great.

Also this may not be the right plugin for this PR, I understand if its better suited for https://github.com/esm7/obsidian-vimrc-support/tree/master or the vim extension itself.

at last, first time using ts/js, sorry for potential bad code quality

@llakala
Copy link
Contributor

llakala commented Dec 6, 2024

Tested this, and can confirm basic functionality is working. I can't speak for code quality, but I'd love to see something added to DOCS.md about this before merging.

Also, for what it's worth, I personally think this fits in perfectly fine into this plugin, and doesn't need to be put into something else.

@superle3
Copy link
Contributor Author

superle3 commented Dec 6, 2024

looked a bit more into unmap and map and changed descriptions accordingly. Also added ? for the undocumented objects, since im just copying that from the vimrc plugin and I have no idea what their behavior is. Also removed setting keyword from settings tab to comply with obsidian guidelines. But behavior is the same so amended it.

Okay after checking <S-a> mapping again, it seems shift doesn't work in vim mappings as in the actual shift key <S-[key]> not <C-a>B. Will report it to the vim repo, but will change the description accordingly again since the change will take time.

edit: <C-a>B also doesn't work, only B.

edit2: will add an explanation to the visual snippets in the DOCS.md later

@superle3
Copy link
Contributor Author

superle3 commented Dec 7, 2024

also would like to add #352. Would do it in a seperate PR, but I wouldn't be able to reuse my current code for that

llakala

This comment was marked as duplicate.

Copy link
Contributor

@llakala llakala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small wording changes to new documentation. Newline logic working perfectly - I'll spend some time using this PR on my main vault to see if I encounter any bugs.

@superle3
Copy link
Contributor Author

superle3 commented Dec 9, 2024

Now o doesn't work outside of environments. Which makes sense from the code, but I thought I tested that and it did work.
easy solution would be to add

if (!runMatrixShortcuts(view, ctx, "Enter", false)) {
    cm.getInputField().dispatchEvent(new KeyboardEvent("keydown", { key: "Enter" }));
}

but that changes the behaviour of o for empty indented lines.
I tried to look at the original code, and it comes down to the code below, but I am not really sure whats going on there. I would have to look at the commands api from codemirror first.
Most importantly though the current implementation from both vim and codemirror-vim seem counterintuitive (although vim probably makes some sense).

I would expect it to keep the current indentation regardless if the line is empty, but
codemirror-vim: uses the current indentation for the the newline but deletes the current indentation if the line is empty.
vim (tested for python on vim --clean): finds the proper indentation to use for the newline through the parser (did not work for md file) and deletes the current indentation if the line is empty and has not been edited so if you do the sequence o<Esc>o.

The code below does work instead of pressing the enter key.

import {insertNewlineAndIndent} from "@codemirror/commands"
    newlineAndIndent: function (cm: CodeMirror) {
      insertNewlineAndIndent({
        state: cm.cm6.state,
        dispatch: (tr) => {
          return dispatchChange(cm, tr);
        }
      })
function dispatchChange(cm: CodeMirror, transaction: any) {
  var view = cm.cm6;
  if (view.state.readOnly)
    return;
  var type = "input.type.compose";
  if (cm.curOp) {
    if (!cm.curOp.lastChange) type = "input.type.compose.start";
  }
  if (transaction.annotations) {
    try {
      transaction.annotations.some(function (note: any) {
        if (note.value == "input") note.value = type;
      });
    } catch (e) {
      console.error(e);
    }
  } else {
    transaction.userEvent =  type;
  }
  return view.dispatch(transaction)
}

@superle3
Copy link
Contributor Author

I couldn't find out the reason for this code from the documentation of both codemirror and the vim plugin. There is a slight change from the code a both. insertmode is entered after a newline has been added since otherwise macros would behave weird and the annotations are only changed if its an array. I don't know why there is a try catch but im guessing it has a reason.

@superle3 superle3 force-pushed the main branch 4 times, most recently from f88e921 to be91eb6 Compare December 19, 2024 21:19
@superle3
Copy link
Contributor Author

superle3 commented Dec 19, 2024

forgot to unmap the old keymappings when vim keybindings are turned off. Everything should be good now.

Edit:
In light of #310, I feel I should clarify that the insert-newline-below action redefined in this pr is only meant to insert a \\ and a newline inside matrix environments defined by the user within display math and not inline math. Otherwise it works as normal.

I don't think it should work in inline math, since no newline is inserted then.

Copy link
Contributor

@llakala llakala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline behavior working perfectly for me, thank you!

@superle3
Copy link
Contributor Author

superle3 commented Feb 1, 2025

For the type safety it would probably be better to use https://github.com/Fevol/obsidian-typings for the untyped objects. But the methods of the vimApi still untyped so its still not ideal.

@superle3
Copy link
Contributor Author

superle3 commented Feb 1, 2025

changed window.CodeMirrorAdapter.Vim with initVimMode(CodeMirrorAdapter)

edit: ignore that.

superle3 and others added 2 commits February 3, 2025 19:10
Use the vimapi from codemirror to define 2 actions: "from visual mode to insert mode" and "from insert mode to visual mode" while selecting something. This exposes the visual snippets to vim users who want to use vim visual mode to select something.
Its only enabled if vim itself is enabled and maps these "actions" to the vim extension itself and not to hotkeys of obsidian. This enables more complex

Also implemented better wording for the vim docs suggested by

Co-authored-by: Eman Resu <78693624+llakala@users.noreply.github.com>
give the option to redefine the `insert new line below` to also append a
\\ at end of the current line in a matrix environment. The enter is
handled by simulating a enter press call. The cursor is moved to the
current line and collum = line.length + 1. This may have unwanted
consequences, other option would be to handle the key with vim but that
relies on the vim keymap.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants