ianhi / jupyterlab-vimrc

add a basic vimrc to jupyterlab vim
BSD 3-Clause "New" or "Revised" License
66 stars 4 forks source link

Command mode support #7

Open ejisoo opened 4 years ago

ejisoo commented 4 years ago

Thanks for creating this extension. I can't believe I missed this extension before.

I was wondering if you thought about extending the mapping to work in command mode as well not just in edit mode.

ianhi commented 4 years ago

Hi @ejisoo thanks!

I'm not sure exactly what you mean? I think of there being three modes in jupyterlab-vim

  1. Jupyter command mode
  2. Vim command mode (Normal Mode)
  3. Vim insert mode

Are you referring to mode 1? This extension should work in both Normal mode and insert mode, and you can use the built-in shortcut extension for mode 1.

If you have a suggestion for something to add though I'm all ears :)

ejisoo commented 4 years ago

Yes, I'm referring to 1. My key mapping looks likes this:

{
    "imap": [
        ["ii", "<Esc>"],
        ["<C-d>", "<Esc>dd"]
    ],
    "nmap": [
        ["<C-d>", "dd"]
    ],
    "nnoremap": [
        ["j", "gj"],
        ["k", "gk"],
    ]  // sometimes works, sometimes doesn't
}

I want to use the same Ctrl-D to delete cells in Jupyter command mode, but it's not working (probably because it's not a vim mode).

The default jupyterlab-vim bindings work just fine, but I want to use the vimrc mapping consistently across Jupyter command and edit mode.

ianhi commented 4 years ago

I want to use the same Ctrl-D to delete cells in Jupyter command mode, but it's not working (probably because it's not a vim mode).

Unfortunately these modes are pretty fundamentally disconnected. Each cell is it's own codemirror instance and this extension works by accessing the codemirror vim api. Basically codemirror vim mode maintains a dictionary of the mappings that is shared across all of the codemirror editor instances and this extension just modifies that dictionary. Jupyterlab then has its own whole set of commands that are totally separate. I don't think that there is an easy way to map vim commands to notebook commands. Or at the very least we would have to manually curate the mapping.

Extensions can modify jupyter shortcuts, for example jupyterlab-vim changes how dd behaves in command mode like this: https://github.com/axelfahy/jupyterlab-vim/blob/c4e43f940ef4be4c961608b6192412d2f3a33d1f/src/index.ts#L551-L555 . I've even considered adding some specific commands to toggle on and off what would improve the vim experience (esp if notebook vim becomes part of core) here https://github.com/jupyterlab/jupyterlab/issues/8592#issuecomment-664103749 I don't have immediate plans to implement something like this, in part because I'm not sure exactly what form it ought to take. If you have suggestions I'd love to hear them and even better if you have a solution a PR would be welcome as well.

In the meantime you can get the behavior you want by using the keyboard shortcut settings and adding this shortcut:

    {
      "command": "notebook:cut-cell",
      "keys": ["Ctrl D"],
      "selector": ".jp-Notebook:focus"
    },
ianhi commented 4 years ago
]  // sometimes works, sometimes doesn't

I'm curious about this. This isn't won't be a bug with this extension but it probably is a bug somewhere, either in codemirror or in jupyterlab. Have you ever narrowed down when it works vs when it doesn't?

ianhi commented 4 years ago

I guess part of what you want is to not have to change the settings file in multiple places every time you want to add a new mapping? Maybe we could introduce a new option in vimrc settings where you specify the keys to be remapped, the vim remapping, and the jupyter command you want run. So your example could have fit into something like this:

"nmap+jupyter": [
["Ctrl D", "dd", "notebook:cut-cell"]
]

this would require making some assumptions about what the desired selector is though. Or perhaps this could default to .jp-Notebok:focus and there could be an optional 4th argument that is the selector.

Pros:

cons:

ejisoo commented 4 years ago

My GitHub app notifications were off for some reason. I really appreciate you researching and brainstorming.

Each cell is it's own codemirror instance and this extension works by accessing the codemirror vim api.

Jupyterlab then has its own whole set of commands that are totally separate. I don't think that there is an easy way to map vim commands to notebook commands.

I conceptually knew that (but confused by the fact that even a vanilla Jupyter supports D, D for cut-cell) the two key bindings are different, but didn't know how separately they were implemented. So, thanks for the links. Like you said, there may not be an easy way to propagate key mapping customizations.

In the meantime you can get the behavior you want by using the keyboard shortcut settings and adding this shortcut:

    {
      "command": "notebook:cut-cell",
      "keys": ["Ctrl D"],
      "selector": ".jp-Notebook:focus"
    },

I'll try this instead. I would normally avoid having to change the setting in two places, but I guess it's like setting the clock on the microwave and the oven separately (honestly, I wish those were in sync at least..)

Extensions can modify jupyter shortcuts, for example jupyterlab-vim changes how dd behaves in command mode like this: https://github.com/axelfahy/jupyterlab-vim/blob/c4e43f940ef4be4c961608b6192412d2f3a33d1f/src/index.ts#L551-L555

  • Redundant with the keyboard shortcuts settings
  • Would increase complexity both in code and in UI for this extension

