mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-17 c4001ccd1864293b64aa37d83a9d9457eb875e70
commit | author | age
5cb5f7 1 ;;; smartparens.el --- Automatic insertion, wrapping and paredit-like navigation with user defined pairs. -*- lexical-binding: t -*-
C 2
3 ;; Copyright (C) 2012-2016 Matus Goljer
4
5 ;; Author: Matus Goljer <matus.goljer@gmail.com>
6 ;; Maintainer: Matus Goljer <matus.goljer@gmail.com>
7 ;; Created: 17 Nov 2012
8 ;; Keywords: abbrev convenience editing
9 ;; URL: https://github.com/Fuco1/smartparens
10
11 ;; This file is not part of GNU Emacs.
12
13 ;;; License:
14
15 ;; This file is part of Smartparens.
16
17 ;; Smartparens is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation, either version 3 of the License, or
20 ;; (at your option) any later version.
21
22 ;; Smartparens is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 ;; GNU General Public License for more details.
26
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with Smartparens.  If not, see <http://www.gnu.org/licenses/>.
29
30 ;;; Commentary:
31
32 ;; Smartparens is minor mode for Emacs that deals with parens pairs
33 ;; and tries to be smart about it.  It started as a unification effort
34 ;; to combine functionality of several existing packages in a single,
35 ;; compatible and extensible way to deal with parentheses, delimiters,
36 ;; tags and the like.  Some of these packages include autopair,
37 ;; textmate, wrap-region, electric-pair-mode, paredit and others.  With
38 ;; the basic features found in other packages it also brings many
39 ;; improvements as well as completely new features.
40
41 ;; For a basic overview, see github readme at
42 ;; https://github.com/Fuco1/smartparens
43
44 ;; For the complete documentation visit the documentation wiki located
45 ;; at https://github.com/Fuco1/smartparens/wiki
46
47 ;; If you like this project, you can donate here:
48 ;; https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CEYP5YVHDRX8C
49
50 ;;; Code:
51
52 (eval-when-compile
53   (require 'subr-x) ; for `string-trim'
54   (require 'cl-lib))
55
56 (require 'dash)
57 (require 'thingatpt)
58 (require 'help-mode) ;; for help-xref-following #85
59
60 (declare-function cua-replace-region "cua-base") ; FIXME: remove this when we drop support for old emacs
61 (declare-function cua-delete-region "cua-base")
62 (declare-function cua--fallback "cua-base")
63 (declare-function package-version-join "package")
64 (declare-function package-desc-version "package")
65
66 (declare-function subword-kill "subword")
67 (declare-function subword-forward "subword")
68 (declare-function subword-backward "subword")
69
70 (declare-function hungry-delete-backward "hungry-delete")
71 (declare-function hungry-delete-forward "hungry-delete")
72
73 (declare-function evil-get-register "evil-common")
74 (declare-function evil-set-register "evil-common")
75 (eval-when-compile
76   (defvar evil-this-register)
77   (defvar package-alist)
78   (defvar sp-autoskip-closing-pair)
79   (defvar sp-show-enclosing-pair-commands)
80   (defvar show-smartparens-mode))
81
82
83 ;;; backport for older emacsen
84
85 ;; introduced in 24.3
86 (unless (fboundp 'defvar-local)
87   (defmacro defvar-local (var val &optional docstring)
88     "Define VAR as a buffer-local variable with default value VAL.
89 Like `defvar' but additionally marks the variable as being automatically
90 buffer-local wherever it is set."
91     (declare (debug defvar) (doc-string 3))
92     ;; Can't use backquote here, it's too early in the bootstrap.
93     (list 'progn (list 'defvar var val docstring)
94           (list 'make-variable-buffer-local (list 'quote var)))))
95
96 ;;;###autoload
97 (defun sp-cheat-sheet (&optional arg)
98   "Generate a cheat sheet of all the smartparens interactive functions.
99
100 Without a prefix argument, print only the short documentation and examples.
101
102 With non-nil prefix argument ARG, show the full documentation for each function.
103
104 You can follow the links to the function or variable help page.
105 To get back to the full list, use \\[help-go-back].
106
107 You can use `beginning-of-defun' and `end-of-defun' to jump to
108 the previous/next entry.
109
110 Examples are fontified using the `font-lock-string-face' for
111 better orientation."
112   (interactive "P")
113   (setq arg (not arg))
114   (let ((do-not-display '(
115                           smartparens-mode
116                           smartparens-global-mode
117                           turn-on-smartparens-mode
118                           turn-off-smartparens-mode
119                           sp-wrap-cancel
120                           sp-remove-active-pair-overlay
121                           sp-splice-sexp-killing-around ;; is aliased to `sp-raise-sexp'
122                           show-smartparens-mode
123                           show-smartparens-global-mode
124                           turn-on-show-smartparens-mode
125                           turn-off-show-smartparens-mode
126                           ))
127         (do-not-display-with-arg '(
128                                    sp-use-paredit-bindings
129                                    sp-use-smartparens-bindings
130                                    ))
131         (commands (cl-loop for i in (cdr (assoc-string (file-truename (locate-library "smartparens")) load-history))
132                            if (and (consp i) (eq (car i) 'defun) (commandp (cdr i)))
133                            collect (cdr i))))
134     (with-current-buffer (get-buffer-create "*Smartparens cheat sheet*")
135       (let ((standard-output (current-buffer))
136             (help-xref-following t))
137         (read-only-mode -1)
138         (erase-buffer)
139         (help-mode)
140         (smartparens-mode 1)
141         (help-setup-xref (list #'sp-cheat-sheet)
142                          (called-interactively-p 'interactive))
143         (read-only-mode -1)
144         (--each (--remove (or (memq it do-not-display)
145                               (and arg (memq it do-not-display-with-arg)))
146                           commands)
147           (unless (equal (symbol-name it) "advice-compilation")
148             (let ((start (point)) kill-from)
149               (insert (propertize (symbol-name it) 'face 'font-lock-function-name-face))
150               (insert " is ")
151               (describe-function-1 it)
152               (save-excursion
153                 (when arg
154                   (goto-char start)
155                   (forward-paragraph 1)
156                   (forward-line 1)
157                   (if (looking-at "^It is bound")
158                       (forward-paragraph 2)
159                     (forward-paragraph 1))
160                   (setq kill-from (point))
161                   (when (re-search-forward "^Examples:" nil t)
162                     (delete-region kill-from
163                                    (save-excursion
164                                      (forward-line 1)
165                                      (point))))))
166               (insert (propertize (concat
167                                    "\n\n"
168                                    (make-string 72 ?―)
169                                    "\n\n") 'face 'font-lock-function-name-face)))))
170         (goto-char (point-min))
171         (while (re-search-forward "\\(->\\|​\\)" nil t)
172           (let ((thing (bounds-of-thing-at-point 'line)))
173             (put-text-property (car thing) (cdr thing) 'face 'font-lock-string-face)))
174         (goto-char (point-min))
175         (while (re-search-forward "|" nil t)
176           (put-text-property (1- (point)) (point) 'face 'font-lock-warning-face))
177         (goto-char (point-min))
178         (while (re-search-forward "^It is bound to \\(.*?\\)\\." nil t)
179           (put-text-property (match-beginning 1) (match-end 1) 'face 'font-lock-keyword-face))
180         (goto-char (point-min))
181         (while (re-search-forward ";;.*?$" nil t)
182           (put-text-property (match-beginning 0) (match-end 0) 'face 'font-lock-comment-face))
183         (help-make-xrefs)
184         (goto-char (point-min))))
185     (pop-to-buffer "*Smartparens cheat sheet*")))
186
187 (defun sp-describe-system (starterkit)
188   "Describe user's system.
189
190 The output of this function can be used in bug reports."
191   (interactive
192    (list (completing-read "Starterkit/Distribution used: "
193                           (list
194                            "Spacemacs"
195                            "Evil"
196                            "Vanilla"
197                            ))))
198   (let ((text (format "- `smartparens` version: %s
199 - Active `major-mode`: `%s`
200 - Smartparens strict mode: %s
201 - Emacs version (`M-x emacs-version`): %s
202 - Starterkit/Distribution: %s
203 - OS: %s"
204                       (--if-let (cadr (assoc 'smartparens package-alist))
205                           (package-version-join (package-desc-version it))
206                         "<Please specify manually>")
207                       (symbol-name major-mode)
208                       (bound-and-true-p smartparens-strict-mode)
209                       (replace-regexp-in-string "\n" "" (emacs-version))
210                       starterkit
211                       (symbol-name system-type))))
212     (pop-to-buffer
213      (with-current-buffer (get-buffer-create "*sp-describe-system*")
214        (erase-buffer)
215        (insert "The content of the buffer underneath the line was
216 copied to your clipboard.  You can also edit it in this buffer
217 and then copy the results manually.
218 ------------------------------------------------
219 ")
220        (insert text)
221        (current-buffer)))
222     (kill-new text)))
223
224
225 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
226 ;; Variables
227
228 (defvar-local sp-forward-bound-fn nil
229   "Function to restrict the forward search")
230
231 (defvar-local sp-backward-bound-fn nil
232   "Function to restrict the backward search")
233
234 (defun sp--get-forward-bound ()
235   "Get the bound to limit the forward search for looking for pairs.
236
237 If it returns nil, the original bound passed to the search
238 function will be considered."
239   (and sp-forward-bound-fn (funcall sp-forward-bound-fn)))
240
241 (defun sp--get-backward-bound ()
242   "Get the bound to limit the backward search for looking for pairs.
243
244 If it returns nil, the original bound passed to the search
245 function will be considered."
246   (and sp-backward-bound-fn (funcall sp-backward-bound-fn)))
247
248
249 ;;;###autoload
250 (defvar smartparens-mode-map (make-sparse-keymap)
251   "Keymap used for `smartparens-mode'.")
252 (defvaralias 'sp-keymap 'smartparens-mode-map)
253 (make-obsolete-variable 'sp-keymap 'smartparens-mode-map "2015-01-01")
254
255 (defvar sp-paredit-bindings '(
256                               ("C-M-f" . sp-forward-sexp) ;; navigation
257                               ("C-M-b" . sp-backward-sexp)
258                               ("C-M-u" . sp-backward-up-sexp)
259                               ("C-M-d" . sp-down-sexp)
260                               ("C-M-p" . sp-backward-down-sexp)
261                               ("C-M-n" . sp-up-sexp)
262                               ("M-s" . sp-splice-sexp) ;; depth-changing commands
263                               ("M-<up>" . sp-splice-sexp-killing-backward)
264                               ("M-<down>" . sp-splice-sexp-killing-forward)
265                               ("M-r" . sp-splice-sexp-killing-around)
266                               ("M-(" . sp-wrap-round)
267                               ("C-)" . sp-forward-slurp-sexp) ;; barf/slurp
268                               ("C-<right>" . sp-forward-slurp-sexp)
269                               ("C-}" . sp-forward-barf-sexp)
270                               ("C-<left>" . sp-forward-barf-sexp)
271                               ("C-(" . sp-backward-slurp-sexp)
272                               ("C-M-<left>" . sp-backward-slurp-sexp)
273                               ("C-{" . sp-backward-barf-sexp)
274                               ("C-M-<right>" . sp-backward-barf-sexp)
275                               ("M-S" . sp-split-sexp) ;; misc
276                               ("M-j" . sp-join-sexp)
277                               ("M-?" . sp-convolute-sexp)
278                               )
279   "Paredit inspired bindings.
280
281 Alist containing the default paredit bindings to corresponding
282 smartparens functions.")
283
284 (defun sp--populate-keymap (bindings)
285   "Populates the `smartparens-mode-map' from the BINDINGS alist."
286   (--each bindings
287     (define-key smartparens-mode-map (read-kbd-macro (car it)) (cdr it))))
288
289 ;;;###autoload
290 (defun sp-use-paredit-bindings ()
291   "Initiate `smartparens-mode-map' with `sp-paredit-bindings'."
292   (interactive)
293   (sp--populate-keymap sp-paredit-bindings))
294
295 (defvar sp-smartparens-bindings '(
296                                   ("C-M-f" . sp-forward-sexp)
297                                   ("C-M-b" . sp-backward-sexp)
298                                   ("C-M-d" . sp-down-sexp)
299                                   ("C-M-a" . sp-backward-down-sexp)
300                                   ("C-S-d" . sp-beginning-of-sexp)
301                                   ("C-S-a" . sp-end-of-sexp)
302                                   ("C-M-e" . sp-up-sexp)
303                                   ("C-M-u" . sp-backward-up-sexp)
304                                   ("C-M-n" . sp-next-sexp)
305                                   ("C-M-p" . sp-previous-sexp)
306                                   ("C-M-k" . sp-kill-sexp)
307                                   ("C-M-w" . sp-copy-sexp)
308                                   ("M-<delete>" . sp-unwrap-sexp)
309                                   ("M-<backspace>" . sp-backward-unwrap-sexp)
310                                   ("C-<right>" . sp-forward-slurp-sexp)
311                                   ("C-<left>" . sp-forward-barf-sexp)
312                                   ("C-M-<left>" . sp-backward-slurp-sexp)
313                                   ("C-M-<right>" . sp-backward-barf-sexp)
314                                   ("M-D" . sp-splice-sexp)
315                                   ("C-M-<delete>" . sp-splice-sexp-killing-forward)
316                                   ("C-M-<backspace>" . sp-splice-sexp-killing-backward)
317                                   ("C-S-<backspace>" . sp-splice-sexp-killing-around)
318                                   ("C-]" . sp-select-next-thing-exchange)
319                                   ("C-M-]" . sp-select-next-thing)
320                                   ("C-M-SPC" . sp-mark-sexp)
321                                   ("M-F" . sp-forward-symbol)
322                                   ("M-B" . sp-backward-symbol)
323                                   )
324   "Alist containing the default smartparens bindings.")
325
326 ;;;###autoload
327 (defun sp-use-smartparens-bindings ()
328   "Initiate `smartparens-mode-map' with `sp-smartparens-bindings'."
329   (interactive)
330   (sp--populate-keymap sp-smartparens-bindings))
331
332 (defun sp--set-base-key-bindings (&optional symbol value)
333   "Set up the default keymap based on `sp-base-key-bindings'.
334
335 SYMBOL is the symbol being set, that is `sp-base-key-bindings'.
336
337 VALUE is the saved value (as a symbol), can be one of:
338 - sp
339 - paredit
340
341 This function is also used as a setter for this customize value."
342   (when symbol (set-default symbol value))
343   (cond
344    ((eq value 'sp)
345     (sp-use-smartparens-bindings))
346    ((eq value 'paredit)
347     (sp-use-paredit-bindings))))
348
349 (defun sp--update-override-key-bindings (&optional symbol value)
350   "Override the key bindings with values from `sp-override-key-bindings'.
351
352 SYMBOL is `sp-override-key-bindings', VALUE is the value being set.
353
354 This function is also used as a setter for this customize value."
355   (when symbol (set-default symbol value))
356   ;; this also needs to reload the base set, if any is present.
357   (sp--set-base-key-bindings)
358   (sp--populate-keymap value))
359
360 (defcustom sp-base-key-bindings nil
361   "A default set of key bindings for commands provided by smartparens.
362
363 Paredit binding adds the bindings in `sp-paredit-bindings' to the
364 corresponding smartparens commands.  It does not add bindings to
365 any other commands, or commands that do not have a paredit
366 counterpart.
367
368 Smartparens binding adds the bindings in
369 `sp-smartparens-bindings' to most common smartparens commands.
370 These are somewhat inspired by paredit, but in many cases differ.
371
372 Note that neither \"paredit\" nor \"smartparens\" bindings add a
373 binding for all the provided commands."
374   :type '(radio
375           (const :tag "Don't use any default set of bindings" nil)
376           (const :tag "Use smartparens set of bindings" sp)
377           (const :tag "Use paredit set of bindings" paredit))
378   :set 'sp--set-base-key-bindings
379   :group 'smartparens)
380
381 (defcustom sp-override-key-bindings nil
382   "An alist of bindings and commands that should override the base key set.
383
384 If you wish to override a binding from the base set, set the
385 value for the binding to the `kbd' recognizable string constant
386 and command to the command symbol you wish to bind there.
387
388 If you wish to disable a binding from the base set, set the value
389 for the command to nil.
390
391 Examples:
392  (\"C-M-f\" . sp-forward-sexp)
393  (\"C-<right>\" . nil)
394
395 See `sp-base-key-bindings'."
396   :type '(alist
397           :key-type string
398           :value-type symbol)
399   :set 'sp--update-override-key-bindings
400   :group 'smartparens)
401
402 (defvar sp-escape-char nil
403   "Character used to escape quotes inside strings.")
404 (make-variable-buffer-local 'sp-escape-char)
405
406 (defvar sp-comment-char nil
407   "Character used to start comments.")
408 (make-variable-buffer-local 'sp-comment-char)
409
410 (defvar sp-pair-list nil
411   "List of pairs for autoinsertion or wrapping.
412
413 Maximum length of opening or closing pair is
414 `sp-max-pair-length' characters.")
415 (make-variable-buffer-local 'sp-pair-list)
416
417 (defvar sp-local-pairs nil
418   "List of pair definitions used for current buffer.")
419 (make-variable-buffer-local 'sp-local-pairs)
420
421 (defvar sp-last-operation nil
422   "Symbol holding the last successful operation.")
423 (make-variable-buffer-local 'sp-last-operation)
424
425 (cl-defstruct sp-state
426   "Smartparens state for the current buffer."
427   ;; A "counter" to track delayed hook.  When a pair is inserted, a
428   ;; cons of the form (:next . pair) is stored.  On the next
429   ;; (immediately after insertion) invocation of post-command-hook, it
430   ;; is changed to (:this . pair).  When the `car' is :this, the
431   ;; post-command-hook checks the delayed hooks for `pair' and
432   ;; executes them, then reset the "counter".
433   delayed-hook
434   ;; TODO
435   delayed-insertion
436   ;; The last point checked by sp--syntax-ppss and its result, used for
437   ;; memoization
438   last-syntax-ppss-point ;; a list (point point-min point-max)
439   last-syntax-ppss-result
440   ;; Value of `sp-pair-list' for this buffer.  Note that this might
441   ;; differ from `sp-pair-list' which is often changed by dynamic
442   ;; binding
443   pair-list
444   ;; Value of `sp-local-pairs' for this buffer.  Note that this might
445   ;; differ from `sp-local-pairs' which is often changed by dynamic
446   ;; binding
447   local-pairs
448   )
449
450 (defvar sp-state (make-sp-state)
451   "Smartparens state for the current buffer.")
452 (make-variable-buffer-local 'sp-state)
453
454 ;; TODO: get rid of this
455 (defvar sp-previous-point -1
456   "Location of point before last command.
457
458 This is only updated when some pair-overlay is active.  Do not
459 rely on the value of this variable anywhere else!")
460 (make-variable-buffer-local 'sp-previous-point)
461
462 ;; TODO: get rid of this
463 (defvar sp-wrap-point nil
464   "Save the value of point before attemt to wrap a region.
465
466 Used for restoring the original state if the wrapping is
467 cancelled.")
468 (make-variable-buffer-local 'sp-wrap-point)
469
470 ;; TODO: get rid of this
471 (defvar sp-wrap-mark nil
472   "Save the value of mark before attemt to wrap a region.
473
474 Used for restoring the original state if the wrapping is
475 cancelled.")
476 (make-variable-buffer-local 'sp-wrap-mark)
477
478 (defvar sp-last-inserted-characters ""
479   "Characters typed during the wrapping selection.
480
481 If wrapping is cancelled, these characters are re-inserted to the
482 location of point before the wrapping.")
483 (make-variable-buffer-local 'sp-last-inserted-characters)
484
485 (defvar sp-last-inserted-pair nil
486   "Last inserted pair.")
487 (make-variable-buffer-local 'sp-last-inserted-pair)
488
489 (defvar sp-delayed-pair nil
490   "The pair whose insertion is being delayed.
491
492 The insertion of this pair is delayed to be carried out in
493 `sp--post-command-hook-handler'.  The format is (opening delim
494 .  beg of the opening delim)")
495 (make-variable-buffer-local 'sp-delayed-pair)
496
497 (defvar sp-last-wrapped-region nil
498   "Information about the last wrapped region.
499 The format is the same as returned by `sp-get-sexp'.")
500 (make-variable-buffer-local 'sp-last-wrapped-region)
501
502 (defvar sp-point-inside-string nil
503   "Non-nil if point is inside a string.
504
505 Used to remember the state from before `self-insert-command' is
506 run.")
507
508 (defvar sp-buffer-modified-p nil
509   "Non-nil if buffer was modified before `pre-command-hook'.")
510
511 (defvar sp-pre-command-point nil
512   "Position of `point' before `this-command' gets executed.")
513
514 (defconst sp-max-pair-length 10
515   "Maximum length of an opening or closing delimiter.
516
517 Only the pairs defined by `sp-pair' are considered.  Tag pairs
518 can be of any length.")
519
520 (defconst sp-max-prefix-length 100
521   "Maximum length of a pair prefix.
522
523 Because prefixes for pairs can be specified using regular
524 expressions, they can potentially be of arbitrary length.  This
525 settings solves the problem where the parser would decide to
526 backtrack the entire buffer which would lock up Emacs.")
527
528 (defvar sp-pairs
529   '((t
530      .
531      ((:open "\\\\(" :close "\\\\)" :actions (insert wrap autoskip navigate))
532       (:open "\\{"   :close "\\}"   :actions (insert wrap autoskip navigate))
533       (:open "\\("   :close "\\)"   :actions (insert wrap autoskip navigate))
534       (:open "\\\""  :close "\\\""  :actions (insert wrap autoskip navigate))
535       (:open "\""    :close "\""
536        :actions (insert wrap autoskip navigate escape)
537        :unless (sp-in-string-quotes-p)
538        :post-handlers (sp-escape-wrapped-region sp-escape-quotes-after-insert))
539       (:open "'"     :close "'"
540        :actions (insert wrap autoskip navigate escape)
541        :unless (sp-in-string-quotes-p sp-point-after-word-p)
542        :post-handlers (sp-escape-wrapped-region sp-escape-quotes-after-insert))
543       (:open "("     :close ")"     :actions (insert wrap autoskip navigate))
544       (:open "["     :close "]"     :actions (insert wrap autoskip navigate))
545       (:open "{"     :close "}"     :actions (insert wrap autoskip navigate))
546       (:open "`"     :close "`"     :actions (insert wrap autoskip navigate)))))
547   "List of pair definitions.
548
549 Maximum length of opening or closing pair is
550 `sp-max-pair-length' characters.")
551
552 (defvar sp-tags nil
553   "List of tag definitions.  See `sp-local-tag' for more information.")
554
555 (defvar sp-prefix-tag-object nil
556   "If non-nil, only consider tags while searching for next thing.")
557
558 (defvar sp-prefix-pair-object nil
559   "If non-nil, only consider pairs while searching for next thing.
560
561 Pairs are defined as expressions delimited by pairs from
562 `sp-pair-list'.")
563
564 (defvar sp-prefix-symbol-object nil
565   "If non-nil, only consider symbols while searching for next thing.
566
567 Symbol is defined as a chunk of text recognized by
568 `sp-forward-symbol'.")
569
570 (define-obsolete-variable-alias 'sp--lisp-modes 'sp-lisp-modes "2015-11-08")
571
572 (defcustom sp-lisp-modes '(
573                            cider-repl-mode
574                            clojure-mode
575                            clojurec-mode
576                            clojurescript-mode
577                            clojurex-mode
578                            common-lisp-mode
579                            emacs-lisp-mode
580                            eshell-mode
581                            geiser-repl-mode
582                            gerbil-mode
583                            inf-clojure-mode
584                            inferior-emacs-lisp-mode
585                            inferior-lisp-mode
586                            inferior-scheme-mode
587                            lisp-interaction-mode
588                            lisp-mode
589                            monroe-mode
590                            racket-mode
591                            racket-repl-mode
592                            scheme-interaction-mode
593                            scheme-mode
594                            slime-repl-mode
595                            stumpwm-mode
596                            )
597   "List of Lisp-related modes."
598   :type '(repeat symbol)
599   :group 'smartparens)
600
601 (defcustom sp-clojure-modes '(
602                               cider-repl-mode
603                               clojure-mode
604                               clojurec-mode
605                               clojurescript-mode
606                               clojurex-mode
607                               inf-clojure-mode
608                               )
609   "List of Clojure-related modes."
610   :type '(repeat symbol)
611   :group 'smartparens)
612
613 (defcustom sp-no-reindent-after-kill-modes '(
614                                              python-mode
615                                              coffee-mode
616                                              asm-mode
617                                              makefile-gmake-mode
618                                              haml-mode
619                                              )
620   "List of modes that should not reindent after kill."
621   :type '(repeat symbol)
622   :group 'smartparens)
623
624 (defcustom sp-no-reindent-after-kill-indent-line-functions
625   '(
626     insert-tab
627     )
628   "List of `indent-line-function's that should not reindent after kill."
629   :type '(repeat symbol)
630   :group 'smartparens)
631
632 (defvar sp--html-modes '(
633                          sgml-mode
634                          html-mode
635                          rhtml-mode
636                          nxhtml-mode
637                          nxml-mode
638                          web-mode
639                          jinja2-mode
640                          html-erb-mode
641                          js-jsx-mode
642                          js2-jsx-mode
643                          rjsx-mode
644                          )
645   "List of HTML modes.")
646
647 (defvar sp-message-alist
648   '((:unmatched-expression
649      "Search failed: there is an unmatched expression somewhere or we are at the beginning/end of file"
650      "Unmatched expression")
651     (:unbalanced-region
652      "Can not kill the region: the buffer would end up in an unbalanced state after deleting the active region"
653      "Killing the region would make the buffer unbalanced"
654      "Unbalanced region")
655     (:delimiter-in-string
656      "Ignored: opening or closing pair is inside a string or comment and matching pair is outside (or vice versa)")
657     (:no-matching-tag
658      "Search failed: no matching tag found"
659      "No matching tag")
660     (:invalid-context-prev
661      "Invalid context: previous h-sexp ends after the next one"
662      "Invalid context")
663     (:invalid-context-cur
664      "Invalid context: current h-sexp starts after the next one"
665      "Invalid context")
666     (:no-structure-found
667      "Previous sexp starts after current h-sexp or no structure was found"
668      "No valid structure found")
669     (:invalid-structure
670      "Ignored: this operation would result in invalid structure"
671      "Ignored because of invalid structure")
672     (:cant-slurp
673      "Ignored: we can not slurp without breaking strictly balanced expression"
674      "Can not slurp without breaking balance")
675     (:cant-slurp-context
676      "Ignored: we can not slurp into different context (comment -> code)"
677      "Can not slurp into different context")
678     (:cant-insert-closing-delimiter
679      "We can not insert unbalanced closing delimiter in strict mode"
680      "Can not insert unbalanced delimiter")
681     (:blank-sexp
682      "Point is in blank sexp, nothing to barf"
683      "Point is in blank sexp")
684     (:point-not-deep-enough
685      "Point has to be at least two levels deep to swap the enclosing delimiters"
686      "Point has to be at least two levels deep"
687      "Point not deep enough")
688     (:different-type
689      "The expressions to be joined are of different type"
690      "Expressions are of different type"))
691   "List of predefined messages to be displayed by `sp-message'.
692
693 Each element is a list consisting of a keyword and one or more
694 strings, which are chosen based on the `sp-message-width'
695 variable.  If the latter is t, the first string is chosen as
696 default, which should be the most verbose option available.")
697
698
699 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
700 ;; Customize & Mode definitions
701
702 (defgroup smartparens ()
703   "Smartparens minor mode."
704   :group 'editing
705   :prefix "sp-")
706
707 ;;;###autoload
708 (define-minor-mode smartparens-mode
709   "Toggle smartparens mode.
710
711 You can enable pre-set bindings by customizing
712 `sp-base-key-bindings' variable.  The current content of
713 `smartparens-mode-map' is:
714
715  \\{smartparens-mode-map}"
716   :init-value nil
717   :lighter (" SP" (:eval (if smartparens-strict-mode "/s" "")))
718   :group 'smartparens
719   :keymap smartparens-mode-map
720   (if smartparens-mode
721       (progn
722         (sp--init)
723         (add-hook 'self-insert-uses-region-functions 'sp-wrap--can-wrap-p nil 'local)
724         (run-hooks 'smartparens-enabled-hook))
725     (remove-hook 'self-insert-uses-region-functions 'sp-wrap--can-wrap-p 'local)
726     (run-hooks 'smartparens-disabled-hook)))
727
728 (defvar smartparens-strict-mode-map
729   (let ((map (make-sparse-keymap)))
730     (define-key map [remap delete-char] 'sp-delete-char)
731     (define-key map [remap delete-forward-char] 'sp-delete-char)
732     (define-key map [remap backward-delete-char-untabify] 'sp-backward-delete-char)
733     (define-key map [remap backward-delete-char] 'sp-backward-delete-char)
734     (define-key map [remap delete-backward-char] 'sp-backward-delete-char)
735     (define-key map [remap kill-word] 'sp-kill-word)
736     (define-key map [remap kill-line] 'sp-kill-hybrid-sexp)
737     (define-key map [remap backward-kill-word] 'sp-backward-kill-word)
738     (define-key map [remap kill-region] 'sp-kill-region)
739     (define-key map [remap delete-region] 'sp-delete-region)
740     (define-key map [remap kill-whole-line] 'sp-kill-whole-line)
741     map)
742   "Keymap used for `smartparens-strict-mode'.")
743
744 ;;;###autoload
745 (define-minor-mode smartparens-strict-mode
746   "Toggle the strict smartparens mode.
747
748 When strict mode is active, `delete-char', `kill-word' and their
749 backward variants will skip over the pair delimiters in order to
750 keep the structure always valid (the same way as `paredit-mode'
751 does).  This is accomplished by remapping them to
752 `sp-delete-char' and `sp-kill-word'.  There is also function
753 `sp-kill-symbol' that deletes symbols instead of words, otherwise
754 working exactly the same (it is not bound to any key by default).
755
756 When strict mode is active, this is indicated with \"/s\"
757 after the smartparens indicator in the mode list."
758   :init-value nil
759   :group 'smartparens
760   (if smartparens-strict-mode
761       (progn
762         (unless smartparens-mode
763           (smartparens-mode 1))
764         (unless (-find-indices (lambda (it) (eq (car it) 'smartparens-strict-mode)) minor-mode-overriding-map-alist)
765           (setq minor-mode-overriding-map-alist
766                 (cons `(smartparens-strict-mode . ,smartparens-strict-mode-map) minor-mode-overriding-map-alist)))
767         (put 'sp-backward-delete-char 'delete-selection 'sp--delete-selection-supersede-p)
768         (put 'sp-delete-char 'delete-selection 'sp--delete-selection-supersede-p)
769         (add-hook 'self-insert-uses-region-functions 'sp--self-insert-uses-region-strict-p nil 'local)
770         (setq sp-autoskip-closing-pair 'always))
771     (setq minor-mode-overriding-map-alist
772           (-remove (lambda (it) (eq (car it) 'smartparens-strict-mode)) minor-mode-overriding-map-alist))
773     (put 'sp-backward-delete-char 'delete-selection 'supersede)
774     (put 'sp-delete-char 'delete-selection 'supersede)
775     (remove-hook 'self-insert-uses-region-functions 'sp--self-insert-uses-region-strict-p 'local)
776     (let ((std-val (car (plist-get (symbol-plist 'sp-autoskip-closing-pair) 'standard-value)))
777           (saved-val (car (plist-get (symbol-plist 'sp-autoskip-closing-pair) 'saved-value))))
778       (setq sp-autoskip-closing-pair (eval (or saved-val std-val))))))
779
780 ;;;###autoload
781 (define-globalized-minor-mode smartparens-global-strict-mode
782   smartparens-strict-mode
783   turn-on-smartparens-strict-mode
784   :group 'smartparens)
785
786 (defcustom sp-ignore-modes-list '(
787                                   minibuffer-inactive-mode
788                                   )
789   "Modes where smartparens mode is inactive if allowed globally."
790   :type '(repeat symbol)
791   :group 'smartparens)
792
793 ;;;###autoload
794 (defun turn-on-smartparens-strict-mode ()
795   "Turn on `smartparens-strict-mode'."
796   (interactive)
797   (unless (or (member major-mode sp-ignore-modes-list)
798               (and (not (derived-mode-p 'comint-mode))
799                    (eq (get major-mode 'mode-class) 'special)))
800     (smartparens-strict-mode 1)))
801
802 ;;;###autoload
803 (defun turn-off-smartparens-strict-mode ()
804   "Turn off `smartparens-strict-mode'."
805   (interactive)
806   (smartparens-strict-mode -1))
807
808 (defun sp--init ()
809   "Initialize the buffer local smartparens state.
810
811  This includes pair bindings and other buffer local variables
812 that depend on the active `major-mode'."
813   (setq sp-state (make-sp-state))
814   ;; setup local pair replacements
815   (sp--update-local-pairs)
816   ;; set the escape char
817   (dotimes (char 256)
818     (unless sp-escape-char
819       (when (= ?\\ (char-syntax char))
820         (setq sp-escape-char (string char))))
821     (unless sp-comment-char
822       (when (= ?< (char-syntax char))
823         (setq sp-comment-char (string char))))))
824
825 (defun sp--maybe-init ()
826   "Initialize the buffer if it is not already initialized.
827
828 See `sp--init'."
829   (unless sp-pair-list
830     (sp--init)))
831
832 (defun sp--remove-local-pair (open)
833   "Remove OPEN from `sp-local-pairs'."
834   (setq sp-local-pairs
835         (--remove (equal (plist-get it :open) open)
836                   sp-local-pairs)))
837
838 (defun sp--update-sp-pair-list ()
839   "Update `sp-pair-list' according to current value of `sp-local-pairs'."
840   (setq sp-pair-list
841         (->> sp-local-pairs
842              (--map (cons (plist-get it :open) (plist-get it :close)))
843              (-sort (lambda (x y) (> (length (car x)) (length (car y))))))))
844
845 (defun sp--update-local-pairs ()
846   "Update local pairs after change or at mode initialization.
847
848 This commands load all the parent major mode definitions and
849 merges them into current buffer's `sp-local-pairs'."
850   (let ((parent-modes (-fix (lambda (x)
851                               (--if-let (get (car x) 'derived-mode-parent)
852                                   (cons it x)
853                                 x))
854                             (list major-mode))))
855     ;; Combine all the definitions from the most ancient parent to the
856     ;; most recent parent
857     (--each parent-modes (sp-update-local-pairs it))))
858
859 (defun sp-update-local-pairs (configuration)
860   "Update `sp-local-pairs' with CONFIGURATION.
861
862 The pairs are only updated in current buffer not in all buffers
863 with the same major mode!  If you want to update all buffers of
864 the specific major-modes use `sp-local-pair'.
865
866 CONFIGURATION can be a symbol to be looked up in `sp-pairs' or a
867 property list corresponding to the arguments of `sp-local-pair'
868 or a list of such property lists."
869   (setq sp-local-pairs
870         (cond
871          ((symbolp configuration)
872           (sp--merge-pair-configurations (cdr (assq configuration sp-pairs))))
873          ((plist-member configuration :open)
874           (sp--merge-pair-configurations (list configuration)))
875          (t
876           (sp--merge-pair-configurations configuration))))
877
878   ;; Keep only those which have non-nil :actions
879   (setq sp-local-pairs (--filter (plist-get it :actions) sp-local-pairs))
880
881   ;; update the `sp-pair-list'.  This is a list only containing
882   ;; (open.close) cons pairs for easier querying.  We also must order
883   ;; it by length of opening delimiter in descending order (first
884   ;; value is the longest)
885   (sp--update-sp-pair-list)
886   (setf (sp-state-local-pairs sp-state) sp-local-pairs)
887   (setf (sp-state-pair-list sp-state) sp-pair-list))
888
889 (defmacro sp-with-buffers-using-mode (mode &rest body)
890   "Execute BODY in every existing buffer using `major-mode' MODE."
891   (declare (indent 1))
892   `(--each (buffer-list)
893      (with-current-buffer it
894        (when (derived-mode-p ,mode)
895          ,@body))))
896
897 (defun sp--update-local-pairs-everywhere (&rest modes)
898   "Run `sp--update-local-pairs' in all buffers.
899
900 This is necessary to update all the buffer-local definitions.  If
901 MODES is non-nil, only update buffers with `major-mode' equal to
902 MODES."
903   (setq modes (-flatten modes))
904   (--each (buffer-list)
905     (with-current-buffer it
906       (when (and smartparens-mode
907                  (or (not modes)
908                      (--any? (derived-mode-p it) modes)))
909         (sp--update-local-pairs)))))
910
911 (defcustom smartparens-enabled-hook nil
912   "Called after `smartparens-mode' is turned on."
913   :type 'hook
914   :group 'smartparens)
915
916 (defcustom smartparens-disabled-hook nil
917   "Called after `smartparens-mode' is turned off."
918   :type 'hook
919   :group 'smartparens)
920
921 ;;;###autoload
922 (define-globalized-minor-mode smartparens-global-mode
923   smartparens-mode
924   turn-on-smartparens-mode)
925
926 ;;;###autoload
927 (defun turn-on-smartparens-mode ()
928   "Turn on `smartparens-mode'.
929
930 This function is used to turn on `smartparens-global-mode'.
931
932 By default `smartparens-global-mode' ignores buffers with
933 `mode-class' set to special, but only if they are also not comint
934 buffers.
935
936 Additionally, buffers on `sp-ignore-modes-list' are ignored.
937
938 You can still turn on smartparens in these mode manually (or
939 in mode's startup-hook etc.) by calling `smartparens-mode'."
940   (interactive)
941   (unless (or (member major-mode sp-ignore-modes-list)
942               (and (not (derived-mode-p 'comint-mode))
943                    (eq (get major-mode 'mode-class) 'special)))
944     (smartparens-mode t)))
945
946 ;;;###autoload
947 (defun turn-off-smartparens-mode ()
948   "Turn off `smartparens-mode'."
949   (interactive)
950   (smartparens-mode -1))
951
952 ;; insert custom
953 (defcustom sp-autoinsert-pair t
954   "If non-nil, autoinsert pairs.  See `sp-insert-pair'."
955   :type 'boolean
956   :group 'smartparens)
957
958 ;; TODO: remove this in 1.12
959 (defcustom sp-autoinsert-quote-if-followed-by-closing-pair nil
960   "If non-nil autoinsert quotes when the point is followed by closing delimiter.
961
962 This option only changes behaviour of the insertion process if
963 point is inside a string.  In other words, if string is not
964 closed and next character is a closing pair.
965
966 For example, in a situation like this:
967
968   [\"some text|]
969
970 after pressing \", one would probably want to insert the closing
971 quote, not a nested pair (\\\"\\\"), to close the string literal
972 in the array.  To enable such behaviour, set this variable to
973 nil.
974
975 Note: the values of this varible seem to be backward, i.e. it is
976 \"enabled\" when the value is nil.  This was an unfortunate
977 choice of wording.  It is kept this way to preserve backward
978 compatibility.  The intended meaning is \"insert the pair if
979 followed by closing pair?\", t = yes."
980   :type 'boolean
981   :group 'smartparens)
982 (make-obsolete-variable
983  'sp-autoinsert-quote-if-followed-by-closing-pair
984  "the option was removed and no longer has any effect." "1.10")
985
986 (defcustom sp-autoskip-closing-pair 'always-end
987   "Determine the behaviour when skipping closing delimiters.
988
989 If t, skip the following closing pair if the expression is
990 active (that is right after insertion).  This is controlled by
991 `sp-cancel-autoskip-on-backward-movement'.
992
993 If set to \"always-end\", skip the closing pair even if the
994 expression is not active and point is at the end of the
995 expression.  This only works for expressions with
996 single-character delimiters.
997
998 If set to \"always\", `sp-up-sexp' is called whenever the closing
999 delimiter is typed inside a sexp of the same type.  This is the
1000 paredit-like behaviour.  This setting only works for
1001 single-character delimiters and does not work for string-like
1002 delimiters.
1003
1004 See `sp-autoskip-opening-pair' for similar setting for
1005 string-like delimiters.
1006
1007 See also `sp-skip-closing-pair'."
1008   :type '(radio
1009           (const :tag "Never skip closing delimiter" nil)
1010           (const :tag "Skip closing delimiter in active expressions" t)
1011           (const :tag "Always skip closing delimiter if at the end of sexp" always-end)
1012           (const :tag "Always skip closing delimiter" always))
1013   :group 'smartparens)
1014 (make-variable-buffer-local 'sp-autoskip-closing-pair)
1015
1016 (defcustom sp-autoskip-opening-pair nil
1017   "Determine the behaviour when skipping opening delimiters.
1018
1019 If non-nil, skip into the following string-like expression
1020 instead of inserting a new pair."
1021   :type 'boolean
1022   :group 'smartparens)
1023 (make-variable-buffer-local 'sp-autoskip-opening-pair)
1024
1025 ;; TODO: rename to reflect what this actually does
1026 (defcustom sp-cancel-autoskip-on-backward-movement t
1027   "If non-nil, deactivate the active expression on backward movement.
1028
1029 Note: the name of this variable is a historic coincidence and
1030 will change in some future release to reflect its real purpose.
1031
1032 See also `sp-skip-closing-pair'."
1033   :type 'boolean
1034   :group 'smartparens)
1035
1036 ;; delete custom
1037 (defcustom sp-autodelete-pair t
1038   "If non-nil, auto delete pairs.  See `sp-delete-pair'."
1039   :type 'boolean
1040   :group 'smartparens)
1041
1042 (defcustom sp-autodelete-closing-pair t
1043   "If non-nil, auto delete the whole closing-pair.  See `sp-delete-pair'."
1044   :type 'boolean
1045   :group 'smartparens)
1046
1047 (defcustom sp-autodelete-opening-pair t
1048   "If non-nil, auto delete the whole opening-pair.  See `sp-delete-pair'."
1049   :type 'boolean
1050   :group 'smartparens)
1051
1052 (defcustom sp-undo-pairs-separately nil
1053   "If non-nil, put an `undo-boundary' before each inserted pair.
1054
1055 Calling undo after smartparens complete a pair will remove only
1056 the pair before undoing any previous insertion.
1057
1058 WARNING: This option is implemented by hacking the
1059 `buffer-undo-list'.  Turning this option on might have
1060 irreversible consequences on the buffer's undo information and in
1061 some cases might remove important information.  Usage of package
1062 `undo-tree' is recommended if you ever need to revert to a state
1063 unreachable by undo."
1064   :type 'boolean
1065   :group 'smartparens)
1066
1067 (defcustom sp-successive-kill-preserve-whitespace 1
1068   "Control the behaviour of `sp-kill-sexp' on successive kills.
1069
1070 In the description, we consider more than one space
1071 \"superfluous\", however, newlines are preserved."
1072   :type '(radio
1073           (const :tag "Always preserve the whitespace" 0)
1074           (const :tag "Remove superfluous whitespace after last kill" 1)
1075           (const :tag "Remove superfluous whitespace after all kills" 2))
1076   :group 'smartparens)
1077
1078 ;; wrap custom
1079 (defcustom sp-autowrap-region t
1080   "If non-nil, wrap the active region with pair."
1081   :type 'boolean
1082   :group 'smartparens)
1083
1084 (defcustom sp-wrap-show-possible-pairs t
1085   "If non-nil, show possible pairs which can complete the wrapping."
1086   :type 'boolean
1087   :group 'smartparens)
1088
1089 (defcustom sp-autodelete-wrap t
1090   "If non-nil, autodelete opening and closing pair of most recent wrapping.
1091
1092 Deletion command must be the very first command after the
1093 insertion, otherwise normal behaviour is applied."
1094   :type 'boolean
1095   :group 'smartparens)
1096
1097 (defcustom sp-wrap-repeat-last 1
1098   "Context in which smartparens repeats the last wrap.
1099
1100 If the last operation was a wrap and we insert another pair at
1101 the beginning or end of the last wrapped region, repeat the
1102 wrap on this region with current pair."
1103   :type '(radio
1104           (const :tag "Do not repeat wrapping" 0)
1105           (const :tag "Only repeat if current tag is the same as the last one" 1)
1106           (const :tag "Always repeat if the point is after the opening/closing delimiter of last wrapped region" 2))
1107   :group 'smartparens)
1108
1109 (defcustom sp-wrap-entire-symbol nil
1110   "If non-nil, do NOT wrap the entire symbol, only the part after point.
1111
1112 If set to \"Enable globally\", smart symbol wrapping is active
1113 everywhere.  This is the default option.
1114
1115 If set to \"Disable globally\", smart symbol wrapping is disabled
1116 everywhere.
1117
1118 Otherwise, a list of major modes where smart symbol wrapping is
1119 *disabled* can be supplied.
1120
1121 Examples:
1122
1123  foo-ba|r-baz -> (|foo-bar-baz) ;; if enabled
1124
1125  foo-ba|r-baz -> foo-ba(|r-baz) ;; if disabled"
1126   :type '(choice
1127           (const :tag "Enable globally" nil)
1128           (const :tag "Disable globally" globally)
1129           (repeat :tag "Disable in these major modes" symbol))
1130   :group 'smartparens)
1131
1132 (defcustom sp-wrap-from-point nil
1133   "If non-nil, do not wrap from the beginning of next expression but from point.
1134
1135 However, if the point is inside a symbol/word, the entire
1136 symbol/word is wrapped.  To customize this behaviour, see
1137 variable `sp-wrap-entire-symbol'."
1138   :type 'boolean
1139   :group 'smartparens)
1140
1141 (defcustom sp-wrap-respect-direction nil
1142   "When non-nil respect the wrap direction.
1143
1144 When non-nil, wrapping with opening pair always jumps to the
1145 beginning of the region and wrapping with closing pair always
1146 jumps to the end of the region.
1147
1148   |fooM -> [ -> |[foo]M
1149   Mfoo| -> [ -> |[foo]M
1150   |fooM -> ] -> M[foo]|
1151   Mfoo| -> ] -> M[foo]|
1152
1153 When nil, closing pair places the point at the end of the region
1154 and the opening pair leaves the point at its original
1155 position (before or after the region).
1156
1157   |fooM -> [ -> [|fooM]
1158   Mfoo| -> [ -> M[foo]|
1159   |fooM -> ] -> M[foo]|
1160   Mfoo| -> ] -> M[foo]|"
1161   :type 'boolean
1162   :group 'smartparens)
1163
1164 ;; escaping custom
1165 (defcustom sp-escape-wrapped-region t
1166   "If non-nil, escape special chars inside the just wrapped region."
1167   :type 'boolean
1168   :group 'smartparens)
1169
1170 (defcustom sp-escape-quotes-after-insert t
1171   "If non-nil, escape string quotes if typed inside string."
1172   :type 'boolean
1173   :group 'smartparens)
1174
1175 ;; navigation & manip custom
1176 (defcustom sp-navigate-consider-sgml-tags '(
1177                                             html-mode
1178                                             )
1179   "List of modes where sgml tags are considered to be sexps."
1180   :type '(repeat symbol)
1181   :group 'smartparens)
1182
1183
1184 (defcustom sp-navigate-use-textmode-stringlike-parser '((derived . text-mode))
1185   "List of modes where textmode stringlike parser is used.
1186
1187 See `sp-get-textmode-stringlike-expression'.
1188
1189 Each element of the list can either be a symbol which is then
1190 checked against `major-mode', or a cons (derived . PARENT-MODE),
1191 where PARENT-MODE is checked using `derived-mode-p'."
1192   :type '(repeat (choice
1193                   (symbol :tag "Major mode")
1194                   (cons :tag "Derived mode"
1195                     (const derived)
1196                     (symbol :tag "Parent major mode name"))))
1197   :group 'smartparens)
1198
1199 (defcustom sp-navigate-consider-symbols t
1200   "If non-nil, consider symbols outside balanced expressions as such.
1201
1202 Symbols are recognized by function `sp-forward-symbol'.  This
1203 setting affect all the navigation and manipulation functions
1204 where it make sense.
1205
1206 Also, special handling of strings is enabled, where the whole
1207 string delimited with \"\" is considered as one token.
1208
1209 WARNING: This is a legacy setting and changing its value to NIL
1210 may break many things.  It is kept only for backward
1211 compatibility and will be removed in the next major release."
1212   :type 'boolean
1213   :group 'smartparens)
1214
1215 (defcustom sp-navigate-comments-as-sexps t
1216   "If non-nil, consider comments as sexps in `sp-get-enclosing-sexp'.
1217
1218 If this option is enabled, unbalanced expressions in comments are
1219 never automatically closed (see `sp-navigate-close-if-unbalanced')."
1220   :type 'boolean
1221   :group 'smartparens)
1222
1223 ;; TODO: add -alist suffix
1224 (defcustom sp-navigate-skip-match `(
1225                                     (,sp-lisp-modes . sp--elisp-skip-match)
1226                                     )
1227   "Major-mode dependent specifications of skip functions.
1228
1229 Alist where the key is a list of major-modes and the value is a
1230 function used to skip over matches in `sp-get-paired-expression'.
1231 This function takes three arguments: the currently matched
1232 delimiter, beginning of match and end of match.  If this function
1233 returns true, the current match will be skipped.
1234
1235 You can use this to skip over expressions that serve multiple
1236 functions, such as if/end pair or unary if in Ruby or * in
1237 markdown when it signifies list item instead of emphasis.  If the
1238 exception is only relevant to one pair, you should rather
1239 use :skip-match option in `sp-local-pair'."
1240   :type '(alist
1241           :key-type (repeat symbol)
1242           :value-type symbol)
1243   :group 'smartparens)
1244
1245 (defcustom sp-navigate-reindent-after-up `(
1246                                            (interactive
1247                                             ,@sp-lisp-modes
1248                                             )
1249                                            )
1250   "Modes where sexps should be reindented after `sp-up-sexp'.
1251
1252 The whitespace between the closing delimiter and last \"thing\"
1253 inside the expression is removed.  It works analogically for the
1254 `sp-backward-up-sexp'.
1255
1256 Note that this also happens when `sp-skip-closing-pair' is
1257 invoked (usually in strict mode when the closing delimiter is
1258 typed) as it calls `sp-up-sexp' internally.  This behaviour can
1259 be customized by various settings of `sp-autoskip-closing-pair'
1260 and `sp-autoskip-opening-pair'.
1261
1262 If the mode is in the list \"interactive\", only reindent the sexp
1263 if the command was called interactively.  This is recommended for
1264 general use.
1265
1266 If the mode is in the list \"always\", reindend the sexp even if the
1267 command was called programatically."
1268   :type '(alist
1269           :options (interactive always)
1270           :value-type (repeat symbol))
1271   :group 'smartparens)
1272
1273 (defcustom sp-navigate-reindent-after-up-in-string t
1274   "If non-nil, `sp-up-sexp' will reindent inside strings.
1275
1276 If `sp-navigate-reindent-after-up' is enabled and the point is
1277 inside a string, this setting determines if smartparens should
1278 reindent the current (string) sexp or not."
1279   :type 'boolean
1280   :group 'smartparens)
1281
1282 (defcustom sp-navigate-close-if-unbalanced nil
1283   "If non-nil, insert the closing pair of the un-matched pair on `sp-up-sexp'.
1284
1285 The closing delimiter is inserted after the symbol at
1286 point (using `sp-previous-sexp')."
1287   :type 'boolean
1288   :group 'smartparens)
1289
1290 (defcustom sp-navigate-interactive-always-progress-point nil
1291   "Make point always move in the direction of navigation.
1292
1293 If non-nil and the function is called interactively,
1294 `sp-next-sexp' and `sp-previous-sexp' will always move the point
1295 to the end/beg of such an expression where the point would end up
1296 being further in the direction of travel.
1297
1298 Note: this behaviour will become default in release 2.0 and will
1299 cease to be configurable."
1300   :type 'boolean
1301   :group 'smartparens)
1302
1303 (defcustom sp-sexp-prefix nil
1304   "Alist of `major-mode' specific prefix specification.
1305
1306 Each item is a list with three properties:
1307 - major mode
1308 - a constant symbol 'regexp or 'syntax
1309 - a regexp or a string containing syntax class codes.
1310
1311 If the second argument is 'regexp, the third argument is
1312 interpreted as a regexp to search backward from the start of an
1313 expression.
1314
1315 If the second argument is 'syntax, the third argument is
1316 interpreted as string containing syntax codes that will be
1317 skipped.
1318
1319 You can also override this property locally for a specific pair
1320 by specifying its :prefix property."
1321   :type '(repeat
1322           (list symbol
1323                 (choice
1324                  (const :tag "Regexp" regexp)
1325                  (const :tag "Syntax class codes" syntax))
1326                 string))
1327   :group 'smartparens)
1328
1329 (defcustom sp-sexp-suffix nil
1330   "Alist of `major-mode' specific suffix specification.
1331
1332 Each item is a list with three properties:
1333 - major mode
1334 - a constant symbol 'regexp or 'syntax
1335 - a regexp or a string containing syntax class codes.
1336
1337 If the second argument is 'regexp, the third argument is
1338 interpreted as a regexp to search forward from the end of an
1339 expression.
1340
1341 If the second argument is 'syntax, the third argument is
1342 interpreted as string containing syntax codes that will be
1343 skipped.
1344
1345 You can also override this property locally for a specific pair
1346 by specifying its :suffix property."
1347   :type '(repeat
1348           (list symbol
1349                 (choice
1350                  (const :tag "Regexp" regexp)
1351                  (const :tag "Syntax class codes" syntax))
1352                 string))
1353   :group 'smartparens)
1354
1355 (defcustom sp-split-sexp-always-split-as-string t
1356   "Determine if sexp inside string is split.
1357
1358 If the point is inside a sexp inside a string, the default
1359 behaviour is now to split the string, such that:
1360
1361   \"foo (|) bar\"
1362
1363 becomes
1364
1365    \"foo (\"|\") bar\"
1366
1367 instead of
1368
1369    \"foo ()|() bar\".
1370
1371 Note: the old default behaviour was the reverse, it would split
1372 the sexp, but this is hardly ever what you want.
1373
1374 You can add a post-handler on string pair and check for
1375 'split-string action to add concatenation operators of the
1376 language you work in (in each `major-mode' you can have a separate
1377 hook).
1378
1379 For example, in PHP the string concatenation operator is a
1380 dot (.), so you would add:
1381
1382   (defun my-php-post-split-handler (_ action _)
1383     (when (eq action 'split-sexp)
1384       (just-one-space)
1385       (insert \".  . \")
1386       (backward-char 3)))
1387
1388   (sp-local-pair 'php-mode \"'\" nil
1389    :post-handlers '(my-php-post-split-handler))
1390
1391 Then
1392
1393   echo 'foo |baz';
1394
1395 results in
1396
1397   echo 'foo' . | . 'baz';"
1398   :type 'boolean
1399   :group 'smartparens)
1400
1401 ;; hybrid lines
1402 (defcustom sp-hybrid-kill-excessive-whitespace nil
1403   "Determine how `sp-kill-hybrid-sexp' kills excessive whitespace.
1404
1405 If non-nil, `sp-kill-hybrid-sexp' will delete all whitespace
1406 up until next hybrid sexp if the point is at the end of line or
1407 on a blank line.
1408
1409 When it is set to 'kill, whitespace will be appended to the sexp
1410 in kill ring."
1411   :type '(choice
1412           (const :tag "Delete" t)
1413           (const :tag "Kill" kill)
1414           (const :tag "Off" nil))
1415   :group 'smartparens)
1416
1417 (defcustom sp-hybrid-kill-entire-symbol nil
1418   "Governs how symbols under point are treated by `sp-kill-hybrid-sexp'.
1419
1420 If t, always kill the symbol under point.
1421
1422 If nil, never kill the entire symbol and only kill the part after point.
1423
1424 If a function, this should be a zero-arg predicate.  When it
1425 returns non-nil value, we should kill from point."
1426   :type '(radio
1427           (const :tag "Always kill entire symbol" t)
1428           (const :tag "Always kill from point" nil)
1429           (const :tag "Kill from point only inside strings" sp-point-in-string)
1430           (function :tag "Custom predicate"))
1431   :group 'smartparens)
1432
1433 (defcustom sp-comment-string nil
1434   "String that is inserted after calling `sp-comment'.
1435
1436 It is an alist of list of major modes to a string.
1437
1438 The value of `comment-start' is used if the major mode is not found."
1439   :type '(alist
1440           :key-type (repeat symbol)
1441           :value-type string)
1442   :group 'smartparens)
1443
1444 ;; ui custom
1445 (defcustom sp-highlight-pair-overlay t
1446   "If non-nil, autoinserted pairs are highlighted while point is inside the pair."
1447   :type 'boolean
1448   :group 'smartparens)
1449
1450 (defcustom sp-highlight-wrap-overlay t
1451   "If non-nil, wrap overlays are highlighted during editing of the wrapping pair."
1452   :type 'boolean
1453   :group 'smartparens)
1454
1455 (defcustom sp-highlight-wrap-tag-overlay t
1456   "If non-nil, wrap tag overlays are highlighted during editing of the wrapping tag pair."
1457   :type 'boolean
1458   :group 'smartparens)
1459
1460 (defcustom sp-echo-match-when-invisible t
1461   "If non-nil, show-smartparens-mode prints the line of the
1462 matching paren in the echo area if not visible on screen."
1463   :type 'boolean
1464   :group 'smartparens)
1465
1466 (defcustom sp-message-width 'frame
1467   "Length of information and error messages to display.
1468
1469 If set to 'frame (the default), messages are chosen based of the
1470 frame width.  t means chose the default (verbose) message, nil
1471 means mute.  Integers specify the maximum width."
1472   :type '(choice (const :tag "Fit to frame" frame)
1473                  (const :tag "Verbose" t)
1474                  (const :tag "Mute" nil)
1475                  (integer :tag "Max width"))
1476   :group 'smartparens)
1477
1478 ;; TODO: this should be true by default > then the behaviour is
1479 ;; controlled by subword-mode... and this is a hard override
1480 (defcustom sp-use-subword nil
1481   "Override of `subword-mode' killing behaviour.
1482
1483 If non-nill, `sp-kill-word' and `sp-backward-kill-word' only
1484 kill \"subwords\" when `subword-mode' is active."
1485   :type 'boolean
1486   :group 'smartparens)
1487
1488
1489 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1490 ;; Selection mode handling
1491
1492 (defun sp--delete-selection-p ()
1493   "Return t if `delete-selection-mode' or `cua-delete-selection' is enabled."
1494   (or (and (boundp 'delete-selection-mode) delete-selection-mode)
1495       (and (boundp 'cua-delete-selection) cua-delete-selection cua-mode)))
1496
1497 (defun sp--delete-selection-supersede-p ()
1498   "Decide if the current command should delete the region or not.
1499
1500 This check is used as value of 'delete-selection property on the
1501 command symbol."
1502   (if (or (equal current-prefix-arg '(4))
1503           (sp-region-ok-p (region-beginning) (region-end)))
1504       'supersede
1505     (sp-message :unbalanced-region)
1506     ;; Since this check runs in the pre-command-hook we can change the
1507     ;; command to be executed... in this case we set it to ignore
1508     ;; because we don't want to do anything.
1509     (setq this-command 'ignore)
1510     nil))
1511
1512 (defun sp--self-insert-uses-region-strict-p ()
1513   "Decide if the current `self-insert-command' should be able to
1514 replace the region.
1515
1516 This check is added to the special hook
1517 `self-insert-uses-region-functions' which is checked by
1518 `delete-selection-uses-region-p'."
1519   (if (or (equal current-prefix-arg '(4))
1520           (sp-region-ok-p (region-beginning) (region-end)))
1521       ;; region is OK or we are allowed to replace it, just say nil so
1522       ;; that delsel handles this
1523       nil
1524     ;; in case region is bad we interrupt the insertion
1525     (setq this-command 'ignore)
1526     t))
1527
1528 ;; TODO: this function was removed from Emacs, we should get rid of
1529 ;; the advice in time.
1530 (defadvice cua-replace-region (around fix-sp-wrap activate)
1531   "Fix `sp-wrap' in `cua-selection-mode'."
1532   (if (sp-wrap--can-wrap-p)
1533       (cua--fallback)
1534     ad-do-it))
1535
1536 (defadvice cua-delete-region (around fix-sp-delete-region activate)
1537   "If `smartparens-strict-mode' is enabled, perform a region
1538 check before deleting."
1539   (if smartparens-strict-mode
1540       (progn
1541         (unless (or current-prefix-arg
1542                     (sp-region-ok-p (region-beginning) (region-end)))
1543           (user-error (sp-message :unbalanced-region :return)))
1544         ad-do-it)
1545     ad-do-it))
1546
1547
1548
1549 (cl-eval-when (compile eval load)
1550   (defun sp--get-substitute (struct list)
1551     "Only ever call this from sp-get!  This function does the
1552 replacement of all the keywords with actual calls to sp-get."
1553     (if (listp list)
1554         (if (eq (car list) 'sp-get)
1555             list
1556           (mapcar (lambda (x) (sp--get-substitute struct x))
1557                   (let ((command (car list)))
1558                     (cond
1559                      ((eq command 'sp-do-move-op)
1560                       (let ((argument (make-symbol "--sp-argument--")))
1561                         `(let ((,argument ,(cadr list)))
1562                            (if (< ,argument :beg-prf)
1563                                (progn
1564                                  (goto-char :beg-prf)
1565                                  (delete-char (+ :op-l :prefix-l))
1566                                  (goto-char ,argument)
1567                                  (insert :prefix :op))
1568                              (goto-char ,argument)
1569                              (insert :prefix :op)
1570                              (goto-char :beg-prf)
1571                              (delete-char (+ :op-l :prefix-l))))))
1572                      ((eq command 'sp-do-move-cl)
1573                       (let ((argument (make-symbol "--sp-argument--")))
1574                         `(let ((,argument ,(cadr list)))
1575                            (if (> ,argument :end-in)
1576                                (progn
1577                                  (goto-char ,argument)
1578                                  (insert :cl :suffix)
1579                                  (goto-char :end-in)
1580                                  (delete-char (+ :cl-l :suffix-l)))
1581                              (goto-char :end-in)
1582                              (delete-char (+ :cl-l :suffix-l))
1583                              (goto-char ,argument)
1584                              (insert :cl :suffix)))))
1585                      ((eq command 'sp-do-del-op)
1586                       `(progn
1587                          (goto-char :beg-prf)
1588                          (delete-char (+ :op-l :prefix-l))))
1589                      ((eq command 'sp-do-del-cl)
1590                       `(progn
1591                          (goto-char :end-in)
1592                          (delete-char (+ :cl-l :suffix-l))))
1593                      ((eq command 'sp-do-put-op)
1594                       `(progn
1595                          (goto-char ,(cadr list))
1596                          (insert :prefix :op)))
1597                      ((eq command 'sp-do-put-cl)
1598                       `(progn
1599                          (goto-char ,(cadr list))
1600                          (insert :cl :suffix)))
1601                      (t list)))))
1602       (if (keywordp list)
1603           (sp--get-replace-keyword struct list)
1604         list)))
1605
1606   (defun sp--get-replace-keyword (struct keyword)
1607     (cl-case keyword
1608       ;; point in buffer before the opening delimiter
1609       (:beg         `(plist-get ,struct :beg))
1610       ;; point in the buffer after the closing delimiter
1611       (:end         `(plist-get ,struct :end))
1612       ;; point in buffer after the opening delimiter
1613       (:beg-in      `(+ (plist-get ,struct :beg) (length (plist-get ,struct :op))))
1614       ;; point in buffer before the closing delimiter
1615       (:end-in      `(- (plist-get ,struct :end) (length (plist-get ,struct :cl))))
1616       ;; point in buffer before the prefix of this expression
1617       (:beg-prf     `(- (plist-get ,struct :beg) (length (plist-get ,struct :prefix))))
1618       ;; point in the buffer after the suffix of this expression
1619       (:end-suf     `(+ (plist-get ,struct :end) (length (plist-get ,struct :suffix))))
1620       ;; opening delimiter
1621       (:op          `(plist-get ,struct :op))
1622       ;; closing delimiter
1623       (:cl          `(plist-get ,struct :cl))
1624       ;; length of the opening pair
1625       (:op-l        `(length (plist-get ,struct :op)))
1626       ;; length of the closing pair
1627       (:cl-l        `(length (plist-get ,struct :cl)))
1628       ;; length of the entire expression, including enclosing
1629       ;; delimiters and the prefix and suffix
1630       (:len         `(- (plist-get ,struct :end)
1631                         (plist-get ,struct :beg)
1632                         (- (length (plist-get ,struct :prefix)))
1633                         (- (length (plist-get ,struct :suffix)))))
1634       ;; length of the the pair ignoring the prefix, including delimiters
1635       (:len-out     `(- (plist-get ,struct :end) (plist-get ,struct :beg)))
1636       ;; length of the pair inside the delimiters
1637       (:len-in      `(- (plist-get ,struct :end)
1638                         (plist-get ,struct :beg)
1639                         (length (plist-get ,struct :op))
1640                         (length (plist-get ,struct :cl))))
1641       ;; expression prefix
1642       (:prefix      `(plist-get ,struct :prefix))
1643       ;; expression prefix length
1644       (:prefix-l    `(length (plist-get ,struct :prefix)))
1645       (:suffix      `(plist-get ,struct :suffix))
1646       (:suffix-l    `(length (plist-get ,struct :suffix)))
1647       ;; combined op/cl and suffix/prefix
1648       (:opp         `(concat (plist-get ,struct :prefix)
1649                              (plist-get ,struct :op)))
1650       (:opp-l       `(+ (length (plist-get ,struct :prefix))
1651                         (length (plist-get ,struct :op))))
1652       (:cls         `(concat (plist-get ,struct :cl)
1653                              (plist-get ,struct :suffix)))
1654       (:cls-l       `(+ (length (plist-get ,struct :cl))
1655                         (length (plist-get ,struct :suffix))))
1656       (t keyword))))
1657
1658
1659 ;; TODO: rewrite this in terms of `symbol-macrolet' ??
1660 (defmacro sp-get (struct &rest forms)
1661   "Get a property from a structure.
1662
1663 STRUCT is a plist with the format as returned by `sp-get-sexp'.
1664 Which means this macro also works with `sp-get-symbol',
1665 `sp-get-string' and `sp-get-thing'.
1666
1667 FORMS is an attribute we want to query.  Currently supported
1668 attributes are:
1669
1670 :beg       - point in buffer before the opening delimiter
1671 :end       - point in the buffer after the closing delimiter
1672 :beg-in    - point in buffer after the opening delimiter
1673 :end-in    - point in buffer before the closing delimiter
1674 :beg-prf   - point in buffer before the prefix of this expression
1675 :end-suf   - point in buffer after the suffix of this expression
1676 :op        - opening delimiter
1677 :cl        - closing delimiter
1678 :op-l      - length of the opening pair
1679 :cl-l      - length of the closing pair
1680 :len       - length of the entire expression, including enclosing
1681              delimiters, the prefix and the suffix
1682 :len-out   - length of the the pair ignoring the prefix and suffix,
1683              including delimiters
1684 :len-in    - length of the pair inside the delimiters
1685 :prefix    - expression prefix
1686 :prefix-l  - expression prefix length
1687 :suffix    - expression suffix
1688 :suffix-l  - expression suffix length
1689
1690 These special \"functions\" are expanded to do the selected
1691 action in the context of currently queried pair:
1692
1693 Nullary:
1694 \(sp-do-del-op) - remove prefix and opening delimiter
1695 \(sp-do-del-cl) - remove closing delimiter and suffix
1696
1697 Unary:
1698 \(sp-do-move-op p) - move prefix and opening delimiter to point p
1699 \(sp-do-move-cl p) - move closing delimiter and suffix to point p
1700 \(sp-do-put-op p) - put prefix and opening delimiter at point p
1701 \(sp-do-put-cl p) - put closing delimiter and suffix at point p
1702
1703 In addition to these simple queries and commands, this macro
1704 understands arbitrary forms where any of the aforementioned
1705 attributes are used.  Therefore, you can for example query for
1706 \"(+ :op-l :cl-l)\".  This query would return the sum of lengths
1707 of opening and closing delimiter.  A query
1708 \"(concat :prefix :op)\" would return the string containing
1709 expression prefix and the opening delimiter.
1710
1711 Special care is taken to only evaluate the STRUCT argument once."
1712   (declare (indent 1)
1713            (debug (form body)))
1714   (let ((st (make-symbol "struct")))
1715     (sp--get-substitute st `(let ((,st ,struct)) ,@forms))))
1716
1717
1718 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1719 ;; Misc/Utility functions
1720
1721 (defun sp--indent-region (start end &optional column)
1722   "Call `indent-region' unless `aggressive-indent-mode' is enabled.
1723
1724 START, END and COLUMN are the same as in `indent-region'."
1725   (unless (bound-and-true-p aggressive-indent-mode)
1726     ;; Don't issue "Indenting region..." message.
1727     (cl-letf (((symbol-function 'message) #'ignore))
1728       (indent-region start end column))))
1729
1730 (defmacro sp-with-modes (arg &rest forms)
1731   "Add ARG as first argument to each form in FORMS.
1732
1733 This can be used with `sp-local-pair' calls to automatically
1734 insert the modes."
1735   (declare (indent 1)
1736            (debug (form body)))
1737   (let ((modes (make-symbol "modes")))
1738     `(let ((,modes ,arg))
1739        (progn
1740          ,@(mapcar (lambda (form) (append (list (car form) modes) (cdr form))) forms)))))
1741
1742 (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "("
1743                                                      (regexp-opt '("sp-with-modes"
1744                                                                    "sp-get"
1745                                                                    "sp-compare-sexps") t)
1746                                                      "\\_>")
1747                                             (1 font-lock-keyword-face))))
1748
1749 (defmacro sp--with-case-sensitive (&rest body)
1750   "Ensure that searching done within BODY is case-sensitive.
1751
1752 Bind `case-fold-search' to nil if it is not already and avoid the
1753 bind if it is already.  Any function that needs to use any of the
1754 sp--looking-* functions more than once should wrap them all in
1755 `sp--with-case-sensitive'."
1756   (declare (indent 0)
1757            (debug (body)))
1758   `(if case-fold-search
1759        (let ((case-fold-search nil))
1760          ,@body)
1761      ,@body))
1762
1763 (defun sp--evil-normal-state-p ()
1764   "Check to see if the current `evil-state' is in normal mode."
1765   (and (fboundp 'evil-normal-state-p) (evil-normal-state-p)))
1766
1767 (defun sp--evil-motion-state-p ()
1768   "Check to see if the current `evil-state' is in motion mode."
1769   (and (fboundp 'evil-motion-state-p) (evil-motion-state-p)))
1770
1771 (defun sp--evil-visual-state-p ()
1772   "Check to see if the current `evil-state' is in visual mode."
1773   (and (fboundp 'evil-visual-state-p) (evil-visual-state-p)))
1774
1775 (defun sp-point-in-blank-line (&optional p)
1776   "Return non-nil if line at point is blank (whitespace only).
1777
1778 If optional argument P is present test this instead of point."
1779   (save-excursion
1780     (when p (goto-char p))
1781     (beginning-of-line)
1782     (looking-at "[ \t]*$")))
1783
1784 (defun sp-point-in-blank-sexp (&optional p)
1785   "Return non-nil if point is inside blank (whitespace only) sexp.
1786
1787 If optional argument P is present test this instead of point.
1788
1789 Warning: it is only safe to call this when point is inside a
1790 sexp, otherwise the call may be very slow."
1791   (save-excursion
1792     (when p (goto-char p))
1793     (-when-let (enc (sp-get-enclosing-sexp))
1794       (sp-get enc (string-match-p
1795                    "\\`[ \t\n]*\\'"
1796                    (buffer-substring-no-properties :beg-in :end-in))))))
1797
1798 (defun sp-char-is-escaped-p (&optional point)
1799   "Test if the char at POINT is escaped or not.
1800
1801 POINT defaults to `point'."
1802   (setq point (or point (point)))
1803   (save-match-data
1804     (when (save-excursion
1805             (goto-char point)
1806             (looking-back (concat sp-escape-char sp-escape-char "+") nil t))
1807       (eq (logand (length (match-string 0)) 1) 1))))
1808
1809 (defun sp--syntax-ppss (&optional p)
1810   "Memoize the last result of `syntax-ppss'.
1811
1812 P is the point at which we run `syntax-ppss'"
1813   (let ((p (or p (point)))
1814         (mem-p (sp-state-last-syntax-ppss-point sp-state)))
1815     (if (and (eq p (nth 0 mem-p))
1816              (eq (point-min) (nth 1 mem-p))
1817              (eq (point-max) (nth 2 mem-p)))
1818         (sp-state-last-syntax-ppss-result sp-state)
1819       ;; Add hook to reset memoization if necessary
1820       (unless (sp-state-last-syntax-ppss-point sp-state)
1821         (add-hook 'before-change-functions 'sp--reset-memoization t t))
1822       (setf (sp-state-last-syntax-ppss-point sp-state)
1823             (list p (point-min) (point-max))
1824             (sp-state-last-syntax-ppss-result sp-state) (syntax-ppss p)))))
1825
1826 (defun sp-point-in-string (&optional p)
1827   "Return non-nil if point is inside string or documentation string.
1828
1829 This function actually returns the 3rd element of `syntax-ppss'
1830 which can be a number if the string is delimited by that
1831 character or t if the string is delimited by general string
1832 fences.
1833
1834 If optional argument P is present test this instead of point."
1835   (ignore-errors
1836     (save-excursion
1837       (nth 3 (sp--syntax-ppss p)))))
1838
1839 (defun sp-point-in-comment (&optional p)
1840   "Return non-nil if point is inside comment.
1841
1842 If optional argument P is present test this instead off point."
1843   (setq p (or p (point)))
1844   (ignore-errors
1845     (save-excursion
1846       ;; We cannot be in a comment if we are inside a string
1847       (unless (nth 3 (sp--syntax-ppss p))
1848         (or (nth 4 (sp--syntax-ppss p))
1849             ;; this also test opening and closing comment delimiters... we
1850             ;; need to chack that it is not newline, which is in "comment
1851             ;; ender" class in elisp-mode, but we just want it to be
1852             ;; treated as whitespace
1853             (and (< p (point-max))
1854                  (memq (char-syntax (char-after p)) '(?< ?>))
1855                  (not (eq (char-after p) ?\n)))
1856             ;; we also need to test the special syntax flag for comment
1857             ;; starters and enders, because `syntax-ppss' does not yet
1858             ;; know if we are inside a comment or not (e.g. / can be a
1859             ;; division or comment starter...).
1860             (-when-let (s (car (syntax-after p)))
1861               (or (and (/= 0 (logand (lsh 1 16) s))
1862                        (nth 4 (syntax-ppss (+ p 2))))
1863                   (and (/= 0 (logand (lsh 1 17) s))
1864                        (nth 4 (syntax-ppss (+ p 1))))
1865                   (and (/= 0 (logand (lsh 1 18) s))
1866                        (nth 4 (syntax-ppss (- p 1))))
1867                   (and (/= 0 (logand (lsh 1 19) s))
1868                        (nth 4 (syntax-ppss (- p 2)))))))))))
1869
1870 (defun sp-point-in-string-or-comment (&optional p)
1871   "Return non-nil if point is inside string, documentation string or a comment.
1872
1873 If optional argument P is present, test this instead of point."
1874   (or (sp-point-in-string p)
1875       (sp-point-in-comment p)))
1876
1877 ;; TODO: add -p suffix
1878 (defun sp-point-in-symbol (&optional p)
1879   "Return non-nil if `point' is inside symbol.
1880
1881 If P is non-nil, interpret it as buffer position and test there.
1882
1883 Point is inside symbol if characters on both sides of the point
1884 are in either word or symbol class."
1885   (setq p (or p (point)))
1886   (save-excursion
1887     (goto-char p)
1888     (and (/= 0 (following-char))
1889          (memq (char-syntax (following-char)) '(?w ?_))
1890          (memq (char-syntax (preceding-char)) '(?w ?_)))))
1891
1892 (defun sp--single-key-description (event)
1893   "Return a description of the last EVENT.
1894
1895 Replace all the function key symbols with garbage character (ň).
1896
1897 TODO: fix this!"
1898   (let ((original (single-key-description event)))
1899     (cond
1900      ((string-match-p "<.*?>" original) "ň")
1901      ((string-match-p "SPC" original) " ")
1902      (t original))))
1903
1904 ;; see https://github.com/Fuco1/smartparens/issues/125#issuecomment-20356176
1905 (defun sp--current-indentation ()
1906   "Get the indentation offset of the current line."
1907   (save-excursion
1908     (back-to-indentation)
1909     (current-column)))
1910
1911 (defun sp--calculate-indentation-offset (old-column old-indentation)
1912   "Calculate correct indentation after re-indent.
1913
1914 OLD-COLUMN is the column before reindent.
1915
1916 OLD-INDENTATION is the indentation depth before reindent."
1917   (let ((indentation (sp--current-indentation)))
1918     (cond
1919      ;; Point was in code, so move it along with the re-indented code
1920      ((>= old-column old-indentation)
1921       (+ old-column (- indentation old-indentation)))
1922      ;; Point was indentation, but would be in code now, so move to
1923      ;; the beginning of indentation
1924      ((<= indentation old-column) indentation)
1925      ;; Point was in indentation, and still is, so leave it there
1926      (:else old-column))))
1927
1928 (defun sp--back-to-indentation (old-column old-indentation)
1929   "Set the current column to proper value.
1930
1931 See `sp--keep-indentation'.
1932
1933 OLD-COLUMN is the column before reindent.
1934
1935 OLD-INDENTATION is the indentation depth before reindent."
1936   (let ((offset (sp--calculate-indentation-offset old-column old-indentation)))
1937     (move-to-column offset)))
1938
1939 ;; TODO: rename to preserve-current-column
1940 (defmacro sp--keep-indentation (&rest body)
1941   "Execute BODY and restore the column.
1942
1943 If point was in code move it along if the line is reinvented so
1944 it is the same distance relative to first code column.
1945
1946 If point was previously in the indentation region but would end
1947 up in code, move it to the first code column.
1948
1949 If point was in the indentation region and is still there after
1950 BODY, do nothing."
1951   (declare (indent 0)
1952            (debug (body)))
1953   (let ((c (make-symbol "c"))
1954         (i (make-symbol "i")))
1955     `(let ((,c (current-column))
1956            (,i (sp--current-indentation)))
1957        ,@body
1958        (sp--back-to-indentation ,c ,i))))
1959
1960 ;; Please contribute these if you come across some!
1961 (defvar sp--self-insert-commands
1962   '(self-insert-command
1963     org-self-insert-command
1964     LaTeX-insert-left-brace)
1965    "List of commands that are some sort of `self-insert-command'.
1966
1967 Many modes rebind \"self-inserting\" keys to \"smart\" versions
1968 which do some additional processing before delegating the
1969 insertion to `self-insert-command'.  Smartparens needs to be able
1970 to distinguish these to properly handle insertion and reinsertion
1971 of pairs and wraps.")
1972
1973 ;; Please contribute these if you come across some!
1974 (defvar sp--special-self-insert-commands
1975   '(
1976     TeX-insert-dollar
1977     TeX-insert-quote
1978     quack-insert-opening-paren
1979     quack-insert-closing-paren
1980     quack-insert-opening-bracket
1981     quack-insert-closing-bracket
1982     racket-insert-closing-paren
1983     racket-insert-closing-bracket
1984     racket-insert-closing-brace
1985     )
1986    "List of commands which are handled as if they were `self-insert-command's.
1987
1988 Some modes redefine \"self-inserting\" keys to \"smart\" versions
1989 which do some additional processing but do _not_ delegate the
1990 insertion to `self-insert-command', instead inserting via
1991 `insert'.  Smartparens needs to be able to distinguish these to
1992 properly handle insertion and reinsertion of pairs and wraps.
1993
1994 The `sp--post-self-insert-hook-handler' is called in the
1995 `post-command-hook' for these commands.")
1996
1997 (defun sp--self-insert-command-p ()
1998   "Return non-nil if `this-command' is some sort of `self-insert-command'."
1999   (memq this-command sp--self-insert-commands))
2000
2001 (defun sp--special-self-insert-command-p ()
2002   "Return non-nil if `this-command' is \"special\" self insert command.
2003
2004 A special self insert command is one that inserts a character but
2005 does not trigger `post-self-insert-hook'."
2006   (memq this-command sp--special-self-insert-commands))
2007
2008 (defun sp--signum (x)
2009   "Return 1 if X is positive, -1 if negative, 0 if zero."
2010   (cond ((> x 0) 1) ((< x 0) -1) (t 0)))
2011
2012 ;; The structure returned by sp-get-sexp is a plist with following properties:
2013 ;;
2014 ;; :beg    - point in the buffer before the opening delimiter (ignoring prefix)
2015 ;; :end    - point in the buffer after the closing delimiter
2016 ;; :op     - opening delimiter
2017 ;; :cl     - closing delimiter
2018 ;; :prefix - expression prefix
2019 ;;
2020 ;; This structure should never be accessed directly and should only be
2021 ;; exposed by the sp-get macro.  This way, we can later change the
2022 ;; internal representation without much trouble.
2023
2024 (defmacro sp-compare-sexps (a b &optional fun what-a what-b)
2025   "Return non-nil if the expressions A and B are equal.
2026
2027 Two expressions are equal if their :beg property is the same.
2028
2029 If optional argument FUN is non-nil, it is the comparison
2030 function.
2031
2032 If optional argument WHAT-A is non-nil, use it as a keyword on
2033 which to do the comparsion (default to :beg).
2034
2035 If optional argument WHAT-B is non-nil, use it as a keyword on
2036 which to do the comparsion (default to WHAT-A)."
2037   (declare (debug (form form &optional functionp keywordp keywordp)))
2038   (setq fun (or fun 'equal))
2039   (setq what-a (or what-a :beg))
2040   (setq what-b (or what-b what-a))
2041   `(,fun (sp-get ,a ,what-a) (sp-get ,b ,what-b)))
2042
2043 (defun sp-message (key &optional return)
2044   "Display a message.
2045
2046 KEY is either a string or list of strings, or a keyword,
2047 in which case the string list is looked up in
2048 `sp-message-alist'.  The string to be displayed is chosen based on
2049 the `sp-message-width' variable.
2050
2051 If RETURN is non-nil return the string instead of printing it."
2052   (let ((msgs (cond ((listp key) key)
2053                     ((stringp key) (list key))
2054                     (t (cdr (assq key sp-message-alist))))))
2055     (when (and msgs sp-message-width)
2056       (if (eq sp-message-width t)
2057           (if return (car msgs) (message "%s." (car msgs)))
2058         (let ((maxlen (if (eq sp-message-width 'frame)
2059                           (frame-width)
2060                         sp-message-width))
2061               (s nil))
2062           (dolist (msg msgs)
2063             (if (and (<= (length msg) maxlen)
2064                      (> (length msg) (length s)))
2065                 (setf s msg)))
2066           (when s
2067             (if return s (message "%s." s))))))))
2068
2069
2070 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2071 ;; Adding/removing of pairs/bans/allows etc.
2072
2073 (defun sp--merge-prop (prop new-pair old-pair)
2074   "Merge a property PROP from NEW-PAIR into OLD-PAIR.
2075
2076 The list OLD-PAIR must not be nil."
2077   (let ((new-val (plist-get new-pair prop)))
2078     (cl-case prop
2079       (:close (plist-put old-pair :close new-val))
2080       (:prefix (plist-put old-pair :prefix new-val))
2081       (:suffix (plist-put old-pair :suffix new-val))
2082       (:skip-match (plist-put old-pair :skip-match new-val))
2083       (:trigger (plist-put old-pair :trigger new-val))
2084       (:trigger-wrap (plist-put old-pair :trigger-wrap new-val))
2085       ((:actions :when :unless :pre-handlers :post-handlers)
2086        (cl-case (car new-val)
2087          (:add (plist-put old-pair prop (-union (plist-get old-pair prop) (cdr new-val))))
2088          (:rem (plist-put old-pair prop (-difference (plist-get old-pair prop) (cdr new-val))))
2089          (t
2090           (cond
2091            ;; this means we have ((:add ...) (:rem ...)) argument
2092            ((and new-val
2093                  (listp (car new-val))
2094                  (memq (caar new-val) '(:add :rem)))
2095             (let ((a (assq :add new-val))
2096                   (r (assq :rem new-val)))
2097               (plist-put old-pair prop (-union (plist-get old-pair prop) (cdr a)))
2098               (plist-put old-pair prop (-difference (plist-get old-pair prop) (cdr r)))))
2099            (t
2100             (plist-put old-pair prop (plist-get new-pair prop))))))))))
2101
2102 (defun sp--merge-pairs (old-pair new-pair)
2103   "Merge OLD-PAIR and NEW-PAIR.
2104 This modifies the OLD-PAIR by side effect."
2105   (let ((ind 0))
2106     (--each new-pair
2107       (when (= 0 (% ind 2))
2108         (sp--merge-prop it new-pair old-pair))
2109       (setq ind (1+ ind))))
2110   old-pair)
2111
2112 (defun sp--update-pair (new-pair old-pair)
2113   "Copy properties from NEW-PAIR to OLD-PAIR.
2114
2115 The list OLD-PAIR must not be nil."
2116   (let ((ind 0))
2117     (--each new-pair
2118       (when (= 0 (% ind 2))
2119         (when (or (not (plist-get old-pair it))
2120                   ;; HACK: we don't want to overwrite list properties
2121                   ;; that aren't just :add with :add because this
2122                   ;; would break the "idempotency".
2123                   (not (equal '(:add) (plist-get new-pair it))))
2124           (plist-put old-pair it (plist-get new-pair it))))
2125       (setq ind (1+ ind))))
2126   old-pair)
2127
2128 (defun sp--update-pair-list (pair mode)
2129   "Update the PAIR for major mode MODE.
2130
2131 If this pair is not defined yet for this major mode, add it.  If
2132 this pair is already defined, replace all the properties in the
2133 old definition with values from PAIR."
2134   ;; get the structure relevant to mode.  t means global setting
2135   (let ((struct (--first (eq mode (car it)) sp-pairs)))
2136     (if (not struct)
2137         (!cons (cons mode (list pair)) sp-pairs)
2138       ;; this does NOT merge changes, only replace the values at
2139       ;; properties.  Open delimiter works as ID as usual.
2140       (let ((old-pair (--first (equal (plist-get pair :open)
2141                                       (plist-get it :open))
2142                                (cdr struct)))
2143             (open (plist-get pair :open)))
2144         (if (not old-pair)
2145             (progn
2146               (unless (or (plist-get pair :close)
2147                           (sp--get-pair open (assq t sp-pairs)))
2148                 (error "Pair %s was never defined, please specify closing delimiter in instead of passing `nil'" open))
2149               (setcdr struct (cons pair (cdr struct))))
2150           (sp--update-pair pair old-pair)))))
2151   sp-pairs)
2152
2153 (defun sp--get-pair (open list)
2154   "Get the pair with id OPEN from list LIST."
2155   (--first (equal open (plist-get it :open)) list))
2156
2157 (defun sp--get-pair-definition (open list &optional prop)
2158   "Get the definition of a pair identified by OPEN from list LIST.
2159
2160 If PROP is non-nil, return the value of that property instead."
2161   (let ((pair (sp--get-pair open list)))
2162     (if prop
2163         (cond
2164          ((eq prop :op-l)
2165           (length (plist-get pair :open)))
2166          ((eq prop :cl-l)
2167           (length (plist-get pair :close)))
2168          ((eq prop :len)
2169           (+ (length (plist-get pair :open)) (length (plist-get pair :close))))
2170          ((eq prop :post-handlers)
2171           (--filter (not (listp it)) (plist-get pair prop)))
2172          ((eq prop :post-handlers-cond)
2173           (--filter (listp it) (plist-get pair :post-handlers)))
2174          ((eq prop :when)
2175           (--filter (not (listp it)) (plist-get pair :when)))
2176          ((eq prop :when-cond)
2177           (-flatten (-concat (--filter (listp it) (plist-get pair :when)))))
2178          (t (plist-get pair prop)))
2179       pair)))
2180
2181 (defun sp-get-pair-definition (open mode &optional prop)
2182   "Get the definition of pair identified by OPEN.
2183
2184 OPEN is the opening delimiter, MODE is the major mode symbol or t
2185 for global definition.
2186
2187 If PROP is non-nil, return the value of that property instead."
2188   (sp--get-pair-definition open (cdr (assq mode sp-pairs)) prop))
2189
2190 (defun sp-get-pair (open &optional prop)
2191   "Return the definition of pair defined by OPEN in the current buffer.
2192
2193 The value is fetched from `sp-local-pairs'.
2194
2195 If PROP is non-nil, return the value of that property instead."
2196   (sp--get-pair-definition open sp-local-pairs prop))
2197
2198 (defun sp--merge-pair-configurations (specific &optional current)
2199   "Merge SPECIFIC pair configuration to the CURRENT configuration.
2200
2201 CURRENT defaults to `sp-local-pairs' if it is non-nil or the
2202 global definition from `sp-pairs' if `sp-local-pairs' is nil."
2203   (let* ((global (or current sp-local-pairs (cdr (assq t sp-pairs))))
2204          (local specific)
2205          (result nil))
2206     ;; copy the pairs on global list first.  This creates new plists
2207     ;; so we can modify them without changing the global "template"
2208     ;; values.
2209     (dolist (old-pair global)
2210       (!cons (list :open (plist-get old-pair :open)) result))
2211
2212     ;; merge the global list with result.  This basically "deep copy"
2213     ;; global list.  We use `sp--merge-pairs' because it also clones
2214     ;; the list properties (actions, filters etc.)
2215     (dolist (new-pair global)
2216       (let ((old-pair (sp--get-pair (plist-get new-pair :open) result)))
2217         (sp--merge-pairs old-pair new-pair)))
2218
2219     ;; for each local pair, merge it into the global definition
2220     (dolist (new-pair local)
2221       (let ((old-pair (sp--get-pair (plist-get new-pair :open) result)))
2222         (if old-pair
2223             (sp--merge-pairs old-pair new-pair)
2224           ;; pair does not have global definition, simply copy it over
2225           (!cons
2226            ;; this "deep copy" the new-pair
2227            (sp--merge-pairs (list :open (plist-get new-pair :open)) new-pair)
2228            ;; TODO: remove the nil lists from the definitions
2229            result))))
2230     result))
2231
2232 (defun sp-wrap-with-pair (pair)
2233   "Wrap the following expression with PAIR.
2234
2235 This function is a non-interactive helper.  To use this function
2236 interactively, bind the following lambda to a key:
2237
2238  (lambda (&optional arg) (interactive \"P\") (sp-wrap-with-pair \"(\"))
2239
2240 This lambda accepts the same prefix arguments as
2241 `sp-select-next-thing'.
2242
2243 If region is active and `use-region-p' returns true, the region
2244 is wrapped instead.  This is useful with selection functions in
2245 `evil-mode' to wrap regions with pairs."
2246   (let* ((arg (or current-prefix-arg 1))
2247          (sel (and (not (use-region-p))
2248                    (sp-select-next-thing-exchange
2249                     arg
2250                     (cond
2251                      ;; point is inside symbol and smart symbol wrapping is disabled
2252                      ((and (sp-point-in-symbol)
2253                            (or (eq sp-wrap-entire-symbol 'globally)
2254                                (memq major-mode sp-wrap-entire-symbol)))
2255                       (point))
2256                      ;; wrap from point, not the start of the next expression
2257                      ((and sp-wrap-from-point
2258                            (not (sp-point-in-symbol)))
2259                       (point))))))
2260          (active-pair (--first (equal (car it) pair) sp-pair-list))
2261          (rb (region-beginning))
2262          (re (region-end)))
2263     (goto-char re)
2264     (insert (cdr active-pair))
2265     (goto-char rb)
2266     (insert (car active-pair))
2267     (if (use-region-p)
2268         (sp--indent-region rb re)
2269       (sp-get sel (sp--indent-region :beg :end)))))
2270
2271 (cl-defun sp-pair (open
2272                    close
2273                    &key
2274                    trigger
2275                    trigger-wrap
2276                    (actions '(wrap insert autoskip navigate))
2277                    when
2278                    unless
2279                    pre-handlers
2280                    post-handlers
2281                    wrap
2282                    bind
2283                    insert)
2284   "Add a pair definition.
2285
2286 OPEN is the opening delimiter.  Every pair is uniquely determined
2287 by this string.
2288
2289 CLOSE is the closing delimiter.  You can use nil for this
2290 argument if you are updating an existing definition.  In this
2291 case, the old value is retained.
2292
2293 TRIGGER is an optional trigger for the pair.  The pair will be
2294 inserted if either OPEN or TRIGGER is typed.  This is usually
2295 used as a shortcut for longer pairs or for pairs that can't be
2296 typed easily.
2297
2298 TRIGGER-WRAP is the same as TRIGGER but used for wrapping.
2299
2300 ACTIONS is a list of actions that smartparens will perform with
2301 this pair.  Possible values are:
2302
2303 - insert  - autoinsert the closing pair when opening pair is
2304   typed.
2305 - wrap    - wrap an active region with the pair defined by opening
2306   delimiter if this is typed while region is active.
2307 - autoskip - if the sexp is active or `sp-autoskip-closing-pair' is
2308   set to 'always, skip over the closing delimiter if user types its
2309   characters in order.
2310 - navigate - enable this pair for navigation/highlight and strictness
2311   checks
2312 - escape - allow autoescaping of this delimiter in string contexts
2313
2314 If the ACTIONS argument has value :rem, the pair is removed.
2315 This can be used to remove default pairs you don't want to use.
2316 For example: (sp-pair \"[\" nil :actions :rem)
2317
2318 WHEN is a list of predicates that test whether the action
2319 should be performed in current context.  The values in the list
2320 should be names of the predicates (that is symbols, not
2321 lambdas!).  They should accept three arguments: opening
2322 delimiter (which uniquely determines the pair), action and
2323 context.  The context argument can have values:
2324
2325 - string  - if point is inside string.
2326 - comment - if point is inside comment.
2327 - code    - if point is inside code.  This context is only
2328   recognized in programming modes that define string semantics.
2329
2330 If *any* filter returns t, the action WILL be performed. A number
2331 of filters are predefined: `sp-point-after-word-p',
2332 `sp-point-before-word-p', `sp-in-string-p',
2333 `sp-point-before-eol-p' etc.
2334
2335 When clause also supports a special format for delayed insertion.
2336 The condition is a list with commands, predicates (with three
2337 arguments as regular when form) or strings specifying the last
2338 event.  All three types can be combined in one list.  The pair
2339 will be inserted *after* the next command if it matches the any
2340 command on the list, if the last event matches any string on the
2341 list or if any predicate returns true.  If the pair's :when
2342 clause contains this special form, it will never be immediately
2343 inserted and will always test for delayed insertion.
2344
2345 UNLESS is a list of predicates.  The conventions are the same as
2346 for the WHEN list.  If *any* filter on this list returns t, the
2347 action WILL NOT be performed.  The predicates in the WHEN list
2348 are checked first, and if any of them succeeds, the UNLESS list
2349 is not checked.
2350
2351 Note: the functions on the WHEN/UNLESS lists are also called
2352 \"filters\" in the documentation.
2353
2354 All the filters are run *after* the trigger character is
2355 inserted.
2356
2357 PRE-HANDLERS is a list of functions that are called before there
2358 has been some action caused by this pair.  The arguments are the
2359 same as for filters.  Context is relative to the point *before*
2360 the last inserted character.  Because of the nature of the
2361 wrapping operation, this hook is not called if the action is
2362 wrapping.
2363
2364 POST-HANDLERS is a list of functions that are called after there
2365 has been some action caused by this pair.  The arguments are the
2366 same as for filters.  Context is relative to current position of
2367 point *after* the closing pair was inserted.
2368
2369 After a wrapping action, the point might end on either side of
2370 the wrapped region, depending on the original direction.  You can
2371 use the variable `sp-last-wrapped-region' to retrieve information
2372 about the wrapped region and position the point to suit your
2373 needs.
2374
2375 A special syntax for conditional execution of hooks is also
2376 supported.  If the added item is a list (function command1
2377 command2...), where function is a 3 argument function described
2378 above and command(s) can be either name of a command or a string
2379 representing an event.  If the last command or event as described
2380 by `single-key-description' matches any on the list, the hook
2381 will be executed.  This means these hooks are run not after the
2382 insertion, but after the *next* command is executed.
2383
2384 Example:
2385   ((lambda (id act con)
2386      (save-excursion
2387        (newline))) \"RET\" newline)
2388
2389 This function will move the closing pair on its own line only if
2390 the next command is `newline' or is triggered by RET.  Otherwise
2391 the pairs stay on the same line.
2392
2393 WRAP is a key binding to which a \"wrapping\" action is bound.
2394 The key should be in format that is accepted by `kbd'.  This
2395 option binds a lambda form:
2396
2397   `(lambda (&optional arg)
2398      (interactive \"P\")
2399      (sp-wrap-with-pair ,OPEN))
2400
2401 to the specified key sequence.  The binding is added to global
2402 keymap.  When executed, it wraps ARG (default 1) expressions with
2403 this pair (like `paredit-wrap-round' and friends).  Additionally,
2404 it accepts the same prefix arguments as `sp-select-next-thing'.
2405
2406 BIND is equivalent to WRAP.  It is a legacy setting and will be
2407 removed soon.
2408
2409 INSERT is a key binding to which an \"insert\" action is bound.
2410 The key should be in format that is accepted by `kbd'.  This is
2411 achieved by binding a lambda form:
2412
2413  (lambda () (interactive) (sp-insert-pair \"pair-id\"))
2414
2415 to the supplied key, where pair-id is the open delimiter of the
2416 pair.  The binding is added to the global map.  You can also bind
2417 a similar lambda manually.  To only bind this in specific major
2418 modes, use this property on `sp-local-pair' instead."
2419   (if (eq actions :rem)
2420       (let ((global-list (assq t sp-pairs)))
2421         (setcdr global-list (--remove (equal (plist-get it :open) open) (cdr global-list)))
2422         (--each (buffer-list)
2423           (with-current-buffer it (sp--remove-local-pair open))))
2424     (let ((pair nil))
2425       (setq pair (plist-put pair :open open))
2426       (when close (plist-put pair :close close))
2427       (when trigger (plist-put pair :trigger trigger))
2428       (when trigger-wrap (plist-put pair :trigger-wrap trigger-wrap))
2429       (dolist (arg `((:actions . ,actions)
2430                      (:when . ,when)
2431                      (:unless . ,unless)
2432                      (:pre-handlers . ,pre-handlers)
2433                      (:post-handlers . ,post-handlers)))
2434         ;; We only consider "nil" as a proper value if the property
2435         ;; already exists in the pair.  In that case, we will set it to
2436         ;; nil.  This allows for removing properties in global
2437         ;; definitions.
2438         (when (or (cdr arg)
2439                   (sp-get-pair-definition open t (car arg)))
2440           (plist-put pair (car arg) (cdr arg))))
2441       (sp--update-pair-list pair t))
2442     (when (or wrap bind) (global-set-key (read-kbd-macro (or wrap bind))
2443                                          `(lambda (&optional arg)
2444                                             (interactive "P")
2445                                             (sp-wrap-with-pair ,open))))
2446     (when insert (global-set-key (kbd insert) `(lambda () (interactive) (sp-insert-pair ,open)))))
2447   (sp--update-local-pairs-everywhere)
2448   sp-pairs)
2449
2450 (cl-defun sp-local-pair (modes
2451                          open
2452                          close
2453                          &key
2454                          trigger
2455                          trigger-wrap
2456                          (actions '(:add))
2457                          (when '(:add))
2458                          (unless '(:add))
2459                          (pre-handlers '(:add))
2460                          (post-handlers '(:add))
2461                          wrap
2462                          bind
2463                          insert
2464                          prefix
2465                          suffix
2466                          skip-match)
2467   "Add a local pair definition or override a global definition.
2468
2469 MODES can be a single mode or a list of modes where these settings
2470 should be applied.
2471
2472 PREFIX is a regular expression matching an optional prefix for
2473 this pair in the specified major modes.  If not specified, the
2474 characters of expression prefix syntax class are automatically
2475 considered instead.  This can be used to attach custom prefixes
2476 to pairs, such as prefix \"\\function\" in \\function{arg} in
2477 `LaTeX-mode'.
2478
2479 SUFFIX is a regular expression matching an optional suffix for
2480 this pair in the specified major modes.  If not specified, the
2481 characters of punctuation syntax class are automatically
2482 considered instead.
2483
2484 The rest of the arguments have same semantics as in `sp-pair'.
2485
2486 If the pair is not defined globally, ACTIONS defaults to (wrap
2487 insert) instead of (:add) (which inherits global settings)
2488
2489 The pairs are uniquely identified by the opening delimiter.  If you
2490 replace the closing one with a different string in the local
2491 definition, this will override the global closing delimiter.
2492
2493 The list arguments can optionally be of form starting with
2494 \":add\" or \":rem\" when these mean \"add to the global list\"
2495 and \"remove from the global list\" respectively.  Otherwise,
2496 the global list is replaced.  If you wish to both add and remove
2497 things with single call, use \"((:add ...) (:rem ...))\" as an
2498 argument.  Therefore,
2499
2500   :when '(:add my-test)
2501
2502 would mean \"use the global settings for this pair, but also this
2503 additional test\". If no value is provided for list arguments,
2504 they default to \"(:add)\" which means they inherit the list from
2505 the global definition.
2506
2507 To disable a pair in a major mode, simply set its actions set to
2508 nil. This will ensure the pair is not even loaded when the mode is
2509 activated.
2510
2511 If WRAP is non-nil, the binding is added into major mode keymap
2512 called \"foo-mode-map\".  If the mode does not follow this
2513 convention, you will need to bind the function manually (see
2514 `sp-pair' to how the function is named for each particular pair).
2515 The bindings are not added into `smartparens-mode-map' to prevent
2516 clashes between different modes.
2517
2518 BIND is equivalent to WRAP.  It is a legacy setting and will be
2519 removed soon.
2520
2521 The binding for INSERT follows the same convention as BIND.  See
2522 `sp-pair' for more info.
2523
2524 You can provide a function SKIP-MATCH, that will take three
2525 arguments: the currently matched delimiter, beginning of match
2526 and end of match.  If this function returns true, the
2527 `sp-get-paired-expression' matcher will ignore this match.  You
2528 can use this to skip over expressions that serve multiple
2529 functions, such as if/end pair or unary if in Ruby or * in
2530 markdown when it signifies list item instead of emphasis.  In
2531 addition, there is a global per major-mode option, see
2532 `sp-navigate-skip-match'."
2533   (if (eq actions :rem)
2534       (dolist (m (-flatten (list modes)))
2535         (let ((mode-pairs (assq m sp-pairs)))
2536           (setcdr mode-pairs
2537                   (--remove (equal (plist-get it :open) open)
2538                             (cdr mode-pairs))))
2539         (sp-with-buffers-using-mode m
2540           (sp--remove-local-pair open)))
2541     (dolist (m (-flatten (list modes)))
2542       (let* ((pair nil))
2543         (setq pair (plist-put pair :open open))
2544         (when close (plist-put pair :close close))
2545         (when trigger (plist-put pair :trigger trigger))
2546         (when trigger-wrap (plist-put pair :trigger-wrap trigger-wrap))
2547         (when prefix (plist-put pair :prefix prefix))
2548         (when suffix (plist-put pair :suffix suffix))
2549         (when skip-match (plist-put pair :skip-match skip-match))
2550         (when (and (not (sp-get-pair-definition open t))
2551                    (equal actions '(:add)))
2552           (setq actions '(wrap insert autoskip navigate)))
2553         (plist-put pair :actions actions)
2554         (plist-put pair :when when)
2555         (plist-put pair :unless unless)
2556         (plist-put pair :pre-handlers pre-handlers)
2557         (plist-put pair :post-handlers post-handlers)
2558         (sp--update-pair-list pair m)
2559         (-when-let* ((symbol (intern (concat (symbol-name m) "-map")))
2560                      (map (and (boundp symbol) (symbol-value symbol))))
2561           (when (or wrap bind) (define-key map
2562                                  (read-kbd-macro (or wrap bind))
2563                                  `(lambda (&optional arg)
2564                                     (interactive "P")
2565                                     (sp-wrap-with-pair ,open))))
2566           (when insert (define-key map
2567                          (kbd insert)
2568                          `(lambda () (interactive) (sp-insert-pair ,open))))))))
2569   (sp--update-local-pairs-everywhere (-flatten (list modes)))
2570   sp-pairs)
2571
2572 (cl-defun sp-local-tag (modes trig open close &key
2573                               (transform 'identity)
2574                               (actions '(wrap insert))
2575                               post-handlers)
2576   "Add a tag definition.
2577
2578 MODES is a mode or a list of modes where this tag should
2579 activate.  It is impossible to define global tags.
2580
2581 TRIG is the trigger sequence.  It can be a string of any length.
2582 If more triggers share a common prefix, the shortest trigger is
2583 executed.
2584
2585 OPEN is the format of the opening tag.  This is inserted before
2586 the active region.
2587
2588 CLOSE is the format of the closing tag.  This is inserted after
2589 the active region.
2590
2591 Opening and closing tags can optionally contain the _ character.
2592
2593 If the opening tag contains the _ character, after you type the
2594 trigger, the region is wrapped with \"skeleton\" tags and a
2595 special tag editing mode is entered.  The text you now type is
2596 substituted for the _ character in the opening tag.
2597
2598 If the closing tag contains the _ character, the text from the
2599 opening pair is mirrored to the closing pair and substituted for
2600 the _ character.
2601
2602 TRANSFORM is a function name (symbol) that is called to perform a
2603 transformation of the opening tag text before this is inserted to
2604 the closing tag.  For example, in html tag it might simply select
2605 the name of the tag and cut off the tag attributes (like
2606 class/style etc.).  Defaults to identity.
2607
2608 ACTIONS is a list of actions this tag should support. Currently,
2609 only \"wrap\" action is supported.  Usually, you don't need to
2610 specify this argument.
2611
2612 POST-HANDLERS is a list of functions that are called after the
2613 tag is inserted.  If the tag does contain the _ character, these
2614 functions are called after the tag editing mode is exited.  Each
2615 function on this list should accept two arguments: the trigger
2616 string and the action."
2617   (dolist (mode (-flatten (list modes)))
2618     (let* ((tag-list (assq mode sp-tags))
2619            (tag (--first (equal trig (plist-get it :trigger)) (cdr tag-list)))
2620            (new-tag nil))
2621       (setq new-tag (plist-put new-tag :trigger trig))
2622       (plist-put new-tag :open open)
2623       (plist-put new-tag :close close)
2624       (when transform (plist-put new-tag :transform transform))
2625       (when actions (plist-put new-tag :actions actions))
2626       (when post-handlers (plist-put new-tag :post-handlers post-handlers))
2627       (if tag-list
2628           (if (not actions)
2629               (setcdr tag-list (--remove (equal trig (plist-get it :trigger)) (cdr tag-list)))
2630             (if (not tag)
2631                 (setcdr tag-list (cons new-tag (cdr tag-list)))
2632               (sp--update-pair new-tag tag)))
2633         ;; mode doesn't exist
2634         (when actions
2635           (!cons (cons mode (list new-tag)) sp-tags))))))
2636
2637
2638 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2639 ;; Overlay management
2640
2641 ;; burlywood4
2642 (defface sp-pair-overlay-face
2643   '((t (:inherit highlight)))
2644   "The face used to highlight pair overlays."
2645   :group 'smartparens)
2646
2647 (defface sp-wrap-overlay-face
2648   '((t (:inherit sp-pair-overlay-face)))
2649   "The face used to highlight wrap overlays.
2650
2651 When the user wraps a region with multi-character pair a special
2652 insertion mode is entered.  This face is used for the overlays
2653 where the possible wrappings are displayed.
2654
2655 The opening and closing delimiters use
2656 `sp-wrap-overlay-opening-pair' and `sp-wrap-overlay-closing-pair'
2657 respectively."
2658   :group 'smartparens)
2659
2660 (defface sp-wrap-overlay-opening-pair
2661   '((t (:inherit sp-wrap-overlay-face
2662         :foreground "green")))
2663   "The face used to highlight opening pairs for wrapping.
2664
2665 See `sp-wrap-overlay-face'."
2666   :group 'smartparens)
2667
2668 (defface sp-wrap-overlay-closing-pair
2669   '((t (:inherit sp-wrap-overlay-face
2670         :foreground "red")))
2671   "The face used to highlight closing pairs for wrapping.
2672
2673 See `sp-wrap-overlay-face'."
2674   :group 'smartparens)
2675
2676 (defface sp-wrap-tag-overlay-face
2677   '((t (:inherit sp-pair-overlay-face)))
2678   "The face used to highlight wrap tag overlays."
2679   :group 'smartparens)
2680
2681 (defvar sp-pair-overlay-list '()
2682   "List of overlays used for tracking inserted pairs.
2683
2684 When a pair is inserted, an overlay is created over it.  When the
2685 user starts typing the closing pair we will not insert it again.
2686 If user leaves the overlay, it is canceled and the insertion
2687 works again as usual.")
2688 (make-variable-buffer-local 'sp-pair-overlay-list)
2689
2690 (defvar sp-wrap-overlays nil
2691   "Cons pair of wrap overlays.")
2692 (make-variable-buffer-local 'sp-wrap-overlays)
2693
2694 (defvar sp-wrap-tag-overlays nil
2695   "Cons pair of tag wrap overlays.")
2696 (make-variable-buffer-local 'sp-wrap-tag-overlays)
2697
2698 (defvar sp-pair-overlay-keymap (make-sparse-keymap)
2699   "Keymap for the pair overlays.")
2700 (define-key sp-pair-overlay-keymap (kbd "C-g")
2701   '(menu-item nil sp-remove-active-pair-overlay :filter
2702               (lambda (cmd)
2703                 (unless (bound-and-true-p company-my-keymap)
2704                   cmd))))
2705
2706 (defvar sp-wrap-overlay-keymap (make-sparse-keymap)
2707   "Keymap for the wrap overlays.")
2708 (define-key sp-wrap-overlay-keymap (kbd "C-g") 'sp-wrap-cancel)
2709
2710 (defun sp--overlays-at (&optional pos)
2711   "Wrapper around `overlays-at' to get smartparens overlays.
2712
2713 POS is the same as for `overlays-at'.
2714
2715 Smartparens functions must use this function instead of
2716 `overlays-at' directly."
2717   ;; TODO: we should probably also check the returned value
2718   (--filter (overlay-get it 'type) (overlays-at (or pos (point)))))
2719
2720 (defun sp--point-in-overlay-p (overlay)
2721   "Return t if point is in OVERLAY."
2722   (and (< (point) (overlay-end overlay))
2723        (> (point) (overlay-start overlay))))
2724
2725 (defun sp--get-overlay-length (overlay)
2726   "Compute the length of OVERLAY."
2727   (- (overlay-end overlay) (overlay-start overlay)))
2728
2729 (defun sp--get-active-overlay (&optional type)
2730   "Get active overlay.
2731
2732 Active overlay is the shortest overlay at point.  Optional
2733 argument TYPE restrict overlays to only those with given type."
2734   (let ((overlays (sp--overlays-at)))
2735     (when type
2736       (setq overlays (--filter (eq (overlay-get it 'type) type) overlays)))
2737     (cond
2738      ((not overlays) nil)
2739      ((not (cdr overlays)) (car overlays))
2740      (t
2741       (--reduce (if (< (sp--get-overlay-length it) (sp--get-overlay-length acc)) it acc) overlays)))))
2742
2743 (defun sp--pair-overlay-create (start end id)
2744   "Create an overlay over the currently inserted pair.
2745
2746 This overlay is used for tracking the position of the point and
2747 marks the active expression.  START and END are the boundaries of
2748 the overlay, ID is the id of the pair."
2749   (let ((overlay (make-overlay start end)))
2750     ;; set priority to 99 so that yasnippet with 100 overloads the
2751     ;; keymap #625
2752     (overlay-put overlay 'priority 99)
2753     (overlay-put overlay 'keymap sp-pair-overlay-keymap)
2754     (overlay-put overlay 'pair-id id)
2755     (overlay-put overlay 'type 'pair)
2756     (!cons overlay sp-pair-overlay-list)
2757     (sp--pair-overlay-fix-highlight)
2758     (add-hook 'post-command-hook 'sp--pair-overlay-post-command-handler nil t)))
2759
2760 (defun sp-wrap-cancel ()
2761   "Cancel the active wrapping."
2762   (interactive)
2763   (unwind-protect
2764       (-let (((obeg . oend) sp-wrap-overlays))
2765         (when (and (not (called-interactively-p 'any))
2766                    (sp--delete-selection-p))
2767           (kill-region (overlay-end obeg) (overlay-start oend)))
2768         (delete-region (overlay-start oend) (overlay-end oend))
2769         (when (> sp-wrap-point sp-wrap-mark)
2770           (let ((beg (delete-and-extract-region (overlay-start obeg) (overlay-end obeg))))
2771             (goto-char (overlay-start oend))
2772             (insert beg))))
2773     (sp-wrap--clean-overlays)))
2774
2775 (defun sp-wrap--clean-overlays ()
2776   "Delete wrap overlays."
2777   (-let [(obeg . oend) sp-wrap-overlays]
2778     (delete-overlay obeg)
2779     (delete-overlay oend)
2780     (setq sp-wrap-overlays nil)))
2781
2782 (defun sp--pair-overlay-fix-highlight ()
2783   "Fix highlighting of the pair overlays.
2784
2785 Only the active overlay should be highlighted."
2786   (--each (sp--overlays-at) (overlay-put it 'face nil))
2787   (let* ((active (sp--get-active-overlay))
2788          (type (and active (overlay-get active 'type))))
2789     (if active
2790         (cond
2791          ((eq 'wrap-tag type)
2792           (when sp-highlight-wrap-tag-overlay
2793             (overlay-put active 'face 'sp-wrap-tag-overlay-face)))
2794          ((eq 'pair type)
2795           (when sp-highlight-pair-overlay
2796             (overlay-put active 'face 'sp-pair-overlay-face))))
2797       ;; edge case where we're at the end of active overlay.  If
2798       ;; there is a wrap-tag overlay, restore it's face
2799       (when sp-wrap-tag-overlays
2800         (overlay-put (car sp-wrap-tag-overlays) 'face 'sp-wrap-tag-overlay-face)))))
2801
2802 (defun sp--pair-overlay-post-command-handler ()
2803   "Remove all invalid pair overlays.
2804
2805 An invalid overlay is one that doesn't have point inside it or
2806 is of zero length.
2807
2808 Also remove all pair overlays if point moved backwards and
2809 `sp-cancel-autoskip-on-backward-movement' is non-nil."
2810   ;; if the point moved backwards, remove all overlays
2811   (if (and sp-cancel-autoskip-on-backward-movement
2812            (< (point) sp-previous-point))
2813       (dolist (o sp-pair-overlay-list) (sp--remove-overlay o))
2814     ;; else only remove the overlays where point is outside them or
2815     ;; their length is zero
2816     (dolist (o (--remove (and (sp--point-in-overlay-p it)
2817                               (> (sp--get-overlay-length it) 0))
2818                          sp-pair-overlay-list))
2819       (sp--remove-overlay o)))
2820   (when sp-pair-overlay-list
2821     (setq sp-previous-point (point))))
2822
2823 (defun sp--reset-memoization (&rest ignored)
2824   "Reset memoization as a safety precaution.
2825
2826 IGNORED is a dummy argument used to eat up arguments passed from
2827 the hook where this is executed."
2828   (setf (sp-state-last-syntax-ppss-point sp-state) nil
2829         (sp-state-last-syntax-ppss-result sp-state) nil))
2830
2831 (defun sp-remove-active-pair-overlay ()
2832   "Deactivate the active overlay.  See `sp--get-active-overlay'."
2833   (interactive)
2834   (-when-let (active-overlay (sp--get-active-overlay 'pair))
2835     (sp--remove-overlay active-overlay)))
2836
2837 (defun sp--remove-overlay (overlay)
2838   "Remove OVERLAY."
2839   ;; if it's not a pair overlay, nothing happens here anyway
2840   (setq sp-pair-overlay-list (--remove (equal it overlay) sp-pair-overlay-list))
2841   ;; if we have zero pair overlays, remove the post-command hook
2842   (when (not sp-pair-overlay-list)
2843     (remove-hook 'post-command-hook 'sp--pair-overlay-post-command-handler t)
2844     ;; this is only updated when sp--pair-overlay-post-command-handler
2845     ;; is active.  Therefore, we need to reset this to 1.  If not, newly
2846     ;; created overlay could be removed right after creation - if
2847     ;; sp-previous-point was greater than actual point
2848     (setq sp-previous-point -1))
2849   (delete-overlay overlay)
2850   (sp--pair-overlay-fix-highlight))
2851
2852 (defun sp--replace-overlay-text (o string)
2853   "Replace text inside overlay O with STRING."
2854   (save-excursion
2855     (goto-char (overlay-start o))
2856     (insert string)
2857     (delete-region (point) (overlay-end o))))
2858
2859 (defun sp--get-overlay-text (o)
2860   "Get text inside overlay O."
2861   (buffer-substring (overlay-start o) (overlay-end o)))
2862
2863
2864 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2865 ;; Action predicates
2866
2867 (defun sp-in-string-p (_id _action context)
2868   "Return t if point is inside string or comment, nil otherwise."
2869   (eq context 'string))
2870
2871 (defun sp-in-string-quotes-p (_id action context)
2872   "Special string test for quotes.
2873
2874 On insert action, test the string context one character back from
2875 point.  Return nil at `bobp'.
2876
2877 On escape action use the value of CONTEXT."
2878   (cond
2879    ((eq action 'insert)
2880     (if (bobp) nil
2881       (save-excursion (backward-char 1) (sp-point-in-string))))
2882    ((eq action 'escape)
2883     (eq context 'string))))
2884
2885 (defun sp-in-docstring-p (_id _action context)
2886   "Return t if point is inside elisp docstring, nil otherwise."
2887   (and (eq context 'string)
2888        (save-excursion
2889          (--when-let (car (sp-get-quoted-string-bounds))
2890            (goto-char it)
2891            (ignore-errors (backward-sexp 3))
2892            (looking-at-p (regexp-opt '("defun" "defmacro"
2893                                        "cl-defun" "cl-defmacro"
2894                                        "defun*" "defmacro*"
2895                                        "lambda" "-lambda")))))))
2896
2897 (defun sp-in-code-p (_id _action context)
2898   "Return t if point is inside code, nil otherwise."
2899   (eq context 'code))
2900
2901 (defun sp-in-comment-p (_id _action context)
2902   "Return t if point is inside comment, nil otherwise."
2903   (eq context 'comment))
2904
2905 (defun sp-in-math-p (_id _action _context)
2906   "Return t if point is inside code, nil otherwise."
2907   (when (functionp 'texmathp)
2908     (texmathp)))
2909
2910 (defun sp-point-before-eol-p (_id action _context)
2911   "Return t if point is followed by optional white spaces and end of line, nil otherwise.
2912 This predicate is only tested on \"insert\" action."
2913   (when (eq action 'insert)
2914     (sp--looking-at-p "\\s-*$")))
2915
2916 (defun sp-point-after-bol-p (id action _context)
2917   "Return t if point follows beginning of line and possibly white spaces, nil otherwise.
2918 This predicate is only tested on \"insert\" action."
2919   (when (eq action 'insert)
2920     (sp--looking-back-p (concat "^\\s-*" (regexp-quote id)))))
2921
2922 (defun sp-point-at-bol-p (id action _context)
2923   "Return t if point is at the beginning of line, nil otherwise.
2924 This predicate is only tested on \"insert\" action."
2925   (when (eq action 'insert)
2926     (sp--looking-back-p (concat "^" (regexp-quote id)))))
2927
2928 (defun sp-point-before-symbol-p (_id action _context)
2929   "Return t if point is followed by a symbol, nil otherwise.
2930 This predicate is only tested on \"insert\" action."
2931   (when (eq action 'insert)
2932     (sp--looking-at-p "\\s_")))
2933
2934 (defun sp-point-before-word-p (_id action _context)
2935   "Return t if point is followed by a word, nil otherwise.
2936 This predicate is only tested on \"insert\" action."
2937   (when (eq action 'insert)
2938     (sp--looking-at-p "\\sw\\|\\s_")))
2939
2940 (defun sp-point-after-word-p (id action _context)
2941   "Return t if point is after a word, nil otherwise.
2942 This predicate is only tested on \"insert\" action."
2943   ;; TODO: remove condition with sp-defpair
2944   (when (memq action '(insert escape))
2945     (sp--looking-back-p (concat "\\(\\sw\\|\\s_\\)" (regexp-quote id)))))
2946
2947 (defun sp-point-before-same-p (id action _context)
2948   "Return t if point is followed by ID, nil otherwise.
2949 This predicate is only tested on \"insert\" action."
2950   (when (eq action 'insert)
2951     (sp--looking-at-p (regexp-quote id))))
2952
2953 (defun sp-point-in-empty-line-p (id _action _context)
2954   "Return t if point is on an empty line, nil otherwise."
2955   (and (sp--looking-at-p "\\s-*$")
2956        (sp--looking-back-p (concat "^\\s-*" (regexp-quote id)))))
2957
2958 (defun sp-char-escaped-p (_id action _context)
2959   "Return non-nil if character before point is escaped with \\."
2960   (when (eq action 'insert)
2961     (save-excursion
2962       (backward-char 1)
2963       (looking-back "\\\\" 1))))
2964
2965
2966 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2967 ;; Pair insertion/deletion/skipping
2968
2969 (defun sp--do-action-p (id action &optional use-inside-string)
2970   "Return t if pair ID can perform ACTION.
2971
2972 If ACTION is a list, return t if at least one action from the
2973 list can be performed.
2974
2975 If USE-INSIDE-STRING is non-nil, use value of
2976 `sp-point-inside-string' instead of testing with
2977 `sp-point-in-string-or-comment'."
2978   (setq action (-flatten (list action)))
2979   (let* ((actions (sp-get-pair id :actions))
2980          (when-l (sp-get-pair id :when))
2981          (unless-l (sp-get-pair id :unless))
2982          (in-string (if use-inside-string
2983                         sp-point-inside-string
2984                       (sp-point-in-string)))
2985          (context (cond
2986                    (in-string 'string)
2987                    ((sp-point-in-comment) 'comment)
2988                    (t 'code)))
2989          a r)
2990     (while (and action (not r))
2991       (setq a (car action))
2992       (setq r (when (memq a actions)
2993                 ;;(and (when-clause) (not (unless-clause)))
2994                 (and (or (not when-l)
2995                          (--some (funcall it id a context) when-l))
2996                      (or (not unless-l)
2997                          (not (--some (funcall it id a context) unless-l))))))
2998       (!cdr action))
2999     r))
3000
3001 (defun sp--get-handler-context (type)
3002   "Return the context constant.  TYPE is type of the handler."
3003   (let ((in-string (cl-case type
3004                      (:pre-handlers
3005                       (save-excursion
3006                         (unless (bobp) (backward-char 1))
3007                         (sp-point-in-string-or-comment)))
3008                      (:post-handlers
3009                       (sp-point-in-string-or-comment)))))
3010     (if in-string 'string 'code)))
3011
3012 (defun sp--get-context (&optional point in-string in-comment)
3013   "Return the context of POINT.
3014
3015 If the optional arguments IN-STRING or IN-COMMENT non-nil, their
3016 value is used instead of a test."
3017   (save-excursion
3018     (goto-char (or point (point)))
3019     (cond
3020      ((or in-string (sp-point-in-string)) 'string)
3021      ((or in-comment (sp-point-in-comment)) 'comment)
3022      (t 'code))))
3023
3024 (defun sp--parse-insertion-spec (fun)
3025   "Parse the insertion specification FUN and return a form to evaluate."
3026   (let ((spec nil)
3027         (after nil)
3028         (last 1))
3029     (cl-labels ((push-non-empty
3030                  (what)
3031                  (unless (equal (cadr what) "")
3032                    (push what spec))))
3033       (with-temp-buffer
3034         (insert fun)
3035         (goto-char (point-min))
3036         (while (re-search-forward "\\(|\\|\\[\\)" nil t)
3037           (cond
3038            ((equal (match-string 0) "[")
3039             (if (save-excursion (backward-char 1) (eq (preceding-char) 92))
3040                 (push-non-empty `(insert ,(concat (buffer-substring-no-properties last (- (point) 2)) "[")))
3041               (push-non-empty `(insert ,(buffer-substring-no-properties last (1- (point)))))
3042               (let* ((p (point))
3043                      (fun-end (progn
3044                                 (re-search-forward "]" nil t)
3045                                 (1- (point))))
3046                      (fun-spec (buffer-substring-no-properties p fun-end))
3047                      (instruction (cond
3048                                    ((equal fun-spec "i")
3049                                     '(indent-according-to-mode))
3050                                    ((equal (aref fun-spec 0) ?d)
3051                                     `(delete-char ,(string-to-number (substring fun-spec 1)))))))
3052                 (when instruction (push instruction spec)))))
3053            ((equal (match-string 0) "|")
3054             (cond
3055              ((save-excursion (backward-char 1) (eq (preceding-char) 92))
3056               (push-non-empty `(insert ,(concat (buffer-substring-no-properties last (- (point) 2)) "|"))))
3057              (t
3058               (push-non-empty `(insert ,(buffer-substring-no-properties last (1- (point)))))
3059               (push 'save-excursion spec)
3060               (when (eq (following-char) 124)
3061                 (forward-char 1)
3062                 (setq after '(indent-according-to-mode)))))))
3063           (setq last (point)))
3064         (push-non-empty `(insert ,(buffer-substring-no-properties last (point-max)))))
3065       (let* ((specr (nreverse spec))
3066              (specsplit (--split-with (not (eq it 'save-excursion)) specr))
3067              (re (-concat (car specsplit) (if (cadr specsplit) (cdr specsplit) nil))))
3068         (cons 'progn (if after (-snoc re after) re))))))
3069
3070 (defun sp--run-function-or-insertion (fun id action context)
3071   "Run a function or insertion.
3072
3073 If FUN is a function, call it with `funcall' with ID, ACTION and
3074 CONTEXT as arguments.
3075
3076 If FUN is a string, interpret it as \"insertion specification\",
3077 see `sp-pair' for description."
3078   (cond
3079    ((functionp fun)
3080     (funcall fun id action context))
3081    ((stringp fun)
3082     (eval (sp--parse-insertion-spec fun)))))
3083
3084
3085 (defvar sp-handler-context nil
3086   "Special variable holding context during handler execution.")
3087
3088 ;; TODO: get rid of `sp-handler-context' and make all the handlers (we
3089 ;; should call them hooks) take better arguments, what we pass now is
3090 ;; useless almost always
3091 (defun sp--run-hook-with-args (id type action &optional context-values)
3092   "Run all the hooks for pair ID of type TYPE on action ACTION.
3093
3094 CONTEXT-VALUES is a plist with arbitrary values (depending on the
3095 action).  A dynamic varable `sp-handler-context' will be bound to
3096 this value during execution of the handler."
3097   (ignore-errors
3098     (let ((hook (sp-get-pair id type))
3099           (context (sp--get-handler-context type)))
3100       (if hook
3101           (let ((sp-handler-context context-values))
3102             (--each hook (sp--run-function-or-insertion it id action context)))
3103         (run-hook-with-args 'tag-hook id action context)))))
3104
3105 ;; TODO: add a test for a symbol property that would tell this handler
3106 ;; not to re=set `sp-last-operation'. Useful for example in "macro
3107 ;; functions" like `my-wrap-with-paren'.
3108 (defun sp--post-command-hook-handler ()
3109   "Handle the situation after some command has executed."
3110   (sp--with-case-sensitive
3111     (when (sp--special-self-insert-command-p)
3112       (sp--post-self-insert-hook-handler))
3113     (ignore-errors
3114       (when smartparens-mode
3115         ;; handle the wrap overlays
3116         (when sp-wrap-overlays
3117           (let* ((overlay (car sp-wrap-overlays))
3118                  (start (overlay-start overlay))
3119                  (end (overlay-end overlay))
3120                  (p (point)))
3121             (when (or (< p sp-previous-point)
3122                       (> p end)
3123                       (< p start))
3124               (sp-wrap-cancel))))
3125         (when sp-wrap-overlays
3126           (setq sp-previous-point (point)))
3127
3128         ;; Here we run the delayed hooks. See issue #80
3129         (cond
3130          ((eq (car-safe (sp-state-delayed-hook sp-state)) :next)
3131           (setf (car (sp-state-delayed-hook sp-state)) :this))
3132          ((eq (car-safe (sp-state-delayed-hook sp-state)) :this)
3133           (let* ((pair (cdr (sp-state-delayed-hook sp-state)))
3134                  (hooks (sp-get-pair pair :post-handlers-cond)))
3135             (--each hooks
3136               (let ((fun (car it))
3137                     (conds (cdr it)))
3138                 (when (or (--any? (eq this-command it) conds)
3139                           (--any? (equal (single-key-description last-command-event) it) conds))
3140                   (sp--run-function-or-insertion
3141                    fun pair 'insert
3142                    (sp--get-handler-context :post-handlers)))))
3143             (setf (sp-state-delayed-hook sp-state) nil)
3144             (setq sp-last-inserted-pair nil))))
3145
3146         ;; Here we run the delayed insertion. Some details in issue #113
3147         (when (and (not (eq sp-last-operation 'sp-insert-pair-delayed))
3148                    sp-delayed-pair)
3149           (let* ((pair (car sp-delayed-pair))
3150                  (beg (cdr sp-delayed-pair))
3151                  (conds (sp-get-pair pair :when-cond))
3152                  (open-pair pair)
3153                  (close-pair (sp-get-pair pair :close)))
3154             (when (and conds
3155                        (--any? (cond
3156                                 ((and (commandp it)
3157                                       (not (stringp it)))
3158                                  (eq this-command it))
3159                                 ((stringp it)
3160                                  (equal (single-key-description last-command-event) it))
3161                                 ((ignore-errors (funcall it pair 'insert (sp--get-handler-context :post-handlers))))) conds))
3162               ;; TODO: refactor this and the same code in
3163               ;; `sp-insert-pair' to a separate function
3164               (sp--run-hook-with-args open-pair :pre-handlers 'insert)
3165               (insert close-pair)
3166               (backward-char (length close-pair))
3167               (sp--pair-overlay-create beg
3168                                        (+ (point) (length close-pair))
3169                                        open-pair)
3170               ;; no auto-escape here? Should be fairly safe
3171               (sp--run-hook-with-args open-pair :post-handlers 'insert)
3172               (setq sp-last-inserted-pair open-pair)
3173               ;; TODO: this is probably useless
3174               (setq sp-last-operation 'sp-insert-pair)))
3175           (setq sp-delayed-pair nil))
3176
3177         (when (eq sp-last-operation 'sp-insert-pair-delayed)
3178           (setq sp-last-operation nil))
3179
3180         (unless (or (sp--self-insert-command-p)
3181                     (sp--special-self-insert-command-p))
3182           ;; unless the last command was a self-insert, remove the
3183           ;; information about the last wrapped region.  It is only used
3184           ;; for: 1. deleting the wrapping immediately after the wrap,
3185           ;; 2. re-wrapping region immediatelly after a sucessful wrap.
3186           ;; Therefore, the deletion should have no ill-effect.  If the
3187           ;; necessity will arise, we can add a different flag.
3188           (setq sp-last-wrapped-region nil)
3189           (setq sp-last-operation nil))
3190
3191         (when show-smartparens-mode
3192           (if (member this-command sp-show-enclosing-pair-commands)
3193               (sp-show--pair-enc-function)
3194             (when (not (eq this-command 'sp-highlight-current-sexp))
3195               (sp-show--pair-delete-enc-overlays))))))))
3196
3197 (defmacro sp--setaction (action &rest forms)
3198   "Use ACTION as a flag to evaluating FORMS.
3199
3200 If ACTION is nil, evaluate FORMS and set it to the value of the
3201 last form; otherwise do nothing."
3202   (declare (debug (form body)))
3203   `(unless ,action
3204      (setq ,action (progn ,@forms))))
3205
3206 ;; TODO: this introduces a regression, where doing C-4 [ inserts [[[[]
3207 ;; figure out how to detect the argument to self-insert-command that
3208 ;; resulted to this insertion
3209 (defun sp--post-self-insert-hook-handler ()
3210   "Handler for `post-self-insert-hook'."
3211   (with-demoted-errors "sp--post-self-insert-hook-handler: %S"
3212     (when smartparens-mode
3213       (sp--with-case-sensitive
3214         (catch 'done
3215           (let (action)
3216             (when (region-active-p)
3217               (condition-case err
3218                   (sp-wrap--initialize)
3219                 (user-error
3220                  (message (error-message-string err))
3221                  ;; we need to remove the undo record of the insertion
3222                  (unless (eq buffer-undo-list t)
3223                    ;; pop all undo info until we hit an insertion node
3224                    (sp--undo-pop-to-last-insertion-node)
3225                    ;; get rid of it and insert an undo boundary marker
3226                    (pop buffer-undo-list)
3227                    (undo-boundary))
3228                  (restore-buffer-modified-p sp-buffer-modified-p)
3229                  (throw 'done nil))))
3230             (cond
3231              (sp-wrap-overlays
3232               (sp-wrap))
3233              (t
3234               ;; TODO: this does not pick correct pair!! it uses insert and not wrapping code
3235               (sp--setaction
3236                action
3237                (-when-let ((_ . open-pairs) (sp--all-pairs-to-insert nil 'wrap))
3238                  (catch 'done
3239                    (-each open-pairs
3240                      (-lambda ((&keys :open open :close close))
3241                        (--when-let (sp--wrap-repeat-last (cons open close))
3242                          (throw 'done it)))))))
3243               (unless overwrite-mode (sp--setaction action (sp-insert-pair)))
3244               (sp--setaction action (sp-skip-closing-pair))
3245               (unless action (sp-escape-open-delimiter))
3246               ;; if nothing happened, we just inserted a character, so
3247               ;; set the apropriate operation.
3248               (unless action
3249                 (setq sp-last-operation 'sp-self-insert))))))))))
3250
3251 ;; Unfortunately, some modes rebind "inserting" keys to their own
3252 ;; handlers but do not hand over the insertion back to
3253 ;; `self-insert-command', rather, they insert via `insert'.
3254 ;; Therefore, we need to call this handler in `post-command-hook' too.
3255 ;; The list `sp--special-self-insert-commands' specifies which
3256 ;; commands to handle specially.
3257 (add-hook 'post-self-insert-hook 'sp--post-self-insert-hook-handler)
3258
3259 ;; TODO: make a proper data structure for state tracking and describe
3260 ;; why we need each of these.
3261 (defun sp--save-pre-command-state ()
3262   "Save some of the buffer state before `pre-command-hook'."
3263   (setq sp-point-inside-string (sp-point-in-string))
3264   (setq sp-pre-command-point (point))
3265   (setq sp-buffer-modified-p (buffer-modified-p)))
3266
3267 (add-hook 'pre-command-hook 'sp--save-pre-command-state)
3268
3269 (defun sp--get-pair-list ()
3270   "Get all non-stringlike pairs.
3271
3272 Return all pairs that are recognized in this `major-mode' and do
3273 not have same opening and closing delimiter.  This is used for
3274 navigation functions."
3275   (--filter (not (string= (car it) (cdr it))) sp-pair-list))
3276
3277 (defun sp--get-stringlike-list ()
3278   "Get all string-like pairs.
3279
3280 Return all pairs that are recognized in this `major-mode' that
3281 have same opening and closing delimiter."
3282   (--filter (string= (car it) (cdr it)) sp-pair-list))
3283
3284 (defun sp--get-allowed-pair-list ()
3285   "Get all allowed non string-like pairs.
3286
3287 Return all pairs that are recognized in this `major-mode', do not
3288 have same opening and closing delimiter and are allowed in the
3289 current context.  See also `sp--get-pair-list'."
3290   (--filter (and (sp--do-action-p (car it) 'navigate)
3291                  (not (equal (car it) (cdr it)))) sp-pair-list))
3292
3293 (defun sp--get-allowed-stringlike-list ()
3294   "Get all allowed string-like pairs.
3295
3296 Return all pairs that are recognized in this `major-mode',
3297 have the same opening and closing delimiter and are allowed in
3298 the current context."
3299   (--filter (and (sp--do-action-p (car it) 'navigate)
3300                  (equal (car it) (cdr it))) sp-pair-list))
3301
3302 (defun sp--get-pair-list-context (&optional action)
3303   "Return all pairs that are recognized in this `major-mode' and
3304 are allowed in the current context."
3305   (setq action (or action 'insert))
3306   (--filter (sp--do-action-p (car it) action) sp-pair-list))
3307
3308 (defun sp--get-pair-list-wrap ()
3309   "Return the list of all pairs that can be used for wrapping."
3310   (--filter (sp--do-action-p (car it) 'wrap) sp-pair-list))
3311
3312 (defun sp--wrap-regexp (string start end)
3313   "Wraps regexp with start and end boundary conditions to avoid
3314 matching symbols in symbols."
3315   (concat "\\(?:" (when start "\\<") string (when end "\\>") "\\)"))
3316
3317 (defun sp--regexp-for-group (parens &rest strings)
3318   "Generates an optimized regexp matching all string, but with
3319 extra boundary conditions depending on parens."
3320   (let* ((start (car parens))
3321          (end (cadr parens)))
3322     (sp--wrap-regexp (regexp-opt strings) start end)))
3323
3324 (defun sp--strict-regexp-opt (strings &optional ignored)
3325   "Like regexp-opt, but with extra boundary conditions to ensure
3326 that the strings are not matched in-symbol."
3327   (if strings
3328       (with-syntax-table
3329           ;; HACK: this is a terrible hack to make ' be treated as a
3330           ;; punctuation.  Many text modes set it as word character which
3331           ;; messes up the regexps
3332           (let ((table (make-syntax-table (syntax-table))))
3333             (modify-syntax-entry ?' "." table)
3334             table)
3335         (--> strings
3336              (-group-by (lambda (string)
3337                           (list (and (string-match-p "\\`\\<" string) t)
3338                                 (and (string-match-p "\\>\\'" string) t)))
3339                         it)
3340              (mapconcat (lambda (g) (apply 'sp--regexp-for-group g)) it "\\|")
3341              (concat "\\(?:" it "\\)")))
3342     "^\\<$"))
3343
3344 (defun sp--strict-regexp-quote (string)
3345   "Like regexp-quote, but make sure that the string is not
3346 matched in-symbol."
3347   (sp--wrap-regexp (regexp-quote string)
3348                    (string-match-p "\\`\\<" string)
3349                    (string-match-p "\\>\\'" string)))
3350
3351 (cl-defun sp--get-opening-regexp (&optional (pair-list (sp--get-pair-list)))
3352   "Return regexp matching any opening pair."
3353   (sp--strict-regexp-opt (--map (car it) pair-list)))
3354
3355 (cl-defun sp--get-closing-regexp (&optional (pair-list (sp--get-pair-list)))
3356   "Return regexp matching any closing pair."
3357   (sp--strict-regexp-opt (--map (cdr it) pair-list)))
3358
3359 (cl-defun sp--get-allowed-regexp (&optional (pair-list (sp--get-allowed-pair-list)))
3360   "Return regexp matching any opening or closing
3361 delimiter for any pair allowed in current context."
3362   (sp--strict-regexp-opt (--mapcat (list (car it) (cdr it)) pair-list)))
3363
3364 (cl-defun sp--get-stringlike-regexp (&optional (pair-list (sp--get-allowed-stringlike-list)))
3365   "Return a regexp matching any string-like delimiter.
3366
3367 In case PAIR-LIST is empty return a regexp that never matches
3368 anything."
3369   (if (consp pair-list)
3370       (regexp-opt (--map (car it) pair-list))
3371     "^\\<$"))
3372
3373 (defun sp--get-last-wraped-region (beg end open close)
3374   "Return `sp-get-sexp' style plist about the last wrapped region.
3375
3376 Note: this function does not retrieve the actual value of
3377 `sp-last-wrapped-region', it merely construct the plist from the
3378 provided values."
3379   (let ((b (make-marker))
3380         (e (make-marker)))
3381     (set-marker b beg)
3382     (set-marker e end)
3383     (set-marker-insertion-type e t)
3384     `(:beg ,b :end ,e :op ,open :cl ,close :prefix "")))
3385
3386 ;; Wrapping is basically the same thing as insertion, only the closing
3387 ;; pair is placed at a distance.
3388
3389 ;; However, we want to be able to insert the *closing* delimiter and
3390 ;; go to the end of block.  This will only work with delimiters which
3391 ;; are unique wrt their opening one.  For more complex wrapping, there
3392 ;; will probably be an IDO/minibuffer interface.  Openings are checked
3393 ;; first.
3394
3395 ;; Inserting the opening delimiter should put the point wherever it
3396 ;; was when we started insertion.
3397
3398 (defun sp-wrap--can-wrap-p ()
3399   "Return non-nil if we can wrap a region.
3400
3401 This is used in advices on various pre-command-hooks from
3402 \"selection deleting\" modes to intercept their actions.
3403
3404 Also added to `self-insert-uses-region-functions' to prevent
3405 `delete-selection-mode' from replacing the region."
3406   (let* ((list (sp--get-pair-list-wrap))
3407          (desc (sp--single-key-description last-command-event)))
3408     (--any? (or (string-prefix-p desc (car it))
3409                 (string-prefix-p desc (cdr it)))
3410             list)))
3411
3412 (defun sp--pair-to-wrap-comparator (prop a b)
3413   "Comparator for wrapping pair selection.
3414
3415 PROP specifies wrapping-end.  A and B are pairs to be compared."
3416   (< (length (plist-get a prop)) (length (plist-get b prop))))
3417
3418 (defun sp--pair-to-wrap (&optional prefix)
3419   "Return information about possible wrapping pairs.
3420
3421 If optional PREFIX is non-nil, this is used to determine the
3422 possible wrapping pairs instead of the text in the wrapping
3423 overlay."
3424   (let* ((working-pairs
3425           ;; TODO: abstract this into a new "sp--get-..." hierarchy
3426           (--filter (sp--do-action-p (plist-get it :open) 'wrap) sp-local-pairs))
3427          (obeg (car sp-wrap-overlays))
3428          (prefix (or prefix (sp--get-overlay-text obeg)))
3429          (opening-pairs (--filter (string-prefix-p prefix (plist-get it :open)) working-pairs))
3430          ;; HACK: Here, we will add special "trigger pairs" to the
3431          ;; opening list.  We set the opening delimiter to the
3432          ;; trigger, leave the rest alone and put the real open into
3433          ;; :open-real property.  When we get the pair back, we will
3434          ;; check this property, and if present, fix the pair back to
3435          ;; the regular form
3436          (wrapper-pairs (->> (--filter (string-prefix-p prefix (or (plist-get it :trigger-wrap) "")) working-pairs)
3437                              (-map (-lambda ((pair &as &plist :open open :trigger-wrap trigger-wrap))
3438                                      (setq pair (copy-sequence pair))
3439                                      (setq pair (plist-put pair :open trigger-wrap))
3440                                      (setq pair (plist-put pair :open-real open))
3441                                      pair))))
3442          (opening-pairs (-concat wrapper-pairs opening-pairs))
3443          (closing-pairs (--filter (string-prefix-p prefix (plist-get it :close)) working-pairs))
3444          (open (car (--sort (sp--pair-to-wrap-comparator :open it other) opening-pairs)))
3445          ;; TODO: do we need the special sorting here?
3446          (close (car (--sort (sp--pair-to-wrap-comparator :close it other) closing-pairs))))
3447     (list :open open
3448           :close close
3449           :opening opening-pairs
3450           :closing closing-pairs)))
3451
3452 (defun sp-wrap--initialize ()
3453   "Initialize wrapping."
3454   (when (and sp-autowrap-region
3455              (sp-wrap--can-wrap-p))
3456     ;; This is the length of string which was inserted by the last
3457     ;; "self-insert" action.  Typically this is 1, but sometimes a
3458     ;; single key inserts two or more characters, such as " in latex
3459     ;; where it translates into `` or ''.
3460     (let ((inserted-string-length (- (point) sp-pre-command-point)))
3461       ;; TODO: get rid of the following variables
3462       (setq sp-wrap-point (- (point) inserted-string-length))
3463       (setq sp-wrap-mark (mark))
3464       ;; balance check
3465       (with-silent-modifications
3466         (let ((inserted-string
3467                (prog1 (delete-and-extract-region sp-wrap-point (point))
3468                  ;; HACK: in modes with string fences, the insertion
3469                  ;; of the delimiter causes `syntax-propertize' to
3470                  ;; fire, but the above deletion doesn't re-run it
3471                  ;; because the cache tells it the state is OK.  We
3472                  ;; need to destroy the cache and re-run the
3473                  ;; `syntax-propertize' on the buffer.  This might be
3474                  ;; expensive, but we only done this on wrap-init so
3475                  ;; it's fine, I guess.
3476                  (setq syntax-propertize--done -1)
3477                  (syntax-propertize (point-max))))
3478               (point-string-context (sp-get-quoted-string-bounds sp-wrap-point))
3479               (mark-string-context (sp-get-quoted-string-bounds (mark))))
3480           ;; If point and mark are inside the same string, we don't
3481           ;; need to check if the region is OK.  If both are outisde
3482           ;; strings, we have to.  If one is inside and the other is
3483           ;; not, no matter what we would break, so we exit.
3484           (cond
3485            ;; inside the same string
3486            ((and point-string-context mark-string-context
3487                  (eq (car point-string-context)
3488                      (car mark-string-context))))
3489            ;; neither is inside string
3490            ((and (not point-string-context)
3491                  (not mark-string-context))
3492             (unless (sp-region-ok-p sp-wrap-point (mark))
3493               (user-error "Mismatched sexp state: wrapping would break structure")))
3494            ;; one is in and the other isn't
3495            ((if point-string-context (not mark-string-context) mark-string-context)
3496             (user-error "Mismatched string state: point %sin string, mark %sin string"
3497                         (if (car-safe point-string-context) "" "not ")
3498                         (if (car-safe mark-string-context) "" "not ")))
3499            ;; both are in but in different strings
3500            (t (user-error "Mismatched string state: point and mark are inside different strings")))
3501           (insert inserted-string)))
3502       ;; if point > mark, we need to move point to mark and reinsert the
3503       ;; just inserted character.
3504       (when (> (point) (mark))
3505         (let ((char (delete-and-extract-region (- (point) inserted-string-length) (point))))
3506           (exchange-point-and-mark)
3507           (insert char)))
3508       (let* ((oleft (make-overlay (- (region-beginning) inserted-string-length)
3509                                   (region-beginning) nil nil t))
3510              (oright (make-overlay (region-end) (region-end) nil nil t)))
3511         (setq sp-wrap-overlays (cons oleft oright))
3512         (when sp-highlight-wrap-overlay
3513           (overlay-put oleft 'face 'sp-wrap-overlay-face)
3514           (overlay-put oright 'face 'sp-wrap-overlay-face))
3515         (overlay-put oleft 'priority 100)
3516         (overlay-put oright 'priority 100)
3517         (overlay-put oleft 'keymap sp-wrap-overlay-keymap)
3518         (overlay-put oleft 'type 'wrap)
3519         (setq sp-previous-point (point))
3520         (goto-char (1+ (overlay-start oleft)))))))
3521
3522 (defun sp-wrap--finalize (wrapping-end open close)
3523   "Finalize a successful wrapping.
3524
3525 WRAPPING-END specifies the wrapping end.  If we wrapped using
3526 opening delimiter it is :open.  If we wrapped using closing
3527 delimiter it is :close.  Position of point after wrapping depends
3528 on this value---if :open, go where the wrapping was initalized,
3529 if :close, go after the newly-formed sexp.
3530
3531 OPEN and CLOSE are the delimiters."
3532   (-let (((obeg . oend) sp-wrap-overlays))
3533     (sp--replace-overlay-text obeg open)
3534     (sp--replace-overlay-text oend close)
3535     (setq sp-last-operation 'sp-wrap-region)
3536     (setq sp-last-wrapped-region
3537           (sp--get-last-wraped-region
3538            (overlay-start obeg) (overlay-end oend)
3539            open close))
3540     (cond
3541      ((eq wrapping-end :open)
3542       (if sp-wrap-respect-direction
3543           (progn
3544             (set-mark (overlay-end oend))
3545             (goto-char (overlay-start obeg)))
3546         (when (> sp-wrap-point sp-wrap-mark)
3547           (set-mark (overlay-start obeg))
3548           (goto-char (overlay-end oend)))))
3549      ((eq wrapping-end :close)
3550       (set-mark (overlay-start obeg))
3551       (goto-char (overlay-end oend))))
3552     (sp-wrap--clean-overlays)
3553     (sp--run-hook-with-args open :post-handlers 'wrap)))
3554
3555 (defun sp-wrap ()
3556   "Try to wrap the active region with some pair.
3557
3558 This function is not ment to be used to wrap sexps with pairs
3559 programatically.  Use `sp-wrap-with-pair' instead."
3560   (-let* (((&plist :open open :close close
3561                    :opening opening-pairs
3562                    :closing closing-pairs) (sp--pair-to-wrap))
3563           ((obeg . oend) sp-wrap-overlays))
3564     (cond
3565      (open
3566       (-let (((&plist :open open :close close :open-real open-real) open))
3567         (when sp-wrap-show-possible-pairs
3568           (overlay-put
3569            oend 'after-string
3570            (mapconcat (lambda (x)
3571                         (if sp-highlight-wrap-overlay
3572                             (concat
3573                              (propertize
3574                               (plist-get x :open) 'face
3575                               'sp-wrap-overlay-opening-pair)
3576                              (propertize
3577                               (plist-get x :close)
3578                               'face 'sp-wrap-overlay-closing-pair))
3579                           (concat (plist-get x :open) (plist-get x :close))))
3580                       opening-pairs " ")))
3581         (when (equal (sp--get-overlay-text obeg) open)
3582           (sp-wrap--finalize :open (or open-real open) close))))
3583      ((and close (= 1 (length closing-pairs)))
3584       (-let (((&plist :open open :close close) close))
3585         (when (equal (sp--get-overlay-text obeg) close)
3586           (sp-wrap--finalize :close open close))))
3587      (t
3588       (sp-wrap-cancel)))))
3589
3590 (defun sp--escape-region (chars-to-escape beg end)
3591   "Escape instances of CHARS-TO-ESCAPE between BEG and END.
3592
3593 Return non-nil if at least one escaping was performed."
3594   (save-excursion
3595     (goto-char beg)
3596     (let ((pattern (regexp-opt chars-to-escape))
3597           (end-marker (set-marker (make-marker) end))
3598           (re nil))
3599       (while (re-search-forward pattern end-marker t)
3600         (setq re t)
3601         (save-excursion
3602           (goto-char (match-beginning 0))
3603           (insert sp-escape-char)))
3604       re)))
3605
3606 ;; TODO: refactor the rewrap-sexp dependent parts out so that this
3607 ;; function has less dependencies on the action
3608 ;; TODO: add mode-dependent escape/unescape actions?
3609 (defun sp-escape-wrapped-region (id action _context)
3610   "Escape quotes and special chars when a region is (re)wrapped."
3611   (when (and sp-escape-wrapped-region
3612              (memq action '(wrap rewrap-sexp)))
3613     (sp-get sp-last-wrapped-region
3614       (let* ((parent-delim (save-excursion
3615                              (goto-char :beg)
3616                              (sp-get (sp-get-string)
3617                                (cond
3618                                 ((and (< :beg (point))
3619                                       (< (point) :end))
3620                                  :op)
3621                                 ((eq action 'rewrap-sexp)
3622                                  (plist-get sp-handler-context :parent)))))))
3623         (cond
3624          ((equal parent-delim id)
3625           (sp--escape-region (list id sp-escape-char) :beg :end))
3626          (parent-delim
3627           (sp--escape-region (list id) :beg-in :end-in))
3628          (t
3629           (sp--escape-region (list id sp-escape-char) :beg-in :end-in)))))))
3630
3631 (defun sp-escape-quotes-after-insert (id action context)
3632   "Escape quotes inserted via `sp-insert-pair'."
3633   (when (and sp-escape-quotes-after-insert
3634              (eq action 'insert)
3635              ;; we test not being inside string because if we were
3636              ;; before inserting the "" pair it is now split into two
3637              ;; -> which moves us outside the pair
3638              (not (eq context 'string))
3639              ;; the inserted character must have string syntax, otherwise no "context" flip happens
3640              (eq (char-syntax (aref id 0)) ?\"))
3641     (let ((open id)
3642           (close (sp-get-pair id :close)))
3643       (sp--escape-region (list open close)
3644                          (- (point) (length open))
3645                          (+ (point) (length close))))))
3646
3647 (defun sp--buffer-is-string-balanced-p ()
3648   "Check if the buffer is string-balanced.
3649
3650 A string-balanced buffer is one where where is no unclosed
3651 string, that is, the string state at the end of the buffer is
3652 \"closed\"."
3653   (save-excursion
3654     (save-restriction
3655       (widen)
3656       (goto-char (point-max))
3657       (let ((syntax (sp--syntax-ppss)))
3658         (or (< (car syntax) 0)
3659             (nth 3 syntax))))))
3660
3661 (defun sp-escape-open-delimiter ()
3662   "Escape just inserted opening pair if `sp-insert-pair' was skipped.
3663
3664 This is useful for escaping of \" inside strings when its pairing
3665 is disabled.  This way, we can control autoescape and closing
3666 delimiter insertion separately."
3667   (-when-let (open (plist-get (sp--pair-to-insert 'escape) :open))
3668     (when (and (sp--do-action-p open 'escape)
3669                sp-point-inside-string
3670                ;; do not escape if we are looking at a closing
3671                ;; delimiter, that means we closed an opened string,
3672                ;; most likely.
3673                (sp--buffer-is-string-balanced-p))
3674       (sp--escape-region (list open) (- (point) (length open)) (point)))))
3675
3676 ;; kept to not break people's config... remove later
3677 (defun sp-match-sgml-tags (tag)
3678   "Split the html tag TAG at the first space and return its name."
3679   (let* ((split (split-string tag " "))
3680          (close (car split)))
3681     close))
3682 (make-obsolete 'sp-match-sgml-tags "do not use this function as the tag system has been removed." "2015-02-07")
3683
3684 (defun sp--is-number-cons (c)
3685   "Return non-nil if C is a cons cell with numbers at `car' and `cdr'."
3686   (and (consp c) (numberp (car c)) (numberp (cdr c))))
3687
3688 ;; TODO: more research is needed
3689 (defun sp--undo-pop-to-last-insertion-node ()
3690   "Pop all undo info until an insertion node (beg . end) is found.
3691
3692 This can potentially remove some undo important information."
3693   (while (and buffer-undo-list
3694               (or (null (car buffer-undo-list)) ;; is nil
3695                   ;; is not undo action we're interested in
3696                   (not (sp--is-number-cons (car buffer-undo-list)))))
3697     (pop buffer-undo-list)))
3698
3699 ;; modified from: https://github.com/Fuco1/smartparens/issues/90#issuecomment-18800369
3700 (defun sp--split-last-insertion-undo (len)
3701   "Split the last insertion node in the `buffer-undo-list' to
3702 include separate pair node."
3703   (sp--undo-pop-to-last-insertion-node)
3704   (when buffer-undo-list
3705     (let* ((previous-undo-actions (cdr buffer-undo-list))
3706            (beg (caar buffer-undo-list))
3707            (end (cdar buffer-undo-list))
3708            first-action second-action)
3709       (unless (< beg (- end len))
3710         ;; We need to go back more than one action.  Given the pairs
3711         ;; are limited to 10 chars now and the chunks seem to be 20
3712         ;; chars, we probably wouldn't need more.
3713         (pop buffer-undo-list)
3714         (sp--undo-pop-to-last-insertion-node)
3715         (when buffer-undo-list
3716           (setq beg (caar buffer-undo-list))
3717           (setq previous-undo-actions (cdr buffer-undo-list))))
3718       (setq first-action (cons beg (- end len)))
3719       (setq second-action (cons (- end len) end))
3720       (setq buffer-undo-list
3721             (append (list nil second-action nil first-action)
3722                     previous-undo-actions)))))
3723
3724 ;; TODO: remove ACTION argument and make the selection process more
3725 ;; unified (see also sp--pair-to-wrap which depends on buffer state
3726 ;; among other things)
3727 (defun sp--all-pairs-to-insert (&optional looking-fn action)
3728   "Return all pairs that can be inserted at point.
3729
3730 Return nil if such pair does not exist.
3731
3732 Pairs inserted using a trigger have higher priority over pairs
3733 without a trigger and only one or the other list is returned.
3734
3735 In other words, if any pair can be inserted using a trigger, only
3736 pairs insertable by trigger are returned.
3737
3738 ACTION is an implementation detail.  Usually it has the value
3739 'insert when we determine pairs to insert.  On repeated wrapping
3740 however we pass the value 'wrap.  This will be refactored away in
3741 the upcoming version."
3742   (setq looking-fn (or looking-fn 'sp--looking-back-p))
3743   (setq action (or action 'insert))
3744   (let ((working-pairs
3745          ;; TODO: abstract this into a new "sp--get-..." hierarchy
3746          (--filter (sp--do-action-p (plist-get it :open) action) sp-local-pairs)))
3747     (-if-let (trigs (--filter (and (plist-get it :trigger)
3748                                    (funcall looking-fn (sp--strict-regexp-quote (plist-get it :trigger))))
3749                               working-pairs))
3750         (cons :trigger trigs)
3751       (-when-let (pairs (--filter (funcall looking-fn (sp--strict-regexp-quote (plist-get it :open))) working-pairs))
3752         (cons :open pairs)))))
3753
3754 (defun sp--pair-to-insert-comparator (prop a b)
3755   (cond
3756    ;; in case of triggers shorter always wins
3757    ((eq prop :trigger)
3758     (< (length (plist-get a :trigger)) (length (plist-get b :trigger))))
3759    ;; Shorter wins only if the shorter's closing is a prefix of the
3760    ;; longer's closing.  In other words, if we are looking at
3761    ;; shorter's closing and we are trying to nest it.
3762    (t
3763     (if (< (length (plist-get a :open)) (length (plist-get b :open)))
3764         (and (string-prefix-p (plist-get a :close) (plist-get b :close))
3765              (sp--looking-at-p (plist-get a :close)))
3766       (not (and (string-prefix-p (plist-get b :close) (plist-get a :close))
3767                 (sp--looking-at-p (plist-get b :close))))))))
3768
3769 (defun sp--pair-to-insert (&optional action)
3770   "Return pair that can be inserted at point.
3771
3772 Return nil if such pair does not exist.
3773
3774 If more triggers or opening pairs are possible select the
3775 shortest one."
3776   (-when-let ((property . pairs) (sp--all-pairs-to-insert nil action))
3777     (car (--sort (sp--pair-to-insert-comparator property it other) pairs))))
3778
3779 (defun sp--longest-prefix-to-insert ()
3780   "Return pair with the longest :open which can be inserted at point."
3781   (-when-let (pairs (--filter (sp--looking-back-p (sp--strict-regexp-quote (plist-get it :open))) sp-local-pairs))
3782     (car (--sort (> (length (plist-get it :open)) (length (plist-get other :open))) pairs))))
3783
3784 (defun sp--pair-to-uninsert ()
3785   "Return pair to uninsert.
3786
3787 If the current to-be-inserted pair shares a prefix with
3788 another (shorter) pair, we must first remove the effect of
3789 inserting its closing pair before inserting the current one.
3790
3791 The previously inserted pair must be the one with the longest
3792 common prefix excluding the current pair."
3793   (-when-let (lp (sp--longest-prefix-to-insert))
3794     (save-excursion
3795       (backward-char (length (plist-get lp :open)))
3796       (-when-let ((property . pairs) (sp--all-pairs-to-insert 'sp--looking-at-p))
3797         (car (--sort (> (length (plist-get it property)) (length (plist-get other property)))
3798                      ;; remove pairs whose open is longer than the
3799                      ;; current longest possible prefix---otherwise
3800                      ;; they would overflow to the closing pair
3801                      ;; TODO: this ignores the possibility when lp is
3802                      ;; inserted by trigger.  We assume triggers are
3803                      ;; shorter than the openings and this situation,
3804                      ;; if ever, should be very rare
3805                      (--remove (>= (length (plist-get it :open))
3806                                    (length (plist-get lp :open))) pairs)))))))
3807
3808 (defun sp--insert-pair-get-pair-info (active-pair)
3809   "Get basic info about the to-be-inserted pair."
3810   (let ((open-pair (plist-get active-pair :open)))
3811     (list
3812      open-pair
3813      (plist-get active-pair :close)
3814      (-if-let (tr (plist-get active-pair :trigger))
3815          (if (sp--looking-back-p (sp--strict-regexp-quote tr)) tr open-pair)
3816        open-pair))))
3817
3818 (defun sp-insert-pair (&optional pair)
3819   "Automatically insert the closing pair if it is allowed in current context.
3820
3821 If PAIR is provided, use this as pair ID instead of looking
3822 through the recent history of pressed keys.
3823
3824 You can disable this feature completely for all modes and all pairs by
3825 setting `sp-autoinsert-pair' to nil.
3826
3827 You can globally disable insertion of closing pair if point is
3828 followed by the matching opening pair.  It is disabled by
3829 default."
3830   (sp--with-case-sensitive
3831     (catch 'done
3832       (-let* ((active-pair (unwind-protect
3833                                ;; This fake insertion manufactures proper
3834                                ;; context for the tests below... in effect
3835                                ;; we must make it look as if the user
3836                                ;; typed in the opening part themselves
3837                                ;; TODO: it is duplicated in the test
3838                                ;; below, maybe it wouldn't hurt to
3839                                ;; restructure this function a bit
3840                                (progn
3841                                  (when pair (insert pair))
3842                                  (sp--pair-to-insert))
3843                              (when pair (delete-char (- (length pair))))))
3844               ((open-pair close-pair trig) (sp--insert-pair-get-pair-info active-pair)))
3845         ;; We are not looking at a closing delimiter which might mean we
3846         ;; are in an already existing sexp.  If the to-be-inserted pair
3847         ;; has a prefix which is also a pair we migth be extending the
3848         ;; opener of a sexp with this opener.  In which case we should
3849         ;; probably rewrap.
3850         (unless (sp--looking-at-p (sp--get-closing-regexp))
3851           (when (and open-pair
3852                      (= 1 (- (point) sp-pre-command-point)))
3853             (-when-let (prefix-pair (sp-get-pair (substring open-pair 0 -1)))
3854               (let ((last-char-of-open-pair (substring open-pair -1)))
3855                 (unwind-protect
3856                     (progn
3857                       (delete-char -1)
3858                       (--when-let (sp-get-thing t)
3859                         (save-excursion
3860                           (sp-get it
3861                             (delete-region :end-in :end)
3862                             (goto-char :end-in)
3863                             (insert close-pair)))
3864                         (throw 'done t)))
3865                   (insert last-char-of-open-pair))))))
3866         (if (not (unwind-protect
3867                      (progn
3868                        (when pair (insert pair))
3869                        ;; TODO: all these tests must go into `sp--pair-to-insert'
3870                        (and sp-autoinsert-pair
3871                             active-pair
3872                             (if (memq sp-autoskip-closing-pair '(always always-end))
3873                                 (or (not (equal open-pair close-pair))
3874                                     (not (sp-skip-closing-pair nil t)))
3875                               t)
3876                             (sp--do-action-p open-pair 'insert t)
3877                             ;; was sp-autoinsert-if-followed-by-same
3878                             (or (not (sp--get-active-overlay 'pair))
3879                                 (not (sp--looking-at (sp--strict-regexp-quote open-pair)))
3880                                 (and (equal open-pair close-pair)
3881                                      (eq sp-last-operation 'sp-insert-pair)
3882                                      (save-excursion
3883                                        (backward-char (length trig))
3884                                        (sp--looking-back (sp--strict-regexp-quote open-pair))))
3885                                 (not (equal open-pair close-pair)))))
3886                    (when pair (delete-char (- (length pair))))))
3887             ;; if this pair could not be inserted, we try the procedure
3888             ;; again with this pair removed from sp-pair-list to give
3889             ;; chance to other pairs sharing a common suffix (for
3890             ;; example \[ and [)
3891             (let ((new-sp-pair-list (--remove (equal (car it) open-pair) sp-pair-list))
3892                   (new-sp-local-pairs (--remove (equal (plist-get it :open) open-pair) sp-local-pairs)))
3893               (when (> (length sp-pair-list) (length new-sp-pair-list))
3894                 (let ((sp-pair-list new-sp-pair-list)
3895                       (sp-local-pairs new-sp-local-pairs))
3896                   (sp-insert-pair))))
3897           ;; setup the delayed insertion here.
3898           (if (sp-get-pair open-pair :when-cond)
3899               (progn
3900                 (setq sp-delayed-pair (cons open-pair (- (point) (length open-pair))))
3901                 (setq sp-last-operation 'sp-insert-pair-delayed))
3902             (unless pair (delete-char (- (length trig))))
3903             (insert open-pair)
3904             (sp--run-hook-with-args open-pair :pre-handlers 'insert)
3905             ;; The re-binding of these dynamic variables is a hack to
3906             ;; combat the similar rebinding in the branch above where
3907             ;; we retry `sp-insert-pair' with some pairs removed.
3908             ;; This however causes them to be uninserted improperly,
3909             ;; so for this one operation we need to restore the state
3910             ;; to the "full" pair list.  TODO: in the future we might
3911             ;; want to pass the state around explicitly so we have
3912             ;; better control.
3913             (--when-let (let ((sp-pair-list (sp-state-pair-list sp-state))
3914                               (sp-local-pairs (sp-state-local-pairs sp-state)))
3915                           (sp--pair-to-uninsert))
3916               (let ((cl (plist-get it :close)))
3917                 (when (and (sp--looking-at-p (sp--strict-regexp-quote cl))
3918                            (> (- (length close-pair) (length cl)) 0))
3919                   (delete-char (length cl)))))
3920             (insert close-pair)
3921             (backward-char (length close-pair))
3922             (sp--pair-overlay-create (- (point) (length open-pair))
3923                                      (+ (point) (length close-pair))
3924                                      open-pair)
3925             (when sp-undo-pairs-separately
3926               (sp--split-last-insertion-undo (+ (length open-pair) (length close-pair)))
3927               ;; TODO: abc\{abc\} undo undo \{asd\} . next undo removes the
3928               ;; entire \{asd\} if we do not insert two nils here.
3929               ;; Normally, repeated nils are ignored so it shouldn't
3930               ;; matter.  It would still be useful to inspect further.
3931               (push nil buffer-undo-list)
3932               (push nil buffer-undo-list))
3933             (sp--run-hook-with-args open-pair :post-handlers 'insert)
3934             (setq sp-last-inserted-pair open-pair)
3935             (setf (sp-state-delayed-hook sp-state) (cons :next open-pair))
3936             (setq sp-last-operation 'sp-insert-pair)))))))
3937
3938 (defun sp--wrap-repeat-last (active-pair)
3939   "If the last operation was a wrap and `sp-wrap-repeat-last' is
3940 non-nil, repeat the wrapping with this pair around the last
3941 active region."
3942   (unless (= 0 sp-wrap-repeat-last)
3943     (when sp-last-wrapped-region
3944       (let* ((b (sp-get sp-last-wrapped-region :beg))
3945              (e (sp-get sp-last-wrapped-region :end))
3946              (op (sp-get sp-last-wrapped-region :op))
3947              (oplen (length op))
3948              (cllen (sp-get sp-last-wrapped-region :cl-l))
3949              (acolen (length (car active-pair))))
3950         (when (and
3951                (cond
3952                 ((= 1 sp-wrap-repeat-last)
3953                  (equal (car active-pair) op))
3954                 ((= 2 sp-wrap-repeat-last)))
3955                (memq sp-last-operation '(sp-self-insert sp-wrap-region))
3956                (or (= (point) (+ b oplen acolen))
3957                    (= (point) e)))
3958           (delete-char (- acolen))
3959           (if (< (point) e)
3960               (progn (goto-char (+ b oplen))
3961                      (insert (car active-pair))
3962                      (goto-char (- e cllen))
3963                      (insert (cdr active-pair))
3964                      (setq sp-last-wrapped-region
3965                            (sp--get-last-wraped-region
3966                             (+ b oplen) (point)
3967                             (car active-pair) (cdr active-pair)))
3968                      (goto-char (+ b oplen acolen)))
3969             (goto-char b)
3970             (insert (car active-pair))
3971             (goto-char e)
3972             (insert (cdr active-pair))
3973             (setq sp-last-wrapped-region
3974                   (sp--get-last-wraped-region
3975                    b e (car active-pair) (cdr active-pair))))
3976           (setq sp-last-operation 'sp-wrap-region)
3977           (sp--run-hook-with-args (car active-pair) :post-handlers 'wrap)
3978           sp-last-operation)))))
3979
3980 (defun sp--char-is-part-of-stringlike (char)
3981   "Return non-nil if CHAR is part of a string-like delimiter of length 1."
3982   (->> (sp--get-stringlike-list)
3983     (--filter (= 1 (length (cdr it))))
3984     (-map 'car)
3985     (--any? (string-match-p (regexp-quote char) it))))
3986
3987 (defun sp--char-is-part-of-closing (char &optional pair-list)
3988   "Return non-nil if CHAR is part of a pair delimiter of length 1.
3989 Specifically, return the pair for which CHAR is the closing
3990 delimiter."
3991   (let ((regexp (regexp-quote char)))
3992     (->> (or pair-list (sp--get-pair-list))
3993          (--filter (= 1 (length (cdr it))))
3994          (--find (string-match-p regexp (cdr it))))))
3995
3996 ;; TODO: this only supports single-char delimiters.  Maybe it should
3997 ;; that that way.
3998 (defun sp-skip-closing-pair (&optional last test-only)
3999   "Automatically skip the closing delimiters of pairs.
4000
4001 If point is inside an inserted pair, and the user only moved
4002 forward with point (that is, only inserted text), if the closing
4003 pair is typed, we shouldn't insert it again but skip forward.  We
4004 call this state \"active sexp\".  The setting
4005 `sp-cancel-autoskip-on-backward-movement' controls when an active
4006 expression become inactive.
4007
4008 For example, pressing ( is followed by inserting the pair (|).  If
4009 we then type 'word' and follow by ), the result should be (word)|
4010 instead of (word)|).
4011
4012 This behaviour can be customized by various settings of
4013 `sp-autoskip-closing-pair' and `sp-autoskip-opening-pair'.
4014
4015 Additionally, this behaviour can be selectively disabled for
4016 specific pairs by removing their \"autoskip\" action.  You can
4017 achieve this by using `sp-pair' or `sp-local-pair' with
4018 \":actions '(:rem autoskip)\"."
4019   (sp--with-case-sensitive
4020     (when (or (and (eq sp-autoskip-closing-pair t)
4021                    sp-pair-overlay-list
4022                    (sp--get-active-overlay 'pair))
4023               (memq sp-autoskip-closing-pair '(always always-end)))
4024       ;; TODO: ugly hack to override 'navigate with 'autoskip.  Each of
4025       ;; these submodules should set-up their own environment somehow
4026       ;; and thread it through the entire computation
4027       (cl-letf (((symbol-function 'sp--get-allowed-stringlike-list)
4028                  (lambda ()
4029                    (--filter (and (sp--do-action-p (car it) 'autoskip)
4030                                   (equal (car it) (cdr it))) sp-pair-list))))
4031         ;; these two are pretty hackish ~_~
4032         (cl-labels ((get-sexp
4033                      (last)
4034                      (delete-char -1)
4035                      (insert " ")
4036                      (prog1 (sp-get-sexp)
4037                        (delete-char -1)
4038                        (insert last)))
4039                     (get-enclosing-sexp
4040                      (last)
4041                      (delete-char -1)
4042                      (insert " ")
4043                      (prog1 (sp-get-enclosing-sexp)
4044                        (delete-char -1)
4045                        (insert last))))
4046           (let ((last (or last (sp--single-key-description last-command-event))))
4047             (-if-let (active-sexp
4048                       (cond
4049                        ((-when-let* ((ov (sp--get-active-overlay 'pair))
4050                                      (op (overlay-get ov 'pair-id))
4051                                      (cl (cdr (assoc op sp-pair-list))))
4052                           ;; if the sexp is active, we are inside it.
4053                           (when (and (= 1 (length op))
4054                                      (equal last cl))
4055                             (list :beg (overlay-start ov)
4056                                   :end (overlay-end ov)
4057                                   :op op
4058                                   :cl cl
4059                                   :prefix ""
4060                                   :suffix ""))))
4061                        ((sp--char-is-part-of-stringlike last)
4062                         ;; a part of closing delimiter is typed. There are four
4063                         ;; options now:
4064                         ;; - we are inside the sexp, at its end
4065                         ;; - we are inside the sexp, somewhere in the middle
4066                         ;; - we are outside, in front of a sexp
4067                         ;; - we are outside, somewhere between sexps
4068                         (cond
4069                          ((and (sp--looking-at (sp--get-stringlike-regexp))
4070                                (not (sp--skip-match-p (match-string-no-properties 0)
4071                                                       (match-beginning 0)
4072                                                       (match-end 0))))
4073                           ;; if we're looking at the delimiter, and it is valid in
4074                           ;; current context, get the sexp.
4075                           (get-sexp last))
4076                          ;; here comes the feature when we're somewhere in the
4077                          ;; middle of the sexp (or outside), if ever supported.
4078                          ))
4079                        ((sp--char-is-part-of-closing last)
4080                         (cond
4081                          ((and (sp--looking-at (sp--get-closing-regexp))
4082                                (not (sp--skip-match-p (match-string-no-properties 0)
4083                                                       (match-beginning 0)
4084                                                       (match-end 0))))
4085                           (get-sexp last))
4086                          ((eq sp-autoskip-closing-pair 'always)
4087                           (get-enclosing-sexp last))))))
4088                 (if (and active-sexp
4089                          (equal (sp-get active-sexp :cl) last)
4090                          (sp--do-action-p (sp-get active-sexp :op) 'autoskip)
4091                          ;; if the point is inside string and preceded
4092                          ;; by an odd number of `sp-escape-char's, we
4093                          ;; should not skip as that would leave the
4094                          ;; string broken.
4095                          (or (not (sp-point-in-string))
4096                              (not (sp-char-is-escaped-p (1- (point))))))
4097                     (-when-let (re (cond
4098                                     ((= (point) (sp-get active-sexp :beg))
4099                                      ;; we are in front of a string-like sexp
4100                                      (when sp-autoskip-opening-pair
4101                                        (if test-only t
4102                                          (delete-char -1)
4103                                          (forward-char)
4104                                          (setq sp-last-operation 'sp-skip-closing-pair))))
4105                                     ((= (point) (sp-get active-sexp :end-in))
4106                                      (if test-only t
4107                                        (delete-char 1)
4108                                        (setq sp-last-operation 'sp-skip-closing-pair)))
4109                                     ((sp-get active-sexp
4110                                        (and (> (point) :beg-in)
4111                                             (< (point) :end-in)))
4112                                      (if test-only t
4113                                        (delete-char -1)
4114                                        (sp-up-sexp nil t)))))
4115                       (unless (or test-only
4116                                   sp-buffer-modified-p)
4117                         (set-buffer-modified-p nil))
4118                       (unless test-only
4119                         (sp--run-hook-with-args (sp-get active-sexp :op) :post-handlers 'skip-closing-pair))
4120                       re)
4121                   ;; if we can't skip and are in strict mode we must not
4122                   ;; insert anything if it is a closing character
4123                   (sp--inhibit-insertion-of-closing-delim last))
4124               (sp--inhibit-insertion-of-closing-delim last))))))))
4125
4126 (defun sp--inhibit-insertion-of-closing-delim (last)
4127   "Inhibit insertion of closing delimiter in `smartparens-strict-mode'.
4128
4129 If we are not inserting inside string or a comment, and the LAST
4130 inserted character is closing delimiter for a pair that performs
4131 autoskip, and we can not jump out of its enclosing sexp (i.e. it
4132 does not match), we are not allowed to insert it literally
4133 because it would break the balance; so we delete the
4134 just-inserted character."
4135   (when (and smartparens-strict-mode
4136              (-when-let (pair (sp--char-is-part-of-closing
4137                                last (sp--get-allowed-pair-list)))
4138                (memq 'autoskip (sp-get-pair (car pair) :actions)))
4139              (not (sp-point-in-string-or-comment)))
4140     (delete-char -1)
4141     (set-buffer-modified-p sp-buffer-modified-p)
4142     (sp-message :cant-insert-closing-delimiter)
4143     nil))
4144
4145 (defun sp-delete-pair (&optional arg)
4146   "Automatically delete opening or closing pair, or both, depending on
4147 position of point.
4148
4149 If the point is inside an empty pair, automatically delete both.  That
4150 is, [(|) turns to [|, [\{|\} turns to [|.  Can be disabled by setting
4151 `sp-autodelete-pair' to nil.
4152
4153 If the point is behind a closing pair or behind an opening pair delete
4154 it as a whole.  That is, \{\}| turns to \{|, \{| turns to |.  Can be
4155 disabled by setting `sp-autodelete-closing-pair' and
4156 `sp-autodelete-opening-pair' to nil.
4157
4158 If the last operation was a wrap and `sp-autodelete-wrap' is
4159 enabled, invoking this function will unwrap the expression, that
4160 is remove the just added wrapping."
4161   ;; NOTE: Only use delete-char inside this function, so we
4162   ;; don't activate the advice recursively!
4163
4164   ;; only activate if argument is 1 (this is 0-th argument of the
4165   ;; delete-backward-char), otherwise the user wants to delete
4166   ;; multiple character, so let him do that
4167   (sp--with-case-sensitive
4168     (when (and (= arg 1)
4169                smartparens-mode)
4170       (if (and sp-autodelete-wrap
4171                (eq sp-last-operation 'sp-wrap-region))
4172           (let ((p (point))
4173                 (b (sp-get sp-last-wrapped-region :beg))
4174                 (e (sp-get sp-last-wrapped-region :end))
4175                 (o (sp-get sp-last-wrapped-region :op-l))
4176                 (c (sp-get sp-last-wrapped-region :cl-l)))
4177             ;; if the last operation was `sp-wrap-region', and we are at
4178             ;; the position of either opening or closing pair, delete the
4179             ;; just-inserted pair
4180             (when (or (= p (+ b o))
4181                       (= p e))
4182               (insert "x") ;dummy char to account for the regularly deleted one
4183               (save-excursion
4184                 (goto-char e)
4185                 (delete-char (- c))
4186                 (goto-char b)
4187                 (delete-char o))
4188               (setq sp-last-operation 'sp-delete-pair-wrap)))
4189         (let ((p (point))
4190               (inside-pair (--first (and (sp--looking-back (sp--strict-regexp-quote (car it)))
4191                                          (sp--looking-at (concat "[ \n\t]*" (sp--strict-regexp-quote (cdr it)))))
4192                                     sp-pair-list))
4193               (behind-pair (--first (sp--looking-back (sp--strict-regexp-quote (cdr it))) sp-pair-list))
4194               (opening-pair (--first (sp--looking-back (sp--strict-regexp-quote (car it))) sp-pair-list)))
4195
4196           (cond
4197            ;; we're just before the closing quote of a string.  If there
4198            ;; is an opening or closing pair behind the point, remove
4199            ;; it.  This is only really relevant if the pair ends in the
4200            ;; same character as string quote.  We almost never want to
4201            ;; delete it as an autopair (it would "open up the string").
4202            ;; So, word\"|" and <backspace> should produce word\|" or
4203            ;; word|" (if \" is autopair) instead of word\|.
4204            ((and (sp-point-in-string)
4205                  (not (sp-point-in-string (1+ p)))
4206                  (sp-point-in-string (1- p))) ;; the string isn't empty
4207             (cond ;; oh, you ugly duplication :/
4208              ((and behind-pair sp-autodelete-closing-pair)
4209               (delete-char (- (1- (length (car behind-pair)))))
4210               (setq sp-last-operation 'sp-delete-pair-closing))
4211              ((and opening-pair sp-autodelete-opening-pair)
4212               (delete-char (- (1- (length (car opening-pair)))))
4213               (setq sp-last-operation 'sp-delete-pair-opening))))
4214            ;; we're inside a pair
4215            ((and inside-pair sp-autodelete-pair)
4216             (let* ((beg (save-excursion
4217                           (search-backward (car inside-pair))))
4218                    (end (save-excursion
4219                           (search-forward (cdr inside-pair))))
4220                    (cs (sp--get-context p))
4221                    (ce (sp--get-context end))
4222                    (current-sexp (sp-get-sexp)))
4223               (when (and (or (not (eq cs 'comment)) ;; a => b <=> ~a v b
4224                              (eq ce 'comment))
4225                          (eq beg (sp-get current-sexp :beg))
4226                          (eq end (sp-get current-sexp :end))
4227                          (equal (sp-get current-sexp :op) (car inside-pair))
4228                          (equal (sp-get current-sexp :cl) (cdr inside-pair)))
4229                 (delete-char (- end p))
4230                 (delete-char (- (1- (length (car inside-pair)))))
4231                 (setq sp-last-operation 'sp-delete-pair))))
4232            ;; we're behind a closing pair
4233            ((and behind-pair sp-autodelete-closing-pair)
4234             (delete-char (- (1- (length (cdr behind-pair)))))
4235             (setq sp-last-operation 'sp-delete-pair-closing))
4236            ;; we're behind an opening pair and there's no closing pair
4237            ((and opening-pair sp-autodelete-opening-pair)
4238             (delete-char (- (1- (length (car opening-pair)))))
4239             (setq sp-last-operation 'sp-delete-pair-opening))))))))
4240
4241
4242 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4243 ;; Navigation
4244
4245 (defun sp--looking-at (regexp)
4246   "Like `looking-at', but always case sensitive."
4247   (sp--with-case-sensitive
4248     (looking-at regexp)))
4249
4250 (defun sp--looking-at-p (regexp)
4251   "Like `looking-at-p', but always case sensitive."
4252   (sp--with-case-sensitive
4253     (looking-at-p regexp)))
4254
4255 (defun sp--looking-back (regexp &optional limit not-greedy)
4256   "Return non-nil if text before point matches regular expression REGEXP.
4257
4258 With optional argument LIMIT search only that many characters
4259 backward.  If LIMIT is nil, default to `sp-max-pair-length'.
4260
4261 If optional argument NON-GREEDY is t search for any matching
4262 sequence, not necessarily the longest possible."
4263   (setq limit (or limit sp-max-pair-length))
4264   (sp--with-case-sensitive
4265     (let ((from (max 1 (- (point) limit)))
4266           (to (point))
4267           (greedy (not not-greedy))
4268           has-match)
4269       (if greedy
4270           (save-excursion
4271             (goto-char from)
4272             (save-match-data
4273               (while (and (not has-match) (< (point) to))
4274                 ;; don't use looking-at because we can't limit that search
4275                 (if (and (save-excursion (re-search-forward regexp to t))
4276                          (= (match-end 0) to))
4277                     (setq has-match (match-data))
4278                   (forward-char 1))))
4279             (when has-match
4280               (set-match-data has-match)
4281               t))
4282         (save-excursion
4283           (not (null (search-backward-regexp (concat "\\(?:" regexp "\\)\\=") from t))))))))
4284
4285 (defun sp--looking-back-p (regexp &optional limit not-greedy)
4286   "Same as `sp--looking-back' but do not change the match data."
4287   (save-match-data
4288     (sp--looking-back regexp limit not-greedy)))
4289
4290 (defun sp--search-backward-regexp (regexp &optional bound noerror count)
4291   "Works just like `search-backward-regexp', but returns the
4292 longest possible match.  That means that searching for
4293 \"defun|fun\" backwards would return \"defun\" instead of
4294 \"fun\", which would be matched first.
4295
4296 This is an internal function.  Only use this for searching for
4297 pairs!"
4298   (setq count (or count 1))
4299   (setq bound (or (sp--get-backward-bound) bound))
4300   (sp--with-case-sensitive
4301     (let (r)
4302       (while (> count 0)
4303         (when (search-backward-regexp regexp bound noerror)
4304           (goto-char (match-end 0))
4305           (if (sp--looking-back regexp)
4306               (setq r (goto-char (match-beginning 0)))
4307             (if noerror nil (error "Search failed: %s" regexp))))
4308         (setq count (1- count)))
4309       r)))
4310
4311 (defun sp--search-forward-regexp (regexp &optional bound noerror count)
4312   "Just like `search-forward-regexp', but always case sensitive."
4313   (setq bound (or (sp--get-forward-bound) bound))
4314   (sp--with-case-sensitive
4315     (search-forward-regexp regexp bound noerror count)))
4316
4317 (defun sp--search-forward-in-context (regexp &optional bound noerror count)
4318   "Just like `sp--search-forward-regexp' but only accept results in same context.
4319
4320 The context at point is considered the reference context."
4321   (let ((context (sp--get-context))
4322         (re))
4323     (--dotimes (or count 1)
4324       (save-excursion
4325         (while (and (setq re (sp--search-forward-regexp regexp bound noerror))
4326                     (not (eq (sp--get-context) context)))))
4327       (when re (goto-char re)))
4328     re))
4329
4330 (defun sp--search-backward-in-context (regexp &optional bound noerror count)
4331   "Just like `sp--search-backward-regexp' but only accept results in same context.
4332
4333 The context at point is considered the reference context."
4334   (let ((context (sp--get-context))
4335         (re))
4336     (--dotimes (or count 1)
4337       (save-excursion
4338         (while (and (setq re (sp--search-backward-regexp regexp bound noerror))
4339                     (not (eq (sp--get-context) context))))
4340         (when re (goto-char re))))
4341     re))
4342
4343 (defun sp-get-quoted-string-bounds (&optional point)
4344   "Return the bounds of the string around POINT.
4345
4346 POINT defaults to `point'.
4347
4348 If the point is not inside a quoted string, return nil."
4349   (setq point (or point (point)))
4350   (save-excursion
4351     (goto-char point)
4352     (let ((parse-data (syntax-ppss)))
4353       (when (nth 3 parse-data)
4354         (let* ((open (nth 8 parse-data))
4355                (close (save-excursion
4356                         (parse-partial-sexp
4357                          (point) (point-max)
4358                          nil nil parse-data 'syntax-table)
4359                         (point))))
4360           (cons open close))))))
4361
4362 ;; TODO: the repeated conditions are ugly, refactor this!
4363 (defun sp-get-comment-bounds ()
4364   "If the point is inside a comment, return its bounds."
4365   (when (or (sp-point-in-comment)
4366             (looking-at "[[:space:]]+\\s<"))
4367     (let ((open (save-excursion
4368                   (--when-let (nth 8 (sp--syntax-ppss))
4369                     (goto-char it))
4370                   (while (and (not (bobp))
4371                               (or (when (sp-point-in-comment)
4372                                     (backward-char 1)
4373                                     t)
4374                                   (when (save-excursion
4375                                           (beginning-of-line)
4376                                           (looking-at "^[[:space:]]+\\s<"))
4377                                     (when (>= (forward-line -1) 0)
4378                                       (end-of-line))
4379                                     t))))
4380                   ;; this means we got here by `sp-point-in-comment' condition
4381                   (unless (and (bobp) (sp-point-in-comment))
4382                     (forward-char))
4383                   (point)))
4384           (close (save-excursion
4385                    (while (and (not (eobp))
4386                                (or (sp-point-in-comment)
4387                                    (looking-at "[[:space:]]+\\s<")))
4388                      (forward-char 1))
4389                    (let ((pp (1- (point))))
4390                      (when (not (or (eobp)
4391                                     (sp-point-in-comment)
4392                                     (looking-at "[[:space:]]+\\s<")
4393                                     (and (eq (char-syntax
4394                                               (char-after pp)) ?>)
4395                                          (not (eq (char-after pp) ?\n)))
4396                                     (/= (logand
4397                                          (lsh 1 18)
4398                                          (car (syntax-after pp))) 0)
4399                                     (/= (logand
4400                                          (lsh 1 19)
4401                                          (car (syntax-after pp))) 0)))
4402                        (backward-char 1)))
4403                    (point))))
4404       (cons open close))))
4405
4406 (defun sp--get-string-or-comment-bounds ()
4407   "Get the bounds of string or comment the point is in."
4408   (or (sp-get-quoted-string-bounds)
4409       (sp-get-comment-bounds)))
4410
4411 (defmacro sp--search-and-save-match (search-fn pattern bound res beg end str)
4412   "Save the last match info."
4413   `(progn
4414      (setq ,res (funcall ,search-fn ,pattern ,bound t))
4415      (when ,res
4416        (setq ,beg (match-beginning 0))
4417        (setq ,end (match-end 0))
4418        (setq ,str (match-string 0)))
4419      ,res))
4420
4421 (cl-defun sp--skip-match-p (ms mb me
4422                                &key
4423                                (global-skip (cdr (--first (memq major-mode (car it)) sp-navigate-skip-match)))
4424                                (pair-skip (sp-get-pair ms :skip-match)))
4425   "Return non-nil if this match should be skipped.
4426
4427 This function uses two tests, one specified in
4428 `sp-navigate-skip-match' (this is global setting for all pairs in
4429 given major mode) and by a function specified in :skip-match
4430 property of the pair.
4431
4432 If you are calling this function in a heavy loop, you can supply
4433 the test functions as keyword arguments to speed up the lookup."
4434   (save-match-data
4435     (or (when global-skip (funcall global-skip ms mb me))
4436         (when pair-skip (funcall pair-skip ms mb me)))))
4437
4438 (defmacro sp--valid-initial-delimiter-p (form)
4439   "Test the last match using `sp--skip-match-p'.  The form should
4440 be a function call that sets the match data."
4441   (declare (debug (form)))
4442   (let ((match (make-symbol "match"))
4443         (pair-skip (make-symbol "pair-skip")))
4444     `(and ,form
4445           (let* ((,match (match-string 0))
4446                  (,pair-skip (or (sp-get-pair ,match :skip-match)
4447                                  (sp-get-pair (car (--first
4448                                                     (equal (cdr it) ,match)
4449                                                     sp-pair-list))
4450                                               :skip-match))))
4451             (not (sp--skip-match-p
4452                   ,match
4453                   (match-beginning 0)
4454                   (match-end 0)
4455                   :pair-skip ,pair-skip))))))
4456
4457 (defun sp--elisp-skip-match (ms mb _me)
4458   "Function used to test for escapes in lisp modes.
4459
4460 Non-nil return value means to skip the result."
4461   (and ms
4462        (> mb 1)
4463        (save-excursion
4464          (goto-char mb)
4465          (save-match-data
4466            (or (and (sp--looking-back "\\\\" 1 t)
4467                     ;; it might be a part of ?\\ token
4468                     (not (sp--looking-back "\\?\\\\\\\\" 3 t)))
4469                (and (not (sp-point-in-string-or-comment))
4470                     (sp--looking-back "\\?" 1 t) ;;TODO surely we can do better
4471                     (not (sp--looking-back "\\\\\\?" 2 t))
4472                     (not (sp--looking-back "\\s_\\?" 2 t))
4473                     (not (sp--looking-back "\\sw\\?" 2 t))))))))
4474
4475 (defun sp--backslash-skip-match (ms mb _me)
4476   (and ms
4477        (save-excursion
4478          (goto-char mb)
4479          (sp--looking-back "\\\\" 1 t))))
4480
4481 ;; TODO: since this function is used for all the navigation, we should
4482 ;; optimize it a lot! Get some elisp profiler! Also, we should split
4483 ;; this into smaller functions (esp. the "first expression search"
4484 ;; business)
4485 (defun sp-get-paired-expression (&optional back)
4486   "Find the nearest balanced pair expression after point.
4487
4488 The expressions considered are those delimited by pairs on
4489 `sp-pair-list'."
4490   (sp--with-case-sensitive
4491     (save-excursion
4492       (let* ((search-fn (if (not back) 'sp--search-forward-regexp 'sp--search-backward-regexp))
4493              (global-skip-fn (cdr (--first (memq major-mode (car it)) sp-navigate-skip-match)))
4494              (pair-list (sp--get-allowed-pair-list))
4495              ;; TODO UGLY HACK!!!  When the situation is:
4496              ;; ..)|;; comment
4497              ;; the context the point gets is the comment.  But if we
4498              ;; are searching backward, that is incorrect, because in
4499              ;; that case we want the context of the closing pair.
4500              ;; Therefore, if the direction is backward, we need to move
4501              ;; one point backward, then test the comment/string thing,
4502              ;; then compute the correct bounds, and then restore the
4503              ;; point so the search will pick up the )
4504
4505              ;; However, we need to distinguish the cases where we are
4506              ;; in comment and trying to get out, and when we are in any
4507              ;; context and we jump into string (in that case, we should
4508              ;; report code context!).  For example:
4509              ;;   "foo"|;bar
4510              ;; or
4511              ;;   "foo"|bar
4512              ;; should both report code context
4513              ;; and "|(foo)" should report string context.
4514
4515              ;; Beware the case when we have a string inside a comment, like
4516              ;;   (foo) ;; bar "baz"| qux
4517              ;; In this case we want to report comment context even when
4518              ;; backing into the "" (which however is commented)
4519
4520              ;; Yet another case is when we are not in a comment but
4521              ;; directly after one and we search backwards, consider:
4522              ;;   /* foo bar */|
4523              ;; in C-like language.  In this case, we want to report the
4524              ;; context as comment.
4525
4526              ;; In some languages, special paren syntax with a prefix
4527              ;; serves to mark strings.  This means that regular
4528              ;; delimiters, like () are used to delimit strings.  For
4529              ;; example, in ruby the sequence %w(...) signifies a
4530              ;; string.  If the point is after such a sequence and we
4531              ;; are searching back, we must use the string context,
4532              ;; because the paren is now a string delimiter.  This is
4533              ;; usually implemented with "string fence" syntax, so we
4534              ;; will simply check for that.
4535
4536              ;; Thanks for being consistent at handling syntax bounds Emacs!
4537              (in-string-or-comment (if back
4538                                        (let ((in-comment (sp-point-in-comment))
4539                                              (in-string (sp-point-in-string)))
4540                                          (save-excursion
4541                                            (unless (= (point) (point-min))
4542                                              (backward-char)
4543                                              (cond
4544                                               ((eq (car (syntax-after (point))) 15) (point))
4545                                               (in-comment (when (sp-point-in-comment) (1+ (point))))
4546                                               ((and (not in-comment) (sp-point-in-comment)) (1+ (point)))
4547                                               ((or in-comment in-string) (1+ (point)))))))
4548                                      (when (sp-point-in-string-or-comment) (point))))
4549              (string-bounds (and in-string-or-comment
4550                                  (progn
4551                                    (goto-char in-string-or-comment)
4552                                    (sp--get-string-or-comment-bounds))))
4553              (fw-bound (if in-string-or-comment (cdr string-bounds) (point-max)))
4554              (bw-bound (if in-string-or-comment (car string-bounds) (point-min)))
4555              s e forward mb me ms r done
4556              possible-pairs possible-interfering-pairs possible-ops possible-cls)
4557         (while (and (not done)
4558                     (sp--search-and-save-match
4559                      search-fn
4560                      ;; #556 The regexp we use here might exclude or
4561                      ;; include extra pairs in case the next match is in
4562                      ;; a different context.  There's no way to know
4563                      ;; beforehand where we land, so we need to consider
4564                      ;; *all* pairs in the search and then re-check with
4565                      ;; a regexp based on the context of the found pair
4566                      (sp--get-allowed-regexp
4567                       ;; use all the pairs!
4568                       (sp--get-pair-list))
4569                      (if back bw-bound fw-bound)
4570                      r mb me ms))
4571           ;; search for the first opening pair.  Here, only consider tags
4572           ;; that are allowed in the current context.
4573           (unless (or (not (save-excursion
4574                              (if back
4575                                  (progn
4576                                    (goto-char me)
4577                                    (sp--looking-back-p (sp--get-allowed-regexp)))
4578                                (goto-char mb)
4579                                (sp--looking-at-p (sp--get-allowed-regexp)))))
4580                       (sp--skip-match-p ms mb me :global-skip global-skip-fn))
4581             ;; if the point originally wasn't inside of a string or comment
4582             ;; but now is, jump out of the string/comment and only search
4583             ;; the code.  This ensures that the comments and strings are
4584             ;; skipped if we search inside code.
4585             (if (and (not in-string-or-comment)
4586                      (if back
4587                          ;; When searching back, the point lands on the
4588                          ;; first character of whatever pair we've found
4589                          ;; and it is in the proper context, for example
4590                          ;; "|(foo)"
4591                          (sp-point-in-string-or-comment)
4592                        ;; However, when searching forward, the point
4593                        ;; lands after the last char of the pair so to get
4594                        ;; its context we must back up one character
4595                        (sp-point-in-string-or-comment (1- (point)))))
4596                 (-if-let (bounds (sp--get-string-or-comment-bounds))
4597                     (let ((jump-to (if back (car bounds) (cdr bounds))))
4598                       (goto-char jump-to)
4599                       ;; Can't move out of comment because eob, #427
4600                       (when (eobp)
4601                         (setq done t)))
4602                   (setq done t))
4603               (setq done t))))
4604         (when r
4605           (setq possible-pairs (--filter (or (equal ms (car it))
4606                                              (equal ms (cdr it)))
4607                                          pair-list))
4608           (setq possible-ops (-map 'car possible-pairs))
4609           (setq possible-cls (-map 'cdr possible-pairs))
4610           (setq pair-list (-difference pair-list possible-pairs))
4611           (setq possible-interfering-pairs pair-list)
4612           (while possible-interfering-pairs
4613             (setq possible-interfering-pairs
4614                   (--filter (or (-contains? possible-ops (car it))
4615                                 (-contains? possible-cls (cdr it)))
4616                             pair-list))
4617             (setq pair-list (-difference pair-list possible-interfering-pairs))
4618             (setq possible-ops (append possible-ops (-map 'car possible-interfering-pairs)))
4619             (setq possible-cls (append possible-cls (-map 'cdr possible-interfering-pairs))))
4620           (when (--any? (equal ms it) possible-ops)
4621             (setq forward t)
4622             (setq s mb)
4623             (when back
4624               (forward-char (length ms))))
4625           (when (--any? (equal ms it) possible-cls)
4626             (setq forward nil)
4627             (setq e me)
4628             (when (not back)
4629               (backward-char (length ms))))
4630           (let* ((opens (if forward possible-ops possible-cls))
4631                  (closes (if forward possible-cls possible-ops))
4632                  (needle (sp--strict-regexp-opt (append possible-ops possible-cls)))
4633                  (search-fn (if forward 'sp--search-forward-regexp 'sp--search-backward-regexp))
4634                  (depth 1)
4635                  (eof (if forward 'eobp 'bobp))
4636                  (b (if forward fw-bound bw-bound))
4637                  (open (substring-no-properties ms))
4638                  (close (substring-no-properties ms))
4639                  (failure (funcall eof))
4640                  (skip-match-pair-fns (->> possible-ops
4641                                            (--mapcat (-when-let (smf (sp-get-pair it :skip-match))
4642                                                        (list (cons it smf) (cons (sp-get-pair it :close) smf)))))))
4643             (while (and (> depth 0) (not (funcall eof)))
4644               (sp--search-and-save-match search-fn needle b r mb me ms)
4645               (if r
4646                   (unless (or (and (not in-string-or-comment)
4647                                    (if forward (save-excursion
4648                                                  (backward-char)
4649                                                  (sp-point-in-string-or-comment))
4650                                      (sp-point-in-string-or-comment)))
4651                               ;; check the individual pair skipper.  We
4652                               ;; need to test all the possible-ops,
4653                               ;; which makes it a bit ugly :/
4654                               (let ((skip-match-pair-fn
4655                                      (cdr (--first (equal (car it) ms) skip-match-pair-fns))))
4656                                 (sp--skip-match-p ms mb me :global-skip global-skip-fn :pair-skip skip-match-pair-fn)))
4657                     (when (--any? (equal ms it) opens) (setq depth (1+ depth)))
4658                     (when (--any? (equal ms it) closes) (setq depth (1- depth))))
4659                 (unless (minibufferp)
4660                   (sp-message :unmatched-expression))
4661                 (setq depth -1)
4662                 (setq failure t)))
4663             (if forward
4664                 (setq e me)
4665               (setq s mb))
4666             (setq close (substring-no-properties ms))
4667             (if (or failure
4668                     (/= depth 0))
4669                 (progn
4670                   (unless (minibufferp)
4671                     (sp-message :unmatched-expression))
4672                   nil)
4673               (let ((end-in-cos (sp-point-in-string-or-comment (1- e)))) ;; fix the "point on comment" issue
4674                 (cond
4675                  ((or (and (sp-point-in-string-or-comment s) (not end-in-cos))
4676                       (and (not (sp-point-in-string-or-comment s)) end-in-cos))
4677                   (unless (minibufferp)
4678                     (sp-message :delimiter-in-string))
4679                   nil)
4680                  (t
4681                   (let* ((op (if forward open close)))
4682                     (list :beg s
4683                           :end e
4684                           :op op
4685                           :cl (if forward close open)
4686                           :prefix (sp--get-prefix s op)
4687                           :suffix (sp--get-suffix e op)))))))))))))
4688
4689 ;; TODO: this does not consider unbalanced quotes in comments!!!
4690 (defun sp--find-next-stringlike-delimiter (needle search-fn-f &optional limit skip-fn)
4691   "Find the next string-like delimiter, considering the escapes
4692 and the skip-match predicate."
4693   (let (hit match)
4694     (while (and (not hit)
4695                 (funcall search-fn-f needle limit t))
4696       (save-match-data
4697         (setq match (match-string-no-properties 0))
4698         (unless (or (save-match-data
4699                       (save-excursion
4700                         (goto-char (match-beginning 0))
4701                         (or (sp--looking-back-p "\\\\" 2) ;; assumes \ is always the escape... bad?
4702                             (and (eq major-mode 'emacs-lisp-mode)
4703                                  (not (sp-point-in-string))
4704                                  (sp--looking-back-p "?" 1)))))
4705                     ;; TODO: HACK: global-skip is hack here!!!
4706                     (sp--skip-match-p match (match-beginning 0) (match-end 0)
4707                                       :pair-skip (or skip-fn
4708                                                      (sp-get-pair match :skip-match))
4709                                       :global-skip nil))
4710           (setq hit (match-data)))))
4711     hit))
4712
4713 (defun sp-get-stringlike-expression (&optional back)
4714   "Find the nearest string-like expression after point.
4715
4716 String-like expression is expression enclosed with the same
4717 opening and closing delimiter, such as *...*, \"...\", `...` etc."
4718   (sp--with-case-sensitive
4719     (save-excursion
4720       (let ((needle (sp--get-stringlike-regexp))
4721             (search-fn-f (if (not back) 'sp--search-forward-regexp 'sp--search-backward-regexp))
4722             (search-fn-b (if back 'sp--search-forward-regexp 'sp--search-backward-regexp))
4723             (count 0)
4724             m b e skip-match-fn limit ok)
4725         (when (not (equal needle ""))
4726           (when (sp--find-next-stringlike-delimiter needle search-fn-f)
4727             ;; assumes \ is always the escape... bad?
4728             (setq m (match-string-no-properties 0))
4729             (setq needle (regexp-quote m))
4730             (setq skip-match-fn (sp-get-pair m :skip-match))
4731             (cond
4732              ((sp-point-in-string)
4733               (setq limit (sp-get-quoted-string-bounds)))
4734              ((sp-point-in-comment)
4735               (setq limit (sp-get-comment-bounds))))
4736             (save-excursion
4737               (while (sp--find-next-stringlike-delimiter needle 'search-backward-regexp (car limit) skip-match-fn)
4738                 (setq count (1+ count))))
4739             (when (= (mod count 2) 0)
4740               (sp--find-next-stringlike-delimiter needle search-fn-b nil))
4741             (save-excursion
4742               (setq ok (sp--find-next-stringlike-delimiter needle 'sp--search-backward-regexp (car limit)))
4743               (setq e (match-beginning 0)))
4744             (setq ok (and ok (sp--find-next-stringlike-delimiter needle 'search-forward-regexp (cdr limit))))
4745             (setq b (match-end 0))
4746             (when ok
4747               (let ((mb b) (me e))
4748                 (setq b (min mb me))
4749                 (setq e (max mb me)))
4750               (list :beg b :end e :op m :cl m :prefix (sp--get-prefix b m) :suffix (sp--get-suffix e m)))))))))
4751
4752 (defun sp--textmode-stringlike-regexp (delimiters &optional direction)
4753   "Get a regexp matching text-mode string-like DELIMITERS.
4754
4755 Capture group 1 or 2 has the delimiter itself, depending on the
4756 direction (forward, backward).
4757
4758 If DIRECTION is :open, create a regexp matching opening only.
4759
4760 If DIRECTION is :close, create a regexp matching closing only.
4761
4762 If DIRECTION is nil, create a regexp matching both directions."
4763   (let* ((delims (regexp-opt delimiters))
4764          (re (concat
4765               (if (or (not direction)
4766                       (eq direction :open))
4767                   (concat "\\(?:" "\\(?:\\`\\|[ \t\n\r]\\)" "\\(" delims "\\)" "[^ \t\n\r]\\)") "")
4768               (if (not direction) "\\|" "")
4769               (if (or (not direction)
4770                       (eq direction :close))
4771                   (concat "\\(?:[^ \t\n\r]" "\\(" delims "\\)" "\\(?:[ \t\n\r[:punct:]]\\|\\'\\)" "\\)") ""))))
4772     re))
4773
4774 (defun sp--find-next-textmode-stringlike-delimiter (needle search-fn-f &optional limit)
4775   "Find the next string-like delimiter, considering the escapes
4776 and the skip-match predicate."
4777   (let (hit)
4778     (while (and (not hit)
4779                 (funcall search-fn-f needle limit t))
4780       (save-match-data
4781         (let* ((group (if (match-string 1) 1 2))
4782                (match (match-string-no-properties group))
4783                (mb (match-beginning group))
4784                (me (match-end group))
4785                (skip-fn (sp-get-pair match :skip-match)))
4786           (unless (sp--skip-match-p match mb me :pair-skip skip-fn :global-skip nil)
4787             (setq hit (list match (if (= group 1) :open :close)))))))
4788     hit))
4789
4790 (defun sp-get-textmode-stringlike-expression (&optional back)
4791   "Find the nearest text-mode string-like expression.
4792
4793 If BACK is non-nil search in the backwards direction.
4794
4795 Text-mode string-like expression is one where the delimiters must
4796 be surrounded by whitespace from the outside.  For example,
4797
4798 foo *bar* baz
4799
4800 is a valid expression enclosed in ** pair, but
4801
4802 foo*bar*baz  OR  foo *bar*baz  OR  foo*bar* baz
4803
4804 are not.
4805
4806 This is the case in almost every markup language, and so we will
4807 adjust the parsing to only consider such pairs as delimiters.
4808 This makes the parsing much faster as it transforms the problem
4809 to non-stringlike matching and we can use a simple
4810 counting (stack) algorithm."
4811   (save-excursion
4812     (let ((restart-from (point))
4813           (bounds (or (sp-get-comment-bounds)
4814                       (cons (point-min) (point-max))))
4815           hit re)
4816       (while (not hit)
4817         (goto-char restart-from)
4818         (save-excursion
4819           (ignore-errors
4820             (if back (forward-char) (backward-char)))
4821           (let* ((delimiters (-map 'car (sp--get-allowed-stringlike-list)))
4822                  (needle (sp--textmode-stringlike-regexp delimiters))
4823                  (search-fn-f (if (not back) 'sp--search-forward-regexp 'sp--search-backward-regexp))
4824                  (limit-f (if (not back) (cdr bounds) (car bounds))))
4825             (-if-let ((delim type) (sp--find-next-textmode-stringlike-delimiter needle search-fn-f limit-f))
4826                 (let ((search-fn (if (eq type :open) 'sp--search-forward-regexp 'sp--search-backward-regexp))
4827                       (limit (if (eq type :open) (cdr bounds) (car bounds)))
4828                       (needle (sp--textmode-stringlike-regexp (list delim) (if (eq type :open) :close :open))))
4829                   (setq restart-from (point))
4830                   ;; this adjustments are made because elisp regexp
4831                   ;; can't do lookahead assertions... so we match and
4832                   ;; then back up.
4833                   (ignore-errors
4834                     (when (and (not back) (eq type :open)) (backward-char (1+ (length delim))))
4835                     (when (and (not back) (eq type :close) (not (eobp))) (backward-char 1))
4836                     (when (and back (eq type :close)) (forward-char (1+ (length delim))))
4837                     (when (and back (eq type :open) (not (bobp))) (forward-char 1)))
4838                   (let ((other-end (point)))
4839                     (when (sp--find-next-textmode-stringlike-delimiter needle search-fn limit)
4840                       ;; Beware, we also need to test the beg/end of
4841                       ;; buffer, because we have that variant in the
4842                       ;; regexp.  In that case the match does not
4843                       ;; consume anything and we needn't do any
4844                       ;; correction.
4845                       (let* ((this-end (if (eq type :open)
4846                                            (max (point-min) (if (eobp) (point) (1- (point))))
4847                                          (min (point-max) (if (bobp) (point) (1+ (point))))))
4848                              (b (min this-end other-end))
4849                              (e (max this-end other-end)))
4850                         (setq re (list :beg b
4851                                        :end e
4852                                        :op delim
4853                                        :cl delim
4854                                        :prefix (sp--get-prefix b delim) :suffix (sp--get-suffix e delim)))
4855                         (setq hit t)
4856                         ;; We ignore matches that contain two
4857                         ;; consecutive newlines, as that usually means
4858                         ;; there's a new paragraph somewhere inbetween
4859                         ;; TODO: make this customizable
4860                         (when (sp-get re
4861                                 (save-excursion
4862                                   (goto-char :beg)
4863                                   (re-search-forward "\n\n\\|\r\r" :end t)))
4864                           (setq re nil)
4865                           (setq hit nil))))))
4866               (setq hit :no-more)))))
4867       re)))
4868
4869 (defun sp-use-textmode-stringlike-parser-p ()
4870   "Test if we should use textmode stringlike parser or not."
4871   (let ((modes (-filter 'symbolp sp-navigate-use-textmode-stringlike-parser))
4872         (derived (-map 'cdr (-remove 'symbolp sp-navigate-use-textmode-stringlike-parser))))
4873     (or (--any? (eq major-mode it) modes)
4874         (apply 'derived-mode-p derived))))
4875
4876 (defun sp-get-stringlike-or-textmode-expression (&optional back delimiter)
4877   "Return a stringlike expression using stringlike or textmode parser.
4878
4879 DELIMITER is a candidate in case we performed a search before
4880 calling this function and we know it's the closest string
4881 delimiter to try.  This is purely a performance hack, do not rely
4882 on it when calling directly."
4883   (if (sp-use-textmode-stringlike-parser-p)
4884       (sp-get-textmode-stringlike-expression back)
4885     ;; performance hack. If the delimiter is a character in
4886     ;; syntax class 34, grab the string-like expression using
4887     ;; `sp-get-string'
4888     (if (and delimiter
4889              (= (length delimiter) 1)
4890              ;; TODO: this "smart" behaviour is duplicated in
4891              ;; `sp-get-thing', maybe the whole string parsing could
4892              ;; be extracted to some common function (actually we
4893              ;; should probably use this one from `sp-get-thing')
4894              (eq (char-syntax (string-to-char delimiter)) 34))
4895         (if (eq t (sp-point-in-string))
4896             ;; TODO: this is duplicated in `sp-get-thing', move to a function
4897             (save-excursion
4898               (save-restriction
4899                 (widen)
4900                 (-let (((beg . end) (sp-get-quoted-string-bounds)))
4901                   (narrow-to-region beg end))
4902                 (sp-get-stringlike-expression back)))
4903           (sp-get-string back))
4904       (sp-get-stringlike-expression back))))
4905
4906 (defun sp-get-expression (&optional back)
4907   "Find the nearest balanced expression of any kind.
4908
4909 For markup and text modes a special, more efficient stringlike
4910 parser is available, see `sp-get-textmode-stringlike-expression'.
4911 By default, this is enabled in all modes derived from
4912 `text-mode'.  You can change it by customizing
4913 `sp-navigate-use-textmode-stringlike-parser'."
4914   (let ((pre (sp--get-allowed-regexp))
4915         (sre (sp--get-stringlike-regexp))
4916         (search-fn (if (not back) 'sp--search-forward-regexp 'sp--search-backward-regexp))
4917         (ps (if back (1- (point-min)) (1+ (point-max))))
4918         (ss (if back (1- (point-min)) (1+ (point-max))))
4919         (string-delim nil))
4920     (setq ps (if (equal pre "") ps
4921                (or (save-excursion (funcall search-fn pre nil t)) ps)))
4922     (setq ss (if (equal sre "") ss
4923                (or (--when-let (save-excursion
4924                                  (sp--find-next-stringlike-delimiter sre search-fn))
4925                      (setq string-delim (match-string 0))
4926                      (save-match-data
4927                        (set-match-data it)
4928                        (if back (match-beginning 0) (match-end 0))))
4929                    ss)))
4930     ;; TODO: simplify this logic somehow... (this really depends
4931     ;; on a rewrite of the core parser logic: separation of "find
4932     ;; the valid opening" and "parse it")
4933
4934     ;; Here, we sacrifice readability for performance.  Because we
4935     ;; only use regexp to look forward for the closest pair, it
4936     ;; might occasionally happen that what we picked in fact
4937     ;; *can't* form a pair and it returns error (for example, it
4938     ;; is an unclosed pair or a quote between words like'so, which
4939     ;; doesn't form a pair).  In such a case, or when the pair
4940     ;; found is further than the other possible pair type (for
4941     ;; example, we think we should parse stringlike, but we skip
4942     ;; the first occurrence and the next one is only after a
4943     ;; regular pair, which we should've picked instead), we must
4944     ;; try the other parser as well.
4945     (-let (((type . re) (if (or (and (not back) (< ps ss))
4946                                 (and back (> ps ss)))
4947                             (cons :regular (sp-get-paired-expression back))
4948                           (cons :string (sp-get-stringlike-or-textmode-expression back string-delim)))))
4949       (when re
4950         (sp-get re
4951           (cond
4952            ;; If the returned sexp is regular, but the
4953            ;; to-be-tried-string-expression is before it, we try
4954            ;; to parse it as well, it might be a complete sexp in
4955            ;; which case it should be returned.
4956            ((and (eq type :regular)
4957                  (or (and (not back) (< ss :beg))
4958                      (and back (> ss :end))))
4959             (or (sp-get-stringlike-or-textmode-expression back string-delim) re))
4960            ((and (eq type :string)
4961                  (or (and (not back) (< ps :beg))
4962                      (and back (> ps :end))))
4963             (or (sp-get-paired-expression back) re))
4964            (t re)))))))
4965
4966 (defun sp-get-sexp (&optional back)
4967   "Find the nearest balanced expression that is after (before) point.
4968
4969 Search backward if BACK is non-nil.  This also means, if the
4970 point is inside an expression, this expression is returned.
4971
4972 If `major-mode' is member of `sp-navigate-consider-sgml-tags',
4973 sgml tags will also be considered as sexps in current buffer.
4974
4975 If the search starts outside a comment, all subsequent comments
4976 are skipped.
4977
4978 If the search starts inside a string or comment, it tries to find
4979 the first balanced expression that is completely contained inside
4980 the string or comment.  If no such expression exist, a warning is
4981 raised (for example, when you comment out imbalanced expression).
4982 However, if you start a search from within a string and the next
4983 complete sexp lies completely outside, this is returned.  Note
4984 that this only works in modes where strings and comments are
4985 properly defined via the syntax tables.
4986
4987 The return value is a plist with following keys:
4988
4989   :beg    - point in the buffer before the opening
4990   delimiter (ignoring prefix)
4991   :end    - point in the buffer after the closing delimiter
4992   :op     - opening delimiter
4993   :cl     - closing delimiter
4994   :prefix - expression prefix
4995   :suffix - expression suffix
4996
4997 However, you should never access this structure directly as it is
4998 subject to change.  Instead, use the macro `sp-get' which also
4999 provide shortcuts for many commonly used queries (such as length
5000 of opening/closing delimiter or prefix)."
5001   (sp--maybe-init)
5002   (sp--with-case-sensitive
5003     (cond
5004      (sp-prefix-tag-object
5005       (sp-get-sgml-tag back))
5006      (sp-prefix-pair-object
5007       (sp-get-paired-expression back))
5008      ((memq major-mode sp-navigate-consider-sgml-tags)
5009       (let ((paired (sp-get-expression back)))
5010         (if (and paired
5011                  (equal "<" (sp-get paired :op)))
5012             ;; if the point is inside the tag delimiter, return the pair.
5013             (if (sp-get paired (and (<= :beg-in (point)) (>= :end-in (point))))
5014                 paired
5015               ;; if the tag can't be completed, we can at least return
5016               ;; the <> pair
5017               (or (sp-get-sgml-tag back) paired))
5018           ;; we can still try the tag if the first < or > is closer than
5019           ;; the pair.  This is a bit too complicated... seems like a
5020           ;; more clever solution would be needed in the future, esp if
5021           ;; we add the python hack.
5022           (cond
5023            ((and (not back)
5024                  (< (save-excursion
5025                       (or (search-forward "<" nil t) (point-max)))
5026                     (or (sp-get paired :beg) (point-max))))
5027             (or (sp-get-sgml-tag) paired))
5028            ((and back
5029                  (> (save-excursion
5030                       (or (search-backward ">" nil t) (point-min)))
5031                     (or (sp-get paired :end) (point-max))))
5032             (or (sp-get-sgml-tag t) paired))
5033            (t paired)))))
5034      (t (sp-get-expression back)))))
5035
5036 (defun sp--get-hybrid-sexp-beg ()
5037   "Get the beginning of hybrid sexp.
5038 See `sp-get-hybrid-sexp' for definition."
5039   (save-excursion
5040     (cl-labels ((indent-or-beg-of-line
5041                  (lb)
5042                  (if (sp-point-in-blank-line)
5043                      lb
5044                    (back-to-indentation)
5045                    (point))))
5046       (let ((p (progn (when (sp-point-in-symbol) (sp-backward-sexp)) (point)))
5047             (lb (line-beginning-position))
5048             (cur (--if-let (save-excursion (sp-backward-sexp)) it (list :end 0))) ;hack
5049             last)
5050         (if (< (sp-get cur :end) lb)
5051             ;; if the line is not empty, we move the beg to the indent
5052             (indent-or-beg-of-line lb)
5053           (while (sp-get cur
5054                    (and cur
5055                         (> :end lb)
5056                         (<= :end p)))
5057             (setq last cur)
5058             (setq cur (sp-backward-sexp)))
5059           (if last
5060               (sp-get last :beg-prf)
5061             ;; happens when there is no sexp before the opening delim of
5062             ;; the enclosing sexp.  In case it is on line above, we take
5063             ;; the maximum wrt lb.
5064             (sp-get cur (max :beg-in (indent-or-beg-of-line lb)))))))))
5065
5066 (defun sp--narrow-to-line ()
5067   "Narrow to the current line."
5068   (narrow-to-region (line-beginning-position) (line-end-position)))
5069
5070 (defun sp--get-hybrid-sexp-end ()
5071   "Get the end of hybrid sexp.
5072 See `sp-get-hybrid-sexp' for definition."
5073   (save-excursion
5074     (cl-labels ((skip-prefix-backward
5075                  (p)
5076                  (save-excursion
5077                    (goto-char p)
5078                    (save-restriction
5079                      (sp--narrow-to-line)
5080                      (skip-syntax-backward " .")
5081                      (point)))))
5082       (let ((p (progn (when (sp-point-in-symbol) (sp-backward-sexp)) (point)))
5083             (le (line-end-position))
5084             (cur (--if-let (save-excursion (sp-forward-sexp)) it (list :beg (1+ (point-max))))) ;hack
5085             last)
5086         (if (> (sp-get cur :beg) le)
5087             (if (sp-point-in-blank-line) le (skip-prefix-backward le))
5088           (while (sp-get cur
5089                    (and cur
5090                         (< :beg le)
5091                         (>= :beg p)))
5092             (setq last cur)
5093             (setq cur (sp-forward-sexp)))
5094           (let ((r (skip-prefix-backward
5095                     (if last
5096                         (sp-get last :end)
5097                       ;; happens when there is no sexp before the closing delim of
5098                       ;; the enclosing sexp.  In case it is on line below, we take
5099                       ;; the minimum wrt le.
5100                       (sp-get cur (min :end-in le))))))
5101             (goto-char r)
5102             ;; fix the situation when point ends in comment
5103             (cond
5104              ((sp-point-in-comment)
5105               (if (= (line-number-at-pos p)
5106                      (line-number-at-pos r))
5107                   (line-end-position)
5108                 (goto-char p)
5109                 (line-end-position)))
5110              (t r))))))))
5111
5112 (defun sp--get-hybrid-suffix (p)
5113   "Get the hybrid sexp suffix, which is any punctuation after
5114 the end, possibly preceded by whitespace."
5115   (save-excursion
5116     (goto-char p)
5117     (buffer-substring-no-properties
5118      p
5119      (save-restriction
5120        (sp--narrow-to-line)
5121        (skip-syntax-forward " ")
5122        (if (not (looking-at "\\s."))
5123            p
5124          (skip-syntax-forward ".")
5125          (point))))))
5126
5127 (defun sp-get-hybrid-sexp ()
5128   "Return the hybrid sexp around point.
5129
5130 A hybrid sexp is defined as the smallest balanced region containing
5131 the point while not expanding further than the current line.  That is,
5132 any hanging sexps will be included, but the expansion stops at the
5133 enclosing list boundaries or line boundaries."
5134   (let ((end (sp--get-hybrid-sexp-end)))
5135     (list :beg (sp--get-hybrid-sexp-beg)
5136           :end end
5137           :op ""
5138           :cl ""
5139           :prefix ""
5140           :suffix (sp--get-hybrid-suffix end))))
5141
5142 (defun sp-get-enclosing-sexp (&optional arg)
5143   "Return the balanced expression that wraps point at the same level.
5144
5145 With ARG, ascend that many times.  This function expects a positive
5146 argument."
5147   (setq arg (or arg 1))
5148   (save-excursion
5149     (let ((n arg)
5150           (ok t)
5151           (okr))
5152       (while (and (> n 0) ok)
5153         (setq ok t)
5154         (setq okr nil)
5155         ;; if we are inside string, get the string bounds and "string
5156         ;; expression"
5157         (when (sp-point-in-string)
5158           (setq okr (sp-get-string)))
5159         ;; get the "normal" expression defined by pairs
5160         (let ((p (point)))
5161           (setq ok (sp-get-sexp))
5162           (cond
5163            ((and ok (= (sp-get ok :beg) p))
5164             (goto-char (sp-get ok :end))
5165             (setq n (1+ n)))
5166            ((and ok (< (sp-get ok :beg) p))
5167             (goto-char (sp-get ok :end)))
5168            (t
5169             (while (and ok (>= (sp-get ok :beg) p))
5170               (setq ok (sp-get-sexp))
5171               (when ok (goto-char (sp-get ok :end)))))))
5172         ;; if the pair expression is enclosed inside a string, return
5173         ;; the pair expression, otherwise return the string expression
5174         (when okr
5175           (unless (and ok
5176                        (sp-compare-sexps ok okr >=)
5177                        (sp-compare-sexps ok okr <= :end))
5178             (setq ok okr)
5179             (goto-char (sp-get ok :end))))
5180         (setq n (1- n)))
5181       (if (not (and (not ok)
5182                     sp-navigate-comments-as-sexps))
5183           ok
5184         (when (sp-point-in-comment)
5185           (let* ((cb (sp-get-comment-bounds))
5186                  (b (save-excursion
5187                       (goto-char (car cb))
5188                       (sp-skip-backward-to-symbol t)
5189                       (point)))
5190                  (e (save-excursion
5191                       (goto-char (cdr cb))
5192                       (sp-skip-forward-to-symbol t)
5193                       (point))))
5194             (list :beg b :end e :op "" :cl "" :prefix sp-comment-char)))))))
5195
5196 (defun sp-get-list-items (&optional lst)
5197   "Return the information about expressions inside LST.
5198
5199 LST should be a data structure in format as returned by
5200 `sp-get-sexp'.
5201
5202 The return value is a list of such structures in order as they
5203 occur inside LST describing each expression, with LST itself
5204 prepended to the front.
5205
5206 If LST is nil, the list at point is used (that is the list
5207 following point after `sp-backward-up-sexp' is called)."
5208   (let ((r nil))
5209     (save-excursion
5210       (unless lst
5211         (setq lst (sp-backward-up-sexp)))
5212       (when lst
5213         (goto-char (sp-get lst :beg-in))
5214         (while (< (point) (sp-get lst :end))
5215           (!cons (sp-forward-sexp) r))
5216         (cons lst (nreverse (cdr r)))))))
5217
5218 (cl-defun sp--get-prefix (&optional (p (point)) op)
5219   "Get the prefix of EXPR.
5220
5221 Prefix is any continuous sequence of characters in \"expression
5222 prefix\" syntax class.  You can also specify a set of syntax code
5223 characters or a regexp for a specific major mode.  See
5224 `sp-sexp-prefix'.
5225
5226 The point is expected to be at the opening delimiter of the sexp
5227 and the prefix is searched backwards.
5228
5229 If the prefix property is defined for OP, the associated regexp
5230 is used to retrieve the prefix instead of the global setting."
5231   (sp--with-case-sensitive
5232     (save-excursion
5233       (goto-char p)
5234       (let* ((pref (sp-get-pair op :prefix))
5235              (prefix
5236               (if pref
5237                   (when (sp--looking-back pref sp-max-prefix-length)
5238                     (match-string-no-properties 0))
5239                 (-if-let (mmode-prefix (cdr (assoc major-mode sp-sexp-prefix)))
5240                     (cond
5241                      ((and (eq (car mmode-prefix) 'regexp)
5242                            (sp--looking-back (cadr mmode-prefix)))
5243                       (match-string-no-properties 0))
5244                      ((eq (car mmode-prefix) 'syntax)
5245                       (skip-syntax-backward (cadr mmode-prefix))
5246                       (buffer-substring-no-properties (point) p))
5247                      (t ""))
5248                   (backward-prefix-chars)
5249                   (buffer-substring-no-properties (point) p)))))
5250         ;; do not consider it a prefix if it matches some opening or
5251         ;; closing delimiter which is allowed for parsing in current
5252         ;; context
5253         (goto-char p)
5254         (if (and (< 0 (length prefix))
5255                  (or (sp--do-action-p prefix 'navigate)
5256                      (sp--do-action-p
5257                       (car (--first (equal (cdr it) prefix)
5258                                     sp-pair-list))
5259                       'navigate)))
5260             ""
5261           prefix)))))
5262
5263 (cl-defun sp--get-suffix (&optional (p (point)) op)
5264   "Get the suffix of EXPR.
5265
5266 Suffix is any continuous sequence of characters in the
5267 \"punctuation suffix\" syntax class.  You can also specify a set
5268 of syntax code characters or a regexp for a specific major mode.
5269 See `sp-sexp-suffix'.
5270
5271 If the suffix property is defined for OP, the associated regexp
5272 is used to retrieve the suffix instead of the global setting."
5273   (sp--with-case-sensitive
5274     (save-excursion
5275       (goto-char p)
5276       (let* ((suff (sp-get-pair op :suffix))
5277              (suffix
5278               (if suff
5279                   (when (sp--looking-at suff)
5280                     (match-string-no-properties 0))
5281                 (-if-let (mmode-suffix (cdr (assoc major-mode sp-sexp-suffix)))
5282                     (cond
5283                      ((and (eq (car mmode-suffix) 'regexp)
5284                            (sp--looking-at (cadr mmode-suffix)))
5285                       (match-string-no-properties 0))
5286                      ((eq (car mmode-suffix) 'syntax)
5287                       (skip-syntax-forward (cadr mmode-suffix))
5288                       (buffer-substring-no-properties p (point)))
5289                      (t ""))
5290                   (skip-syntax-forward ".")
5291                   (buffer-substring-no-properties p (point))))))
5292         ;; do not consider it a suffix if it matches some opening or
5293         ;; closing delimiter which is allowed for parsing in current
5294         ;; context
5295         (goto-char p)
5296         (if (and (< 0 (length suffix))
5297                  (or (sp--do-action-p suffix 'navigate)
5298                      (sp--do-action-p
5299                       (car (--first (equal (cdr it) suffix)
5300                                     sp-pair-list))
5301                       'navigate)))
5302             ""
5303           suffix)))))
5304
5305 (defun sp-get-symbol (&optional back)
5306   "Find the nearest symbol that is after point, or before point if BACK is non-nil.
5307
5308 This also means, if the point is inside a symbol, this symbol is
5309 returned.  Symbol is defined as a chunk of text recognized by
5310 `sp-forward-symbol'.
5311
5312 The return value is a plist with the same format as the value
5313 returned by `sp-get-sexp'."
5314   (sp--maybe-init)
5315   (let (b e last-or-first)
5316     (save-excursion
5317       (if back
5318           (progn
5319             (sp-skip-backward-to-symbol)
5320             (when (= (point) (point-min)) (setq last-or-first t))
5321             (sp-forward-symbol -1)
5322             (setq b (point))
5323             (sp-forward-symbol 1)
5324             (setq e (point)))
5325         (sp-skip-forward-to-symbol)
5326         (when (= (point) (point-max)) (setq last-or-first t))
5327         (sp-forward-symbol 1)
5328         (setq e (point))
5329         (sp-forward-symbol -1)
5330         (setq b (point))))
5331     (unless last-or-first
5332       (list :beg b :end e :op "" :cl "" :prefix (sp--get-prefix b) :suffix (sp--get-suffix e)))))
5333
5334 (defun sp--get-string (bounds)
5335   "Return the `sp-get-sexp' format info about the string.
5336
5337 This function simply transforms BOUNDS, which is a cons (BEG
5338 . END) into format compatible with `sp-get-sexp'."
5339   (let* ((op (char-to-string (char-after (car bounds))))
5340          (cl (char-to-string (char-before (cdr bounds)))))
5341     ;; if the closing and opening isn't the same token, we should
5342     ;; return nil
5343     (when (equal op cl)
5344       (list :beg (car bounds)
5345             :end (cdr bounds)
5346             :op cl
5347             :cl cl
5348             :prefix (sp--get-prefix (car bounds) op)
5349             :suffix (sp--get-suffix (cdr bounds) cl)))))
5350
5351 (defun sp-get-string (&optional back)
5352   "Find the nearest string after point, or before if BACK is non-nil.
5353
5354 This also means if the point is inside a string, this string is
5355 returned.  If there are another symbols between point and the
5356 string, nil is returned.  That means that this function only
5357 return non-nil if the string is the very next meaningful
5358 expression.
5359
5360 The return value is a plist with the same format as the value
5361 returned by `sp-get-sexp'."
5362   (sp--maybe-init)
5363   (if (sp-point-in-comment)
5364       (sp-get-stringlike-expression back)
5365     (if (sp-point-in-string)
5366         (let ((r (sp-get-quoted-string-bounds)))
5367           (sp--get-string r))
5368       (save-excursion
5369         (sp-skip-into-string back)
5370         (--when-let (sp-get-quoted-string-bounds)
5371           (sp--get-string it))))))
5372
5373 (defun sp-get-whitespace ()
5374   "Get the whitespace around point.
5375
5376 Whitespace here is defined as any of the characters: space, tab
5377 and newline."
5378   (list :beg (save-excursion (skip-chars-backward " \t\n") (point))
5379         :end (save-excursion (skip-chars-forward " \t\n") (point))
5380         :op ""
5381         :cl ""
5382         :prefix ""
5383         :suffix ""))
5384
5385 (defun sp--sgml-get-tag-name (match)
5386   (let ((sub (if (equal "/" (substring match 1 2))
5387                  (substring match 2)
5388                (substring match 1))))
5389     (car (split-string sub "\\( \\|>\\)"))))
5390
5391 (defun sp--sgml-opening-p (tag)
5392   (not (equal "/" (substring tag 1 2))))
5393
5394 (defun sp--sgml-ignore-tag (tag)
5395   "Return non-nil if tag should be ignored in search, nil otherwise."
5396   (member tag '("!--" "!DOCTYPE")))
5397
5398 (defun sp-get-sgml-tag (&optional back)
5399   (sp--maybe-init)
5400   (sp--with-case-sensitive
5401     (save-excursion
5402       (let ((search-fn (if (not back) 'sp--search-forward-regexp 'search-backward-regexp))
5403             tag tag-name needle
5404             open-start open-end
5405             close-start close-end)
5406         (when (and (funcall search-fn "</?.*?\\s-?.*?>" nil t)
5407                    (progn
5408                      (setq tag (substring-no-properties (match-string 0)))
5409                      (setq tag-name (sp--sgml-get-tag-name tag))
5410                      (not (sp--sgml-ignore-tag tag-name))))
5411           (setq needle (concat "</?" tag-name))
5412           (let* ((forward (sp--sgml-opening-p tag))
5413                  (search-fn (if forward 'sp--search-forward-regexp 'search-backward-regexp))
5414                  (depth 1))
5415             (save-excursion
5416               (if (not back)
5417                   (progn
5418                     (setq open-end (point))
5419                     (search-backward-regexp "<" nil t)
5420                     (setq open-start (point)))
5421                 (setq open-start (point))
5422                 (search-forward-regexp ">" nil t)
5423                 (setq open-end (point))))
5424             (cond
5425              ((and (not back) (not forward))
5426               (goto-char (match-beginning 0)))
5427              ((and back forward)
5428               (goto-char (match-end 0))))
5429             (while (> depth 0)
5430               (if (funcall search-fn needle nil t)
5431                   (if (sp--sgml-opening-p (match-string 0))
5432                       (if forward (setq depth (1+ depth)) (setq depth (1- depth)))
5433                     (if forward (setq depth (1- depth)) (setq depth (1+ depth))))
5434                 (setq depth -1)))
5435             (if (eq depth -1)
5436                 (progn (sp-message :no-matching-tag) nil)
5437               (save-excursion
5438                 (if forward
5439                     (progn
5440                       (setq close-start (match-beginning 0))
5441                       (search-forward-regexp ">" nil t)
5442                       (setq close-end (point)))
5443                   (setq close-start (point))
5444                   (search-forward-regexp ">" nil t)
5445                   (setq close-end (point))))
5446               (let ((op (buffer-substring-no-properties open-start open-end))
5447                     (cl (buffer-substring-no-properties close-start close-end)))
5448                 (list :beg (if forward open-start close-start)
5449                       :end (if forward close-end open-end)
5450                       :op (if forward op cl)
5451                       :cl (if forward cl op)
5452                       :prefix ""
5453                       :suffix "")))))))))
5454
5455 (defun sp--end-delimiter-closure (pairs pair-list)
5456   "Compute the \"end-delimiter\" closure of set PAIRS.
5457
5458 PAIRS can be:
5459 - single pair ID
5460 - single cons with opening and closing delimiter
5461 - list of pair IDs
5462 - list of conses of opening and closing delimiters
5463
5464 For example, if we have pairs (if . end) and (def . end), then
5465 the closure of \"if\" pair are both of these because they share
5466 the closing delimiter.  Therefore, in the navigation functions,
5467 both have to be considered by the parser."
5468   (let* ((pairs (-flatten (list pairs)))
5469          (pairs (if (consp (car pairs)) (-map 'car pairs) pairs))
5470          (pairs (--filter (member (car it) pairs) pair-list))
5471          (closure (-mapcat
5472                    (lambda (x)
5473                      (--filter (equal (cdr x) (cdr it)) pair-list))
5474                    pairs)))
5475     closure))
5476
5477 (defun sp-restrict-to-pairs (pairs function)
5478   "Call the FUNCTION restricted to PAIRS.
5479
5480 PAIRS is either an opening delimiter of a list of opening
5481 delimiters.
5482
5483 FUNCTION is a function symbol.
5484
5485 For example, you can restrict function `sp-down-sexp' to the
5486 pair (\"{\" . \"}\") for easier navigation of blocks in C-like
5487 languages."
5488   (let* ((pairs (-flatten (list pairs)))
5489          (new-pairs (--filter (member (car it) pairs) sp-pair-list))
5490          (sp-pair-list (sp--end-delimiter-closure new-pairs sp-pair-list)))
5491     (call-interactively function)))
5492
5493 (defun sp-restrict-to-object (object function)
5494   "Call the FUNCTION restricted to OBJECT.
5495
5496 OBJECT is one of following symbols (you have to quote it!):
5497 - `sp-prefix-pair-object'
5498 - `sp-prefix-tag-object'
5499 - `sp-prefix-symbol-object'
5500
5501 This function will enable this prefix and then call FUNCTION.
5502
5503 FUNCTION is a function symbol.
5504
5505 This function is equivalent to doing:
5506
5507   (let ((sp-prefix-object t))
5508     (call-interactively function))
5509
5510 For example, you can restrict function `sp-forward-sexp' to just
5511 the pairs for easier navigation of blocks in C-like languages."
5512   (cl-letf (((symbol-value object) t))
5513     (call-interactively function)))
5514
5515 ;; TODO: add shorter alias?
5516 (defun sp-restrict-to-pairs-interactive (pairs function)
5517   "Return an interactive lambda that calls FUNCTION restricted to PAIRS.
5518
5519 See `sp-restrict-to-pairs'.
5520
5521 This function implements a \"decorator pattern\", that is, you
5522 can apply another scoping function to the output of this function
5523 and the effects will added together. In particular, you can
5524 combine it with:
5525
5526 - `sp-restrict-to-object-interactive'
5527
5528 You can also bind the output of this function directly to a key, like:
5529
5530   (global-set-key (kbd ...) (sp-restrict-to-pairs-interactive \"{\" 'sp-down-sexp))
5531
5532 This will be a function that descends down only into { } pair,
5533 ignoring all others."
5534   (lambda (&optional _arg)
5535     (interactive "P")
5536     (sp-restrict-to-pairs pairs function)))
5537
5538 (defun sp-restrict-to-object-interactive (object function)
5539   "Return an interactive lambda that calls FUNCTION restricted to OBJECT.
5540
5541 See `sp-restrict-to-object'.
5542
5543 This function implements a \"decorator pattern\", that is, you
5544 can apply another scoping function to the output of this function
5545 and the effects will added together. In particular, you can
5546 combine it with:
5547
5548 - `sp-restrict-to-pairs-interactive'
5549
5550 You can also bind the output of this function directly to a key, like:
5551
5552   (global-set-key (kbd ...) (sp-restrict-to-object-interactive
5553                              'sp-prefix-pair-object
5554                              'sp-forward-sexp))
5555
5556 This will be a function that navigates only by using paired
5557 expressions, ignoring strings and sgml tags."
5558   (lambda (&optional _arg)
5559     (interactive "P")
5560     (sp-restrict-to-object object function)))
5561
5562 (defun sp-prefix-tag-object (&optional _arg)
5563   "Read the command and invoke it on the next tag object.
5564
5565 If you specify a regular emacs prefix argument this is passed to
5566 the executed command.  Therefore, executing
5567 \"\\[universal-argument] 2 \\[sp-prefix-tag-object] \\[sp-forward-sexp]\" will move two tag
5568 expressions forward, ignoring possible symbols or paired
5569 expressions inbetween.
5570
5571 Tag object is anything delimited by sgml tag."
5572   (interactive "P")
5573   (let* ((cmd (read-key-sequence "" t))
5574          (com (key-binding cmd))
5575          (sp-prefix-tag-object t))
5576     (if (commandp com)
5577         (call-interactively com)
5578       (execute-kbd-macro cmd))))
5579
5580 (defun sp-prefix-pair-object (&optional _arg)
5581   "Read the command and invoke it on the next pair object.
5582
5583 If you specify a regular emacs prefix argument this is passed to
5584 the executed command.  Therefore, executing
5585 \"\\[universal-argument] 2 \\[sp-prefix-pair-object] \\[sp-forward-sexp]\" will move two paired
5586 expressions forward, ignoring possible symbols inbetween.
5587
5588 Pair object is anything delimited by pairs from `sp-pair-list'."
5589   (interactive "P")
5590   (let* ((cmd (read-key-sequence "" t))
5591          (com (key-binding cmd))
5592          (sp-prefix-pair-object t))
5593     (if (commandp com)
5594         (call-interactively com)
5595       (execute-kbd-macro cmd))))
5596
5597 (defun sp-prefix-symbol-object (&optional _arg)
5598   "Read the command and invoke it on the next pair object.
5599
5600 If you specify a regular emacs prefix argument this is passed to
5601 the executed command.  Therefore, executing
5602 \"\\[universal-argument] 2 \\[sp-prefix-symbol-object] \\[sp-forward-sexp]\" will move two symbols
5603 forward, ignoring any structure.
5604
5605 Symbol is defined as a chunk of text recognized by
5606 `sp-forward-symbol'."
5607   (interactive "P")
5608   (let* ((cmd (read-key-sequence "" t))
5609          (com (key-binding cmd))
5610          (sp-prefix-symbol-object t))
5611     (if (commandp com)
5612         (call-interactively com)
5613       (execute-kbd-macro cmd))))
5614
5615 (defun sp-prefix-save-excursion (&optional _arg)
5616   "Execute the command keeping the point fixed.
5617
5618 If you specify a regular emacs prefix argument this is passed to
5619 the executed command."
5620   (interactive "P")
5621   (let* ((cmd (read-key-sequence "" t))
5622          (com (key-binding cmd)))
5623     (sp--keep-indentation
5624       (save-excursion
5625         (if (commandp com)
5626             (call-interactively com)
5627           (execute-kbd-macro cmd))))))
5628
5629 (defun sp-get-thing (&optional back)
5630   "Find next thing after point, or before if BACK is non-nil.
5631
5632 Thing is either symbol (`sp-get-symbol'),
5633 string (`sp-get-string') or balanced expression recognized by
5634 `sp-get-sexp'.
5635
5636 If `sp-navigate-consider-symbols' is nil, only balanced
5637 expressions are considered."
5638   (sp--maybe-init)
5639   (sp--with-case-sensitive
5640     (cond
5641      (sp-prefix-tag-object (sp-get-sgml-tag back))
5642      (sp-prefix-pair-object (sp-get-paired-expression back))
5643      (sp-prefix-symbol-object (sp-get-symbol back))
5644      (t
5645       (if back
5646           (if (not sp-navigate-consider-symbols)
5647               (sp-get-sexp t)
5648             (save-excursion
5649               (cond
5650                ((sp-point-in-empty-string)
5651                 (sp-get-string t))
5652                (t
5653                 (sp-skip-backward-to-symbol t nil t)
5654                 (cond
5655                  ;; this is an optimization, we do not need to look up
5656                  ;; the "pair" expression first. If this fails, follow
5657                  ;; up with regular sexps
5658                  ((and (memq major-mode sp-navigate-consider-sgml-tags)
5659                        (or (sp--looking-back ">")
5660                            ;; sp-skip-backward-to-symbol moves the
5661                            ;; point to the end of an element name in
5662                            ;; js2-jsx-mode
5663                            (looking-at ">"))
5664                        (sp-get-sgml-tag t)))
5665                  ((sp--valid-initial-delimiter-p (sp--looking-back (sp--get-closing-regexp (sp--get-allowed-pair-list)) nil))
5666                   (sp-get-sexp t))
5667                  ((sp--valid-initial-delimiter-p (sp--looking-back (sp--get-opening-regexp (sp--get-allowed-pair-list)) nil))
5668                   (sp-get-sexp t))
5669                  ((and (eq (syntax-class (syntax-after (1- (point)))) 7)
5670                        (not (sp-char-is-escaped-p (1- (point)))))
5671                   (if (eq t (sp-point-in-string))
5672                       (save-excursion
5673                         (save-restriction
5674                           (widen)
5675                           (-let (((beg . end) (sp-get-quoted-string-bounds)))
5676                             (narrow-to-region beg end))
5677                           (sp-get-stringlike-expression t)))
5678                     (sp-get-string t)))
5679                  ((sp--valid-initial-delimiter-p (sp--looking-back (sp--get-stringlike-regexp) nil))
5680                   (sp-get-expression t))
5681                  ;; We might be somewhere inside the prefix of the
5682                  ;; sexp after the point.  Since the prefix can be
5683                  ;; specified as regexp and not syntax class, it might
5684                  ;; itself by a symbol which would invalidly get
5685                  ;; picked here.
5686                  (t (-when-let (sym (sp-get-symbol t))
5687                       (save-excursion
5688                         (sp-get sym (goto-char :end))
5689                         (if (sp--valid-initial-delimiter-p (sp--looking-at (sp--get-opening-regexp (sp--get-allowed-pair-list))))
5690                             (let* ((ms (match-string 0))
5691                                    (pref (sp--get-prefix (point) ms)))
5692                               (if (and pref
5693                                        (not (equal pref "")))
5694                                   (sp-get-sexp t)
5695                                 sym))
5696                           sym)))))))))
5697         (if (not sp-navigate-consider-symbols)
5698             (sp-get-sexp nil)
5699           (save-excursion
5700             (cond
5701              ((sp-point-in-empty-string)
5702               (sp-get-string nil))
5703              (t
5704               (sp-skip-forward-to-symbol t nil t)
5705               (cond
5706                ((and (memq major-mode sp-navigate-consider-sgml-tags)
5707                      (or (looking-at "<")
5708                          ;; sp-skip-forward-to-symbol moves the point
5709                          ;; to the beginning of an element name in
5710                          ;; js2-jsx-mode
5711                          (and (sp--looking-back "</?" (- (point) 2))
5712                               (goto-char (match-beginning 0))))
5713                      (sp-get-sgml-tag)))
5714                ((sp--valid-initial-delimiter-p (sp--looking-at (sp--get-opening-regexp (sp--get-allowed-pair-list))))
5715                 (sp-get-sexp nil))
5716                ((sp--valid-initial-delimiter-p (sp--looking-at (sp--get-closing-regexp (sp--get-allowed-pair-list))))
5717                 (sp-get-sexp nil))
5718                ;; TODO: merge the following two conditions and use
5719                ;; `sp-get-stringlike-or-textmode-expression'
5720                ((and (eq (syntax-class (syntax-after (point))) 7)
5721                      (not (sp-char-is-escaped-p)))
5722                 ;; It might happen that the string delimiter we are
5723                 ;; looking at is nested inside another string
5724                 ;; delimited by string fences (for example nested "
5725                 ;; and ' in python).  In this case we can't use
5726                 ;; `sp-get-string' parser because it would pick up the
5727                 ;; outer string.  So if we are inside a string and
5728                 ;; `syntax-ppss' returns t as delimiter we need to use
5729                 ;; `sp-get-stringlike-expression'
5730                 (if (eq t (sp-point-in-string))
5731                     (save-excursion
5732                       (save-restriction
5733                         (widen)
5734                         (-let (((beg . end) (sp-get-quoted-string-bounds)))
5735                           (narrow-to-region beg end))
5736                         (sp-get-stringlike-expression nil)))
5737                   (sp-get-string nil)))
5738                ((sp--valid-initial-delimiter-p (sp--looking-at (sp--get-stringlike-regexp)))
5739                 (sp-get-expression nil))
5740                ;; it can still be that we are looking at a /prefix/ of a
5741                ;; sexp.  We should skip a symbol forward and check if it
5742                ;; is a sexp, and then maybe readjust the output.
5743                (t (let* ((sym (sp-get-symbol nil))
5744                          (sym-string (and sym (sp-get sym (buffer-substring-no-properties :beg :end))))
5745                          (point-before-prefix (point)))
5746                     (when sym-string
5747                       (if (sp--valid-initial-delimiter-p (sp--search-forward-regexp (sp--get-opening-regexp (sp--get-pair-list-context 'navigate)) nil t))
5748                           (let* ((ms (match-string 0))
5749                                  (pref (progn
5750                                          ;; need to move before the
5751                                          ;; opening, so (point) evals
5752                                          ;; there.
5753                                          (backward-char (length ms))
5754                                          (sp--get-prefix (point) ms))))
5755                             ;; We use >= because the first skip to
5756                             ;; symbol might have skipped some prefix
5757                             ;; chars which make prefix of the symbol
5758                             ;; which together make prefix of a sexp.
5759                             ;; For example \foo{} in latex, where \ is
5760                             ;; prefix of symbol foo and \foo is prefix
5761                             ;; of {
5762                             (if (and pref
5763                                      (not (equal pref ""))
5764                                      (>= point-before-prefix (- (point) (length pref))))
5765                                 (sp-get-sexp nil)
5766                               sym))
5767                         sym))))))))))))))
5768
5769 (defun sp-narrow-to-sexp (arg)
5770   "Make text outside current balanced expression invisible.
5771 A numeric arg specifies to move up by that many enclosing expressions.
5772
5773 See also `narrow-to-region' and `narrow-to-defun'."
5774   (interactive "p")
5775   (-when-let (enc (sp-get-enclosing-sexp arg))
5776     (sp-get enc (narrow-to-region :beg-prf :end))))
5777
5778 (defun sp-forward-sexp (&optional arg)
5779   "Move forward across one balanced expression.
5780
5781 With ARG, do it that many times.  Negative arg -N means move
5782 backward across N balanced expressions.  If there is no forward
5783 expression, jump out of the current one (effectively doing
5784 `sp-up-sexp').
5785
5786 With `sp-navigate-consider-symbols' symbols and strings are also
5787 considered balanced expressions.
5788
5789 Examples: (prefix arg in comment)
5790
5791   |(foo bar baz)   -> (foo bar baz)|
5792
5793   (|foo bar baz)   -> (foo| bar baz)
5794
5795   (|foo bar baz)   -> (foo bar| baz) ;; 2
5796
5797   (foo (bar baz|)) -> (foo (bar baz)|)"
5798   (interactive "^p")
5799   (setq arg (or arg 1))
5800   (if (< arg 0)
5801       (sp-backward-sexp (- arg))
5802     (let* ((n arg)
5803            (ok t))
5804       (while (and ok (> n 0))
5805         (setq ok (sp-get-thing))
5806         (setq n (1- n))
5807         (when ok (goto-char (sp-get ok :end))))
5808       ok)))
5809
5810 (put 'sp-forward-sexp 'CUA 'move)
5811
5812 (defun sp-backward-sexp (&optional arg)
5813   "Move backward across one balanced expression (sexp).
5814
5815 With ARG, do it that many times.  Negative arg -N means move
5816 forward across N balanced expressions.  If there is no previous
5817 expression, jump out of the current one (effectively doing
5818 `sp-backward-up-sexp').
5819
5820 With `sp-navigate-consider-symbols' symbols and strings are also
5821 considered balanced expressions.
5822
5823 Examples: (prefix arg in comment)
5824
5825   (foo bar baz)|   -> |(foo bar baz)
5826
5827   (foo| bar baz)   -> (|foo bar baz)
5828
5829   (foo bar| baz)   -> (|foo bar baz) ;; 2
5830
5831   (|(foo bar) baz) -> ((|foo bar) baz)"
5832   (interactive "^p")
5833   (setq arg (or arg 1))
5834   (if (< arg 0)
5835       (sp-forward-sexp (- arg))
5836     (let* ((n arg)
5837            (ok t))
5838       (while (and ok (> n 0))
5839         (setq ok (sp-get-thing t))
5840         (setq n (1- n))
5841         (when ok (goto-char (sp-get ok :beg))))
5842       ok)))
5843
5844 (put 'sp-backward-sexp 'CUA 'move)
5845
5846 (defun sp-next-sexp (&optional arg)
5847   "Move forward to the beginning of next balanced expression.
5848
5849 With ARG, do it that many times.  If there is no next expression
5850 at current level, jump one level up (effectively doing
5851 `sp-backward-up-sexp').  Negative arg -N means move to the
5852 beginning of N-th previous balanced expression.
5853
5854 If `sp-navigate-interactive-always-progress-point' is non-nil,
5855 and this is called interactively, the point will move to the
5856 first expression in forward direction where it will end up
5857 greater than the current location.
5858
5859 With `sp-navigate-consider-symbols' symbols and strings are also
5860 considered balanced expressions.
5861
5862 Examples:
5863
5864   ((foo) |bar (baz quux)) -> ((foo) bar |(baz quux))
5865
5866   ((foo) bar |(baz quux)) -> |((foo) bar (baz quux))
5867
5868 and with non-nil `sp-navigate-interactive-always-progress-point'
5869
5870   (f|oo bar) -> (foo |bar)
5871
5872   ((fo|o) (bar)) -> ((foo) |(bar))"
5873   (interactive "^p")
5874   (setq arg (or arg 1))
5875   (if (<= arg 0)
5876       (sp-backward-sexp (- arg))
5877     (if (and sp-navigate-interactive-always-progress-point
5878              (called-interactively-p 'any))
5879         (progn
5880           (while (< 0 arg)
5881             (let ((point-start (point)))
5882               (while (--when-let (sp-forward-sexp)
5883                        (<= (sp-get it :beg) point-start))))
5884             (setq arg (1- arg)))
5885           (goto-char (sp-get (sp-get-thing t) :beg)))
5886       (if (= arg 1)
5887           (-when-let (ok (sp-get-thing))
5888             (if (= (point) (sp-get ok :beg))
5889                 (progn (sp-forward-sexp 2)
5890                        (sp-backward-sexp))
5891               (goto-char (sp-get ok :beg))
5892               ok))
5893         (sp-forward-sexp arg)
5894         (sp-backward-sexp)))))
5895
5896 (put 'sp-next-sexp 'CUA 'move)
5897
5898 (defun sp-previous-sexp (&optional arg)
5899   "Move backward to the end of previous balanced expression.
5900
5901 With ARG, do it that many times.  If there is no next
5902 expression at current level, jump one level up (effectively
5903 doing `sp-up-sexp').  Negative arg -N means move to the end of
5904 N-th following balanced expression.
5905
5906 With `sp-navigate-consider-symbols' symbols and strings are also
5907 considered balanced expressions.
5908
5909 If `sp-navigate-interactive-always-progress-point' is non-nil,
5910 and this is called interactively, the point will move to the
5911 first expression in backward direction where it will end up
5912 less than the current location.
5913
5914 Examples:
5915
5916   ((foo) bar| (baz quux)) -> ((foo)| bar (baz quux))
5917
5918   ((foo)| bar (baz quux)) -> ((foo) bar (baz quux))|
5919
5920 and if `sp-navigate-interactive-always-progress-point' is non-nil
5921
5922   (foo b|ar baz) -> (foo| bar baz)
5923
5924   (foo (b|ar baz)) -> (foo| (bar baz))"
5925   (interactive "^p")
5926   (setq arg (or arg 1))
5927   (if (<= arg 0)
5928       (sp-forward-sexp (- arg))
5929     (if (and sp-navigate-interactive-always-progress-point
5930              ;; (called-interactively-p 'any)
5931              )
5932         (progn
5933           (while (< 0 arg)
5934             (let ((point-start (point)))
5935               (while (--when-let (sp-backward-sexp)
5936                        (>= (sp-get it :end) point-start))))
5937             (setq arg (1- arg)))
5938           (goto-char (sp-get (sp-get-thing) :end)))
5939       (if (= arg 1)
5940           (-when-let (ok (sp-get-thing t))
5941             (if (= (point) (sp-get ok :end))
5942                 (progn (sp-backward-sexp 2)
5943                        (sp-forward-sexp))
5944               (goto-char (sp-get ok :end))
5945               ok))
5946         (sp-backward-sexp arg)
5947         (sp-forward-sexp)))))
5948
5949 (put 'sp-previous-sexp 'CUA 'move)
5950
5951 (defun sp-forward-parallel-sexp (&optional arg)
5952   "Move forward across one balanced expressions at the same depth.
5953
5954 If calling `sp-forward-sexp' at point would result in raising a
5955 level up, loop back to the first expression at current level,
5956 that is the first child of the enclosing sexp as defined by
5957 `sp-get-enclosing-sexp'."
5958   (interactive "^p")
5959   (setq arg (or arg 1))
5960   (if (< arg 0)
5961       (sp-backward-parallel-sexp (- arg))
5962     (let (re)
5963       (while (> arg 0)
5964         (setq arg (1- arg))
5965         (let ((next (sp-get-thing))
5966               (prev (sp-get-thing t)))
5967           (setq
5968            re
5969            (cond
5970             ((eq next nil)
5971              (goto-char (point-min))
5972              (sp-forward-sexp))
5973             ((eq prev nil)
5974              (goto-char (sp-get next :end))
5975              next)
5976             (t (if (> (sp-get next :beg) (sp-get prev :beg))
5977                    (progn
5978                      (goto-char (sp-get next :end))
5979                      next)
5980                  (goto-char (sp-get next :beg-in))
5981                  (sp-forward-sexp)))))))
5982       re)))
5983
5984 (defun sp-backward-parallel-sexp (&optional arg)
5985   "Move backward across one balanced expressions at the same depth.
5986
5987 If calling `sp-backward-sexp' at point would result in raising a
5988 level up, loop back to the last expression at current level, that
5989 is the last child of the enclosing sexp as defined by
5990 `sp-get-enclosing-sexp'."
5991   (interactive "^p")
5992   (setq arg (or arg 1))
5993   (if (< arg 0)
5994       (sp-forward-parallel-sexp (- arg))
5995     (let (re)
5996       (while (> arg 0)
5997         (setq arg (1- arg))
5998         (let ((next (sp-get-thing))
5999               (prev (sp-get-thing t)))
6000           (setq
6001            re
6002            (cond
6003             ((eq prev nil)
6004              (goto-char (point-max))
6005              (sp-backward-sexp))
6006             ((eq next nil)
6007              (goto-char (sp-get prev :beg))
6008              prev)
6009             (t (if (< (sp-get prev :end) (sp-get next :end))
6010                    (progn
6011                      (goto-char (sp-get prev :beg))
6012                      prev)
6013                  (goto-char (sp-get prev :end-in))
6014                  (sp-backward-sexp)))))))
6015       re)))
6016
6017 (defun sp--raw-argument-p (arg)
6018   "Return t if ARG represents raw argument, that is a non-empty list."
6019   (and (listp arg) (car arg)))
6020
6021 (defun sp--negate-argument (arg)
6022   "Return the argument ARG but negated.
6023
6024 If the argument is a raw prefix argument (cons num nil) return a
6025 list with its car negated.  If the argument is just the - symbol,
6026 return 1.  If the argument is nil, return -1.  Otherwise negate
6027 the input number."
6028   (cond
6029    ((sp--raw-argument-p arg) (list (- (car arg))))
6030    ((eq arg '-) 1)
6031    ((not arg) -1)
6032    (t (- arg))))
6033
6034 (defun sp-down-sexp (&optional arg)
6035   "Move forward down one level of sexp.
6036
6037 With ARG, do this that many times.  A negative argument -N means
6038 move backward but still go down a level.
6039
6040 If ARG is raw prefix argument \\[universal-argument], descend forward as much as
6041 possible.
6042
6043 If ARG is raw prefix argument \\[universal-argument] \\[universal-argument], jump to the beginning of
6044 current list.
6045
6046 If the point is inside sexp and there is no down expression to
6047 descend to, jump to the beginning of current one.  If moving
6048 backwards, jump to end of current one.
6049
6050 Examples:
6051
6052   |foo (bar (baz quux)) -> foo (|bar (baz quux))
6053
6054   |foo (bar (baz quux)) -> foo (bar (|baz quux)) ;; 2
6055
6056   |foo (bar (baz (quux) blab)) -> foo (bar (baz (|quux) blab)) ;; \\[universal-argument]
6057
6058   (foo (bar baz) |quux) -> (|foo (bar baz) quux)
6059
6060   (blab foo |(bar baz) quux) -> (|blab foo (bar baz) quux) ;; \\[universal-argument] \\[universal-argument]"
6061   (interactive "^P")
6062   (let* ((raw (sp--raw-argument-p arg))
6063          (arg (prefix-numeric-value arg))
6064          (n (abs arg))
6065          (ok t)
6066          (last-point -1))
6067     (if (and raw (= (abs arg) 16))
6068         ;; jump to the beginning/end of current list
6069         (-when-let (enc (sp-get-enclosing-sexp))
6070           (if (> arg 0)
6071               (goto-char (sp-get enc :beg-in))
6072             (goto-char (sp-get enc :end-in)))
6073           (setq ok enc))
6074       ;; otherwise descend normally
6075       (while (and ok (> n 0))
6076         (setq ok (sp-get-sexp (< arg 0)))
6077         ;; if the prefix was C-u, we do not decrease n and instead set
6078         ;; it to -1 when (point) == "last ok"
6079         (if raw
6080             (when (= (point) last-point)
6081               (setq n -1))
6082           (setq n (1- n)))
6083         (when ok
6084           (setq last-point (point))
6085           (if (< arg 0)
6086               (goto-char (sp-get ok :end-in))
6087             (goto-char (sp-get ok :beg-in))))))
6088     ok))
6089
6090 (put 'sp-down-sexp 'CUA 'move)
6091
6092 (defun sp-backward-down-sexp (&optional arg)
6093   "Move backward down one level of sexp.
6094
6095 With ARG, do this that many times.  A negative argument -N means
6096 move forward but still go down a level.
6097
6098 If ARG is raw prefix argument \\[universal-argument], descend backward as much as
6099 possible.
6100
6101 If ARG is raw prefix argument \\[universal-argument] \\[universal-argument], jump to the end of current
6102 list.
6103
6104 If the point is inside sexp and there is no down expression to
6105 descend to, jump to the end of current one.  If moving forward,
6106 jump to beginning of current one.
6107
6108 Examples:
6109
6110   foo (bar (baz quux))| -> foo (bar (baz quux)|)
6111
6112   (bar (baz quux)) foo| -> (bar (baz quux|)) foo ;; 2
6113
6114   foo (bar (baz (quux) blab))| -> foo (bar (baz (quux|) blab)) ;; \\[universal-argument]
6115
6116   (foo| (bar baz) quux) -> (foo (bar baz) quux|)
6117
6118   (foo (bar baz) |quux blab) -> (foo (bar baz) quux blab|) ;; \\[universal-argument] \\[universal-argument]"
6119   (interactive "^P")
6120   (sp-down-sexp (sp--negate-argument arg)))
6121
6122 (put 'sp-backward-down-sexp 'CUA 'move)
6123
6124 (defun sp-beginning-of-sexp (&optional arg)
6125   "Jump to beginning of the sexp the point is in.
6126
6127 The beginning is the point after the opening delimiter.
6128
6129 With no argument, this is the same as calling
6130 \\[universal-argument] \\[universal-argument] `sp-down-sexp'
6131
6132 With ARG positive N > 1, move forward out of the current
6133 expression, move N-2 expressions forward and move down one level
6134 into next expression.
6135
6136 With ARG negative -N < 1, move backward out of the current
6137 expression, move N-1 expressions backward and move down one level
6138 into next expression.
6139
6140 With ARG raw prefix argument \\[universal-argument] move out of the current expressions
6141 and then to the beginning of enclosing expression.
6142
6143 Examples:
6144
6145   (foo (bar baz) quux| (blab glob)) -> (|foo (bar baz) quux (blab glob))
6146
6147   (foo (bar baz|) quux (blab glob)) -> (foo (|bar baz) quux (blab glob))
6148
6149   (|foo) (bar) (baz quux) -> (foo) (bar) (|baz quux) ;; 3
6150
6151   (foo bar) (baz) (quux|) -> (|foo bar) (baz) (quux) ;; -3
6152
6153   ((foo bar) (baz |quux) blab) -> (|(foo bar) (baz quux) blab) ;; \\[universal-argument]"
6154   (interactive "^P")
6155   (let* ((raw (sp--raw-argument-p arg))
6156          (arg (prefix-numeric-value arg))
6157          (re (cond
6158               ((and raw (= arg 4))
6159                (sp-up-sexp)
6160                (sp-beginning-of-sexp))
6161               ((= arg 1)
6162                (sp-down-sexp '(16)))
6163               ((< arg 0)
6164                (sp-backward-up-sexp)
6165                (sp-forward-sexp (1+ arg))
6166                (sp-down-sexp))
6167               ((> arg 0)
6168                (sp-up-sexp)
6169                (sp-forward-sexp (- arg 2))
6170                (sp-down-sexp)))))
6171     (sp--run-hook-with-args (sp-get re :op) :post-handlers 'beginning-of-sexp)
6172     re))
6173
6174 (put 'sp-beginning-of-sexp 'CUA 'move)
6175
6176 (defun sp-end-of-sexp (&optional arg)
6177   "Jump to end of the sexp the point is in.
6178
6179 The end is the point before the closing delimiter.
6180
6181 With no argument, this is the same as calling
6182 \\[universal-argument] \\[universal-argument] `sp-backward-down-sexp'.
6183
6184 With ARG positive N > 1, move forward out of the current
6185 expression, move N-1 expressions forward and move down backward
6186 one level into previous expression.
6187
6188 With ARG negative -N < 1, move backward out of the current
6189 expression, move N-2 expressions backward and move down backward
6190 one level into previous expression.
6191
6192 With ARG raw prefix argument \\[universal-argument] move out of the current expressions
6193 and then to the end of enclosing expression.
6194
6195 Examples:
6196
6197   (foo |(bar baz) quux (blab glob)) -> (foo (bar baz) quux (blab glob)|)
6198
6199   (foo (|bar baz) quux (blab glob)) -> (foo (bar baz|) quux (blab glob))
6200
6201   (|foo) (bar) (baz quux) -> (foo) (bar) (baz quux|) ;; 3
6202
6203   (foo bar) (baz) (quux|) -> (foo bar|) (baz) (quux) ;; -3
6204
6205   ((foo |bar) (baz quux) blab) -> ((foo bar) (baz quux) blab|) ;; \\[universal-argument]"
6206   (interactive "^P")
6207   (let* ((raw (sp--raw-argument-p arg))
6208          (arg (prefix-numeric-value arg))
6209          (re (cond
6210               ((and raw (= arg 4))
6211                (sp-up-sexp)
6212                (sp-end-of-sexp))
6213               ((= arg 1)
6214                (sp-down-sexp '(-16)))
6215               ((< arg 0)
6216                (sp-backward-up-sexp)
6217                (sp-forward-sexp (+ 2 arg))
6218                (sp-backward-down-sexp))
6219               ((> arg 0)
6220                (sp-up-sexp)
6221                (sp-forward-sexp (1- arg))
6222                (sp-backward-down-sexp)))))
6223     (sp--run-hook-with-args (sp-get re :op) :post-handlers 'end-of-sexp)
6224     re))
6225
6226 (put 'sp-end-of-sexp 'CUA 'move)
6227
6228 (defun sp-beginning-of-next-sexp (&optional arg)
6229   "Jump to the beginning of next sexp on the same depth.
6230
6231 Optional argument ARG defaults to 1 and means how many times we
6232 should repeat.
6233
6234 This acts exactly as `sp-beginning-of-sexp' but adds 1 to the
6235 numeric argument.
6236
6237 Examples:
6238
6239   (f|oo) (bar) (baz) -> (foo) (|bar) (baz)
6240
6241   (f|oo) (bar) (baz) -> (foo) (bar) (|baz) ;; 2"
6242   (interactive "^P")
6243   (if (sp--raw-argument-p arg)
6244       (sp-beginning-of-sexp arg)
6245     (let ((arg (prefix-numeric-value arg)))
6246       (if (> arg 0)
6247           (sp-beginning-of-sexp (1+ arg))
6248         (sp-beginning-of-sexp (1- arg))))))
6249
6250 (put 'sp-beginning-of-next-sexp 'CUA 'move)
6251
6252 (defun sp-beginning-of-previous-sexp (&optional arg)
6253   "Jump to the beginning of previous sexp on the same depth.
6254
6255 Optional argument ARG defaults to 1 and means how many times we
6256 should repeat.
6257
6258 This acts exactly as `sp-beginning-of-sexp' with negative
6259 argument but subtracts 1 from it.
6260
6261 Examples:
6262
6263   (foo) (b|ar) (baz) -> (|foo) (bar) (baz)
6264
6265   (foo) (bar) (b|az) -> (|foo) (bar) (baz) ;; 2"
6266   (interactive "^P")
6267   (if (sp--raw-argument-p arg)
6268       (sp-beginning-of-sexp (sp--negate-argument arg))
6269     (let ((arg (prefix-numeric-value arg)))
6270       (if (> arg 0)
6271           (sp-beginning-of-sexp (- (1+ arg)))
6272         (sp-beginning-of-sexp (- (1- arg)))))))
6273
6274 (put 'sp-beginning-of-previous-sexp 'CUA 'move)
6275
6276 (defun sp-end-of-next-sexp (&optional arg)
6277   "Jump to the end of next sexp on the same depth.
6278
6279 Optional argument ARG defaults to 1 and means how many times we
6280 should repeat.
6281
6282 This acts exactly as `sp-end-of-sexp' but adds 1 to the
6283 numeric argument.
6284
6285 Examples:
6286
6287   (f|oo) (bar) (baz) -> (foo) (bar|) (baz)
6288
6289   (f|oo) (bar) (baz) -> (foo) (bar) (baz|) ;; 2"
6290   (interactive "^P")
6291   (if (sp--raw-argument-p arg)
6292       (sp-end-of-sexp arg)
6293     (let ((arg (prefix-numeric-value arg)))
6294       (if (> arg 0)
6295           (sp-end-of-sexp (1+ arg))
6296         (sp-end-of-sexp (1- arg))))))
6297
6298 (put 'sp-end-of-next-sexp 'CUA 'move)
6299
6300 (defun sp-end-of-previous-sexp (&optional arg)
6301   "Jump to the end of previous sexp on the same depth.
6302
6303 Optional argument ARG defaults to 1 and means how many times we
6304 should repeat.
6305
6306 This acts exactly as `sp-end-of-sexp' with negative
6307 argument but subtracts 1 from it.
6308
6309 Examples:
6310
6311   (foo) (b|ar) (baz) -> (foo|) (bar) (baz)
6312
6313   (foo) (bar) (b|az) -> (foo|) (bar) (baz) ;; 2"
6314   (interactive "^P")
6315   (if (sp--raw-argument-p arg)
6316       (sp-end-of-sexp (sp--negate-argument arg))
6317     (let ((arg (prefix-numeric-value arg)))
6318       (if (> arg 0)
6319           (sp-end-of-sexp (- (1+ arg)))
6320         (sp-end-of-sexp (- (1- arg)))))))
6321
6322 (put 'sp-end-of-previous-sexp 'CUA 'move)
6323
6324 ;; TODO: split the reindent code so we can call it inside strings on
6325 ;; sexps like [foo ]... We can't reindent that by default because it
6326 ;; can be a regular expression or something where the whitespace
6327 ;; matters.  For now, disable reindent in strings if the sexp is not
6328 ;; the string quote itself.
6329 (defun sp-up-sexp (&optional arg interactive)
6330   "Move forward out of one level of parentheses.
6331
6332 With ARG, do this that many times.  A negative argument means
6333 move backward but still to a less deep spot.
6334
6335 The argument INTERACTIVE is for internal use only.
6336
6337 If called interactively and `sp-navigate-reindent-after-up' is
6338 enabled for current major-mode, remove the whitespace between end
6339 of the expression and the last \"thing\" inside the expression.
6340
6341 If `sp-navigate-close-if-unbalanced' is non-nil, close the
6342 unbalanced expressions automatically.
6343
6344 Examples:
6345
6346   (foo |(bar baz) quux blab) -> (foo (bar baz) quux blab)|
6347
6348   (foo (bar |baz) quux blab) -> (foo (bar baz) quux blab)| ;; 2
6349
6350   (foo bar |baz              -> (foo bar baz)| ;; re-indent the expression
6351 ​   )
6352
6353   (foo  |(bar baz)           -> (foo)| (bar baz) ;; close unbalanced expr."
6354   (interactive "^p\np")
6355   (setq arg (or arg 1))
6356   (sp--with-case-sensitive
6357     (let ((ok (sp-get-enclosing-sexp (abs arg))))
6358       (if ok
6359           (progn
6360             (if (> arg 0)
6361                 (goto-char (sp-get ok :end))
6362               (goto-char (sp-get ok :beg)))
6363             (when (and (= (abs arg) 1)
6364                        (not (equal (sp-get ok :prefix) sp-comment-char))
6365                        (or (memq major-mode (assq 'always sp-navigate-reindent-after-up))
6366                            (and (memq major-mode (assq 'interactive sp-navigate-reindent-after-up))
6367                                 interactive))
6368                        (or sp-navigate-reindent-after-up-in-string
6369                            (sp-get ok (not (sp-point-in-string :end-in))))
6370                        ;; if the sexp to be reindented is not a string
6371                        ;; but is inside a string, we should rather do
6372                        ;; nothing than break semantics (in e.g. regexp
6373                        ;; [...])
6374                        (let ((str (sp-point-in-string)))
6375                          (or (not str)
6376                              ;; op must be the delimiter of the string we're in
6377                              (eq (sp-get ok :op)
6378                                  (or (eq str t)
6379                                      (char-to-string str))))))
6380               ;; TODO: this needs different indent rules for different
6381               ;; modes.  Should we concern with such things?  Lisp rules are
6382               ;; funny in HTML... :/
6383               (save-excursion
6384                 (if (> arg 0)
6385                     (progn
6386                       (goto-char (sp-get ok :end-in))
6387                       (let ((prev (sp-get-thing t)))
6388                         ;; if the expression is empty remove everything inside
6389                         (if (sp-compare-sexps ok prev)
6390                             (sp-get ok (delete-region :beg-in :end-in))
6391                           (when (save-excursion
6392                                   (skip-chars-backward " \t\n")
6393                                   (= (point) (sp-get prev :end-suf)))
6394                             (delete-region (sp-get prev :end-suf) (point))))))
6395                   (goto-char (sp-get ok :beg-in))
6396                   (let ((next (sp-get-thing)))
6397                     (if (sp-compare-sexps ok next)
6398                         (sp-get ok (delete-region :beg-in :end-in))
6399                       (when (save-excursion
6400                               (skip-chars-forward " \t\n")
6401                               (= (point) (sp-get next :beg-prf)))
6402                         (delete-region (point) (sp-get next :beg-prf)))))))))
6403         ;; on forward up, we can detect that the pair was not closed.
6404         ;; Therefore, jump sexps backwards until we hit the error, then
6405         ;; extract the opening pair and insert it at point.  Only works
6406         ;; for pairs defined in `sp-pair-list'.
6407         (when (and (> arg 0)
6408                    sp-navigate-close-if-unbalanced)
6409           (let (active-pair)
6410             (save-excursion
6411               ;; add support for SGML tags here
6412               (while (sp-backward-sexp))
6413               (sp-skip-backward-to-symbol t)
6414               (when (sp--looking-back (sp--get-opening-regexp))
6415                 (let* ((op (match-string 0)))
6416                   (setq active-pair (assoc op sp-pair-list)))))
6417             (when active-pair
6418               (sp-backward-sexp)
6419               (sp-forward-sexp)
6420               (insert (cdr active-pair))))))
6421       ok)))
6422
6423 (put 'sp-up-sexp 'CUA 'move)
6424
6425 (defun sp-backward-up-sexp (&optional arg interactive)
6426   "Move backward out of one level of parentheses.
6427
6428 With ARG, do this that many times.  A negative argument means
6429 move forward but still to a less deep spot.
6430
6431 The argument INTERACTIVE is for internal use only.
6432
6433 If called interactively and `sp-navigate-reindent-after-up' is
6434 enabled for current major-mode, remove the whitespace between
6435 beginning of the expression and the first \"thing\" inside the
6436 expression.
6437
6438 Examples:
6439
6440   (foo (bar baz) quux| blab) -> |(foo (bar baz) quux blab)
6441
6442   (foo (bar |baz) quux blab) -> |(foo (bar baz) quux blab) ;; 2
6443
6444   (                  -> |(foo bar baz)
6445 ​    foo |bar baz)"
6446   (interactive "^p\np")
6447   (setq arg (or arg 1))
6448   (sp-up-sexp (- arg) interactive))
6449
6450 (put 'sp-backward-up-sexp 'CUA 'move)
6451
6452 (defvar sp-last-kill-whitespace nil
6453   "Save the whitespace cleaned after the last kill.
6454
6455 If the next command is `sp-kill-sexp', append the whitespace
6456 between the successive kills.")
6457
6458 (defun sp--kill-or-copy-region (beg end &optional dont-kill)
6459   "Kill or copy region between BEG and END according to DONT-KILL.
6460 If `evil-mode' is active, copying a region will also add it to the 0 register.
6461 Additionally, if command was prefixed with a register, copy the region
6462 to that register."
6463   (interactive)
6464   (let ((result
6465          (if dont-kill
6466              (copy-region-as-kill beg end)
6467            (kill-region beg end))))
6468     (when (bound-and-true-p evil-mode)
6469       (when dont-kill
6470         (evil-set-register ?0 (evil-get-register ?1)))
6471       (when evil-this-register
6472         (evil-set-register evil-this-register (evil-get-register ?1))
6473         (setq evil-this-register nil)))
6474     result))
6475
6476 (defun sp-kill-sexp (&optional arg dont-kill)
6477   "Kill the balanced expression following point.
6478
6479 If point is inside an expression and there is no following
6480 expression, kill the topmost enclosing expression.
6481
6482 With ARG being positive number N, repeat that many times.
6483
6484 With ARG being Negative number -N, repeat that many times in
6485 backward direction.
6486
6487 With ARG being raw prefix \\[universal-argument], kill all the expressions from
6488 point up until the end of current list.  With raw prefix \\[negative-argument] \\[universal-argument],
6489 kill all the expressions from beginning of current list up until
6490 point.  If point is inside a symbol, this is also killed.  If
6491 there is no expression after/before the point, just delete the
6492 whitespace up until the closing/opening delimiter.
6493
6494 With ARG being raw prefix \\[universal-argument] \\[universal-argument], kill current list (the list
6495 point is inside).
6496
6497 With ARG numeric prefix 0 (zero) kill the insides of the current
6498 list, that is everything from after the opening delimiter to
6499 before the closing delimiter.
6500
6501 If ARG is nil, default to 1 (kill single expression forward)
6502
6503 If second optional argument DONT-KILL is non-nil, save the to be
6504 killed region in the kill ring, but do not kill the region from
6505 buffer.
6506
6507 With `sp-navigate-consider-symbols', symbols and strings are also
6508 considered balanced expressions.
6509
6510 Examples:
6511
6512  (foo |(abc) bar)  -> (foo | bar) ;; nil, defaults to 1
6513
6514  (foo (bar) | baz) -> |           ;; 2
6515
6516  (foo |(bar) baz)  -> |           ;; \\[universal-argument] \\[universal-argument]
6517
6518  (1 |2 3 4 5 6)    -> (1|)        ;; \\[universal-argument]
6519
6520  (1 |2 3 4 5 6)    -> (1 | 5 6)   ;; 3
6521
6522  (1 2 3 4 5| 6)    -> (1 2 3 | 6) ;; -2
6523
6524  (1 2 3 4| 5 6)    -> (|5 6)      ;; - \\[universal-argument]
6525
6526  (1 2 |   )        -> (1 2|)      ;; \\[universal-argument], kill useless whitespace
6527
6528  (1 2 3 |4 5 6)    -> (|)         ;; 0
6529
6530 Note: prefix argument is shown after the example in
6531 \"comment\". Assumes `sp-navigate-consider-symbols' equal to t."
6532   (interactive "P")
6533   (let* ((raw (sp--raw-argument-p arg))
6534          (arg (prefix-numeric-value arg))
6535          (n (abs arg))
6536          (ok t)
6537          (b (point-max))
6538          (e (point)))
6539     (cond
6540      ;; kill to the end or beginning of list
6541      ((and raw
6542            (= n 4))
6543       (let ((next (sp-get-thing (< arg 0)))
6544             (enc (sp-get-enclosing-sexp)))
6545         (if (sp-compare-sexps next enc)
6546             (when (not dont-kill)
6547               (let ((del (sp-get-whitespace)))
6548                 (sp-get del (delete-region :beg :end))))
6549           (if (> arg 0)
6550               (sp--kill-or-copy-region
6551                (sp-get next :beg-prf) (sp-get enc :end-in) dont-kill)
6552             (sp--kill-or-copy-region
6553              (sp-get next :end) (sp-get enc :beg-in) dont-kill))
6554           (when (not dont-kill)
6555             (let ((del (sp-get-whitespace)))
6556               (sp-get del (delete-region :beg :end)))))))
6557      ;; kill the enclosing list
6558      ((and raw
6559            (= n 16))
6560       (let ((lst (sp-backward-up-sexp)))
6561         (sp-get lst (sp--kill-or-copy-region
6562                      :beg-prf :end dont-kill))))
6563      ;; kill inside of sexp
6564      ((= n 0)
6565       (let ((e (sp-get-enclosing-sexp)))
6566         (when e
6567           (sp-get e (sp--kill-or-copy-region
6568                      :beg-in :end-in dont-kill)))))
6569      ;; regular kill
6570      (t
6571       (save-excursion
6572         (while (and (> n 0) ok)
6573           (setq ok (sp-forward-sexp (sp--signum arg)))
6574           (sp-get ok
6575             (when (< :beg-prf b) (setq b :beg-prf))
6576             (when (> :end e) (setq e :end)))
6577           (setq n (1- n))))
6578       (when ok
6579         (let ((bm (set-marker (make-marker) b)))
6580           (if (eq last-command 'kill-region)
6581               (progn
6582                 (when (member sp-successive-kill-preserve-whitespace '(1 2))
6583                   (kill-append sp-last-kill-whitespace nil))
6584                 (sp--kill-or-copy-region
6585                  (if (> b (point)) (point) b) e dont-kill))
6586             (sp--kill-or-copy-region b e dont-kill))
6587           ;; kill useless junk whitespace, but only if we're actually
6588           ;; killing the region
6589           (when (not dont-kill)
6590             (sp--cleanup-after-kill)
6591             ;; kill useless newlines
6592             (when (string-match-p "\n" (buffer-substring-no-properties bm (point)))
6593               (setq sp-last-kill-whitespace
6594                     (concat sp-last-kill-whitespace
6595                             (buffer-substring-no-properties bm (point))))
6596               (delete-region bm (point)))
6597             (when (= 0 sp-successive-kill-preserve-whitespace)
6598               (kill-append sp-last-kill-whitespace nil)))))))))
6599
6600 (defun sp--cleanup-after-kill ()
6601   (unless (save-match-data (looking-back "^[\t\s]+" (1- (line-beginning-position))))
6602     (let ((bdel (save-excursion
6603                   (when (sp--looking-back-p " " 1)
6604                     (skip-chars-backward " \t")
6605                     (when (not (sp--looking-back-p (sp--get-opening-regexp)))
6606                       (forward-char)))
6607                   (point)))
6608           (edel (save-excursion
6609                   (when (looking-at " ")
6610                     (skip-chars-forward " \t")
6611                     (when (not (or (sp--looking-at (sp--get-closing-regexp))
6612                                    (looking-at "$")))
6613                       (backward-char)))
6614                   (point))))
6615       (when (eq this-command 'kill-region)
6616         (setq sp-last-kill-whitespace
6617               (if (/= 2 sp-successive-kill-preserve-whitespace)
6618                   (buffer-substring-no-properties bdel edel)
6619                 "")))
6620       (delete-region bdel edel)))
6621   (if (memq major-mode sp-lisp-modes)
6622       ;; WARNING: The above white-space killing routine might preserve
6623       ;; less whitespace than there actually is because the indent
6624       ;; might further eat some up
6625       (indent-according-to-mode)
6626     (unless (or (memq major-mode sp-no-reindent-after-kill-modes)
6627                 (memq indent-line-function
6628                       sp-no-reindent-after-kill-indent-line-functions))
6629       (save-excursion
6630         (sp--indent-region (line-beginning-position) (line-end-position)))
6631       (when (> (save-excursion
6632                  (back-to-indentation)
6633                  (current-indentation))
6634                (current-column))
6635         (back-to-indentation)))))
6636
6637 (defun sp-backward-kill-sexp (&optional arg dont-kill)
6638   "Kill the balanced expression preceding point.
6639
6640 This is exactly like calling `sp-kill-sexp' with minus ARG.
6641 In other words, the direction of all commands is reversed.  For
6642 more information, see the documentation of `sp-kill-sexp'.
6643
6644 Examples:
6645
6646   (foo (abc)| bar)           -> (foo | bar)
6647
6648   blab (foo (bar baz) quux)| -> blab |
6649
6650   (1 2 3 |4 5 6)             -> (|4 5 6) ;; \\[universal-argument]"
6651   (interactive "P")
6652   (sp-kill-sexp (sp--negate-argument arg) dont-kill))
6653
6654 (defun sp-copy-sexp (&optional arg)
6655   "Copy the following ARG expressions to the kill-ring.
6656
6657 This is exactly like calling `sp-kill-sexp' with second argument
6658 t.  All the special prefix arguments work the same way."
6659   (interactive "P")
6660   (save-excursion
6661     (sp-kill-sexp arg t)))
6662
6663 (defun sp-backward-copy-sexp (&optional arg)
6664   "Copy the previous ARG expressions to the kill-ring.
6665
6666 This is exactly like calling `sp-backward-kill-sexp' with second argument
6667 t.  All the special prefix arguments work the same way."
6668   (interactive "P")
6669   (save-excursion
6670     (sp-kill-sexp (sp--negate-argument arg) t)))
6671
6672 (defun sp-clone-sexp ()
6673   "Clone sexp after or around point.
6674
6675 If the form immediately after point is a sexp, clone it below the
6676 current one and put the point in front of it.
6677
6678 Otherwise get the enclosing sexp and clone it below the current
6679 enclosing sexp."
6680   (interactive)
6681   (-when-let (ok (let ((sexp (sp-get-thing)))
6682                    (if (not (equal (sp-get sexp :op) ""))
6683                        sexp
6684                      (sp-get-enclosing-sexp))))
6685     (sp-get ok
6686       (undo-boundary)
6687       (if (< :beg-prf (point))
6688           ;; this is the case where point is inside a sexp, we place
6689           ;; the "clone" before the current enclosing sexp and move
6690           ;; the old one below.  Note that the "net result" is the
6691           ;; same as the other case, but the implementation must
6692           ;; reflect different relative position of the point wrt
6693           ;; "current" sexp.
6694           (save-excursion
6695             (goto-char :beg-prf)
6696             (insert-buffer-substring-no-properties
6697              (current-buffer) :beg-prf :end-suf)
6698             (newline-and-indent))
6699         ;; in this case we are in front, so we move after the current
6700         ;; one, place the clone and move it below
6701         (goto-char :end-suf)
6702         (save-excursion
6703           (insert-buffer-substring-no-properties
6704            (current-buffer) :beg-prf :end-suf))
6705         (newline-and-indent))
6706       (sp-indent-defun))))
6707
6708 (defun sp-kill-hybrid-sexp (arg)
6709   "Kill a line as if with `kill-line', but respecting delimiters.
6710
6711 With ARG being raw prefix \\[universal-argument] \\[universal-argument], kill the hybrid sexp
6712 the point is in (see `sp-get-hybrid-sexp').
6713
6714 With ARG numeric prefix 0 (zero) just call `kill-line'.
6715
6716 You can customize the behaviour of this command by toggling
6717 `sp-hybrid-kill-excessive-whitespace'.
6718
6719 Examples:
6720
6721   foo | bar baz               -> foo |               ;; nil
6722
6723   foo (bar | baz) quux        -> foo (bar |) quux    ;; nil
6724
6725   foo | bar (baz              -> foo |               ;; nil
6726              quux)
6727
6728   foo \"bar |baz quux\" quack   -> foo \"bar |\" quack   ;; nil
6729
6730   foo (bar
6731        baz) qu|ux (quack      ->   foo | hoo         ;; \\[universal-argument] \\[universal-argument]
6732                    zaq) hoo
6733
6734   foo | (bar                  -> foo |               ;; C-0
6735          baz)                          baz)"
6736   (interactive "P")
6737   (let* ((raw (sp--raw-argument-p arg))
6738          (arg (prefix-numeric-value arg))
6739          (orig-indent (save-excursion
6740                         (back-to-indentation)
6741                         (current-column)))
6742          (orig-column (current-column)))
6743     (cond
6744      ((= arg 0) (kill-line))
6745      ((and raw (= arg 16))
6746       (let ((hl (sp-get-hybrid-sexp)))
6747         (sp-get hl (kill-region :beg-prf :end-suf))))
6748      (t
6749       (let ((hl (sp-get-hybrid-sexp)))
6750         (save-excursion
6751           (when (and (or (eq sp-hybrid-kill-entire-symbol t)
6752                          (and (functionp sp-hybrid-kill-entire-symbol)
6753                               (not (funcall sp-hybrid-kill-entire-symbol))))
6754                      (sp-point-in-symbol))
6755             (sp-backward-sexp))
6756           (sp-get hl
6757             (let ((end (min (point-max) (if (looking-at "[ \t]*$")
6758                                             (1+ :end-suf)
6759                                           :end-suf))))
6760               (when sp-hybrid-kill-excessive-whitespace
6761                 (save-excursion
6762                   (goto-char end)
6763                   (skip-chars-forward "\n\t\r\s")
6764                   (cond
6765                    ((eq 'kill sp-hybrid-kill-excessive-whitespace)
6766                     (setq end (point)))
6767                    (t (delete-region end (point))))))
6768               (kill-region (point) end)))))
6769       (sp--cleanup-after-kill)
6770       ;; if we've killed the entire line, do *not* contract the indent
6771       ;; to just one space
6772       (when (sp-point-in-blank-line)
6773         (delete-region (line-beginning-position) (line-end-position))
6774         (if (and (= 0 orig-column)
6775                  kill-whole-line)
6776             (delete-char 1) ;; delete the newline
6777           (let ((need-indent (- orig-indent (current-column))))
6778             (when (> need-indent 0)
6779               (insert (make-string need-indent ?\ ))))))))))
6780
6781 (defun sp-kill-whole-line ()
6782   "Kill current line in sexp-aware manner.
6783
6784 First, go to the beginning of current line and then try to kill
6785 as much as possible on the current line but without breaking
6786 balance.
6787
6788 If there is a hanging sexp at the end of line the it is killed as
6789 well.
6790
6791 If there is a closing delimiter for a sexp \"up\" current sexp,
6792 the kill is not extended after it.  For more details see
6793 `sp-kill-hybrid-sexp'.
6794
6795 Examples:
6796
6797   (progn                    (progn
6798     (some |long sexp))  ->    |)"
6799   (interactive)
6800   (beginning-of-line)
6801   (sp-kill-hybrid-sexp nil)
6802   (let ((empty-last-line (save-excursion (beginning-of-line) (eobp))))
6803     ;; We can't kill the line if it is empty and the last line
6804     (when (and (sp-point-in-blank-line) (not empty-last-line))
6805       (kill-whole-line))))
6806
6807 (defun sp--transpose-objects (first second)
6808   "Transpose FIRST and SECOND object while preserving the
6809 whitespace between them."
6810   (save-excursion
6811     (goto-char (sp-get second :beg-prf))
6812     (let ((ins (sp-get second (delete-and-extract-region :beg-prf :end)))
6813           (between (delete-and-extract-region (sp-get first :end) (point))))
6814       (goto-char (sp-get first :beg-prf))
6815       (insert ins between))))
6816
6817 (defun sp-transpose-sexp (&optional arg)
6818   "Transpose the expressions around point.
6819
6820 The operation will move the point after the transposed block, so
6821 the next transpose will \"drag\" it forward.
6822
6823 With arg positive N, apply that many times, dragging the
6824 expression forward.
6825
6826 With arg negative -N, apply N times backward, pushing the word
6827 before cursor backward.  This will therefore not transpose the
6828 expressions before and after point, but push the expression
6829 before point over the one before it.
6830
6831 Examples:
6832
6833   foo |bar baz     -> bar foo| baz
6834
6835   foo |bar baz     -> bar baz foo| ;; 2
6836
6837   (foo) |(bar baz) -> (bar baz) (foo)|
6838
6839   (foo bar)        ->    (baz quux)   ;; keeps the formatting
6840 ​    |(baz quux)            |(foo bar)
6841
6842   foo bar baz|     -> foo baz| bar ;; -1"
6843   (interactive "P")
6844   (let* ((arg (prefix-numeric-value arg))
6845          (n (abs arg)))
6846     ;; if we're inside a symbol, we need to move out of it first
6847     (when (> arg 0)
6848       (when (sp-point-in-symbol)
6849         (sp-forward-symbol)))
6850     (while (> n 0)
6851       (when (< arg 0) (sp-backward-sexp))
6852       (let* ((next (save-excursion (sp-forward-sexp)))
6853              (prev (save-excursion (goto-char (sp-get next :beg-prf)) (sp-backward-sexp))))
6854         (sp--transpose-objects prev next)
6855         (when (< arg 0)
6856           (goto-char (+ (sp-get prev :beg-prf) (sp-get next :len))))
6857         (setq n (1- n))))))
6858
6859 (defun sp-transpose-hybrid-sexp (&optional arg)
6860   "Transpose the hybrid sexps around point.
6861
6862 `sp-backward-sexp' is used to enter the previous hybrid sexp.
6863
6864 With ARG numeric prefix call `transpose-lines' with this
6865 argument.
6866
6867 The operation will move the point at the next line after the
6868 transposed block if it is at the end of line already.
6869
6870 Examples:
6871
6872   foo bar            baz (quux
6873   |baz (quux   ->         quack)
6874         quack)       foo bar\\n|
6875
6876
6877   [(foo) (bar) -> [(baz)
6878   |(baz)]          (foo) (bar)|]
6879
6880   foo bar baz  -> quux flux
6881   |quux flux      foo bar baz\\n|"
6882   (interactive "P")
6883   (if (numberp arg)
6884       (transpose-lines arg)
6885     (let* ((next (save-excursion
6886                    (sp-forward-sexp)
6887                    (sp-backward-sexp)
6888                    (sp-get-hybrid-sexp)))
6889            (prev (save-excursion
6890                    (goto-char (sp-get next :beg))
6891                    (sp-backward-sexp)
6892                    (sp-get-hybrid-sexp))))
6893       (if (sp-compare-sexps prev next > :end)
6894           (sp-message :invalid-context-prev)
6895         (sp--transpose-objects prev next))
6896       (when (looking-at "[\n\t ]+")
6897         (forward-line)
6898         (back-to-indentation)))))
6899
6900 (defun sp-push-hybrid-sexp ()
6901   "Push the hybrid sexp after point over the following one.
6902
6903 `sp-forward-sexp' is used to enter the following hybrid sexp.
6904
6905 Examples:
6906
6907   |x = big_function_call(a,    |(a,
6908                          b)      b) = read_user_input()
6909                            ->
6910   (a,                          x = big_function_call(a,
6911    b) = read_user_input()                            b)"
6912   (interactive)
6913   (let* ((cur (sp-get-hybrid-sexp))
6914          (next (save-excursion
6915                  (goto-char (sp-get cur :end))
6916                  (sp-forward-sexp)
6917                  (sp-get-hybrid-sexp))))
6918     (if (sp-compare-sexps cur next >)
6919         (sp-message :invalid-context-cur)
6920       (sp--transpose-objects cur next))))
6921
6922 ;; The following two functions are inspired by "adjust-parens.el"
6923 ;; package available at
6924 ;; http://elpa.gnu.org/packages/adjust-parens-1.0.el
6925 (defun sp-indent-adjust-sexp ()
6926   "Add the hybrid sexp at line into previous sexp.  All forms
6927 between the two are also inserted.  Specifically, if the point is
6928 on empty line, move the closing delimiter there, so the next
6929 typed text will become the last item of the previous sexp.
6930
6931 This acts similarly to `sp-add-to-previous-sexp' but with special
6932 handling of empty lines."
6933   (interactive)
6934   (let* ((hsexp (sp-get-hybrid-sexp))
6935          (prev-sexp (save-excursion
6936                       (goto-char (sp-get hsexp :beg))
6937                       (sp-get-sexp t))))
6938     (if (not (and prev-sexp hsexp
6939                   (sp-compare-sexps prev-sexp hsexp < :end :beg)))
6940         (sp-message :no-structure-found)
6941       (save-excursion
6942         (sp-get prev-sexp
6943           (goto-char (sp-get hsexp :end))
6944           (insert :cl)
6945           (goto-char :end-in)
6946           (delete-char :cl-l)))
6947       (sp-get (sp-get-enclosing-sexp) (sp--indent-region :beg :end))
6948       (indent-according-to-mode)
6949       (sp--run-hook-with-args (sp-get prev-sexp :op) :post-handlers 'indent-adjust-sexp))))
6950
6951 (defun sp-dedent-adjust-sexp ()
6952   "Remove the hybrid sexp at line from previous sexp.  All
6953 sibling forms after it are also removed (not deleted, just placed
6954 outside of the enclosing list).  Specifically, if the point is on
6955 empty line followed by closing delimiter of enclosing list, move
6956 the closing delimiter after the last item in the list.
6957
6958 This acts similarly to `sp-forward-barf-sexp' but with special
6959 handling of empty lines."
6960   (interactive)
6961   (-when-let (enc (sp-get-enclosing-sexp))
6962     (save-excursion
6963       ;; if we're looking at whitespace and end of sexp, move the
6964       ;; closing paren over the whitespace but *after* the last item
6965       ;; in the list (barf would also go *before* the last item)
6966       (sp-skip-forward-to-symbol t)
6967       (if (= (point) (sp-get enc :end-in))
6968           (let ((prev-sexp (sp-get-thing t)))
6969             (sp-get enc
6970               (delete-char :cl-l)
6971               (goto-char (sp-get prev-sexp :end))
6972               ;; see next TODO
6973               (save-restriction
6974                 (sp--narrow-to-line)
6975                 (skip-syntax-forward " ")
6976                 (skip-syntax-forward "."))
6977               (insert :cl)))
6978         ;; otherwise just C-u barf
6979         (sp-skip-backward-to-symbol t)
6980         (sp-forward-barf-sexp '(4))
6981         ;; we need to take special care of any hanging
6982         ;; punctuation. TODO: this should be a sexp suffix? HACK until
6983         ;; we fix barf to get the info.
6984         (save-restriction
6985           (sp-get (sp-backward-down-sexp)
6986             (goto-char :end)
6987             (delete-char (- :cl-l))
6988             (sp--narrow-to-line)
6989             (skip-syntax-forward " ")
6990             (skip-syntax-forward ".")
6991             (insert :cl)))
6992         (sp-get enc (sp--indent-region :beg :end))))
6993     (indent-according-to-mode)
6994     (sp--run-hook-with-args (sp-get enc :op) :post-handlers 'dedent-adjust-sexp)))
6995
6996 ;;  "When the hook is called point is *after* the just moved closing delimiter."
6997 ;; TODO: add hook
6998 (defun sp-slurp-hybrid-sexp ()
6999   "Add hybrid sexp following the current list in it by moving the
7000 closing delimiter.
7001
7002 This is philosophically similar to `sp-forward-slurp-sexp' but
7003 works better in \"line-based\" languages like C or Java.
7004
7005 Because the structure is much looser in these languages, this
7006 command currently does not support all the prefix argument
7007 triggers that `sp-forward-slurp-sexp' does."
7008   (interactive)
7009   (let (slurped-within-line)
7010     (-if-let* ((enc (sp-get-enclosing-sexp))
7011                (bsexp (save-excursion
7012                         (sp-get enc (goto-char :end))
7013                         (when (sp-compare-sexps (sp-forward-sexp) enc >)
7014                           (sp-get-hybrid-sexp)))))
7015         (save-excursion
7016           (sp-get enc
7017             (goto-char :end-suf)
7018             (delete-char (- (+ :cl-l :suffix-l)))
7019             ;; TODO: move to hook
7020             (when (sp-point-in-blank-line)
7021               (delete-region (line-beginning-position) (1+ (line-end-position))))
7022             (sp-forward-sexp)
7023
7024             (when (eq (line-number-at-pos :beg)
7025                       (line-number-at-pos :end))
7026               (setq slurped-within-line t))
7027             ;; If we're slurping over multiple lines, include the suffix on the next line.
7028             ;; I.e. while () {|} -> while () {\n foo(); \n}
7029             (unless slurped-within-line
7030               (sp-get (sp-get-hybrid-sexp) (goto-char :end-suf)))
7031             (insert :cl :suffix))
7032           ;; TODO: move to hook
7033           (sp-get (sp--next-thing-selection -1)
7034             (save-excursion
7035               (if (save-excursion
7036                     (goto-char :beg-in)
7037                     (looking-at "[ \t]*$"))
7038                   (progn
7039                     (goto-char :end-in)
7040                     (newline))
7041                 ;; copy the whitespace after opening delim and put it in
7042                 ;; front of the closing. This will ensure pretty { foo }
7043                 ;; or {foo}
7044                 (goto-char :end-in)
7045                 (insert (buffer-substring-no-properties
7046                          :beg-in
7047                          (+ :beg-in (save-excursion
7048                                       (goto-char :beg-in)
7049                                       (skip-syntax-forward " ")))))))
7050             (unless (or (looking-at "[ \t]*$")
7051                         (looking-at (sp--get-stringlike-regexp))
7052                         (looking-at (sp--get-closing-regexp))
7053                         slurped-within-line)
7054               (newline)))
7055           (sp-get (sp--next-thing-selection -1) (sp--indent-region :beg :end))
7056           ;; we need to call this again to get the new structure after
7057           ;; indent.
7058           (sp--next-thing-selection -1))
7059       (sp-message :invalid-structure)
7060       nil)))
7061
7062
7063 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7064 ;; "paredit" operations
7065
7066 (defun sp-forward-slurp-sexp (&optional arg)
7067   "Add sexp following the current list in it by moving the closing delimiter.
7068
7069 If the current list is the last in a parent list, extend that
7070 list (and possibly apply recursively until we can extend a list
7071 or end of file).
7072
7073 If ARG is N, apply this function that many times.
7074
7075 If ARG is negative -N, extend the opening pair instead (that is,
7076 backward).
7077
7078 If ARG is raw prefix \\[universal-argument], extend all the way to the end of the parent list.
7079
7080 If both the current expression and the expression to be slurped
7081 are strings, they are joined together.
7082
7083 See also `sp-slurp-hybrid-sexp' which is similar but handles
7084 C-style syntax better.
7085
7086 Examples:
7087
7088   (foo |bar) baz        -> (foo |bar baz)
7089
7090   [(foo |bar)] baz      -> [(foo |bar) baz]
7091
7092   [(foo |bar) baz]      -> [(foo |bar baz)]
7093
7094   ((|foo) bar baz quux) -> ((|foo bar baz quux)) ;; with \\[universal-argument]
7095
7096   \"foo| bar\" \"baz quux\" -> \"foo| bar baz quux\""
7097   (interactive "P")
7098   (if (> (prefix-numeric-value arg) 0)
7099       (let ((n (abs (prefix-numeric-value arg)))
7100             (enc (sp-get-enclosing-sexp))
7101             (in-comment (sp-point-in-comment))
7102             next-thing ok)
7103         (when enc
7104           (save-excursion
7105             (if (sp--raw-argument-p arg)
7106                 (progn
7107                   (goto-char (sp-get enc :end-suf))
7108                   (setq next-thing (sp-get-enclosing-sexp))
7109                   (when next-thing
7110                     (goto-char (sp-get next-thing :end-in))
7111                     (sp--run-hook-with-args (sp-get enc :op) :pre-handlers 'slurp-forward
7112                                             (list :arg arg :enc enc :next-thing next-thing))
7113                     (sp-get enc (insert :cl :suffix))
7114                     (goto-char (sp-get enc :end-suf))
7115                     (delete-char (sp-get enc (- (+ :cl-l :suffix-l))))
7116                     (sp--indent-region (sp-get enc :beg-prf) (sp-get next-thing :end))
7117                     (sp--run-hook-with-args (sp-get enc :op) :post-handlers 'slurp-forward
7118                                             (list :arg arg :enc enc :next-thing next-thing))))
7119               (while (> n 0)
7120                 (goto-char (sp-get enc :end-suf))
7121                 (setq ok enc)
7122                 (setq next-thing (sp-get-thing nil))
7123                 (while (sp-compare-sexps next-thing ok <)
7124                   (goto-char (sp-get next-thing :end-suf))
7125                   (setq ok next-thing)
7126                   (setq next-thing (sp-get-thing nil)))
7127                 ;; do not allow slurping into a different context from
7128                 ;; inside a comment
7129                 (if (and in-comment
7130                          (save-excursion
7131                            (sp-get next-thing
7132                              (goto-char :beg)
7133                              (not (sp-point-in-comment)))))
7134                     (progn
7135                       (sp-message :cant-slurp-context)
7136                       (setq n -1))
7137                   (if ok
7138                       (progn
7139                         (if (and (equal (sp-get next-thing :cl) "\"")
7140                                  (equal (sp-get ok :cl) "\""))
7141                             (progn
7142                               (sp--join-sexp ok next-thing)
7143                               (goto-char (- (sp-get next-thing :end) 2))
7144                               (plist-put enc :end (- (sp-get next-thing :end) 2)))
7145                           (let ((inner-sexp
7146                                  (save-excursion
7147                                    (goto-char (sp-get ok :end-in))
7148                                    (sp-get-thing t))))
7149                             (delete-char (sp-get ok (- (+ :cl-l :suffix-l))))
7150                             ;; this calculation corrects the absence
7151                             ;; of already deleted cls
7152                             (goto-char (- (sp-get next-thing :end-suf)
7153                                           (sp-get ok (+ :cl-l :suffix-l))))
7154                             ;; only insert space if not inserting it
7155                             ;; would merge two sexps together
7156                             (when (and (sp-get ok (/= :len-in 0))
7157                                        (sp-compare-sexps
7158                                         inner-sexp
7159                                         (sp-get-thing t))
7160                                        (= (sp-get ok :end-suf)
7161                                           (sp-get next-thing :beg-prf)))
7162                               (save-excursion
7163                                 (goto-char (sp-get ok :end-in))
7164                                 (insert " "))))
7165                           (sp--run-hook-with-args
7166                            (sp-get enc :op) :pre-handlers 'slurp-forward
7167                            (list :arg arg :enc enc :ok ok :next-thing next-thing))
7168                           (sp-get ok (insert :cl :suffix))
7169                           (sp--indent-region (sp-get ok :beg-prf) (point))
7170                           ;; HACK: update the "enc" data structure if ok==enc
7171                           (when (= (sp-get enc :beg) (sp-get ok :beg)) (plist-put enc :end (point)))
7172                           (sp--run-hook-with-args
7173                            (sp-get enc :op) :post-handlers 'slurp-forward
7174                            (list :arg arg :enc enc :ok ok :next-thing next-thing)))
7175                         (setq n (1- n)))
7176                     (sp-message :cant-slurp)
7177                     (setq n -1))))))))
7178     (sp-backward-slurp-sexp (sp--negate-argument arg))))
7179
7180 (defun sp-backward-slurp-sexp (&optional arg)
7181   "Add the sexp preceding the current list in it by moving the opening delimiter.
7182
7183 If the current list is the first in a parent list, extend that
7184 list (and possibly apply recursively until we can extend a list
7185 or beginning of file).
7186
7187 If arg is N, apply this function that many times.
7188
7189 If arg is negative -N, extend the closing pair instead (that is,
7190 forward).
7191
7192 If ARG is raw prefix \\[universal-argument], extend all the way to the beginning of the parent list.
7193
7194 If both the current expression and the expression to be slurped
7195 are strings, they are joined together.
7196
7197 Examples:
7198
7199   foo (bar| baz)        -> (foo bar| baz)
7200
7201   foo [(bar| baz)]      -> [foo (bar| baz)]
7202
7203   [foo (bar| baz)]      -> [(foo bar| baz)]
7204
7205   (foo bar baz (|quux)) -> ((foo bar baz |quux)) ;; with \\[universal-argument]
7206
7207   \"foo bar\" \"baz |quux\" -> \"foo bar baz |quux\""
7208   (interactive "P")
7209   (if (> (prefix-numeric-value arg) 0)
7210       (let ((n (abs (prefix-numeric-value arg)))
7211             (enc (sp-get-enclosing-sexp))
7212             (in-comment (sp-point-in-comment))
7213             next-thing ok)
7214         (when enc
7215           (save-excursion
7216             (if (sp--raw-argument-p arg)
7217                 (progn
7218                   (goto-char (sp-get enc :beg-prf))
7219                   (setq next-thing (sp-get-enclosing-sexp))
7220                   (when next-thing
7221                     (delete-char (sp-get enc (+ :op-l :prefix-l)))
7222                     (goto-char (sp-get next-thing :beg-in))
7223                     (sp--run-hook-with-args
7224                      (sp-get enc :op) :pre-handlers 'slurp-backward
7225                      (list :arg arg :enc enc :next-thing next-thing))
7226                     (sp-get enc (insert :prefix :op))
7227                     (sp--indent-region (sp-get next-thing :beg-in) (sp-get enc :end))
7228                     (sp--run-hook-with-args
7229                      (sp-get enc :op) :post-handlers 'slurp-backward
7230                      (list :arg arg :enc enc :next-thing next-thing))))
7231               (while (> n 0)
7232                 (goto-char (sp-get enc :beg-prf))
7233                 (setq ok enc)
7234                 (setq next-thing (sp-get-thing t))
7235                 (while (sp-compare-sexps next-thing ok > :end)
7236                   (goto-char (sp-get next-thing :beg-prf))
7237                   (setq ok next-thing)
7238                   (setq next-thing (sp-get-thing t)))
7239                 ;; do not allow slurping into a different context from
7240                 ;; inside a comment
7241                 (if (and in-comment
7242                          (save-excursion
7243                            (sp-get next-thing
7244                              (goto-char :beg)
7245                              (not (sp-point-in-comment)))))
7246                     (progn
7247                       (sp-message :cant-slurp-context)
7248                       (setq n -1))
7249                   (if ok
7250                       (progn
7251                         (if (and (equal (sp-get next-thing :cl) "\"")
7252                                  (equal (sp-get ok :cl) "\""))
7253                             (progn
7254                               (sp--join-sexp next-thing ok)
7255                               (goto-char (sp-get next-thing :beg-prf))
7256                               (plist-put enc :beg (sp-get next-thing :beg)))
7257                           (let ((inner-sexp
7258                                  (save-excursion
7259                                    (goto-char (sp-get ok :beg-in))
7260                                    (sp-get-thing))))
7261                             (delete-char (sp-get ok (+ :op-l :prefix-l)))
7262                             (goto-char (sp-get next-thing :beg-prf))
7263                             ;; only insert space if not inserting it
7264                             ;; would merge two sexps together
7265                             (when (and (sp-get ok (/= :len-in 0))
7266                                        (= (sp-get ok (- (sp-get inner-sexp :end)
7267                                                         :op-l :prefix-l))
7268                                           (sp-get (sp-get-thing) :end))
7269                                        (= (sp-get ok :beg-prf)
7270                                           (sp-get next-thing :end-suf)))
7271                               (save-excursion
7272                                 (goto-char (sp-get ok (- :beg-in :op-l :prefix-l)))
7273                                 (insert " "))))
7274                           (sp--run-hook-with-args
7275                            (sp-get enc :op) :pre-handlers 'slurp-backward
7276                            (list :arg arg :enc enc :ok ok :next-thing next-thing))
7277                           (sp-get ok (insert :prefix :op))
7278                           (sp--indent-region (point) (sp-get ok :end))
7279                           ;; HACK: update the "enc" data structure if ok==enc
7280                           (when (sp-compare-sexps enc ok) (plist-put enc :beg (- (point) (sp-get ok :op-l))))
7281                           (sp--run-hook-with-args
7282                            (sp-get enc :op) :post-handlers 'slurp-backward
7283                            (list :arg arg :enc enc :ok ok :next-thing next-thing)))
7284                         (setq n (1- n)))
7285                     (sp-message :cant-slurp)
7286                     (setq n -1))))))))
7287     (sp-forward-slurp-sexp (sp--negate-argument arg))))
7288
7289 (defun sp-add-to-previous-sexp (&optional arg)
7290   "Add the expression around point to the first list preceding point.
7291
7292 With ARG positive N add that many expressions to the preceding
7293 list.
7294
7295 If ARG is raw prefix argument \\[universal-argument] add all expressions until
7296 the end of enclosing list to the previous list.
7297
7298 If ARG is raw prefix argument \\[universal-argument] \\[universal-argument] add the current
7299 list into the previous list.
7300
7301 Examples:
7302
7303   (foo bar) |baz quux        -> (foo bar |baz) quux
7304
7305   (foo bar) |baz quux        -> (foo bar |baz quux) ;; 2
7306
7307   (blab (foo bar) |baz quux) -> (blab (foo bar |baz quux)) ;; \\[universal-argument]
7308
7309   (foo bar) (baz |quux)      -> (foo bar (baz |quux)) ;; \\[universal-argument] \\[universal-argument]"
7310   (interactive "P")
7311   (save-excursion
7312     (cond
7313      ((equal arg '(16))
7314       (sp-backward-up-sexp)
7315       (sp-backward-down-sexp)
7316       (sp-forward-slurp-sexp))
7317      (t
7318       (sp-backward-down-sexp)
7319       (sp-forward-slurp-sexp arg))))
7320   (indent-according-to-mode))
7321
7322 (defun sp-add-to-next-sexp (&optional arg)
7323   "Add the expressions around point to the first list following point.
7324
7325 With ARG positive N add that many expressions to the following
7326 list.
7327
7328 If ARG is raw prefix argument \\[universal-argument] add all expressions until
7329 the beginning of enclosing list to the following list.
7330
7331 If ARG is raw prefix argument \\[universal-argument] \\[universal-argument] add the current
7332 list into the following list.
7333
7334 Examples:
7335
7336   foo bar| (baz quux)        -> foo (bar| baz quux)
7337
7338   foo bar| (baz quux)        -> (foo bar| baz quux) ;; 2
7339
7340   (foo bar |(bar quux) blab) -> ((foo bar |bar quux) blab) ;; \\[universal-argument]
7341
7342   (foo |bar) (baz quux)      -> ((foo |bar) baz quux) ;; \\[universal-argument] \\[universal-argument]"
7343   (interactive "P")
7344   (save-excursion
7345     (cond
7346      ((equal arg '(16))
7347       (sp-up-sexp)
7348       (sp-down-sexp)
7349       (sp-backward-slurp-sexp))
7350      (t
7351       (sp-down-sexp)
7352       (sp-backward-slurp-sexp arg)))))
7353
7354 (defun sp-forward-barf-sexp (&optional arg)
7355   "Remove the last sexp in the current list by moving the closing delimiter.
7356
7357 If ARG is positive number N, barf that many expressions.
7358
7359 If ARG is negative number -N, contract the opening pair instead.
7360
7361 If ARG is raw prefix \\[universal-argument], barf all expressions from the one after
7362 point to the end of current list and place the point before the
7363 closing delimiter of the list.
7364
7365 If the current list is empty, do nothing.
7366
7367 Examples: (prefix arg in comment)
7368
7369   (foo bar| baz)   -> (foo bar|) baz   ;; nil (defaults to 1)
7370
7371   (foo| [bar baz]) -> (foo|) [bar baz] ;; 1
7372
7373   (1 2 3| 4 5 6)   -> (1 2 3|) 4 5 6   ;; \\[universal-argument] (or numeric prefix 3)
7374
7375   (foo bar| baz)   -> foo (bar| baz)   ;; -1"
7376   (interactive "P")
7377   (let* ((raw (sp--raw-argument-p arg))
7378          (old-arg arg)
7379          (arg (prefix-numeric-value arg)))
7380     (if (> arg 0)
7381         (if (sp-point-in-blank-sexp)
7382             (sp-message :blank-sexp)
7383           (save-excursion
7384             (let ((enc (sp-get-enclosing-sexp)))
7385               (sp-get enc
7386                 (cond
7387                  ((and raw (= arg 4))
7388                   (sp-get (sp-get-thing t)
7389                     (goto-char :end-suf)))
7390                  (t
7391                   (goto-char :end-in)
7392                   (sp-backward-sexp arg)
7393                   (when (<= (point) :beg)
7394                     (goto-char :beg-in))))
7395                 ;; we know for sure there is at least one thing in the list
7396                 (let ((back (sp-get-thing t)))
7397                   (if (sp-compare-sexps back enc)
7398                       (goto-char :beg-in)
7399                     (goto-char (sp-get back :end-suf))))
7400                 (sp--run-hook-with-args :op :pre-handlers 'barf-forward
7401                   (list :arg arg :enc enc)))
7402               (sp-get (sp-get-enclosing-sexp)
7403                 (sp-do-move-cl (point))
7404                 (sp--indent-region :beg :end)
7405                 (sp--run-hook-with-args :op :post-handlers 'barf-forward
7406                   (list :arg arg :enc enc))))))
7407       (sp-backward-barf-sexp (sp--negate-argument old-arg)))))
7408
7409 (defun sp-backward-barf-sexp (&optional arg)
7410   "This is exactly like calling `sp-forward-barf-sexp' with minus ARG.
7411 In other words, instead of contracting the closing pair, the
7412 opening pair is contracted.  For more information, see the
7413 documentation of `sp-forward-barf-sexp'.
7414
7415 Examples:
7416
7417   (foo bar| baz) -> foo (bar| baz)
7418
7419   ([foo bar] |baz) -> [foo bar] (|baz)
7420
7421   (1 2 3 |4 5 6) -> 1 2 3 (|4 5 6) ;; \\[universal-argument] (or 3)"
7422   (interactive "P")
7423   (let* ((raw (sp--raw-argument-p arg))
7424          (old-arg arg)
7425          (arg (prefix-numeric-value arg)))
7426     (if (> arg 0)
7427         (if (sp-point-in-blank-sexp)
7428             (sp-message :blank-sexp)
7429           (save-excursion
7430             (let ((enc (sp-get-enclosing-sexp)))
7431               (sp-get enc
7432                 (cond
7433                  ((and raw (= arg 4))
7434                   (sp-get (sp-get-thing)
7435                     (goto-char :beg-prf)))
7436                  (t
7437                   (goto-char :beg-in)
7438                   (sp-forward-sexp arg)
7439                   (when (>= (point) :end)
7440                     (goto-char :end-in))))
7441                 ;; we know for sure there is at least one thing in the list
7442                 (let ((next (sp-get-thing)))
7443                   (if (sp-compare-sexps next enc)
7444                       (goto-char :end-in)
7445                     (goto-char (sp-get next :beg-prf))))
7446                 (sp--run-hook-with-args :op :pre-handlers 'barf-backward
7447                   (list :arg arg :enc enc)))
7448               (sp-get (sp-get-enclosing-sexp)
7449                 (sp-do-move-op (point))
7450                 (sp--indent-region :beg :end)
7451                 (sp--run-hook-with-args :op :post-handlers 'barf-backward
7452                   (list :arg arg :enc enc))))))
7453       (sp-forward-barf-sexp (sp--negate-argument old-arg)))))
7454
7455 ;; TODO: get rid of the macro anyway, it's stupid!
7456 (defmacro sp--skip-to-symbol-1 (forward)
7457   "Generate `sp-skip-forward-to-symbol' or `sp-skip-backward-to-symbol'."
7458   (let ((inc (if forward '1+ '1-))
7459         (dec (if forward '1- '1+))
7460         (forward-fn (if forward 'forward-char 'backward-char))
7461         (next-char-fn (if forward 'following-char 'preceding-char))
7462         (looking (if forward 'sp--looking-at 'sp--looking-back))
7463         (prefix-fn (if forward 'sp--get-suffix 'sp--get-prefix))
7464         (eob-test (if forward '(eobp) '(bobp)))
7465         (comment-bound (if forward 'cdr 'car)))
7466     `(let ((in-comment (sp-point-in-comment))
7467            ;; HACK: if we run out of current context this might skip a
7468            ;; pair that was not allowed before.  However, such a call is
7469            ;; never made in SP, so it's OK for now
7470            (allowed-pairs (sp--get-allowed-regexp))
7471            (allowed-open (sp--get-opening-regexp (sp--get-allowed-pair-list)))
7472            (allowed-close (sp--get-closing-regexp (sp--get-allowed-pair-list)))
7473            (allowed-strings (sp--get-stringlike-regexp))
7474            (prefix nil))
7475        (while (and (not (or ,eob-test
7476                             (and stop-after-string
7477                                  (not (sp-point-in-string))
7478                                  (sp-point-in-string (,dec (point))))
7479                             (and stop-at-string
7480                                  (not (sp-point-in-string))
7481                                  (sp-point-in-string (,inc (point))))
7482                             (and stop-inside-string
7483                                  (sp-point-in-string)
7484                                  (not (sp-point-in-string (,inc (point)))))
7485                             (and (,looking allowed-pairs)
7486                                  (or in-comment (not (sp-point-in-comment))))
7487                             (and (,looking allowed-strings)
7488                                  (or in-comment (not (sp-point-in-comment))))))
7489                    (or (member (char-syntax (,next-char-fn)) '(?< ?> ?! ?| ?\ ?\\ ?\" ?' ?.))
7490                        (/= 0 (logand (lsh 1 20) (car (syntax-after
7491                                                       ,(if forward
7492                                                            '(point)
7493                                                          '(1- (point)))))))
7494                        (unless in-comment (sp-point-in-comment))
7495                        ;; This is the case where we are starting at
7496                        ;; pair (looking at it) and there is some
7497                        ;; prefix which is not recognized by syntax,
7498                        ;; i.e. defined by regexp.  This should only be
7499                        ;; tested once in principle before the next
7500                        ;; time we land on a delimiter this whole loop
7501                        ;; stops based on the first branch of the `and'
7502                        ;; condition in `while' so using expensive
7503                        ;; functions here is not a bg deal.
7504                        (and (or (,(if forward 'sp--looking-back 'sp--looking-at)
7505                                  ,(if forward 'allowed-close 'allowed-open))
7506                                 (,(if forward 'sp--looking-back 'sp--looking-at) allowed-strings))
7507                             (progn
7508                               (setq prefix (,prefix-fn))
7509                               (> (length prefix) 0)))))
7510          (if (and (not in-comment)
7511                   (sp-point-in-comment))
7512              (progn
7513                (goto-char (,comment-bound (sp-get-comment-bounds)))
7514                (unless ,eob-test (,forward-fn 1)))
7515            (unless ,eob-test
7516              (,forward-fn (max (length prefix) 1))))))))
7517
7518 (defun sp-skip-forward-to-symbol (&optional stop-at-string stop-after-string stop-inside-string)
7519   "Skip whitespace and comments moving forward.
7520
7521 If STOP-AT-STRING is non-nil, stop before entering a string (if
7522 not already in a string).
7523
7524 If STOP-AFTER-STRING is non-nil, stop after exiting a string.
7525
7526 If STOP-INSIDE-STRING is non-nil, stop before exiting a string.
7527
7528 Examples:
7529
7530   foo|   bar -> foo   |bar
7531
7532   foo|   [bar baz] -> foo   |[bar baz]"
7533   (interactive "^")
7534   (sp--skip-to-symbol-1 t))
7535
7536 (put 'sp-skip-forward-to-symbol 'CUA 'move)
7537
7538 (defun sp-skip-backward-to-symbol (&optional stop-at-string stop-after-string stop-inside-string)
7539   "Skip whitespace and comments moving backward.
7540 If STOP-AT-STRING is non-nil, stop before entering a string (if
7541 not already in a string).
7542
7543 If STOP-AFTER-STRING is non-nil, stop after exiting a string.
7544
7545 If STOP-INSIDE-STRING is non-nil, stop before exiting a string.
7546
7547 Examples:
7548
7549   foo   |bar -> foo|   bar
7550
7551   [bar baz]   |foo -> [bar baz]|   foo"
7552   (interactive "^")
7553   (sp--skip-to-symbol-1 nil))
7554
7555 (put 'sp-skip-backward-to-symbol 'CUA 'move)
7556
7557 (defun sp-skip-into-string (&optional back)
7558   "Move the point into the next string.
7559
7560 With BACK non-nil, move backwards."
7561   (if back
7562       (while (not (sp-point-in-string))
7563         (backward-char))
7564     (while (not (sp-point-in-string))
7565       (forward-char))))
7566
7567 ;; TODO: in ruby, "foo |if bar" now moves correctly, but there's a
7568 ;; noticable lag before it jumps over "if".  This is probably caused
7569 ;; by :skip-match handlers.  Investigate!
7570 (defun sp-forward-symbol (&optional arg)
7571   "Move point to the next position that is the end of a symbol.
7572
7573 With ARG being positive number N, repeat that many times.
7574
7575 With ARG being Negative number -N, repeat that many times in
7576 backward direction.
7577
7578 A symbol is any sequence of characters that are in either the
7579 word constituent or symbol constituent syntax class.  Current
7580 symbol only extend to the possible opening or closing delimiter
7581 as defined by `sp-add-pair' even if part of this delimiter
7582 would match \"symbol\" syntax classes.
7583
7584 Examples:
7585
7586   |foo bar baz          -> foo| bar baz
7587
7588   |foo (bar (baz))      -> foo (bar| (baz)) ;; 2
7589
7590   |foo (bar (baz) quux) -> foo (bar (baz) quux|) ;; 4"
7591   (interactive "^p")
7592   (setq arg (or arg 1))
7593   (sp--with-case-sensitive
7594     (let* ((n (abs arg))
7595            (fw (> arg 0))
7596            (allowed (sp--get-allowed-pair-list))
7597            (open (sp--get-opening-regexp allowed))
7598            (close (sp--get-closing-regexp allowed)))
7599       (if fw
7600           (while (> n 0)
7601             ;; First we need to get to the beginning of a symbol.  This means
7602             ;; skipping all whitespace and pair delimiters until we hit
7603             ;; something in \sw or \s_
7604             (while (cond
7605                     ((eobp) nil)
7606                     ((not (memq (char-syntax (following-char)) '(?w ?_)))
7607                      (forward-char)
7608                      t)
7609                     ;; if allowed is empty, the regexp matches anything
7610                     ;; and we go into infinite loop, cf. Issue #400
7611                     ((and allowed (sp--valid-initial-delimiter-p (sp--looking-at open)))
7612                      (goto-char (match-end 0)))
7613                     ((and allowed (sp--valid-initial-delimiter-p (sp--looking-at close)))
7614                      (goto-char (match-end 0)))))
7615             (while (and (not (eobp))
7616                         (or (not allowed)
7617                             (not (or (sp--valid-initial-delimiter-p (sp--looking-at open))
7618                                      (sp--valid-initial-delimiter-p (sp--looking-at close)))))
7619                         (memq (char-syntax (following-char)) '(?w ?_)))
7620               (forward-char))
7621             (setq n (1- n)))
7622         (sp-backward-symbol n)))))
7623
7624 (put 'sp-forward-symbol 'CUA 'move)
7625
7626 (defun sp-backward-symbol (&optional arg)
7627   "Move point to the next position that is the beginning of a symbol.
7628
7629 With ARG being positive number N, repeat that many times.
7630
7631 With ARG being Negative number -N, repeat that many times in
7632 forward direction.
7633
7634 A symbol is any sequence of characters that are in either the word
7635 constituent or symbol constituent syntax class.  Current symbol only
7636 extend to the possible opening or closing delimiter as defined by
7637 `sp-add-pair' even if part of this delimiter would match \"symbol\"
7638 syntax classes.
7639
7640 Examples:
7641
7642   foo bar| baz            -> foo |bar baz
7643
7644   ((foo bar) baz)|        -> ((foo |bar) baz) ;; 2
7645
7646   (quux ((foo) bar) baz)| -> (|quux ((foo) bar) baz) ;; 4"
7647   (interactive "^p")
7648   (setq arg (or arg 1))
7649   (sp--with-case-sensitive
7650     (let ((n (abs arg))
7651           (fw (> arg 0))
7652           (open (sp--get-opening-regexp (sp--get-allowed-pair-list)))
7653           (close (sp--get-closing-regexp (sp--get-allowed-pair-list))))
7654       (if fw
7655           (while (> n 0)
7656             (while (cond
7657                     ((bobp) nil)
7658                     ((not (memq (char-syntax (preceding-char)) '(?w ?_)))
7659                      (backward-char)
7660                      t)
7661                     ((sp--valid-initial-delimiter-p (sp--looking-back open))
7662                      (goto-char (match-beginning 0)))
7663                     ((sp--valid-initial-delimiter-p (sp--looking-back close))
7664                      (goto-char (match-beginning 0)))))
7665             (while (and (not (bobp))
7666                         (not (or (sp--valid-initial-delimiter-p (sp--looking-back open))
7667                                  (sp--valid-initial-delimiter-p (sp--looking-back close))))
7668                         (memq (char-syntax (preceding-char)) '(?w ?_)))
7669               (backward-char))
7670             ;; skip characters which are symbols with prefix flag
7671             (while (and (not (eobp))
7672                         (/= 0 (logand (lsh 1 20) (car (syntax-after (point))))))
7673               (forward-char 1))
7674             (setq n (1- n)))
7675         (sp-forward-symbol n)))))
7676
7677 (put 'sp-backward-symbol 'CUA 'move)
7678
7679 (defun sp-rewrap-sexp (pair &optional keep-old)
7680   "Rewrap the enclosing expression with a different pair.
7681
7682 PAIR is the new enclosing pair.
7683
7684 If optional argument KEEP-OLD is set, keep old delimiter and wrap
7685 with PAIR on the outside of the current expression.
7686
7687 When used interactively, the new pair is specified in minibuffer
7688 by typing the *opening* delimiter, same way as with pair
7689 wrapping.
7690
7691 When used interactively with raw prefix argument \\[universal-argument], KEEP-OLD
7692 is set to non-nil.
7693
7694 Examples:
7695
7696   (foo |bar baz) -> [foo |bar baz]   ;; [
7697
7698   (foo |bar baz) -> [(foo |bar baz)] ;; \\[universal-argument] ["
7699   (interactive (list
7700                 (catch 'done
7701                   (let ((available-pairs (sp--get-pair-list-context 'wrap))
7702                         ev ac (pair-prefix ""))
7703                     (while (not ac)
7704                       (setq ev (read-event (format "Rewrap with: %s" pair-prefix) t))
7705                       (if (and (equal pair-prefix "")
7706                                (eq ev 'return))
7707                           (throw 'done nil))
7708                       (setq pair-prefix (concat pair-prefix (format-kbd-macro (vector ev))))
7709                       (unless (--any? (string-prefix-p pair-prefix (car it)) available-pairs)
7710                         (user-error "Impossible pair prefix selected: %s" pair-prefix))
7711                       (setq ac (--first (equal pair-prefix (car it)) available-pairs)))
7712                     ac))
7713                 current-prefix-arg))
7714   (if (not pair)
7715       (sp-unwrap-sexp)
7716     (-when-let (enc (sp-get-enclosing-sexp))
7717       (save-excursion
7718         (sp-get enc
7719           (goto-char :end)
7720           (unless keep-old
7721             (delete-char (- :cl-l)))
7722           (insert (cdr pair))
7723           (goto-char :beg)
7724           (insert (car pair))
7725           (unless keep-old
7726             (delete-char :op-l))
7727           (setq sp-last-wrapped-region
7728                 (sp--get-last-wraped-region
7729                  :beg (+ :end
7730                         (length (car pair))
7731                         (length (cdr pair))
7732                         (- :op-l)
7733                         (- :cl-l))
7734                   (car pair) (cdr pair)))))
7735       (sp--run-hook-with-args (car pair) :post-handlers 'rewrap-sexp
7736                               (list :parent (sp-get enc :op))))))
7737
7738 (defun sp-swap-enclosing-sexp (&optional arg)
7739   "Swap the enclosing delimiters of this and the parent expression.
7740
7741 With N > 0 numeric argument, ascend that many levels before
7742 swapping.
7743
7744 Examples:
7745
7746   (foo [|bar] baz)              -> [foo (|bar) baz] ;; 1
7747
7748   (foo {bar [|baz] quux} quack) -> [foo {bar (|baz) quux} quack] ;; 2"
7749   (interactive "p")
7750   (let ((enc (sp-get-enclosing-sexp))
7751         (encp (sp-get-enclosing-sexp (1+ arg))))
7752     (if (and enc encp)
7753         (save-excursion
7754           (sp-get encp
7755             (goto-char :end)
7756             (delete-char (- :cl-l)))
7757           (sp-get enc
7758             (insert :cl)
7759             (goto-char :end)
7760             (delete-char (- :cl-l)))
7761           (sp-get encp (insert :cl))
7762           (sp-get enc (goto-char :beg-prf))
7763           (sp-get encp (insert :prefix :op))
7764           (sp-get enc (delete-char (+ :op-l :prefix-l)))
7765           (sp-get encp (goto-char :beg-prf))
7766           (sp-get enc (insert :prefix :op))
7767           (sp-get encp (delete-char (+ :op-l :prefix-l))))
7768       (sp-message :point-not-deep-enough))))
7769
7770 (defun sp--unwrap-sexp (sexp &optional no-cleanup)
7771   "Unwrap expression defined by SEXP.
7772
7773 Warning: this function remove possible empty lines and reindents
7774 the unwrapped sexp, so the SEXP structure will no longer
7775 represent a valid object in a buffer!"
7776   (sp-get sexp
7777     (delete-region :end-in :end)
7778     (delete-region :beg-prf :beg-in))
7779   ;; if the delimiters were the only thing on the line, we should also
7780   ;; get rid of the (possible) empty line that will be the result of
7781   ;; their removal.  This is especially nice in HTML mode or
7782   ;; long-running tags like \[\] in latex.
7783   (unless no-cleanup
7784     (let ((new-start (sp-get sexp :beg-prf))
7785           (new-end (sp-get sexp (- :end-in :op-l :prefix-l)))
7786           indent-from indent-to)
7787       (save-excursion
7788         (goto-char new-end)
7789         (when (string-match-p "^[\n\t ]+\\'" (thing-at-point 'line))
7790           (let ((b (bounds-of-thing-at-point 'line)))
7791             (delete-region (car b) (cdr b))))
7792         (setq indent-to (point))
7793         (goto-char new-start)
7794         (when (string-match-p "^[\n\t ]+\\'" (thing-at-point 'line))
7795           (let ((b (bounds-of-thing-at-point 'line)))
7796             (delete-region (car b) (cdr b))))
7797         (setq indent-from (point)))
7798       (unless (or (memq major-mode sp-no-reindent-after-kill-modes)
7799                   (memq indent-line-function
7800                         sp-no-reindent-after-kill-indent-line-functions))
7801         (sp--keep-indentation
7802           (sp--indent-region indent-from indent-to))))))
7803
7804 (defun sp-change-inner ()
7805   "Change the inside of the next expression.
7806
7807 First, kill the inside of the next balanced expression, then move
7808 point just after the opening delimiter.
7809
7810 Examples:
7811
7812   (f|oo [bar] baz) -> (foo [|] baz)
7813
7814   {|'foo': 'bar'}  -> {'|': 'bar'}"
7815   (interactive)
7816   (-when-let (ok (sp-get-sexp))
7817     (sp-get ok
7818       (kill-region :beg-in :end-in)
7819       (goto-char :beg-in))))
7820
7821 (defun sp-change-enclosing ()
7822   "Change the inside of the enclosing expression.
7823
7824 Whitespace on both sides of the inner items is preserved if it
7825 contains newlines.  Invoking this function on a blank sexp will
7826 wipe out remaining whitespace (see `sp-point-in-blank-sexp').
7827
7828 Move the point to the beginning of the original content.
7829
7830 Examples:
7831
7832   (f|oo [bar] baz) -> (|)
7833
7834   {'f|oo': 'bar'}  -> {'|': 'bar'}"
7835   (interactive)
7836   (-when-let (ok (sp-get-enclosing-sexp))
7837     (sp-get ok
7838       (if (sp-point-in-blank-sexp)
7839           (progn
7840             (kill-region :beg-in :end-in)
7841             (goto-char :beg-in))
7842         (let ((beg (progn
7843                      (goto-char :beg-in)
7844                      (skip-chars-forward "\t\n ")
7845                      (point)))
7846               (end (progn
7847                      (goto-char :end-in)
7848                      (skip-chars-backward "\t\n ")
7849                      (point))))
7850           (kill-region beg end)
7851           (goto-char beg))))))
7852
7853 (defun sp-unwrap-sexp (&optional arg)
7854   "Unwrap the following expression.
7855
7856 With ARG N, unwrap Nth expression as returned by
7857 `sp-forward-sexp'.  If ARG is negative -N, unwrap Nth expression
7858 backwards as returned by `sp-backward-sexp'.
7859
7860 Return the information about the just unwrapped expression.  Note
7861 that this structure does not represent a valid expression in the
7862 buffer.
7863
7864 Examples:
7865
7866   |(foo bar baz)     -> |foo bar baz
7867
7868   (foo bar| baz)     -> foo bar| baz
7869
7870   |(foo) (bar) (baz) -> |(foo) bar (baz) ;; 2"
7871   (interactive "p")
7872   (setq arg (or arg 1))
7873   (let ((sp-navigate-consider-symbols nil))
7874     (let ((ok (save-excursion (sp-forward-sexp arg))))
7875       (when ok (sp--unwrap-sexp ok))
7876       ok)))
7877
7878 (defun sp-backward-unwrap-sexp (&optional arg)
7879   "Unwrap the previous expression.
7880
7881 With ARG N, unwrap Nth expression as returned by
7882 `sp-backward-sexp'.  If ARG is negative -N, unwrap Nth expression
7883 forward as returned by `sp-forward-sexp'.
7884
7885 Examples:
7886
7887   (foo bar baz)|     -> foo bar baz|
7888
7889   (foo bar)| (baz)   -> foo bar| (baz)
7890
7891   (foo) (bar) (baz)| -> foo (bar) (baz) ;; 3"
7892   (interactive "p")
7893   (sp-unwrap-sexp (- (or arg 1))))
7894
7895 (defun sp-splice-sexp (&optional arg)
7896   "Unwrap the current list.
7897
7898 With ARG N, unwrap Nth list as returned by applying `sp-up-sexp'
7899 N times.  This function expect positive arg.
7900
7901 Examples:
7902
7903   (foo (bar| baz) quux) -> (foo bar| baz quux)
7904
7905   (foo |(bar baz) quux) -> foo |(bar baz) quux
7906
7907   (foo (bar| baz) quux) -> foo (bar| baz) quux ;; 2"
7908   (interactive "p")
7909   (setq arg (or arg 1))
7910   (-when-let (ok (sp-get-enclosing-sexp arg))
7911     (if (equal ";" (sp-get ok :prefix))
7912         (sp-get ok
7913           (save-excursion
7914             (goto-char :beg)
7915             (-when-let (enc (sp-get-enclosing-sexp arg))
7916               (sp--unwrap-sexp enc))))
7917       (sp--unwrap-sexp ok))))
7918
7919 (defun sp--splice-sexp-do-killing (beg end expr &optional jump-end)
7920   "Save the text in the region between BEG and END inside EXPR,
7921 then delete EXPR and insert the saved text.
7922
7923 If optional argument JUPM-END is equal to the symbol 'end move
7924 the point after the re-inserted text."
7925   (let (str p)
7926     (setq str (buffer-substring-no-properties beg end))
7927     (delete-region (sp-get expr :beg-prf) (sp-get expr :end))
7928     (save-excursion
7929       (insert str)
7930       (sp--indent-region (sp-get expr :beg-prf) (point))
7931       (setq p (point)))
7932     (when (eq jump-end 'end) (goto-char p))))
7933
7934 (defun sp-splice-sexp-killing-backward (&optional arg)
7935   "Unwrap the current list and kill all the expressions
7936 between start of this list and the point.
7937
7938 With the optional argument ARG, repeat that many times.  This
7939 argument should be positive number.
7940
7941 Examples:
7942
7943   (foo (let ((x 5)) |(sqrt n)) bar)  -> (foo |(sqrt n) bar)
7944
7945 ​  (when ok|                             |(perform-operation-1)
7946 ​    (perform-operation-1)            ->  (perform-operation-2)
7947 ​    (perform-operation-2))
7948
7949 ​  (save-excursion                    -> |(awesome-stuff-happens) ;; 2
7950 ​    (unless (test)
7951 ​      |(awesome-stuff-happens)))
7952
7953 Note that to kill only the content and not the enclosing
7954 delimiters you can use \\[universal-argument] \\[sp-backward-kill-sexp].
7955 See `sp-backward-kill-sexp' for more information."
7956   (interactive "p")
7957   (while (> arg 0)
7958     (sp-splice-sexp-killing-around '(4))
7959     (setq arg (1- arg))))
7960
7961 ;; TODO: write in terms of `sp-splice-sexp-killing-around'.
7962 (defun sp-splice-sexp-killing-forward (&optional arg)
7963   "Unwrap the current list and kill all the expressions between
7964 the point and the end of this list.
7965
7966 With the optional argument ARG, repeat that many times.  This
7967 argument should be positive number.
7968
7969 Examples:
7970
7971   (a (b c| d e) f) -> (a b c| f)
7972
7973   (+ (x |y z) w)   -> (+ x| w)
7974
7975 Note that to kill only the content and not the enclosing
7976 delimiters you can use \\[universal-argument] \\[sp-kill-sexp].
7977 See `sp-kill-sexp' for more information."
7978   (interactive "p")
7979   (while (> arg 0)
7980     (let ((ok (sp-get-enclosing-sexp 1)))
7981       (if ok
7982           (let ((next (sp-get-thing t)))
7983             (if (sp-compare-sexps next ok)
7984                 (sp-kill-sexp '(16))
7985               (sp--splice-sexp-do-killing
7986                (sp-get next :end) ;search backward
7987                (sp-get ok :beg-in)
7988                ok 'end)))
7989         (setq arg -1)))
7990     (setq arg (1- arg))))
7991
7992 (defun sp-splice-sexp-killing-around (&optional arg)
7993   "Unwrap the current list and kill everything inside except next expression.
7994
7995 With ARG save that many next expressions.  With ARG negative -N,
7996 save that many expressions backward.
7997
7998 If ARG is raw prefix argument \\[universal-argument] this function behaves exactly
7999 the same as `sp-splice-sexp-killing-backward'.
8000
8001 If ARG is negative raw prefix argument \\[negative-argument] \\[universal-argument] this function
8002 behaves exactly the same as `sp-splice-sexp-killing-forward'.
8003
8004 Note that the behaviour with the prefix argument seems to be
8005 reversed.  This is because the backward variant is much more
8006 common and hence deserve shorter binding.
8007
8008 If ARG is raw prefix argument \\[universal-argument] \\[universal-argument] raise the expression the point
8009 is inside of.  This is the same as `sp-backward-up-sexp' followed by
8010 `sp-splice-sexp-killing-around'.
8011
8012 Examples:
8013
8014   (a b |(c d) e f)      -> |(c d)     ;; with arg = 1
8015
8016   (a b |c d e f)        -> |c d       ;; with arg = 2
8017
8018   (- (car x) |a 3)      -> (car x)|   ;; with arg = -1
8019
8020   (foo (bar |baz) quux) -> |(bar baz) ;; with arg = \\[universal-argument] \\[universal-argument]"
8021   (interactive "P")
8022   (cond
8023    ((equal arg '(-4))
8024     (sp-splice-sexp-killing-forward 1))
8025    (t
8026     (if (equal arg '(16))
8027         (progn
8028           (sp-backward-up-sexp)
8029           (setq arg 1)))
8030     (let* (inside-comment-inside-sexp
8031            (num-arg (prefix-numeric-value arg))
8032            (ok ;; (sp-get-enclosing-sexp 1)
8033             (save-excursion
8034               (sp-skip-backward-to-symbol)
8035               ;; if the point is inside a comment, we want to
8036               ;; operate on the sexp that contains it.  however,
8037               ;; if we are inside a sexp inside a comment, we
8038               ;; should operate on that instead.
8039               (if (sp-point-in-comment)
8040                   (let ((enc (sp-get-enclosing-sexp 1))
8041                         (cb (sp-get-comment-bounds)))
8042                     (if (> (sp-get enc :beg) (car cb))
8043                         (progn
8044                           (setq inside-comment-inside-sexp t)
8045                           enc)
8046                       (goto-char (cdr cb))
8047                       ;; todo: replace with something more
8048                       ;; abstract
8049                       (skip-chars-forward "\t\n ")
8050                       (sp-get-enclosing-sexp 1)))
8051                 (sp-get-enclosing-sexp 1)))))
8052       (when ok
8053         (when (and (sp-point-in-comment)
8054                    (not inside-comment-inside-sexp))
8055           (let ((cb (sp-get-comment-bounds)))
8056             (goto-char (if (> num-arg 0) (car cb) (cdr cb)))))
8057         (sp-skip-backward-to-symbol)
8058         (-let* ((next (sp--next-thing-selection arg))
8059                 ((from . to)
8060                  (cond
8061                   ((and (sp-point-in-comment)
8062                         (not inside-comment-inside-sexp))
8063                    (if (> num-arg 0)
8064                        ;; only extends to keep the comment if raising
8065                        ;; towards the end.
8066                        (cons (car (sp-get-comment-bounds))
8067                              (sp-get next :end-suf))
8068                      (sp-get next (cons :beg-prf :end-suf))))
8069                   ((and (sp-point-in-comment)
8070                         inside-comment-inside-sexp)
8071                    (sp-get next (cons :beg-prf :end-suf)))
8072                   ;; If we are splicing before a comment, the
8073                   ;; comment might be connected to the sexp
8074                   ;; after it, so we better don't kill it.  Only
8075                   ;; do that if the comment is on its own line
8076                   ;; though, otherwise it is connected to the
8077                   ;; sexp before it.
8078                   ((save-excursion
8079                      (skip-chars-forward "\t\n ")
8080                      (when (and (> num-arg 0)
8081                                 (sp-point-in-comment)
8082                                 (save-excursion
8083                                   (skip-chars-backward "\t ")
8084                                   (bolp)))
8085                        (cons (point) (sp-get next :end-suf)))))
8086                   ;; similarly, if there is a comment before
8087                   ;; this sexp, keep it.
8088                   ((save-excursion
8089                      (sp-backward-symbol)
8090                      (when (and (> num-arg 0)
8091                                 (sp-point-in-comment)
8092                                 (goto-char (car (sp-get-comment-bounds)))
8093                                 (> (point) (sp-get ok :beg))
8094                                 (save-excursion
8095                                   (skip-chars-backward "\t ")
8096                                   (bolp)))
8097                        (cons (point) (sp-get next :end-suf)))))
8098                   (t (sp-get next (cons :beg-prf :end-suf))))))
8099           (sp--splice-sexp-do-killing from to
8100                                       ok (if (> num-arg 0) nil 'end))))))))
8101
8102 (defalias 'sp-raise-sexp 'sp-splice-sexp-killing-around)
8103
8104 (defun sp-convolute-sexp (&optional arg)
8105   "Convolute balanced expressions.
8106
8107 Save the expressions preceding point and delete them.  Then
8108 splice the resulting expression.  Wrap the current enclosing list
8109 with the delimiters of the spliced list and insert the saved
8110 expressions.
8111
8112 If point is in a symbol, move to end of symbol before convolving.
8113
8114 With ARG positive N, move up N lists before wrapping.
8115
8116 Examples:
8117
8118 We want to move the `while' before the `let'.
8119
8120 ​  (let ((stuff 1)             (while (we-are-good)
8121 ​        (other 2))              (let ((stuff 1)
8122 ​    (while (we-are-good)  ->          (other 2))
8123 ​     |(do-thing 1)               |(do-thing 1)
8124 ​      (do-thing 2)                (do-thing 2)
8125 ​      (do-thing 3)))              (do-thing 3)))
8126
8127   (forward-char (sp-get env |:op-l)) -> (sp-get env (forward-char |:op-l))"
8128   (interactive "p")
8129   (save-excursion
8130     (when (sp-point-in-symbol)
8131       (sp-forward-symbol))
8132     (when (looking-at-p " ")
8133       (just-one-space))
8134     (let* ((old-buffer-size (buffer-size))
8135            (enc (sp-get-enclosing-sexp))
8136            (inner-close (sp-get enc (delete-and-extract-region
8137                                      (save-excursion
8138                                        (goto-char :end-in)
8139                                        (sp-backward-whitespace))
8140                                      :end)))
8141            (inner-raise (sp-get enc (delete-and-extract-region
8142                                      :beg-prf
8143                                      (save-excursion
8144                                        (sp-forward-whitespace)))))
8145            (whitespace (sp-get enc
8146                          ;; this happens when the entire inside sexp was removed.
8147                          (when (= old-buffer-size (+ (buffer-size) :len))
8148                            (delete-and-extract-region
8149                             (save-excursion
8150                               (goto-char :beg-prf)
8151                               (max (line-beginning-position) (sp-backward-whitespace)))
8152                             :beg-prf))))
8153            (encp (sp-get-enclosing-sexp arg)))
8154       (sp-get encp
8155         (goto-char :end)
8156         (insert inner-close)
8157         (goto-char :beg-prf)
8158         (insert inner-raise (if whitespace whitespace ""))
8159         (sp-get (sp-get-enclosing-sexp)
8160           (sp--indent-region :beg :end)))))
8161   (indent-according-to-mode))
8162
8163 (defun sp-absorb-sexp (&optional arg)
8164   "Absorb previous expression.
8165
8166 Save the expressions preceding point and delete them.  Then slurp
8167 an expression backward and insert the saved expressions.
8168
8169 With ARG positive N, absorb that many expressions.
8170
8171 Examples:
8172
8173 ​  (do-stuff 1)         (save-excursion
8174 ​  (save-excursion  ->   |(do-stuff 1)
8175 ​   |(do-stuff 2))        (do-stuff 2))
8176
8177   foo bar (concat |baz quux) -> (concat |foo bar baz quux) ;; 2"
8178   (interactive "p")
8179   (sp-forward-whitespace)
8180   (let* ((old (point))
8181          (raise (progn
8182                   (sp-beginning-of-sexp)
8183                   (buffer-substring (point) old))))
8184     (delete-region (point) old)
8185     (sp-backward-slurp-sexp arg)
8186     (sp-forward-whitespace)
8187     (sp-beginning-of-sexp)
8188     (insert raise)
8189     (save-excursion
8190       (sp-backward-up-sexp)
8191       (indent-sexp)))
8192   (sp-forward-whitespace))
8193
8194 (defun sp-emit-sexp (&optional arg)
8195   "Move all expression preceding point except the first one out of the current list.
8196
8197 With ARG positive N, keep that many expressions from the start of
8198 the current list.
8199
8200 This is similar as `sp-backward-barf-sexp' but it also drags the
8201 first N expressions with the delimiter.
8202
8203 Examples:
8204
8205 ​  (save-excursion     ​(do-stuff 1)
8206 ​    (do-stuff 1)      (do-stuff 2)
8207 ​    (do-stuff 2)  ->  (save-excursion
8208 ​   |(do-stuff 3))      |(do-stuff 3))
8209
8210 ​  (while not-done-yet       (execute-only-once)
8211 ​    (execute-only-once) ->  (while not-done-yet    ;; arg = 2
8212 ​   |(execute-in-loop))       |(execute-in-loop))"
8213   (interactive "p")
8214   (let (save-text)
8215     (save-excursion
8216       (sp-beginning-of-sexp)
8217       (let* ((start (point)))
8218         (sp-forward-sexp arg)
8219         (sp-skip-forward-to-symbol t)
8220         (setq save-text (buffer-substring start (point)))
8221         (delete-region start (point))))
8222     (save-excursion (sp-backward-barf-sexp '(4)))
8223     (sp-down-sexp)
8224     (insert save-text)
8225     (save-excursion
8226       (sp-backward-up-sexp)
8227       (indent-sexp))))
8228
8229 (defun sp-extract-before-sexp (&optional arg)
8230   "Move the expression after point before the enclosing balanced expression.
8231
8232 The point moves with the extracted expression.
8233
8234 With ARG positive N, extract N expressions after point.
8235
8236 With ARG negative -N, extract N expressions before point.
8237
8238 With ARG being raw prefix argument \\[universal-argument], extract all the expressions
8239 up until the end of enclosing list.
8240
8241 If the raw prefix is negative, this behaves as \\[universal-argument] `sp-backward-barf-sexp'."
8242   (interactive "P")
8243   (if (equal arg '(-4))
8244       (sp-backward-barf-sexp '(4))
8245     (sp-select-next-thing arg)
8246     (let ((enc (sp-get-enclosing-sexp))
8247           save-text b e nl)
8248       (save-excursion
8249         ;; TODO: extract this use pattern into general "get X things
8250         ;; with or without surrounding whitespace."
8251         (setq b (region-beginning))
8252         (setq e (region-end))
8253         (goto-char (sp-get enc :end-in))
8254         (if (save-excursion
8255               (skip-chars-backward "\t ")
8256               (bolp))
8257             (let ((whitespace (sp-get-whitespace)))
8258               (sp-get whitespace (when (= :beg e)
8259                                    (delete-region :beg :end))))
8260           (setq nl t))
8261         (setq save-text (delete-and-extract-region b e))
8262         (when nl
8263           (let ((whitespace (sp-get-whitespace)))
8264             (sp-get whitespace (delete-region :beg :end))))
8265         (goto-char (sp-get enc :beg-prf))
8266         (insert save-text "\n")
8267         (sp-get enc (sp--indent-region :beg-prf :end)))
8268       ;; if we're at an empty line, remove it
8269       (when (string-match-p "^[\n\t ]+\\'" (thing-at-point 'line))
8270         (let ((b (bounds-of-thing-at-point 'line)))
8271           (delete-region (car b) (cdr b))))
8272       (goto-char (sp-get enc :beg-prf)))))
8273
8274 (defun sp-extract-after-sexp (&optional arg)
8275   "Move the expression after point after the enclosing balanced expression.
8276
8277 The point moves with the extracted expression.
8278
8279 With ARG positive N, extract N expressions after point.
8280
8281 With ARG negative -N, extract N expressions before point.
8282
8283 With ARG being raw prefix argument \\[universal-argument], extract all the
8284 expressions up until the end of enclosing list.
8285
8286 With ARG being negative raw prefix argument \\[negative-argument] \\[universal-argument], extract all the
8287 expressions up until the start of enclosing list."
8288   ;; this is uch uglier than the "before" version, since the
8289   ;; calculations forward have to account for the deleted text. Figure
8290   ;; out a way to make it smoother.
8291   (interactive "P")
8292   (sp-select-next-thing arg)
8293   (sp--with-case-sensitive
8294     (let ((enc (sp-get-enclosing-sexp))
8295           (dws 0)                       ;length of deleted whitespace
8296           save-text b e nl)
8297       (save-excursion
8298         (setq b (region-beginning))
8299         (setq e (region-end))
8300         (goto-char (sp-get enc :end-in))
8301         (if (save-excursion
8302               (skip-chars-backward "\t ")
8303               (bolp))
8304             (let ((whitespace (sp-get-whitespace)))
8305               (sp-get whitespace
8306                 (when (= :beg e)
8307                   (delete-region :beg :end)
8308                   (setq dws (- :end :beg)))))
8309           (setq nl t))
8310         (setq save-text (delete-and-extract-region b e))
8311         (when nl
8312           (let ((whitespace (sp-get-whitespace)))
8313             (sp-get whitespace (delete-region :beg :end))
8314             (sp-get whitespace (setq dws (+ dws (- :end :beg))))))
8315         (sp-get enc (goto-char (- :end (length save-text) dws)))
8316         (insert "\n" save-text)
8317         (sp-get enc (sp--indent-region :beg-prf :end))
8318         (setq e (point)))
8319       ;; if we're at an empty line, remove it
8320       (setq dws 0)                      ; variable reuse, ugly :/
8321       (when (string-match-p "^[\n\t ]+\\'" (thing-at-point 'line))
8322         (let ((b (bounds-of-thing-at-point 'line)))
8323           (delete-region (car b) (cdr b))
8324           (setq dws (- (cdr b) (car b)))))
8325       (when (sp--looking-back (sp--get-opening-regexp) nil t)
8326         (let ((whitespace (sp-get-whitespace)))
8327           (sp-get whitespace
8328             (delete-region :beg :end)
8329             (setq dws (- :end :beg)))))
8330       (goto-char (- e dws)))))
8331
8332 (defun sp-forward-whitespace (&optional arg)
8333   "Skip forward past the whitespace characters.
8334 With non-nil ARG return number of characters skipped."
8335   (interactive "^P")
8336   (let ((rel-move (skip-chars-forward " \t\n")))
8337     (if arg rel-move (point))))
8338
8339 (put 'sp-forward-whitespace 'CUA 'move)
8340
8341 (defun sp-backward-whitespace (&optional arg)
8342   "Skip backward past the whitespace characters.
8343 With non-nil ARG return number of characters skipped."
8344   (interactive "^P")
8345   (let ((rel-move (skip-chars-backward " \t\n")))
8346     (if arg rel-move (point))))
8347
8348 (put 'sp-backward-whitespace 'CUA 'move)
8349
8350 (defun sp-split-sexp (arg)
8351   "Split the list or string the point is on into two.
8352
8353 If ARG is a raw prefix \\[universal-argument] split all the sexps in current expression
8354 in separate lists enclosed with delimiters of the current
8355 expression.
8356
8357 See also setting `sp-split-sexp-always-split-as-string' which
8358 determines how sexps inside strings are treated and also for a
8359 discussion of how to automatically add concatenation operators to
8360 string splitting.
8361
8362 Examples:
8363
8364   (foo bar |baz quux)   -> (foo bar) |(baz quux)
8365
8366   \"foo bar |baz quux\"   -> \"foo bar\" |\"baz quux\"
8367
8368   ([foo |bar baz] quux) -> ([foo] |[bar baz] quux)
8369
8370   (foo bar| baz quux) -> (foo) (bar|) (baz) (quux) ;; \\[universal-argument]"
8371   (interactive "P")
8372   (cond
8373    ((equal arg '(4))
8374     (-when-let (items (sp-get-list-items))
8375       (let ((op (sp-get (car items) :op))
8376             (cl (sp-get (car items) :cl))
8377             (beg (sp-get (car items) :beg))
8378             (end (sp-get (car items) :end)))
8379         (!cdr items)
8380         (setq items (nreverse items))
8381         (save-excursion
8382           (goto-char end)
8383           (delete-char (- (length cl)))
8384           (while items
8385             (sp-get (car items)
8386               (goto-char :end)
8387               (insert cl)
8388               (goto-char :beg)
8389               (insert op))
8390             (!cdr items))
8391           (goto-char beg)
8392           (delete-char (length op))))))
8393    (t
8394     (let ((should-split-as-string
8395            (and sp-split-sexp-always-split-as-string
8396                 (sp-point-in-string))))
8397       (-when-let (ok (if should-split-as-string
8398                          (save-excursion
8399                            (goto-char (1- (cdr (sp-get-quoted-string-bounds))))
8400                            (sp-get-enclosing-sexp 1))
8401                        (sp-get-enclosing-sexp 1)))
8402         (sp-get ok
8403           (sp--run-hook-with-args :op :pre-handlers 'split-sexp)
8404           (if should-split-as-string
8405               (progn
8406                 (insert :cl)
8407                 (save-excursion (insert :op)))
8408             (forward-char (- (prog1 (sp-backward-whitespace t) (insert :cl))))
8409             (save-excursion (sp-forward-whitespace) (insert :op)))
8410           (sp--run-hook-with-args :op :post-handlers 'split-sexp)))))))
8411
8412 (defun sp--join-sexp (prev next)
8413   "Join the expressions PREV and NEXT if they are of the same type.
8414
8415 The expression with smaller :beg is considered the previous one,
8416 so the input order does not actually matter.
8417
8418 Return the information about resulting expression."
8419   (if (and (sp-compare-sexps prev next equal :op)
8420            (sp-compare-sexps prev next equal :cl))
8421       ;; if there's some prefix on the second expression, remove it.
8422       ;; We do not move it to the first expression, it is assumed
8423       ;; there's one already
8424       (progn
8425         (if (sp-compare-sexps prev next >)
8426             (let ((tmp prev))
8427               (setq prev next)
8428               (setq next tmp)))
8429         (sp-get next (delete-region :beg-prf :beg-in))
8430         (sp-get prev (delete-region :end-in :end))
8431         (list :beg (sp-get prev :beg)
8432               :end (- (sp-get next (- :end :op-l :prefix-l)) (sp-get prev :cl-l))
8433               :op (sp-get prev :op)
8434               :cl (sp-get prev :cl)
8435               :prefix (sp-get prev :prefix)))
8436     (sp-message :different-type)))
8437
8438 (defun sp-join-sexp (&optional arg)
8439   "Join the sexp before and after point if they are of the same type.
8440
8441 If ARG is positive N, join N expressions after the point with the
8442 one before the point.
8443
8444 If ARG is negative -N, join N expressions before the point with
8445 the one after the point.
8446
8447 If ARG is a raw prefix \\[universal-argument] join all the things up until the end
8448 of current expression.
8449
8450 The joining stops at the first expression of different type.
8451
8452 Examples:
8453
8454   (foo bar) |(baz)                    -> (foo bar |baz)
8455
8456   (foo) |(bar) (baz)                  -> (foo |bar baz) ;; 2
8457
8458   [foo] [bar] |[baz]                  -> [foo bar |baz] ;; -2
8459
8460   (foo bar (baz)| (quux) (blob bluq)) -> (foo bar (baz| quux blob bluq)) ;; \\[universal-argument]"
8461   (interactive "P")
8462   (let* ((raw (sp--raw-argument-p arg))
8463          (arg (prefix-numeric-value arg))
8464          (n (abs arg))
8465          (prev (save-excursion (sp-backward-sexp (sp--signum arg))))
8466          next)
8467     (save-excursion
8468       (cond
8469        ((and raw (= n 4))
8470         (setq next (sp-forward-sexp (sp--signum arg)))
8471         (while (cond
8472                 ((> arg 0)
8473                  (sp-compare-sexps next prev > :beg :end))
8474                 ((< arg 0)
8475                  (sp-compare-sexps next prev < :end :beg)))
8476           (setq prev (sp--join-sexp prev next))
8477           (setq next (sp-forward-sexp (sp--signum arg)))))
8478        (t (while (> n 0)
8479             (setq next (sp-forward-sexp (sp--signum arg)))
8480             (setq prev (sp--join-sexp prev next))
8481             (setq n (1- n)))))
8482       prev)))
8483
8484 (defun sp--next-thing-selection (&optional arg point)
8485   "Return the bounds of selection over next thing.
8486
8487 See `sp-select-next-thing' for the meaning of ARG.
8488
8489 If POINT is non-nil, it is assumed it's a point inside the buffer
8490 from which the selection extends, either forward or backward,
8491 depending on the value of ARG.
8492
8493 The return value has the same format as `sp-get-sexp'.  This does
8494 not necessarily represent a valid balanced expression!"
8495   (save-excursion
8496     (let* ((raw (sp--raw-argument-p arg))
8497            (arg (prefix-numeric-value arg))
8498            (beg point) (end point)
8499            (op "") (cl "")
8500            (prefix "")
8501            (suffix ""))
8502       (cond
8503        ;; select up until end of list
8504        ((and raw (= arg 4))
8505         (let ((enc (sp-get-enclosing-sexp)))
8506           (if (not enc)
8507               (error "No enclosing expression")
8508             (save-excursion
8509               (goto-char (sp-get enc :end-in))
8510               (-when-let (ok (sp-get-thing t))
8511                 (sp-get ok
8512                   (setq end :end)
8513                   (setq cl :cl)
8514                   (setq suffix :suffix)))))
8515           (unless point
8516             (-when-let (ok (sp-get-thing))
8517               (if (sp-compare-sexps ok enc)
8518                   (progn
8519                     (setq beg end)
8520                     (setq end (sp-get enc :end-in)))
8521                 (sp-get ok
8522                   (setq beg :beg)
8523                   (setq op :op)
8524                   (setq prefix :prefix)))))))
8525        ;; select up until beg of list
8526        ((and raw (= arg -4))
8527         (let ((enc (sp-get-enclosing-sexp)))
8528           (if (not enc)
8529               (error "No enclosing expression")
8530             (save-excursion
8531               (goto-char (sp-get enc :beg-in))
8532               (-when-let (ok (sp-get-thing))
8533                 (sp-get ok
8534                   (setq beg :beg)
8535                   (setq op :op)
8536                   (setq prefix :prefix))))))
8537         (unless point
8538           (-when-let (ok (sp-get-thing t))
8539             (sp-get ok
8540               (setq end :end)
8541               (setq cl :cl)
8542               (setq suffix :suffix)))))
8543        ;; select the enclosing expression
8544        ((and raw (= (abs arg) 16))
8545         (let ((enc (sp-get-enclosing-sexp)))
8546           (if (not enc)
8547               (error "No enclosing expression")
8548             (sp-get enc (setq beg :beg) (setq end :end)
8549                     (setq op :op) (setq cl :cl)
8550                     (setq prefix :prefix)
8551                     (setq suffix :suffix)))))
8552        ;; normal selection, select N expressions
8553        ((> arg 0)
8554         (let* ((first (sp-forward-sexp))
8555                (last first))
8556           (setq arg (1- arg))
8557           (setq beg (or point (sp-get first :beg)))
8558           (while (and (> arg 0) last)
8559             (setq last (sp-forward-sexp))
8560             (let ((nb (sp-get last :beg))) (when (< nb beg)
8561                                              (setq first last)
8562                                              (setq beg nb)))
8563             (setq arg (1- arg)))
8564           (unless (and point (= point beg))
8565             (sp-get first
8566               (setq beg :beg)
8567               (setq op :op)
8568               (setq prefix :prefix)))
8569           (sp-get last
8570             (setq end :end)
8571             (setq cl :cl)
8572             (setq suffix :suffix))))
8573        ;; normal select, select -N expressions
8574        ((< arg 0)
8575         (let* ((first (sp-backward-sexp))
8576                (last first))
8577           (setq arg (1+ arg))
8578           (setq end (or point (sp-get first :end)))
8579           (while (and (< arg 0) last)
8580             (setq last (sp-backward-sexp))
8581             (let ((ne (sp-get last :end))) (when (> ne end)
8582                                              (setq first last)
8583                                              (setq end ne)))
8584             (setq arg (1+ arg)))
8585           (sp-get last
8586             (setq beg :beg)
8587             (setq op :op)
8588             (setq prefix :prefix))
8589           (unless (and point (= point end))
8590             (sp-get first
8591               (setq end :end)
8592               (setq cl :cl)
8593               (setq suffix :suffix)))))
8594        ;; N = 0, select insides
8595        ((= arg 0)
8596         (let ((enc (sp-get-enclosing-sexp)))
8597           (if (not enc)
8598               (error "No enclosing expression")
8599             (save-excursion
8600               (goto-char (sp-get enc :beg-in))
8601               (-when-let (ok (sp-get-thing))
8602                 (sp-get ok
8603                   (setq beg :beg)
8604                   (setq op :op)
8605                   (setq prefix :prefix))))
8606             (save-excursion
8607               (goto-char (sp-get enc :end-in))
8608               (-when-let (ok (sp-get-thing t))
8609                 (sp-get ok
8610                   (setq end :end)
8611                   (setq cl :cl)
8612                   (setq suffix :suffix))))))))
8613       (list :beg beg :end end :op op :cl cl :prefix prefix :suffix suffix))))
8614
8615 (defun sp-select-next-thing (&optional arg point)
8616   "Set active region over next thing as recognized by `sp-get-thing'.
8617
8618 If ARG is positive N, select N expressions forward.
8619
8620 If ARG is negative -N, select N expressions backward.
8621
8622 If ARG is a raw prefix \\[universal-argument] select all the things up until the
8623 end of current expression.
8624
8625 If ARG is a raw prefix \\[universal-argument] \\[universal-argument] select the current expression (as
8626 if doing `sp-backward-up-sexp' followed by
8627 `sp-select-next-thing').
8628
8629 If ARG is number 0 (zero), select all the things inside the
8630 current expression.
8631
8632 If POINT is non-nil, it is assumed it's a point inside the buffer
8633 from which the selection extends, either forward or backward,
8634 depending on the value of ARG.
8635
8636 If the currently active region contains a balanced expression,
8637 following invocation of `sp-select-next-thing' will select the
8638 inside of this expression .  Therefore calling this function
8639 twice with no active region will select the inside of the next
8640 expression.
8641
8642 If the point is right in front of the expression any potential
8643 prefix is ignored.  For example, '|(foo) would only select (foo)
8644 and not include ' in the selection.  If you wish to also select
8645 the prefix, you have to move the point backwards.
8646
8647 With `sp-navigate-consider-symbols' symbols and strings are also
8648 considered balanced expressions."
8649   (interactive "P")
8650   (let* ((selection (sp--next-thing-selection arg point))
8651          (p (point))
8652          (b (sp-get selection :beg))
8653          (e (sp-get selection :end))
8654          contracted)
8655     ;; Show a helpful error if we're trying to move beyond the
8656     ;; beginning or end of the buffer.
8657     (when (or (null b) (null e))
8658       (user-error (if (bobp) "At beginning of buffer" "At end of buffer")))
8659     ;; if region is active and ready to use, check if this selection
8660     ;; == old selection.  If so, reselect the insides
8661     (when (region-active-p)
8662       (let ((rb (region-beginning))
8663             (re (region-end)))
8664         (when (and (sp-get selection
8665                      (or (= rb :beg)
8666                          (= rb :beg-prf)))
8667                    (= re (sp-get selection :end)))
8668           (sp-get selection
8669             (setq b :beg-in)
8670             (setq e :end-in))
8671           (setq contracted t))))
8672     ;; if we moved forward check if the old-point was in front of an
8673     ;; expression and after a prefix. If so, remove the prefix from
8674     ;; the selection
8675     (unless (and (> (prefix-numeric-value arg) 0)
8676                  (not (sp--raw-argument-p arg))
8677                  (= b p))
8678       (unless contracted (setq b (sp-get selection :beg-prf))))
8679     (push-mark b t t)
8680     (goto-char e)
8681     selection))
8682
8683 (defun sp-select-previous-thing (&optional arg point)
8684   "Set active region over ARG previous things as recognized by `sp-get-thing'.
8685
8686 If ARG is negative -N, select that many expressions forward.
8687
8688 With `sp-navigate-consider-symbols' symbols and strings are also
8689 considered balanced expressions."
8690   (interactive "P")
8691   (sp-select-next-thing (sp--negate-argument arg) point))
8692
8693 (defun sp-select-next-thing-exchange (&optional arg point)
8694   "Just like `sp-select-next-thing' but run `exchange-point-and-mark' afterwards."
8695   (interactive "P")
8696   (prog1
8697       (sp-select-next-thing arg point)
8698     (exchange-point-and-mark)))
8699
8700 (defun sp-select-previous-thing-exchange (&optional arg point)
8701   "Just like `sp-select-previous-thing' but run `exchange-point-and-mark' afterwards."
8702   (interactive "P")
8703   (prog1
8704       (sp-select-previous-thing arg point)
8705     (exchange-point-and-mark)))
8706
8707 (defun sp-mark-sexp (&optional arg allow-extend)
8708   "Set mark ARG balanced expressions from point.
8709 The place mark goes is the same place \\[sp-forward-sexp] would
8710 move to with the same argument.
8711 Interactively, if this command is repeated
8712 or (in Transient Mark mode) if the mark is active,
8713 it marks the next ARG sexps after the ones already marked.
8714 This command assumes point is not in a string or comment."
8715   (interactive "P\np")
8716   (cond ((and allow-extend
8717               (or (and (eq last-command this-command) (mark t))
8718                   (and transient-mark-mode mark-active)))
8719          (setq arg (if arg (prefix-numeric-value arg)
8720                      (if (< (mark) (point)) -1 1)))
8721          (set-mark
8722           (save-excursion
8723             (let ((p (point)))
8724               (goto-char (mark))
8725               (sp-forward-sexp arg)
8726               (unless (sp-region-ok-p p (point))
8727                 (user-error "Can not extend selection: region invalid"))
8728               (point)))))
8729         (t
8730          (push-mark
8731           (save-excursion
8732             (sp-forward-sexp (prefix-numeric-value arg))
8733             (point))
8734           nil t))))
8735
8736 (defun sp-delete-char (&optional arg)
8737   "Delete a character forward or move forward over a delimiter.
8738
8739 If on an opening delimiter, move forward into balanced expression.
8740
8741 If on a closing delimiter, refuse to delete unless the balanced
8742 expression is empty, in which case delete the entire expression.
8743
8744 If the delimiter does not form a balanced expression, it will be
8745 deleted normally.
8746
8747 With a numeric prefix argument N > 0, delete N characters forward.
8748
8749 With a numeric prefix argument N < 0, delete N characters backward.
8750
8751 With a numeric prefix argument N = 0, simply delete a character
8752 forward, without regard for delimiter balancing.
8753
8754 If ARG is raw prefix argument \\[universal-argument], delete
8755 characters forward until a closing delimiter whose deletion would
8756 break the proper pairing is hit.
8757
8758 Examples:
8759
8760  (quu|x \"zot\") -> (quu| \"zot\")
8761
8762  (quux |\"zot\") -> (quux \"|zot\") -> (quux \"|ot\")
8763
8764  (foo (|) bar) -> (foo | bar)
8765
8766  |(foo bar) -> (|foo bar)"
8767   (interactive "P")
8768   (sp--with-case-sensitive
8769     (let* ((raw (sp--raw-argument-p arg))
8770            ;; if you edit 10 gigabyte files in Emacs, you're gonna have
8771            ;; a bad time.
8772            (n (if raw 100000000
8773                 (prefix-numeric-value arg))))
8774       (cond
8775        ((> n 0)
8776         (while (> n 0)
8777           (cond
8778            ((let ((ok (sp-point-in-empty-sexp)))
8779               (when ok
8780                 (backward-char (length (car ok)))
8781                 (delete-char (+ (length (car ok)) (length (cdr ok)))))
8782               ok)
8783             ;; make this customizable
8784             (setq n (1- n)))
8785            ((and (sp-point-in-string)
8786                  (save-excursion (forward-char) (not (sp-point-in-string))))
8787             (setq n 0))
8788            ((sp--looking-at (sp--get-opening-regexp (sp--get-pair-list-context 'navigate)))
8789             (-if-let (thing (save-match-data (sp-get-thing)))
8790                 (cond
8791                  ((= (sp-get thing :end-in) (point))
8792                   (setq n 0))
8793                  ((= (sp-get thing :beg) (point))
8794                   (goto-char (sp-get thing :beg-in)))
8795                  (t
8796                   (delete-char (length (match-string 0)))))
8797               (delete-char (length (match-string 0))))
8798             ;; make this customizable
8799             (setq n (1- n)))
8800            ((and (not (sp-point-in-string))
8801                  (save-excursion (forward-char) (sp-point-in-string)))
8802             (forward-char)
8803             ;; make this customizable
8804             (setq n (1- n)))
8805            ((sp--looking-at (sp--get-closing-regexp (sp--get-pair-list-context 'navigate)))
8806             (if (save-match-data (sp-get-thing))
8807                 ;; make this customizable -- maybe we want to skip and
8808                 ;; continue deleting
8809                 (setq n 0)
8810               (delete-char (length (match-string 0)))
8811               (setq n (1- n))))
8812            ((bound-and-true-p hungry-delete-mode)
8813             (hungry-delete-forward 1)
8814             (setq n (1- n)))
8815            (t
8816             (delete-char 1)
8817             (setq n (1- n))))))
8818        ((= n 0) (delete-char 1))
8819        (t (sp-backward-delete-char (sp--negate-argument arg)))))))
8820
8821 (defun sp-backward-delete-char (&optional arg)
8822   "Delete a character backward or move backward over a delimiter.
8823
8824 If on a closing delimiter, move backward into balanced expression.
8825
8826 If on a opening delimiter, refuse to delete unless the balanced
8827 expression is empty, in which case delete the entire expression.
8828
8829 If the delimiter does not form a balanced expression, it will be
8830 deleted normally.
8831
8832 With a numeric prefix argument N > 0, delete N characters backward.
8833
8834 With a numeric prefix argument N < 0, delete N characters forward.
8835
8836 With a numeric prefix argument N = 0, simply delete a character
8837 backward, without regard for delimiter balancing.
8838
8839 If ARG is raw prefix argument \\[universal-argument], delete
8840 characters backward until a opening delimiter whose deletion would
8841 break the proper pairing is hit.
8842
8843 Examples:
8844
8845  (\"zot\" q|uux) -> (\"zot\" |uux)
8846
8847  (\"zot\"| quux) -> (\"zot|\" quux) -> (\"zo|\" quux)
8848
8849  (foo (|) bar) -> (foo | bar)
8850
8851  (foo bar)| -> (foo bar|)"
8852   (interactive "P")
8853   (if (and sp-autodelete-wrap
8854            (eq sp-last-operation 'sp-wrap-region))
8855       (sp-backward-unwrap-sexp)
8856     (sp--with-case-sensitive
8857       (let* ((raw (sp--raw-argument-p arg))
8858              ;; if you edit 10 gigabyte files in Emacs, you're gonna have
8859              ;; a bad time.
8860              (n (if raw 100000000
8861                   (prefix-numeric-value arg))))
8862         (cond
8863          ((> n 0)
8864           (while (> n 0)
8865             (cond
8866              ((let ((ok (sp-point-in-empty-sexp)))
8867                 (when ok
8868                   (backward-char (length (car ok)))
8869                   (delete-char (+ (length (car ok)) (length (cdr ok)))))
8870                 ok)
8871               ;; make this customizable
8872               (setq n (1- n)))
8873              ((and (sp-point-in-string)
8874                    (save-excursion (backward-char) (not (sp-point-in-string))))
8875               (setq n 0))
8876              ((sp--looking-back (sp--get-closing-regexp (sp--get-pair-list-context 'navigate)))
8877               (-if-let (thing (save-match-data (sp-get-thing t)))
8878                   (cond
8879                    ((= (sp-get thing :end) (point))
8880                     (goto-char (sp-get thing :end-in)))
8881                    ((= (sp-get thing :beg-in) (point))
8882                     (setq n 0))
8883                    (t
8884                     (delete-char (- (length (match-string 0))))))
8885                 (delete-char (- (length (match-string 0)))))
8886               ;; make this customizable
8887               (setq n (1- n)))
8888              ((and (not (sp-point-in-string))
8889                    (save-excursion (backward-char) (sp-point-in-string)))
8890               (backward-char)
8891               ;; make this customizable
8892               (setq n (1- n)))
8893              ((sp--looking-back (sp--get-opening-regexp (sp--get-pair-list-context 'navigate)))
8894               (if (save-match-data (sp-get-thing t))
8895                   ;; make this customizable -- maybe we want to skip and
8896                   ;; continue deleting
8897                   (setq n 0)
8898                 (delete-char (- (length (match-string 0))))
8899                 (setq n (1- n))))
8900              ((bound-and-true-p hungry-delete-mode)
8901               (hungry-delete-backward 1)
8902               (setq n (1- n)))
8903              (t
8904               (delete-char -1)
8905               (setq n (1- n))))))
8906          ((= n 0) (delete-char -1))
8907          (t (sp-delete-char (sp--negate-argument arg))))))))
8908
8909 (put 'sp-backward-delete-char 'delete-selection 'supersede)
8910 (put 'sp-delete-char 'delete-selection 'supersede)
8911
8912 (defun sp-point-in-empty-sexp (&optional pos)
8913   "Return non-nil if point is in empty sexp or string.
8914
8915 The return value is active cons pair of opening and closing sexp
8916 delimiter enclosing this sexp."
8917   (setq pos (or pos (point)))
8918   (let (op act)
8919     (cond
8920      ((sp--looking-back (sp--get-opening-regexp (sp--get-pair-list-context 'navigate)))
8921       (setq op (match-string 0))
8922       (setq act (--first (equal (car it) op) sp-pair-list))
8923       (when (sp--looking-at (regexp-quote (cdr act))) act))
8924      ((sp-point-in-empty-string pos)))))
8925
8926 (defun sp-point-in-empty-string (&optional pos)
8927   "Return non-nil if point is in empty string.
8928
8929 The return value is actually cons pair of opening and closing
8930 string delimiter enclosing this string."
8931   (setq pos (or pos (point)))
8932   (when (and (sp-point-in-string)
8933              (save-excursion (if (= (point-max) (point))
8934                                  t
8935                                (forward-char) (not (sp-point-in-string))))
8936              (save-excursion (backward-char) (not (sp-point-in-string))))
8937     (save-excursion
8938       (let* ((syntax (nth 3 (syntax-ppss pos)))
8939              (c (char-to-string (if (eq syntax t) (following-char) syntax))))
8940         (cons c c)))))
8941
8942 (defun sp--use-subword ()
8943   "Return non-nil if word killing commands should kill subwords.
8944 This is the case if `subword-mode' is enabled and
8945 `sp-use-subword' is non-nil."
8946   (and sp-use-subword (bound-and-true-p subword-mode)))
8947
8948 (defun sp--kill-word (&optional n)
8949   "Kill N words or subwords."
8950   (let ((n (or n 1)))
8951     (if (sp--use-subword)
8952         (subword-kill n)
8953       (kill-word n))))
8954
8955 (defun sp--forward-word (&optional n)
8956   "Move forward N words or subwords."
8957   (let ((n (or n 1)))
8958     (if (sp--use-subword)
8959         (subword-forward n)
8960       (forward-word n))))
8961
8962 (defun sp--backward-word (&optional n)
8963   "Move backward N words or subwords."
8964   (let ((n (or n 1)))
8965     (if (sp--use-subword)
8966         (subword-backward n)
8967       (backward-word n))))
8968
8969 (defun sp-kill-symbol (&optional arg word)
8970   "Kill a symbol forward, skipping over any intervening delimiters.
8971
8972 With ARG being positive number N, repeat that many times.
8973
8974 With ARG being Negative number -N, repeat that many times in
8975 backward direction.
8976
8977 See `sp-forward-symbol' for what constitutes a symbol."
8978   (interactive "p")
8979   (sp--with-case-sensitive
8980     (if (> arg 0)
8981         (while (> arg 0)
8982           (-when-let (s (sp-get-symbol))
8983             (sp-get s
8984               (let* ((beg
8985                       (if (< :beg-prf (point))
8986                           (if word (point) :beg)
8987                         (if (= (save-excursion
8988                                  (sp-skip-forward-to-symbol)
8989                                  (point))
8990                                :beg-prf)
8991                             (point)
8992                           :beg-prf)))
8993                      (end (if word
8994                               (let ((fw-end
8995                                      (save-excursion
8996                                        (sp--forward-word)
8997                                        (point))))
8998                                 (if (sp-region-ok-p beg fw-end)
8999                                     fw-end
9000                                   :end-suf))
9001                             :end-suf)))
9002                 (goto-char beg)
9003                 (kill-region beg end))))
9004           (sp--cleanup-after-kill)
9005           (setq arg (1- arg)))
9006       (sp-backward-kill-symbol (sp--negate-argument arg) word))))
9007
9008 (defun sp-kill-word (&optional arg)
9009   "Kill a word forward, skipping over intervening delimiters.
9010
9011 With ARG being positive number N, repeat that many times.
9012
9013 With ARG being Negative number -N, repeat that many times in
9014 backward direction."
9015   (interactive "p")
9016   (sp-kill-symbol arg t))
9017
9018 (defun sp-delete-symbol (&optional arg word)
9019   "Delete a symbol forward, skipping over any intervening delimiters.
9020
9021 Deleted symbol does not go to the clipboard or kill ring.
9022
9023 With ARG being positive number N, repeat that many times.
9024
9025 With ARG being Negative number -N, repeat that many times in
9026 backward direction.
9027
9028 See `sp-forward-symbol' for what constitutes a symbol."
9029   (interactive "p")
9030   (let* ((kill-ring kill-ring)
9031          (select-enable-clipboard nil))
9032     (sp-kill-symbol arg word)))
9033
9034 (defun sp-delete-word (&optional arg)
9035   "Delete a word forward, skipping over intervening delimiters.
9036
9037 Deleted word does not go to the clipboard or kill ring.
9038
9039 With ARG being positive number N, repeat that many times.
9040
9041 With ARG being Negative number -N, repeat that many times in
9042 backward direction."
9043   (interactive "p")
9044   (sp-delete-symbol arg t))
9045
9046 (defun sp-backward-kill-symbol (&optional arg word)
9047   "Kill a symbol backward, skipping over any intervening delimiters.
9048
9049 With ARG being positive number N, repeat that many times.
9050
9051 With ARG being Negative number -N, repeat that many times in
9052 forward direction.
9053
9054 See `sp-backward-symbol' for what constitutes a symbol."
9055   (interactive "p")
9056   (sp--with-case-sensitive
9057     (if (> arg 0)
9058         (while (> arg 0)
9059           (-when-let (s (sp-get-symbol t))
9060             (sp-get s
9061               (let* ((end
9062                       (if (< (point) :end-suf)
9063                           (if word (point) :end-suf)
9064                         (if (= (save-excursion
9065                                  (sp-skip-backward-to-symbol)
9066                                  (point))
9067                                :end-suf)
9068                             (point)
9069                           :end-suf)))
9070                      (beg (if word
9071                               (let ((bw-start
9072                                      (save-excursion
9073                                        (sp--backward-word)
9074                                        (point))))
9075                                 (if (sp-region-ok-p bw-start end)
9076                                     bw-start
9077                                   :beg-prf))
9078                             :beg-prf)))
9079                 (goto-char end)
9080                 (kill-region end beg))))
9081           (sp--cleanup-after-kill)
9082           (setq arg (1- arg)))
9083       (sp-kill-symbol (sp--negate-argument arg) word))))
9084
9085 (defun sp-backward-kill-word (&optional arg)
9086   "Kill a word backward, skipping over intervening delimiters.
9087
9088 With ARG being positive number N, repeat that many times.
9089
9090 With ARG being Negative number -N, repeat that many times in
9091 backward direction."
9092   (interactive "p")
9093   (sp-backward-kill-symbol arg t))
9094
9095 (defun sp-backward-delete-symbol (&optional arg word)
9096   "Delete a symbol backward, skipping over any intervening delimiters.
9097
9098 Deleted symbol does not go to the clipboard or kill ring.
9099
9100 With ARG being positive number N, repeat that many times.
9101
9102 With ARG being Negative number -N, repeat that many times in
9103 forward direction.
9104
9105 See `sp-backward-symbol' for what constitutes a symbol."
9106   (interactive "p")
9107   (let* ((kill-ring kill-ring)
9108          (select-enable-clipboard nil))
9109     (sp-backward-kill-symbol arg word)))
9110
9111 (defun sp-backward-delete-word (&optional arg)
9112   "Delete a word backward, skipping over intervening delimiters.
9113
9114 Deleted word does not go to the clipboard or kill ring.
9115
9116 With ARG being positive number N, repeat that many times.
9117
9118 With ARG being Negative number -N, repeat that many times in
9119 backward direction."
9120   (interactive "p")
9121   (sp-backward-delete-symbol arg t))
9122
9123 (defun sp-delete-region (beg end)
9124   "Delete the text between point and mark, like `delete-region'.
9125
9126 BEG and END are the bounds of region to be deleted.
9127
9128 If that text is unbalanced, signal an error instead.
9129 With a prefix argument, skip the balance check."
9130   (interactive "r")
9131   (when (or current-prefix-arg
9132             (sp-region-ok-p beg end)
9133             (user-error (sp-message :unbalanced-region :return)))
9134     (setq this-command 'delete-region)
9135     (delete-region beg end)))
9136
9137 (defun sp-kill-region (beg end)
9138   "Kill the text between point and mark, like `kill-region'.
9139
9140 BEG and END are the bounds of region to be killed.
9141
9142 If that text is unbalanced, signal an error instead.
9143 With a prefix argument, skip the balance check."
9144   (interactive "r")
9145   (when (or current-prefix-arg
9146             (sp-region-ok-p beg end)
9147             (user-error (sp-message :unbalanced-region :return)))
9148     (setq this-command 'kill-region)
9149     (kill-region beg end)))
9150
9151 (defun sp-indent-defun (&optional arg)
9152   "Reindent the current defun.
9153
9154 If point is inside a string or comment, fill the current
9155 paragraph instead, and with ARG, justify as well.
9156
9157 Otherwise, reindent the current defun, and adjust the position
9158 of the point."
9159   (interactive "P")
9160   (if (sp-point-in-string-or-comment)
9161       (fill-paragraph arg)
9162     (let ((column (current-column))
9163           (indentation (sp--current-indentation)))
9164       (save-excursion
9165         (end-of-defun)
9166         (beginning-of-defun)
9167         (indent-sexp))
9168       (sp--back-to-indentation column indentation))))
9169
9170 (cl-defun sp-region-ok-p (start end)
9171   "Test if region between START and END is balanced.
9172
9173 A balanced region is one where all opening delimiters are matched
9174 by closing delimiters.
9175
9176 This function does *not* check that the delimiters are correctly
9177 ordered, that is [(]) is correct even though it is not logically
9178 properly balanced."
9179   (interactive "r")
9180   (save-excursion
9181     (save-restriction
9182       (when (eq (sp-point-in-string start) (sp-point-in-string end))
9183         (narrow-to-region start end)
9184         (let ((regex (sp--get-allowed-regexp (-difference sp-pair-list (sp--get-allowed-pair-list)))))
9185           (goto-char (point-min))
9186           (while (or (prog1 (sp-forward-sexp)
9187                        (sp-skip-forward-to-symbol))
9188                      ;; skip impossible delimiters
9189                      (when (looking-at-p regex)
9190                        (goto-char (match-end 0)))))
9191           (looking-at-p "[[:blank:]\n]*\\'"))))))
9192
9193 (defun sp-newline ()
9194   "Insert a newline and indent it.
9195
9196 This is like `newline-and-indent', but it not only indents the
9197 line that the point is on but also the S-expression following the
9198 point, if there is one.
9199
9200 If in a string, just insert a literal newline.
9201
9202 If in a comment and if followed by invalid structure, call
9203 `indent-new-comment-line' to keep the invalid structure in a
9204 comment."
9205   (interactive)
9206   (cond
9207    ((sp-point-in-string)
9208     (newline))
9209    ((sp-point-in-comment)
9210     (if (sp-region-ok-p (point) (point-at-eol))
9211         (progn (newline-and-indent) (ignore-errors (indent-sexp)))
9212       (indent-new-comment-line)))
9213    (t
9214     (newline-and-indent)
9215     (ignore-errors (indent-sexp)))))
9216
9217 (defun sp-comment ()
9218   "Insert the comment character and adjust hanging sexps such
9219   that it doesn't break structure."
9220   (interactive)
9221   (if (sp-point-in-string-or-comment)
9222       (if (= 1 (length (single-key-description last-command-event))) ;; pretty hacky
9223           (insert (single-key-description last-command-event))
9224         (insert comment-start))
9225     (sp--with-case-sensitive
9226       (let ((old-point (point))
9227             (column (current-column))
9228             (indentation (sp--current-indentation))
9229             (old-line (line-number-at-pos))
9230             (hsexp (sp-get-hybrid-sexp))
9231             (newline-inserted 0))
9232         (goto-char (sp-get hsexp :end))
9233         (if (and (sp--looking-at-p (concat "\\s-*" (sp--get-closing-regexp)))
9234                  (= old-line (line-number-at-pos)))
9235             (progn
9236               (setq old-point (point))
9237               (newline)
9238               (setq newline-inserted (1+ (- (line-end-position) (point)))))
9239           (when (/= old-line (line-number-at-pos))
9240             (sp-backward-sexp)
9241             (setq old-point (+ old-point (skip-syntax-backward " ")))
9242             (newline)
9243             (setq newline-inserted (- (line-end-position) (point)))))
9244         ;; @{ indenting madness
9245         (goto-char old-point)
9246         (sp-get hsexp (sp--indent-region :beg (+ :end newline-inserted)))
9247         (sp--back-to-indentation column indentation)
9248         ;; @}
9249         (let ((comment-delim (or (cdr (--first (memq major-mode (car it)) sp-comment-string))
9250                                  comment-start)))
9251           (when (and (/= 0 (current-column))
9252                      (not (sp--looking-back-p "\\s-")))
9253             (insert " "))
9254           (insert comment-delim)
9255           (when (/= newline-inserted 0)
9256             (save-excursion
9257               (forward-line 1)
9258               (indent-according-to-mode))))))))
9259
9260 (defun sp-wrap-round ()
9261   "Wrap following sexp in round parentheses."
9262   (interactive)
9263   (sp-wrap-with-pair "("))
9264
9265 (defun sp-wrap-square ()
9266   "Wrap following sexp in square brackets."
9267   (interactive)
9268   (sp-wrap-with-pair "["))
9269
9270 (defun sp-wrap-curly ()
9271   "Wrap following sexp in curly braces."
9272   (interactive)
9273   (sp-wrap-with-pair "{"))
9274
9275
9276 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9277 ;; show-smartparens-mode
9278
9279 (defgroup show-smartparens nil
9280   "Show smartparens minor mode."
9281   :group 'smartparens)
9282
9283 (defcustom sp-show-pair-delay 0.125
9284   "Time in seconds to delay before showing a matching pair."
9285   :type '(number :tag "seconds")
9286   :group 'show-smartparens)
9287
9288 (defcustom sp-show-enclosing-pair-commands '(
9289                                              sp-show-enclosing-pair
9290                                              sp-forward-slurp-sexp
9291                                              sp-backward-slurp-sexp
9292                                              sp-forward-barf-sexp
9293                                              sp-backward-barf-sexp
9294                                              )
9295   "List of commands after which the enclosing pair is highlighted.
9296
9297 After the next command the pair will automatically disappear."
9298   :type '(repeat symbol)
9299   :group 'show-smartparens)
9300
9301 (defcustom sp-show-pair-from-inside nil
9302   "If non-nil, highlight the enclosing pair if immediately after
9303 the opening delimiter or before the closing delimiter."
9304   :type 'boolean
9305   :group 'show-smartparens)
9306
9307 (defface sp-show-pair-match-face
9308   '((t (:inherit show-paren-match)))
9309   "`show-smartparens-mode' face used for a matching pair."
9310   :group 'show-smartparens)
9311
9312 (defface sp-show-pair-mismatch-face
9313   '((t (:inherit show-paren-mismatch)))
9314   "`show-smartparens-mode' face used for a mismatching pair."
9315   :group 'show-smartparens)
9316
9317 (defface sp-show-pair-enclosing
9318   '((t (:inherit highlight)))
9319   "The face used to highlight pair overlays."
9320   :group 'show-smartparens)
9321
9322 (defface sp-show-pair-match-content-face
9323   '()
9324   "`show-smartparens-mode' face used for a matching pair's content."
9325   :group 'show-smartparens)
9326
9327 (defvar sp-show-pair-idle-timer nil)
9328
9329 (defvar sp-show-pair-overlays nil)
9330
9331 (defvar sp-show-pair-previous-match-positions nil)
9332
9333 (defvar sp-show-pair-previous-point nil)
9334
9335 (defvar sp-show-pair-enc-overlays nil)
9336
9337 ;;;###autoload
9338 (define-minor-mode show-smartparens-mode
9339   "Toggle visualization of matching pairs.  When enabled, any
9340 matching pair is highlighted after `sp-show-pair-delay' seconds
9341 of Emacs idle time if the point is immediately in front or after
9342 a pair.  This mode works similarly to `show-paren-mode', but
9343 support custom pairs."
9344   :init-value nil
9345   :group 'show-smartparens
9346   (if show-smartparens-mode
9347       (unless sp-show-pair-idle-timer
9348         (setq sp-show-pair-idle-timer
9349               (run-with-idle-timer sp-show-pair-delay t
9350                                    'sp-show--pair-function)))
9351     (when sp-show-pair-overlays
9352       (sp-show--pair-delete-overlays))))
9353
9354 ;;;###autoload
9355 (define-globalized-minor-mode show-smartparens-global-mode
9356   show-smartparens-mode
9357   turn-on-show-smartparens-mode)
9358
9359 ;;;###autoload
9360 (defun turn-on-show-smartparens-mode ()
9361   "Turn on `show-smartparens-mode'."
9362   (interactive)
9363   (unless (or (member major-mode sp-ignore-modes-list)
9364               (and (not (derived-mode-p 'comint-mode))
9365                    (eq (get major-mode 'mode-class) 'special)))
9366     (show-smartparens-mode t)))
9367
9368 ;;;###autoload
9369 (defun turn-off-show-smartparens-mode ()
9370   "Turn off `show-smartparens-mode'."
9371   (interactive)
9372   (show-smartparens-mode -1))
9373
9374 (defun sp-show-enclosing-pair ()
9375   "Highlight the enclosing pair around point."
9376   (interactive))
9377
9378 (defun sp-highlight-current-sexp (_arg)
9379   "Highlight the expression returned by the next command, preserving point position."
9380   (interactive "P")
9381   (let* ((cmd (read-key-sequence "" t))
9382          (com (key-binding cmd)))
9383     (if (commandp com)
9384         (save-excursion
9385           (let ((ok (call-interactively com)))
9386             (sp-show--pair-enc-function ok)))
9387       (execute-kbd-macro cmd))))
9388
9389 (defun sp-show--pair-function ()
9390   "Display the show pair overlays and print the line of the
9391 matching paren in the echo area if not visible on screen."
9392   (when show-smartparens-mode
9393     (sp--with-case-sensitive
9394       (save-match-data
9395         (cl-labels ((scan-and-place-overlays
9396                      (match &optional back)
9397                      ;; we can use `sp-get-thing' here because we *are* at some
9398                      ;; pair opening, and so only the tag or the sexp can trigger.
9399                      (-if-let (ok (sp-get-thing back))
9400                          (sp-get ok
9401                            (when (or (and back
9402                                           (or (= :end (point))
9403                                               (= :beg-in (point))))
9404                                      (and (not back)
9405                                           (or (= :beg (point))
9406                                               (= :end-in (point)))))
9407                              (sp-show--pair-create-overlays :beg :end :op-l :cl-l)
9408                              (when (and sp-echo-match-when-invisible
9409                                         (not (or (active-minibuffer-window) cursor-in-echo-area)))
9410                                (sp-show--pair-echo-match :beg :end :op-l :cl-l))))
9411                        (if back
9412                            (sp-show--pair-create-mismatch-overlay (- (point) (length match))
9413                                                                   (length match))
9414                          (sp-show--pair-create-mismatch-overlay (point) (length match)))
9415                        (setq sp-show-pair-previous-match-positions nil)
9416                        (setq sp-show-pair-previous-point nil))))
9417           (let* ((pair-list (sp--get-allowed-pair-list))
9418                  (opening (sp--get-opening-regexp pair-list))
9419                  (closing (sp--get-closing-regexp pair-list))
9420                  (allowed (and sp-show-pair-from-inside (sp--get-allowed-regexp))))
9421             (cond
9422              ;; if we are in a situation "()|", we should highlight the
9423              ;; regular pair and not the string pair "from inside"
9424              ((and (not (sp--evil-normal-state-p))
9425                    (not (sp--evil-motion-state-p))
9426                    (not (sp--evil-visual-state-p))
9427                    (sp--looking-back (if sp-show-pair-from-inside allowed closing)))
9428               (scan-and-place-overlays (match-string 0) :back))
9429              ((or (and (or (sp--evil-normal-state-p)
9430                            (sp--evil-motion-state-p)
9431                            (sp--evil-visual-state-p))
9432                        (sp--looking-at (sp--get-allowed-regexp)))
9433                   (sp--looking-at (if sp-show-pair-from-inside allowed opening))
9434                   (looking-at (sp--get-stringlike-regexp))
9435                   (and (memq major-mode sp-navigate-consider-sgml-tags)
9436                        (looking-at "<")))
9437               (scan-and-place-overlays (match-string 0)))
9438              ((or (sp--looking-back (if sp-show-pair-from-inside allowed closing))
9439                   (sp--looking-back (sp--get-stringlike-regexp))
9440                   (and (memq major-mode sp-navigate-consider-sgml-tags)
9441                        (sp--looking-back ">")))
9442               (scan-and-place-overlays (match-string 0) :back))
9443              (sp-show-pair-overlays
9444               (sp-show--pair-delete-overlays)
9445               (setq sp-show-pair-previous-match-positions nil)
9446               (setq sp-show-pair-previous-point nil)))))))))
9447
9448 (defun sp-show--pair-enc-function (&optional thing)
9449   "Display the show pair overlays for enclosing expression."
9450   (when show-smartparens-mode
9451     (-when-let (enc (or thing (sp-get-enclosing-sexp)))
9452       (sp-get enc (sp-show--pair-create-enc-overlays :beg :end :op-l :cl-l)))))
9453
9454 (defun sp-show--pair-create-overlays (start end olen clen)
9455   "Create the show pair overlays."
9456   (when sp-show-pair-overlays
9457     (sp-show--pair-delete-overlays))
9458   (let* ((oleft (make-overlay start (+ start olen) nil t nil))
9459          (omiddle (make-overlay (+ start olen) (- end clen) nil t nil))
9460          (oright (make-overlay (- end clen) end nil t nil)))
9461     (setq sp-show-pair-overlays (list oleft omiddle oright))
9462     (overlay-put oleft 'face 'sp-show-pair-match-face)
9463     (unless (use-region-p)
9464       (overlay-put omiddle 'face 'sp-show-pair-match-content-face))
9465     (overlay-put oright 'face 'sp-show-pair-match-face)
9466     (overlay-put oleft 'priority 1000)
9467     (overlay-put omiddle 'priority 1000)
9468     (overlay-put oright 'priority 1000)
9469     (overlay-put oleft 'type 'show-pair)))
9470
9471 (defun sp-show--pair-echo-match (start end olen clen)
9472   "Print the line of the matching paren in the echo area if not
9473 visible on screen. Needs to be called after the show-pair overlay
9474 has been created."
9475   (let ((match-positions (list start end olen clen)))
9476     (when (not (and (equal sp-show-pair-previous-match-positions match-positions)
9477                     (equal sp-show-pair-previous-point (point))))
9478       (setq sp-show-pair-previous-match-positions match-positions)
9479       (setq sp-show-pair-previous-point (point))
9480       (let* ((visible-start (pos-visible-in-window-p start))
9481              (visible-end (pos-visible-in-window-p end))
9482              (where (cond
9483                      ((not visible-start) start)
9484                      ((not visible-end) end))))
9485         (when where
9486           (save-excursion
9487             (let* ((from (progn (goto-char where) (beginning-of-line) (point)))
9488                    (to (progn (end-of-line) (point)))
9489                    (line (buffer-substring from to))
9490                    (message-log-max)) ;; don't log in messages
9491               ;; Add smartparens overlay for opening parens
9492               (let* ((i1 (- start from))
9493                      (i2 (+ i1 olen)))
9494                 (when (and (< i1 (length line)) (>= i2 0))
9495                   (add-face-text-property (max i1 0) (min i2 (length line))
9496                                           'sp-show-pair-match-face nil line)))
9497               ;; Add smartparens overlay for closing parens
9498               (let* ((i1 (- end from 1))
9499                      (i2 (+ i1 clen)))
9500                 (when (and (< i1 (length line)) (>= i2 0))
9501                   (add-face-text-property (max i1 0) (min i2 (length line))
9502                                           'sp-show-pair-match-face nil line)))
9503               ;; echo line of match
9504               (message "Matches: %s" (string-trim line)))))))))
9505
9506 (defun sp-show--pair-create-enc-overlays (start end olen clen)
9507   "Create the show pair enclosing overlays"
9508   (when sp-show-pair-enc-overlays
9509     (sp-show--pair-delete-enc-overlays))
9510   (let* ((oleft (make-overlay start (+ start olen) nil t nil))
9511          (oright (make-overlay (- end clen) end nil t nil)))
9512     (setq sp-show-pair-enc-overlays (cons oleft oright))
9513     (overlay-put oleft 'face 'sp-show-pair-enclosing)
9514     (overlay-put oright 'face 'sp-show-pair-enclosing)
9515     (overlay-put oleft 'priority 1000)
9516     (overlay-put oright 'priority 1000)
9517     (overlay-put oleft 'type 'show-pair-enc)))
9518
9519 (defun sp-show--pair-create-mismatch-overlay (start len)
9520   "Create the mismatch pair overlay."
9521   (when sp-show-pair-overlays
9522     (sp-show--pair-delete-overlays))
9523   (let ((o (make-overlay start (+ start len) nil t nil)))
9524     (setq sp-show-pair-overlays (list o))
9525     (overlay-put o 'face 'sp-show-pair-mismatch-face)
9526     (overlay-put o 'priority 1000)
9527     (overlay-put o 'type 'show-pair)))
9528
9529 (defun sp-show--pair-delete-overlays ()
9530   "Remove both show pair overlays."
9531   (when sp-show-pair-overlays
9532     (dolist (overlay sp-show-pair-overlays)
9533       (delete-overlay overlay))
9534     (setq sp-show-pair-overlays nil)))
9535
9536 (defun sp-show--pair-delete-enc-overlays ()
9537   "Remove both show pair enclosing overlays."
9538   (when sp-show-pair-enc-overlays
9539     (when (car sp-show-pair-enc-overlays)
9540       (delete-overlay (car sp-show-pair-enc-overlays)))
9541     (when (cdr sp-show-pair-enc-overlays)
9542       (delete-overlay (cdr sp-show-pair-enc-overlays)))
9543     (setq sp-show-pair-enc-overlays nil)))
9544
9545
9546 ;; global initialization
9547 (defadvice delete-backward-char (before sp-delete-pair-advice activate)
9548   (save-match-data
9549     (sp-delete-pair (ad-get-arg 0))))
9550 (defadvice haskell-indentation-delete-backward-char (before sp-delete-pair-advice activate)
9551   (save-match-data
9552     (sp-delete-pair (ad-get-arg 0))))
9553 (add-hook 'post-command-hook 'sp--post-command-hook-handler)
9554 (sp--set-base-key-bindings)
9555 (sp--update-override-key-bindings)
9556
9557 (defadvice company--insert-candidate (after sp-company--insert-candidate activate)
9558   "If `smartparens-mode' is active, we check if the completed string
9559 has a pair definition.  If so, we insert the closing pair."
9560   (when smartparens-mode
9561     (sp-insert-pair))
9562   ad-return-value)
9563
9564 (defadvice hippie-expand (after sp-auto-complete-advice activate)
9565   (when smartparens-mode
9566     (sp-insert-pair)))
9567
9568 (defvar sp--mc/cursor-specific-vars
9569   '(
9570     sp-wrap-point
9571     sp-wrap-mark
9572     sp-last-wrapped-region
9573     sp-pair-overlay-list
9574     sp-wrap-overlays
9575     sp-wrap-tag-overlays
9576     sp-last-operation
9577     sp-previous-point
9578     )
9579   "A list of vars that need to be tracked on a per-cursor basis.")
9580
9581 (defvar mc/cursor-specific-vars)
9582 (eval-after-load 'multiple-cursors
9583   '(dolist (it sp--mc/cursor-specific-vars)
9584      (add-to-list 'mc/cursor-specific-vars it)))
9585
9586 (provide 'smartparens)
9587
9588 ;; Local Variables:
9589 ;; coding: utf-8
9590 ;; eval: (font-lock-add-keywords nil `((,(concat "(" (regexp-opt '("sp-do-move-op" "sp-do-move-cl" "sp-do-put-op" "sp-do-put-cl" "sp-do-del-op" "sp-do-del-cl") t) "\\_>") 1 'font-lock-variable-name-face)))
9591 ;; End:
9592
9593 ;;; smartparens.el ends here