On Sat, Jul 24, 2010 at 3:23 PM, Vegard Øye <[email protected]> wrote: > On 2010-07-23 20:46, Tim Harper wrote: > >> I'm not extremely happy with my approach on how I'm looking into the >> delete/change commands. Basically, I'm hijacking them in doing an >> advise (as in defadvice) approach. > > There isn't a perfect way, not even in Vim itself. surround.vim does > this: > > nmap ds <Plug>Dsurround > > Which corresponds to making a "careful" binding in Vimpulse -- that > is, one of these lines: > > (vimpulse-map "ds" 'vimpulse-surround-delete) > (vimpulse-make-careful-binding viper-vi-basic-map "ds" > 'vimpulse-surround-delete) > > Which will execute `vimpulse-surround-delete' when the user hits "ds" > and `vimpulse-delete' when the user hits "d" + any other key than "s". > The fatal flaw with this approach, both in Emacs and Vim, is that the > keystrokes are read /before/ Operator-Pending mode is entered, so the > half-height "operator cursor" is permanently lost. > > Second approach: write a "null motion" (one that returns an empty > range) and bind it to "s" in Operator-Pending mode: > > (defun vimpulse-surround-delete (&optional arg) > (interactive) > ;; Delete surrounding characters > ... > (viper-move-marker-locally 'viper-com-point (point))) > > (define-key vimpulse-operator-basic-map "s" 'vimpulse-surround-delete) > > This will preserve the half-height cursor. The call to > `viper-move-marker-locally' ensures that the starting point is > equivalent to the ending point -- e.g., (vimpulse-delete 45 45) -- > hence no actual deletion takes place. > > Third approach: we could make the function bodies of `vimpulse-delete' > and `vimpulse-delete' contingent on a "cancellation variable". A > pseudo-motion like above could set this to t during its execution to > inhibit the deletion code of `vimpulse-delete', the change code of > `vimpulse-change', and so on. (Conceivably, `vimpulse-range' itself > could cancel further code execution with `keyboard-quit', but this > would probably be noisy.) > > Fourth approach: stay with the delete-or-surround DWIM functions, but > bind them in a separate, toggleable keymap rather than overwriting the > basic bindings. Like this: > > (define-minor-mode surround-mode) > > (vimpulse-define-key 'surround-mode 'vi-state "d" > 'vimpulse-delete-surround-or-delete) > (vimpulse-define-key 'surround-mode 'vi-state "c" > 'vimpulse-change-surround-or-change) > > Then you can enable surround-mode in certain buffers as appropriate, > or turn it into a global minor mode.
Approach 4 does seem pretty good (better than the current behavior of hijacking another keymap). What about option 5: advise vimpulse-range to set the *vimpulse-surrounding* variable to nil before calling it advise vimpulse-delete with an around filter, if *vimpulse-surrounding* is non-nil, then call vimpulse-surround-delete, otherwise invoke as normal with ad-do-it Benefits: * If for some sick reason one decides to remap vimpulse-delete, they can do so with less complexity of having to remap vimpulse-delete-surround-or-delete (maybe dvorak users would want to?) * Multiple plugins can chain in this way. Both the current solution and approach 4 have the limitation that if another plugin wants to do something similar, it will conflict with vimpulse-surround. Drawbacks: * We are depending on side-effect value from a previous function call. This adds complexity and can make things difficult to follow. _______________________________________________ implementations-list mailing list [email protected] https://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list