As a result, I would have to agree with this assessment. I think your extension is small and neat — it may be best if kept that way. Initially, I thought of your extension as (jupyter-vim)rc as opposed to jupyter-(vimrc) if that makes sense.

ejisoo commented 4 years ago
]  // sometimes works, sometimes doesn't

I'm curious about this. This isn't won't be a bug with this extension but it probably is a bug somewhere, either in codemirror or in jupyterlab. Have you ever narrowed down when it works vs when it doesn't?

I had to comment out that mapping because it was inconsistent. I'll screen record it when I get a chance.

It's irrelevant to this issue, but have you tried the black hole register ("_)? Is it supposed to (not) work?

ianhi commented 4 years ago

It's irrelevant to this issue, but have you tried the black hole register ("_)? Is it supposed to (not) work?

I think this is a known bug in codemirror's vim mode. See https://github.com/codemirror/CodeMirror/issues/6223

So it first needs to be fixed there, and then someone needs to open a PR to jupyterlab updating the codemirror version (instructions for such a PR here: https://github.com/jupyterlab/jupyterlab/issues/8267#issuecomment-619260406)

ianhi commented 4 years ago

Just left a comment on the codemirror issue for what I think the solution might be. Unfortunately, I don't have the mental bandwidth to try to fix it myself, but my hope is that it may just be a one line fix. So it may be worth your while to look into it. Though beware that the effort distribution on these sorts of things is apparently insanely heavy tailed... hence my reticence to look into it myself

ianhi commented 4 years ago

even a vanilla Jupyter supports D, D for cut-cell)

It actually deletes the cell rather than cut which has been opened as a bug https://github.com/jupyterlab/jupyterlab/issues/4765

So, thanks for the links. Like you said, there may not be an easy way to propagate key mapping customizations.

Thinking about this more it probably wouldn't be too hard. At least it would be so long as jupyter-commands had their own section in the settings. And there is a definitely a mental coherence to having the whole jupyterlab vim experience configurable via one settings file.

but I guess it's like setting the clock on the microwave and the oven separately (honestly, I wish those were in sync at least..)

I really like this description btw

Initially, I thought of your extension as (jupyter-vim)rc as opposed to jupyter-(vimrc) if that makes sense.

Another excellent and concise phrasing - you're on fire!

It does make sense. I've actually never firmly determined to myself what I wanted this extension to be. Until I became aware of the efforts to integrate jlab-vim into jupyterlab-core I had toyed with the idea of making a new vim extension that incorporated vimrc and the system-clipboard-support and calling it some horrendous like jupyterlab-vim-improved because I think that configurable settings are a big thing that that extension is missing. But now I'm not really sure what is best.

I think the following would be ideal

  1. jupyterlab-vim integrated into core
  2. jupyterlab_vim-system-clipboard-support integrated into core
  3. jupyterlab-vimrc integrated into

It looks as though 1 is going to happen, 2 is a maybe (idk how jlab devs would feel about it), and 3 just feels more unlikely as it starts to add complexity that I don't think the jlab devs will want to directly support. Though I definitely could be wrong about that. In the case where 1+ 2 happen I think it would make sense to extend vimrc to allow configurability of the entire vim experience in jupyterlab

ianhi commented 4 years ago

hooray! the _ register is now fixed on the codemirror master branch. It may be worth watching out for what codemirror release that ends up in and trying to get it included in jlab - nows a good time for that as theres lots of changes going on into the jlab 3 release

ejisoo commented 4 years ago

hooray! the _ register is now fixed on the codemirror master branch.

Awesome!

nows a good time for that as theres lots of changes going on into the jlab 3 release

I'm curious to see and nervous about how long I need to wait until the extensions start (or stop) supporting 3.

ejisoo commented 4 years ago
]  // sometimes works, sometimes doesn't

I'm curious about this. This isn't won't be a bug with this extension but it probably is a bug somewhere, either in codemirror or in jupyterlab. Have you ever narrowed down when it works vs when it doesn't?

What I ended up doing is not so fancy.. I just need those keys for moving around the cursor in Markdown mode.

"nmap": [
    ["<Down>", "gj"],
    ["<Up>", "gk"],
]

Then jumping to the next cell is the usual jupyterlab-vim's Ctrl-J.

even a vanilla Jupyter supports D, D for cut-cell)

It actually deletes the cell rather than cut which has been opened as a bug jupyterlab/jupyterlab#4765

Glad I don't remember trying and regretting it. Years ago, I used to use jupyter-vim-binding and I've been using jupyterlab-vim for as long as I remember.

And there is a definitely a mental coherence to having the whole jupyterlab vim experience configurable via one settings file.

Absolutely.

  1. jupyterlab-vim integrated into core

I really hope this happens. Until I knew about axelfahy's fork of jupyterlab-vim, I had been on jupyterlab 1.2 for a long time only to use the vim binding. I was so happy to find the fork and later vimrc. I don't have the skills and time to develop extensions sophisticated like these, so I'm really thankful that these are/were around. Back to the point, I would be thrilled to see it integrated into core for my peace of mind.