This package emulates surround.vim by Tim Pope. The functionality is wrapped into a minor mode.
This package uses Evil as its vi layer.
Installation
To enable it through use-package, add the following lines to ~/.emacs
or ~/.emacs.d/init.el
:
(use-package evil-surround
:ensure t
:config
(global-evil-surround-mode 1))
Alternatively, can add the evil-surround.el
file to your load-path and add (require 'evil-surround)
to your init file.
Also, Instead of enabling it globally, you can also enable surround-mode
along a major mode by adding turn-on-surround-mode
to the mode hook.
Usage
Add surrounding
You can surround in visual-state with S<textobject>
or gS<textobject>
.
Or in normal-state with ys<textobject>
or yS<textobject>
.
Change surrounding
You can change a surrounding with cs<old-textobject><new-textobject>
.
Delete surrounding
You can delete a surrounding with ds<textobject>
.
Add new surround pairs
A surround pair is this (trigger char with textual left and right strings):
(?> . ("<" . ">"))
or this (trigger char and calling a function):
(?< . surround-read-tag)
You can add new by adding them to evil-surround-pairs-alist
.
For more information do: C-h v evil-surround-pairs-alist
.
evil-surround-pairs-alist
is a buffer local variable, which means that
you can have different surround pairs in different modes. By default <
is used to insert a tag, in C++ this may not be useful - but inserting
angle brackets is, so you can add this:
(add-hook 'c++-mode-hook (lambda ()
(push '(?< . ("< " . " >")) evil-surround-pairs-alist)))
Don’t worry about having two entries for <
surround will take the
first.
Or in Emacs Lisp modes using ` to enter ` ’ is quite useful, but not
adding a pair of ` (the default behavior if no entry in
evil-surround-pairs-alist
is present), so you can do this:
(add-hook 'emacs-lisp-mode-hook (lambda ()
(push '(?` . ("`" . "'")) evil-surround-pairs-alist)))
without affecting your Markdown surround pairs, where the default is useful.
To change the default evil-surround-pairs-alist
you have to use setq-default
,
for example to remove all default pairs:
(setq-default evil-surround-pairs-alist '())
or to add a pair that surrounds with two ` if you enter ~:
(setq-default evil-surround-pairs-alist
(push '(?~ . ("``" . "``")) evil-surround-pairs-alist))
Add new surround pairs through creation of evil objects
- You can create new evil objects that will be respected by evil-surround. Just use the following code:
;; this macro was copied from here: https://stackoverflow.com/a/22418983/4921402
(defmacro define-and-bind-quoted-text-object (name key start-regex end-regex)
(let ((inner-name (make-symbol (concat "evil-inner-" name)))
(outer-name (make-symbol (concat "evil-a-" name))))
`(progn
(evil-define-text-object ,inner-name (count &optional beg end type)
(evil-select-paren ,start-regex ,end-regex beg end type count nil))
(evil-define-text-object ,outer-name (count &optional beg end type)
(evil-select-paren ,start-regex ,end-regex beg end type count t))
(define-key evil-inner-text-objects-map ,key #',inner-name)
(define-key evil-outer-text-objects-map ,key #',outer-name))))
(define-and-bind-quoted-text-object "pipe" "|" "|" "|")
(define-and-bind-quoted-text-object "slash" "/" "/" "/")
(define-and-bind-quoted-text-object "dollar" "*" "*" "*")
(define-and-bind-quoted-text-object "dollar" "$" "\\$" "\\$") ;; sometimes your have to escape the regex
Add new supported operators
You can add support for new operators by adding them to evil-surround-operator-alist
.
For more information do: C-h v evil-surround-operator-alist
.
By default, surround works with evil-change
and evil-delete
.
To add support for the evil-paredit package,
you need to add evil-paredit-change
and evil-paredit-delete
to evil-surround-operator-alist
, like so:
(add-to-list 'evil-surround-operator-alist
'(evil-paredit-change . change))
(add-to-list 'evil-surround-operator-alist
'(evil-paredit-delete . delete))
Examples
Here are some usage examples (taken from surround.vim):
Press =cs”’= inside
"Hello world!"
to change it to
'Hello world!'
Now press cs'<q>
to change it to
<q>Hello world!</q>
To go full circle, press =cst”= to get
"Hello world!"
To remove the delimiters entirely, press =ds”=.
Hello world!
Now with the cursor on “Hello”, press ysiw]
(iw
is a text object).
[Hello] world!
Let’s make that braces and add some space (use }
instead of {
for no
space): cs]{
{ Hello } world!
Now wrap the entire line in parentheses with yssb
or yss)
.
({ Hello } world!)
Revert to the original text: ds{ds)
Hello world!
Emphasize hello: ysiw<em>
<em>Hello</em> world!
Finally, let’s try out visual mode. Press a capital V (for linewise
visual mode) followed by S<p class
“important”>=.
<p class="important">
<em>Hello</em> world!
</p>
Suppose you want to call a function on your visual selection or a text
object. You can simply press f
instead of the aforementioned keys and
are then prompted for a functionname in the minibuffer, like with the
tags. So with:
"Hello world!"
… after selecting the string, then pressing Sf
, entering print
and
pressing return you would get
print("Hello world!")
FAAQ (frequently actually asked questions)
vs
no longer surround?
Why does This is due to an upstream change in vim-surround
. It happened in this commit. See the
discussion in this pull request for more details.
Contributing
- you are encouraged to test your changes a standard environment with a clean emacs and just the needed plugins
interactively
# open a shell and go to the evil-surround directory, after cloning it
make
make emacs
# now load evil-surround/test/evil-surround-test.el and M-x ert and run the tests
command
# open a shell and go to the evil-surround directory, after cloning it
make
make test
Credits
Credits and many thanks go to Tim Harper, the original mantainer of the package.
LICENSE
GNU General Public License v3
Copyright (C) 2010 - 2017 Tim Harper
Copyright (c) 2018 - 2019 The evil-surround Contributors