-
-
Notifications
You must be signed in to change notification settings - Fork 195
Working with expressions
Smartparens provides multitude of functions to navigate and manipulate balanced expressions (s-expressions, sexps).
In the function lists, after each function in comment is the "recommended" binding, however, no function is bound by default. You should put these into sp-keymap
so they would only be enabled in smartparens-mode
. You can use:
(define-key sp-keymap (kbd "your-key") 'function)
to do the local binding. Note that this has to occur after smartparens-mode
is loaded, otherwise the sp-keymap
variable will be void. See the example configuration for the example of working code of how to set the bindings.
You can use the function sp-use-paredit-bindings
to setup the key bindings to smartparens functions with key bindings of corresponding paredit functions. However, not all functions will get a key binding so if you wish to add the functions from smartparens that are not in paredit you have to bind them manually.
You can use the function sp-use-smartparens-bindings
to setup the key bindings to smartparens functions to the same values as seen in example configuration.
Each function where it makes sense comes with forward and backward version, where the backward version does the same thing as forward but in reverse direction. Therefore, if you only bind the forward version you can still access the backward version using negative-prefix
, by default bound to C--
, M--
and C-M--
. Therefore, if you have sp-kill-sexp
on C-M-k
then using C-M-- C-M-k
will behave the same as calling sp-backward-kill-sexp
.
These functions mostly mirror names of the built-in emacs functions and work in roughly same way, as would be expected by most users. However, if you are experiencing "weird" or unexpected behaviour, check the built-in description with C-h f name-of-function
, where the behaviour and accepted arguments are explained in detail.
For additional tips on how to use these functions in concord, read tips and tricks.
# Arguments and return valuesMost of the provided functions can accept a numeric prefix argument in which case they do the thing that many times or instead of next expression they operate on arg-th expression. The forward versions also accept negative argument, in which case they behave just as the backward versions. In fact, backward versions just call forward ones with negative argument. This means you can also call the backward versions with negative argument, in which case they behave as forward versions. This is useful if you have bound only one of them to a key, then you can use C--
prefix to turn it into "other direction" version.
Some functions accept raw prefix argument C-u
. This always act as "infinity" argument, in a sense that they repeat the thing as much as possible (but within reason). This usually means "until the end of the enclosing list" (instead of unreasonable "until end of file") for functions that can operate inside list (sp-kill-sexp
, sp-select-next-thing
, sp-forward-barf-sexp
, ...). For other functions, like sp-down-sexp
it means "move down to the deepst possible expression", which is the same as calling it with numeric argument "1000" (hence the "infinity" semantics).
Some functions accept raw prefix argument C-u C-u
. This makes the function operate on the enclosing list. Therefore C-u C-u sp-kill-sexp
will kill the list enclosing point (same as doing sp-up-list sp-backward-kill-sexp
).
To see if a function accepts raw prefix arguments, you can read its built-in documentation using C-h f name-of-function
.
When it makes sense, these functions return information about the expression on which they operated most recently. The return value is the same as that of sp-get-sexp
, that is a plist with keywords :beg :end :op :cl :prefix
for beginning of the expression, end of expression, opening and closing delimiter and expression prefix (like quotes or splice (,@
) prefixes in lisp). However, you should never access this structure directly, as it is subject to change. Instead, use the sp-get
macro which can also handle queries for other properties. For a complete description, read the built-in documentation (C-h f sp-get RET
).
For example, (sp-next-sexp 2)
would return the information about 2nd next expression. This, in combination with (save-excursion)
macro can be used to quickly query for information about sexps in your own functions.
Legacy info, before commit 161
# Navigation functionsBefore the redesign of
sp-get-sexp
family of functions, the return format was a simple 4-tuple(beg-of-expr end-of-expr opening-pair closing-pair)
. If you use this in your own code, you should adapt it to the new version usingsp-get
macro to access all the sexp properties.
List of navigation functions:
sp-forward-sexp (&optional arg) ;; C-M-f
sp-backward-sexp (&optional arg) ;; C-M-b
sp-down-sexp (&optional arg) ;; C-M-d
sp-backward-down-sexp (&optional arg) ;; C-M-a
sp-up-sexp (&optional arg) ;; C-M-e
sp-backward-up-sexp (&optional arg) ;; C-M-u
sp-next-sexp (&optional arg) ;; C-M-n
sp-previous-sexp (&optional arg) ;; C-M-p
sp-beginning-of-sexp () ;; C-S-a
sp-end-of-sexp () ;; C-S-d
These functions work pretty much exactly the same as the emacs-built in versions without sp-
prefix, but operate on all user defined strictly balanced expressions. Strictly balanced means that |( [ ) ]
will jump to ( [ |) ]
, not ( [ ) |]
as the default forward-sexp
would.
These functions never signal the "Unbalanced parentheses" scan error and by default jump to the beginning or end of next/previous sexp, which is reasonable behaviour. If there is some special behaviour, it is documented.
If you want to also operate on symbols that are not wrapped, such as (defun >name-of-fun< (arg) nil)
(leq/geq mark the symbol boundary), set sp-navigate-consider-symbols
to t
. Emacs built-in functions forward-sexp
and backward-sexp
recognize these as "expressions". If you set this option to t
, all functions where it makes sense (that is, not unwrapping functions etc.) will consider symbols as balanced expressions. Strings enclosed with "" are also considerd as being one symbol. This option is turned on by default.
Lastly, the navigation with expressions where opening and closing pair is the same is troublesome, as it is impossible to detect the beginning and end without maintaining a count in the whole buffer (where odd occurences would be opening pairs and even occurences closing pairs). Therefore, at the moment, these are not recognized as balanced expressions. If you have an idea for a good heuristic or a method how to implement this, please file an issue with the suggestion.
Here's a quick summary for each navigation function. For the complete info consult the built-in documentation.
-
sp-forward-sexp
- Jump after the next balanced expression. If inside one and there is no forward exp., jump after its closing pair. -
sp-backward-sexp
- Jump before the previous balanced expression. If inside one and there is no previous exp., jump before its opening pair. -
sp-down-sexp
- Jump after the opening pair of next balanced expression. This effectively descends one level down in the "expression hierarchy". If there is no expression to descend to, jump after current expression's opening pair. This can be used to quickly navigate to the beginning of current balanced expression. -
sp-backward-down-sexp
- Jump before the closing pair of previous balanced expression. If there is no expr. to descend to, jump before current expression's closing pair. -
sp-up-sexp
- Jump up one level from the current balanced expression. This means skipping all the enclosed expressions within this and then jumping after the closing pair. For example(if (= a b) | (some call) (some other call))
->(if ...)|
. -
sp-backward-up-sexp
- Jump up backwards one level from the current balanced expressions. This means skipping all the enclosed expressions within this backwards and then jumping before the opening pair. -
sp-next-sexp
- Jump to the beginning of following balanced expression. If there is no following expression on the current level, jump one level up backward, effectively doingsp-backward-up-sexp
. -
sp-previous-sexp
- Jump to the end of the previous balanced expression. If there is no previous expression on the current level, jupm one level up forward, effectively doingsp-up-sexp
. -
sp-beginning-of-sexp
- Jump to the beginning of current sexp, that is after the opening delimiter. -
sp-end-of-sexp
- Jump to the end of current sexp, that is before the closing delimiter.
Some functions, especially slurp/barf functions are inspired by paredit package and work roughly the same. However, they can accept optional prefix arguments to modify their behaviour.
List of manipulation functions:
sp-kill-sexp (&optional arg) ;; C-M-k
sp-backward-kill-sexp (&optional arg) ;; C-- C-M-k
sp-unwrap-sexp (&optional arg) ;; M-<delete>
sp-backward-unwrap-sexp (&optional arg) ;; M-<backspace>
sp-splice-sexp (&optional arg) ;; M-D
sp-splice-sexp-killing-forward (&optional arg) ;; C-M-<delete>
sp-splice-sexp-killing-backward (&optional arg) ;; C-M-<backspace>
sp-splice-sexp-killing-around (&optional arg) ;; C-S-<backspace>
sp-split-sexp () ;; none
sp-forward-slurp-sexp (&optional arg) ;; C-<right>
sp-forward-barf-sexp (&optional arg) ;; C-<left>
sp-backward-slurp-sexp (&optional arg) ;; C-M-<left>
sp-backward-barf-sexp (&optional arg) ;; C-M-<right>
sp-select-next-thing (&optional arg) ;; C-M-]
sp-select-previous-thing (&optional arg) ;; C-[
sp-select-next-thing-exchange (&optional arg) ;; C-]
sp-select-previous-thing-exchange (&optional arg) ;; C-- C-]
Here's a quick summary for each manipulation function. For the complete info consult the built-in documentation.
-
sp-kill-sexp
- Kill the next balanced expression. If point is inside one and there's no following expression, kill the enclosing expression instead. -
sp-backward-kill-sexp
- Kill the previous balanced expression. -
sp-unwrap-sexp
- Remove the wrapping pair from the following expression. Following expression is one returned bysp-forward-sexp
. -
sp-backward-unwrap-sexp
- Remove the wrapping pair from the previous expression. Previous expression is one returned bysp-backward-sexp
. -
sp-splice-sexp
- Remove the wrapping pair from this expression. With arg, do this on Nth enclosing expression as if first navigated withsp-up-sexp
. -
sp-splice-sexp-killing-forward
- Remove the wrapping pair from this expression and kill everything from the end of expression before(point)
to end of this expression. -
sp-splice-sexp-killing-backward
- Remove the wrapping pair from this expression and kill everything from the beginning of this expression to beginning of expression after(point)
. -
sp-splice-sexp-killing-around
- Remove the wrapping pair from this expression and kill everything inside save for ARG next expressions. -
sp-split-sexp
- Split the current list using the enclosing delimiters. -
sp-forward-slurp-sexp
- Extend the current list by one balanced expression or symbol by moving the closing delimiter. -
sp-forward-barf-sexp
- Contract the current list by one balanced expression or symbol by moving the closing delimiter. -
sp-backward-slurp-sexp
- Extend the current list by one balanced expression or symbol by moving the opening delimiter. -
sp-backward-barf-sexp
- Contract the current list by one balanced expression or symbol by moving the opening delimiter. -
sp-select-next-thing
- Select next balanced expression as returned bysp-forward-sexp
. Examples of usage: Can be cleverly used with wrapping features, for example if you want to wrap next expression in additional pair of parens. It can also be used to select expressions followed byM-w
to copy to ring but not kill. -
sp-select-previous-thing
- Select previous balanced expression as returned bysp-backward-sexp
. -
sp-select-next-thing-exchange
- Same assp-select-next-thing
but executeexchange-point-and-mark
afterwards. -
sp-select-previous-thing-exchange
- Same assp-select-previous-thing
but executeexchange-point-and-mark
afterwards.