vimpulse bug: visual-line does not select final newline
Hello, Using a recent snapshot of vimpulse (0.4+git, downloaded 08/2010) in Emacs 23.2.1, it appears that linewise-visual mode (V) often fails to select the trailing newline in the last line. This causes unexpected results (i.e. not like vim) when used with the delete (d) and yank (y) commands (and probably others). Similar behavior can be observed using characterwise-visual mode (v) (e.g. '0v$' also fails to select the trailing newline). For example, starting with: one two three and the cursor on line 'two', pressing 'Vd' results in: one three rather than the expected: one three Similarly, pressing 'Vyp' results in: one ttwowo three rather than: one two two three Similar oddities result for variations with multiple lines, using characterwise-visual mode, et cetera. I'm assuming this is tied up in the visual-expand/contract-functions and associated needs-newline variables. Thank you to the developers and contributors to vimpulse. Finding it has allowed me to consider using Emacs. Regards, Craig
null
This is an expansion of my previous bug report. Results from further experimentation are provided below. Aside from adding to 'load-path, at most the only lines in my emacs.d/init.el file were: (require 'vimpulse) (require 'vimpulse-surround)
For example, starting with:
one two three
and the cursor on line 'two', pressing 'Vd' results in:
one
three
rather than the expected:
one three
This problem appears to be caused by vimpulse-surround rather than vimpulse. Perhaps something gets broken in connection with vimpulse-surround's 'vimpulse-delete-surround-or-delete' function. Even without loading vimpulse-surround, however, selecting a line with '0v$' still results in non-vim-like behavior, but I suppose this could be considered a 'feature'.
Similarly, pressing 'Vyp' results in:
one ttwowo three
rather than:
one two two three
This problem remains even without vimpulse-surround. -Craig
Hi Craig, welcome to the mailing list. I haven't looked into the Vimpulse/vimpulse-surround issue yet, but I can confirm that "0v$" does not work like in Vim. In Vim, keys like "$" and "l" move one character more in Visual mode than they do in Normal mode. Vimpulse lacks this distinction. Adding it shouldn't be very hard, so just watch this space. Thanks for the bug report! -- Vegard
Vegard Øye <vegard_oye <at> hotmail.com> writes:
I haven't looked into the Vimpulse/vimpulse-surround issue yet, but I can confirm that "0v$" does not work like in Vim. In Vim, keys like "$" and "l" move one character more in Visual mode than they do in Normal mode. Vimpulse lacks this distinction.
Adding it shouldn't be very hard, so just watch this space. Thanks for the bug report!
Thanks. Although Vim grabs the newline with "v$", I often find myself typing "v$h" to get what I really wanted, so I won't vote either way on that particular aspect of the issue. Not having "V" (visual-line) grab the final newline, however, prevents easy copying of lines, and that's keeping me solidly in Vim for now. Thanks again. Normally I'd prefer to offer a patch, but elisp is still eludes me.
Craig Tenney <[email protected]> writes:
Thanks. Although Vim grabs the newline with "v$", I often find myself typing "v$h" to get what I really wanted, so I won't vote either way on that particular aspect of the issue.
I always use Y (remapped to y$ both in Vim and Vimpulse) for that, which leaves the newline out.
Not having "V" (visual-line) grab the final newline, however, prevents easy copying of lines, and that's keeping me solidly in Vim for now.
I always use yy for copying single lines including the newline. *But* I can't actually reproduce any of the difference you described between V in Vim and Vimpulse, even the Vyp case. [Just in case it could affect solidity of your Vim position. ;-P ] Štěpán
I always use Y (remapped to y$ both in Vim and Vimpulse) for that, which leaves the newline out.
I like that -- it fits much better with C and D. Thank you for the tip!
Not having "V" (visual-line) grab the final newline, however, prevents easy copying of lines, and that's keeping me solidly in Vim for now.
I always use yy for copying single lines including the newline.
Same here, but I like V{motion}y for larger blocks.
*But* I can't actually reproduce any of the difference you described between V in Vim and Vimpulse, even the Vyp case.
I dug further. This is my 'min_init.el' file: (add-to-list 'load-path "~/.emacs.d/elisp/") (require 'vimpulse) and for testing I'm starting Emacs with: emacs -q -l min_init.el testfile Here's what I've discovered: If 'vimpulse.elc' exists, 'Vyp' doesn't work correctly (i.e. it doesn't grab the final newline). If I delete the 'elc' file, 'Vyp' works as expected. If I byte-compile 'vimpulse.el' again, the 'Vyp' problem returns. Through all of this, 'Vd' has worked properly, i.e. it grabs the final newline. (fyi my vimpulse snapshot appears to have been from ~August 5.) What a queer problem... So I deleted every byte-compiled file and added a line to the end of 'min_init.el': (require 'vimpulse-surround) When I load vimpulse-surround, 'Vd' fails to grab the final newline (as described in the orginal bug report), but 'Vyp' still works properly. I apologize for leading you down a false path with my byte-compiled weirdness. I'm still lost on the vimpulse-surround thing, but that is presumably someone else's domain. Regards and thanks, Craig
On 2010-08-18 20:07, Craig Tenney wrote:
Here's what I've discovered: If 'vimpulse.elc' exists, 'Vyp' doesn't work correctly (i.e. it doesn't grab the final newline). If I delete the 'elc' file, 'Vyp' works as expected. If I byte-compile 'vimpulse.el' again, the 'Vyp' problem returns.
Thanks for this very valuable information. I've confirmed the bug, which should be fixed in commit [edcc432584]; please test. :) What caused the bug is that Vimpulse inspects the `interactive' form of the command to be executed to determine if it is an operator (like "c", "d", "y") or not. That form looks a little different when compiled, obviously, so the inspection failed. The relation of this to the missing newline is explained below.
I'm still lost on the vimpulse-surround thing, but that is presumably someone else's domain.
I can now explain this, too. Vimpulse intentionally drops the final newline when a non-Vimpulse command is issued on a line selection. I've found that this integrates better with other packages, like skeleton-mode and AUCTeX. Say you edit a TeX document and want to convert the following line to a heading: Lorem ipsum If you press "V C-c C-s" (followed by a couple of RET's), you get: \section{Lorem ipsum} However, if Vimpulse included the newline, you would get this instead: \section{Lorem ipsum } So Vimpulse tries to be clever and do the "right thing", depending on the circumstances. If you execute one of Vimpulse's operator commands, then the right thing is to include the newline -- to provide the selection "as-is", so to speak. The operator will handle the rest. In other cases, the newline is omitted. Which is why vimpulse-surround's `vimpulse-delete-surround-or-delete' command fails: it is not an operator -- or is not identified as one, anyway. To be identified as an operator, the command has to call `vimpulse-range' in its `interactive' form. Rewriting the code along the lines of approach #2 in the post below is one solution.[1] Another is to list the commands in `vimpulse-newline-cmds': (add-to-list 'vimpulse-newline-cmds 'vimpulse-change-surround-or-change) (add-to-list 'vimpulse-newline-cmds 'vimpulse-delete-surround-or-delete) At this point, I think it would be beneficial to define operators with a dedicated `vimpulse-define-operator' macro to make their special standing more explicit. I recall Štěpán has proposed this already. [1] http://permalink.gmane.org/gmane.emacs.vim-emulation/524 -- Vegard
Vegard Øye <[email protected]> writes:
On 2010-08-18 20:07, Craig Tenney wrote:
Here's what I've discovered: If 'vimpulse.elc' exists, 'Vyp' doesn't work correctly (i.e. it doesn't grab the final newline). If I delete the 'elc' file, 'Vyp' works as expected. If I byte-compile 'vimpulse.el' again, the 'Vyp' problem returns.
Thanks for this very valuable information. I've confirmed the bug, which should be fixed in commit [edcc432584]; please test. :)
What caused the bug is that Vimpulse inspects the `interactive' form of the command to be executed to determine if it is an operator (like "c", "d", "y") or not. That form looks a little different when compiled, obviously, so the inspection failed. The relation of this to the missing newline is explained below.
Are you sure? I can see no difference in the result of `interactive-form' (and the old definition of `vimpulse-operator-cmd-p') for compiled and uncompiled functions, so I don't think this is the actual problem.
I'm still lost on the vimpulse-surround thing, but that is presumably someone else's domain.
I can now explain this, too.
[...]
Rewriting the code along the lines of approach #2 in the post below is one solution.[1] Another is to list the commands in `vimpulse-newline-cmds':
(add-to-list 'vimpulse-newline-cmds 'vimpulse-change-surround-or-change) (add-to-list 'vimpulse-newline-cmds 'vimpulse-delete-surround-or-delete)
This works, thanks for pointing that out.
At this point, I think it would be beneficial to define operators with a dedicated `vimpulse-define-operator' macro to make their special standing more explicit. I recall Štěpán has proposed this already.
Yeah, the manual interactive spec "parsing" is fragile. Štěpán
Štěpán Němec <[email protected]> writes:
Vegard Øye <[email protected]> writes:
What caused the bug is that Vimpulse inspects the `interactive' form of the command to be executed to determine if it is an operator (like "c", "d", "y") or not. That form looks a little different when compiled, obviously, so the inspection failed. The relation of this to the missing newline is explained below.
Are you sure? I can see no difference in the result of `interactive-form' (and the old definition of `vimpulse-operator-cmd-p') for compiled and uncompiled functions, so I don't think this is the actual problem.
I take that back, I see the problem now, too. Sorry for the noise. Štěpán
Vegard Øye <[email protected]> writes: [...]
Rewriting the code along the lines of approach #2 in the post below is one solution.[1] Another is to list the commands in `vimpulse-newline-cmds':
(add-to-list 'vimpulse-newline-cmds 'vimpulse-change-surround-or-change) (add-to-list 'vimpulse-newline-cmds 'vimpulse-delete-surround-or-delete)
[...]
[1] http://permalink.gmane.org/gmane.emacs.vim-emulation/524
I went for the minor mode approach (and thus the second recommended solution above) to be able to enable and disable the plugin cleanly. Tim seems to be absent lately, so I forked his Github repo to make the changes available to anyone interested: git://github.com/stepnem/vimpulse-surround.el.git There are still glitches, though, e.g.: - with the mode enabled, `cw' eats the space after the word being changed, unlike in plain Vim(pulse) - after enabling the mode, you have to actually do something for the new bindings to take effect, i.e. `C-h c c' still reports `vimpulse-change', only after e.g. entering and exiting Insert mode does `vimpulse-change-surround-or-change' take effect. - changing curly braces (`cs}' on "{word}") doesn't seem to work I guess I'll try to investigate when I get the time'n'energy, but the relevant parts of Vimpulse make my head explode, so I welcome any advice or contribution. ;-) Štěpán P.S.: Locally I have also changed `<' and `>' to behave as other brackets and left only `t' for tags. That's surround.vim-incompatible AFAIK so I haven't pushed it, but I *really* want angle brackets, too (and it's a net win, as `t' already takes care of tags anyway). What do you people think? I should ask the surround.vim author, too.
Hi Stepan, I am back. I recently lost a daughter and have been grieving, and am transitioning back into the temporal world again. Before I say more, I'd just encourage everyone to hold their families close and be sure to spend time with them every day. Family is the most important thing in this world. Now, to the discussion at hand: On Thu, Aug 19, 2010 at 11:06 AM, Štěpán Němec <[email protected]> wrote:
Vegard Øye <[email protected]> writes:
[...]
Rewriting the code along the lines of approach #2 in the post below is one solution.[1] Another is to list the commands in `vimpulse-newline-cmds':
(add-to-list 'vimpulse-newline-cmds 'vimpulse-change-surround-or-change) (add-to-list 'vimpulse-newline-cmds 'vimpulse-delete-surround-or-delete)
[...]
[1] http://permalink.gmane.org/gmane.emacs.vim-emulation/524
I went for the minor mode approach (and thus the second recommended solution above) to be able to enable and disable the plugin cleanly.
Tim seems to be absent lately, so I forked his Github repo to make the changes available to anyone interested:
git://github.com/stepnem/vimpulse-surround.el.git
Thank you for making the changes, I'll review them with the confidence that they are clearly improvements. I don't fully understand how vimpulse-surround had repercussions and was affecting vimpulse surround behavior, I will read more carefully into it.
There are still glitches, though, e.g.:
- with the mode enabled, `cw' eats the space after the word being changed, unlike in plain Vim(pulse)
- after enabling the mode, you have to actually do something for the new bindings to take effect, i.e. `C-h c c' still reports `vimpulse-change', only after e.g. entering and exiting Insert mode does `vimpulse-change-surround-or-change' take effect.
- changing curly braces (`cs}' on "{word}") doesn't seem to work
I guess I'll try to investigate when I get the time'n'energy, but the relevant parts of Vimpulse make my head explode, so I welcome any advice or contribution. ;-)
Štěpán
P.S.: Locally I have also changed `<' and `>' to behave as other brackets and left only `t' for tags. That's surround.vim-incompatible AFAIK so I haven't pushed it, but I *really* want angle brackets, too (and it's a net win, as `t' already takes care of tags anyway). What do you people think? I should ask the surround.vim author, too.
I have thought about that as well, but there's something very natural about typing 's<a href="...">' to create a link. Tim Pope I'm sure wrestled with that decision.
_______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
On Fri, Aug 20, 2010 at 10:19 AM, Tim Harper <[email protected]> wrote:
... I don't fully understand how vimpulse-surround had repercussions and was affecting vimpulse surround behavior, I will read more carefully into it.
I understand now. I've pulled the latest vimpulse code, and it appears to have addressed this issue. It still seems like it would be wise to define the "vimpulse-define-operator" macro. Vegard: Would the defadvice route [1] not work? (as opposed to option #2, the null range selector). Tim [1] http://permalink.gmane.org/gmane.emacs.vim-emulation/527
On 2010-08-19 19:06, Štěpán Němec wrote:
I went for the minor mode approach (and thus the second recommended solution above) to be able to enable and disable the plugin cleanly.
Good!
There are still glitches, though, e.g. with the mode enabled, `cw' eats the space after the word being changed, unlike in plain Vim(pulse) ... I guess I'll try to investigate when I get the time'n'energy, but the relevant parts of Vimpulse make my head explode, so I welcome any advice or contribution. ;-)
In a simple world, motions and operators would be completely orthogonal. In the real world, special cases turn out to have their uses. The "w" and "W" motions normally include the trailing space, unless the operator is "c", in which case they exclude it. (This strange-yet-intuitive behavior is not a Vim hack, but is part of classical vi, as can be seen by running Viper only or enabling :set compatible in Vim.) Which raises an implementation question: are operators functions of text ranges, or functions of motions? If motions and operators are orthogonal, then it doesn't matter where the text range came from, and operators may take a range as their input. If the motion does matter, on the other hand, then that should be the operator's argument. Vimpulse's solution is to accept both in different contexts. If the operator is called interactively, then not only is a motion read from the keyboard, but the current motion and operator can be accessed via the variables `vimpulse-this-motion' and `vimpulse-this-operator'. If the operator is called programmatically, on the other hand, then only a text range is specified, and no motion enters the picture. Finally, there's `vimpulse-operator-apply', which lets us pass a motion to an operator in a programmatic context. It is used by the repeat system, which remembers the last repeatable operator/motion combination in `vimpulse-last-operator' and `vimpulse-last-motion'. Based on this, a cleaner way to define the dispatchers would be (defun vimpulse-change-surround-or-change (beg end &optional dont-save) (interactive (vimpulse-range)) (if (memq vimpulse-this-motion '(vimpulse-surround-paren vimpulse-surround-bracket vimpulse-surround-brace vimpulse-surround-angle vimpulse-surround-single-quote vimpulse-surround-double-quote)) (vimpulse-surround-change beg end (eq *vimpulse-surrounding* 'strip)) (vimpulse-operator-apply 'vimpulse-change vimpulse-this-motion vimpulse-this-count))) where the `memq' expression would of course be replaced by a call to a `vimpulse-surround-object-p' function which looked up the motion in a list autogenerated by the `vimpulse-surround-define-text-object' macro. This definition also obviates the need to list the dispatcher in `vimpulse-newline-cmds', since it is an operator proper. Speaking of macros, I think an even cleaner solution would be to build a condition into all operators for bypassing the operator's body when called interactively. If the motion sets some variable to t, then the operator will do nothing -- only the motion is executed. Defining the surround commands as "standalone motions", there is no need for dispatcher functions at all, which lets vimpulse-surround play nicely with other extensions which might do similar things. Furthermore, such a variable would allow for a reversal of roles where the motion is calling the operator (which is actually how vip and Viper were implemented), letting one add instructions /after/ the operator. For example, a custom "dap" object may clean up whitespace between paragraphs as a separate step, so that the deleted paragraph may be pasted without the extra whitespace. There's a lot of possibilites once you have a general `vimpulse-define-operator' macro in place. -- Vegard
On 2010-08-19 19:06, Štěpán Němec wrote:
- after enabling the mode, you have to actually do something for the new bindings to take effect, i.e. `C-h c c' still reports `vimpulse-change', only after e.g. entering and exiting Insert mode does `vimpulse-change-surround-or-change' take effect.
Should be fixed in Vimpulse commit [f01061610c], provided you enable the mode with M-x vimpulse-surround-mode or (vimpulse-surround-mode 1) rather than (setq vimpulse-surround-mode t). -- Vegard
On Wed, Aug 18, 2010 at 20:01, Vegard Øye <[email protected]> wrote:
On 2010-08-18 20:07, Craig Tenney wrote:
Here's what I've discovered: If 'vimpulse.elc' exists, 'Vyp' doesn't work correctly (i.e. it doesn't grab the final newline). If I delete the 'elc' file, 'Vyp' works as expected. If I byte-compile 'vimpulse.el' again, the 'Vyp' problem returns.
Thanks for this very valuable information. I've confirmed the bug, which should be fixed in commit [edcc432584]; please test. :)
The snapshot I just downloaded appears to handle 'Vy' and trailing newlines properly in both byte-compiled and un-compiled form. Thank you very much. I have some Latex editing to do soon and almost look forward to seeing what Emacs can do for me. :)
participants (4)
-
Craig Tenney -
Tim Harper -
Vegard Øye -
Štěpán Němec