On 2011-03-01 16:57 +0100, Frank Fischer wrote:
Am Dienstag, 1. März 2011 schrieb Vegard Øye:
When some of those completion-dialogs pops up, the user can keep on typing or use the cursor-keys or whatever to select possible completions. How do you realize that these commands should *not* be recorded although they may look like, e.g., a motion (I just don't know how these packages really work). If this packages inserts text behind point it will drop you in the second case, but then the sequence of keys just does not represent what has been inserted (the sequence may be something like [a b b <down> <down> <up> c d <enter>].
What kind of command it is can only be determined in `post-command-hook', after the command has done all its stuff -- completion or otherwise. `after-change-functions' collect info while the command is executing, and then the hook uses that info to decide.
Another point why I would prefer key-sequence as default in all cases is that sometimes insertion triggers other changes, too, like indentation. I this case repeation of key-sequences does what you want (indent according to where the repeation took place) while direct insertion of text may fail. This may depend, in this example, on whether the additional spaces are inserted just before point.
True. It's just a heuristic, and it probably will have to be supplemented with some hard-coding ("this is an indentation command") as more complex use cases emerge. I don't see a way around the dreaded blacklist -- just ways to (hopefully) make the blacklist shorter.
In fact, is there a way to detect motion of point? Again another pre-/post-command-hook hack or something better? I ask because in some situations a certain motion or sequence of motions will actually change point while in other situations point will left unchanged (I think of motions like "tx" which does not move point if we are right before an x - okay we are in insert mode but again such situations may happen, e.g., end-of-line by leave point unchanged in one situation but when we repeat the keq-sequence elsewhere it would not).
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.
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.
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.
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. 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). -- Vegard