dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

paredit.el (127752B)


      1 ;;; paredit.el --- minor mode for editing parentheses  -*- Mode: Emacs-Lisp -*-
      2 
      3 ;; Copyright (C) 2005--2022 Taylor R. Campbell
      4 
      5 ;; Author: Taylor R. Campbell <campbell@paredit.org>
      6 ;; Version: 26
      7 ;; Created: 2005-07-31
      8 ;; Keywords: lisp
      9 
     10 ;; Paredit is free software: you can redistribute it and/or modify it
     11 ;; under the terms of the GNU General Public License as published by
     12 ;; the Free Software Foundation, either version 3 of the License, or
     13 ;; (at your option) any later version.
     14 ;;
     15 ;; Paredit is distributed in the hope that it will be useful, but
     16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
     17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18 ;; GNU General Public License for more details.
     19 ;;
     20 ;; You should have received a copy of the GNU General Public License
     21 ;; along with paredit.  If not, see <http://www.gnu.org/licenses/>.
     22 
     23 ;;; Paredit - https://paredit.org
     24 ;;;
     25 ;;; Latest release: https://paredit.org/paredit.el
     26 ;;; Current development version: https://paredit.org/paredit-beta.el
     27 ;;; Release notes: https://paredit.org/NEWS
     28 
     29 ;;; Install paredit by placing `paredit.el' in `/path/to/elisp', a
     30 ;;; directory of your choice, and adding to your .emacs file:
     31 ;;;
     32 ;;;   (add-to-list 'load-path "/path/to/elisp")
     33 ;;;   (autoload 'enable-paredit-mode "paredit"
     34 ;;;     "Turn on pseudo-structural editing of Lisp code."
     35 ;;;     t)
     36 ;;;
     37 ;;; Start Paredit Mode on the fly with `M-x enable-paredit-mode RET',
     38 ;;; or always enable it in a major mode `M' (e.g., `lisp') with:
     39 ;;;
     40 ;;;   (add-hook 'M-mode-hook 'enable-paredit-mode)
     41 ;;;
     42 ;;; Customize paredit using `eval-after-load':
     43 ;;;
     44 ;;;   (eval-after-load 'paredit
     45 ;;;     '(progn
     46 ;;;        (define-key paredit-mode-map (kbd "ESC M-A-C-s-)")
     47 ;;;          'paredit-dwim)))
     48 ;;;
     49 ;;; Send questions, bug reports, comments, feature suggestions, &c.,
     50 ;;; via email to the author's surname at paredit.org.
     51 ;;;
     52 ;;; Paredit should run in GNU Emacs 21 or later and XEmacs 21.5.28 or
     53 ;;; later.
     54 
     55 ;;; The paredit minor mode, Paredit Mode, binds common character keys,
     56 ;;; such as `(', `)', `"', and `\', to commands that carefully insert
     57 ;;; S-expression structures in the buffer:
     58 ;;;
     59 ;;;   ( inserts `()', leaving the point in the middle;
     60 ;;;   ) moves the point over the next closing delimiter;
     61 ;;;   " inserts `""' if outside a string, or inserts an escaped
     62 ;;;      double-quote if in the middle of a string, or moves over the
     63 ;;;      closing double-quote if at the end of a string; and
     64 ;;;   \ prompts for the character to escape, to avoid inserting lone
     65 ;;;      backslashes that may break structure.
     66 ;;;
     67 ;;; In comments, these keys insert themselves.  If necessary, you can
     68 ;;; insert these characters literally outside comments by pressing
     69 ;;; `C-q' before these keys, in case a mistake has broken the
     70 ;;; structure.
     71 ;;;
     72 ;;; These key bindings are designed so that when typing new code in
     73 ;;; Paredit Mode, you can generally type exactly the same sequence of
     74 ;;; keys you would have typed without Paredit Mode.
     75 ;;;
     76 ;;; Paredit Mode also binds common editing keys, such as `DEL', `C-d',
     77 ;;; and `C-k', to commands that respect S-expression structures in the
     78 ;;; buffer:
     79 ;;;
     80 ;;;   DEL deletes the previous character, unless it is a delimiter: DEL
     81 ;;;        will move the point backward over a closing delimiter, and
     82 ;;;        will delete a delimiter pair together if between an open and
     83 ;;;        closing delimiter;
     84 ;;;
     85 ;;;   C-d deletes the next character in much the same manner; and
     86 ;;;
     87 ;;;   C-k kills all S-expressions that begin anywhere between the point
     88 ;;;        and the end of the line or the closing delimiter of the
     89 ;;;        enclosing list, whichever is first.
     90 ;;;
     91 ;;; If necessary, you can delete a character, kill a line, &c.,
     92 ;;; irrespective of S-expression structure, by pressing `C-u' before
     93 ;;; these keys, in case a mistake has broken the structure.
     94 ;;;
     95 ;;; Finally, Paredit Mode binds some keys to complex S-expression
     96 ;;; editing operations.  For example, `C-<right>' makes the enclosing
     97 ;;; list slurp up an S-expression to its right (here `|' denotes the
     98 ;;; point):
     99 ;;;
    100 ;;;   (foo (bar | baz) quux)  C-<right>  (foo (bar | baz quux))
    101 ;;;
    102 ;;; Note: Paredit Mode is not compatible with Electric Indent Mode.
    103 ;;; Use one or the other, not both.  If you want RET to auto-indent and
    104 ;;; C-j to just insert newline in Paredit Mode, simply rebind the keys
    105 ;;; with the following fragment in your .emacs file:
    106 ;;;
    107 ;;;     (eval-after-load 'paredit
    108 ;;;       '(progn
    109 ;;;          (define-key paredit-mode-map (kbd "RET") 'paredit-newline)
    110 ;;;          (define-key paredit-mode-map (kbd "C-j") nil)))
    111 ;;;
    112 ;;; Some paredit commands automatically reindent code.  When they do,
    113 ;;; they try to indent as locally as possible, to avoid interfering
    114 ;;; with any indentation you might have manually written.  Only the
    115 ;;; advanced S-expression manipulation commands automatically reindent,
    116 ;;; and only the forms that they immediately operated upon (and their
    117 ;;; subforms).
    118 ;;;
    119 ;;; This code is written for clarity, not efficiency.  It frequently
    120 ;;; walks over S-expressions redundantly.  If you have problems with
    121 ;;; the time it takes to execute some of the commands, let me know.
    122 
    123 ;;; This assumes Unix-style LF line endings.
    124 
    125 (defconst paredit-version 26)
    126 (defconst paredit-beta-p nil)
    127 
    128 (eval-and-compile
    129 
    130   (defun paredit-xemacs-p ()
    131     ;; No idea where I got this definition from.  Edward O'Connor
    132     ;; (hober in #emacs) suggested the current definition.
    133     ;;   (and (boundp 'running-xemacs)
    134     ;;        running-xemacs)
    135     (featurep 'xemacs))
    136 
    137   (defun paredit-gnu-emacs-p ()
    138     ;++ This could probably be improved.
    139     (not (paredit-xemacs-p)))
    140 
    141   (defmacro xcond (&rest clauses)
    142     "Exhaustive COND.
    143 Signal an error if no clause matches."
    144     `(cond ,@clauses
    145            (t (error "XCOND lost."))))
    146 
    147   (defalias 'paredit-warn (if (fboundp 'warn) 'warn 'message))
    148 
    149   (defvar paredit-sexp-error-type
    150     (with-temp-buffer
    151       (insert "(")
    152       (condition-case condition
    153           (backward-sexp)
    154         (error (if (eq (car condition) 'error)
    155                    (paredit-warn "%s%s%s%s%s"
    156                                  "Paredit is unable to discriminate"
    157                                  " S-expression parse errors from"
    158                                  " other errors. "
    159                                  " This may cause obscure problems. "
    160                                  " Please upgrade Emacs."))
    161                (car condition)))))
    162 
    163   (defmacro paredit-handle-sexp-errors (body &rest handler)
    164     `(condition-case ()
    165          ,body
    166        (,paredit-sexp-error-type ,@handler)))
    167 
    168   (put 'paredit-handle-sexp-errors 'lisp-indent-function 1)
    169 
    170   (defmacro paredit-ignore-sexp-errors (&rest body)
    171     `(paredit-handle-sexp-errors (progn ,@body)
    172        nil))
    173 
    174   (put 'paredit-ignore-sexp-errors 'lisp-indent-function 0)
    175 
    176   (defmacro paredit-preserving-column (&rest body)
    177     "Evaluate BODY and restore point to former column, relative to code.
    178 Assumes BODY will change only indentation.
    179 If point was on code, it moves with the code.
    180 If point was on indentation, it stays in indentation."
    181     (let ((column (make-symbol "column"))
    182           (indentation (make-symbol "indentation")))
    183       `(let ((,column (paredit-current-column))
    184              (,indentation (paredit-current-indentation)))
    185          (let ((value (progn ,@body)))
    186            (paredit-restore-column ,column ,indentation)
    187            value))))
    188 
    189   (put 'paredit-preserving-column 'lisp-indent-function 0)
    190 
    191   nil)
    192 
    193 ;;;; Minor Mode Definition
    194 
    195 (defvar paredit-lighter " Paredit"
    196   "Mode line lighter Paredit Mode.")
    197 
    198 (defvar paredit-mode-map (make-sparse-keymap)
    199   "Keymap for the paredit minor mode.")
    200 
    201 (defvar paredit-override-check-parens-function
    202   (lambda (condition) (declare ignore condition) nil)
    203   "Function to tell whether unbalanced text should inhibit Paredit Mode.")
    204 
    205 ;;;###autoload
    206 (define-minor-mode paredit-mode
    207   "Minor mode for pseudo-structurally editing Lisp code.
    208 With a prefix argument, enable Paredit Mode even if there are
    209   unbalanced parentheses in the buffer.
    210 Paredit behaves badly if parentheses are unbalanced, so exercise
    211   caution when forcing Paredit Mode to be enabled, and consider
    212   fixing unbalanced parentheses instead.
    213 \\<paredit-mode-map>"
    214   :lighter paredit-lighter
    215   ;; Setting `paredit-mode' to false here aborts enabling Paredit Mode.
    216   (if (and paredit-mode
    217            (not current-prefix-arg))
    218       (condition-case condition
    219           (check-parens)
    220         (error
    221          (if (not (funcall paredit-override-check-parens-function condition))
    222              (progn (setq paredit-mode nil)
    223                     (signal (car condition) (cdr condition))))))))
    224 
    225 (defun paredit-override-check-parens-interactively (condition)
    226   (y-or-n-p (format "Enable Paredit Mode despite condition %S? " condition)))
    227 
    228 ;;;###autoload
    229 (defun enable-paredit-mode ()
    230   "Turn on pseudo-structural editing of Lisp code."
    231   (interactive)
    232   (paredit-mode +1))
    233 
    234 (defun disable-paredit-mode ()
    235   "Turn off pseudo-structural editing of Lisp code."
    236   (interactive)
    237   (paredit-mode -1))
    238 
    239 (defvar paredit-backward-delete-key
    240   (xcond ((paredit-xemacs-p)    "BS")
    241          ((paredit-gnu-emacs-p) "DEL")))
    242 
    243 (defvar paredit-forward-delete-keys
    244   (xcond ((paredit-xemacs-p)    '("DEL"))
    245          ((paredit-gnu-emacs-p) '("<delete>" "<deletechar>"))))
    246 
    247 ;;;; Paredit Keys
    248 
    249 ;;; Separating the definition and initialization of this variable
    250 ;;; simplifies the development of paredit, since re-evaluating DEFVAR
    251 ;;; forms doesn't actually do anything.
    252 
    253 (defvar paredit-commands nil
    254   "List of paredit commands with their keys and examples.")
    255 
    256 ;;; Each specifier is of the form:
    257 ;;;   (key[s] function (example-input example-output) ...)
    258 ;;; where key[s] is either a single string suitable for passing to KBD
    259 ;;; or a list of such strings.  Entries in this list may also just be
    260 ;;; strings, in which case they are headings for the next entries.
    261 
    262 (progn (setq paredit-commands
    263  `(
    264    "Basic Insertion Commands"
    265    ("("         paredit-open-round
    266                 ("(a b |c d)"
    267                  "(a b (|) c d)")
    268                 ("(foo \"bar |baz\" quux)"
    269                  "(foo \"bar (|baz\" quux)"))
    270    (")"         paredit-close-round
    271                 ("(a b |c   )" "(a b c)|")
    272                 ("; Hello,| world!"
    273                  "; Hello,)| world!"))
    274    ("M-)"       paredit-close-round-and-newline
    275                 ("(defun f (x|  ))"
    276                  "(defun f (x)\n  |)")
    277                 ("; (Foo.|"
    278                  "; (Foo.)|"))
    279    ("["         paredit-open-square
    280                 ("(a b |c d)"
    281                  "(a b [|] c d)")
    282                 ("(foo \"bar |baz\" quux)"
    283                  "(foo \"bar [|baz\" quux)"))
    284    ("]"         paredit-close-square
    285                 ("(define-key keymap [frob|  ] 'frobnicate)"
    286                  "(define-key keymap [frob]| 'frobnicate)")
    287                 ("; [Bar.|"
    288                  "; [Bar.]|"))
    289 
    290    ("\""        paredit-doublequote
    291                 ("(frob grovel |full lexical)"
    292                  "(frob grovel \"|\" full lexical)"
    293                  "(frob grovel \"\"| full lexical)")
    294                 ("(foo \"bar |baz\" quux)"
    295                  "(foo \"bar \\\"|baz\" quux)")
    296                 ("(frob grovel)   ; full |lexical"
    297                  "(frob grovel)   ; full \"|lexical"))
    298    ("M-\""      paredit-meta-doublequote
    299                 ("(foo \"bar |baz\" quux)"
    300                  "(foo \"bar baz\"| quux)")
    301                 ("(foo |(bar #\\x \"baz \\\\ quux\") zot)"
    302                  ,(concat "(foo \"|(bar #\\\\x \\\"baz \\\\"
    303                           "\\\\ quux\\\")\" zot)")))
    304    ("\\"        paredit-backslash
    305                 ("(string #|)\n  ; Character to escape: x"
    306                  "(string #\\x|)")
    307                 ("\"foo|bar\"\n  ; Character to escape: \""
    308                  "\"foo\\\"|bar\""))
    309    (";"         paredit-semicolon
    310                 ("|(frob grovel)"
    311                  ";|(frob grovel)")
    312                 ("(frob |grovel)"
    313                  "(frob ;|grovel\n )")
    314                 ("(frob |grovel (bloit\n               zargh))"
    315                  "(frob ;|grovel\n (bloit\n  zargh))")
    316                 ("(frob grovel)          |"
    317                  "(frob grovel)          ;|"))
    318    ("M-;"       paredit-comment-dwim
    319                 ("(foo |bar)   ; baz"
    320                  "(foo bar)                               ; |baz")
    321                 ("(frob grovel)|"
    322                  "(frob grovel)                           ;|")
    323                 ("(zot (foo bar)\n|\n     (baz quux))"
    324                  "(zot (foo bar)\n     ;; |\n     (baz quux))")
    325                 ("(zot (foo bar) |(baz quux))"
    326                  "(zot (foo bar)\n     ;; |\n     (baz quux))")
    327                 ("|(defun hello-world ...)"
    328                  ";;; |\n(defun hello-world ...)"))
    329 
    330    (()          paredit-newline
    331                 ("(let ((n (frobbotz))) |(display (+ n 1)\nport))"
    332                  ,(concat "(let ((n (frobbotz)))"
    333                           "\n  |(display (+ n 1)"
    334                           "\n           port))")))
    335    ("RET"       paredit-RET)
    336    ("C-j"       paredit-C-j)
    337 
    338    "Deleting & Killing"
    339    (,paredit-forward-delete-keys
    340                 paredit-forward-delete
    341                 ("(quu|x \"zot\")" "(quu| \"zot\")")
    342                 ("(quux |\"zot\")"
    343                  "(quux \"|zot\")"
    344                  "(quux \"|ot\")")
    345                 ("(foo (|) bar)" "(foo | bar)")
    346                 ("|(foo bar)" "(|foo bar)"))
    347    (,paredit-backward-delete-key
    348                 paredit-backward-delete
    349                 ("(\"zot\" q|uux)" "(\"zot\" |uux)")
    350                 ("(\"zot\"| quux)"
    351                  "(\"zot|\" quux)"
    352                  "(\"zo|\" quux)")
    353                 ("(foo (|) bar)" "(foo | bar)")
    354                 ("(foo bar)|" "(foo bar|)"))
    355    ("C-d"       paredit-delete-char
    356                 ("(quu|x \"zot\")" "(quu| \"zot\")")
    357                 ("(quux |\"zot\")"
    358                  "(quux \"|zot\")"
    359                  "(quux \"|ot\")")
    360                 ("(foo (|) bar)" "(foo | bar)")
    361                 ("|(foo bar)" "(|foo bar)"))
    362    ("C-k"       paredit-kill
    363                 ("(foo bar)|     ; Useless comment!"
    364                  "(foo bar)|")
    365                 ("(|foo bar)     ; Useful comment!"
    366                  "(|)     ; Useful comment!")
    367                 ("|(foo bar)     ; Useless line!"
    368                  "|")
    369                 ("(foo \"|bar baz\"\n     quux)"
    370                  "(foo \"|\"\n     quux)"))
    371    ("M-d"       paredit-forward-kill-word
    372                 ("|(foo bar)    ; baz"
    373                  "(| bar)    ; baz"
    374                  "(|)    ; baz"
    375                  "()    ;|")
    376                 (";;;| Frobnicate\n(defun frobnicate ...)"
    377                  ";;;|\n(defun frobnicate ...)"
    378                  ";;;\n(| frobnicate ...)"))
    379    (,(concat "M-" paredit-backward-delete-key)
    380                 paredit-backward-kill-word
    381                 ("(foo bar)    ; baz\n(quux)|"
    382                  "(foo bar)    ; baz\n(|)"
    383                  "(foo bar)    ; |\n()"
    384                  "(foo |)    ; \n()"
    385                  "(|)    ; \n()"))
    386 
    387    "Movement & Navigation"
    388    ("C-M-f"     paredit-forward
    389                 ("(foo |(bar baz) quux)"
    390                  "(foo (bar baz)| quux)")
    391                 ("(foo (bar)|)"
    392                  "(foo (bar))|"))
    393    ("C-M-b"     paredit-backward
    394                 ("(foo (bar baz)| quux)"
    395                  "(foo |(bar baz) quux)")
    396                 ("(|(foo) bar)"
    397                  "|((foo) bar)"))
    398    ("C-M-u"     paredit-backward-up)
    399    ("C-M-d"     paredit-forward-down)
    400    ("C-M-p"     paredit-backward-down)  ; Built-in, these are FORWARD-
    401    ("C-M-n"     paredit-forward-up)     ; & BACKWARD-LIST, which have
    402                                         ; no need given C-M-f & C-M-b.
    403 
    404    "Depth-Changing Commands"
    405    ("M-("       paredit-wrap-round
    406                 ("(foo |bar baz)"
    407                  "(foo (|bar) baz)"))
    408    ("M-s"       paredit-splice-sexp
    409                 ("(foo (bar| baz) quux)"
    410                  "(foo bar| baz quux)"))
    411    (("M-<up>" "ESC <up>")
    412                 paredit-splice-sexp-killing-backward
    413                 ("(foo (let ((x 5)) |(sqrt n)) bar)"
    414                  "(foo |(sqrt n) bar)"))
    415    (("M-<down>" "ESC <down>")
    416                 paredit-splice-sexp-killing-forward
    417                 ("(a (b c| d e) f)"
    418                  "(a b c| f)"))
    419    ("M-r"       paredit-raise-sexp
    420                 ("(dynamic-wind in (lambda () |body) out)"
    421                  "(dynamic-wind in |body out)"
    422                  "|body"))
    423    ("M-?"       paredit-convolute-sexp
    424                 ("(let ((x 5) (y 3)) (frob |(zwonk)) (wibblethwop))"
    425                  "(frob |(let ((x 5) (y 3)) (zwonk) (wibblethwop)))"))
    426 
    427    "Barfage & Slurpage"
    428    (("C-)" "C-<right>")
    429                 paredit-forward-slurp-sexp
    430                 ("(foo (bar |baz) quux zot)"
    431                  "(foo (bar |baz quux) zot)")
    432                 ("(a b ((c| d)) e f)"
    433                  "(a b ((c| d) e) f)"))
    434    (("C-}" "C-<left>")
    435                 paredit-forward-barf-sexp
    436                 ("(foo (bar |baz quux) zot)"
    437                  "(foo (bar |baz) quux zot)"))
    438    (("C-(" "C-M-<left>" "ESC C-<left>")
    439                 paredit-backward-slurp-sexp
    440                 ("(foo bar (baz| quux) zot)"
    441                  "(foo (bar baz| quux) zot)")
    442                 ("(a b ((c| d)) e f)"
    443                  "(a (b (c| d)) e f)"))
    444    (("C-{" "C-M-<right>" "ESC C-<right>")
    445                 paredit-backward-barf-sexp
    446                 ("(foo (bar baz |quux) zot)"
    447                  "(foo bar (baz |quux) zot)"))
    448 
    449    "Miscellaneous Commands"
    450    ("M-S"       paredit-split-sexp
    451                 ("(hello| world)"
    452                  "(hello)| (world)")
    453                 ("\"Hello, |world!\""
    454                  "\"Hello, \"| \"world!\""))
    455    ("M-J"       paredit-join-sexps
    456                 ("(hello)| (world)"
    457                  "(hello| world)")
    458                 ("\"Hello, \"| \"world!\""
    459                  "\"Hello, |world!\"")
    460                 ("hello-\n|  world"
    461                  "hello-|world"))
    462    ("C-c C-M-l" paredit-recenter-on-sexp)
    463    ("M-q"       paredit-reindent-defun)
    464    ))
    465        nil)                             ; end of PROGN
    466 
    467 ;;;;; Command Examples
    468 
    469 (eval-and-compile
    470   (defmacro paredit-do-commands (vars string-case &rest body)
    471     (let ((spec     (nth 0 vars))
    472           (keys     (nth 1 vars))
    473           (fn       (nth 2 vars))
    474           (examples (nth 3 vars)))
    475       `(dolist (,spec paredit-commands)
    476          (if (stringp ,spec)
    477              ,string-case
    478            (let ((,keys (let ((k (car ,spec)))
    479                           (cond ((stringp k) (list k))
    480                                 ((listp k) k)
    481                                 (t (error "Invalid paredit command %s."
    482                                           ,spec)))))
    483                  (,fn (cadr ,spec))
    484                  (,examples (cddr ,spec)))
    485              ,@body)))))
    486 
    487   (put 'paredit-do-commands 'lisp-indent-function 2))
    488 
    489 (defun paredit-define-keys ()
    490   (paredit-do-commands (spec keys fn examples)
    491       nil       ; string case
    492     (dolist (key keys)
    493       (define-key paredit-mode-map (read-kbd-macro key) fn))))
    494 
    495 (defun paredit-function-documentation (fn)
    496   (let ((original-doc (get fn 'paredit-original-documentation))
    497         (doc (documentation fn 'function-documentation)))
    498     (or original-doc
    499         (progn (put fn 'paredit-original-documentation doc)
    500                doc))))
    501 
    502 (defun paredit-annotate-mode-with-examples ()
    503   (let ((contents
    504          (list (paredit-function-documentation 'paredit-mode))))
    505     (paredit-do-commands (spec keys fn examples)
    506         (push (concat "\n\n" spec "\n")
    507               contents)
    508       (let ((name (symbol-name fn)))
    509         (if (string-match (symbol-name 'paredit-) name)
    510             (push (concat "\n\n\\[" name "]\t" name
    511                           (if examples
    512                               (mapconcat (lambda (example)
    513                                            (concat
    514                                             "\n"
    515                                             (mapconcat 'identity
    516                                                        example
    517                                                        "\n  --->\n")
    518                                             "\n"))
    519                                          examples
    520                                          "")
    521                               "\n  (no examples)\n"))
    522                   contents))))
    523     (put 'paredit-mode 'function-documentation
    524          (apply 'concat (reverse contents))))
    525   ;; PUT returns the huge string we just constructed, which we don't
    526   ;; want it to return.
    527   nil)
    528 
    529 (defun paredit-annotate-functions-with-examples ()
    530   (paredit-do-commands (spec keys fn examples)
    531       nil       ; string case
    532     (put fn 'function-documentation
    533          (concat (paredit-function-documentation fn)
    534                  "\n\n\\<paredit-mode-map>\\[" (symbol-name fn) "]\n"
    535                  (mapconcat (lambda (example)
    536                               (concat "\n"
    537                                       (mapconcat 'identity
    538                                                  example
    539                                                  "\n  ->\n")
    540                                       "\n"))
    541                             examples
    542                             "")))))
    543 
    544 ;;;;; HTML Examples
    545 
    546 (defun paredit-insert-html-examples ()
    547   "Insert HTML for a paredit quick reference table."
    548   (interactive)
    549   (let ((insert-lines
    550          (lambda (&rest lines) (dolist (line lines) (insert line) (newline))))
    551         (initp nil))
    552     (paredit-do-commands (spec keys fn examples)
    553         (progn (if initp
    554                    (funcall insert-lines "</table>")
    555                    (setq initp t))
    556                (funcall insert-lines (concat "<h3>" spec "</h3>"))
    557                (funcall insert-lines "<table>"))
    558       (let ((name (symbol-name fn))
    559             (keys
    560              (mapconcat (lambda (key)
    561                           (concat "<tt>" (paredit-html-quote key) "</tt>"))
    562                         keys
    563                         ", ")))
    564         (funcall insert-lines "<tr>")
    565         (funcall insert-lines (concat "  <th align=\"left\">" keys "</th>"))
    566         (funcall insert-lines (concat "  <th align=\"left\">" name "</th>"))
    567         (funcall insert-lines "</tr>")
    568         (funcall insert-lines
    569                  "<tr><td colspan=\"2\"><table cellpadding=\"5\"><tr>")
    570         (dolist (example examples)
    571           (let ((prefix "<td><table border=\"1\"><tr><td><table><tr><td><pre>")
    572                 (examples
    573                  (mapconcat 'paredit-html-quote
    574                             example
    575                             (concat "</pre></td></tr>"
    576                                     "<tr><th>&darr;</th></tr>"
    577                                     "<tr><td><pre>")))
    578                 (suffix "</pre></td></tr></table></td></tr></table></td>"))
    579             (funcall insert-lines (concat prefix examples suffix))))
    580         (funcall insert-lines "</tr></table></td></tr>")))
    581     (funcall insert-lines "</table>")))
    582 
    583 (defun paredit-html-quote (string)
    584   (with-temp-buffer
    585     (dotimes (i (length string))
    586       (insert (let ((c (elt string i)))
    587                 (cond ((eq c ?\<) "&lt;")
    588                       ((eq c ?\>) "&gt;")
    589                       ((eq c ?\&) "&amp;")
    590                       ((eq c ?\') "&apos;")
    591                       ((eq c ?\") "&quot;")
    592                       (t c)))))
    593     (buffer-string)))
    594 
    595 ;;;; Delimiter Insertion
    596 
    597 (eval-and-compile
    598   (defun paredit-conc-name (&rest strings)
    599     (intern (apply 'concat strings)))
    600 
    601   (defmacro define-paredit-pair (open close name)
    602     `(progn
    603        (defun ,(paredit-conc-name "paredit-open-" name) (&optional n)
    604          ,(concat "Insert a balanced " name " pair.
    605 With a prefix argument N, put the closing " name " after N
    606   S-expressions forward.
    607 If the region is active, `transient-mark-mode' is enabled, and the
    608   region's start and end fall in the same parenthesis depth, insert a
    609   " name " pair around the region.
    610 If in a string or a comment, insert a single " name ".
    611 If in a character literal, do nothing.  This prevents changing what was
    612   in the character literal to a meaningful delimiter unintentionally.")
    613          (interactive "P")
    614          (cond ((or (paredit-in-string-p)
    615                     (paredit-in-comment-p))
    616                 (insert ,open))
    617                ((not (paredit-in-char-p))
    618                 (paredit-insert-pair n ,open ,close 'goto-char)
    619                 (save-excursion (backward-up-list) (indent-sexp)))))
    620        (defun ,(paredit-conc-name "paredit-close-" name) ()
    621          ,(concat "Move past one closing delimiter and reindent.
    622 \(Agnostic to the specific closing delimiter.)
    623 If in a string or comment, insert a single closing " name ".
    624 If in a character literal, do nothing.  This prevents changing what was
    625   in the character literal to a meaningful delimiter unintentionally.")
    626          (interactive)
    627          (paredit-move-past-close ,close))
    628        (defun ,(paredit-conc-name "paredit-close-" name "-and-newline") ()
    629          ,(concat "Move past one closing delimiter, add a newline,"
    630                   " and reindent.
    631 If there was a margin comment after the closing delimiter, preserve it
    632   on the same line.")
    633          (interactive)
    634          (paredit-move-past-close-and-newline ,close))
    635        (defun ,(paredit-conc-name "paredit-wrap-" name)
    636            (&optional argument)
    637          ,(concat "Wrap the following S-expression.
    638 See `paredit-wrap-sexp' for more details.")
    639          (interactive "P")
    640          (paredit-wrap-sexp argument ,open ,close))
    641        (add-to-list 'paredit-wrap-commands
    642                     ',(paredit-conc-name "paredit-wrap-" name)))))
    643 
    644 (defvar paredit-wrap-commands '(paredit-wrap-sexp)
    645   "List of paredit commands that wrap S-expressions.
    646 Used by `paredit-yank-pop'; for internal paredit use only.")
    647 
    648 (define-paredit-pair ?\( ?\) "round")
    649 (define-paredit-pair ?\[ ?\] "square")
    650 (define-paredit-pair ?\{ ?\} "curly")
    651 (define-paredit-pair ?\< ?\> "angled")
    652 
    653 ;;; Aliases for the old names.
    654 
    655 (defalias 'paredit-open-parenthesis 'paredit-open-round)
    656 (defalias 'paredit-close-parenthesis 'paredit-close-round)
    657 (defalias 'paredit-close-parenthesis-and-newline
    658   'paredit-close-round-and-newline)
    659 
    660 (defalias 'paredit-open-bracket 'paredit-open-square)
    661 (defalias 'paredit-close-bracket 'paredit-close-square)
    662 (defalias 'paredit-close-bracket-and-newline
    663   'paredit-close-square-and-newline)
    664 
    665 (defun paredit-move-past-close (close)
    666   (paredit-move-past-close-and close
    667     (lambda ()
    668       (paredit-blink-paren-match nil))))
    669 
    670 (defun paredit-move-past-close-and-newline (close)
    671   (paredit-move-past-close-and close
    672     (lambda ()
    673       (let ((comment.point (paredit-find-comment-on-line)))
    674         (newline)
    675         (if comment.point
    676             (save-excursion
    677               (forward-line -1)
    678               (end-of-line)
    679               (indent-to (cdr comment.point))
    680               (insert (car comment.point)))))
    681       (lisp-indent-line)
    682       (paredit-ignore-sexp-errors (indent-sexp))
    683       (paredit-blink-paren-match t))))
    684 
    685 (defun paredit-move-past-close-and (close if-moved)
    686   (if (or (paredit-in-string-p)
    687           (paredit-in-comment-p))
    688       (insert close)
    689     (if (paredit-in-char-p) (forward-char))
    690     (paredit-move-past-close-and-reindent close)
    691     (funcall if-moved)))
    692 
    693 (defun paredit-find-comment-on-line ()
    694   "Find a margin comment on the current line.
    695 Return nil if there is no such comment or if there is anything but
    696   whitespace until such a comment.
    697 If such a comment exists, delete the comment (including all leading
    698   whitespace) and return a cons whose car is the comment as a string
    699   and whose cdr is the point of the comment's initial semicolon,
    700   relative to the start of the line."
    701   (save-excursion
    702     (paredit-skip-whitespace t (point-at-eol))
    703     (and (eq ?\; (char-after))
    704          (not (eq ?\; (char-after (1+ (point)))))
    705          (not (or (paredit-in-string-p)
    706                   (paredit-in-char-p)))
    707          (let* ((start                  ;Move to before the semicolon.
    708                  (progn (backward-char) (point)))
    709                 (comment
    710                  (buffer-substring start (point-at-eol))))
    711            (paredit-skip-whitespace nil (point-at-bol))
    712            (delete-region (point) (point-at-eol))
    713            (cons comment (- start (point-at-bol)))))))
    714 
    715 (defun paredit-insert-pair (n open close forward)
    716   (let* ((regionp
    717           (and (paredit-region-active-p)
    718                (paredit-region-safe-for-insert-p)))
    719          (end
    720           (and regionp
    721                (not n)
    722                (prog1 (region-end) (goto-char (region-beginning))))))
    723     (let ((spacep (paredit-space-for-delimiter-p nil open)))
    724       (if spacep (insert " "))
    725       (insert open)
    726       (save-excursion
    727         ;; Move past the desired region.
    728         (cond (n
    729                (funcall forward
    730                         (paredit-scan-sexps-hack (point)
    731                                                  (prefix-numeric-value n))))
    732               (regionp
    733                (funcall forward (+ end (if spacep 2 1)))))
    734         ;; The string case can happen if we are inserting string
    735         ;; delimiters.  The comment case may happen by moving to the
    736         ;; end of a buffer that has a comment with no trailing newline.
    737         (if (and (not (paredit-in-string-p))
    738                  (paredit-in-comment-p))
    739             (newline))
    740         (insert close)
    741         (if (paredit-space-for-delimiter-p t close)
    742             (insert " "))))))
    743 
    744 ;++ This needs a better name...
    745 
    746 (defun paredit-scan-sexps-hack (point n)
    747   (save-excursion
    748     (goto-char point)
    749     (let ((direction (if (< 0 n) +1 -1))
    750           (magnitude (abs n))
    751           (count 0))
    752       (catch 'exit
    753         (while (< count magnitude)
    754           (let ((p
    755                  (paredit-handle-sexp-errors (scan-sexps (point) direction)
    756                    nil)))
    757             (if (not p) (throw 'exit nil))
    758             (goto-char p))
    759           (setq count (+ count 1)))))
    760     (point)))
    761 
    762 (defun paredit-region-safe-for-insert-p ()
    763   (save-excursion
    764     (let ((beginning (region-beginning))
    765           (end (region-end)))
    766       (goto-char beginning)
    767       (let* ((beginning-state (paredit-current-parse-state))
    768              (end-state
    769               (parse-partial-sexp beginning end nil nil beginning-state)))
    770         (and (=  (nth 0 beginning-state)   ; 0. depth in parens
    771                  (nth 0 end-state))
    772              (eq (nth 3 beginning-state)   ; 3. non-nil if inside a
    773                  (nth 3 end-state))        ;    string
    774              (eq (nth 4 beginning-state)   ; 4. comment status, yada
    775                  (nth 4 end-state))
    776              (eq (nth 5 beginning-state)   ; 5. t if following char
    777                  (nth 5 end-state)))))))   ;    quote
    778 
    779 (defvar paredit-space-for-delimiter-predicates nil
    780   "List of predicates for whether to put space by delimiter at point.
    781 Each predicate is a function that is is applied to two arguments, ENDP
    782   and DELIMITER, and that returns a boolean saying whether to put a
    783   space next to the delimiter -- before/after the delimiter if ENDP is
    784   false/true, respectively.
    785 If any predicate returns false, no space is inserted: every predicate
    786   has veto power.
    787 Each predicate may assume that the point is not at the beginning/end of
    788   the buffer, and that the point is preceded/followed by a word
    789   constituent, symbol constituent, string quote, or delimiter matching
    790   DELIMITER, if ENDP is false/true, respectively.
    791 Each predicate should examine only text before/after the point if ENDP is
    792   false/true, respectively.")
    793 
    794 (defun paredit-space-for-delimiter-p (endp delimiter)
    795   ;; If at the buffer limit, don't insert a space.  If there is a word,
    796   ;; symbol, other quote, or non-matching parenthesis delimiter (i.e. a
    797   ;; close when want an open the string or an open when we want to
    798   ;; close the string), do insert a space.
    799   (and (not (if endp (eobp) (bobp)))
    800        (memq (char-syntax (if endp (char-after) (char-before)))
    801              (list ?w ?_ ?\"
    802                    (let ((matching (matching-paren delimiter)))
    803                      (and matching (char-syntax matching)))
    804                    (and (not endp)
    805                         (eq ?\" (char-syntax delimiter))
    806                         ?\) )))
    807        (catch 'exit
    808          (dolist (predicate paredit-space-for-delimiter-predicates)
    809            (if (not (funcall predicate endp delimiter))
    810                (throw 'exit nil)))
    811          t)))
    812 
    813 (defun paredit-move-past-close-and-reindent (close)
    814   (let ((open (paredit-missing-close)))
    815     (if open
    816         (if (eq close (matching-paren open))
    817             (save-excursion
    818               (message "Missing closing delimiter: %c" close)
    819               (insert close))
    820             (error "Mismatched missing closing delimiter: %c ... %c"
    821                    open close))))
    822   (up-list)
    823   (if (catch 'return                    ; This CATCH returns T if it
    824         (while t                        ; should delete leading spaces
    825           (save-excursion               ; and NIL if not.
    826             (let ((before-paren (1- (point))))
    827               (back-to-indentation)
    828               (cond ((not (eq (point) before-paren))
    829                      ;; Can't call PAREDIT-DELETE-LEADING-WHITESPACE
    830                      ;; here -- we must return from SAVE-EXCURSION
    831                      ;; first.
    832                      (throw 'return t))
    833                     ((save-excursion (forward-line -1)
    834                                      (end-of-line)
    835                                      (paredit-in-comment-p))
    836                      ;; Moving the closing delimiter any further
    837                      ;; would put it into a comment, so we just
    838                      ;; indent the closing delimiter where it is and
    839                      ;; abort the loop, telling its continuation that
    840                      ;; no leading whitespace should be deleted.
    841                      (lisp-indent-line)
    842                      (throw 'return nil))
    843                     (t (delete-indentation)))))))
    844       (paredit-delete-leading-whitespace)))
    845 
    846 (defun paredit-missing-close ()
    847   (save-excursion
    848     (paredit-handle-sexp-errors (backward-up-list)
    849       (error "Not inside a list."))
    850     (let ((open (char-after)))
    851       (paredit-handle-sexp-errors (progn (forward-sexp) nil)
    852         open))))
    853 
    854 (defun paredit-delete-leading-whitespace ()
    855   ;; This assumes that we're on the closing delimiter already.
    856   (save-excursion
    857     (backward-char)
    858     (while (let ((syn (char-syntax (char-before))))
    859              (and (or (eq syn ?\ ) (eq syn ?-))     ; whitespace syntax
    860                   ;; The above line is a perfect example of why the
    861                   ;; following test is necessary.
    862                   (not (paredit-in-char-p (1- (point))))))
    863       (delete-char -1))))
    864 
    865 (defun paredit-blink-paren-match (another-line-p)
    866   (if (and blink-matching-paren
    867            (or (not show-paren-mode) another-line-p))
    868       (paredit-ignore-sexp-errors
    869         (save-excursion
    870           (backward-sexp)
    871           (forward-sexp)
    872           ;; SHOW-PAREN-MODE inhibits any blinking, so we disable it
    873           ;; locally here.
    874           (let ((show-paren-mode nil))
    875             (blink-matching-open))))))
    876 
    877 (defun paredit-doublequote (&optional n)
    878   "Insert a pair of double-quotes.
    879 With a prefix argument N, wrap the following N S-expressions in
    880   double-quotes, escaping intermediate characters if necessary.
    881 If the region is active, `transient-mark-mode' is enabled, and the
    882   region's start and end fall in the same parenthesis depth, insert a
    883   pair of double-quotes around the region, again escaping intermediate
    884   characters if necessary.
    885 Inside a comment, insert a literal double-quote.
    886 At the end of a string, move past the closing double-quote.
    887 In the middle of a string, insert a backslash-escaped double-quote.
    888 If in a character literal, do nothing.  This prevents accidentally
    889   changing a what was in the character literal to become a meaningful
    890   delimiter unintentionally."
    891   (interactive "P")
    892   (cond ((paredit-in-string-p)
    893          (if (eq (point) (- (paredit-enclosing-string-end) 1))
    894              (forward-char)             ; Just move past the closing quote.
    895            ;; Don't split a \x into an escaped backslash and a string end.
    896            (if (paredit-in-string-escape-p) (forward-char))
    897            (insert ?\\ ?\" )))
    898         ((paredit-in-comment-p)
    899          (insert ?\" ))
    900         ((not (paredit-in-char-p))
    901          (paredit-insert-pair n ?\" ?\" 'paredit-forward-for-quote))))
    902 
    903 (defun paredit-meta-doublequote (&optional n)
    904   "Move to the end of the string.
    905 If not in a string, act as `paredit-doublequote'; if not prefix argument
    906  is specified and the region is not active or `transient-mark-mode' is
    907  disabled, the default is to wrap one S-expression, however, not zero."
    908   (interactive "P")
    909   (if (not (paredit-in-string-p))
    910       (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
    911       (goto-char (paredit-enclosing-string-end))))
    912 
    913 (defun paredit-meta-doublequote-and-newline (&optional n)
    914   "Move to the end of the string, insert a newline, and indent.
    915 If not in a string, act as `paredit-doublequote'; if not prefix argument
    916  is specified and the region is not active or `transient-mark-mode' is
    917  disabled, the default is to wrap one S-expression, however, not zero."
    918   (interactive "P")
    919   (if (not (paredit-in-string-p))
    920       (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
    921       (progn (goto-char (paredit-enclosing-string-end))
    922              (newline)
    923              (lisp-indent-line)
    924              (paredit-ignore-sexp-errors (indent-sexp)))))
    925 
    926 (defun paredit-forward-for-quote (end)
    927   (let ((state (paredit-current-parse-state)))
    928     (while (< (point) end)
    929       (let ((new-state (parse-partial-sexp (point) (1+ (point))
    930                                            nil nil state)))
    931         (if (paredit-in-string-p new-state)
    932             (if (not (paredit-in-string-escape-p))
    933                 (setq state new-state)
    934               ;; Escape character: turn it into an escaped escape
    935               ;; character by appending another backslash.
    936               (insert ?\\ )
    937               ;; Now the point is after both escapes, and we want to
    938               ;; rescan from before the first one to after the second
    939               ;; one.
    940               (setq state
    941                     (parse-partial-sexp (- (point) 2) (point)
    942                                         nil nil state))
    943               ;; Advance the end point, since we just inserted a new
    944               ;; character.
    945               (setq end (1+ end)))
    946           ;; String: escape by inserting a backslash before the quote.
    947           (backward-char)
    948           (insert ?\\ )
    949           ;; The point is now between the escape and the quote, and we
    950           ;; want to rescan from before the escape to after the quote.
    951           (setq state
    952                 (parse-partial-sexp (1- (point)) (1+ (point))
    953                                     nil nil state))
    954           ;; Advance the end point for the same reason as above.
    955           (setq end (1+ end)))))))
    956 
    957 ;;;; Escape Insertion
    958 
    959 (defun paredit-backslash ()
    960   "Insert a backslash followed by a character to escape."
    961   (interactive)
    962   (cond ((paredit-in-string-p) (paredit-backslash-interactive))
    963         ((paredit-in-comment-p) (insert ?\\))
    964         ((paredit-in-char-p) (forward-char) (paredit-backslash-interactive))
    965         (t (paredit-backslash-interactive))))
    966 
    967 (defun paredit-backslash-interactive ()
    968   (insert ?\\ )
    969   ;; Read a character to insert after the backslash.  If anything
    970   ;; goes wrong -- the user hits delete (entering the rubout
    971   ;; `character'), aborts with C-g, or enters non-character input
    972   ;; -- then delete the backslash to avoid a dangling escape.
    973   (let ((delete-p t))
    974     (unwind-protect
    975         (let ((char (read-char "Character to escape: " t)))
    976           (if (not (eq char ?\^?))
    977               (progn (message "Character to escape: %c" char)
    978                      (insert char)
    979                      (setq delete-p nil))))
    980       (if delete-p
    981           (progn (message "Deleting escape.")
    982                  (delete-char -1))))))
    983 
    984 (defun paredit-newline ()
    985   "Insert a newline and indent it.
    986 This is like `newline-and-indent', but it not only indents the line
    987   that the point is on but also the S-expression following the point,
    988   if there is one.
    989 Move forward one character first if on an escaped character.
    990 If in a string, just insert a literal newline.
    991 If in a comment and if followed by invalid structure, call
    992   `indent-new-comment-line' to keep the invalid structure in a
    993   comment."
    994   (interactive)
    995   (cond ((paredit-in-string-p)
    996          (newline))
    997         ((paredit-in-comment-p)
    998          (if (paredit-region-ok-p (point) (point-at-eol))
    999              (progn (newline-and-indent)
   1000                     (paredit-ignore-sexp-errors (indent-sexp)))
   1001              (indent-new-comment-line)))
   1002         (t
   1003          (if (paredit-in-char-p)
   1004              (forward-char))
   1005          (newline-and-indent)
   1006          ;; Indent the following S-expression, but don't signal an
   1007          ;; error if there's only a closing delimiter after the point.
   1008          (paredit-ignore-sexp-errors (indent-sexp)))))
   1009 
   1010 (defun paredit-electric-indent-mode-p ()
   1011   "True if Electric Indent Mode is on, false if not.
   1012 Electric Indent Mode is generally not compatible with paredit and
   1013   users are advised to disable it, since paredit does essentially
   1014   everything it tries to do better.
   1015 However, to mitigate the negative user experience of combining
   1016  Electric Indent Mode with paredit, the default key bindings for
   1017  RET and C-j in paredit are exchanged depending on whether
   1018  Electric Indent Mode is enabled."
   1019   (and (boundp 'electric-indent-mode)
   1020        electric-indent-mode))
   1021 
   1022 (defun paredit-RET ()
   1023   "Default key binding for RET in Paredit Mode.
   1024 Normally, inserts a newline, like traditional Emacs RET.
   1025 With Electric Indent Mode enabled, inserts a newline and indents
   1026   the new line, as well as any subexpressions of it on subsequent
   1027   lines."
   1028   (interactive)
   1029   (if (paredit-electric-indent-mode-p)
   1030       (let ((electric-indent-mode nil))
   1031         (paredit-newline))
   1032     (newline)))
   1033 
   1034 (defun paredit-C-j ()
   1035   "Default key binding for C-j in Paredit Mode.
   1036 Normally, inserts a newline and indents
   1037   the new line, as well as any subexpressions of it on subsequent
   1038   lines.
   1039 With Electric Indent Mode enabled, inserts a newline, like
   1040   traditional Emacs RET."
   1041   (interactive)
   1042   (if (paredit-electric-indent-mode-p)
   1043       (let ((electric-indent-mode nil))
   1044         (newline))
   1045     (paredit-newline)))
   1046 
   1047 (defun paredit-reindent-defun (&optional argument)
   1048   "Reindent the definition that the point is on.
   1049 If the point is in a string or a comment, fill the paragraph instead,
   1050   and with a prefix argument, justify as well."
   1051   (interactive "P")
   1052   (if (or (paredit-in-string-p)
   1053           (paredit-in-comment-p))
   1054       (if (memq fill-paragraph-function '(t nil))
   1055           (lisp-fill-paragraph argument)
   1056         (funcall fill-paragraph-function argument))
   1057     (paredit-preserving-column
   1058       (save-excursion
   1059         (end-of-defun)
   1060         (beginning-of-defun)
   1061         (indent-sexp)))))
   1062 
   1063 ;;;; Comment Insertion
   1064 
   1065 (defun paredit-semicolon (&optional n)
   1066   "Insert a semicolon.
   1067 With a prefix argument N, insert N semicolons.
   1068 If in a string, do just that and nothing else.
   1069 If in a character literal, move to the beginning of the character
   1070   literal before inserting the semicolon.
   1071 If the enclosing list ends on the line after the point, break the line
   1072   after the last S-expression following the point.
   1073 If a list begins on the line after the point but ends on a different
   1074   line, break the line after the last S-expression following the point
   1075   before the list."
   1076   (interactive "p")
   1077   (if (or (paredit-in-string-p) (paredit-in-comment-p))
   1078       (insert (make-string (or n 1) ?\; ))
   1079     (if (paredit-in-char-p)
   1080         (backward-char 2))
   1081     (let ((line-break-point (paredit-semicolon-find-line-break-point)))
   1082       (if line-break-point
   1083           (paredit-semicolon-with-line-break line-break-point (or n 1))
   1084           (insert (make-string (or n 1) ?\; ))))))
   1085 
   1086 (defun paredit-semicolon-find-line-break-point ()
   1087   (and (not (eolp))                   ;Implies (not (eobp)).
   1088        (let ((eol (point-at-eol)))
   1089          (save-excursion
   1090            (catch 'exit
   1091              (while t
   1092                (let ((line-break-point (point)))
   1093                  (cond ((paredit-handle-sexp-errors (progn (forward-sexp) t)
   1094                           nil)
   1095                         ;; Successfully advanced by an S-expression.
   1096                         ;; If that S-expression started on this line
   1097                         ;; and ended on another one, break here.
   1098                         (cond ((not (eq eol (point-at-eol)))
   1099                                (throw 'exit
   1100                                       (and (save-excursion
   1101                                              (backward-sexp)
   1102                                              (eq eol (point-at-eol)))
   1103                                            line-break-point)))
   1104                               ((eobp)
   1105                                (throw 'exit nil))))
   1106                        ((save-excursion
   1107                           (paredit-skip-whitespace t (point-at-eol))
   1108                           (or (eolp) (eobp) (eq (char-after) ?\;)))
   1109                         ;; Can't move further, but there's no closing
   1110                         ;; delimiter we're about to clobber -- either
   1111                         ;; it's on the next line or we're at the end of
   1112                         ;; the buffer.  Don't break the line.
   1113                         (throw 'exit nil))
   1114                        (t
   1115                         ;; Can't move because we hit a delimiter at the
   1116                         ;; end of this line.  Break here.
   1117                         (throw 'exit line-break-point))))))))))
   1118 
   1119 (defun paredit-semicolon-with-line-break (line-break-point n)
   1120   (let ((line-break-marker (make-marker)))
   1121     (set-marker line-break-marker line-break-point)
   1122     (set-marker-insertion-type line-break-marker t)
   1123     (insert (make-string (or n 1) ?\; ))
   1124     (save-excursion
   1125       (goto-char line-break-marker)
   1126       (set-marker line-break-marker nil)
   1127       (newline)
   1128       (lisp-indent-line)
   1129       ;; This step is redundant if we are inside a list, but even if we
   1130       ;; are at the top level, we want at least to indent whatever we
   1131       ;; bumped off the line.
   1132       (paredit-ignore-sexp-errors (indent-sexp))
   1133       (paredit-indent-sexps))))
   1134 
   1135 ;;; This is all a horrible, horrible hack, primarily for GNU Emacs 21,
   1136 ;;; in which there is no `comment-or-uncomment-region'.
   1137 
   1138 (autoload 'comment-forward "newcomment")
   1139 (autoload 'comment-normalize-vars "newcomment")
   1140 (autoload 'comment-region "newcomment")
   1141 (autoload 'comment-search-forward "newcomment")
   1142 (autoload 'uncomment-region "newcomment")
   1143 
   1144 (defun paredit-initialize-comment-dwim ()
   1145   (require 'newcomment)
   1146   (if (not (fboundp 'comment-or-uncomment-region))
   1147       (defalias 'comment-or-uncomment-region
   1148         (lambda (beginning end &optional argument)
   1149           (interactive "*r\nP")
   1150           (if (save-excursion (goto-char beginning)
   1151                               (comment-forward (point-max))
   1152                               (<= end (point)))
   1153               (uncomment-region beginning end argument)
   1154               (comment-region beginning end argument)))))
   1155   (defalias 'paredit-initialize-comment-dwim 'comment-normalize-vars)
   1156   (comment-normalize-vars))
   1157 
   1158 (defvar paredit-comment-prefix-toplevel ";;; "
   1159   "String of prefix for top-level comments aligned at the left margin.")
   1160 
   1161 (defvar paredit-comment-prefix-code ";; "
   1162   "String of prefix for comments indented at the same depth as code.")
   1163 
   1164 (defvar paredit-comment-prefix-margin ";"
   1165   "String of prefix for comments on the same line as code in the margin.")
   1166 
   1167 (defun paredit-comment-dwim (&optional argument)
   1168   "Call the Lisp comment command you want (Do What I Mean).
   1169 This is like `comment-dwim', but it is specialized for Lisp editing.
   1170 If transient mark mode is enabled and the mark is active, comment or
   1171   uncomment the selected region, depending on whether it was entirely
   1172   commented not not already.
   1173 If there is already a comment on the current line, with no prefix
   1174   argument, indent to that comment; with a prefix argument, kill that
   1175   comment.
   1176 Otherwise, insert a comment appropriate for the context and ensure that
   1177   any code following the comment is moved to the next line.
   1178 At the top level, where indentation is calculated to be at column 0,
   1179   insert a triple-semicolon comment; within code, where the indentation
   1180   is calculated to be non-zero, and on the line there is either no code
   1181   at all or code after the point, insert a double-semicolon comment;
   1182   and if the point is after all code on the line, insert a single-
   1183   semicolon margin comment at `comment-column'."
   1184   (interactive "*P")
   1185   (paredit-initialize-comment-dwim)
   1186   (cond ((paredit-region-active-p)
   1187          (comment-or-uncomment-region (region-beginning)
   1188                                       (region-end)
   1189                                       argument))
   1190         ((paredit-comment-on-line-p)
   1191          (if argument
   1192              (comment-kill (if (integerp argument) argument nil))
   1193              (comment-indent)))
   1194         (t (paredit-insert-comment))))
   1195 
   1196 (defun paredit-comment-on-line-p ()
   1197   "True if there is a comment on the line following point.
   1198 This is expected to be called only in `paredit-comment-dwim'; do not
   1199   call it elsewhere."
   1200   (save-excursion
   1201     (beginning-of-line)
   1202     (let ((comment-p nil))
   1203       ;; Search forward for a comment beginning.  If there is one, set
   1204       ;; COMMENT-P to true; if not, it will be nil.
   1205       (while (progn
   1206                (setq comment-p          ;t -> no error
   1207                      (comment-search-forward (point-at-eol) t))
   1208                (and comment-p
   1209                     (or (paredit-in-string-p)
   1210                         (paredit-in-char-p (1- (point))))))
   1211         (forward-char))
   1212       comment-p)))
   1213 
   1214 (defun paredit-insert-comment ()
   1215   (let ((code-after-p
   1216          (save-excursion (paredit-skip-whitespace t (point-at-eol))
   1217                          (not (eolp))))
   1218         (code-before-p
   1219          (save-excursion (paredit-skip-whitespace nil (point-at-bol))
   1220                          (not (bolp)))))
   1221     (cond ((and (bolp)
   1222                 (let ((indent
   1223                        (let ((indent (calculate-lisp-indent)))
   1224                          (if (consp indent) (car indent) indent))))
   1225                   (and indent (zerop indent))))
   1226            ;; Top-level comment
   1227            (if code-after-p (save-excursion (newline)))
   1228            (insert paredit-comment-prefix-toplevel))
   1229           ((or code-after-p (not code-before-p))
   1230            ;; Code comment
   1231            (if code-before-p
   1232                (newline-and-indent)
   1233                (lisp-indent-line))
   1234            (insert paredit-comment-prefix-code)
   1235            (if code-after-p
   1236                (save-excursion
   1237                  (newline)
   1238                  (lisp-indent-line)
   1239                  (paredit-indent-sexps))))
   1240           (t
   1241            ;; Margin comment
   1242            (indent-to comment-column 1) ; 1 -> force one leading space
   1243            (insert paredit-comment-prefix-margin)))))
   1244 
   1245 ;;;; Character Deletion
   1246 
   1247 (defun paredit-delete-char (&optional argument)
   1248   "Delete a character forward or move forward over a delimiter.
   1249 If on an opening S-expression delimiter, move forward into the
   1250   S-expression.
   1251 If on a closing S-expression delimiter, refuse to delete unless the
   1252   S-expression is empty, in which case delete the whole S-expression.
   1253 With a numeric prefix argument N, delete N characters forward.
   1254 With a `C-u' prefix argument, simply delete a character forward,
   1255   without regard for delimiter balancing.
   1256 
   1257 Like `delete-char', ignores `delete-active-region'."
   1258   (interactive "P")
   1259   (let ((delete-active-region nil))
   1260     (paredit-forward-delete argument)))
   1261 
   1262 (defun paredit-delete-active-region-p ()
   1263   "True if the region is active and to be deleted."
   1264   (and (paredit-region-active-p)
   1265        (boundp 'delete-active-region)
   1266        (eq delete-active-region t)))
   1267 
   1268 (defun paredit-kill-active-region-p ()
   1269   "True if the region is active and to be killed."
   1270   (and (paredit-region-active-p)
   1271        (boundp 'delete-active-region)
   1272        (eq delete-active-region 'kill)))
   1273 
   1274 (defun paredit-forward-delete (&optional argument)
   1275   "Delete a character forward or move forward over a delimiter.
   1276 If on an opening S-expression delimiter, move forward into the
   1277   S-expression.
   1278 If on a closing S-expression delimiter, refuse to delete unless the
   1279   S-expression is empty, in which case delete the whole S-expression.
   1280 With a numeric prefix argument N, delete N characters forward.
   1281 With a `C-u' prefix argument, simply delete a character forward,
   1282   without regard for delimiter balancing.
   1283 
   1284 If `delete-active-region' is enabled and the mark is active and
   1285   no prefix argument is specified, act as `paredit-delete-region'
   1286   or `paredit-kill-region' as appropriate instead."
   1287   (interactive "P")
   1288   (cond ((consp argument)
   1289          (delete-char +1))
   1290         ((integerp argument)
   1291          (let ((delete-active-region nil))
   1292            (if (< argument 0)
   1293                (paredit-backward-delete argument)
   1294              (while (> argument 0)
   1295                (paredit-forward-delete)
   1296                (setq argument (- argument 1))))))
   1297         ((paredit-delete-active-region-p)
   1298          (paredit-delete-region (region-beginning) (region-end)))
   1299         ((paredit-kill-active-region-p)
   1300          (paredit-kill-region (region-beginning) (region-end)))
   1301         ((eobp)
   1302          (delete-char +1))
   1303         ((paredit-in-string-p)
   1304          (paredit-forward-delete-in-string))
   1305         ((paredit-in-comment-p)
   1306          (paredit-forward-delete-in-comment))
   1307         ((paredit-in-char-p)            ; Escape -- delete both chars.
   1308          (delete-char -1)
   1309          (delete-char +1))
   1310         ((eq (char-after) ?\\ )         ; ditto
   1311          (delete-char +2))
   1312         ((let ((syn (char-syntax (char-after))))
   1313            (or (eq syn ?\( )
   1314                (eq syn ?\" )))
   1315          (if (save-excursion
   1316                (paredit-handle-sexp-errors (progn (forward-sexp) t)
   1317                  nil))
   1318              (forward-char)
   1319            (message "Deleting spurious opening delimiter.")
   1320            (delete-char +1)))
   1321         ((and (not (paredit-in-char-p (1- (point))))
   1322               (eq (char-syntax (char-after)) ?\) )
   1323               (eq (char-before) (matching-paren (char-after))))
   1324          (delete-char -1)               ; Empty list -- delete both
   1325          (delete-char +1))              ;   delimiters.
   1326         ((eq ?\; (char-after))
   1327          (paredit-forward-delete-comment-start))
   1328         ((eq (char-syntax (char-after)) ?\) )
   1329          (if (paredit-handle-sexp-errors
   1330                  (save-excursion (forward-char) (backward-sexp) t)
   1331                nil)
   1332              (message "End of list!")
   1333              (progn
   1334                (message "Deleting spurious closing delimiter.")
   1335                (delete-char +1))))
   1336         ;; Just delete a single character, if it's not a closing
   1337         ;; delimiter.  (The character literal case is already handled
   1338         ;; by now.)
   1339         (t (delete-char +1))))
   1340 
   1341 (defun paredit-forward-delete-in-string ()
   1342   (let ((start+end (paredit-string-start+end-points)))
   1343     (cond ((not (eq (point) (cdr start+end)))
   1344            ;; If it's not the close-quote, it's safe to delete.  But
   1345            ;; first handle the case that we're in a string escape.
   1346            (cond ((paredit-in-string-escape-p)
   1347                   ;; We're right after the backslash, so backward
   1348                   ;; delete it before deleting the escaped character.
   1349                   (delete-char -1))
   1350                  ((eq (char-after) ?\\ )
   1351                   ;; If we're not in a string escape, but we are on a
   1352                   ;; backslash, it must start the escape for the next
   1353                   ;; character, so delete the backslash before deleting
   1354                   ;; the next character.
   1355                   (delete-char +1)))
   1356            (delete-char +1))
   1357           ((eq (1- (point)) (car start+end))
   1358            ;; If it is the close-quote, delete only if we're also right
   1359            ;; past the open-quote (i.e. it's empty), and then delete
   1360            ;; both quotes.  Otherwise we refuse to delete it.
   1361            (delete-char -1)
   1362            (delete-char +1)))))
   1363 
   1364 (defun paredit-check-forward-delete-in-comment ()
   1365   ;; Point is in a comment, possibly at eol.  We are about to delete
   1366   ;; some characters forward; if we are at eol, we are about to delete
   1367   ;; the line break.  Refuse to do so if if moving the next line into
   1368   ;; the comment would break structure.
   1369   (if (eolp)
   1370       (let ((next-line-start (point-at-bol 2))
   1371             (next-line-end (point-at-eol 2)))
   1372         (paredit-check-region next-line-start next-line-end))))
   1373 
   1374 (defun paredit-forward-delete-in-comment ()
   1375   (paredit-check-forward-delete-in-comment)
   1376   (delete-char +1))
   1377 
   1378 (defun paredit-forward-delete-comment-start ()
   1379   ;; Point precedes a comment start (not at eol).  Refuse to delete a
   1380   ;; comment start if the comment contains unbalanced junk.
   1381   (paredit-check-region (+ (point) 1) (point-at-eol))
   1382   (delete-char +1))
   1383 
   1384 (defun paredit-backward-delete (&optional argument)
   1385   "Delete a character backward or move backward over a delimiter.
   1386 If on a closing S-expression delimiter, move backward into the
   1387   S-expression.
   1388 If on an opening S-expression delimiter, refuse to delete unless the
   1389   S-expression is empty, in which case delete the whole S-expression.
   1390 With a numeric prefix argument N, delete N characters backward.
   1391 With a `C-u' prefix argument, simply delete a character backward,
   1392   without regard for delimiter balancing.
   1393 
   1394 If `delete-active-region' is enabled and the mark is active and
   1395   no prefix argument is specified, act as `paredit-delete-region'
   1396   or `paredit-kill-region' as appropriate instead."
   1397   (interactive "P")
   1398   (cond ((consp argument)
   1399          ;++ Should this untabify?
   1400          (delete-char -1))
   1401         ((integerp argument)
   1402          (let ((delete-active-region nil))
   1403            (if (< argument 0)
   1404                (paredit-forward-delete (- 0 argument))
   1405              (while (> argument 0)
   1406                (paredit-backward-delete)
   1407                (setq argument (- argument 1))))))
   1408         ((paredit-delete-active-region-p)
   1409          (paredit-delete-region (region-beginning) (region-end)))
   1410         ((paredit-kill-active-region-p)
   1411          (paredit-kill-region (region-beginning) (region-end)))
   1412         ((bobp)
   1413          (delete-char -1))
   1414         ((paredit-in-string-p)
   1415          (paredit-backward-delete-in-string))
   1416         ((paredit-in-comment-p)
   1417          (paredit-backward-delete-in-comment))
   1418         ((paredit-in-char-p)            ; Escape -- delete both chars.
   1419          (delete-char -1)
   1420          (delete-char +1))
   1421         ((paredit-in-char-p (1- (point)))
   1422          (delete-char -2))              ; ditto
   1423         ((let ((syn (char-syntax (char-before))))
   1424            (or (eq syn ?\) )
   1425                (eq syn ?\" )))
   1426          (if (save-excursion
   1427                (paredit-handle-sexp-errors (progn (backward-sexp) t)
   1428                  nil))
   1429              (backward-char)
   1430            (message "Deleting spurious closing delimiter.")
   1431            (delete-char -1)))
   1432         ((and (eq (char-syntax (char-before)) ?\( )
   1433               (eq (char-after) (matching-paren (char-before))))
   1434          (delete-char -1)               ; Empty list -- delete both
   1435          (delete-char +1))              ;   delimiters.
   1436         ((bolp)
   1437          (paredit-backward-delete-maybe-comment-end))
   1438         ((eq (char-syntax (char-before)) ?\( )
   1439          (if (paredit-handle-sexp-errors
   1440                  (save-excursion (backward-char) (forward-sexp) t)
   1441                nil)
   1442              (message "Beginning of list!")
   1443              (progn
   1444                (message "Deleting spurious closing delimiter.")
   1445                (delete-char -1))))
   1446         ;; Delete it, unless it's an opening delimiter.  The case of
   1447         ;; character literals is already handled by now.
   1448         (t
   1449          ;; Turn off the @#&*&!^&(%^ botch in GNU Emacs 24 that changed
   1450          ;; `backward-delete-char' and `backward-delete-char-untabify'
   1451          ;; semantically so that they delete the region in transient
   1452          ;; mark mode.
   1453          (let ((delete-active-region nil))
   1454            (backward-delete-char-untabify +1)))))
   1455 
   1456 (defun paredit-backward-delete-in-string ()
   1457   (let ((start+end (paredit-string-start+end-points)))
   1458     (cond ((not (eq (1- (point)) (car start+end)))
   1459            ;; If it's not the open-quote, it's safe to delete.
   1460            (if (paredit-in-string-escape-p)
   1461                ;; If we're on a string escape, since we're about to
   1462                ;; delete the backslash, we must first delete the
   1463                ;; escaped char.
   1464                (delete-char +1))
   1465            (delete-char -1)
   1466            (if (paredit-in-string-escape-p)
   1467                ;; If, after deleting a character, we find ourselves in
   1468                ;; a string escape, we must have deleted the escaped
   1469                ;; character, and the backslash is behind the point, so
   1470                ;; backward delete it.
   1471                (delete-char -1)))
   1472           ((eq (point) (cdr start+end))
   1473            ;; If it is the open-quote, delete only if we're also right
   1474            ;; past the close-quote (i.e. it's empty), and then delete
   1475            ;; both quotes.  Otherwise we refuse to delete it.
   1476            (delete-char -1)
   1477            (delete-char +1)))))
   1478 
   1479 (defun paredit-backward-delete-in-comment ()
   1480   ;; Point is in a comment, possibly just after the comment start.
   1481   ;; Refuse to delete a comment start if the comment contains
   1482   ;; unbalanced junk.
   1483   (if (save-excursion
   1484         (backward-char)
   1485         ;; Must call `paredit-in-string-p' before
   1486         ;; `paredit-in-comment-p'.
   1487         (not (or (paredit-in-string-p) (paredit-in-comment-p))))
   1488       (paredit-check-region (point) (point-at-eol)))
   1489   (backward-delete-char-untabify +1))
   1490 
   1491 (defun paredit-backward-delete-maybe-comment-end ()
   1492   ;; Point is at bol, possibly just after a comment end (i.e., the
   1493   ;; previous line may have had a line comment).  Refuse to delete a
   1494   ;; comment end if moving the current line into the previous line's
   1495   ;; comment would break structure.
   1496   (if (save-excursion
   1497         (backward-char)
   1498         (and (not (paredit-in-string-p)) (paredit-in-comment-p)))
   1499       (paredit-check-region (point-at-eol) (point-at-bol)))
   1500   (delete-char -1))
   1501 
   1502 ;;;; Killing
   1503 
   1504 (defun paredit-kill (&optional argument)
   1505   "Kill a line as if with `kill-line', but respecting delimiters.
   1506 In a string, act exactly as `kill-line' but do not kill past the
   1507   closing string delimiter.
   1508 On a line with no S-expressions on it starting after the point or
   1509   within a comment, act exactly as `kill-line'.
   1510 Otherwise, kill all S-expressions that start after the point.
   1511 With a `C-u' prefix argument, just do the standard `kill-line'.
   1512 With a numeric prefix argument N, do `kill-line' that many times."
   1513   (interactive "P")
   1514   (cond (argument
   1515          (kill-line (if (integerp argument) argument 1)))
   1516         ((paredit-in-string-p)
   1517          (paredit-kill-line-in-string))
   1518         ((paredit-in-comment-p)
   1519          (paredit-kill-line-in-comment))
   1520         ((save-excursion (paredit-skip-whitespace t (point-at-eol))
   1521                          (or (eolp) (eq (char-after) ?\; )))
   1522          ;** Be careful about trailing backslashes.
   1523          (if (paredit-in-char-p)
   1524              (backward-char))
   1525          (kill-line))
   1526         (t (paredit-kill-sexps-on-line))))
   1527 
   1528 (defun paredit-kill-line-in-string ()
   1529   (if (save-excursion (paredit-skip-whitespace t (point-at-eol))
   1530                       (eolp))
   1531       (kill-line)
   1532     (save-excursion
   1533       ;; Be careful not to split an escape sequence.
   1534       (if (paredit-in-string-escape-p)
   1535           (backward-char))
   1536       (kill-region (point)
   1537                    (min (point-at-eol)
   1538                         (cdr (paredit-string-start+end-points)))))))
   1539 
   1540 (defun paredit-kill-line-in-comment ()
   1541   ;; The variable `kill-whole-line' is not relevant: the point is in a
   1542   ;; comment, and hence not at the beginning of the line.
   1543   (paredit-check-forward-delete-in-comment)
   1544   (kill-line))
   1545 
   1546 (defun paredit-kill-sexps-on-line ()
   1547   (if (paredit-in-char-p)               ; Move past the \ and prefix.
   1548       (backward-char 2))                ; (# in Scheme/CL, ? in elisp)
   1549   (let ((beginning (point))
   1550         (eol (point-at-eol)))
   1551     (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
   1552       ;; If we got to the end of the list and it's on the same line,
   1553       ;; move backward past the closing delimiter before killing.  (This
   1554       ;; allows something like killing the whitespace in (    ).)
   1555       (if end-of-list-p (progn (up-list) (backward-char)))
   1556       (if kill-whole-line
   1557           (paredit-kill-sexps-on-whole-line beginning)
   1558         (kill-region beginning
   1559                      ;; If all of the S-expressions were on one line,
   1560                      ;; i.e. we're still on that line after moving past
   1561                      ;; the last one, kill the whole line, including
   1562                      ;; any comments; otherwise just kill to the end of
   1563                      ;; the last S-expression we found.  Be sure,
   1564                      ;; though, not to kill any closing parentheses.
   1565                      (if (and (not end-of-list-p)
   1566                               (eq (point-at-eol) eol))
   1567                          eol
   1568                          (point)))))))
   1569 
   1570 ;;; Please do not try to understand this code unless you have a VERY
   1571 ;;; good reason to do so.  I gave up trying to figure it out well
   1572 ;;; enough to explain it, long ago.
   1573 
   1574 (defun paredit-forward-sexps-to-kill (beginning eol)
   1575   (let ((end-of-list-p nil)
   1576         (firstp t))
   1577     ;; Move to the end of the last S-expression that started on this
   1578     ;; line, or to the closing delimiter if the last S-expression in
   1579     ;; this list is on the line.
   1580     (catch 'return
   1581       (while t
   1582         ;; This and the `kill-whole-line' business below fix a bug that
   1583         ;; inhibited any S-expression at the very end of the buffer
   1584         ;; (with no trailing newline) from being deleted.  It's a
   1585         ;; bizarre fix that I ought to document at some point, but I am
   1586         ;; too busy at the moment to do so.
   1587         (if (and kill-whole-line (eobp)) (throw 'return nil))
   1588         (save-excursion
   1589           (paredit-handle-sexp-errors (forward-sexp)
   1590             (up-list)
   1591             (setq end-of-list-p (eq (point-at-eol) eol))
   1592             (throw 'return nil))
   1593           (if (or (and (not firstp)
   1594                        (not kill-whole-line)
   1595                        (eobp))
   1596                   (paredit-handle-sexp-errors
   1597                       (progn (backward-sexp) nil)
   1598                     t)
   1599                   (not (eq (point-at-eol) eol)))
   1600               (throw 'return nil)))
   1601         (forward-sexp)
   1602         (if (and firstp
   1603                  (not kill-whole-line)
   1604                  (eobp))
   1605             (throw 'return nil))
   1606         (setq firstp nil)))
   1607     end-of-list-p))
   1608 
   1609 (defun paredit-kill-sexps-on-whole-line (beginning)
   1610   (kill-region beginning
   1611                (or (save-excursion     ; Delete trailing indentation...
   1612                      (paredit-skip-whitespace t)
   1613                      (and (not (eq (char-after) ?\; ))
   1614                           (point)))
   1615                    ;; ...or just use the point past the newline, if
   1616                    ;; we encounter a comment.
   1617                    (point-at-eol)))
   1618   (cond ((save-excursion (paredit-skip-whitespace nil (point-at-bol))
   1619                          (bolp))
   1620          ;; Nothing but indentation before the point, so indent it.
   1621          (lisp-indent-line))
   1622         ((eobp) nil)       ; Protect the CHAR-SYNTAX below against NIL.
   1623         ;; Insert a space to avoid invalid joining if necessary.
   1624         ((let ((syn-before (char-syntax (char-before)))
   1625                (syn-after  (char-syntax (char-after))))
   1626            (or (and (eq syn-before ?\) )            ; Separate opposing
   1627                     (eq syn-after  ?\( ))           ;   parentheses,
   1628                (and (eq syn-before ?\" )            ; string delimiter
   1629                     (eq syn-after  ?\" ))           ;   pairs,
   1630                (and (memq syn-before '(?_ ?w))      ; or word or symbol
   1631                     (memq syn-after  '(?_ ?w)))))   ;   constituents.
   1632          (insert " "))))
   1633 
   1634 ;;;;; Killing Words
   1635 
   1636 ;;; This is tricky and asymmetrical because backward parsing is
   1637 ;;; extraordinarily difficult or impossible, so we have to implement
   1638 ;;; killing in both directions by parsing forward.
   1639 
   1640 (defun paredit-forward-kill-word (&optional argument)
   1641   "Kill a word forward, skipping over intervening delimiters."
   1642   (interactive "p")
   1643   (let ((argument (or argument 1)))
   1644     (if (< argument 0)
   1645         (paredit-backward-kill-word (- argument))
   1646       (dotimes (i argument)
   1647         (let ((beginning (point)))
   1648           (skip-syntax-forward " -")
   1649           (let* ((parse-state (paredit-current-parse-state))
   1650                  (state (paredit-kill-word-state parse-state 'char-after)))
   1651             (while (not (or (eobp)
   1652                             (eq ?w (char-syntax (char-after)))))
   1653               (setq parse-state
   1654                     (progn (forward-char 1) (paredit-current-parse-state))
   1655                     ;; XXX Why did I comment this out?
   1656                     ;; (parse-partial-sexp (point) (1+ (point))
   1657                     ;;                     nil nil parse-state)
   1658                     )
   1659               (let* ((old-state state)
   1660                      (new-state
   1661                       (paredit-kill-word-state parse-state 'char-after)))
   1662                 (cond ((not (eq old-state new-state))
   1663                        (setq parse-state
   1664                              (paredit-kill-word-hack old-state
   1665                                                      new-state
   1666                                                      parse-state))
   1667                        (setq state
   1668                              (paredit-kill-word-state parse-state
   1669                                                       'char-after))
   1670                        (setq beginning (point)))))))
   1671           (goto-char beginning)
   1672           (kill-word 1))))))
   1673 
   1674 (defun paredit-backward-kill-word (&optional argument)
   1675   "Kill a word backward, skipping over any intervening delimiters."
   1676   (interactive "p")
   1677   (let ((argument (or argument 1)))
   1678     (if (< argument 0)
   1679         (paredit-forward-kill-word (- argument))
   1680       (dotimes (i argument)
   1681         (if (not (or (bobp)
   1682                      (eq (char-syntax (char-before)) ?w)))
   1683             (let ((end (point)))
   1684               (backward-word 1)
   1685               (forward-word 1)
   1686               (goto-char (min end (point)))
   1687               (let* ((parse-state (paredit-current-parse-state))
   1688                      (state
   1689                       (paredit-kill-word-state parse-state 'char-before)))
   1690                 (while (and (< (point) end)
   1691                             (progn
   1692                               (setq parse-state
   1693                                     (parse-partial-sexp (point) (1+ (point))
   1694                                                         nil nil parse-state))
   1695                               (or (eq state
   1696                                       (paredit-kill-word-state parse-state
   1697                                                                'char-before))
   1698                                   (progn (backward-char 1) nil)))))
   1699                 (if (and (eq state 'comment)
   1700                          (eq ?\# (char-after (point)))
   1701                          (eq ?\| (char-before (point))))
   1702                     (backward-char 1)))))
   1703         (backward-kill-word 1)))))
   1704 
   1705 ;;;;;; Word-Killing Auxiliaries
   1706 
   1707 (defun paredit-kill-word-state (parse-state adjacent-char-fn)
   1708   (cond ((paredit-in-comment-p parse-state) 'comment)
   1709         ((paredit-in-string-p  parse-state) 'string)
   1710         ((memq (char-syntax (funcall adjacent-char-fn))
   1711                '(?\( ?\) ))
   1712          'delimiter)
   1713         (t 'other)))
   1714 
   1715 ;;; This optionally advances the point past any comment delimiters that
   1716 ;;; should probably not be touched, based on the last state change and
   1717 ;;; the characters around the point.  It returns a new parse state,
   1718 ;;; starting from the PARSE-STATE parameter.
   1719 
   1720 (defun paredit-kill-word-hack (old-state new-state parse-state)
   1721   (cond ((and (not (eq old-state 'comment))
   1722               (not (eq new-state 'comment))
   1723               (not (paredit-in-string-escape-p))
   1724               (eq ?\# (char-before))
   1725               (eq ?\| (char-after)))
   1726          (forward-char 1)
   1727          (paredit-current-parse-state)
   1728 ;;          (parse-partial-sexp (point) (1+ (point))
   1729 ;;                              nil nil parse-state)
   1730          )
   1731         ((and (not (eq old-state 'comment))
   1732               (eq new-state 'comment)
   1733               (eq ?\; (char-before)))
   1734          (skip-chars-forward ";")
   1735          (paredit-current-parse-state)
   1736 ;;          (parse-partial-sexp (point) (save-excursion
   1737 ;;                                        (skip-chars-forward ";"))
   1738 ;;                              nil nil parse-state)
   1739          )
   1740         (t parse-state)))
   1741 
   1742 (defun paredit-copy-as-kill ()
   1743   "Save in the kill ring the region that `paredit-kill' would kill."
   1744   (interactive)
   1745   (cond ((paredit-in-string-p)
   1746          (paredit-copy-as-kill-in-string))
   1747         ((paredit-in-comment-p)
   1748          (copy-region-as-kill (point) (point-at-eol)))
   1749         ((save-excursion (paredit-skip-whitespace t (point-at-eol))
   1750                          (or (eolp) (eq (char-after) ?\; )))
   1751          ;** Be careful about trailing backslashes.
   1752          (save-excursion
   1753            (if (paredit-in-char-p)
   1754                (backward-char))
   1755            (copy-region-as-kill (point) (point-at-eol))))
   1756         (t (paredit-copy-sexps-as-kill))))
   1757 
   1758 (defun paredit-copy-as-kill-in-string ()
   1759   (save-excursion
   1760     (if (paredit-in-string-escape-p)
   1761         (backward-char))
   1762     (copy-region-as-kill (point)
   1763                          (min (point-at-eol)
   1764                               (cdr (paredit-string-start+end-points))))))
   1765 
   1766 (defun paredit-copy-sexps-as-kill ()
   1767   (save-excursion
   1768     (if (paredit-in-char-p)
   1769         (backward-char 2))
   1770     (let ((beginning (point))
   1771           (eol (point-at-eol)))
   1772       (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
   1773         (if end-of-list-p (progn (up-list) (backward-char)))
   1774         (copy-region-as-kill beginning
   1775                              (cond (kill-whole-line
   1776                                     (or (save-excursion
   1777                                           (paredit-skip-whitespace t)
   1778                                           (and (not (eq (char-after) ?\; ))
   1779                                                (point)))
   1780                                         (point-at-eol)))
   1781                                    ((and (not end-of-list-p)
   1782                                          (eq (point-at-eol) eol))
   1783                                     eol)
   1784                                    (t
   1785                                     (point))))))))
   1786 
   1787 ;;;; Deleting Regions
   1788 
   1789 (defun paredit-delete-region (start end)
   1790   "Delete the text between point and mark, like `delete-region'.
   1791 If that text is unbalanced, signal an error instead.
   1792 With a prefix argument, skip the balance check."
   1793   (interactive "r")
   1794   (if (and start end (not current-prefix-arg))
   1795       (paredit-check-region-for-delete start end))
   1796   (setq this-command 'delete-region)
   1797   (delete-region start end))
   1798 
   1799 (defun paredit-kill-region (start end)
   1800   "Kill the text between point and mark, like `kill-region'.
   1801 If that text is unbalanced, signal an error instead.
   1802 With a prefix argument, skip the balance check."
   1803   (interactive "r")
   1804   (if (and start end (not current-prefix-arg))
   1805       (paredit-check-region-for-delete start end))
   1806   (setq this-command 'kill-region)
   1807   (kill-region start end))
   1808 
   1809 (defun paredit-check-region-for-delete (start end)
   1810   "Signal an error deleting text between START and END is unsafe."
   1811   (save-excursion
   1812     (goto-char start)
   1813     (let* ((start-state (paredit-current-parse-state))
   1814            (end-state (parse-partial-sexp start end nil nil start-state)))
   1815       (paredit-check-region-for-delete:depth start start-state end end-state)
   1816       (paredit-check-region-for-delete:string start start-state end end-state)
   1817       (paredit-check-region-for-delete:comment start start-state end end-state)
   1818       (paredit-check-region-for-delete:char-quote start start-state
   1819                                                   end end-state))))
   1820 
   1821 (defun paredit-check-region-for-delete:depth (start start-state end end-state)
   1822   (let ((start-depth (nth 0 start-state))
   1823         (end-depth (nth 0 end-state)))
   1824     (if (not (= start-depth end-depth))
   1825         (error "Mismatched parenthesis depth: %S at start, %S at end."
   1826                start-depth
   1827                end-depth))))
   1828 
   1829 (defun paredit-check-region-for-delete:string (start start-state end end-state)
   1830   (let ((start-string-p (nth 3 start-state))
   1831         (end-string-p (nth 3 end-state)))
   1832     (if (not (eq start-string-p end-string-p))
   1833         (error "Mismatched string state: start %sin string, end %sin string."
   1834                (if start-string-p "" "not ")
   1835                (if end-string-p "" "not ")))))
   1836 
   1837 (defun paredit-check-region-for-delete:comment
   1838     (start start-state end end-state)
   1839   (let ((start-comment-state (nth 4 start-state))
   1840         (end-comment-state (nth 4 end-state)))
   1841     (if (not (or (eq start-comment-state end-comment-state)
   1842                  ;; If we are moving text into or out of a line
   1843                  ;; comment, make sure that the text is balanced.  (The
   1844                  ;; comment state may be a number, not t or nil at all,
   1845                  ;; for nestable comments, which are not handled by
   1846                  ;; this heuristic (or any of paredit, really).)
   1847                  (and (or (and (eq start-comment-state nil)
   1848                                (eq end-comment-state t))
   1849                           (and (eq start-comment-state t)
   1850                                (eq end-comment-state nil)))
   1851                       (save-excursion
   1852                         (goto-char end)
   1853                         (paredit-region-ok-p (point) (point-at-eol))))))
   1854         (error "Mismatched comment state: %s"
   1855                (cond ((and (integerp start-comment-state)
   1856                            (integerp end-comment-state))
   1857                       (format "depth %S at start, depth %S at end."
   1858                               start-comment-state
   1859                               end-comment-state))
   1860                      ((integerp start-comment-state)
   1861                       "start in nested comment, end otherwise.")
   1862                      ((integerp end-comment-state)
   1863                       "end in nested comment, start otherwise.")
   1864                      (start-comment-state
   1865                       "start in comment, end not in comment.")
   1866                      (end-comment-state
   1867                       "end in comment, start not in comment.")
   1868                      (t
   1869                       (format "start %S, end %S."
   1870                               start-comment-state
   1871                               end-comment-state)))))))
   1872 
   1873 (defun paredit-check-region-for-delete:char-quote
   1874     (start start-state end end-state)
   1875   (let ((start-char-quote (nth 5 start-state))
   1876         (end-char-quote (nth 5 end-state)))
   1877     (if (not (eq start-char-quote end-char-quote))
   1878         (let ((phrase "character quotation"))
   1879           (error "Mismatched %s: start %sin %s, end %sin %s."
   1880                  phrase
   1881                  (if start-char-quote "" "not ")
   1882                  phrase
   1883                  (if end-char-quote "" "not ")
   1884                  phrase)))))
   1885 
   1886 ;;;; Point Motion
   1887 
   1888 (eval-and-compile
   1889   (defmacro defun-motion (name bvl doc &rest body)
   1890     `(defun ,name ,bvl
   1891        ,doc
   1892        ,(xcond ((paredit-xemacs-p)
   1893                 '(interactive "_"))
   1894                ((paredit-gnu-emacs-p)
   1895                 ;++ Not sure this is sufficient for the `^'.
   1896                 (if (fboundp 'handle-shift-selection)
   1897                     '(interactive "^p")
   1898                     '(interactive "p"))))
   1899        ,@body)))
   1900 
   1901 (defun-motion paredit-forward (&optional arg)
   1902   "Move forward an S-expression, or up an S-expression forward.
   1903 If there are no more S-expressions in this one before the closing
   1904   delimiter, move past that closing delimiter; otherwise, move forward
   1905   past the S-expression following the point."
   1906   (let ((n (or arg 1)))
   1907     (cond ((< 0 n) (dotimes (i n)       (paredit-move-forward)))
   1908           ((< n 0) (dotimes (i (- n))   (paredit-move-backward))))))
   1909 
   1910 (defun-motion paredit-backward (&optional arg)
   1911   "Move backward an S-expression, or up an S-expression backward.
   1912 If there are no more S-expressions in this one before the opening
   1913   delimiter, move past that opening delimiter backward; otherwise, move
   1914   move backward past the S-expression preceding the point."
   1915   (let ((n (or arg 1)))
   1916     (cond ((< 0 n) (dotimes (i n)       (paredit-move-backward)))
   1917           ((< n 0) (dotimes (i (- n))   (paredit-move-forward))))))
   1918 
   1919 (defun paredit-move-forward ()
   1920   (cond ((paredit-in-string-p)
   1921          (let ((end (paredit-enclosing-string-end)))
   1922            ;; `forward-sexp' and `up-list' may move into the next string
   1923            ;; in the buffer.  Don't do that; move out of the current one.
   1924            (if (paredit-handle-sexp-errors
   1925                    (progn (paredit-handle-sexp-errors (forward-sexp)
   1926                             (up-list))
   1927                           (<= end (point)))
   1928                  t)
   1929                (goto-char end))))
   1930         ((paredit-in-char-p)
   1931          (forward-char))
   1932         (t
   1933          (paredit-handle-sexp-errors (forward-sexp)
   1934            (up-list)))))
   1935 
   1936 (defun paredit-move-backward ()
   1937   (cond ((paredit-in-string-p)
   1938          (let ((start (paredit-enclosing-string-start)))
   1939            (if (paredit-handle-sexp-errors
   1940                    (progn (paredit-handle-sexp-errors (backward-sexp)
   1941                             (backward-up-list))
   1942                           (<= (point) start))
   1943                  t)
   1944                (goto-char start))))
   1945         ((paredit-in-char-p)
   1946          ;++ Corner case: a buffer of `\|x'.  What to do?
   1947          (backward-char 2))
   1948         (t
   1949          (paredit-handle-sexp-errors (backward-sexp)
   1950            (backward-up-list)))))
   1951 
   1952 ;;;; Window Positioning
   1953 
   1954 (defalias 'paredit-recentre-on-sexp 'paredit-recenter-on-sexp)
   1955 
   1956 (defun paredit-recenter-on-sexp (&optional n)
   1957   "Recenter the screen on the S-expression following the point.
   1958 With a prefix argument N, encompass all N S-expressions forward."
   1959   (interactive "P")
   1960   (let* ((p (point))
   1961          (end-point (progn (forward-sexp n) (point)))
   1962          (start-point (progn (goto-char end-point) (backward-sexp n) (point))))
   1963     ;; Point is at beginning of first S-expression.
   1964     (let ((p-visible nil) (start-visible nil))
   1965       (save-excursion
   1966         (forward-line (/ (count-lines start-point end-point) 2))
   1967         (recenter)
   1968         (setq p-visible (pos-visible-in-window-p p))
   1969         (setq start-visible (pos-visible-in-window-p start-point)))
   1970       (cond ((not start-visible)
   1971              ;; Implies (not p-visible).  Put the start at the top of
   1972              ;; the screen.
   1973              (recenter 0))
   1974             (p-visible
   1975              ;; Go back to p if we can.
   1976              (goto-char p))))))
   1977 
   1978 (defun paredit-recenter-on-defun ()
   1979   "Recenter the screen on the definition at point."
   1980   (interactive)
   1981   (save-excursion
   1982     (beginning-of-defun)
   1983     (paredit-recenter-on-sexp)))
   1984 
   1985 (defun paredit-focus-on-defun ()
   1986   "Moves display to the top of the definition at point."
   1987   (interactive)
   1988   (beginning-of-defun)
   1989   (recenter 0))
   1990 
   1991 ;;;; Generalized Upward/Downward Motion
   1992 
   1993 (defun paredit-up/down (n vertical-direction)
   1994   (let ((horizontal-direction (if (< 0 n) +1 -1)))
   1995     (while (/= n 0)
   1996       (goto-char
   1997        (paredit-next-up/down-point horizontal-direction vertical-direction))
   1998       (setq n (- n horizontal-direction)))))
   1999 
   2000 (defun paredit-next-up/down-point (horizontal-direction vertical-direction)
   2001   (let ((state (paredit-current-parse-state))
   2002         (scan-lists
   2003          (lambda ()
   2004            (scan-lists (point) horizontal-direction vertical-direction))))
   2005     (cond ((paredit-in-string-p state)
   2006            (let ((start+end (paredit-string-start+end-points state)))
   2007              (if (< 0 vertical-direction)
   2008                  (if (< 0 horizontal-direction)
   2009                      (+ 1 (cdr start+end))
   2010                      (car start+end))
   2011                  ;; We could let the user try to descend into lists
   2012                  ;; within the string, but that would be asymmetric
   2013                  ;; with the up case, which rises out of the whole
   2014                  ;; string and not just out of a list within the
   2015                  ;; string, so this case will just be an error.
   2016                  (error "Can't descend further into string."))))
   2017           ((< 0 vertical-direction)
   2018            ;; When moving up, just try to rise up out of the list.
   2019            (or (funcall scan-lists)
   2020                (buffer-end horizontal-direction)))
   2021           ((< vertical-direction 0)
   2022            ;; When moving down, look for a string closer than a list,
   2023            ;; and use that if we find it.
   2024            (let* ((list-start
   2025                    (paredit-handle-sexp-errors (funcall scan-lists) nil))
   2026                   (string-start
   2027                    (paredit-find-next-string-start horizontal-direction
   2028                                                    list-start)))
   2029              (if (and string-start list-start)
   2030                  (if (< 0 horizontal-direction)
   2031                      (min string-start list-start)
   2032                      (max string-start list-start))
   2033                  (or string-start
   2034                      ;; Scan again: this is a kludgey way to report the
   2035                      ;; error if there really was one.
   2036                      (funcall scan-lists)
   2037                      (buffer-end horizontal-direction)))))
   2038           (t
   2039            (error "Vertical direction must be nonzero in `%s'."
   2040                   'paredit-up/down)))))
   2041 
   2042 (defun paredit-find-next-string-start (horizontal-direction limit)
   2043   (let ((buffer-limit-p (if (< 0 horizontal-direction) 'eobp 'bobp))
   2044         (next-char (if (< 0 horizontal-direction) 'char-after 'char-before))
   2045         (pastp (if (< 0 horizontal-direction) '> '<)))
   2046     (paredit-handle-sexp-errors
   2047         (save-excursion
   2048           (catch 'exit
   2049             (while t
   2050               (if (or (funcall buffer-limit-p)
   2051                       (and limit (funcall pastp (point) limit)))
   2052                   (throw 'exit nil))
   2053               (forward-sexp horizontal-direction)
   2054               (save-excursion
   2055                 (backward-sexp horizontal-direction)
   2056                 (if (eq ?\" (char-syntax (funcall next-char)))
   2057                     (throw 'exit (+ (point) horizontal-direction)))))))
   2058       nil)))
   2059 
   2060 (defun-motion paredit-forward-down (&optional argument)
   2061   "Move forward down into a list.
   2062 With a positive argument, move forward down that many levels.
   2063 With a negative argument, move backward down that many levels."
   2064   (paredit-up/down (or argument +1) -1))
   2065 
   2066 (defun-motion paredit-backward-up (&optional argument)
   2067   "Move backward up out of the enclosing list.
   2068 With a positive argument, move backward up that many levels.
   2069 With a negative argument, move forward up that many levels.
   2070 If in a string initially, that counts as one level."
   2071   (paredit-up/down (- 0 (or argument +1)) +1))
   2072 
   2073 (defun-motion paredit-forward-up (&optional argument)
   2074   "Move forward up out of the enclosing list.
   2075 With a positive argument, move forward up that many levels.
   2076 With a negative argument, move backward up that many levels.
   2077 If in a string initially, that counts as one level."
   2078   (paredit-up/down (or argument +1) +1))
   2079 
   2080 (defun-motion paredit-backward-down (&optional argument)
   2081   "Move backward down into a list.
   2082 With a positive argument, move backward down that many levels.
   2083 With a negative argument, move forward down that many levels."
   2084   (paredit-up/down (- 0 (or argument +1)) -1))
   2085 
   2086 ;;;; Depth-Changing Commands:  Wrapping, Splicing, & Raising
   2087 
   2088 (defun paredit-wrap-sexp (&optional argument open close)
   2089   "Wrap the following S-expression.
   2090 If a `C-u' prefix argument is given, wrap all S-expressions following
   2091   the point until the end of the buffer or of the enclosing list.
   2092 If a numeric prefix argument N is given, wrap N S-expressions.
   2093 Automatically indent the newly wrapped S-expression.
   2094 As a special case, if the point is at the end of a list, simply insert
   2095   a parenthesis pair, rather than inserting a lone opening delimiter
   2096   and then signalling an error, in the interest of preserving
   2097   structure.
   2098 By default OPEN and CLOSE are round delimiters."
   2099   (interactive "P")
   2100   (paredit-lose-if-not-in-sexp 'paredit-wrap-sexp)
   2101   (let ((open (or open ?\( ))
   2102         (close (or close ?\) )))
   2103     (paredit-handle-sexp-errors
   2104         ((lambda (n) (paredit-insert-pair n open close 'goto-char))
   2105          (cond ((integerp argument) argument)
   2106                ((consp argument) (paredit-count-sexps-forward))
   2107                ((paredit-region-active-p) nil)
   2108                (t 1)))
   2109       (insert close)
   2110       (backward-char)))
   2111   (save-excursion (backward-up-list) (indent-sexp)))
   2112 
   2113 (defun paredit-yank-pop (&optional argument)
   2114   "Replace just-yanked text with the next item in the kill ring.
   2115 If this command follows a `yank', just run `yank-pop'.
   2116 If this command follows a `paredit-wrap-sexp', or any other paredit
   2117   wrapping command (see `paredit-wrap-commands'), run `yank' and
   2118   reindent the enclosing S-expression.
   2119 If this command is repeated, run `yank-pop' and reindent the enclosing
   2120   S-expression.
   2121 
   2122 The argument is passed on to `yank' or `yank-pop'; see their
   2123   documentation for details."
   2124   (interactive "*p")
   2125   (cond ((eq last-command 'yank)
   2126          (yank-pop argument))
   2127         ((memq last-command paredit-wrap-commands)
   2128          (yank argument)
   2129          ;; `yank' futzes with `this-command'.
   2130          (setq this-command 'paredit-yank-pop)
   2131          (save-excursion (backward-up-list) (indent-sexp)))
   2132         ((eq last-command 'paredit-yank-pop)
   2133          ;; Pretend we just did a `yank', so that we can use
   2134          ;; `yank-pop' without duplicating its definition.
   2135          (setq last-command 'yank)
   2136          (yank-pop argument)
   2137          ;; Return to our original state.
   2138          (setq last-command 'paredit-yank-pop)
   2139          (setq this-command 'paredit-yank-pop)
   2140          (save-excursion (backward-up-list) (indent-sexp)))
   2141         (t (error "Last command was not a yank or a wrap: %s" last-command))))
   2142 
   2143 (defun paredit-splice-sexp (&optional argument)
   2144   "Splice the list that the point is on by removing its delimiters.
   2145 With a prefix argument as in `C-u', kill all S-expressions backward in
   2146   the current list before splicing all S-expressions forward into the
   2147   enclosing list.
   2148 With two prefix arguments as in `C-u C-u', kill all S-expressions
   2149   forward in the current list before splicing all S-expressions
   2150   backward into the enclosing list.
   2151 With a numerical prefix argument N, kill N S-expressions backward in
   2152   the current list before splicing the remaining S-expressions into the
   2153   enclosing list.  If N is negative, kill forward.
   2154 Inside a string, unescape all backslashes, or signal an error if doing
   2155   so would invalidate the buffer's structure."
   2156   (interactive "P")
   2157   (if (paredit-in-string-p)
   2158       (paredit-splice-string argument)
   2159     (if (paredit-in-comment-p)
   2160         (error "Can't splice comment."))
   2161     (paredit-handle-sexp-errors (paredit-enclosing-list-start)
   2162       (error "Can't splice top level."))
   2163     (paredit-kill-surrounding-sexps-for-splice argument)
   2164     (let ((delete-start (paredit-enclosing-list-start))
   2165           (delete-end
   2166            (let ((limit
   2167                   (save-excursion
   2168                     (paredit-ignore-sexp-errors (forward-sexp) (backward-sexp))
   2169                     (point))))
   2170              (save-excursion
   2171                (backward-up-list)
   2172                (forward-char +1)
   2173                (paredit-skip-whitespace t limit)
   2174                (point)))))
   2175       (let ((end-marker (make-marker)))
   2176         (save-excursion
   2177           (up-list)
   2178           (delete-char -1)
   2179           (set-marker end-marker (point)))
   2180         (delete-region delete-start delete-end)
   2181         (paredit-splice-reindent delete-start (marker-position end-marker))))))
   2182 
   2183 (defun paredit-splice-reindent (start end)
   2184   (paredit-preserving-column
   2185     ;; If we changed the first subform of the enclosing list, we must
   2186     ;; reindent the whole enclosing list.
   2187     (if (paredit-handle-sexp-errors
   2188             (save-excursion
   2189               (backward-up-list)
   2190               (down-list)
   2191               (paredit-ignore-sexp-errors (forward-sexp))
   2192               (< start (point)))
   2193           nil)
   2194         (save-excursion (backward-up-list) (indent-sexp))
   2195         (paredit-indent-region start end))))
   2196 
   2197 (defun paredit-kill-surrounding-sexps-for-splice (argument)
   2198   (cond ((or (paredit-in-string-p)
   2199              (paredit-in-comment-p))
   2200          (error "Invalid context for splicing S-expressions."))
   2201         ((or (not argument) (eq argument 0)) nil)
   2202         ((or (numberp argument) (eq argument '-))
   2203          ;; Kill S-expressions before/after the point by saving the
   2204          ;; point, moving across them, and killing the region.
   2205          (let* ((argument (if (eq argument '-) -1 argument))
   2206                 (saved (paredit-point-at-sexp-boundary (- argument))))
   2207            (goto-char saved)
   2208            (paredit-ignore-sexp-errors (backward-sexp argument))
   2209            (paredit-hack-kill-region saved (point))))
   2210         ((consp argument)
   2211          (let ((v (car argument)))
   2212            (if (= v 4)                  ;One `C-u'.
   2213                ;; Move backward until we hit the open paren; then
   2214                ;; kill that selected region.
   2215                (let ((end (point)))
   2216                  (paredit-ignore-sexp-errors
   2217                    (while (not (bobp))
   2218                      (backward-sexp)))
   2219                  (paredit-hack-kill-region (point) end))
   2220                ;; Move forward until we hit the close paren; then
   2221                ;; kill that selected region.
   2222                (let ((beginning (point)))
   2223                  (paredit-ignore-sexp-errors
   2224                    (while (not (eobp))
   2225                      (forward-sexp)))
   2226                  (paredit-hack-kill-region beginning (point))))))
   2227         (t (error "Bizarre prefix argument `%s'." argument))))
   2228 
   2229 (defun paredit-splice-sexp-killing-backward (&optional n)
   2230   "Splice the list the point is on by removing its delimiters, and
   2231   also kill all S-expressions before the point in the current list.
   2232 With a prefix argument N, kill only the preceding N S-expressions."
   2233   (interactive "P")
   2234   (paredit-splice-sexp (if n
   2235                            (prefix-numeric-value n)
   2236                            '(4))))
   2237 
   2238 (defun paredit-splice-sexp-killing-forward (&optional n)
   2239   "Splice the list the point is on by removing its delimiters, and
   2240   also kill all S-expressions after the point in the current list.
   2241 With a prefix argument N, kill only the following N S-expressions."
   2242   (interactive "P")
   2243   (paredit-splice-sexp (if n
   2244                            (- (prefix-numeric-value n))
   2245                            '(16))))
   2246 
   2247 (defun paredit-raise-sexp (&optional argument)
   2248   "Raise the following S-expression in a tree, deleting its siblings.
   2249 With a prefix argument N, raise the following N S-expressions.  If N
   2250   is negative, raise the preceding N S-expressions.
   2251 If the point is on an S-expression, such as a string or a symbol, not
   2252   between them, that S-expression is considered to follow the point."
   2253   (interactive "P")
   2254   (save-excursion
   2255     ;; Select the S-expressions we want to raise in a buffer substring.
   2256     (let* ((bound
   2257             (if (and (not argument) (paredit-region-active-p))
   2258                 (progn (if (< (mark) (point))
   2259                            (paredit-check-region (mark) (point))
   2260                            (paredit-check-region (point) (mark)))
   2261                        (mark))
   2262               (cond ((paredit-in-string-p)
   2263                      (goto-char (car (paredit-string-start+end-points))))
   2264                     ((paredit-in-char-p)
   2265                      (backward-sexp))
   2266                     ((paredit-in-comment-p)
   2267                      (error "No S-expression to raise in comment.")))
   2268               (scan-sexps (point) (prefix-numeric-value argument))))
   2269            (sexps
   2270             (if (< bound (point))
   2271                 (buffer-substring bound (paredit-point-at-sexp-end))
   2272                 (buffer-substring (paredit-point-at-sexp-start) bound))))
   2273       ;; Move up to the list we're raising those S-expressions out of and
   2274       ;; delete it.
   2275       (backward-up-list)
   2276       (delete-region (point) (scan-sexps (point) 1))
   2277       (let* ((indent-start (point))
   2278              (indent-end (save-excursion (insert sexps) (point))))
   2279         ;; If the expression spans multiple lines, its indentation is
   2280         ;; probably broken, so reindent it -- but don't reindent
   2281         ;; anything that we didn't touch outside the expression.
   2282         ;;
   2283         ;; XXX What if the *column* of the starting point was preserved
   2284         ;; too?  Should we avoid reindenting in that case?
   2285         (if (not (eq (save-excursion (goto-char indent-start) (point-at-eol))
   2286                      (save-excursion (goto-char indent-end) (point-at-eol))))
   2287             (indent-region indent-start indent-end nil))))))
   2288 
   2289 ;;; The effects of convolution on the surrounding whitespace are pretty
   2290 ;;; random.  If you have better suggestions, please let me know.
   2291 
   2292 (defun paredit-convolute-sexp (&optional n)
   2293   "Convolute S-expressions.
   2294 Save the S-expressions preceding point and delete them.
   2295 Splice the S-expressions following point.
   2296 Wrap the enclosing list in a new list prefixed by the saved text.
   2297 With a prefix argument N, move up N lists before wrapping."
   2298   (interactive "p")
   2299   (paredit-lose-if-not-in-sexp 'paredit-convolute-sexp)
   2300   ;; Make sure we can move up before destroying anything.
   2301   (save-excursion (backward-up-list n) (backward-up-list))
   2302   (let (open close)                     ;++ Is this a good idea?
   2303     (let ((prefix
   2304            (let ((end (point)))
   2305              (paredit-ignore-sexp-errors
   2306                (while (not (bobp)) (backward-sexp)))
   2307              (prog1 (buffer-substring (point) end)
   2308                (backward-up-list)
   2309                (save-excursion (forward-sexp)
   2310                                (setq close (char-before))
   2311                                (delete-char -1))
   2312                (setq open (char-after))
   2313                (delete-region (point) end)
   2314                ;; I'm not sure this makes sense...
   2315                (if (not (eolp)) (just-one-space))))))
   2316       (backward-up-list n)
   2317       (paredit-insert-pair 1 open close 'goto-char)
   2318       (insert prefix)
   2319       ;; I'm not sure this makes sense either...
   2320       (if (not (eolp)) (just-one-space))
   2321       (save-excursion
   2322         (backward-up-list)
   2323         (paredit-ignore-sexp-errors (indent-sexp))))))
   2324 
   2325 (defun paredit-splice-string (argument)
   2326   (let ((original-point (point))
   2327         (start+end (paredit-string-start+end-points)))
   2328     (let ((start (car start+end))
   2329           (end (cdr start+end)))
   2330       ;; START and END both lie before the respective quote
   2331       ;; characters, which we want to delete; thus we increment START
   2332       ;; by one to extract the string, and we increment END by one to
   2333       ;; delete the string.
   2334       (let* ((escaped-string
   2335               (cond ((not (consp argument))
   2336                      (buffer-substring (1+ start) end))
   2337                     ((= 4 (car argument))
   2338                      (buffer-substring original-point end))
   2339                     (t
   2340                      (buffer-substring (1+ start) original-point))))
   2341              (unescaped-string
   2342               (paredit-unescape-string escaped-string)))
   2343         (if (not unescaped-string)
   2344             (error "Unspliceable string.")
   2345           (save-excursion
   2346             (goto-char start)
   2347             (delete-region start (1+ end))
   2348             (insert unescaped-string))
   2349           (if (not (and (consp argument)
   2350                         (= 4 (car argument))))
   2351               (goto-char (- original-point 1))))))))
   2352 
   2353 (defun paredit-unescape-string (string)
   2354   (with-temp-buffer
   2355     (insert string)
   2356     (goto-char (point-min))
   2357     (while (and (not (eobp))
   2358                 ;; nil -> no bound; t -> no errors.
   2359                 (search-forward "\\" nil t))
   2360       (delete-char -1)
   2361       (forward-char))
   2362     (paredit-handle-sexp-errors
   2363         (progn (scan-sexps (point-min) (point-max))
   2364                (buffer-string))
   2365       nil)))
   2366 
   2367 ;;;; Slurpage & Barfage
   2368 
   2369 (defun paredit-forward-slurp-sexp (&optional argument)
   2370   "Add the S-expression following the current list into that list
   2371   by moving the closing delimiter.
   2372 Automatically reindent the newly slurped S-expression with respect to
   2373   its new enclosing form.
   2374 If in a string, move the opening double-quote forward by one
   2375   S-expression and escape any intervening characters as necessary,
   2376   without altering any indentation or formatting."
   2377   (interactive "P")
   2378   (save-excursion
   2379     (cond ((paredit-in-comment-p)
   2380            (error "Invalid context for slurping S-expressions."))
   2381           ((numberp argument)
   2382            (if (< argument 0)
   2383                (paredit-forward-barf-sexp (- 0 argument))
   2384                (while (< 0 argument)
   2385                  (paredit-forward-slurp-sexp)
   2386                  (setq argument (- argument 1)))))
   2387           ((paredit-in-string-p)
   2388            ;; If there is anything to slurp into the string, take that.
   2389            ;; Otherwise, try to slurp into the enclosing list.
   2390            (if (save-excursion
   2391                  (goto-char (paredit-enclosing-string-end))
   2392                  (paredit-handle-sexp-errors (progn (forward-sexp) nil)
   2393                    t))
   2394                (progn
   2395                  (goto-char (paredit-enclosing-string-end))
   2396                  (paredit-forward-slurp-into-list argument))
   2397                (paredit-forward-slurp-into-string argument)))
   2398           (t
   2399            (paredit-forward-slurp-into-list argument)))))
   2400 
   2401 (defun paredit-forward-slurp-into-list (&optional argument)
   2402   (let ((nestedp nil))
   2403     (save-excursion
   2404       (up-list)                            ; Up to the end of the list to
   2405       (let ((close (char-before)))         ;   save and delete the closing
   2406         (delete-char -1)                   ;   delimiter.
   2407         (let ((start (point)))
   2408           (catch 'return                   ; Go to the end of the desired
   2409             (while t                       ;   S-expression, going up a
   2410               (paredit-handle-sexp-errors  ;   list if it's not in this,
   2411                   (progn (forward-sexp)
   2412                          (if argument
   2413                              (paredit-ignore-sexp-errors
   2414                                (while (not (eobp))
   2415                                  (forward-sexp))))
   2416                          (throw 'return nil))
   2417                 (setq nestedp t)
   2418                 (up-list)
   2419                 (setq close                ; adjusting for mixed
   2420                       (prog1 (char-before) ;   delimiters as necessary,
   2421                         (delete-char -1)
   2422                         (insert close))))))
   2423           (insert close)                   ;  to insert that delimiter.
   2424           (indent-region start (point) nil))))
   2425     (if (and (not nestedp)
   2426              (eq (save-excursion (paredit-skip-whitespace nil) (point))
   2427                  (save-excursion (backward-up-list) (forward-char) (point)))
   2428              (eq (save-excursion (forward-sexp) (backward-sexp) (point))
   2429                  (save-excursion (paredit-skip-whitespace t) (point))))
   2430         (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
   2431                        (save-excursion (paredit-skip-whitespace t) (point))))))
   2432 
   2433 (defun paredit-forward-slurp-into-string (&optional argument)
   2434   (let ((start (paredit-enclosing-string-start))
   2435         (end (paredit-enclosing-string-end)))
   2436     (goto-char end)
   2437     ;; Signal any errors that we might get first, before mucking with
   2438     ;; the buffer's contents.
   2439     (save-excursion (forward-sexp))
   2440     (let ((close (char-before)))
   2441       ;; Skip intervening whitespace if we're slurping into an empty
   2442       ;; string.  XXX What about nonempty strings?
   2443       (if (and (= (+ start 2) end)
   2444                (eq (save-excursion (paredit-skip-whitespace t) (point))
   2445                    (save-excursion (forward-sexp) (backward-sexp) (point))))
   2446           (delete-region (- (point) 1)
   2447                          (save-excursion (paredit-skip-whitespace t) (point)))
   2448           (delete-char -1))
   2449       (paredit-forward-for-quote
   2450        (save-excursion
   2451          (forward-sexp)
   2452          (if argument
   2453              (while (paredit-handle-sexp-errors (progn (forward-sexp) t) nil)))
   2454          (point)))
   2455       (insert close))))
   2456 
   2457 (defun paredit-forward-barf-sexp (&optional argument)
   2458   "Remove the last S-expression in the current list from that list
   2459   by moving the closing delimiter.
   2460 Automatically reindent the newly barfed S-expression with respect to
   2461   its new enclosing form."
   2462   (interactive "P")
   2463   (paredit-lose-if-not-in-sexp 'paredit-forward-barf-sexp)
   2464   (if (and (numberp argument) (< argument 0))
   2465       (paredit-forward-slurp-sexp (- 0 argument))
   2466     (let ((start (point)) (end nil))
   2467       (save-excursion
   2468         (up-list)                       ; Up to the end of the list to
   2469         (let ((close (char-before)))    ;   save and delete the closing
   2470           (delete-char -1)              ;   delimiter.
   2471           (setq end (point))
   2472           (paredit-ignore-sexp-errors   ; Go back to where we want to
   2473             (if (or (not argument)      ;   insert the delimiter.
   2474                     (numberp argument))
   2475                 (backward-sexp argument)
   2476                 (while (paredit-handle-sexp-errors
   2477                            (save-excursion (backward-sexp) (<= start (point)))
   2478                          nil)
   2479                   (backward-sexp))))
   2480           (paredit-skip-whitespace nil) ; Skip leading whitespace.
   2481           (cond ((bobp)
   2482                  ;++ We'll have deleted the close, but there's no open.
   2483                  ;++ Is that OK?
   2484                  (error "Barfing all subexpressions with no open-paren?"))
   2485                 ((paredit-in-comment-p) ; Don't put the close-paren in
   2486                  (newline)))            ;   a comment.
   2487           (insert close))
   2488         ;; Reindent all of the newly barfed S-expressions.  Start at the
   2489         ;; start of the first barfed S-expression, not at the close we
   2490         ;; just inserted.
   2491         (forward-sexp)
   2492         (backward-sexp)
   2493         (if (or (not argument) (numberp argument))
   2494             (paredit-forward-and-indent argument)
   2495             (indent-region (point) end))))))
   2496 
   2497 (defun paredit-backward-slurp-sexp (&optional argument)
   2498   "Add the S-expression preceding the current list into that list
   2499   by moving the closing delimiter.
   2500 Automatically reindent the whole form into which new S-expression was
   2501   slurped.
   2502 If in a string, move the opening double-quote backward by one
   2503   S-expression and escape any intervening characters as necessary,
   2504   without altering any indentation or formatting."
   2505   (interactive "P")
   2506   (save-excursion
   2507     (cond ((paredit-in-comment-p)
   2508            (error "Invalid context for slurping S-expressions."))
   2509           ((numberp argument)
   2510            (if (< argument 0)
   2511                (paredit-backward-barf-sexp (- 0 argument))
   2512                (while (< 0 argument)
   2513                  (paredit-backward-slurp-sexp)
   2514                  (setq argument (- argument 1)))))
   2515           ((paredit-in-string-p)
   2516            ;; If there is anything to slurp into the string, take that.
   2517            ;; Otherwise, try to slurp into the enclosing list.
   2518            (if (save-excursion
   2519                  (goto-char (paredit-enclosing-string-start))
   2520                  (paredit-handle-sexp-errors (progn (backward-sexp) nil)
   2521                    t))
   2522                (progn
   2523                  (goto-char (paredit-enclosing-string-start))
   2524                  (paredit-backward-slurp-into-list argument))
   2525                (paredit-backward-slurp-into-string argument)))
   2526           (t
   2527            (paredit-backward-slurp-into-list argument)))))
   2528 
   2529 (defun paredit-backward-slurp-into-list (&optional argument)
   2530   (let ((nestedp nil))
   2531     (save-excursion
   2532       (backward-up-list)
   2533       (let ((open (char-after)))
   2534         (delete-char +1)
   2535         (catch 'return
   2536           (while t
   2537             (paredit-handle-sexp-errors
   2538                 (progn (backward-sexp)
   2539                        (if argument
   2540                            (paredit-ignore-sexp-errors
   2541                              (while (not (bobp))
   2542                                (backward-sexp))))
   2543                        (throw 'return nil))
   2544               (setq nestedp t)
   2545               (backward-up-list)
   2546               (setq open
   2547                     (prog1 (char-after)
   2548                       (save-excursion (insert open) (delete-char +1)))))))
   2549         (insert open))
   2550       ;; Reindent the line at the beginning of wherever we inserted the
   2551       ;; opening delimiter, and then indent the whole S-expression.
   2552       (backward-up-list)
   2553       (lisp-indent-line)
   2554       (indent-sexp))
   2555     ;; If we slurped into an empty list, don't leave dangling space:
   2556     ;; (foo |).
   2557     (if (and (not nestedp)
   2558              (eq (save-excursion (paredit-skip-whitespace nil) (point))
   2559                  (save-excursion (backward-sexp) (forward-sexp) (point)))
   2560              (eq (save-excursion (up-list) (backward-char) (point))
   2561                  (save-excursion (paredit-skip-whitespace t) (point))))
   2562         (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
   2563                        (save-excursion (paredit-skip-whitespace t) (point))))))
   2564 
   2565 (defun paredit-backward-slurp-into-string (&optional argument)
   2566   (let ((start (paredit-enclosing-string-start))
   2567         (end (paredit-enclosing-string-end)))
   2568     (goto-char start)
   2569     ;; Signal any errors that we might get first, before mucking with
   2570     ;; the buffer's contents.
   2571     (save-excursion (backward-sexp))
   2572     (let ((open (char-after))
   2573           (target (point)))
   2574       ;; Skip intervening whitespace if we're slurping into an empty
   2575       ;; string.  XXX What about nonempty strings?
   2576       (if (and (= (+ start 2) end)
   2577                (eq (save-excursion (paredit-skip-whitespace nil) (point))
   2578                    (save-excursion (backward-sexp) (forward-sexp) (point))))
   2579           (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
   2580                          (+ (point) 1))
   2581           (delete-char +1))
   2582       (backward-sexp)
   2583       (if argument
   2584           (paredit-ignore-sexp-errors
   2585             (while (not (bobp))
   2586               (backward-sexp))))
   2587       (insert open)
   2588       (paredit-forward-for-quote target))))
   2589 
   2590 (defun paredit-backward-barf-sexp (&optional argument)
   2591   "Remove the first S-expression in the current list from that list
   2592   by moving the closing delimiter.
   2593 Automatically reindent the barfed S-expression and the form from which
   2594   it was barfed."
   2595   (interactive "P")
   2596   (paredit-lose-if-not-in-sexp 'paredit-backward-barf-sexp)
   2597   (if (and (numberp argument) (< argument 0))
   2598       (paredit-backward-slurp-sexp (- 0 argument))
   2599     (let ((end (make-marker)))
   2600       (set-marker end (point))
   2601       (save-excursion
   2602         (backward-up-list)
   2603         (let ((open (char-after)))
   2604           (delete-char +1)
   2605           (paredit-ignore-sexp-errors
   2606             (paredit-forward-and-indent
   2607              (if (or (not argument) (numberp argument))
   2608                  argument
   2609                  (let ((n 0))
   2610                    (save-excursion
   2611                      (while (paredit-handle-sexp-errors
   2612                                 (save-excursion
   2613                                   (forward-sexp)
   2614                                   (<= (point) end))
   2615                               nil)
   2616                        (forward-sexp)
   2617                        (setq n (+ n 1))))
   2618                    n))))
   2619           (while (progn (paredit-skip-whitespace t) (eq (char-after) ?\; ))
   2620             (forward-line 1))
   2621           (if (eobp)
   2622               ;++ We'll have deleted the close, but there's no open.
   2623               ;++ Is that OK?
   2624               (error "Barfing all subexpressions with no close-paren?"))
   2625           ;** Don't use `insert' here.  Consider, e.g., barfing from
   2626           ;**   (foo|)
   2627           ;** and how `save-excursion' works.
   2628           (insert-before-markers open))
   2629         (backward-up-list)
   2630         (lisp-indent-line)
   2631         (indent-sexp)))))
   2632 
   2633 ;;;; Splitting & Joining
   2634 
   2635 (defun paredit-split-sexp ()
   2636   "Split the list or string the point is on into two."
   2637   (interactive)
   2638   (cond ((paredit-in-string-p)
   2639          (insert "\"")
   2640          (save-excursion (insert " \"")))
   2641         ((or (paredit-in-comment-p)
   2642              (paredit-in-char-p))
   2643          (error "Invalid context for splitting S-expression."))
   2644         (t
   2645          (let ((open (save-excursion (backward-up-list) (char-after)))
   2646                (close (save-excursion (up-list) (char-before))))
   2647            (delete-horizontal-space)
   2648            (insert close)
   2649            (save-excursion
   2650              (insert ?\ )
   2651              (insert open)
   2652              (backward-char)
   2653              (indent-sexp))))))
   2654 
   2655 (defun paredit-join-sexps ()
   2656   "Join the S-expressions adjacent on either side of the point.
   2657 Both must be lists, strings, or atoms; error if there is a mismatch."
   2658   (interactive)
   2659   (cond ((paredit-in-comment-p) (error "Can't join S-expressions in comment."))
   2660         ((paredit-in-string-p) (error "Nothing to join in a string."))
   2661         ((paredit-in-char-p) (error "Can't join characters.")))
   2662   (let ((left-point (paredit-point-at-sexp-end))
   2663         (right-point (paredit-point-at-sexp-start)))
   2664     (let ((left-char (char-before left-point))
   2665           (right-char (char-after right-point)))
   2666       (let ((left-syntax (char-syntax left-char))
   2667             (right-syntax (char-syntax right-char)))
   2668         (cond ((< right-point left-point)
   2669                (error "Can't join a datum with itself."))
   2670               ((and (eq left-syntax ?\) )
   2671                     (eq right-syntax ?\( )
   2672                     (eq left-char (matching-paren right-char))
   2673                     (eq right-char (matching-paren left-char)))
   2674                (paredit-join-lists-internal left-point right-point)
   2675                (paredit-preserving-column
   2676                  (save-excursion
   2677                    (backward-up-list)
   2678                    (indent-sexp))))
   2679               ((and (eq left-syntax ?\" )
   2680                     (eq right-syntax ?\" ))
   2681                ;; Delete any intermediate formatting.
   2682                (delete-region (1- left-point) (1+ right-point)))
   2683               ((and (memq left-syntax '(?w ?_)) ; Word or symbol
   2684                     (memq right-syntax '(?w ?_)))
   2685                (delete-region left-point right-point))
   2686               (t (error "Mismatched S-expressions to join.")))))))
   2687 
   2688 (defun paredit-join-lists-internal (left-point right-point)
   2689   (save-excursion
   2690     ;; Leave intermediate formatting alone.
   2691     (goto-char right-point)
   2692     (delete-char +1)
   2693     (goto-char left-point)
   2694     (delete-char -1)
   2695     ;; Kludge: Add an extra space in several conditions.
   2696     (if (or
   2697          ;; (foo)| ;x\n(bar) => (foo | ;x\nbar), not (foo|  ;x\nbar).
   2698          (and (not (eolp))
   2699               (save-excursion
   2700                 (paredit-skip-whitespace t (point-at-eol))
   2701                 (eq (char-after) ?\;)))
   2702          ;; (foo)|(bar) => (foo| bar), not (foo|bar).
   2703          (and (= left-point right-point)
   2704               (not (or (eq ?\  (char-syntax (char-before)))
   2705                        (eq ?\  (char-syntax (char-after)))))))
   2706         (insert ?\  ))))
   2707 
   2708 ;++ How ought paredit-join to handle comments intervening symbols or strings?
   2709 ;++ Idea:
   2710 ;++
   2711 ;++   "foo"   |        ;bar
   2712 ;++   "baz"      ;quux
   2713 ;++
   2714 ;++ =>
   2715 ;++
   2716 ;++   "foo|baz"       ;bar
   2717 ;++              ;quux
   2718 ;++
   2719 ;++ The point should stay where it is relative to the comments, and the
   2720 ;++ the comments' columns should all be preserved, perhaps.  Hmmmm...
   2721 ;++ What about this?
   2722 ;++
   2723 ;++   "foo"           ;bar
   2724 ;++       |           ;baz
   2725 ;++   "quux"          ;zot
   2726 
   2727 ;++ Should rename:
   2728 ;++     paredit-point-at-sexp-start     -> paredit-start-of-sexp-after-point
   2729 ;++     paredit-point-at-sexp-end       -> paredit-end-of-sexp-before-point
   2730 
   2731 ;;;; Variations on the Lurid Theme
   2732 
   2733 ;;; I haven't the imagination to concoct clever names for these.
   2734 
   2735 (defun paredit-add-to-previous-list ()
   2736   "Add the S-expression following point to the list preceding point."
   2737   (interactive)
   2738   (paredit-lose-if-not-in-sexp 'paredit-add-to-previous-list)
   2739   (save-excursion
   2740     (down-list -1)                      ;++ backward-down-list...
   2741     (paredit-forward-slurp-sexp)))
   2742 
   2743 (defun paredit-add-to-next-list ()
   2744   "Add the S-expression preceding point to the list following point.
   2745 If no S-expression precedes point, move up the tree until one does."
   2746   (interactive)
   2747   (paredit-lose-if-not-in-sexp 'paredit-add-to-next-list)
   2748   (save-excursion
   2749     (down-list)
   2750     (paredit-backward-slurp-sexp)))
   2751 
   2752 (defun paredit-join-with-previous-list ()
   2753   "Join the list the point is on with the previous list in the buffer."
   2754   (interactive)
   2755   (paredit-lose-if-not-in-sexp 'paredit-join-with-previous-list)
   2756   (save-excursion
   2757     (while (paredit-handle-sexp-errors (save-excursion (backward-sexp) nil)
   2758              (backward-up-list)
   2759              t))
   2760     (paredit-join-sexps)))
   2761 
   2762 (defun paredit-join-with-next-list ()
   2763   "Join the list the point is on with the next list in the buffer."
   2764   (interactive)
   2765   (paredit-lose-if-not-in-sexp 'paredit-join-with-next-list)
   2766   (save-excursion
   2767     (while (paredit-handle-sexp-errors (save-excursion (forward-sexp) nil)
   2768              (up-list)
   2769              t))
   2770     (paredit-join-sexps)))
   2771 
   2772 ;;;; Utilities
   2773 
   2774 (defun paredit-in-string-escape-p ()
   2775   "True if the point is on a character escape of a string.
   2776 This is true only if the character is preceded by an odd number of
   2777   backslashes.
   2778 This assumes that `paredit-in-string-p' has already returned true."
   2779   (let ((oddp nil))
   2780     (save-excursion
   2781       (while (eq (char-before) ?\\ )
   2782         (setq oddp (not oddp))
   2783         (backward-char)))
   2784     oddp))
   2785 
   2786 (defun paredit-in-char-p (&optional position)
   2787   "True if point is on a character escape outside a string."
   2788   (save-excursion
   2789     (goto-char (or position (point)))
   2790     (paredit-in-string-escape-p)))
   2791 
   2792 (defun paredit-skip-whitespace (trailing-p &optional limit)
   2793   "Skip past any whitespace, or until the point LIMIT is reached.
   2794 If TRAILING-P is nil, skip leading whitespace; otherwise, skip trailing
   2795   whitespace."
   2796   (funcall (if trailing-p 'skip-chars-forward 'skip-chars-backward)
   2797            " \t\n"  ; This should skip using the syntax table, but LF
   2798            limit))    ; is a comment end, not newline, in Lisp mode.
   2799 
   2800 (defalias 'paredit-region-active-p
   2801   (xcond ((paredit-xemacs-p) 'region-active-p)
   2802          ((paredit-gnu-emacs-p)
   2803           (lambda ()
   2804             (and mark-active transient-mark-mode)))))
   2805 
   2806 (defun paredit-hack-kill-region (start end)
   2807   "Kill the region between START and END.
   2808 Do not append to any current kill, and
   2809  do not let the next kill append to this one."
   2810   (interactive "r")                     ;Eh, why not?
   2811   ;; KILL-REGION sets THIS-COMMAND to tell the next kill that the last
   2812   ;; command was a kill.  It also checks LAST-COMMAND to see whether it
   2813   ;; should append.  If we bind these locally, any modifications to
   2814   ;; THIS-COMMAND will be masked, and it will not see LAST-COMMAND to
   2815   ;; indicate that it should append.
   2816   (let ((this-command nil)
   2817         (last-command nil))
   2818     (kill-region start end)))
   2819 
   2820 ;;;;; Reindentation utilities
   2821 
   2822 ;++ Should `paredit-indent-sexps' and `paredit-forward-and-indent' use
   2823 ;++ `paredit-indent-region' rather than `indent-region'?
   2824 
   2825 (defun paredit-indent-sexps ()
   2826   "If in a list, indent all following S-expressions in the list."
   2827   (let* ((start (point))
   2828          (end (paredit-handle-sexp-errors (progn (up-list) (point)) nil)))
   2829     (if end
   2830         (indent-region start end nil))))
   2831 
   2832 (defun paredit-forward-and-indent (&optional n)
   2833   "Move forward by N S-expressions, indenting them with `indent-region'."
   2834   (let ((start (point)))
   2835     (forward-sexp n)
   2836     (indent-region start (point) nil)))
   2837 
   2838 (defun paredit-indent-region (start end)
   2839   "Indent the region from START to END.
   2840 Don't reindent the line starting at START, however."
   2841   (if (not (<= start end))
   2842       (error "Incorrectly related points: %S, %S" start end))
   2843   (save-excursion
   2844     (goto-char start)
   2845     (let ((bol (point-at-bol)))
   2846       ;; Skip all S-expressions that end on the starting line, but
   2847       ;; don't go past `end'.
   2848       (if (and (save-excursion (goto-char end) (not (eq bol (point-at-bol))))
   2849                (paredit-handle-sexp-errors
   2850                    (catch 'exit
   2851                      (while t
   2852                        (save-excursion
   2853                          (forward-sexp)
   2854                          (if (not (eq bol (point-at-bol)))
   2855                              (throw 'exit t))
   2856                          (if (not (< (point) end))
   2857                              (throw 'exit nil)))
   2858                        (forward-sexp)))
   2859                  nil))
   2860           (progn
   2861             ;; Point is still on the same line, but precedes an
   2862             ;; S-expression that ends on a different line.
   2863             (if (not (eq bol (point-at-bol)))
   2864                 (error "Internal error -- we moved forward a line!"))
   2865             (goto-char (+ 1 (point-at-eol)))
   2866             (if (not (<= (point) end))
   2867                 (error "Internal error -- we frobnitzed the garfnut!"))
   2868             (indent-region (point) end nil))))))
   2869 
   2870 ;;;;; S-expression Parsing Utilities
   2871 
   2872 ;++ These routines redundantly traverse S-expressions a great deal.
   2873 ;++ If performance issues arise, this whole section will probably have
   2874 ;++ to be refactored to preserve the state longer, like paredit.scm
   2875 ;++ does, rather than to traverse the definition N times for every key
   2876 ;++ stroke as it presently does.
   2877 
   2878 (defun paredit-current-parse-state ()
   2879   "Return parse state of point from beginning of defun."
   2880   (let ((point (point)))
   2881     (beginning-of-defun)
   2882     ;; Calling PARSE-PARTIAL-SEXP will advance the point to its second
   2883     ;; argument (unless parsing stops due to an error, but we assume it
   2884     ;; won't in paredit-mode).
   2885     (parse-partial-sexp (point) point)))
   2886 
   2887 (defun paredit-in-string-p (&optional state)
   2888   "True if the parse state is within a double-quote-delimited string.
   2889 If no parse state is supplied, compute one from the beginning of the
   2890   defun to the point."
   2891   ;; 3. non-nil if inside a string (the terminator character, really)
   2892   (and (nth 3 (or state (paredit-current-parse-state)))
   2893        t))
   2894 
   2895 (defun paredit-string-start+end-points (&optional state)
   2896   "Return a cons of the points of open and close quotes of the string.
   2897 The string is determined from the parse state STATE, or the parse state
   2898   from the beginning of the defun to the point.
   2899 This assumes that `paredit-in-string-p' has already returned true, i.e.
   2900   that the point is already within a string."
   2901   (save-excursion
   2902     ;; 8. character address of start of comment or string; nil if not
   2903     ;;    in one
   2904     (let ((start (nth 8 (or state (paredit-current-parse-state)))))
   2905       (goto-char start)
   2906       (forward-sexp 1)
   2907       (cons start (1- (point))))))
   2908 
   2909 (defun paredit-enclosing-string-start ()
   2910   (car (paredit-string-start+end-points)))
   2911 
   2912 (defun paredit-enclosing-string-end ()
   2913   (+ 1 (cdr (paredit-string-start+end-points))))
   2914 
   2915 (defun paredit-enclosing-list-start ()
   2916   (save-excursion
   2917     (backward-up-list)
   2918     (point)))
   2919 
   2920 (defun paredit-enclosing-list-end ()
   2921   (save-excursion
   2922     (up-list)
   2923     (point)))
   2924 
   2925 (defun paredit-in-comment-p (&optional state)
   2926   "True if parse state STATE is within a comment.
   2927 If no parse state is supplied, compute one from the beginning of the
   2928   defun to the point."
   2929   ;; 4. nil if outside a comment, t if inside a non-nestable comment,
   2930   ;;    else an integer (the current comment nesting)
   2931   (and (nth 4 (or state (paredit-current-parse-state)))
   2932        t))
   2933 
   2934 (defun paredit-prefix-numeric-value (argument)
   2935   ;++ Kludgerific.
   2936   (cond ((integerp argument) argument)
   2937         ((eq argument '-) -1)
   2938         ((consp argument)
   2939          (cond ((equal argument '(4)) (paredit-count-sexps-forward))   ;C-u
   2940                ((equal argument '(16)) (paredit-count-sexps-backward)) ;C-u C-u
   2941                (t (error "Invalid prefix argument: %S" argument))))
   2942         ((paredit-region-active-p)
   2943          (save-excursion
   2944            (save-restriction
   2945              (narrow-to-region (region-beginning) (region-end))
   2946              (cond ((= (point) (point-min)) (paredit-count-sexps-forward))
   2947                    ((= (point) (point-max)) (paredit-count-sexps-backward))
   2948                    (t
   2949                     (error "Point %S is not start or end of region: %S..%S"
   2950                            (point) (region-beginning) (region-end)))))))
   2951         (t 1)))
   2952 
   2953 (defun paredit-count-sexps-forward ()
   2954   (save-excursion
   2955     (let ((n 0) (p nil))                ;hurk
   2956       (paredit-ignore-sexp-errors
   2957         (while (setq p (scan-sexps (point) +1))
   2958           (goto-char p)
   2959           (setq n (+ n 1))))
   2960       n)))
   2961 
   2962 (defun paredit-count-sexps-backward ()
   2963   (save-excursion
   2964     (let ((n 0) (p nil))                ;hurk
   2965       (paredit-ignore-sexp-errors
   2966         (while (setq p (scan-sexps (point) -1))
   2967           (goto-char p)
   2968           (setq n (+ n 1))))
   2969       n)))
   2970 
   2971 (defun paredit-point-at-sexp-boundary (n)
   2972   (cond ((< n 0) (paredit-point-at-sexp-start))
   2973         ((= n 0) (point))
   2974         ((> n 0) (paredit-point-at-sexp-end))))
   2975 
   2976 (defun paredit-point-at-sexp-start ()
   2977   (save-excursion
   2978     (forward-sexp)
   2979     (backward-sexp)
   2980     (point)))
   2981 
   2982 (defun paredit-point-at-sexp-end ()
   2983   (save-excursion
   2984     (backward-sexp)
   2985     (forward-sexp)
   2986     (point)))
   2987 
   2988 (defun paredit-lose-if-not-in-sexp (command)
   2989   (if (or (paredit-in-string-p)
   2990           (paredit-in-comment-p)
   2991           (paredit-in-char-p))
   2992       (error "Invalid context for command `%s'." command)))
   2993 
   2994 (defun paredit-check-region (start end)
   2995   "Signal an error if text between `start' and `end' is unbalanced."
   2996   ;; `narrow-to-region' will move the point, so avoid calling it if we
   2997   ;; don't need to.  We don't want to use `save-excursion' because we
   2998   ;; want the point to move if `check-parens' reports an error.
   2999   (if (not (paredit-region-ok-p start end))
   3000       (save-restriction
   3001         (narrow-to-region start end)
   3002         (check-parens))))
   3003 
   3004 (defun paredit-region-ok-p (start end)
   3005   "Return true iff the region between `start' and `end' is balanced.
   3006 This is independent of context -- it doesn't check what state the
   3007   text at `start' is in."
   3008   (save-excursion
   3009     (paredit-handle-sexp-errors
   3010         (progn
   3011           (save-restriction
   3012             (narrow-to-region start end)
   3013             (scan-sexps (point-min) (point-max)))
   3014           t)
   3015       nil)))
   3016 
   3017 (defun paredit-current-column ()
   3018   ;; Like current-column, but respects field boundaries in interactive
   3019   ;; modes like ielm.  For use only with paredit-restore-column, which
   3020   ;; works relative to point-at-bol.
   3021   (- (point) (point-at-bol)))
   3022 
   3023 (defun paredit-current-indentation ()
   3024   (save-excursion
   3025     (back-to-indentation)
   3026     (paredit-current-column)))
   3027 
   3028 (defun paredit-restore-column (column indentation)
   3029   ;; Preserve the point's position either in the indentation or in the
   3030   ;; code: if on code, move with the code; if in indentation, leave it
   3031   ;; in the indentation, either where it was (if still on indentation)
   3032   ;; or at the end of the indentation (if the code moved far enough
   3033   ;; left).
   3034   (let ((indentation* (paredit-current-indentation)))
   3035     (goto-char
   3036      (+ (point-at-bol)
   3037         (cond ((not (< column indentation))
   3038                (+ column (- indentation* indentation)))
   3039               ((<= indentation* column) indentation*)
   3040               (t column))))))
   3041 
   3042 ;;;; Initialization
   3043 
   3044 (paredit-define-keys)
   3045 (paredit-annotate-mode-with-examples)
   3046 (paredit-annotate-functions-with-examples)
   3047 
   3048 (provide 'paredit)
   3049 
   3050 ;;; Local Variables:
   3051 ;;; outline-regexp: "\n;;;;+"
   3052 ;;; End:
   3053 
   3054 ;;; paredit.el ends here