Re: [implementations-list] Early implementation of new VIM-like mode
Let's get philosophical for a moment. What is it we "really" want to accomplish by writing a new package? 1. FAITHFUL VIM EMULATION inside Emacs. Key for key, the editing should be as identical to Vim's as possible. "Vim is fundamentally correct, but Emacs has some nice extensions like AUCTeX and Org-mode." 2. MODAL INTERFACE to Emacs' powers. Provide a way to define modal key bindings, and map them to the word/sentence/paragraph functions included with Emacs. "Emacs is Emacs, but modal editing is a good idea." There is a myriad of small differences between Vim and Emacs. For example, Vim's regular expressions are slighty different from Emacs'. Should we write a translator from one to the other, or do we simply bind `/' to `isearch-forward' and encourage the user to adjust? Or, when jumping back to previous locations in the buffer, Vim's `C-o' works slighty different than Emacs' `C-u C-SPC'. Do we re-implement this functionality, or should we stick with Emacs' function? The further we go down this road, the more obvious it becomes that a package that views another editor as the standard can never be very pretty. Viper is an emulator, and it takes tons and tons of replacement code to overrule all the Emacs specifics. It's a self-reinforcing strategy, too: once you've rewritten one function, you typically also have to rewrite the larger system it was part of, and so on. In short, if #1 is the goal, stay with Viper. However, and this is where we get philosophical again, there's something odd about the current state of things. Isn't the very point of using Emacs the power to extend and program it to one's liking? And yet, as we have seen, extending Viper turned out to be a "hackish" and unwieldy process. Worse still, there are few general solutions: e.g., adding text objects by redefining a function means the same function must be redefined again when adding something else. (For the record, this hack was my suggestion.) As someone said, the only way to improve your work or life is by understanding and examining why you do what you do. What we "really" want, I assert, is not all the specifics of Vim, but the general concept of modal editing -- and the ability to combine that concept with the rest of Emacs' powers in unlimited ways. (Of course, since one of those powers is the ability to faithfully emulate vi, the "purists" could get their golden standard simply by using this modal interface as a front-end to Viper's emulation functions.) But there are far more interesting ways to employ a modal interface than just reimplementing vi. For instance, think of text objects again. They aren't just a nifty "Vim trick", but a very reuseable idea. Wouldn't it be wicked cool to be able to do `cxw' -- transpose words (`M-t' in Emacs) `cxb' -- transpose blocks (`C-M-t' in Emacs) `cxs' -- transpose sentences (`transpose-sentences' in Emacs) `cxp' -- transpose paragraphs (`transpose-paragraphs' in Emacs) If we could bind `cx' to a command without overwriting the binding for `c', then this would be easy. Indeed, this is how Vim's `map' command works. But how to implement it in Emacs? Well, Frank Fischer is definitely onto something. Myself, I imagine some list of modal bindings -- wherein `c' maps to `change-command', `cx' to `transpose-object-command', and so on. Then, `change-command' calls the function `modal-read' to read input from the keyboard: (modal-read expectation) Here, `expectation' is what the calling command expects to get. `change-command' may call it like (modal-read motion), where `motion' somehow defines the keys that make up a text motion, like `3w'. Now, if the expectation is not met -- `x' is not a motion -- then `modal-read' will look up `cx' in the modal bindings list, and find `transpose-object-command'. Control will then be passed on to `transpose-object-command', which may read from the keyboard with (modal-read text-object). Anyway, the key is orthogonality. The key parser should be orthogonal to commands, motions, text objects or whatever creative innovation may come along. That way we can add our own, custom modal keys, without redefinitions of fixed code, which are difficult to share. I've probably said more than enough for now. But please, give some thought to what we really "want" from a total rewrite. With #1, Vim is the limit. With #2, Emacs is. _________________________________________________________ Alt i ett. Få Yahoo! Mail med adressekartotek, kalender og notisblokk. http://no.mail.yahoo.com
You made a good summary of what was pushing me to think about a new modal editing/vi core. In one word, we need a modal interface that's designed to be extensible. Actually, I think viper isn't that great to work on top to get #1. Adding something as simple as '< '> marks requires quite some kludges: 1. modify some validation function about register names (yes, viper uses the same function to validate both marks and register names, can't remember if in the ' or in the m command 2. modify the ex parser, so that it accepts < and > as markers 3. modify viper-ex so that it accepts another argument to initialize the starting ex string, or just hard-code the string initialization in the viper-ex function, making it aware of the existence of vimpulse. So, a minimum of 3 function redefinitions is needed to just add something as simple as 2 marks. And still, the result of everything is a big kludge, because viper's marker are accessed with get-register, the same function used for vi's registers. If I understood correctly, they are saved in this fashion, in some kind of associative table (I didn't look at the actual implementation) (let N be the character that identifies the register/mark): register(N): tab[N] marker(N): tab[N - ?a + 1] This is made under the assumption that the valid marks are only [a-z]. Even though I know that the ascii code for < and > is less than the ascii code for ?a, I don't know if the register table is used for stuff other than registers and marks. And even being positive about it, this would still remain a kludge. Maybe I'm pessimist, but I think that faithfully emulating vim means maintaining a parallel viper version. A kludge-ridden one, I daresay :) My 2 cents. Alessandro PS. With this I don't want to say I absolutely want faithful vim emulation, I just want to underline that working on top of viper isn't that great even for that purpose. 2009/7/1 Marius Andersen <[email protected]>
Let's get philosophical for a moment. What is it we "really" want to accomplish by writing a new package?
1. FAITHFUL VIM EMULATION inside Emacs. Key for key, the editing should be as identical to Vim's as possible. "Vim is fundamentally correct, but Emacs has some nice extensions like AUCTeX and Org-mode."
2. MODAL INTERFACE to Emacs' powers. Provide a way to define modal key bindings, and map them to the word/sentence/paragraph functions included with Emacs. "Emacs is Emacs, but modal editing is a good idea."
There is a myriad of small differences between Vim and Emacs. For example, Vim's regular expressions are slighty different from Emacs'. Should we write a translator from one to the other, or do we simply bind `/' to `isearch-forward' and encourage the user to adjust? Or, when jumping back to previous locations in the buffer, Vim's `C-o' works slighty different than Emacs' `C-u C-SPC'. Do we re-implement this functionality, or should we stick with Emacs' function?
The further we go down this road, the more obvious it becomes that a package that views another editor as the standard can never be very pretty. Viper is an emulator, and it takes tons and tons of replacement code to overrule all the Emacs specifics. It's a self-reinforcing strategy, too: once you've rewritten one function, you typically also have to rewrite the larger system it was part of, and so on.
In short, if #1 is the goal, stay with Viper.
However, and this is where we get philosophical again, there's something odd about the current state of things. Isn't the very point of using Emacs the power to extend and program it to one's liking? And yet, as we have seen, extending Viper turned out to be a "hackish" and unwieldy process. Worse still, there are few general solutions: e.g., adding text objects by redefining a function means the same function must be redefined again when adding something else. (For the record, this hack was my suggestion.)
As someone said, the only way to improve your work or life is by understanding and examining why you do what you do.
What we "really" want, I assert, is not all the specifics of Vim, but the general concept of modal editing -- and the ability to combine that concept with the rest of Emacs' powers in unlimited ways. (Of course, since one of those powers is the ability to faithfully emulate vi, the "purists" could get their golden standard simply by using this modal interface as a front-end to Viper's emulation functions.)
But there are far more interesting ways to employ a modal interface than just reimplementing vi. For instance, think of text objects again. They aren't just a nifty "Vim trick", but a very reuseable idea. Wouldn't it be wicked cool to be able to do
`cxw' -- transpose words (`M-t' in Emacs) `cxb' -- transpose blocks (`C-M-t' in Emacs) `cxs' -- transpose sentences (`transpose-sentences' in Emacs) `cxp' -- transpose paragraphs (`transpose-paragraphs' in Emacs)
If we could bind `cx' to a command without overwriting the binding for `c', then this would be easy. Indeed, this is how Vim's `map' command works. But how to implement it in Emacs?
Well, Frank Fischer is definitely onto something. Myself, I imagine some list of modal bindings -- wherein `c' maps to `change-command', `cx' to `transpose-object-command', and so on. Then, `change-command' calls the function `modal-read' to read input from the keyboard:
(modal-read expectation)
Here, `expectation' is what the calling command expects to get. `change-command' may call it like (modal-read motion), where `motion' somehow defines the keys that make up a text motion, like `3w'. Now, if the expectation is not met -- `x' is not a motion -- then `modal-read' will look up `cx' in the modal bindings list, and find `transpose-object-command'. Control will then be passed on to `transpose-object-command', which may read from the keyboard with (modal-read text-object).
Anyway, the key is orthogonality. The key parser should be orthogonal to commands, motions, text objects or whatever creative innovation may come along. That way we can add our own, custom modal keys, without redefinitions of fixed code, which are difficult to share.
I've probably said more than enough for now. But please, give some thought to what we really "want" from a total rewrite. With #1, Vim is the limit. With #2, Emacs is.
_________________________________________________________ Alt i ett. Få Yahoo! Mail med adressekartotek, kalender og notisblokk. http://no.mail.yahoo.com
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
Marius, thank you for your comments. I had some of them in my mind when I started with vim-mode. Am Mittwoch, 1. Juli 2009 schrieb Marius Andersen:
Let's get philosophical for a moment. What is it we "really" want to accomplish by writing a new package?
1. FAITHFUL VIM EMULATION inside Emacs. Key for key, the editing should be as identical to Vim's as possible. "Vim is fundamentally correct, but Emacs has some nice extensions like AUCTeX and Org-mode."
2. MODAL INTERFACE to Emacs' powers. Provide a way to define modal key bindings, and map them to the word/sentence/paragraph functions included with Emacs. "Emacs is Emacs, but modal editing is a good idea."
Well I prefer something between #1 and #2. I would like to have as many key-bindings work as in vim (like Jason, I don't want to learn new one), but not at any costs. If some minor aspects don't work as expected ... well :) For example, the position of the cursor after an operation is usually different in emacs and vim. Other things like ex-mode are not so important to me - usually emacs has better alternatives.
[snip]
What we "really" want, I assert, is not all the specifics of Vim, but the general concept of modal editing -- and the ability to combine that concept with the rest of Emacs' powers in unlimited ways. (Of course, since one of those powers is the ability to faithfully emulate vi, the "purists" could get their golden standard simply by using this modal interface as a front-end to Viper's emulation functions.)
True. This was one of the things I had in mind when starting with vim-mode. It should be easy to define new modes and keybindings.
But there are far more interesting ways to employ a modal interface than just reimplementing vi. For instance, think of text objects again. They aren't just a nifty "Vim trick", but a very reuseable idea. Wouldn't it be wicked cool to be able to do
`cxw' -- transpose words (`M-t' in Emacs) `cxb' -- transpose blocks (`C-M-t' in Emacs) `cxs' -- transpose sentences (`transpose-sentences' in Emacs) `cxp' -- transpose paragraphs (`transpose-paragraphs' in Emacs)
If we could bind `cx' to a command without overwriting the binding for `c', then this would be easy. Indeed, this is how Vim's `map' command works. But how to implement it in Emacs?
Currently there're two key-concepts in vim-modes: modes and keymaps and both should be as independent as possible. modes are just some functions called on activation and deactivation and some keymaps. In fact, one could easily use real emacs minor-modes for this. keymaps are the real core. In principle, in the current design it should be quite easy to do all those 'cxw' stuff. You can already define 'cxw' without any effect on the 'c' command. The only required functionality is execute some code on each 'intermediate' key (or prefix-key in emacs terms) to do something funny. This is what vim-mode does. The rest of vim-mode is just using this core to bring vim-like-bindings to the light. The point is that emacs' own keymaps are not powerful enough or well suited for modal editing (in my opinion). But it's relatively easy to plug another keymap system on top of them. In fact, the design is similar to emacs' own keymaps and minor/major modes. That's the reason why other vim-emulation-packages just use emacs-keymaps and minor modes.
Anyway, the key is orthogonality. The key parser should be orthogonal to commands, motions, text objects or whatever creative innovation may come along. That way we can add our own, custom modal keys, without redefinitions of fixed code, which are difficult to share.
I have to say that currently the core-keymap-system is a little specific to vim (e.g. it knows of 'motions', 'commands' and 'argument'), but it should not be too difficult to make it more generic (I have some ideas in this direction I'll try in the next days). And, of course, there're some aspects that are not so easy to do the right way for all thinkable model-editing-schemes, like undo/redo or repeating. The current implementation is oriented at vim's. I have to think about making it more generic. Some last words. I don't think we should try to build a system that can be the base of every thinkable modal-editing-scheme. Focusing on vim seems more important to me, because I think this is what most people need and most people are used to. Just my 2 cents Frank
Hi, I want to add something to my last mail. I think the 'modes' of modal editing are not the problem when implementing modal-editing in emacs - emacs does already have modes (minor- and major-modes) which can be enabled and disabled. The only problem are the keymaps. The emacs-keymaps don't provide an easy way to parse commands as desired (as vim does). So the only important part to be implemented IS the parsing of input commands. I pushed some new patches to vim-mode's repository which move (almost) all vim-specific components out of vim-keys.el and vim-nodes.el to vim-vim.el. Now the first both files could already provide a simple framework to get vim-like keymaps. The main point is that it's now possible to call a function when an arbitrary node of the keymap-tree is traversed, i.e. not only on the leaf nodes but also on the inner nodes. Vim-specific parts of commands, like counts or registers, can be easily implemented by tagging an appropriate function to the nodes of the keymaps (by this approach it is of course possible to manipulate and redirect the parsing process on inner nodes). Everything else, like the composition of commands and motions, the implementation of commands and even activation and deactivation of modes is not part of the keymap-stuff. Frank
participants (3)
-
Alessandro Piras -
Frank Fischer -
Marius Andersen