emacs-evil / evil-surround

you will be surrounded (surround.vim for evil, the extensible vi layer)
Other
627 stars 60 forks source link

vim-sandwich style bindings #209

Closed aleksandersumowski closed 6 months ago

aleksandersumowski commented 6 months ago

Is there a way to redefine the bindings to be vim-sandwich style, ie: overtake s key as key sequence trigger and use:

more detailed examples: https://github.com/machakann/vim-sandwich

tomdl89 commented 6 months ago

Hi @aleksandersumowski it's not trivial to do in a generic way, but I think I've got the functionality you want working with the following elisp:

(evil-define-command evil-sandwich (char)
  (interactive (evil-surround-input-char))
  (call-interactively
   (pcase char
     (?a #'evil-surround-region)
     (?r #'evil-surround-change)
     (?d #'evil-surround-delete))))

(evil-define-key 'normal evil-surround-mode-map "s" 'evil-sandwich)

Lemme know if that works for you.

tomdl89 commented 6 months ago

Assuming this fixes. Feel free to reopen if not.

aleksandersumowski commented 6 months ago

I'm still strugling to make this keybinding work in Doom Emacs. The binding remains bound to evil-snipe. But I guess thats outside the scope of evil surround 🤷

tomdl89 commented 6 months ago

I don't use Doom or evil-snipe, but having looked at the readme, I think this would fix that problem:

(evil-define-key '(normal motion) evil-snipe-local-mode-map "s" nil)

and then define whatever key you want to use instead in evil-snipe-local-mode-map and you'll be fine.

aleksandersumowski commented 6 months ago

that has worked, but now s runs the command evil-substitute (found in evil-normal-state-map), which is an interactive native-compiled Lisp function in ‘evil-commands.el’.

There should be a way to simply override a mapping ...

aleksandersumowski commented 6 months ago

wait, wouldn't this only work if I'm already in evil-surround-mode? (evil-define-key 'normal evil-surround-mode-map "s" 'evil-sandwich)

tomdl89 commented 6 months ago

Sorry to be unclear. What I was suggesting was to put something like this in your config:

(evil-define-command evil-sandwich...)

(evil-define-key '(normal motion) evil-snipe-local-mode-map "s" nil)
(evil-define-key 'normal evil-surround-mode-map "s" 'evil-sandwich)

Because it's quite clear. You can indeed avoid binding "s" to nil in evil-snipe-local-mode-map, by quoting evil-surround-map like so:

(evil-define-command evil-sandwich...)

(evil-define-key 'normal 'evil-surround-mode-map "s" 'evil-sandwich)

But that very subtle difference (just the ') is too easy to miss imo, so I prefer unbinding beforehand, as above. That's up to you.

WRT

wait, wouldn't this only work if I'm already in evil-surround-mode?

The keybinding will only work if evil-surround-mode is enabled. But defining the key can be done before/after it is enabled. Modes being on or off is a bit of a confusing concept, as the functions are all available either way, as long as they are loaded. If you want to use evil-sandwich without evil-surround being enabled, bind it in another keymap.