cute-jumper / embrace.el

Add/Change/Delete pairs based on `expand-region', similar to `evil-surround'.
129 stars 11 forks source link
emacs evil-surround expand-region

+TITLE: embrace.el

[[http://melpa.org/#/embrace][file:http://melpa.org/packages/embrace-badge.svg]] [[http://stable.melpa.org/#/embrace][file:http://stable.melpa.org/packages/embrace-badge.svg]]

Add/Change/Delete pairs based on [[https://github.com/magnars/expand-region.el][expand-region]].

For =evil-surround= integration, see [[https://github.com/cute-jumper/evil-embrace.el][evil-embrace]].

For Emacs users who don't like =evil= and thus don't use =evil-surround=, =embrace= provides similar commands that can be found in =evil-surround=. =Evil= is absolutely not required. For =evil-surround= users, =embrace= can make your =evil-surround= commands even better! (Have you noticed that =evil-surround= doesn't work on many custom pairs?)

** Example

It might be a little hard for users who have no experience in =evil= and =evil-surround= to understand what =embrace= can do. So let's give an example to show what =embrace= can do fist. You can look at the following sections to see the meaning of key bindings. In this example, I bind @@html:kbd>@@C-,@@html:</kbd@@ to =embrace-commander=. Assume we have following text in =c-mode= and the cursor position is indicated by ~|~: : fo|o

Press @@html:@@C-, a w '@@html:@@ to add '' to the current word: : 'fo|o'

Press @@html:@@C-, a q {@@html:@@ to add {} to outside of the quotes: : {'fo|o'}

Press @@html:@@C-, c ' "@@html:@@ to change the '' to "": : {"fo|o"}

Press @@html:@@C-, c { t@@html:@@, and then enter the tag: body class="page-body", to change the {} to a tag: : "fo|o"

Press @@html:@@C-, c t f@@html:@@, and enter the function name =bar= to change the tag to a function call: : bar("fo|o")

Press @@html:@@C-, d f@@html:@@ to remove the function call: : "fo|o"

If you're an =evil-surround= user, you might notice that the last command can't be achieved by =evil-surround=. However, it works in =embrace=! And yes, you can find even more examples in which =evil-surround= doesn't work while =embrace= works!

** Screencasts For non =evil-mode= users, use the following settings (they will be explained later): : (global-set-key (kbd "C-,") #'embrace-commander) : (add-hook 'org-mode-hook #'embrace-org-mode-hook)

Open an org-mode file, we can perform the following pair changing:

[[./screencasts/embrace.gif]]

For =evil-mode= users, here is a similar screencast (see [[https://github.com/cute-jumper/evil-embrace.el][evil-embrace]] for more details):

[[https://github.com/cute-jumper/evil-embrace.el/blob/master/screencasts/evil-embrace.gif]]

And we have a friendly help system (Yes, it is based on some simplified code from [[https://github.com/justbur/emacs-which-key][which-key]]):

Help to select a semantic unit:

[[./screencasts/help_unit.png]]

Help to delete a pair:

[[./screencasts/help.png]]

** =embrace-change= and =embrace-delete= These two commands can change and delete the surround pair respectively. For =evil-surround= users, =embrace-change= is similar to =cs= and =embrace-delete= is similar to =ds=.

The surrounding pair is specified by a key, which is very similar to the key used for Vim's text objects. For example, =(= stands for the surrounding pair =(= and =)=, and ={= stands for the surrouding pair, ={= and =}=. The default key mappings are shown below: | Key | Left | right | |-----+---------------------+----------| | ( | "(" | ")" | | ) | "( " | " )" | | { | "{" | "}" | | } | "{ " | " }" | | [ | "[" | "]" | | ] | "[ " | " ]" | | > | "<" | ">" | | " | "\"" | "\"" | | ' | "\'" | "\'" | | t | "" | "" | | f | "func(" | ")" |

Note that for =t= and =f= key, the real content is based on the user's input.

** =embrace-add= This command is similar to =evil-surround='s =ys= command. We need to enter a key for the semantic unit to which we want to add a surrounding pair. The semantic unit is marked by the functions provided by =expand-region=.

Here is the default mapping: | key | mark function | |-----+------------------------| | w | er/mark-word | | s | er/mark-symbol | | d | er/mark-defun | | p | er/mark-outside-pairs | | P | er/mark-inside-pairs | | q | er/mark-outside-quotes | | Q | er/mark-inside-quotes | | . | er/mark-sentence | | h | er/mark-paragraph |

After pressing a key to select the semantic unit, you can press another key to add the surrounding pair, which is the same as =embrace-change= and =embrace-delete=.

** Adding More Surrounding Pairs Use the command =embrace-add-pair= to add a pair: : (embrace-add-pair key left right)

The change is also buffer-local, so wrap it in a hook function: : (add-hook 'LaTeX-mode-hook : (lambda () : (embrace-add-pair ?e "\begin{" "}")))

If you want add something like the =t= key for the tag, you can look at the function =embrace-add-pair-regexp= in the source code, and if you're planning to use =embrace-add-pair-regexp=, you should also use =embrace-build-help= to build the user-friendly help message.

Note that if you're using =embrace-add-pair= to add an existing key, then it will replace the old one.

** Disable Help Message If you find the help message annoying, use the following code to disable it: : (setq embrace-show-help-p nil)

** Example Settings I recommend binding a convenient key for =embrace-commander=. For example, : (global-set-key (kbd "C-,") #'embrace-commander)

We have defined several example hook functions that provide additional key bindings which can be used in different major modes. Right now there are hooks for =LaTeX-mode= and =org-mode=:

=LaTeX-mode=: | Key | Left | Right | |-----+------------+-------| | = | \verb\vert | \vert | | ~ | \texttt{ | } | | / | \emph{ | } | | * | \textbf{ | } |

=org-mode=: | Key | Left | Right | |-----+------------------+-------------------| | = | = | = | | ~ | ~ | ~ | | / | / | / | | | | * | | | | _ | | + | + | + | | k | ~@@html:@@~ | ~@@html:@@~ |

=ruby-mode (and enh-ruby-mode)=: | Key | Left | Right | |-----+------+-------| | d | do | end | | # | #{ | } |

To use them: : (add-hook 'LaTeX-mode-hook 'embrace-LaTeX-mode-hook) : (add-hook 'org-mode-hook 'embrace-org-mode-hook) : (add-hook 'ruby-mode-hook 'embrace-ruby-mode-hook) ;; or 'enh-ruby-mode-hook

The code for the three hooks above (which are defined in =embrace.el=): : (defun embrace-LaTeX-mode-hook () : (dolist (lst '((?= "\verb|" . "|") : (?~ "\texttt{" . "}") : (?/ "\emph{" . "}") : (? "\textbf{" . "}"))) : (embrace-add-pair (car lst) (cadr lst) (cddr lst)))) : (defun embrace-org-mode-hook () : (dolist (lst '((?= "=" . "=") : (?~ "~" . "~") : (?/ "/" . "/") : (? "" . "") : (? "" . "_") : (?+ "+" . "+") : (?k "@@html:@@" . "@@html:@@"))) : (embrace-add-pair (car lst) (cadr lst) (cddr lst)))) : (defun embrace-ruby-mode-hook () : (dolist (lst '((?# "#{" "}") : (?d "do" "end"))) : (embrace-add-pair (car lst) (cadr lst) (caddr lst))))

You can define and use your own hook function similar to the code above.

Welcome to add some settings for more major modes.