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