Evil numbered register behavior vis-a-vis vim
Hello, First thanks to all who work on Evil. It makes my days working in emacs much better. One feature I use a lot in vim is, use 'yy' to yank a line, perform some arbitrary editing, possibly including deletions, trusting that vim will hold onto the yanked text in the 0 register until I yank another text, and then, finally, pasting the text back with '"0p'. Evil doesn't implement the same behavior here. This link describes how it's supposed to work in vim. http://blog.sanctum.geek.nz/advanced-vim-registers/ """ Numbered registers The read-only registers 0 through 9 are your "historical record" registers. The register 0 will always contain the most recently yanked text, but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p. The registers 1 through 9 are for deleted text, with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9. """ Note that register 0 never contains deleted text. In Evil (I have version 1.0-dev) register 0 DOES contain deleted text (try it out), therefore the workflow described above does not work. I'm not sure if this is done on purpose or you've had this discussion before, but I know I'd love this particular feature to work the same way as vim. Would this be easy to fix? Thanks, Currell
Hi, I believe you are running into this bug: https://bitbucket.org/lyro/evil/issue/339/zero-register-0-has-odd-behavior Basically, registers 0-9 are mapped to the emacs kill ring. I don't have any experience to say how this would be fixed though. Allen On Sun, Feb 02, 2014 at 07:52:42PM -0500, Currell Berry wrote:
Hello,
First thanks to all who work on Evil. It makes my days working in emacs much better.
One feature I use a lot in vim is, use 'yy' to yank a line, perform some arbitrary editing, possibly including deletions, trusting that vim will hold onto the yanked text in the 0 register until I yank another text, and then, finally, pasting the text back with '"0p'. Evil doesn't implement the same behavior here.
This link describes how it's supposed to work in vim.
http://blog.sanctum.geek.nz/advanced-vim-registers/ """ Numbered registers
The read-only registers 0 through 9 are your "historical record" registers. The register 0 will always contain the most recently yanked text, but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p.
The registers 1 through 9 are for deleted text, with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9. """
Note that register 0 never contains deleted text. In Evil (I have version 1.0-dev) register 0 DOES contain deleted text (try it out), therefore the workflow described above does not work.
I'm not sure if this is done on purpose or you've had this discussion before, but I know I'd love this particular feature to work the same way as vim. Would this be easy to fix?
Thanks,
Currell
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
Currell Berry <[email protected]> writes:
Hello,
First thanks to all who work on Evil. It makes my days working in emacs much better.
One feature I use a lot in vim is, use 'yy' to yank a line, perform some arbitrary editing, possibly including deletions, trusting that vim will hold onto the yanked text in the 0 register until I yank another text, and then, finally, pasting the text back with '"0p'. Evil doesn't implement the same behavior here.
This link describes how it's supposed to work in vim.
http://blog.sanctum.geek.nz/advanced-vim-registers/ """ Numbered registers
The read-only registers 0 through 9 are your "historical record" registers. The register 0 will always contain the most recently yanked text, but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p.
The registers 1 through 9 are for deleted text, with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9. """
Note that register 0 never contains deleted text. In Evil (I have version 1.0-dev) register 0 DOES contain deleted text (try it out), therefore the workflow described above does not work.
I'm not sure if this is done on purpose or you've had this discussion before, but I know I'd love this particular feature to work the same way as vim. Would this be easy to fix?
There's a bug report about this at https://bitbucket.org/lyro/evil/issue/339/zero-register-0-has-odd-behavior I'm not sure if it was done on purpose, but I think it was just an oversight. Perhaps an evil developer will confirm that. I also don't think it would be hard to implement but I don't really know elisp and haven't actually gotten around to trying to do it. -- Kari
Am 03.02.2014 18:27, schrieb Kari Oikarinen:
Currell Berry <[email protected]> writes:
One feature I use a lot in vim is, use 'yy' to yank a line, perform some arbitrary editing, possibly including deletions, trusting that vim will hold onto the yanked text in the 0 register until I yank another text, and then, finally, pasting the text back with '"0p'. Evil doesn't implement the same behavior here.
There's a bug report about this at https://bitbucket.org/lyro/evil/issue/339/zero-register-0-has-odd-behavior
I'm not sure if it was done on purpose, but I think it was just an oversight. Perhaps an evil developer will confirm that. I also don't think it would be hard to implement but I don't really know elisp and haven't actually gotten around to trying to do it.
I can't really remember who implemented number registers and when, but I think the current implementation is how it is because it was ... easy. No special case concerning yank/delete ;). I'm not sure how difficult it is to implement the desired behaviour. The evil function that is responsible for yanking is `evil-yank`, so it could be modified to put text in the 0 register (which would not be mapped to the kill-ring anymore). However, it is also called by `evil-delete` as a subroutine (because deleting is, well, yanking the text followed by wiping it out of the buffer). There are also a few other yank functions, but they all should call `evil-yank`. Furthermore, there are also some non-Evil functions (e.g. `kill-ring-save` typically bound to M-w), which also put text onto the kill-ring but do not delete it from the buffer. Handling all of them appropriately might not be so easy. So, implementing the 0-register correctly is certainly possible but not completely trivial (unless there is some support by pre-existing Emacs functions that I'm not aware of). If somebody wants to try implementing it, I'll be glad to provide any help I can ;) Best regards, Frank
Frank Fischer <frank-fischer <at> shadow-soft.de> writes:
Am 03.02.2014 18:27, schrieb Kari Oikarinen:
Currell Berry <currellberry <at> gmail.com> writes:
One feature I use a lot in vim is, use 'yy' to yank a line, perform some arbitrary editing, possibly including deletions, trusting that vim will hold onto the yanked text in the 0 register until I yank another text, and then, finally, pasting the text back with '"0p'. Evil doesn't implement the same behavior here.
There's a bug report about this at https://bitbucket.org/lyro/evil/issue/339/zero-register-0-has-odd-behavior
I'm not sure if it was done on purpose, but I think it was just an oversight. Perhaps an evil developer will confirm that. I also don't think it would be hard to implement but I don't really know elisp and haven't actually gotten around to trying to do it.
I can't really remember who implemented number registers and when, but I think the current implementation is how it is because it was ... easy. No special case concerning yank/delete ;).
I'm not sure how difficult it is to implement the desired behaviour. The evil function that is responsible for yanking is `evil-yank`, so it could be modified to put text in the 0 register (which would not be mapped to the kill-ring anymore). However, it is also called by `evil-delete` as a subroutine (because deleting is, well, yanking the text followed by wiping it out of the buffer). There are also a few other yank functions, but they all should call `evil-yank`. Furthermore, there are also some non-Evil functions (e.g. `kill-ring-save` typically bound to M-w), which also put text onto the kill-ring but do not delete it from the buffer. Handling all of them appropriately might not be so easy.
So, implementing the 0-register correctly is certainly possible but not completely trivial (unless there is some support by pre-existing Emacs functions that I'm not aware of).
If somebody wants to try implementing it, I'll be glad to provide any help I can ;)
Best regards, Frank
Ok, thanks for the responses everyone. I'll give it a shot myself when I get a window of free time. I will need to read up on emacs kill-ring behavior and vim buffer behavior, and pick up some elisp along the way. Just to confirm: the goal with these types of features is to emulate vim behavior as closely as possible, no? Just from glancing over the evil code, it looks like most of the vim "special register" behaviors are already implemented. "evil-set-register" within evil-common.el does register type checking, and implements special features depending on the register involved. A lot of functions TAKE IN various arguments (including register) but atm I can't figure out where the calls to these functions (with the register number) are actually happening. For example here's the signature for the function "evil-delete-line" in evil-commands.el. (evil-define-operator evil-delete-line (beg end type register yank-handler) "Delete to end of line." and here's where the key mapping to it is set in evil-maps.el (define-key evil-normal-state-map "D" 'evil-delete-line) . Where do the arguments to evil-delete-line actually get specified? Sorry if this is a stupid question, I am new to elisp. --Currell
Am 04.02.2014 17:38, schrieb Currell Berry:
Ok, thanks for the responses everyone. I'll give it a shot myself when I get a window of free time. I will need to read up on emacs kill-ring behavior and vim buffer behavior, and pick up some elisp along the way.
Just to confirm: the goal with these types of features is to emulate vim behavior as closely as possible, no?
Yes, if it is possible with reasonable effort. For instances, buffers are handled in different ways in Vim and Emacs (e.g. Vim buffers are numbered, Emacs buffers are not), but there is probably no real advantage in enforcing Vim-like buffer handling.
Just from glancing over the evil code, it looks like most of the vim "special register" behaviors are already implemented. "evil-set-register" within evil-common.el does register type checking, and implements special features depending on the register involved.
A lot of functions TAKE IN various arguments (including register) but atm I can't figure out where the calls to these functions (with the register number) are actually happening. For example here's the signature for the function "evil-delete-line" in evil-commands.el.
(evil-define-operator evil-delete-line (beg end type register yank-handler) "Delete to end of line."
and here's where the key mapping to it is set in evil-maps.el
(define-key evil-normal-state-map "D" 'evil-delete-line)
.. Where do the arguments to evil-delete-line actually get specified? Sorry if this is a stupid question, I am new to elisp.
Evil commands are Emacs interactive commands. An interactive command is a function with an (interactive ...) directive right at the beginning of the function body. If a function is called, well, interactively, i.e. using a key-sequence, the actual values for the parameters are not passed explicitly (as there is no way in specifying those values with a key-sequence) but are determined by investigating the interactive directive. If you have function like this ``` (defun myfunc (x) (interactive (list 42)) (message "%s" x)) (global-set-key (kbd "C-c t") 'myfunc) ``` then calling `myfunc` by pressing C-c t will pass 42 as value of x. More information about the interactive directive can be found in the elisp manual. Evil extends standard interactive directives to support special codes. The interactive directive of `evil-delete-line` is ``` (interactive "<R><x>") ``` The first code <R> means the Evil should pass the current visual selection (if any) in the first three parameters `beg end type` (or nil if Evil is not in visual state). The second code <x> causes Evil to pass the selected register-name (i.e. the one selected by a preceding `"x` key-sequence, where x is the character of the register) in the next (the fourth) argument (or nil). The fifth argument of the function `yank-handler` is always nil, it is only needed when `evil-delete-line` is called as a function from other elisp code. I hope this helps. Note that interactive codes are a Emacs feature and nothing special to Evil. Best regards, Frank
Frank Fischer <frank-fischer <at> shadow-soft.de> writes:
...
Thank you for your extensive explanation. Especially the bit explaining how Evil extended the standard interactive directives was helpful. I meant to say vim *register* handling when I mentioned vim *buffer* handling. This is on my queue of things to do. Cheers, Currell
participants (4)
-
Allen Li -
Currell Berry -
Frank Fischer -
Kari Oikarinen