insert a symbol

Frank Fischer frank.fischer at mathematik.tu-chemnitz.de
Wed May 30 09:57:50 CEST 2012


You guys always find strange situations I've never thought off ... ;)

On Tue, May 29, 2012 at 11:41:32AM -0400, York Zhao wrote:
> "\ <char>" is a good tip for inputing one char without entering insert mode,
> however, it is not dot repeatable. I used to have my own function bound to SPC
> to insert one char and was repeatable, but I'm now binding SPC to ace-jump which
> I found to be even more useful. Is it possible to make "\<command>" repeatable?

No, not easily. There are two reasons for this. The first one is that
Emacs state is not repeatable by intention. When Evil switches to
Emacs state, then evil is essentially turned off (as far as it could
be). This means the repeat system ignores all commands in Emacs state
completely. That's because Emacs state is, well, plain Emacs, and it
is very difficult to do repeat-recording right if there is no
distinction between different states like normal state and insert
state. Furthermore almost all commands active in Emacs state are
non-Evil commands, which makes it even more difficult (they usually do
not carry appropriate :repeat attributes). Furthermore the one-shot
Emacs state, i.e., the command `evil-execute-in-emacs-state',
essentially simply switches to Emacs state and installs a
post-command-hook that returns to the previous state after the next
command. So there is no easy way for the repeat system to distinguish
the one-shot emacs state from the "real" emacs state.

The second problem is that the repeat system relies on
post-command-hook, too, in this interferes easily with the
post-command-hook of `evil-execute-in-emacs-state'.

A compromise could be to use insert-state instead of emacs-state. Both
states are almost equivalent except for the repeat-recording and a few
key-bindings (especially the ESC key) in `evil-insert-state-map' (In
fact, in almost all situations insert state could be used whenever
emacs state is desired). Still, the post-command-problem needs to be
respected. The following command can be used (highly untested!!!) to
execute a single command in insert state (it's almost equivalent to
`evil-execute-in-emacs-state' except for the two lines dealing with
the repeat system).

(evil-define-command evil-execute-in-insert-state (&optional arg)
  "Execute the next command in Insert state."
  (cond
   ((called-interactively-p 'any)
	(add-hook 'post-command-hook #'evil-execute-in-insert-state t)
	(evil-insert 1)
	(evil-echo "Switched to Insert state for the next command ..."))
   ((not (eq this-command #'evil-execute-in-insert-state))
	(remove-hook 'post-command-hook 'evil-execute-in-insert-state)
	(evil-change-to-previous-state)
    ;; ensure the command is recorded if we return to normal state
	(when (evil-normal-state-p)
	  (evil-repeat-stop)))))

(define-key evil-normal-state-map "\\" 'evil-execute-in-insert-state)
                                        
One could also clear `evil-insert-state-map' temporarily to make
insert-state in this special situation even more like emacs state.

An alternative could be to implement `evil-execute-in-insert-state' or
`evil-execute-in-emacs-state' by directly reading the next command
with `read-key-sequence' and to call the appropriate binding directly, i.e., something like

(evil-define-command evil-execute-in-emacs state ()
  (let (evil-local-mode)
    (let ((key (read-key-sequence "")))
       ...
       (call-interactively (key-binding key))
       ...
       )))

This could probably be much more robust (no post-command-hook magic
necessary), but I've never thought of this (there are certainly a lot
of other problems with this approach).

Frank




More information about the implementations-list mailing list