Skip to content

Paredit and smartparens

Matus Goljer edited this page Aug 24, 2013 · 9 revisions
  1. Random differences
  2. Killing
  3. Movement and navigation
  4. Depth changing commands
  5. Barfage and slurpage
  6. Misc

Smartparens and paredit share some functionality. This article is meant to explain some key differences between the two. It is of interest mostly to the users of paredit.

In each section about specific group of commands we will list the paredit function and the corresponding smartparens function together with the differences. I will omit the backward versions since they work in the exact analogous manner.

All the smartparens functions work with all the user-defined pairs too, not just the built-in (), [], {} and "". However, currently the pairs with the same opening and closing pair (with the exception of string delimiters) are not recognized. That means that \{\} works as balanced pair delimiter but $$ does not. The reasons are described in navigation functions.

Note: from commit ~297, support for "string" pairs is also added as an experimental feature (string pairs are pairs were opening and closing delimiter is the same, like $$ in LaTeX). To make smartparens recognize these pairs, you need to enable this feature for the given major mode by customizing sp-navigate-consider-stringlike-sexp.

Only the commands bound by default in paredit are listed. There are some other commands not bound that also have SP counterparts. You can find the complete list of SP commands in working with expressions. If I didn't miss anything, all the unlisted paredit functions are replicated and enhanced much in the same spirit (accept numeric arguments, special arguments, type objects etc.)

# Random differences

In general, smartparens is much less strict about the "balancedness" of the buffer and it usually allows you to delete whatever you please. However, there are settings you can change to have it behave more like paredit.

  • In smartparens, by default when you try to delete a delimiter it will be deleted, not skipped over like with paredit. You can change this behaviour by binding sp-delete-char, sp-kill-symbol and their backward variants to whatever keys you normally use for this purpose. Since revision 446 you can enable minor mode smartparens-strict-mode to automatically remap these commands (SP in the modeline changes to SP/s if strict mode is on). Note: to fall back to the regular behaviour SP uses C-0 (zero) prefix, not C-u prefix like paredit!
  • Check the variables sp-autoinsert-if-followed-by-same and sp-autoinsert-if-followed-by-word and their customize options. Pick whatever mode you prefer. This is a global setting.
  • SP doesn't bind ) key to the "jump out of sexp" command, instead it just inserts the ) into the buffer. Same for ], } etc. You can bind sp-up-sexp there if you want. Also read the description of this function for more info.
  • The C-k command that kills the line really kills the line in SP. In paredit, it tries to kill the next balanced expression, or kill the line in a way that won't break the balance. If you want, you can bind sp-kill-sexp to C-k. Personally, I like to have both versions and I bind sp-kill-sexp to C-M-k. Check the docs for sp-kill-sexp, it has many modes of operation.

Smartparens recognizes the pairs in comments and strings as well. If the point is outside a string or comment, these are ignored and skipped over. However, if point is inside string or comment the expressions there are recognized normally.

# Killing

This was mostly mentioned in the section above, but for completeness here's the list:

paredit-forward-delete   =   sp-delete-char

Work basically the same way, skipping over the delimiter to keep the structure balanced. If the sexp is empty, kill both ends. SP functions accept numeric prefix argument.

paredit-kill   =   sp-kill-sexp

paredit-kill operates on "line" basis, or always tries to kill as much as possible. This is roughly equivalent to calling sp-kill-sexp with prefix C-u. By default, sp-kill-sexp only kills the next balanced expression after point. sp-kill-sexp also accepts numeric prefix arguments.

paredit-forward-kill-word   =   sp-kill-symbol

sp-kill-symbol kills the entire symbol, not the words. A word variant might be implemented later.

Smartparens also implements sp-copy-sexp that does the same thing as sp-kill-sexp but without removing text from the buffer (that is, only copy to kill-ring).

# Movement and navigation
paredit-forward   =   sp-forward-sexp

Moves forward one sexp. Both functions call "up list" if at the end of the current list. SP functions accept numeric prefix.

paredit-forward-down   =   sp-down-sexp

paredit-forward-down can descend one level down in hierarchy, correctly handling strings. Smartparens currently doesn't handle descending into strings. Both can accept numeric argument to descend that many times. Smartparens accept additional raw prefix arguments C-u and C-u C-u, see the description. Paredit function throws an error if there is no expression to which it is possible to descend. Smartparens in this case jumps to the front of the current list, which is reasonable. After all, descending to "current" list means going to the front.

paredit-forward-up   =   sp-up-sexp

paredit-forward-up is symmetrical to paredit-forward-up. sp-up-sexp can also re-indent the expression automatically (like paredit )) and close unbalanced expressions. Both can accept numeric prefix argument.

Functions without paredit counterpart:

sp-next-sexp (&optional arg)
sp-beginning-of-sexp (&optional arg)

See navigation functions.

# Depth changing commands
paredit-wrap-round

Wraps the next expression in additional pair of (). Smartparens doesn't have corresponding functions. You can instead enable wrapping for any pair you define using the :bind argument in sp-local-pair definition.

paredit-splice-sexp   =   sp-splice-sexp
paredit-splice-sexp-killing-backward   =   sp-splice-sexp-killing-backward
paredit-splice-sexp-killing-forward   =   sp-splice-sexp-killing-forward
paredit-raise-sexp   =   sp-raise-sexp

These functions work in principle the same, but the way the prefix arguments are handled is different. You can read the built-in docs to see the difference. sp-raise-sexp also provides some new functionality.

# Barfage and slurpage
paredit-forward-slurp-sexp   =   sp-forward-slurp-sexp

The basic function is the same. SP version can also accept numeric prefix argument to slurp that many items. It also accepts C-u prefix to slurp "all the way" to the end of enclosing list. If slurping from string, paredit escapes the string to-be-added, smartparens instead joins the strings together (much more common operation).

paredit-forward-barf-sexp   =   sp-forward-barf-sexp

The basic function is the same. SP version can also accept numeric prefix or C-u to barf "all the way", that is everything from point forward. Can also barf out of strings.

Smartparens also implements useful variants of these:

sp-absorb-sexp (&optional arg)
sp-emit-sexp (&optional arg)
sp-extract-before-sexp (&optional arg)
sp-extract-after-sexp (&optional arg)

See working with expressions.

# Misc
paredit-split-sexp   =   sp-split-sexp

Same

paredit-join-sexps   =   sp-join-sexp

In basic variant works the same. SP version can accept numeric prefix to join that many expressions (if they are all of the same type).