Synchronizing VimScript keybindings. #20
Comments
Good question, it's just hard coded in a poor way right now. My initial thinking was to have a ~/.oni/keybindings.json, and create commands for these, like 'oni.menu.nextItem' with JSON bindings, and get to the point where 99% of the mappings could be done in the json file. It does have the downside of having two places for bindings, and being foreign to power users. To bridge the gap, there are a few options I was thinking about:
Long-term, my vision for this project is to make modal editing through neovim more friendly and attractive to users of VSCode/Atom/etc, without having to dive into creating a _vimrc/init.vim... but still retaining much of the flexibility. Thanks for calling out some ideas here and trying out the app, great to have your feedback! |
Where do I sign? |
One thought: If there were an efficient way to invoke VimScript commands directly from JavaScript, then I'd be okay with half my configuration being in VimScript, and the other half being in JS because I know that I can eventually port my VimScript setup to JavaScript (including keyboard mappings). Bonus: The JS configuration can be made to spit out regular VimScript, and then the configuration can be loaded directly from VimScript for better use in regular (non-Oni) Vim (which would also help keep startup performance fast - if computing the pure VimScript configuration ahead of time (and caching it)). The result is that there would be a path to converting all your vimscript config/bindings to JS without any downsides. |
Good point. I believe there would be an efficient way to invoke VimScript commands over the msgpack RPC API, and there's already an entry point via the neovim/node-client. Need to validate the latency though beforehand and make sure that it is actually efficient. Regarding efficiency, eventually it'd be nice to run some input benchmarks, like this article... There is definitely more typing latency in Oni than GVim at the moment for me at the moment, but that's sort of a tangent. I like the idea of spitting out regular VimScript from json - things like inoremap/noremap could be emitted, so there wouldn't be any additional latency, and it would be relatively straightforward to implement. It gives us both the benefits of built-in performance and portability so that the config can still move freely. It also maps well to configuration options - moving some options like linenumbers, colorscheme, etc from init.vim to a configuration.json could be implemented in the exact same way. This sounds like the direction we should move forward in - really gives us the best of both worlds. This is great feedback, thanks for thinking about this! |
For keybindings then, would it be feasible to make a keybinding interpreter/generator so that people can choose to live in their configuration environment of choice? if there was a way to convert vim keybindings into the JSON/JS usable form and vice verse, people can live in their configuration environment of choice. For most people, it would probably be the init.vim, at least until oni attracts new users on its own. |
@bert88sta That's a good idea. I'd love to see some examples of what the bidirectional conversion might look like. One challenge is that there may be complex logic in determining what bindings are generated. For example, let's take the case where we use JS to configure via a file let something = reallyComplicatedExpression ();
let other = reallySlowExpression ();
module.exports = {
'insertMode': {
'ctrl-l': something,
'ctrl-h': other
}
}; The idea I had was that this file could use arbitrary JS expressions / dependencies to determine the keybindings. That isn't something that's easy to convert into VimScript. It's similar to how many are using CSS in JS. You could take this raw JS object that is returned and turn it into pure VimScript. The benefit is that we can run The same could be done of color schemes, and possibly many other forms of configuration. When given the full power of the language (JS) to author configuration, it's very expressive and powerful, but it is then impossible to create a bidirectional mapping between VimScript and JS. However, if the results are rendered as regular VimScript, it makes the appeal of bidirectional mapping smaller. The generated VimScript config could work in any existing Vim configuration (even without NeoVim). Yes, it must be authored in JS, but it works in all versions of Vim, and works fast at startup time because all the expensive stuff has been precomputed. I think it's worth Oni coming up with some conventions early on about which things must be precomputed, and which things can be computed at runtime/startup time. You can put a hard line in the sand that anything that blocks the initial rendering/config of Vim must not have huge JS dependencies or huge computations. That could help keep the "new window" operation blazing fast, while allowing more expensive plugins to be loaded lazily, and asynchronously. I feel it's important to get this right early on before people start making render blocking heavy plugins. |
I don't follow. |
It's only my personal opinion, but if you can render to plain VimScript, then the desire to be able to convert from JS to VimScript, and from VimScript to JS seamlessly seems less appealing. |
A place to start might be comparing the output of :map to a list of oni keybindings and just looking for conflicts |
@extr0py : As a start, I'm going to implement actual variables for keys globally... where would I define this? in config.ts? Oni.d.ts? Any help would be appreciated |
Thanks @bert88sta ! Are you thinking like the actual letter keys, or something higher level like commands? If its the former, we could have a For key handling, I'm picturing we'll have a couple pieces:
That's at least what I was thinking - hope that can help get you started. Thanks for looking at it! |
@extr0py : I was just thinking of this suggestion
As for the OniCommand thing, I'll get on that since (unlike TS) I can actually write vimL. Assuming it's efficient to use it, keeping neovim in charge of the things neovim does best is a pretty solid Idea. |
The generic functions sound great, makes sense to generalize those. Regarding the command execution, this file is a good place to start: This is all the special interop logic - the extra things we send over the wire that Neovim doesn't send out of the box. So might be a good place to define that function. |
alright, so the question becomes how do we add the state info for neovim to get a hold of? |
Hmm, ya, we could always send information down to the Neovim layer by executing a command ( We'd probably need to do the following:
That way, the Vim key bindings can apply depending on the oni state. I think it'd also be good to declare a general global variable like |
Good idea, but the convention seems to be to respond to |
@extr0py: Is it safe to assume that there's only going to be one "list" up at a time? A.K.A there won't be multiple UI instances that require c-p to navigate simultaneously? If not this is going to be complicated and slow. |
@kopischke - good point, thanks! I opened issue #94 to track setting @bert88sta - IMO, it would be a poor user experience to have multiple menus up, so we should avoid that. And it seems like it might also be unclear to the user what the result of might be in that case, so I don't believe there'd be a case to have multiple menus / list up at one time. |
@extr0py 👍 That makes my life a bit easier when it comes to the vim <-> oni communication. |
Could someone summarize the overall architecture for vim keybindings? Is anyone else concerned about impacting the gloriously fast startup time of Vim, by putting large, user configurable JS bundles in the critical load path? This is why I suggested that a more constrained approach be taken for a subset of editor functionality (colorschemes, key bindings, and syntax highlighting), which allows that configuration to compiled ahead of time to VimScript. I understand that no one wants to build that ahead of time converter right now, but it would be nice to take into account the architecture's future potential to be able to do such a thing. Namely - would it require a JavaScript interpreter to know which |
Another consequence of the current architecture is that the I was playing with the source, and I was disappointed that adding the {
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
click: (item, focusedWindow) => executeVimCommand("u")
} |
@jasonszhao, I think that's a consequence of #223, due to the discussion in #216. |
@bryphe I guess this is done already, or is there anything to address on this issue? |
@badosu - sorry for the late reply! Just going through items now.
Yes, although we still have further work to refine our input model, I believe we can close this and tracking remaining issues. I drafted up some of the motivation and architecture behind our current input model here: Architecture: Input Management, and we still have several issues tracking enhancements (chorded key bindings, more robust resolution, config improvements) |
I'll close this out, and we can continue to track the outstanding work in the other issues:
|
For UI interactions such as the popup (command-p) window (and canceling source editor popup menus), how should people configure keyboard mappings? How do they configure these, while also configuring Vim keyboard mapping (for insert/command mode). For example, it might make sense to apply all the
cmap
mappings while the "command P" window is open.If
cmap
doesn't make sense to integrate with, then perhaps a new "mode" for mappings makes sense. But in that case, would users configure 90% of their mappings in Vim, and then 10% of them in~/.oni/config.json
? It would be nice if keyboard mappings could be specified entirely in one place.Edit: Summarizing thoughts, tradeoffs, observations:
The text was updated successfully, but these errors were encountered: