Vimpulse and vim-mode

Frank Fischer frank.fischer at mathematik.tu-chemnitz.de
Tue Mar 1 23:05:05 CET 2011


On Tue, Mar 01, 2011 at 08:42:52PM +0100, Vegard Øye wrote:
> Well, the rule does say that keystrokes are the default
> representation. "tx" will be recorded as keystrokes because it doesn't
> trigger an insertion. A command will only be recorded as insertion if
> it inserts or deletes text /and/ it doesn't do something which cannot
> be represented as an insertion. Otherwise, it's all keystrokes.

Well, if keystrokes are the default and this "linear" stuff is just
the special case, then that's fine for me. I just had the feeling that
you want the linear stuff to be the default.

> > It seems to me that the key-sequence approach is almost always the
> > right way. If there weren't those nasty completion things ... ;)
> 
> I agree. We might be overanalyzing this problem. Maybe the blacklist
> is a tolerable solution after all, because the odd completion command
> is all that needs to be listed.
> 
> >>     (vimpulse-define-operator vimpulse-insert (beg end &optional arg)
> >>       "Insert before point."
> >>       (interactive (list current-prefix-arg))
> >>       ...)
> >
> > Perhaps we could extend the string-variant by further chars
> > understood by define-operator? Would make the stuff more readable.
> 
> Seems like a bit of a job, judging by the length of `interactive's
> docstring. I'm not sure it would be worth the effort.

I would propably use a very special rule like "if the interactive
statement starts with an < and then the next characters up to the
following > are considered to be vim interactive arguments". Something that
does not confuse the rest. Defining an operator with

(define-operator my-op (beg end reg)
  (interactive "<rR>")
 ...)

if <r> means region and <R> means register looks quite nice ;) But
other nice solutions are okay, too. I don't know what the best is, it
was just a suggestion.

> > But I wonder if it is possible to switch to operator-pending, then call
> > read-key-sequence (or something like this), then switch back and
> > continue as before. Of course, before switching one has to read the
> > numeric prefix but this should be possible, I think.
> 
> The problem is handling prefix arguments. If you have two counts, like
> in "2d2w", the common heuristic is to multiply them together,
> effectively giving "d4w". But with Emacs' `digit-argument', it is
> difficult to get "in between" the motion count and the motion and say,
> "But multiply by 2 first!" Hence, `vimpulse-keypress-parser' reads a
> motion and its count without executing them, then the motion count is
> multiplied with the operator count (if any), and finally the motion is
> executed. Each step is disentangled from the others.

Hm, I just thought of replacing the key-parser itself (or large parts
of it) by a simple call to read-key-sequence. It should be easy to
check if the command to be called is indeed digit-argument and in this
case we would not call digit-argument but instead handle the argument
ourselves. Just before calling the final motion (which should be the
first command which is not digit-argument), set prefix-arg to the
appropriate count which is the product of both counts. The motion
won't notice the difference.

> > You use :contract and :expand ... I wonder something like the
> > following would better reflect what we need:
> >
> >    evil:region
> >   "returns BEG and END of the real region covered by motion"
> >
> >    evil:line-region
> >   "returns BEG end END of the lines covered"
> >
> > But I think you have a special use case where the suggestion above
> > does not fit, right? So what do you expect from :expand and
> > :contract, especially, why do you need the inverse transformation?
> > It should be equally easy to store the original pair of BEG and END
> > so the inversion should not be necessary.
> 
> Good question. On the face of it, there doesn't seem to be much use
> for :contract, since you can just remember the previous positions.
> (Indeed, the `line' transformation is irreversible, so in its case you
> /must/ remember them.) The reasons I want contraction are more subtle
> and based on experiences with "gv". How do you save a Visual selection
> for later use? Well, you can use markers to store the boundaries. But
> what boundaries do you store -- the unexpanded ones, or the expanded?
> Now we have two approaches:
> 
>     * Remember the unexpanded buffer positions of point and mark,
>       along with the Visual submode; these three values define the
>       selection. In other words, just put everything exactly where
>       it was the last time.
> 
>     * Remember the /expanded/ positions of point and mark, plus the
>       submode. Contract the positions as you re-enable the selection.
> 
> I call these the "intuitive approach" and the "other approach",
> respectively. As you've guessed by now, the intuitive approach has
> some weaknesses. Since point and mark "expand" to an inclusive
> selection, the largest position is one less than the end of the
> selection. In other words, one of the markers is actually /inside/
> the selection.
> 
> What would happen time and again when I applied something slightly
> destructive on the selection was that the marker would get pushed out
> of it. Then, when I did "gv", the selection would be one character
> larger than before. ("d" is /too/ destructive to demonstrate this,
> while "u"/"U" is at the opposite end of the spectrum since they do
> everything character by character. You need something "in between",
> preferably a command which inserts and deletes here and there --
> like `comment-region'. It's a subtle bug.)
> 
> So what the "other approach" does is to get the markers out of the way
> by expanding them first. That way, a destructive command won't affect
> the markers, since they coincide exactly with the boundaries of the
> text the command is working on. Of course, this approach does require
> the inverse of expansion -- contraction -- afterwards. And in the case
> of `line' you actually cannot contract, so you'll have to fall back on
> remembering the original positions. Still, this solved the problem.

I have to think about this, but currently I'm too tired, so I will
answer tomorrow ;)

> 
> Another thing: is using ":" as a prefix separator good for anything in
> Emacs Lisp? I haven't seen this practice elsewhere; all other Emacs
> packages separate their prefix with a hyphen (as suggested in the
> Emacs Lisp Reference Manual).

It's just personal preference. For me it is logical to separate the
package name visually from the rest by using a different separating
character. There are a few packages out there that do something
similar (e.g., yasnippet uses a /), but you're right, it's unusual. So
just use hyphens, if you prefer, that's fine.

Frank



More information about the implementations-list mailing list