changelog shortlog graph tags branches files raw help

Mercurial > infra > home / changeset: elisp

changeset 24: e74bcdf93260
parent 19: ca703415cc62
child 25: 9b588a7e55d3
child 26: bfdea02d0d0a
child 29: 614d9cfe96a2
author: Richard Westhaver <ellis@rwest.io>
date: Wed, 29 May 2024 11:41:20 -0400
files: .emacs.d/ellis.el .emacs.d/lib/paredit.el .emacs.d/paredit.el
description: elisp
     1.1--- a/.emacs.d/ellis.el	Tue May 21 22:20:59 2024 -0400
     1.2+++ b/.emacs.d/ellis.el	Wed May 29 11:41:20 2024 -0400
     1.3@@ -283,5 +283,8 @@
     1.4   (add-hook 'dired-mode-hook #'all-the-icons-dired-mode)
     1.5   (add-hook 'ibuffer-mode-hook #'all-the-icons-ibuffer-mode))
     1.6 
     1.7+;; strangerdanger
     1.8+(setq slime-enable-evaluate-in-emacs t)
     1.9+
    1.10 (provide 'ellis)
    1.11 ;;; ellis.el ends here
     2.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2+++ b/.emacs.d/lib/paredit.el	Wed May 29 11:41:20 2024 -0400
     2.3@@ -0,0 +1,3098 @@
     2.4+;;; paredit.el --- minor mode for editing parentheses  -*- Mode: Emacs-Lisp -*-
     2.5+
     2.6+;; Copyright (C) 2005--2023 Taylor R. Campbell
     2.7+
     2.8+;; Author: Taylor R. Campbell <campbell@paredit.org>
     2.9+;; Version: 27beta
    2.10+;; Created: 2005-07-31
    2.11+;; Keywords: lisp
    2.12+;; URL: https://paredit.org
    2.13+
    2.14+;; Paredit is free software: you can redistribute it and/or modify it
    2.15+;; under the terms of the GNU General Public License as published by
    2.16+;; the Free Software Foundation, either version 3 of the License, or
    2.17+;; (at your option) any later version.
    2.18+;;
    2.19+;; Paredit is distributed in the hope that it will be useful, but
    2.20+;; WITHOUT ANY WARRANTY; without even the implied warranty of
    2.21+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.22+;; GNU General Public License for more details.
    2.23+;;
    2.24+;; You should have received a copy of the GNU General Public License
    2.25+;; along with paredit.  If not, see <http://www.gnu.org/licenses/>.
    2.26+
    2.27+;;; Paredit - https://paredit.org
    2.28+;;;
    2.29+;;; Latest release: https://paredit.org/paredit.el
    2.30+;;; Current development version: https://paredit.org/paredit-beta.el
    2.31+;;; Release notes: https://paredit.org/NEWS
    2.32+
    2.33+;;; Commentary:
    2.34+
    2.35+;; Paredit keeps your parentheses balanced while editing.  Paredit Mode
    2.36+;; binds keys like `(', `)', and `"' to insert or delete parentheses
    2.37+;; and string quotes in balanced pairs as you're editing without
    2.38+;; getting in your way, augments editing keys like `C-k' to handle
    2.39+;; balanced expressions, and provides advanced commands for editing
    2.40+;; balanced expressions like splicing and joining while judiciously
    2.41+;; keeping the code you're working on indented.
    2.42+
    2.43+;;; Install paredit by placing `paredit.el' in `/path/to/elisp', a
    2.44+;;; directory of your choice, and adding to your .emacs file:
    2.45+;;;
    2.46+;;;   (add-to-list 'load-path "/path/to/elisp")
    2.47+;;;   (autoload 'enable-paredit-mode "paredit"
    2.48+;;;     "Turn on pseudo-structural editing of Lisp code."
    2.49+;;;     t)
    2.50+;;;
    2.51+;;; Start Paredit Mode on the fly with `M-x enable-paredit-mode RET',
    2.52+;;; or always enable it in a major mode `M' (e.g., `lisp') with:
    2.53+;;;
    2.54+;;;   (add-hook 'M-mode-hook 'enable-paredit-mode)
    2.55+;;;
    2.56+;;; Customize paredit using `eval-after-load':
    2.57+;;;
    2.58+;;;   (eval-after-load 'paredit
    2.59+;;;     '(progn
    2.60+;;;        (define-key paredit-mode-map (kbd "ESC M-A-C-s-)")
    2.61+;;;          'paredit-dwim)))
    2.62+;;;
    2.63+;;; Send questions, bug reports, comments, feature suggestions, &c.,
    2.64+;;; via email to the author's surname at paredit.org.
    2.65+;;;
    2.66+;;; Paredit should run in GNU Emacs 21 or later and XEmacs 21.5.28 or
    2.67+;;; later.
    2.68+
    2.69+;;; The paredit minor mode, Paredit Mode, binds common character keys,
    2.70+;;; such as `(', `)', `"', and `\', to commands that carefully insert
    2.71+;;; S-expression structures in the buffer:
    2.72+;;;
    2.73+;;;   ( inserts `()', leaving the point in the middle;
    2.74+;;;   ) moves the point over the next closing delimiter;
    2.75+;;;   " inserts `""' if outside a string, or inserts an escaped
    2.76+;;;      double-quote if in the middle of a string, or moves over the
    2.77+;;;      closing double-quote if at the end of a string; and
    2.78+;;;   \ prompts for the character to escape, to avoid inserting lone
    2.79+;;;      backslashes that may break structure.
    2.80+;;;
    2.81+;;; In comments, these keys insert themselves.  If necessary, you can
    2.82+;;; insert these characters literally outside comments by pressing
    2.83+;;; `C-q' before these keys, in case a mistake has broken the
    2.84+;;; structure.
    2.85+;;;
    2.86+;;; These key bindings are designed so that when typing new code in
    2.87+;;; Paredit Mode, you can generally type exactly the same sequence of
    2.88+;;; keys you would have typed without Paredit Mode.
    2.89+;;;
    2.90+;;; Paredit Mode also binds common editing keys, such as `DEL', `C-d',
    2.91+;;; and `C-k', to commands that respect S-expression structures in the
    2.92+;;; buffer:
    2.93+;;;
    2.94+;;;   DEL deletes the previous character, unless it is a delimiter: DEL
    2.95+;;;        will move the point backward over a closing delimiter, and
    2.96+;;;        will delete a delimiter pair together if between an open and
    2.97+;;;        closing delimiter;
    2.98+;;;
    2.99+;;;   C-d deletes the next character in much the same manner; and
   2.100+;;;
   2.101+;;;   C-k kills all S-expressions that begin anywhere between the point
   2.102+;;;        and the end of the line or the closing delimiter of the
   2.103+;;;        enclosing list, whichever is first.
   2.104+;;;
   2.105+;;; If necessary, you can delete a character, kill a line, &c.,
   2.106+;;; irrespective of S-expression structure, by pressing `C-u' before
   2.107+;;; these keys, in case a mistake has broken the structure.
   2.108+;;;
   2.109+;;; Finally, Paredit Mode binds some keys to complex S-expression
   2.110+;;; editing operations.  For example, `C-<right>' makes the enclosing
   2.111+;;; list slurp up an S-expression to its right (here `|' denotes the
   2.112+;;; point):
   2.113+;;;
   2.114+;;;   (foo (bar | baz) quux)  C-<right>  (foo (bar | baz quux))
   2.115+;;;
   2.116+;;; Note: Paredit Mode is not compatible with Electric Indent Mode.
   2.117+;;; Use one or the other, not both.  If you want RET to auto-indent and
   2.118+;;; C-j to just insert newline in Paredit Mode, simply rebind the keys
   2.119+;;; with the following fragment in your .emacs file:
   2.120+;;;
   2.121+;;;     (eval-after-load 'paredit
   2.122+;;;       '(progn
   2.123+;;;          (define-key paredit-mode-map (kbd "RET") 'paredit-newline)
   2.124+;;;          (define-key paredit-mode-map (kbd "C-j") nil)))
   2.125+;;;
   2.126+;;; Some paredit commands automatically reindent code.  When they do,
   2.127+;;; they try to indent as locally as possible, to avoid interfering
   2.128+;;; with any indentation you might have manually written.  Only the
   2.129+;;; advanced S-expression manipulation commands automatically reindent,
   2.130+;;; and only the forms that they immediately operated upon (and their
   2.131+;;; subforms).
   2.132+;;;
   2.133+;;; This code is written for clarity, not efficiency.  It frequently
   2.134+;;; walks over S-expressions redundantly.  If you have problems with
   2.135+;;; the time it takes to execute some of the commands, let me know.
   2.136+
   2.137+;;; This assumes Unix-style LF line endings.
   2.138+
   2.139+(defconst paredit-version 27)
   2.140+(defconst paredit-beta-p t)
   2.141+
   2.142+(eval-and-compile
   2.143+
   2.144+  (defun paredit-xemacs-p ()
   2.145+    ;; No idea where I got this definition from.  Edward O'Connor
   2.146+    ;; (hober in #emacs) suggested the current definition.
   2.147+    ;;   (and (boundp 'running-xemacs)
   2.148+    ;;        running-xemacs)
   2.149+    (featurep 'xemacs))
   2.150+
   2.151+  (defun paredit-gnu-emacs-p ()
   2.152+    ;++ This could probably be improved.
   2.153+    (not (paredit-xemacs-p)))
   2.154+
   2.155+  (defmacro xcond (&rest clauses)
   2.156+    "Exhaustive COND.
   2.157+Signal an error if no clause matches."
   2.158+    `(cond ,@clauses
   2.159+           (t (error "XCOND lost."))))
   2.160+
   2.161+  (defalias 'paredit-warn (if (fboundp 'warn) 'warn 'message))
   2.162+
   2.163+  (defvar paredit-sexp-error-type
   2.164+    (with-temp-buffer
   2.165+      (insert "(")
   2.166+      (condition-case condition
   2.167+          (backward-sexp)
   2.168+        (error (if (eq (car condition) 'error)
   2.169+                   (paredit-warn "%s%s%s%s%s"
   2.170+                                 "Paredit is unable to discriminate"
   2.171+                                 " S-expression parse errors from"
   2.172+                                 " other errors. "
   2.173+                                 " This may cause obscure problems. "
   2.174+                                 " Please upgrade Emacs."))
   2.175+               (car condition)))))
   2.176+
   2.177+  (defmacro paredit-handle-sexp-errors (body &rest handler)
   2.178+    `(condition-case ()
   2.179+         ,body
   2.180+       (,paredit-sexp-error-type ,@handler)))
   2.181+
   2.182+  (put 'paredit-handle-sexp-errors 'lisp-indent-function 1)
   2.183+
   2.184+  (defmacro paredit-ignore-sexp-errors (&rest body)
   2.185+    `(paredit-handle-sexp-errors (progn ,@body)
   2.186+       nil))
   2.187+
   2.188+  (put 'paredit-ignore-sexp-errors 'lisp-indent-function 0)
   2.189+
   2.190+  (defmacro paredit-preserving-column (&rest body)
   2.191+    "Evaluate BODY and restore point to former column, relative to code.
   2.192+Assumes BODY will change only indentation.
   2.193+If point was on code, it moves with the code.
   2.194+If point was on indentation, it stays in indentation."
   2.195+    (let ((column (make-symbol "column"))
   2.196+          (indentation (make-symbol "indentation")))
   2.197+      `(let ((,column (paredit-current-column))
   2.198+             (,indentation (paredit-current-indentation)))
   2.199+         (let ((value (progn ,@body)))
   2.200+           (paredit-restore-column ,column ,indentation)
   2.201+           value))))
   2.202+
   2.203+  (put 'paredit-preserving-column 'lisp-indent-function 0)
   2.204+
   2.205+  nil)
   2.206+
   2.207+;;;; Minor Mode Definition
   2.208+
   2.209+(defvar paredit-lighter " Paredit"
   2.210+  "Mode line lighter Paredit Mode.")
   2.211+
   2.212+(defvar paredit-mode-map (make-sparse-keymap)
   2.213+  "Keymap for the paredit minor mode.")
   2.214+
   2.215+(defvar paredit-override-check-parens-function
   2.216+  (lambda (condition) (declare ignore condition) nil)
   2.217+  "Function to tell whether unbalanced text should inhibit Paredit Mode.")
   2.218+
   2.219+;;;###autoload
   2.220+(define-minor-mode paredit-mode
   2.221+  "Minor mode for pseudo-structurally editing Lisp code.
   2.222+With a prefix argument, enable Paredit Mode even if there are
   2.223+  unbalanced parentheses in the buffer.
   2.224+Paredit behaves badly if parentheses are unbalanced, so exercise
   2.225+  caution when forcing Paredit Mode to be enabled, and consider
   2.226+  fixing unbalanced parentheses instead.
   2.227+\\<paredit-mode-map>"
   2.228+  :lighter paredit-lighter
   2.229+  ;; Setting `paredit-mode' to false here aborts enabling Paredit Mode.
   2.230+  (if (and paredit-mode
   2.231+           (not current-prefix-arg))
   2.232+      (condition-case condition
   2.233+          (check-parens)
   2.234+        (error
   2.235+         (if (not (funcall paredit-override-check-parens-function condition))
   2.236+             (progn (setq paredit-mode nil)
   2.237+                    (signal (car condition) (cdr condition))))))))
   2.238+
   2.239+(defun paredit-override-check-parens-interactively (condition)
   2.240+  (y-or-n-p (format "Enable Paredit Mode despite condition %S? " condition)))
   2.241+
   2.242+;;;###autoload
   2.243+(defun enable-paredit-mode ()
   2.244+  "Turn on pseudo-structural editing of Lisp code."
   2.245+  (interactive)
   2.246+  (paredit-mode +1))
   2.247+
   2.248+(defun disable-paredit-mode ()
   2.249+  "Turn off pseudo-structural editing of Lisp code."
   2.250+  (interactive)
   2.251+  (paredit-mode -1))
   2.252+
   2.253+(defvar paredit-backward-delete-key
   2.254+  (xcond ((paredit-xemacs-p)    "BS")
   2.255+         ((paredit-gnu-emacs-p) "DEL")))
   2.256+
   2.257+(defvar paredit-forward-delete-keys
   2.258+  (xcond ((paredit-xemacs-p)    '("DEL"))
   2.259+         ((paredit-gnu-emacs-p) '("<delete>" "<deletechar>"))))
   2.260+
   2.261+;;;; Paredit Keys
   2.262+
   2.263+;;; Separating the definition and initialization of this variable
   2.264+;;; simplifies the development of paredit, since re-evaluating DEFVAR
   2.265+;;; forms doesn't actually do anything.
   2.266+
   2.267+(defvar paredit-commands nil
   2.268+  "List of paredit commands with their keys and examples.")
   2.269+
   2.270+;;; Each specifier is of the form:
   2.271+;;;   (key[s] function (example-input example-output) ...)
   2.272+;;; where key[s] is either a single string suitable for passing to KBD
   2.273+;;; or a list of such strings.  Entries in this list may also just be
   2.274+;;; strings, in which case they are headings for the next entries.
   2.275+
   2.276+(progn (setq paredit-commands
   2.277+ `(
   2.278+   "Basic Insertion Commands"
   2.279+   ("("         paredit-open-round
   2.280+                ("(a b |c d)"
   2.281+                 "(a b (|) c d)")
   2.282+                ("(foo \"bar |baz\" quux)"
   2.283+                 "(foo \"bar (|baz\" quux)"))
   2.284+   (")"         paredit-close-round
   2.285+                ("(a b |c   )" "(a b c)|")
   2.286+                ("; Hello,| world!"
   2.287+                 "; Hello,)| world!"))
   2.288+   ("M-)"       paredit-close-round-and-newline
   2.289+                ("(defun f (x|  ))"
   2.290+                 "(defun f (x)\n  |)")
   2.291+                ("; (Foo.|"
   2.292+                 "; (Foo.)|"))
   2.293+   ("["         paredit-open-square
   2.294+                ("(a b |c d)"
   2.295+                 "(a b [|] c d)")
   2.296+                ("(foo \"bar |baz\" quux)"
   2.297+                 "(foo \"bar [|baz\" quux)"))
   2.298+   ("]"         paredit-close-square
   2.299+                ("(define-key keymap [frob|  ] 'frobnicate)"
   2.300+                 "(define-key keymap [frob]| 'frobnicate)")
   2.301+                ("; [Bar.|"
   2.302+                 "; [Bar.]|"))
   2.303+
   2.304+   ("\""        paredit-doublequote
   2.305+                ("(frob grovel |full lexical)"
   2.306+                 "(frob grovel \"|\" full lexical)"
   2.307+                 "(frob grovel \"\"| full lexical)")
   2.308+                ("(foo \"bar |baz\" quux)"
   2.309+                 "(foo \"bar \\\"|baz\" quux)")
   2.310+                ("(frob grovel)   ; full |lexical"
   2.311+                 "(frob grovel)   ; full \"|lexical"))
   2.312+   ("M-\""      paredit-meta-doublequote
   2.313+                ("(foo \"bar |baz\" quux)"
   2.314+                 "(foo \"bar baz\"| quux)")
   2.315+                ("(foo |(bar #\\x \"baz \\\\ quux\") zot)"
   2.316+                 ,(concat "(foo \"|(bar #\\\\x \\\"baz \\\\"
   2.317+                          "\\\\ quux\\\")\" zot)")))
   2.318+   ("\\"        paredit-backslash
   2.319+                ("(string #|)\n  ; Character to escape: x"
   2.320+                 "(string #\\x|)")
   2.321+                ("\"foo|bar\"\n  ; Character to escape: \""
   2.322+                 "\"foo\\\"|bar\""))
   2.323+   (";"         paredit-semicolon
   2.324+                ("|(frob grovel)"
   2.325+                 ";|(frob grovel)")
   2.326+                ("(frob |grovel)"
   2.327+                 "(frob ;|grovel\n )")
   2.328+                ("(frob |grovel (bloit\n               zargh))"
   2.329+                 "(frob ;|grovel\n (bloit\n  zargh))")
   2.330+                ("(frob grovel)          |"
   2.331+                 "(frob grovel)          ;|"))
   2.332+   ("M-;"       paredit-comment-dwim
   2.333+                ("(foo |bar)   ; baz"
   2.334+                 "(foo bar)                               ; |baz")
   2.335+                ("(frob grovel)|"
   2.336+                 "(frob grovel)                           ;|")
   2.337+                ("(zot (foo bar)\n|\n     (baz quux))"
   2.338+                 "(zot (foo bar)\n     ;; |\n     (baz quux))")
   2.339+                ("(zot (foo bar) |(baz quux))"
   2.340+                 "(zot (foo bar)\n     ;; |\n     (baz quux))")
   2.341+                ("|(defun hello-world ...)"
   2.342+                 ";;; |\n(defun hello-world ...)"))
   2.343+
   2.344+   (()          paredit-newline
   2.345+                ("(let ((n (frobbotz))) |(display (+ n 1)\nport))"
   2.346+                 ,(concat "(let ((n (frobbotz)))"
   2.347+                          "\n  |(display (+ n 1)"
   2.348+                          "\n           port))")))
   2.349+   ("RET"       paredit-RET)
   2.350+   ("C-j"       paredit-C-j)
   2.351+
   2.352+   "Deleting & Killing"
   2.353+   (,paredit-forward-delete-keys
   2.354+                paredit-forward-delete
   2.355+                ("(quu|x \"zot\")" "(quu| \"zot\")")
   2.356+                ("(quux |\"zot\")"
   2.357+                 "(quux \"|zot\")"
   2.358+                 "(quux \"|ot\")")
   2.359+                ("(foo (|) bar)" "(foo | bar)")
   2.360+                ("|(foo bar)" "(|foo bar)"))
   2.361+   (,paredit-backward-delete-key
   2.362+                paredit-backward-delete
   2.363+                ("(\"zot\" q|uux)" "(\"zot\" |uux)")
   2.364+                ("(\"zot\"| quux)"
   2.365+                 "(\"zot|\" quux)"
   2.366+                 "(\"zo|\" quux)")
   2.367+                ("(foo (|) bar)" "(foo | bar)")
   2.368+                ("(foo bar)|" "(foo bar|)"))
   2.369+   ("C-d"       paredit-delete-char
   2.370+                ("(quu|x \"zot\")" "(quu| \"zot\")")
   2.371+                ("(quux |\"zot\")"
   2.372+                 "(quux \"|zot\")"
   2.373+                 "(quux \"|ot\")")
   2.374+                ("(foo (|) bar)" "(foo | bar)")
   2.375+                ("|(foo bar)" "(|foo bar)"))
   2.376+   ("C-k"       paredit-kill
   2.377+                ("(foo bar)|     ; Useless comment!"
   2.378+                 "(foo bar)|")
   2.379+                ("(|foo bar)     ; Useful comment!"
   2.380+                 "(|)     ; Useful comment!")
   2.381+                ("|(foo bar)     ; Useless line!"
   2.382+                 "|")
   2.383+                ("(foo \"|bar baz\"\n     quux)"
   2.384+                 "(foo \"|\"\n     quux)"))
   2.385+   ("M-d"       paredit-forward-kill-word
   2.386+                ("|(foo bar)    ; baz"
   2.387+                 "(| bar)    ; baz"
   2.388+                 "(|)    ; baz"
   2.389+                 "()    ;|")
   2.390+                (";;;| Frobnicate\n(defun frobnicate ...)"
   2.391+                 ";;;|\n(defun frobnicate ...)"
   2.392+                 ";;;\n(| frobnicate ...)"))
   2.393+   (,(concat "M-" paredit-backward-delete-key)
   2.394+                paredit-backward-kill-word
   2.395+                ("(foo bar)    ; baz\n(quux)|"
   2.396+                 "(foo bar)    ; baz\n(|)"
   2.397+                 "(foo bar)    ; |\n()"
   2.398+                 "(foo |)    ; \n()"
   2.399+                 "(|)    ; \n()"))
   2.400+
   2.401+   "Movement & Navigation"
   2.402+   ("C-M-f"     paredit-forward
   2.403+                ("(foo |(bar baz) quux)"
   2.404+                 "(foo (bar baz)| quux)")
   2.405+                ("(foo (bar)|)"
   2.406+                 "(foo (bar))|"))
   2.407+   ("C-M-b"     paredit-backward
   2.408+                ("(foo (bar baz)| quux)"
   2.409+                 "(foo |(bar baz) quux)")
   2.410+                ("(|(foo) bar)"
   2.411+                 "|((foo) bar)"))
   2.412+   ("C-M-u"     paredit-backward-up)
   2.413+   ("C-M-d"     paredit-forward-down)
   2.414+   ("C-M-p"     paredit-backward-down)  ; Built-in, these are FORWARD-
   2.415+   ("C-M-n"     paredit-forward-up)     ; & BACKWARD-LIST, which have
   2.416+                                        ; no need given C-M-f & C-M-b.
   2.417+
   2.418+   "Depth-Changing Commands"
   2.419+   ("M-("       paredit-wrap-round
   2.420+                ("(foo |bar baz)"
   2.421+                 "(foo (|bar) baz)"))
   2.422+   ("M-s"       paredit-splice-sexp
   2.423+                ("(foo (bar| baz) quux)"
   2.424+                 "(foo bar| baz quux)"))
   2.425+   (("M-<up>" "ESC <up>")
   2.426+                paredit-splice-sexp-killing-backward
   2.427+                ("(foo (let ((x 5)) |(sqrt n)) bar)"
   2.428+                 "(foo |(sqrt n) bar)"))
   2.429+   (("M-<down>" "ESC <down>")
   2.430+                paredit-splice-sexp-killing-forward
   2.431+                ("(a (b c| d e) f)"
   2.432+                 "(a b c| f)"))
   2.433+   ("M-r"       paredit-raise-sexp
   2.434+                ("(dynamic-wind in (lambda () |body) out)"
   2.435+                 "(dynamic-wind in |body out)"
   2.436+                 "|body"))
   2.437+   ("M-?"       paredit-convolute-sexp
   2.438+                ("(let ((x 5) (y 3)) (frob |(zwonk)) (wibblethwop))"
   2.439+                 "(frob |(let ((x 5) (y 3)) (zwonk) (wibblethwop)))"))
   2.440+
   2.441+   "Barfage & Slurpage"
   2.442+   (("C-)" "C-<right>")
   2.443+                paredit-forward-slurp-sexp
   2.444+                ("(foo (bar |baz) quux zot)"
   2.445+                 "(foo (bar |baz quux) zot)")
   2.446+                ("(a b ((c| d)) e f)"
   2.447+                 "(a b ((c| d) e) f)"))
   2.448+   (("C-}" "C-<left>")
   2.449+                paredit-forward-barf-sexp
   2.450+                ("(foo (bar |baz quux) zot)"
   2.451+                 "(foo (bar |baz) quux zot)"))
   2.452+   (("C-(" "C-M-<left>" "ESC C-<left>")
   2.453+                paredit-backward-slurp-sexp
   2.454+                ("(foo bar (baz| quux) zot)"
   2.455+                 "(foo (bar baz| quux) zot)")
   2.456+                ("(a b ((c| d)) e f)"
   2.457+                 "(a (b (c| d)) e f)"))
   2.458+   (("C-{" "C-M-<right>" "ESC C-<right>")
   2.459+                paredit-backward-barf-sexp
   2.460+                ("(foo (bar baz |quux) zot)"
   2.461+                 "(foo bar (baz |quux) zot)"))
   2.462+
   2.463+   "Miscellaneous Commands"
   2.464+   ("M-S"       paredit-split-sexp
   2.465+                ("(hello| world)"
   2.466+                 "(hello)| (world)")
   2.467+                ("\"Hello, |world!\""
   2.468+                 "\"Hello, \"| \"world!\""))
   2.469+   ("M-J"       paredit-join-sexps
   2.470+                ("(hello)| (world)"
   2.471+                 "(hello| world)")
   2.472+                ("\"Hello, \"| \"world!\""
   2.473+                 "\"Hello, |world!\"")
   2.474+                ("hello-\n|  world"
   2.475+                 "hello-|world"))
   2.476+   ("C-c C-M-l" paredit-recenter-on-sexp)
   2.477+   ("M-q"       paredit-reindent-defun)
   2.478+   ))
   2.479+       nil)                             ; end of PROGN
   2.480+
   2.481+;;;;; Command Examples
   2.482+
   2.483+(eval-and-compile
   2.484+  (defmacro paredit-do-commands (vars string-case &rest body)
   2.485+    (let ((spec     (nth 0 vars))
   2.486+          (keys     (nth 1 vars))
   2.487+          (fn       (nth 2 vars))
   2.488+          (examples (nth 3 vars)))
   2.489+      `(dolist (,spec paredit-commands)
   2.490+         (if (stringp ,spec)
   2.491+             ,string-case
   2.492+           (let ((,keys (let ((k (car ,spec)))
   2.493+                          (cond ((stringp k) (list k))
   2.494+                                ((listp k) k)
   2.495+                                (t (error "Invalid paredit command %s."
   2.496+                                          ,spec)))))
   2.497+                 (,fn (cadr ,spec))
   2.498+                 (,examples (cddr ,spec)))
   2.499+             ,@body)))))
   2.500+
   2.501+  (put 'paredit-do-commands 'lisp-indent-function 2))
   2.502+
   2.503+(defun paredit-define-keys ()
   2.504+  (paredit-do-commands (spec keys fn examples)
   2.505+      nil       ; string case
   2.506+    (dolist (key keys)
   2.507+      (define-key paredit-mode-map (read-kbd-macro key) fn))))
   2.508+
   2.509+(defun paredit-function-documentation (fn)
   2.510+  (let ((original-doc (get fn 'paredit-original-documentation))
   2.511+        (doc (documentation fn 'function-documentation)))
   2.512+    (or original-doc
   2.513+        (progn (put fn 'paredit-original-documentation doc)
   2.514+               doc))))
   2.515+
   2.516+(defun paredit-annotate-mode-with-examples ()
   2.517+  (let ((contents
   2.518+         (list (paredit-function-documentation 'paredit-mode))))
   2.519+    (paredit-do-commands (spec keys fn examples)
   2.520+        (push (concat "\n\n" spec "\n")
   2.521+              contents)
   2.522+      (let ((name (symbol-name fn)))
   2.523+        (if (string-match (symbol-name 'paredit-) name)
   2.524+            (push (concat "\n\n\\[" name "]\t" name
   2.525+                          (if examples
   2.526+                              (mapconcat (lambda (example)
   2.527+                                           (concat
   2.528+                                            "\n"
   2.529+                                            (mapconcat 'identity
   2.530+                                                       example
   2.531+                                                       "\n  --->\n")
   2.532+                                            "\n"))
   2.533+                                         examples
   2.534+                                         "")
   2.535+                              "\n  (no examples)\n"))
   2.536+                  contents))))
   2.537+    (put 'paredit-mode 'function-documentation
   2.538+         (apply 'concat (reverse contents))))
   2.539+  ;; PUT returns the huge string we just constructed, which we don't
   2.540+  ;; want it to return.
   2.541+  nil)
   2.542+
   2.543+(defun paredit-annotate-functions-with-examples ()
   2.544+  (paredit-do-commands (spec keys fn examples)
   2.545+      nil       ; string case
   2.546+    (put fn 'function-documentation
   2.547+         (concat (paredit-function-documentation fn)
   2.548+                 "\n\n\\<paredit-mode-map>\\[" (symbol-name fn) "]\n"
   2.549+                 (mapconcat (lambda (example)
   2.550+                              (concat "\n"
   2.551+                                      (mapconcat 'identity
   2.552+                                                 example
   2.553+                                                 "\n  ->\n")
   2.554+                                      "\n"))
   2.555+                            examples
   2.556+                            "")))))
   2.557+
   2.558+;;;;; HTML Examples
   2.559+
   2.560+(defun paredit-insert-html-examples ()
   2.561+  "Insert HTML for a paredit quick reference table."
   2.562+  (interactive)
   2.563+  (let ((insert-lines
   2.564+         (lambda (&rest lines) (dolist (line lines) (insert line) (newline))))
   2.565+        (initp nil))
   2.566+    (paredit-do-commands (spec keys fn examples)
   2.567+        (progn (if initp
   2.568+                   (funcall insert-lines "</table>")
   2.569+                   (setq initp t))
   2.570+               (funcall insert-lines (concat "<h3>" spec "</h3>"))
   2.571+               (funcall insert-lines "<table>"))
   2.572+      (let ((name (symbol-name fn))
   2.573+            (keys
   2.574+             (mapconcat (lambda (key)
   2.575+                          (concat "<tt>" (paredit-html-quote key) "</tt>"))
   2.576+                        keys
   2.577+                        ", ")))
   2.578+        (funcall insert-lines "<tr>")
   2.579+        (funcall insert-lines (concat "  <th align=\"left\">" keys "</th>"))
   2.580+        (funcall insert-lines (concat "  <th align=\"left\">" name "</th>"))
   2.581+        (funcall insert-lines "</tr>")
   2.582+        (funcall insert-lines
   2.583+                 "<tr><td colspan=\"2\"><table cellpadding=\"5\"><tr>")
   2.584+        (dolist (example examples)
   2.585+          (let ((prefix "<td><table border=\"1\"><tr><td><table><tr><td><pre>")
   2.586+                (examples
   2.587+                 (mapconcat 'paredit-html-quote
   2.588+                            example
   2.589+                            (concat "</pre></td></tr>"
   2.590+                                    "<tr><th>&darr;</th></tr>"
   2.591+                                    "<tr><td><pre>")))
   2.592+                (suffix "</pre></td></tr></table></td></tr></table></td>"))
   2.593+            (funcall insert-lines (concat prefix examples suffix))))
   2.594+        (funcall insert-lines "</tr></table></td></tr>")))
   2.595+    (funcall insert-lines "</table>")))
   2.596+
   2.597+(defun paredit-html-quote (string)
   2.598+  (with-temp-buffer
   2.599+    (dotimes (i (length string))
   2.600+      (insert (let ((c (elt string i)))
   2.601+                (cond ((eq c ?\<) "&lt;")
   2.602+                      ((eq c ?\>) "&gt;")
   2.603+                      ((eq c ?\&) "&amp;")
   2.604+                      ((eq c ?\') "&apos;")
   2.605+                      ((eq c ?\") "&quot;")
   2.606+                      (t c)))))
   2.607+    (buffer-string)))
   2.608+
   2.609+;;;; Delimiter Insertion
   2.610+
   2.611+(eval-and-compile
   2.612+  (defun paredit-conc-name (&rest strings)
   2.613+    (intern (apply 'concat strings)))
   2.614+
   2.615+  (defmacro define-paredit-pair (open close name)
   2.616+    `(progn
   2.617+       (defun ,(paredit-conc-name "paredit-open-" name) (&optional n)
   2.618+         ,(concat "Insert a balanced " name " pair.
   2.619+With a prefix argument N, put the closing " name " after N
   2.620+  S-expressions forward.
   2.621+If the region is active, `transient-mark-mode' is enabled, and the
   2.622+  region's start and end fall in the same parenthesis depth, insert a
   2.623+  " name " pair around the region.
   2.624+If in a string or a comment, insert a single " name ".
   2.625+If in a character literal, do nothing.  This prevents changing what was
   2.626+  in the character literal to a meaningful delimiter unintentionally.")
   2.627+         (interactive "P")
   2.628+         (cond ((or (paredit-in-string-p)
   2.629+                    (paredit-in-comment-p))
   2.630+                (insert ,open))
   2.631+               ((not (paredit-in-char-p))
   2.632+                (paredit-insert-pair n ,open ,close 'goto-char)
   2.633+                (save-excursion (backward-up-list) (indent-sexp)))))
   2.634+       (defun ,(paredit-conc-name "paredit-close-" name) ()
   2.635+         ,(concat "Move past one closing delimiter and reindent.
   2.636+\(Agnostic to the specific closing delimiter.)
   2.637+If in a string or comment, insert a single closing " name ".
   2.638+If in a character literal, do nothing.  This prevents changing what was
   2.639+  in the character literal to a meaningful delimiter unintentionally.")
   2.640+         (interactive)
   2.641+         (paredit-move-past-close ,close))
   2.642+       (defun ,(paredit-conc-name "paredit-close-" name "-and-newline") ()
   2.643+         ,(concat "Move past one closing delimiter, add a newline,"
   2.644+                  " and reindent.
   2.645+If there was a margin comment after the closing delimiter, preserve it
   2.646+  on the same line.")
   2.647+         (interactive)
   2.648+         (paredit-move-past-close-and-newline ,close))
   2.649+       (defun ,(paredit-conc-name "paredit-wrap-" name)
   2.650+           (&optional argument)
   2.651+         ,(concat "Wrap the following S-expression.
   2.652+See `paredit-wrap-sexp' for more details.")
   2.653+         (interactive "P")
   2.654+         (paredit-wrap-sexp argument ,open ,close))
   2.655+       (add-to-list 'paredit-wrap-commands
   2.656+                    ',(paredit-conc-name "paredit-wrap-" name)))))
   2.657+
   2.658+(defvar paredit-wrap-commands '(paredit-wrap-sexp)
   2.659+  "List of paredit commands that wrap S-expressions.
   2.660+Used by `paredit-yank-pop'; for internal paredit use only.")
   2.661+
   2.662+(define-paredit-pair ?\( ?\) "round")
   2.663+(define-paredit-pair ?\[ ?\] "square")
   2.664+(define-paredit-pair ?\{ ?\} "curly")
   2.665+(define-paredit-pair ?\< ?\> "angled")
   2.666+
   2.667+;;; Aliases for the old names.
   2.668+
   2.669+(defalias 'paredit-open-parenthesis 'paredit-open-round)
   2.670+(defalias 'paredit-close-parenthesis 'paredit-close-round)
   2.671+(defalias 'paredit-close-parenthesis-and-newline
   2.672+  'paredit-close-round-and-newline)
   2.673+
   2.674+(defalias 'paredit-open-bracket 'paredit-open-square)
   2.675+(defalias 'paredit-close-bracket 'paredit-close-square)
   2.676+(defalias 'paredit-close-bracket-and-newline
   2.677+  'paredit-close-square-and-newline)
   2.678+
   2.679+(defun paredit-move-past-close (close)
   2.680+  (paredit-move-past-close-and close
   2.681+    (lambda ()
   2.682+      (paredit-blink-paren-match nil))))
   2.683+
   2.684+(defun paredit-move-past-close-and-newline (close)
   2.685+  (paredit-move-past-close-and close
   2.686+    (lambda ()
   2.687+      (let ((comment.point (paredit-find-comment-on-line)))
   2.688+        (newline)
   2.689+        (if comment.point
   2.690+            (save-excursion
   2.691+              (forward-line -1)
   2.692+              (end-of-line)
   2.693+              (indent-to (cdr comment.point))
   2.694+              (insert (car comment.point)))))
   2.695+      (lisp-indent-line)
   2.696+      (paredit-ignore-sexp-errors (indent-sexp))
   2.697+      (paredit-blink-paren-match t))))
   2.698+
   2.699+(defun paredit-move-past-close-and (close if-moved)
   2.700+  (if (or (paredit-in-string-p)
   2.701+          (paredit-in-comment-p))
   2.702+      (insert close)
   2.703+    (if (paredit-in-char-p) (forward-char))
   2.704+    (paredit-move-past-close-and-reindent close)
   2.705+    (funcall if-moved)))
   2.706+
   2.707+(defun paredit-find-comment-on-line ()
   2.708+  "Find a margin comment on the current line.
   2.709+Return nil if there is no such comment or if there is anything but
   2.710+  whitespace until such a comment.
   2.711+If such a comment exists, delete the comment (including all leading
   2.712+  whitespace) and return a cons whose car is the comment as a string
   2.713+  and whose cdr is the point of the comment's initial semicolon,
   2.714+  relative to the start of the line."
   2.715+  (save-excursion
   2.716+    (paredit-skip-whitespace t (point-at-eol))
   2.717+    (and (eq ?\; (char-after))
   2.718+         (not (eq ?\; (char-after (1+ (point)))))
   2.719+         (not (or (paredit-in-string-p)
   2.720+                  (paredit-in-char-p)))
   2.721+         (let* ((start                  ;Move to before the semicolon.
   2.722+                 (progn (backward-char) (point)))
   2.723+                (comment
   2.724+                 (buffer-substring start (point-at-eol))))
   2.725+           (paredit-skip-whitespace nil (point-at-bol))
   2.726+           (delete-region (point) (point-at-eol))
   2.727+           (cons comment (- start (point-at-bol)))))))
   2.728+
   2.729+(defun paredit-insert-pair (n open close forward)
   2.730+  (let* ((regionp
   2.731+          (and (paredit-region-active-p)
   2.732+               (paredit-region-safe-for-insert-p)))
   2.733+         (end
   2.734+          (and regionp
   2.735+               (not n)
   2.736+               (prog1 (region-end) (goto-char (region-beginning))))))
   2.737+    (let ((spacep (paredit-space-for-delimiter-p nil open)))
   2.738+      (if spacep (insert " "))
   2.739+      (insert open)
   2.740+      (save-excursion
   2.741+        ;; Move past the desired region.
   2.742+        (cond (n
   2.743+               (funcall forward
   2.744+                        (paredit-scan-sexps-hack (point)
   2.745+                                                 (prefix-numeric-value n))))
   2.746+              (regionp
   2.747+               (funcall forward (+ end (if spacep 2 1)))))
   2.748+        ;; The string case can happen if we are inserting string
   2.749+        ;; delimiters.  The comment case may happen by moving to the
   2.750+        ;; end of a buffer that has a comment with no trailing newline.
   2.751+        (if (and (not (paredit-in-string-p))
   2.752+                 (paredit-in-comment-p))
   2.753+            (newline))
   2.754+        (insert close)
   2.755+        (if (paredit-space-for-delimiter-p t close)
   2.756+            (insert " "))))))
   2.757+
   2.758+;++ This needs a better name...
   2.759+
   2.760+(defun paredit-scan-sexps-hack (point n)
   2.761+  (save-excursion
   2.762+    (goto-char point)
   2.763+    (let ((direction (if (< 0 n) +1 -1))
   2.764+          (magnitude (abs n))
   2.765+          (count 0))
   2.766+      (catch 'exit
   2.767+        (while (< count magnitude)
   2.768+          (let ((p
   2.769+                 (paredit-handle-sexp-errors (scan-sexps (point) direction)
   2.770+                   nil)))
   2.771+            (if (not p) (throw 'exit nil))
   2.772+            (goto-char p))
   2.773+          (setq count (+ count 1)))))
   2.774+    (point)))
   2.775+
   2.776+(defun paredit-region-safe-for-insert-p ()
   2.777+  (save-excursion
   2.778+    (let ((beginning (region-beginning))
   2.779+          (end (region-end)))
   2.780+      (goto-char beginning)
   2.781+      (let* ((beginning-state (paredit-current-parse-state))
   2.782+             (end-state
   2.783+              (parse-partial-sexp beginning end nil nil beginning-state)))
   2.784+        (and (=  (nth 0 beginning-state)   ; 0. depth in parens
   2.785+                 (nth 0 end-state))
   2.786+             (eq (nth 3 beginning-state)   ; 3. non-nil if inside a
   2.787+                 (nth 3 end-state))        ;    string
   2.788+             (eq (nth 4 beginning-state)   ; 4. comment status, yada
   2.789+                 (nth 4 end-state))
   2.790+             (eq (nth 5 beginning-state)   ; 5. t if following char
   2.791+                 (nth 5 end-state)))))))   ;    quote
   2.792+
   2.793+(defvar paredit-space-for-delimiter-predicates nil
   2.794+  "List of predicates for whether to put space by delimiter at point.
   2.795+Each predicate is a function that is is applied to two arguments, ENDP
   2.796+  and DELIMITER, and that returns a boolean saying whether to put a
   2.797+  space next to the delimiter -- before/after the delimiter if ENDP is
   2.798+  false/true, respectively.
   2.799+If any predicate returns false, no space is inserted: every predicate
   2.800+  has veto power.
   2.801+Each predicate may assume that the point is not at the beginning/end of
   2.802+  the buffer, and that the point is preceded/followed by a word
   2.803+  constituent, symbol constituent, string quote, or delimiter matching
   2.804+  DELIMITER, if ENDP is false/true, respectively.
   2.805+Each predicate should examine only text before/after the point if ENDP is
   2.806+  false/true, respectively.")
   2.807+
   2.808+(defun paredit-space-for-delimiter-p (endp delimiter)
   2.809+  ;; If at the buffer limit, don't insert a space.  If there is a word,
   2.810+  ;; symbol, other quote, or non-matching parenthesis delimiter (i.e. a
   2.811+  ;; close when want an open the string or an open when we want to
   2.812+  ;; close the string), do insert a space.
   2.813+  (and (not (if endp (eobp) (bobp)))
   2.814+       (memq (char-syntax (if endp (char-after) (char-before)))
   2.815+             (list ?w ?_ ?\"
   2.816+                   (let ((matching (matching-paren delimiter)))
   2.817+                     (and matching (char-syntax matching)))
   2.818+                   (and (not endp)
   2.819+                        (eq ?\" (char-syntax delimiter))
   2.820+                        ?\) )))
   2.821+       (catch 'exit
   2.822+         (dolist (predicate paredit-space-for-delimiter-predicates)
   2.823+           (if (not (funcall predicate endp delimiter))
   2.824+               (throw 'exit nil)))
   2.825+         t)))
   2.826+
   2.827+(defun paredit-move-past-close-and-reindent (close)
   2.828+  (let ((open (paredit-missing-close)))
   2.829+    (if open
   2.830+        (if (eq close (matching-paren open))
   2.831+            (save-excursion
   2.832+              (message "Missing closing delimiter: %c" close)
   2.833+              (insert close))
   2.834+            (error "Mismatched missing closing delimiter: %c ... %c"
   2.835+                   open close))))
   2.836+  (up-list)
   2.837+  (if (catch 'return                    ; This CATCH returns T if it
   2.838+        (while t                        ; should delete leading spaces
   2.839+          (save-excursion               ; and NIL if not.
   2.840+            (let ((before-paren (1- (point))))
   2.841+              (back-to-indentation)
   2.842+              (cond ((not (eq (point) before-paren))
   2.843+                     ;; Can't call PAREDIT-DELETE-LEADING-WHITESPACE
   2.844+                     ;; here -- we must return from SAVE-EXCURSION
   2.845+                     ;; first.
   2.846+                     (throw 'return t))
   2.847+                    ((save-excursion (forward-line -1)
   2.848+                                     (end-of-line)
   2.849+                                     (paredit-in-comment-p))
   2.850+                     ;; Moving the closing delimiter any further
   2.851+                     ;; would put it into a comment, so we just
   2.852+                     ;; indent the closing delimiter where it is and
   2.853+                     ;; abort the loop, telling its continuation that
   2.854+                     ;; no leading whitespace should be deleted.
   2.855+                     (lisp-indent-line)
   2.856+                     (throw 'return nil))
   2.857+                    (t (delete-indentation)))))))
   2.858+      (paredit-delete-leading-whitespace)))
   2.859+
   2.860+(defun paredit-missing-close ()
   2.861+  (save-excursion
   2.862+    (paredit-handle-sexp-errors (backward-up-list)
   2.863+      (error "Not inside a list."))
   2.864+    (let ((open (char-after)))
   2.865+      (paredit-handle-sexp-errors (progn (forward-sexp) nil)
   2.866+        open))))
   2.867+
   2.868+(defun paredit-delete-leading-whitespace ()
   2.869+  ;; This assumes that we're on the closing delimiter already.
   2.870+  (save-excursion
   2.871+    (backward-char)
   2.872+    (while (let ((syn (char-syntax (char-before))))
   2.873+             (and (or (eq syn ?\ ) (eq syn ?-))     ; whitespace syntax
   2.874+                  ;; The above line is a perfect example of why the
   2.875+                  ;; following test is necessary.
   2.876+                  (not (paredit-in-char-p (1- (point))))))
   2.877+      (delete-char -1))))
   2.878+
   2.879+(defun paredit-blink-paren-match (another-line-p)
   2.880+  (if (and blink-matching-paren
   2.881+           (or (not show-paren-mode) another-line-p))
   2.882+      (paredit-ignore-sexp-errors
   2.883+        (save-excursion
   2.884+          (backward-sexp)
   2.885+          (forward-sexp)
   2.886+          ;; SHOW-PAREN-MODE inhibits any blinking, so we disable it
   2.887+          ;; locally here.
   2.888+          (let ((show-paren-mode nil))
   2.889+            (blink-matching-open))))))
   2.890+
   2.891+(defun paredit-doublequote (&optional n)
   2.892+  "Insert a pair of double-quotes.
   2.893+With a prefix argument N, wrap the following N S-expressions in
   2.894+  double-quotes, escaping intermediate characters if necessary.
   2.895+If the region is active, `transient-mark-mode' is enabled, and the
   2.896+  region's start and end fall in the same parenthesis depth, insert a
   2.897+  pair of double-quotes around the region, again escaping intermediate
   2.898+  characters if necessary.
   2.899+Inside a comment, insert a literal double-quote.
   2.900+At the end of a string, move past the closing double-quote.
   2.901+In the middle of a string, insert a backslash-escaped double-quote.
   2.902+If in a character literal, do nothing.  This prevents accidentally
   2.903+  changing a what was in the character literal to become a meaningful
   2.904+  delimiter unintentionally."
   2.905+  (interactive "P")
   2.906+  (cond ((paredit-in-string-p)
   2.907+         (if (eq (point) (- (paredit-enclosing-string-end) 1))
   2.908+             (forward-char)             ; Just move past the closing quote.
   2.909+           ;; Don't split a \x into an escaped backslash and a string end.
   2.910+           (if (paredit-in-string-escape-p) (forward-char))
   2.911+           (insert ?\\ ?\" )))
   2.912+        ((paredit-in-comment-p)
   2.913+         (insert ?\" ))
   2.914+        ((not (paredit-in-char-p))
   2.915+         (paredit-insert-pair n ?\" ?\" 'paredit-forward-for-quote))))
   2.916+
   2.917+(defun paredit-meta-doublequote (&optional n)
   2.918+  "Move to the end of the string.
   2.919+If not in a string, act as `paredit-doublequote'; if no prefix argument
   2.920+ is specified and the region is not active or `transient-mark-mode' is
   2.921+ disabled, the default is to wrap one S-expression, however, not zero."
   2.922+  (interactive "P")
   2.923+  (if (not (paredit-in-string-p))
   2.924+      (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
   2.925+      (goto-char (paredit-enclosing-string-end))))
   2.926+
   2.927+(defun paredit-meta-doublequote-and-newline (&optional n)
   2.928+  "Move to the end of the string, insert a newline, and indent.
   2.929+If not in a string, act as `paredit-doublequote'; if no prefix argument
   2.930+ is specified and the region is not active or `transient-mark-mode' is
   2.931+ disabled, the default is to wrap one S-expression, however, not zero."
   2.932+  (interactive "P")
   2.933+  (if (not (paredit-in-string-p))
   2.934+      (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
   2.935+      (progn (goto-char (paredit-enclosing-string-end))
   2.936+             (newline)
   2.937+             (lisp-indent-line)
   2.938+             (paredit-ignore-sexp-errors (indent-sexp)))))
   2.939+
   2.940+(defun paredit-forward-for-quote (end)
   2.941+  (let ((state (paredit-current-parse-state)))
   2.942+    (while (< (point) end)
   2.943+      (let ((new-state (parse-partial-sexp (point) (1+ (point))
   2.944+                                           nil nil state)))
   2.945+        (if (paredit-in-string-p new-state)
   2.946+            (if (not (paredit-in-string-escape-p))
   2.947+                (setq state new-state)
   2.948+              ;; Escape character: turn it into an escaped escape
   2.949+              ;; character by appending another backslash.
   2.950+              (insert ?\\ )
   2.951+              ;; Now the point is after both escapes, and we want to
   2.952+              ;; rescan from before the first one to after the second
   2.953+              ;; one.
   2.954+              (setq state
   2.955+                    (parse-partial-sexp (- (point) 2) (point)
   2.956+                                        nil nil state))
   2.957+              ;; Advance the end point, since we just inserted a new
   2.958+              ;; character.
   2.959+              (setq end (1+ end)))
   2.960+          ;; String: escape by inserting a backslash before the quote.
   2.961+          (backward-char)
   2.962+          (insert ?\\ )
   2.963+          ;; The point is now between the escape and the quote, and we
   2.964+          ;; want to rescan from before the escape to after the quote.
   2.965+          (setq state
   2.966+                (parse-partial-sexp (1- (point)) (1+ (point))
   2.967+                                    nil nil state))
   2.968+          ;; Advance the end point for the same reason as above.
   2.969+          (setq end (1+ end)))))))
   2.970+
   2.971+;;;; Escape Insertion
   2.972+
   2.973+(defun paredit-backslash ()
   2.974+  "Insert a backslash followed by a character to escape."
   2.975+  (interactive)
   2.976+  (cond ((paredit-in-string-p) (paredit-backslash-interactive))
   2.977+        ((paredit-in-comment-p) (insert ?\\))
   2.978+        ((paredit-in-char-p) (forward-char) (paredit-backslash-interactive))
   2.979+        (t (paredit-backslash-interactive))))
   2.980+
   2.981+(defun paredit-backslash-interactive ()
   2.982+  (insert ?\\ )
   2.983+  ;; Read a character to insert after the backslash.  If anything
   2.984+  ;; goes wrong -- the user hits delete (entering the rubout
   2.985+  ;; `character'), aborts with C-g, or enters non-character input
   2.986+  ;; -- then delete the backslash to avoid a dangling escape.
   2.987+  (let ((delete-p t))
   2.988+    (unwind-protect
   2.989+        (let ((char (read-char "Character to escape: " t)))
   2.990+          (if (not (eq char ?\^?))
   2.991+              (progn (message "Character to escape: %c" char)
   2.992+                     (insert char)
   2.993+                     (setq delete-p nil))))
   2.994+      (if delete-p
   2.995+          (progn (message "Deleting escape.")
   2.996+                 (delete-char -1))))))
   2.997+
   2.998+(defun paredit-newline ()
   2.999+  "Insert a newline and indent it.
  2.1000+This is like `newline-and-indent', but it not only indents the line
  2.1001+  that the point is on but also the S-expression following the point,
  2.1002+  if there is one.
  2.1003+Move forward one character first if on an escaped character.
  2.1004+If in a string, just insert a literal newline.
  2.1005+If in a comment and if followed by invalid structure, call
  2.1006+  `indent-new-comment-line' to keep the invalid structure in a
  2.1007+  comment."
  2.1008+  (interactive)
  2.1009+  (cond ((paredit-in-string-p)
  2.1010+         (newline))
  2.1011+        ((paredit-in-comment-p)
  2.1012+         (if (paredit-region-ok-p (point) (point-at-eol))
  2.1013+             (progn (newline-and-indent)
  2.1014+                    (paredit-ignore-sexp-errors (indent-sexp)))
  2.1015+             (indent-new-comment-line)))
  2.1016+        (t
  2.1017+         (if (paredit-in-char-p)
  2.1018+             (forward-char))
  2.1019+         (newline-and-indent)
  2.1020+         ;; Indent the following S-expression, but don't signal an
  2.1021+         ;; error if there's only a closing delimiter after the point.
  2.1022+         (paredit-ignore-sexp-errors (indent-sexp)))))
  2.1023+
  2.1024+(defun paredit-electric-indent-mode-p ()
  2.1025+  "True if Electric Indent Mode is on, false if not.
  2.1026+Electric Indent Mode is generally not compatible with paredit and
  2.1027+  users are advised to disable it, since paredit does essentially
  2.1028+  everything it tries to do better.
  2.1029+However, to mitigate the negative user experience of combining
  2.1030+ Electric Indent Mode with paredit, the default key bindings for
  2.1031+ RET and C-j in paredit are exchanged depending on whether
  2.1032+ Electric Indent Mode is enabled."
  2.1033+  (and (boundp 'electric-indent-mode)
  2.1034+       electric-indent-mode))
  2.1035+
  2.1036+(defun paredit-RET ()
  2.1037+  "Default key binding for RET in Paredit Mode.
  2.1038+Normally, inserts a newline, like traditional Emacs RET.
  2.1039+With Electric Indent Mode enabled, inserts a newline and indents
  2.1040+  the new line, as well as any subexpressions of it on subsequent
  2.1041+  lines; see `paredit-newline' for details and examples."
  2.1042+  (interactive)
  2.1043+  (if (paredit-electric-indent-mode-p)
  2.1044+      (let ((electric-indent-mode nil))
  2.1045+        (paredit-newline))
  2.1046+    (newline)))
  2.1047+
  2.1048+(defun paredit-C-j ()
  2.1049+  "Default key binding for C-j in Paredit Mode.
  2.1050+Normally, inserts a newline and indents
  2.1051+  the new line, as well as any subexpressions of it on subsequent
  2.1052+  lines; see `paredit-newline' for details and examples.
  2.1053+With Electric Indent Mode enabled, inserts a newline, like
  2.1054+  traditional Emacs RET."
  2.1055+  (interactive)
  2.1056+  (if (paredit-electric-indent-mode-p)
  2.1057+      (let ((electric-indent-mode nil))
  2.1058+        (newline))
  2.1059+    (paredit-newline)))
  2.1060+
  2.1061+(defun paredit-reindent-defun (&optional argument)
  2.1062+  "Reindent the definition that the point is on.
  2.1063+If the point is in a string or a comment, fill the paragraph instead,
  2.1064+  and with a prefix argument, justify as well."
  2.1065+  (interactive "P")
  2.1066+  (if (or (paredit-in-string-p)
  2.1067+          (paredit-in-comment-p))
  2.1068+      (if (memq fill-paragraph-function '(t nil))
  2.1069+          (lisp-fill-paragraph argument)
  2.1070+        (funcall fill-paragraph-function argument))
  2.1071+    (paredit-preserving-column
  2.1072+      (save-excursion
  2.1073+        (end-of-defun)
  2.1074+        (beginning-of-defun)
  2.1075+        (indent-sexp)))))
  2.1076+
  2.1077+;;;; Comment Insertion
  2.1078+
  2.1079+(defun paredit-semicolon (&optional n)
  2.1080+  "Insert a semicolon.
  2.1081+With a prefix argument N, insert N semicolons.
  2.1082+If in a string, do just that and nothing else.
  2.1083+If in a character literal, move to the beginning of the character
  2.1084+  literal before inserting the semicolon.
  2.1085+If the enclosing list ends on the line after the point, break the line
  2.1086+  after the last S-expression following the point.
  2.1087+If a list begins on the line after the point but ends on a different
  2.1088+  line, break the line after the last S-expression following the point
  2.1089+  before the list."
  2.1090+  (interactive "p")
  2.1091+  (if (or (paredit-in-string-p) (paredit-in-comment-p))
  2.1092+      (insert (make-string (or n 1) ?\; ))
  2.1093+    (if (paredit-in-char-p)
  2.1094+        (backward-char 2))
  2.1095+    (let ((line-break-point (paredit-semicolon-find-line-break-point)))
  2.1096+      (if line-break-point
  2.1097+          (paredit-semicolon-with-line-break line-break-point (or n 1))
  2.1098+          (insert (make-string (or n 1) ?\; ))))))
  2.1099+
  2.1100+(defun paredit-semicolon-find-line-break-point ()
  2.1101+  (and (not (eolp))                   ;Implies (not (eobp)).
  2.1102+       (let ((eol (point-at-eol)))
  2.1103+         (save-excursion
  2.1104+           (catch 'exit
  2.1105+             (while t
  2.1106+               (let ((line-break-point (point)))
  2.1107+                 (cond ((paredit-handle-sexp-errors (progn (forward-sexp) t)
  2.1108+                          nil)
  2.1109+                        ;; Successfully advanced by an S-expression.
  2.1110+                        ;; If that S-expression started on this line
  2.1111+                        ;; and ended on another one, break here.
  2.1112+                        (cond ((not (eq eol (point-at-eol)))
  2.1113+                               (throw 'exit
  2.1114+                                      (and (save-excursion
  2.1115+                                             (backward-sexp)
  2.1116+                                             (eq eol (point-at-eol)))
  2.1117+                                           line-break-point)))
  2.1118+                              ((eobp)
  2.1119+                               (throw 'exit nil))))
  2.1120+                       ((save-excursion
  2.1121+                          (paredit-skip-whitespace t (point-at-eol))
  2.1122+                          (or (eolp) (eobp) (eq (char-after) ?\;)))
  2.1123+                        ;; Can't move further, but there's no closing
  2.1124+                        ;; delimiter we're about to clobber -- either
  2.1125+                        ;; it's on the next line or we're at the end of
  2.1126+                        ;; the buffer.  Don't break the line.
  2.1127+                        (throw 'exit nil))
  2.1128+                       (t
  2.1129+                        ;; Can't move because we hit a delimiter at the
  2.1130+                        ;; end of this line.  Break here.
  2.1131+                        (throw 'exit line-break-point))))))))))
  2.1132+
  2.1133+(defun paredit-semicolon-with-line-break (line-break-point n)
  2.1134+  (let ((line-break-marker (make-marker)))
  2.1135+    (set-marker line-break-marker line-break-point)
  2.1136+    (set-marker-insertion-type line-break-marker t)
  2.1137+    (insert (make-string (or n 1) ?\; ))
  2.1138+    (save-excursion
  2.1139+      (goto-char line-break-marker)
  2.1140+      (set-marker line-break-marker nil)
  2.1141+      (newline)
  2.1142+      (lisp-indent-line)
  2.1143+      ;; This step is redundant if we are inside a list, but even if we
  2.1144+      ;; are at the top level, we want at least to indent whatever we
  2.1145+      ;; bumped off the line.
  2.1146+      (paredit-ignore-sexp-errors (indent-sexp))
  2.1147+      (paredit-indent-sexps))))
  2.1148+
  2.1149+;;; This is all a horrible, horrible hack, primarily for GNU Emacs 21,
  2.1150+;;; in which there is no `comment-or-uncomment-region'.
  2.1151+
  2.1152+(autoload 'comment-forward "newcomment")
  2.1153+(autoload 'comment-normalize-vars "newcomment")
  2.1154+(autoload 'comment-region "newcomment")
  2.1155+(autoload 'comment-search-forward "newcomment")
  2.1156+(autoload 'uncomment-region "newcomment")
  2.1157+
  2.1158+(defun paredit-initialize-comment-dwim ()
  2.1159+  (require 'newcomment)
  2.1160+  (if (not (fboundp 'comment-or-uncomment-region))
  2.1161+      (defalias 'comment-or-uncomment-region
  2.1162+        (lambda (beginning end &optional argument)
  2.1163+          (interactive "*r\nP")
  2.1164+          (if (save-excursion (goto-char beginning)
  2.1165+                              (comment-forward (point-max))
  2.1166+                              (<= end (point)))
  2.1167+              (uncomment-region beginning end argument)
  2.1168+              (comment-region beginning end argument)))))
  2.1169+  (defalias 'paredit-initialize-comment-dwim 'comment-normalize-vars)
  2.1170+  (comment-normalize-vars))
  2.1171+
  2.1172+(defvar paredit-comment-prefix-toplevel ";;; "
  2.1173+  "String of prefix for top-level comments aligned at the left margin.")
  2.1174+
  2.1175+(defvar paredit-comment-prefix-code ";; "
  2.1176+  "String of prefix for comments indented at the same depth as code.")
  2.1177+
  2.1178+(defvar paredit-comment-prefix-margin ";"
  2.1179+  "String of prefix for comments on the same line as code in the margin.")
  2.1180+
  2.1181+(defun paredit-comment-dwim (&optional argument)
  2.1182+  "Call the Lisp comment command you want (Do What I Mean).
  2.1183+This is like `comment-dwim', but it is specialized for Lisp editing.
  2.1184+If transient mark mode is enabled and the mark is active, comment or
  2.1185+  uncomment the selected region, depending on whether it was entirely
  2.1186+  commented not not already.
  2.1187+If there is already a comment on the current line, with no prefix
  2.1188+  argument, indent to that comment; with a prefix argument, kill that
  2.1189+  comment.
  2.1190+Otherwise, insert a comment appropriate for the context and ensure that
  2.1191+  any code following the comment is moved to the next line.
  2.1192+At the top level, where indentation is calculated to be at column 0,
  2.1193+  insert a triple-semicolon comment; within code, where the indentation
  2.1194+  is calculated to be non-zero, and on the line there is either no code
  2.1195+  at all or code after the point, insert a double-semicolon comment;
  2.1196+  and if the point is after all code on the line, insert a single-
  2.1197+  semicolon margin comment at `comment-column'."
  2.1198+  (interactive "*P")
  2.1199+  (paredit-initialize-comment-dwim)
  2.1200+  (cond ((paredit-region-active-p)
  2.1201+         (comment-or-uncomment-region (region-beginning)
  2.1202+                                      (region-end)
  2.1203+                                      argument))
  2.1204+        ((paredit-comment-on-line-p)
  2.1205+         (if argument
  2.1206+             (comment-kill (if (integerp argument) argument nil))
  2.1207+             (comment-indent)))
  2.1208+        (t (paredit-insert-comment))))
  2.1209+
  2.1210+(defun paredit-comment-on-line-p ()
  2.1211+  "True if there is a comment on the line following point.
  2.1212+This is expected to be called only in `paredit-comment-dwim'; do not
  2.1213+  call it elsewhere."
  2.1214+  (save-excursion
  2.1215+    (beginning-of-line)
  2.1216+    (let ((comment-p nil))
  2.1217+      ;; Search forward for a comment beginning.  If there is one, set
  2.1218+      ;; COMMENT-P to true; if not, it will be nil.
  2.1219+      (while (progn
  2.1220+               (setq comment-p          ;t -> no error
  2.1221+                     (comment-search-forward (point-at-eol) t))
  2.1222+               (and comment-p
  2.1223+                    (or (paredit-in-string-p)
  2.1224+                        (paredit-in-char-p (1- (point))))))
  2.1225+        (forward-char))
  2.1226+      comment-p)))
  2.1227+
  2.1228+(defun paredit-insert-comment ()
  2.1229+  (let ((code-after-p
  2.1230+         (save-excursion (paredit-skip-whitespace t (point-at-eol))
  2.1231+                         (not (eolp))))
  2.1232+        (code-before-p
  2.1233+         (save-excursion (paredit-skip-whitespace nil (point-at-bol))
  2.1234+                         (not (bolp)))))
  2.1235+    (cond ((and (bolp)
  2.1236+                (let ((indent
  2.1237+                       (let ((indent (calculate-lisp-indent)))
  2.1238+                         (if (consp indent) (car indent) indent))))
  2.1239+                  (and indent (zerop indent))))
  2.1240+           ;; Top-level comment
  2.1241+           (if code-after-p (save-excursion (newline)))
  2.1242+           (insert paredit-comment-prefix-toplevel))
  2.1243+          ((or code-after-p (not code-before-p))
  2.1244+           ;; Code comment
  2.1245+           (if code-before-p
  2.1246+               (newline-and-indent)
  2.1247+               (lisp-indent-line))
  2.1248+           (insert paredit-comment-prefix-code)
  2.1249+           (if code-after-p
  2.1250+               (save-excursion
  2.1251+                 (newline)
  2.1252+                 (lisp-indent-line)
  2.1253+                 (paredit-indent-sexps))))
  2.1254+          (t
  2.1255+           ;; Margin comment
  2.1256+           (indent-to comment-column 1) ; 1 -> force one leading space
  2.1257+           (insert paredit-comment-prefix-margin)))))
  2.1258+
  2.1259+;;;; Character Deletion
  2.1260+
  2.1261+(defun paredit-delete-char (&optional argument)
  2.1262+  "Delete a character forward or move forward over a delimiter.
  2.1263+If on an opening S-expression delimiter, move forward into the
  2.1264+  S-expression.
  2.1265+If on a closing S-expression delimiter, refuse to delete unless the
  2.1266+  S-expression is empty, in which case delete the whole S-expression.
  2.1267+With a numeric prefix argument N, delete N characters forward.
  2.1268+With a `C-u' prefix argument, simply delete a character forward,
  2.1269+  without regard for delimiter balancing.
  2.1270+
  2.1271+Like `delete-char', ignores `delete-active-region'."
  2.1272+  (interactive "P")
  2.1273+  (let ((delete-active-region nil))
  2.1274+    (paredit-forward-delete argument)))
  2.1275+
  2.1276+(defun paredit-delete-active-region-p ()
  2.1277+  "True if the region is active and to be deleted."
  2.1278+  (and (paredit-region-active-p)
  2.1279+       (boundp 'delete-active-region)
  2.1280+       (eq delete-active-region t)))
  2.1281+
  2.1282+(defun paredit-kill-active-region-p ()
  2.1283+  "True if the region is active and to be killed."
  2.1284+  (and (paredit-region-active-p)
  2.1285+       (boundp 'delete-active-region)
  2.1286+       (eq delete-active-region 'kill)))
  2.1287+
  2.1288+(defun paredit-forward-delete (&optional argument)
  2.1289+  "Delete a character forward or move forward over a delimiter.
  2.1290+If on an opening S-expression delimiter, move forward into the
  2.1291+  S-expression.
  2.1292+If on a closing S-expression delimiter, refuse to delete unless the
  2.1293+  S-expression is empty, in which case delete the whole S-expression.
  2.1294+With a numeric prefix argument N, delete N characters forward.
  2.1295+With a `C-u' prefix argument, simply delete a character forward,
  2.1296+  without regard for delimiter balancing.
  2.1297+
  2.1298+If `delete-active-region' is enabled and the mark is active and
  2.1299+  no prefix argument is specified, act as `paredit-delete-region'
  2.1300+  or `paredit-kill-region' as appropriate instead."
  2.1301+  (interactive "P")
  2.1302+  (cond ((consp argument)
  2.1303+         (delete-char +1))
  2.1304+        ((integerp argument)
  2.1305+         (let ((delete-active-region nil))
  2.1306+           (if (< argument 0)
  2.1307+               (paredit-backward-delete argument)
  2.1308+             (while (> argument 0)
  2.1309+               (paredit-forward-delete)
  2.1310+               (setq argument (- argument 1))))))
  2.1311+        ((paredit-delete-active-region-p)
  2.1312+         (paredit-delete-region (region-beginning) (region-end)))
  2.1313+        ((paredit-kill-active-region-p)
  2.1314+         (paredit-kill-region (region-beginning) (region-end)))
  2.1315+        ((eobp)
  2.1316+         (delete-char +1))
  2.1317+        ((paredit-in-string-p)
  2.1318+         (paredit-forward-delete-in-string))
  2.1319+        ((paredit-in-comment-p)
  2.1320+         (paredit-forward-delete-in-comment))
  2.1321+        ((paredit-in-char-p)            ; Escape -- delete both chars.
  2.1322+         (delete-char -1)
  2.1323+         (delete-char +1))
  2.1324+        ((eq (char-after) ?\\ )         ; ditto
  2.1325+         (delete-char +2))
  2.1326+        ((let ((syn (char-syntax (char-after))))
  2.1327+           (or (eq syn ?\( )
  2.1328+               (eq syn ?\" )))
  2.1329+         (if (save-excursion
  2.1330+               (paredit-handle-sexp-errors (progn (forward-sexp) t)
  2.1331+                 nil))
  2.1332+             (forward-char)
  2.1333+           (message "Deleting spurious opening delimiter.")
  2.1334+           (delete-char +1)))
  2.1335+        ((and (not (paredit-in-char-p (1- (point))))
  2.1336+              (eq (char-syntax (char-after)) ?\) )
  2.1337+              (eq (char-before) (matching-paren (char-after))))
  2.1338+         (delete-char -1)               ; Empty list -- delete both
  2.1339+         (delete-char +1))              ;   delimiters.
  2.1340+        ((eq ?\; (char-after))
  2.1341+         (paredit-forward-delete-comment-start))
  2.1342+        ((eq (char-syntax (char-after)) ?\) )
  2.1343+         (if (paredit-handle-sexp-errors
  2.1344+                 (save-excursion (forward-char) (backward-sexp) t)
  2.1345+               nil)
  2.1346+             (message "End of list!")
  2.1347+             (progn
  2.1348+               (message "Deleting spurious closing delimiter.")
  2.1349+               (delete-char +1))))
  2.1350+        ;; Just delete a single character, if it's not a closing
  2.1351+        ;; delimiter.  (The character literal case is already handled
  2.1352+        ;; by now.)
  2.1353+        (t (delete-char +1))))
  2.1354+
  2.1355+(defun paredit-forward-delete-in-string ()
  2.1356+  (let ((start+end (paredit-string-start+end-points)))
  2.1357+    (cond ((not (eq (point) (cdr start+end)))
  2.1358+           ;; If it's not the close-quote, it's safe to delete.  But
  2.1359+           ;; first handle the case that we're in a string escape.
  2.1360+           (cond ((paredit-in-string-escape-p)
  2.1361+                  ;; We're right after the backslash, so backward
  2.1362+                  ;; delete it before deleting the escaped character.
  2.1363+                  (delete-char -1))
  2.1364+                 ((eq (char-after) ?\\ )
  2.1365+                  ;; If we're not in a string escape, but we are on a
  2.1366+                  ;; backslash, it must start the escape for the next
  2.1367+                  ;; character, so delete the backslash before deleting
  2.1368+                  ;; the next character.
  2.1369+                  (delete-char +1)))
  2.1370+           (delete-char +1))
  2.1371+          ((eq (1- (point)) (car start+end))
  2.1372+           ;; If it is the close-quote, delete only if we're also right
  2.1373+           ;; past the open-quote (i.e. it's empty), and then delete
  2.1374+           ;; both quotes.  Otherwise we refuse to delete it.
  2.1375+           (delete-char -1)
  2.1376+           (delete-char +1)))))
  2.1377+
  2.1378+(defun paredit-check-forward-delete-in-comment ()
  2.1379+  ;; Point is in a comment, possibly at eol.  We are about to delete
  2.1380+  ;; some characters forward; if we are at eol, we are about to delete
  2.1381+  ;; the line break.  Refuse to do so if if moving the next line into
  2.1382+  ;; the comment would break structure.
  2.1383+  (if (eolp)
  2.1384+      (let ((next-line-start (point-at-bol 2))
  2.1385+            (next-line-end (point-at-eol 2)))
  2.1386+        (paredit-check-region next-line-start next-line-end))))
  2.1387+
  2.1388+(defun paredit-forward-delete-in-comment ()
  2.1389+  (paredit-check-forward-delete-in-comment)
  2.1390+  (delete-char +1))
  2.1391+
  2.1392+(defun paredit-forward-delete-comment-start ()
  2.1393+  ;; Point precedes a comment start (not at eol).  Refuse to delete a
  2.1394+  ;; comment start if the comment contains unbalanced junk.
  2.1395+  (paredit-check-region (+ (point) 1) (point-at-eol))
  2.1396+  (delete-char +1))
  2.1397+
  2.1398+(defun paredit-backward-delete (&optional argument)
  2.1399+  "Delete a character backward or move backward over a delimiter.
  2.1400+If on a closing S-expression delimiter, move backward into the
  2.1401+  S-expression.
  2.1402+If on an opening S-expression delimiter, refuse to delete unless the
  2.1403+  S-expression is empty, in which case delete the whole S-expression.
  2.1404+With a numeric prefix argument N, delete N characters backward.
  2.1405+With a `C-u' prefix argument, simply delete a character backward,
  2.1406+  without regard for delimiter balancing.
  2.1407+
  2.1408+If `delete-active-region' is enabled and the mark is active and
  2.1409+  no prefix argument is specified, act as `paredit-delete-region'
  2.1410+  or `paredit-kill-region' as appropriate instead."
  2.1411+  (interactive "P")
  2.1412+  (cond ((consp argument)
  2.1413+         ;++ Should this untabify?
  2.1414+         (delete-char -1))
  2.1415+        ((integerp argument)
  2.1416+         (let ((delete-active-region nil))
  2.1417+           (if (< argument 0)
  2.1418+               (paredit-forward-delete (- 0 argument))
  2.1419+             (while (> argument 0)
  2.1420+               (paredit-backward-delete)
  2.1421+               (setq argument (- argument 1))))))
  2.1422+        ((paredit-delete-active-region-p)
  2.1423+         (paredit-delete-region (region-beginning) (region-end)))
  2.1424+        ((paredit-kill-active-region-p)
  2.1425+         (paredit-kill-region (region-beginning) (region-end)))
  2.1426+        ((bobp)
  2.1427+         (delete-char -1))
  2.1428+        ((paredit-in-string-p)
  2.1429+         (paredit-backward-delete-in-string))
  2.1430+        ((paredit-in-comment-p)
  2.1431+         (paredit-backward-delete-in-comment))
  2.1432+        ((paredit-in-char-p)            ; Escape -- delete both chars.
  2.1433+         (delete-char -1)
  2.1434+         (delete-char +1))
  2.1435+        ((paredit-in-char-p (1- (point)))
  2.1436+         (delete-char -2))              ; ditto
  2.1437+        ((let ((syn (char-syntax (char-before))))
  2.1438+           (or (eq syn ?\) )
  2.1439+               (eq syn ?\" )))
  2.1440+         (if (save-excursion
  2.1441+               (paredit-handle-sexp-errors (progn (backward-sexp) t)
  2.1442+                 nil))
  2.1443+             (backward-char)
  2.1444+           (message "Deleting spurious closing delimiter.")
  2.1445+           (delete-char -1)))
  2.1446+        ((and (eq (char-syntax (char-before)) ?\( )
  2.1447+              (eq (char-after) (matching-paren (char-before))))
  2.1448+         (delete-char -1)               ; Empty list -- delete both
  2.1449+         (delete-char +1))              ;   delimiters.
  2.1450+        ((bolp)
  2.1451+         (paredit-backward-delete-maybe-comment-end))
  2.1452+        ((eq (char-syntax (char-before)) ?\( )
  2.1453+         (if (paredit-handle-sexp-errors
  2.1454+                 (save-excursion (backward-char) (forward-sexp) t)
  2.1455+               nil)
  2.1456+             (message "Beginning of list!")
  2.1457+             (progn
  2.1458+               (message "Deleting spurious closing delimiter.")
  2.1459+               (delete-char -1))))
  2.1460+        ;; Delete it, unless it's an opening delimiter.  The case of
  2.1461+        ;; character literals is already handled by now.
  2.1462+        (t
  2.1463+         ;; Turn off the @#&*&!^&(%^ botch in GNU Emacs 24 that changed
  2.1464+         ;; `backward-delete-char' and `backward-delete-char-untabify'
  2.1465+         ;; semantically so that they delete the region in transient
  2.1466+         ;; mark mode.
  2.1467+         (let ((delete-active-region nil))
  2.1468+           (backward-delete-char-untabify +1)))))
  2.1469+
  2.1470+(defun paredit-backward-delete-in-string ()
  2.1471+  (let ((start+end (paredit-string-start+end-points)))
  2.1472+    (cond ((not (eq (1- (point)) (car start+end)))
  2.1473+           ;; If it's not the open-quote, it's safe to delete.
  2.1474+           (if (paredit-in-string-escape-p)
  2.1475+               ;; If we're on a string escape, since we're about to
  2.1476+               ;; delete the backslash, we must first delete the
  2.1477+               ;; escaped char.
  2.1478+               (delete-char +1))
  2.1479+           (delete-char -1)
  2.1480+           (if (paredit-in-string-escape-p)
  2.1481+               ;; If, after deleting a character, we find ourselves in
  2.1482+               ;; a string escape, we must have deleted the escaped
  2.1483+               ;; character, and the backslash is behind the point, so
  2.1484+               ;; backward delete it.
  2.1485+               (delete-char -1)))
  2.1486+          ((eq (point) (cdr start+end))
  2.1487+           ;; If it is the open-quote, delete only if we're also right
  2.1488+           ;; past the close-quote (i.e. it's empty), and then delete
  2.1489+           ;; both quotes.  Otherwise we refuse to delete it.
  2.1490+           (delete-char -1)
  2.1491+           (delete-char +1)))))
  2.1492+
  2.1493+(defun paredit-backward-delete-in-comment ()
  2.1494+  ;; Point is in a comment, possibly just after the comment start.
  2.1495+  ;; Refuse to delete a comment start if the comment contains
  2.1496+  ;; unbalanced junk.
  2.1497+  (if (save-excursion
  2.1498+        (backward-char)
  2.1499+        ;; Must call `paredit-in-string-p' before
  2.1500+        ;; `paredit-in-comment-p'.
  2.1501+        (not (or (paredit-in-string-p) (paredit-in-comment-p))))
  2.1502+      (paredit-check-region (point) (point-at-eol)))
  2.1503+  (backward-delete-char-untabify +1))
  2.1504+
  2.1505+(defun paredit-backward-delete-maybe-comment-end ()
  2.1506+  ;; Point is at bol, possibly just after a comment end (i.e., the
  2.1507+  ;; previous line may have had a line comment).  Refuse to delete a
  2.1508+  ;; comment end if moving the current line into the previous line's
  2.1509+  ;; comment would break structure.
  2.1510+  (if (save-excursion
  2.1511+        (backward-char)
  2.1512+        (and (not (paredit-in-string-p)) (paredit-in-comment-p)))
  2.1513+      (paredit-check-region (point-at-eol) (point-at-bol)))
  2.1514+  (delete-char -1))
  2.1515+
  2.1516+;;;; Killing
  2.1517+
  2.1518+(defun paredit-kill (&optional argument)
  2.1519+  "Kill a line as if with `kill-line', but respecting delimiters.
  2.1520+In a string, act exactly as `kill-line' but do not kill past the
  2.1521+  closing string delimiter.
  2.1522+On a line with no S-expressions on it starting after the point or
  2.1523+  within a comment, act exactly as `kill-line'.
  2.1524+Otherwise, kill all S-expressions that start after the point.
  2.1525+With a `C-u' prefix argument, just do the standard `kill-line'.
  2.1526+With a numeric prefix argument N, do `kill-line' that many times.
  2.1527+
  2.1528+If `kill-whole-line' is true, kills the newline character and
  2.1529+  indentation on the next line as well.
  2.1530+In that case, ensure there is at least one space between the
  2.1531+  preceding S-expression and whatever follows on the next line."
  2.1532+  (interactive "P")
  2.1533+  (cond (argument
  2.1534+         (kill-line (if (integerp argument) argument 1)))
  2.1535+        ((paredit-in-string-p)
  2.1536+         (paredit-kill-line-in-string))
  2.1537+        ((paredit-in-comment-p)
  2.1538+         (paredit-kill-line-in-comment))
  2.1539+        ((save-excursion (paredit-skip-whitespace t (point-at-eol))
  2.1540+                         (or (eolp) (eq (char-after) ?\; )))
  2.1541+         ;** Be careful about trailing backslashes.
  2.1542+         (if (paredit-in-char-p)
  2.1543+             (backward-char))
  2.1544+         (kill-line))
  2.1545+        (t (paredit-kill-sexps-on-line))))
  2.1546+
  2.1547+(defun paredit-kill-line-in-string ()
  2.1548+  (if (save-excursion (paredit-skip-whitespace t (point-at-eol))
  2.1549+                      (eolp))
  2.1550+      (kill-line)
  2.1551+    (save-excursion
  2.1552+      ;; Be careful not to split an escape sequence.
  2.1553+      (if (paredit-in-string-escape-p)
  2.1554+          (backward-char))
  2.1555+      (kill-region (point)
  2.1556+                   (min (point-at-eol)
  2.1557+                        (cdr (paredit-string-start+end-points)))))))
  2.1558+
  2.1559+(defun paredit-kill-line-in-comment ()
  2.1560+  ;; The variable `kill-whole-line' is not relevant: the point is in a
  2.1561+  ;; comment, and hence not at the beginning of the line.
  2.1562+  (paredit-check-forward-delete-in-comment)
  2.1563+  (kill-line))
  2.1564+
  2.1565+(defun paredit-kill-sexps-on-line ()
  2.1566+  (if (paredit-in-char-p)               ; Move past the \ and prefix.
  2.1567+      (backward-char 2))                ; (# in Scheme/CL, ? in elisp)
  2.1568+  (let ((beginning (point))
  2.1569+        (eol (point-at-eol)))
  2.1570+    (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
  2.1571+      ;; If we got to the end of the list and it's on the same line,
  2.1572+      ;; move backward past the closing delimiter before killing.  (This
  2.1573+      ;; allows something like killing the whitespace in (    ).)
  2.1574+      (if end-of-list-p (progn (up-list) (backward-char)))
  2.1575+      (if kill-whole-line
  2.1576+          (paredit-kill-sexps-on-whole-line beginning)
  2.1577+        (kill-region beginning
  2.1578+                     ;; If all of the S-expressions were on one line,
  2.1579+                     ;; i.e. we're still on that line after moving past
  2.1580+                     ;; the last one, kill the whole line, including
  2.1581+                     ;; any comments; otherwise just kill to the end of
  2.1582+                     ;; the last S-expression we found.  Be sure,
  2.1583+                     ;; though, not to kill any closing parentheses.
  2.1584+                     (if (and (not end-of-list-p)
  2.1585+                              (eq (point-at-eol) eol))
  2.1586+                         eol
  2.1587+                         (point)))))))
  2.1588+
  2.1589+;;; Move to the end of the last S-expression that started on this line,
  2.1590+;;; or to the closing delimiter if the last S-expression in this list
  2.1591+;;; and the closing delimiter both lie on this line.  Return true if
  2.1592+;;; the closing delimiter of this list is on this line, false if not.
  2.1593+;;;
  2.1594+;;; beginning is (point), and eol is (point-at-eol).  Handling of
  2.1595+;;; `kill-whole-line' is trick, and probably kind of broken.
  2.1596+
  2.1597+(defun paredit-forward-sexps-to-kill (beginning eol)
  2.1598+  (let ((end-of-list-p nil) ;Have we hit a closing delimiter on this line?
  2.1599+        (firstp t))         ;Is this still the first line?
  2.1600+    (catch 'return
  2.1601+      (while t
  2.1602+        ;; This and the `kill-whole-line' business below fix a bug that
  2.1603+        ;; inhibited any S-expression at the very end of the buffer
  2.1604+        ;; (with no trailing newline) from being deleted.  It's a
  2.1605+        ;; bizarre fix that I ought to document at some point, but I am
  2.1606+        ;; too busy at the moment to do so.
  2.1607+        (if (and kill-whole-line (eobp)) (throw 'return nil))
  2.1608+        ;; See if we can move forward, and stay on an S-expression that
  2.1609+        ;; started on this line.
  2.1610+        (save-excursion
  2.1611+          (paredit-handle-sexp-errors (forward-sexp)
  2.1612+            ;; Can't move forward -- we must have hit the end of a
  2.1613+            ;; list.  Stop here, but record whether the closing
  2.1614+            ;; delimiter occurred on the starting line.
  2.1615+            (up-list)
  2.1616+            (setq end-of-list-p (eq (point-at-eol) eol))
  2.1617+            (throw 'return nil))
  2.1618+          ;; We can move forward.  Where did we move to?  Stop if:
  2.1619+          ;;
  2.1620+          ;; (a) we hit the end of the buffer in certain circumstances
  2.1621+          ;;     (XXX why are these circumstances? necessary according
  2.1622+          ;;     to tests, need explanation), because forward-sexp
  2.1623+          ;;     didn't/won't make any progress and we'll get stuck in
  2.1624+          ;;     a loop; or
  2.1625+          ;;
  2.1626+          ;; (b) the S-expression we moved to the end to actually
  2.1627+          ;;     started on line after where we started so it's not
  2.1628+          ;;     under our jurisdiction.
  2.1629+          (if (or (and (not firstp)             ;(a)
  2.1630+                       (not kill-whole-line)
  2.1631+                       (eobp))
  2.1632+                  (paredit-handle-sexp-errors   ;(b)
  2.1633+                      (progn (backward-sexp) nil)
  2.1634+                    t)
  2.1635+                  (not (eq (point-at-eol) eol)))
  2.1636+              (throw 'return nil)))
  2.1637+        ;; Determined we can and should move forward.  Do so.
  2.1638+        (forward-sexp)
  2.1639+        ;; In certain other circumstances (XXX need explanation), if we
  2.1640+        ;; hit the end of the buffer, stop here; otherwise the next
  2.1641+        ;; forward-sexp will fail to make progress and we might get
  2.1642+        ;; stuck in a loop.
  2.1643+        (if (and firstp
  2.1644+                 (not kill-whole-line)
  2.1645+                 (eobp))
  2.1646+            (throw 'return nil))
  2.1647+        ;; We have made it past one S-expression.
  2.1648+        (setq firstp nil)))
  2.1649+    end-of-list-p))
  2.1650+
  2.1651+;;; Handle the actual kill when `kill-whole-line' is enabled.
  2.1652+;;;
  2.1653+;;; XXX This has various broken edge cases (see the xfails in test.el)
  2.1654+;;; and it doesn't make paredit-kill/yank a noop on round-trip, in an
  2.1655+;;; attempt to avoid inadvertently joining S-expressions when it
  2.1656+;;; deletes the newline.  It could use some input and logic from a user
  2.1657+;;; who relies on `kill-whole-line' and has a better sense of
  2.1658+;;; expectations.
  2.1659+
  2.1660+(defun paredit-kill-sexps-on-whole-line (beginning)
  2.1661+  (kill-region beginning
  2.1662+               (or (save-excursion     ; Delete trailing indentation...
  2.1663+                     (paredit-skip-whitespace t)
  2.1664+                     (and (not (eq (char-after) ?\; ))
  2.1665+                          (point)))
  2.1666+                   ;; ...or just use the point past the newline, if
  2.1667+                   ;; we encounter a comment.
  2.1668+                   (point-at-eol)))
  2.1669+  (cond ((save-excursion (paredit-skip-whitespace nil (point-at-bol))
  2.1670+                         (bolp))
  2.1671+         ;; Nothing but indentation before the point, so indent it.
  2.1672+         (lisp-indent-line))
  2.1673+        ((eobp) nil)       ; Protect the CHAR-SYNTAX below against NIL.
  2.1674+        ;; Insert a space to avoid invalid joining if necessary.
  2.1675+        ((let ((syn-before (char-syntax (char-before)))
  2.1676+               (syn-after  (char-syntax (char-after))))
  2.1677+           (and (memq syn-before '(?\) ?\" ?_ ?w))
  2.1678+                (memq syn-after '(?\( ?\" ?_ ?w))))
  2.1679+         (save-excursion (insert " ")))))
  2.1680+
  2.1681+;;;;; Killing Words
  2.1682+
  2.1683+;;; This is tricky and asymmetrical because backward parsing is
  2.1684+;;; extraordinarily difficult or impossible, so we have to implement
  2.1685+;;; killing in both directions by parsing forward.
  2.1686+
  2.1687+(defun paredit-forward-kill-word (&optional argument)
  2.1688+  "Kill a word forward, skipping over intervening delimiters."
  2.1689+  (interactive "p")
  2.1690+  (let ((argument (or argument 1)))
  2.1691+    (if (< argument 0)
  2.1692+        (paredit-backward-kill-word (- argument))
  2.1693+      (dotimes (i argument)
  2.1694+        (let ((beginning (point)))
  2.1695+          (skip-syntax-forward " -")
  2.1696+          (let* ((parse-state (paredit-current-parse-state))
  2.1697+                 (state (paredit-kill-word-state parse-state 'char-after)))
  2.1698+            (while (not (or (eobp)
  2.1699+                            (eq ?w (char-syntax (char-after)))))
  2.1700+              (setq parse-state
  2.1701+                    (progn (forward-char 1) (paredit-current-parse-state))
  2.1702+                    ;; XXX Why did I comment this out?
  2.1703+                    ;; (parse-partial-sexp (point) (1+ (point))
  2.1704+                    ;;                     nil nil parse-state)
  2.1705+                    )
  2.1706+              (let* ((old-state state)
  2.1707+                     (new-state
  2.1708+                      (paredit-kill-word-state parse-state 'char-after)))
  2.1709+                (cond ((not (eq old-state new-state))
  2.1710+                       (setq parse-state
  2.1711+                             (paredit-kill-word-hack old-state
  2.1712+                                                     new-state
  2.1713+                                                     parse-state))
  2.1714+                       (setq state
  2.1715+                             (paredit-kill-word-state parse-state
  2.1716+                                                      'char-after))
  2.1717+                       (setq beginning (point)))))))
  2.1718+          (goto-char beginning)
  2.1719+          (kill-word 1))))))
  2.1720+
  2.1721+(defun paredit-backward-kill-word (&optional argument)
  2.1722+  "Kill a word backward, skipping over any intervening delimiters."
  2.1723+  (interactive "p")
  2.1724+  (let ((argument (or argument 1)))
  2.1725+    (if (< argument 0)
  2.1726+        (paredit-forward-kill-word (- argument))
  2.1727+      (dotimes (i argument)
  2.1728+        (if (not (or (bobp)
  2.1729+                     (eq (char-syntax (char-before)) ?w)))
  2.1730+            (let ((end (point)))
  2.1731+              (backward-word 1)
  2.1732+              (forward-word 1)
  2.1733+              (goto-char (min end (point)))
  2.1734+              (let* ((parse-state (paredit-current-parse-state))
  2.1735+                     (state
  2.1736+                      (paredit-kill-word-state parse-state 'char-before)))
  2.1737+                (while (and (< (point) end)
  2.1738+                            (progn
  2.1739+                              (setq parse-state
  2.1740+                                    (parse-partial-sexp (point) (1+ (point))
  2.1741+                                                        nil nil parse-state))
  2.1742+                              (or (eq state
  2.1743+                                      (paredit-kill-word-state parse-state
  2.1744+                                                               'char-before))
  2.1745+                                  (progn (backward-char 1) nil)))))
  2.1746+                (if (and (eq state 'comment)
  2.1747+                         (eq ?\# (char-after (point)))
  2.1748+                         (eq ?\| (char-before (point))))
  2.1749+                    (backward-char 1)))))
  2.1750+        (backward-kill-word 1)))))
  2.1751+
  2.1752+;;;;;; Word-Killing Auxiliaries
  2.1753+
  2.1754+(defun paredit-kill-word-state (parse-state adjacent-char-fn)
  2.1755+  (cond ((paredit-in-comment-p parse-state) 'comment)
  2.1756+        ((paredit-in-string-p  parse-state) 'string)
  2.1757+        ((memq (char-syntax (funcall adjacent-char-fn))
  2.1758+               '(?\( ?\) ))
  2.1759+         'delimiter)
  2.1760+        (t 'other)))
  2.1761+
  2.1762+;;; This optionally advances the point past any comment delimiters that
  2.1763+;;; should probably not be touched, based on the last state change and
  2.1764+;;; the characters around the point.  It returns a new parse state,
  2.1765+;;; starting from the PARSE-STATE parameter.
  2.1766+
  2.1767+(defun paredit-kill-word-hack (old-state new-state parse-state)
  2.1768+  (cond ((and (not (eq old-state 'comment))
  2.1769+              (not (eq new-state 'comment))
  2.1770+              (not (paredit-in-string-escape-p))
  2.1771+              (eq ?\# (char-before))
  2.1772+              (eq ?\| (char-after)))
  2.1773+         (forward-char 1)
  2.1774+         (paredit-current-parse-state)
  2.1775+;;          (parse-partial-sexp (point) (1+ (point))
  2.1776+;;                              nil nil parse-state)
  2.1777+         )
  2.1778+        ((and (not (eq old-state 'comment))
  2.1779+              (eq new-state 'comment)
  2.1780+              (eq ?\; (char-before)))
  2.1781+         (skip-chars-forward ";")
  2.1782+         (paredit-current-parse-state)
  2.1783+;;          (parse-partial-sexp (point) (save-excursion
  2.1784+;;                                        (skip-chars-forward ";"))
  2.1785+;;                              nil nil parse-state)
  2.1786+         )
  2.1787+        (t parse-state)))
  2.1788+
  2.1789+(defun paredit-copy-as-kill ()
  2.1790+  "Save in the kill ring the region that `paredit-kill' would kill."
  2.1791+  (interactive)
  2.1792+  (cond ((paredit-in-string-p)
  2.1793+         (paredit-copy-as-kill-in-string))
  2.1794+        ((paredit-in-comment-p)
  2.1795+         (copy-region-as-kill (point) (point-at-eol)))
  2.1796+        ((save-excursion (paredit-skip-whitespace t (point-at-eol))
  2.1797+                         (or (eolp) (eq (char-after) ?\; )))
  2.1798+         ;** Be careful about trailing backslashes.
  2.1799+         (save-excursion
  2.1800+           (if (paredit-in-char-p)
  2.1801+               (backward-char))
  2.1802+           (copy-region-as-kill (point) (point-at-eol))))
  2.1803+        (t (paredit-copy-sexps-as-kill))))
  2.1804+
  2.1805+(defun paredit-copy-as-kill-in-string ()
  2.1806+  (save-excursion
  2.1807+    (if (paredit-in-string-escape-p)
  2.1808+        (backward-char))
  2.1809+    (copy-region-as-kill (point)
  2.1810+                         (min (point-at-eol)
  2.1811+                              (cdr (paredit-string-start+end-points))))))
  2.1812+
  2.1813+(defun paredit-copy-sexps-as-kill ()
  2.1814+  (save-excursion
  2.1815+    (if (paredit-in-char-p)
  2.1816+        (backward-char 2))
  2.1817+    (let ((beginning (point))
  2.1818+          (eol (point-at-eol)))
  2.1819+      (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
  2.1820+        (if end-of-list-p (progn (up-list) (backward-char)))
  2.1821+        (copy-region-as-kill beginning
  2.1822+                             (cond (kill-whole-line
  2.1823+                                    (or (save-excursion
  2.1824+                                          (paredit-skip-whitespace t)
  2.1825+                                          (and (not (eq (char-after) ?\; ))
  2.1826+                                               (point)))
  2.1827+                                        (point-at-eol)))
  2.1828+                                   ((and (not end-of-list-p)
  2.1829+                                         (eq (point-at-eol) eol))
  2.1830+                                    eol)
  2.1831+                                   (t
  2.1832+                                    (point))))))))
  2.1833+
  2.1834+;;;; Deleting Regions
  2.1835+
  2.1836+(defun paredit-delete-region (start end)
  2.1837+  "Delete the text between point and mark, like `delete-region'.
  2.1838+If that text is unbalanced, signal an error instead.
  2.1839+With a prefix argument, skip the balance check."
  2.1840+  (interactive "r")
  2.1841+  (if (and start end (not current-prefix-arg))
  2.1842+      (paredit-check-region-for-delete start end))
  2.1843+  (setq this-command 'delete-region)
  2.1844+  (delete-region start end))
  2.1845+
  2.1846+(defun paredit-kill-region (start end)
  2.1847+  "Kill the text between point and mark, like `kill-region'.
  2.1848+If that text is unbalanced, signal an error instead.
  2.1849+With a prefix argument, skip the balance check."
  2.1850+  (interactive "r")
  2.1851+  (if (and start end (not current-prefix-arg))
  2.1852+      (paredit-check-region-for-delete start end))
  2.1853+  (setq this-command 'kill-region)
  2.1854+  (kill-region start end))
  2.1855+
  2.1856+(defun paredit-check-region-for-delete (start end)
  2.1857+  "Signal an error deleting text between START and END is unsafe."
  2.1858+  (save-excursion
  2.1859+    (goto-char start)
  2.1860+    (let* ((start-state (paredit-current-parse-state))
  2.1861+           (end-state (parse-partial-sexp start end nil nil start-state)))
  2.1862+      (paredit-check-region-for-delete:depth start start-state end end-state)
  2.1863+      (paredit-check-region-for-delete:string start start-state end end-state)
  2.1864+      (paredit-check-region-for-delete:comment start start-state end end-state)
  2.1865+      (paredit-check-region-for-delete:char-quote start start-state
  2.1866+                                                  end end-state))))
  2.1867+
  2.1868+(defun paredit-check-region-for-delete:depth (start start-state end end-state)
  2.1869+  (let ((start-depth (nth 0 start-state))
  2.1870+        (end-depth (nth 0 end-state)))
  2.1871+    (if (not (= start-depth end-depth))
  2.1872+        (error "Mismatched parenthesis depth: %S at start, %S at end."
  2.1873+               start-depth
  2.1874+               end-depth))))
  2.1875+
  2.1876+(defun paredit-check-region-for-delete:string (start start-state end end-state)
  2.1877+  (let ((start-string-p (nth 3 start-state))
  2.1878+        (end-string-p (nth 3 end-state)))
  2.1879+    (if (not (eq start-string-p end-string-p))
  2.1880+        (error "Mismatched string state: start %sin string, end %sin string."
  2.1881+               (if start-string-p "" "not ")
  2.1882+               (if end-string-p "" "not ")))))
  2.1883+
  2.1884+(defun paredit-check-region-for-delete:comment
  2.1885+    (start start-state end end-state)
  2.1886+  (let ((start-comment-state (nth 4 start-state))
  2.1887+        (end-comment-state (nth 4 end-state)))
  2.1888+    (if (not (or (eq start-comment-state end-comment-state)
  2.1889+                 ;; If we are moving text into or out of a line
  2.1890+                 ;; comment, make sure that the text is balanced.  (The
  2.1891+                 ;; comment state may be a number, not t or nil at all,
  2.1892+                 ;; for nestable comments, which are not handled by
  2.1893+                 ;; this heuristic (or any of paredit, really).)
  2.1894+                 (and (or (and (eq start-comment-state nil)
  2.1895+                               (eq end-comment-state t))
  2.1896+                          (and (eq start-comment-state t)
  2.1897+                               (eq end-comment-state nil)))
  2.1898+                      (save-excursion
  2.1899+                        (goto-char end)
  2.1900+                        (paredit-region-ok-p (point) (point-at-eol))))))
  2.1901+        (error "Mismatched comment state: %s"
  2.1902+               (cond ((and (integerp start-comment-state)
  2.1903+                           (integerp end-comment-state))
  2.1904+                      (format "depth %S at start, depth %S at end."
  2.1905+                              start-comment-state
  2.1906+                              end-comment-state))
  2.1907+                     ((integerp start-comment-state)
  2.1908+                      "start in nested comment, end otherwise.")
  2.1909+                     ((integerp end-comment-state)
  2.1910+                      "end in nested comment, start otherwise.")
  2.1911+                     (start-comment-state
  2.1912+                      "start in comment, end not in comment.")
  2.1913+                     (end-comment-state
  2.1914+                      "end in comment, start not in comment.")
  2.1915+                     (t
  2.1916+                      (format "start %S, end %S."
  2.1917+                              start-comment-state
  2.1918+                              end-comment-state)))))))
  2.1919+
  2.1920+(defun paredit-check-region-for-delete:char-quote
  2.1921+    (start start-state end end-state)
  2.1922+  (let ((start-char-quote (nth 5 start-state))
  2.1923+        (end-char-quote (nth 5 end-state)))
  2.1924+    (if (not (eq start-char-quote end-char-quote))
  2.1925+        (let ((phrase "character quotation"))
  2.1926+          (error "Mismatched %s: start %sin %s, end %sin %s."
  2.1927+                 phrase
  2.1928+                 (if start-char-quote "" "not ")
  2.1929+                 phrase
  2.1930+                 (if end-char-quote "" "not ")
  2.1931+                 phrase)))))
  2.1932+
  2.1933+;;;; Point Motion
  2.1934+
  2.1935+(eval-and-compile
  2.1936+  (defmacro defun-motion (name bvl doc &rest body)
  2.1937+    `(defun ,name ,bvl
  2.1938+       ,doc
  2.1939+       ,(xcond ((paredit-xemacs-p)
  2.1940+                '(interactive "_"))
  2.1941+               ((paredit-gnu-emacs-p)
  2.1942+                ;++ Not sure this is sufficient for the `^'.
  2.1943+                (if (fboundp 'handle-shift-selection)
  2.1944+                    '(interactive "^p")
  2.1945+                    '(interactive "p"))))
  2.1946+       ,@body)))
  2.1947+
  2.1948+(defun-motion paredit-forward (&optional arg)
  2.1949+  "Move forward an S-expression, or up an S-expression forward.
  2.1950+If there are no more S-expressions in this one before the closing
  2.1951+  delimiter, move past that closing delimiter; otherwise, move forward
  2.1952+  past the S-expression following the point."
  2.1953+  (let ((n (or arg 1)))
  2.1954+    (cond ((< 0 n) (dotimes (i n)       (paredit-move-forward)))
  2.1955+          ((< n 0) (dotimes (i (- n))   (paredit-move-backward))))))
  2.1956+
  2.1957+(defun-motion paredit-backward (&optional arg)
  2.1958+  "Move backward an S-expression, or up an S-expression backward.
  2.1959+If there are no more S-expressions in this one before the opening
  2.1960+  delimiter, move past that opening delimiter backward; otherwise,
  2.1961+  move backward past the S-expression preceding the point."
  2.1962+  (let ((n (or arg 1)))
  2.1963+    (cond ((< 0 n) (dotimes (i n)       (paredit-move-backward)))
  2.1964+          ((< n 0) (dotimes (i (- n))   (paredit-move-forward))))))
  2.1965+
  2.1966+(defun paredit-move-forward ()
  2.1967+  (cond ((paredit-in-string-p)
  2.1968+         (let ((end (paredit-enclosing-string-end)))
  2.1969+           ;; `forward-sexp' and `up-list' may move into the next string
  2.1970+           ;; in the buffer.  Don't do that; move out of the current one.
  2.1971+           (if (paredit-handle-sexp-errors
  2.1972+                   (progn (paredit-handle-sexp-errors (forward-sexp)
  2.1973+                            (up-list))
  2.1974+                          (<= end (point)))
  2.1975+                 t)
  2.1976+               (goto-char end))))
  2.1977+        ((paredit-in-char-p)
  2.1978+         (forward-char))
  2.1979+        (t
  2.1980+         (paredit-handle-sexp-errors (forward-sexp)
  2.1981+           (up-list)))))
  2.1982+
  2.1983+(defun paredit-move-backward ()
  2.1984+  (cond ((paredit-in-string-p)
  2.1985+         (let ((start (paredit-enclosing-string-start)))
  2.1986+           (if (paredit-handle-sexp-errors
  2.1987+                   (progn (paredit-handle-sexp-errors (backward-sexp)
  2.1988+                            (backward-up-list))
  2.1989+                          (<= (point) start))
  2.1990+                 t)
  2.1991+               (goto-char start))))
  2.1992+        ((paredit-in-char-p)
  2.1993+         ;++ Corner case: a buffer of `\|x'.  What to do?
  2.1994+         (backward-char 2))
  2.1995+        (t
  2.1996+         (paredit-handle-sexp-errors (backward-sexp)
  2.1997+           (backward-up-list)))))
  2.1998+
  2.1999+;;;; Window Positioning
  2.2000+
  2.2001+(defalias 'paredit-recentre-on-sexp 'paredit-recenter-on-sexp)
  2.2002+
  2.2003+(defun paredit-recenter-on-sexp (&optional n)
  2.2004+  "Recenter the screen on the S-expression following the point.
  2.2005+With a prefix argument N, encompass all N S-expressions forward."
  2.2006+  (interactive "P")
  2.2007+  (let* ((p (point))
  2.2008+         (end-point (progn (forward-sexp n) (point)))
  2.2009+         (start-point (progn (goto-char end-point) (backward-sexp n) (point))))
  2.2010+    ;; Point is at beginning of first S-expression.
  2.2011+    (let ((p-visible nil) (start-visible nil))
  2.2012+      (save-excursion
  2.2013+        (forward-line (/ (count-lines start-point end-point) 2))
  2.2014+        (recenter)
  2.2015+        (setq p-visible (pos-visible-in-window-p p))
  2.2016+        (setq start-visible (pos-visible-in-window-p start-point)))
  2.2017+      (cond ((not start-visible)
  2.2018+             ;; Implies (not p-visible).  Put the start at the top of
  2.2019+             ;; the screen.
  2.2020+             (recenter 0))
  2.2021+            (p-visible
  2.2022+             ;; Go back to p if we can.
  2.2023+             (goto-char p))))))
  2.2024+
  2.2025+(defun paredit-recenter-on-defun ()
  2.2026+  "Recenter the screen on the definition at point."
  2.2027+  (interactive)
  2.2028+  (save-excursion
  2.2029+    (beginning-of-defun)
  2.2030+    (paredit-recenter-on-sexp)))
  2.2031+
  2.2032+(defun paredit-focus-on-defun ()
  2.2033+  "Moves display to the top of the definition at point."
  2.2034+  (interactive)
  2.2035+  (beginning-of-defun)
  2.2036+  (recenter 0))
  2.2037+
  2.2038+;;;; Generalized Upward/Downward Motion
  2.2039+
  2.2040+(defun paredit-up/down (n vertical-direction)
  2.2041+  (let ((horizontal-direction (if (< 0 n) +1 -1)))
  2.2042+    (while (/= n 0)
  2.2043+      (goto-char
  2.2044+       (paredit-next-up/down-point horizontal-direction vertical-direction))
  2.2045+      (setq n (- n horizontal-direction)))))
  2.2046+
  2.2047+(defun paredit-next-up/down-point (horizontal-direction vertical-direction)
  2.2048+  (let ((state (paredit-current-parse-state))
  2.2049+        (scan-lists
  2.2050+         (lambda ()
  2.2051+           (scan-lists (point) horizontal-direction vertical-direction))))
  2.2052+    (cond ((paredit-in-string-p state)
  2.2053+           (let ((start+end (paredit-string-start+end-points state)))
  2.2054+             (if (< 0 vertical-direction)
  2.2055+                 (if (< 0 horizontal-direction)
  2.2056+                     (+ 1 (cdr start+end))
  2.2057+                     (car start+end))
  2.2058+                 ;; We could let the user try to descend into lists
  2.2059+                 ;; within the string, but that would be asymmetric
  2.2060+                 ;; with the up case, which rises out of the whole
  2.2061+                 ;; string and not just out of a list within the
  2.2062+                 ;; string, so this case will just be an error.
  2.2063+                 (error "Can't descend further into string."))))
  2.2064+          ((< 0 vertical-direction)
  2.2065+           ;; When moving up, just try to rise up out of the list.
  2.2066+           (or (funcall scan-lists)
  2.2067+               (buffer-end horizontal-direction)))
  2.2068+          ((< vertical-direction 0)
  2.2069+           ;; When moving down, look for a string closer than a list,
  2.2070+           ;; and use that if we find it.
  2.2071+           (let* ((list-start
  2.2072+                   (paredit-handle-sexp-errors (funcall scan-lists) nil))
  2.2073+                  (string-start
  2.2074+                   (paredit-find-next-string-start horizontal-direction
  2.2075+                                                   list-start)))
  2.2076+             (if (and string-start list-start)
  2.2077+                 (if (< 0 horizontal-direction)
  2.2078+                     (min string-start list-start)
  2.2079+                     (max string-start list-start))
  2.2080+                 (or string-start
  2.2081+                     ;; Scan again: this is a kludgey way to report the
  2.2082+                     ;; error if there really was one.
  2.2083+                     (funcall scan-lists)
  2.2084+                     (buffer-end horizontal-direction)))))
  2.2085+          (t
  2.2086+           (error "Vertical direction must be nonzero in `%s'."
  2.2087+                  'paredit-up/down)))))
  2.2088+
  2.2089+(defun paredit-find-next-string-start (horizontal-direction limit)
  2.2090+  (let ((buffer-limit-p (if (< 0 horizontal-direction) 'eobp 'bobp))
  2.2091+        (next-char (if (< 0 horizontal-direction) 'char-after 'char-before))
  2.2092+        (pastp (if (< 0 horizontal-direction) '> '<)))
  2.2093+    (paredit-handle-sexp-errors
  2.2094+        (save-excursion
  2.2095+          (catch 'exit
  2.2096+            (while t
  2.2097+              (if (or (funcall buffer-limit-p)
  2.2098+                      (and limit (funcall pastp (point) limit)))
  2.2099+                  (throw 'exit nil))
  2.2100+              (forward-sexp horizontal-direction)
  2.2101+              (save-excursion
  2.2102+                (backward-sexp horizontal-direction)
  2.2103+                (if (eq ?\" (char-syntax (funcall next-char)))
  2.2104+                    (throw 'exit (+ (point) horizontal-direction)))))))
  2.2105+      nil)))
  2.2106+
  2.2107+(defun-motion paredit-forward-down (&optional argument)
  2.2108+  "Move forward down into a list.
  2.2109+With a positive argument, move forward down that many levels.
  2.2110+With a negative argument, move backward down that many levels."
  2.2111+  (paredit-up/down (or argument +1) -1))
  2.2112+
  2.2113+(defun-motion paredit-backward-up (&optional argument)
  2.2114+  "Move backward up out of the enclosing list.
  2.2115+With a positive argument, move backward up that many levels.
  2.2116+With a negative argument, move forward up that many levels.
  2.2117+If in a string initially, that counts as one level."
  2.2118+  (paredit-up/down (- 0 (or argument +1)) +1))
  2.2119+
  2.2120+(defun-motion paredit-forward-up (&optional argument)
  2.2121+  "Move forward up out of the enclosing list.
  2.2122+With a positive argument, move forward up that many levels.
  2.2123+With a negative argument, move backward up that many levels.
  2.2124+If in a string initially, that counts as one level."
  2.2125+  (paredit-up/down (or argument +1) +1))
  2.2126+
  2.2127+(defun-motion paredit-backward-down (&optional argument)
  2.2128+  "Move backward down into a list.
  2.2129+With a positive argument, move backward down that many levels.
  2.2130+With a negative argument, move forward down that many levels."
  2.2131+  (paredit-up/down (- 0 (or argument +1)) -1))
  2.2132+
  2.2133+;;;; Depth-Changing Commands:  Wrapping, Splicing, & Raising
  2.2134+
  2.2135+(defun paredit-wrap-sexp (&optional argument open close)
  2.2136+  "Wrap the following S-expression.
  2.2137+If a `C-u' prefix argument is given, wrap all S-expressions following
  2.2138+  the point until the end of the buffer or of the enclosing list.
  2.2139+If a numeric prefix argument N is given, wrap N S-expressions.
  2.2140+Automatically indent the newly wrapped S-expression.
  2.2141+As a special case, if the point is at the end of a list, simply insert
  2.2142+  a parenthesis pair, rather than inserting a lone opening delimiter
  2.2143+  and then signalling an error, in the interest of preserving
  2.2144+  structure.
  2.2145+By default OPEN and CLOSE are round delimiters."
  2.2146+  (interactive "P")
  2.2147+  (paredit-lose-if-not-in-sexp 'paredit-wrap-sexp)
  2.2148+  (let ((open (or open ?\( ))
  2.2149+        (close (or close ?\) )))
  2.2150+    (paredit-handle-sexp-errors
  2.2151+        ((lambda (n) (paredit-insert-pair n open close 'goto-char))
  2.2152+         (cond ((integerp argument) argument)
  2.2153+               ((consp argument) (paredit-count-sexps-forward))
  2.2154+               ((paredit-region-active-p) nil)
  2.2155+               (t 1)))
  2.2156+      (insert close)
  2.2157+      (backward-char)))
  2.2158+  (save-excursion (backward-up-list) (indent-sexp)))
  2.2159+
  2.2160+(defun paredit-yank-pop (&optional argument)
  2.2161+  "Replace just-yanked text with the next item in the kill ring.
  2.2162+If this command follows a `yank', just run `yank-pop'.
  2.2163+If this command follows a `paredit-wrap-sexp', or any other paredit
  2.2164+  wrapping command (see `paredit-wrap-commands'), run `yank' and
  2.2165+  reindent the enclosing S-expression.
  2.2166+If this command is repeated, run `yank-pop' and reindent the enclosing
  2.2167+  S-expression.
  2.2168+
  2.2169+The argument is passed on to `yank' or `yank-pop'; see their
  2.2170+  documentation for details."
  2.2171+  (interactive "*p")
  2.2172+  (cond ((eq last-command 'yank)
  2.2173+         (yank-pop argument))
  2.2174+        ((memq last-command paredit-wrap-commands)
  2.2175+         (yank argument)
  2.2176+         ;; `yank' futzes with `this-command'.
  2.2177+         (setq this-command 'paredit-yank-pop)
  2.2178+         (save-excursion (backward-up-list) (indent-sexp)))
  2.2179+        ((eq last-command 'paredit-yank-pop)
  2.2180+         ;; Pretend we just did a `yank', so that we can use
  2.2181+         ;; `yank-pop' without duplicating its definition.
  2.2182+         (setq last-command 'yank)
  2.2183+         (yank-pop argument)
  2.2184+         ;; Return to our original state.
  2.2185+         (setq last-command 'paredit-yank-pop)
  2.2186+         (setq this-command 'paredit-yank-pop)
  2.2187+         (save-excursion (backward-up-list) (indent-sexp)))
  2.2188+        (t (error "Last command was not a yank or a wrap: %s" last-command))))
  2.2189+
  2.2190+(defun paredit-splice-sexp (&optional argument)
  2.2191+  "Splice the list that the point is on by removing its delimiters.
  2.2192+With a prefix argument as in `C-u', kill all S-expressions backward in
  2.2193+  the current list before splicing all S-expressions forward into the
  2.2194+  enclosing list.
  2.2195+With two prefix arguments as in `C-u C-u', kill all S-expressions
  2.2196+  forward in the current list before splicing all S-expressions
  2.2197+  backward into the enclosing list.
  2.2198+With a numerical prefix argument N, kill N S-expressions backward in
  2.2199+  the current list before splicing the remaining S-expressions into the
  2.2200+  enclosing list.  If N is negative, kill forward.
  2.2201+Inside a string, unescape all backslashes, or signal an error if doing
  2.2202+  so would invalidate the buffer's structure."
  2.2203+  (interactive "P")
  2.2204+  (if (paredit-in-string-p)
  2.2205+      (paredit-splice-string argument)
  2.2206+    (if (paredit-in-comment-p)
  2.2207+        (error "Can't splice comment."))
  2.2208+    (paredit-handle-sexp-errors (paredit-enclosing-list-start)
  2.2209+      (error "Can't splice top level."))
  2.2210+    (paredit-kill-surrounding-sexps-for-splice argument)
  2.2211+    (let ((delete-start (paredit-enclosing-list-start))
  2.2212+          (delete-end
  2.2213+           (let ((limit
  2.2214+                  (save-excursion
  2.2215+                    (paredit-ignore-sexp-errors (forward-sexp) (backward-sexp))
  2.2216+                    (point))))
  2.2217+             (save-excursion
  2.2218+               (backward-up-list)
  2.2219+               (forward-char +1)
  2.2220+               (paredit-skip-whitespace t limit)
  2.2221+               (point)))))
  2.2222+      (let ((end-marker (make-marker)))
  2.2223+        (save-excursion
  2.2224+          (up-list)
  2.2225+          (delete-char -1)
  2.2226+          (set-marker end-marker (point)))
  2.2227+        (delete-region delete-start delete-end)
  2.2228+        (paredit-splice-reindent delete-start (marker-position end-marker))))))
  2.2229+
  2.2230+(defun paredit-splice-reindent (start end)
  2.2231+  (paredit-preserving-column
  2.2232+    ;; If we changed the first subform of the enclosing list, we must
  2.2233+    ;; reindent the whole enclosing list.
  2.2234+    (if (paredit-handle-sexp-errors
  2.2235+            (save-excursion
  2.2236+              (backward-up-list)
  2.2237+              (down-list)
  2.2238+              (paredit-ignore-sexp-errors (forward-sexp))
  2.2239+              (< start (point)))
  2.2240+          nil)
  2.2241+        (save-excursion (backward-up-list) (indent-sexp))
  2.2242+        (paredit-indent-region start end))))
  2.2243+
  2.2244+(defun paredit-kill-surrounding-sexps-for-splice (argument)
  2.2245+  (cond ((or (paredit-in-string-p)
  2.2246+             (paredit-in-comment-p))
  2.2247+         (error "Invalid context for splicing S-expressions."))
  2.2248+        ((or (not argument) (eq argument 0)) nil)
  2.2249+        ((or (numberp argument) (eq argument '-))
  2.2250+         ;; Kill S-expressions before/after the point by saving the
  2.2251+         ;; point, moving across them, and killing the region.
  2.2252+         (let* ((argument (if (eq argument '-) -1 argument))
  2.2253+                (saved (paredit-point-at-sexp-boundary (- argument))))
  2.2254+           (goto-char saved)
  2.2255+           (paredit-ignore-sexp-errors (backward-sexp argument))
  2.2256+           (paredit-hack-kill-region saved (point))))
  2.2257+        ((consp argument)
  2.2258+         (let ((v (car argument)))
  2.2259+           (if (= v 4)                  ;One `C-u'.
  2.2260+               ;; Move backward until we hit the open paren; then
  2.2261+               ;; kill that selected region.
  2.2262+               (let ((end (point)))
  2.2263+                 (paredit-ignore-sexp-errors
  2.2264+                   (while (not (bobp))
  2.2265+                     (backward-sexp)))
  2.2266+                 (paredit-hack-kill-region (point) end))
  2.2267+               ;; Move forward until we hit the close paren; then
  2.2268+               ;; kill that selected region.
  2.2269+               (let ((beginning (point)))
  2.2270+                 (paredit-ignore-sexp-errors
  2.2271+                   (while (not (eobp))
  2.2272+                     (forward-sexp)))
  2.2273+                 (paredit-hack-kill-region beginning (point))))))
  2.2274+        (t (error "Bizarre prefix argument `%s'." argument))))
  2.2275+
  2.2276+(defun paredit-splice-sexp-killing-backward (&optional n)
  2.2277+  "Splice the list the point is on by removing its delimiters, and
  2.2278+  also kill all S-expressions before the point in the current list.
  2.2279+With a prefix argument N, kill only the preceding N S-expressions."
  2.2280+  (interactive "P")
  2.2281+  (paredit-splice-sexp (if n
  2.2282+                           (prefix-numeric-value n)
  2.2283+                           '(4))))
  2.2284+
  2.2285+(defun paredit-splice-sexp-killing-forward (&optional n)
  2.2286+  "Splice the list the point is on by removing its delimiters, and
  2.2287+  also kill all S-expressions after the point in the current list.
  2.2288+With a prefix argument N, kill only the following N S-expressions."
  2.2289+  (interactive "P")
  2.2290+  (paredit-splice-sexp (if n
  2.2291+                           (- (prefix-numeric-value n))
  2.2292+                           '(16))))
  2.2293+
  2.2294+(defun paredit-raise-sexp (&optional argument)
  2.2295+  "Raise the following S-expression in a tree, deleting its siblings.
  2.2296+With a prefix argument N, raise the following N S-expressions.  If N
  2.2297+  is negative, raise the preceding N S-expressions.
  2.2298+If the point is on an S-expression, such as a string or a symbol, not
  2.2299+  between them, that S-expression is considered to follow the point."
  2.2300+  (interactive "P")
  2.2301+  (save-excursion
  2.2302+    ;; Select the S-expressions we want to raise in a buffer substring.
  2.2303+    (let* ((bound
  2.2304+            (if (and (not argument) (paredit-region-active-p))
  2.2305+                (progn (if (< (mark) (point))
  2.2306+                           (paredit-check-region (mark) (point))
  2.2307+                           (paredit-check-region (point) (mark)))
  2.2308+                       (mark))
  2.2309+              (cond ((paredit-in-string-p)
  2.2310+                     (goto-char (car (paredit-string-start+end-points))))
  2.2311+                    ((paredit-in-char-p)
  2.2312+                     (backward-sexp))
  2.2313+                    ((paredit-in-comment-p)
  2.2314+                     (error "No S-expression to raise in comment.")))
  2.2315+              (scan-sexps (point) (prefix-numeric-value argument))))
  2.2316+           (sexps
  2.2317+            (if (< bound (point))
  2.2318+                (buffer-substring bound (paredit-point-at-sexp-end))
  2.2319+                (buffer-substring (paredit-point-at-sexp-start) bound))))
  2.2320+      ;; Move up to the list we're raising those S-expressions out of and
  2.2321+      ;; delete it.
  2.2322+      (backward-up-list)
  2.2323+      (delete-region (point) (scan-sexps (point) 1))
  2.2324+      (let* ((indent-start (point))
  2.2325+             (indent-end (save-excursion (insert sexps) (point))))
  2.2326+        ;; If the expression spans multiple lines, its indentation is
  2.2327+        ;; probably broken, so reindent it -- but don't reindent
  2.2328+        ;; anything that we didn't touch outside the expression.
  2.2329+        ;;
  2.2330+        ;; XXX What if the *column* of the starting point was preserved
  2.2331+        ;; too?  Should we avoid reindenting in that case?
  2.2332+        (if (not (eq (save-excursion (goto-char indent-start) (point-at-eol))
  2.2333+                     (save-excursion (goto-char indent-end) (point-at-eol))))
  2.2334+            (indent-region indent-start indent-end nil))))))
  2.2335+
  2.2336+;;; The effects of convolution on the surrounding whitespace are pretty
  2.2337+;;; random.  If you have better suggestions, please let me know.
  2.2338+
  2.2339+(defun paredit-convolute-sexp (&optional n)
  2.2340+  "Convolute S-expressions.
  2.2341+Save the S-expressions preceding point and delete them.
  2.2342+Splice the S-expressions following point.
  2.2343+Wrap the enclosing list in a new list prefixed by the saved text.
  2.2344+With a prefix argument N, move up N lists before wrapping."
  2.2345+  (interactive "p")
  2.2346+  (paredit-lose-if-not-in-sexp 'paredit-convolute-sexp)
  2.2347+  ;; Make sure we can move up before destroying anything.
  2.2348+  (save-excursion (backward-up-list n) (backward-up-list))
  2.2349+  (let (open close)                     ;++ Is this a good idea?
  2.2350+    (let ((prefix
  2.2351+           (let ((end (point)))
  2.2352+             (paredit-ignore-sexp-errors
  2.2353+               (while (not (bobp)) (backward-sexp)))
  2.2354+             (prog1 (buffer-substring (point) end)
  2.2355+               (backward-up-list)
  2.2356+               (save-excursion (forward-sexp)
  2.2357+                               (setq close (char-before))
  2.2358+                               (delete-char -1))
  2.2359+               (setq open (char-after))
  2.2360+               (delete-region (point) end)
  2.2361+               ;; I'm not sure this makes sense...
  2.2362+               (if (not (eolp)) (just-one-space))))))
  2.2363+      (backward-up-list n)
  2.2364+      (paredit-insert-pair 1 open close 'goto-char)
  2.2365+      (insert prefix)
  2.2366+      ;; I'm not sure this makes sense either...
  2.2367+      (if (not (eolp)) (just-one-space))
  2.2368+      (save-excursion
  2.2369+        (backward-up-list)
  2.2370+        (paredit-ignore-sexp-errors (indent-sexp))))))
  2.2371+
  2.2372+(defun paredit-splice-string (argument)
  2.2373+  (let ((original-point (point))
  2.2374+        (start+end (paredit-string-start+end-points)))
  2.2375+    (let ((start (car start+end))
  2.2376+          (end (cdr start+end)))
  2.2377+      ;; START and END both lie before the respective quote
  2.2378+      ;; characters, which we want to delete; thus we increment START
  2.2379+      ;; by one to extract the string, and we increment END by one to
  2.2380+      ;; delete the string.
  2.2381+      (let* ((escaped-string
  2.2382+              (cond ((not (consp argument))
  2.2383+                     (buffer-substring (1+ start) end))
  2.2384+                    ((= 4 (car argument))
  2.2385+                     (buffer-substring original-point end))
  2.2386+                    (t
  2.2387+                     (buffer-substring (1+ start) original-point))))
  2.2388+             (unescaped-string
  2.2389+              (paredit-unescape-string escaped-string)))
  2.2390+        (if (not unescaped-string)
  2.2391+            (error "Unspliceable string.")
  2.2392+          (save-excursion
  2.2393+            (goto-char start)
  2.2394+            (delete-region start (1+ end))
  2.2395+            (insert unescaped-string))
  2.2396+          (if (not (and (consp argument)
  2.2397+                        (= 4 (car argument))))
  2.2398+              (goto-char (- original-point 1))))))))
  2.2399+
  2.2400+(defun paredit-unescape-string (string)
  2.2401+  (with-temp-buffer
  2.2402+    (insert string)
  2.2403+    (goto-char (point-min))
  2.2404+    (while (and (not (eobp))
  2.2405+                ;; nil -> no bound; t -> no errors.
  2.2406+                (search-forward "\\" nil t))
  2.2407+      (delete-char -1)
  2.2408+      (forward-char))
  2.2409+    (paredit-handle-sexp-errors
  2.2410+        (progn (scan-sexps (point-min) (point-max))
  2.2411+               (buffer-string))
  2.2412+      nil)))
  2.2413+
  2.2414+;;;; Slurpage & Barfage
  2.2415+
  2.2416+(defun paredit-forward-slurp-sexp (&optional argument)
  2.2417+  "Add the S-expression following the current list into that list
  2.2418+  by moving the closing delimiter.
  2.2419+Automatically reindent the newly slurped S-expression with respect to
  2.2420+  its new enclosing form.
  2.2421+If in a string, move the opening double-quote forward by one
  2.2422+  S-expression and escape any intervening characters as necessary,
  2.2423+  without altering any indentation or formatting."
  2.2424+  (interactive "P")
  2.2425+  (save-excursion
  2.2426+    (cond ((paredit-in-comment-p)
  2.2427+           (error "Invalid context for slurping S-expressions."))
  2.2428+          ((numberp argument)
  2.2429+           (if (< argument 0)
  2.2430+               (paredit-forward-barf-sexp (- 0 argument))
  2.2431+               (while (< 0 argument)
  2.2432+                 (paredit-forward-slurp-sexp)
  2.2433+                 (setq argument (- argument 1)))))
  2.2434+          ((paredit-in-string-p)
  2.2435+           ;; If there is anything to slurp into the string, take that.
  2.2436+           ;; Otherwise, try to slurp into the enclosing list.
  2.2437+           (if (save-excursion
  2.2438+                 (goto-char (paredit-enclosing-string-end))
  2.2439+                 (paredit-handle-sexp-errors (progn (forward-sexp) nil)
  2.2440+                   t))
  2.2441+               (progn
  2.2442+                 (goto-char (paredit-enclosing-string-end))
  2.2443+                 (paredit-forward-slurp-into-list argument))
  2.2444+               (paredit-forward-slurp-into-string argument)))
  2.2445+          (t
  2.2446+           (paredit-forward-slurp-into-list argument)))))
  2.2447+
  2.2448+(defun paredit-forward-slurp-into-list (&optional argument)
  2.2449+  (let ((nestedp nil))
  2.2450+    (save-excursion
  2.2451+      (up-list)                            ; Up to the end of the list to
  2.2452+      (let ((close (char-before)))         ;   save and delete the closing
  2.2453+        (delete-char -1)                   ;   delimiter.
  2.2454+        (let ((start (point)))
  2.2455+          (catch 'return                   ; Go to the end of the desired
  2.2456+            (while t                       ;   S-expression, going up a
  2.2457+              (paredit-handle-sexp-errors  ;   list if it's not in this,
  2.2458+                  (progn (forward-sexp)
  2.2459+                         (if argument
  2.2460+                             (paredit-ignore-sexp-errors
  2.2461+                               (while (not (eobp))
  2.2462+                                 (forward-sexp))))
  2.2463+                         (throw 'return nil))
  2.2464+                (setq nestedp t)
  2.2465+                (up-list)
  2.2466+                (setq close                ; adjusting for mixed
  2.2467+                      (prog1 (char-before) ;   delimiters as necessary,
  2.2468+                        (delete-char -1)
  2.2469+                        (insert close))))))
  2.2470+          (insert close)                   ;  to insert that delimiter.
  2.2471+          (indent-region start (point) nil))))
  2.2472+    (if (and (not nestedp)
  2.2473+             (eq (save-excursion (paredit-skip-whitespace nil) (point))
  2.2474+                 (save-excursion (backward-up-list) (forward-char) (point)))
  2.2475+             (eq (save-excursion (forward-sexp) (backward-sexp) (point))
  2.2476+                 (save-excursion (paredit-skip-whitespace t) (point))))
  2.2477+        (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  2.2478+                       (save-excursion (paredit-skip-whitespace t) (point))))))
  2.2479+
  2.2480+(defun paredit-forward-slurp-into-string (&optional argument)
  2.2481+  (let ((start (paredit-enclosing-string-start))
  2.2482+        (end (paredit-enclosing-string-end)))
  2.2483+    (goto-char end)
  2.2484+    ;; Signal any errors that we might get first, before mucking with
  2.2485+    ;; the buffer's contents.
  2.2486+    (save-excursion (forward-sexp))
  2.2487+    (let ((close (char-before)))
  2.2488+      ;; Skip intervening whitespace if we're slurping into an empty
  2.2489+      ;; string.  XXX What about nonempty strings?
  2.2490+      (if (and (= (+ start 2) end)
  2.2491+               (eq (save-excursion (paredit-skip-whitespace t) (point))
  2.2492+                   (save-excursion (forward-sexp) (backward-sexp) (point))))
  2.2493+          (delete-region (- (point) 1)
  2.2494+                         (save-excursion (paredit-skip-whitespace t) (point)))
  2.2495+          (delete-char -1))
  2.2496+      (paredit-forward-for-quote
  2.2497+       (save-excursion
  2.2498+         (forward-sexp)
  2.2499+         (if argument
  2.2500+             (while (paredit-handle-sexp-errors (progn (forward-sexp) t) nil)))
  2.2501+         (point)))
  2.2502+      (insert close))))
  2.2503+
  2.2504+(defun paredit-forward-barf-sexp (&optional argument)
  2.2505+  "Remove the last S-expression in the current list from that list
  2.2506+  by moving the closing delimiter.
  2.2507+Automatically reindent the newly barfed S-expression with respect to
  2.2508+  its new enclosing form."
  2.2509+  (interactive "P")
  2.2510+  (paredit-lose-if-not-in-sexp 'paredit-forward-barf-sexp)
  2.2511+  (if (and (numberp argument) (< argument 0))
  2.2512+      (paredit-forward-slurp-sexp (- 0 argument))
  2.2513+    (let ((start (point)) (end nil))
  2.2514+      (save-excursion
  2.2515+        (up-list)                       ; Up to the end of the list to
  2.2516+        (let ((close (char-before)))    ;   save and delete the closing
  2.2517+          (delete-char -1)              ;   delimiter.
  2.2518+          (setq end (point))
  2.2519+          (paredit-ignore-sexp-errors   ; Go back to where we want to
  2.2520+            (if (or (not argument)      ;   insert the delimiter.
  2.2521+                    (numberp argument))
  2.2522+                (backward-sexp argument)
  2.2523+                (while (paredit-handle-sexp-errors
  2.2524+                           (save-excursion (backward-sexp) (<= start (point)))
  2.2525+                         nil)
  2.2526+                  (backward-sexp))))
  2.2527+          (paredit-skip-whitespace nil) ; Skip leading whitespace.
  2.2528+          (cond ((bobp)
  2.2529+                 ;++ We'll have deleted the close, but there's no open.
  2.2530+                 ;++ Is that OK?
  2.2531+                 (error "Barfing all subexpressions with no open-paren?"))
  2.2532+                ((paredit-in-comment-p) ; Don't put the close-paren in
  2.2533+                 (newline)))            ;   a comment.
  2.2534+          (insert close))
  2.2535+        ;; Reindent all of the newly barfed S-expressions.  Start at the
  2.2536+        ;; start of the first barfed S-expression, not at the close we
  2.2537+        ;; just inserted.
  2.2538+        (forward-sexp)
  2.2539+        (backward-sexp)
  2.2540+        (if (or (not argument) (numberp argument))
  2.2541+            (paredit-forward-and-indent argument)
  2.2542+            (indent-region (point) end))))))
  2.2543+
  2.2544+(defun paredit-backward-slurp-sexp (&optional argument)
  2.2545+  "Add the S-expression preceding the current list into that list
  2.2546+  by moving the closing delimiter.
  2.2547+Automatically reindent the whole form into which new S-expression was
  2.2548+  slurped.
  2.2549+If in a string, move the opening double-quote backward by one
  2.2550+  S-expression and escape any intervening characters as necessary,
  2.2551+  without altering any indentation or formatting."
  2.2552+  (interactive "P")
  2.2553+  (save-excursion
  2.2554+    (cond ((paredit-in-comment-p)
  2.2555+           (error "Invalid context for slurping S-expressions."))
  2.2556+          ((numberp argument)
  2.2557+           (if (< argument 0)
  2.2558+               (paredit-backward-barf-sexp (- 0 argument))
  2.2559+               (while (< 0 argument)
  2.2560+                 (paredit-backward-slurp-sexp)
  2.2561+                 (setq argument (- argument 1)))))
  2.2562+          ((paredit-in-string-p)
  2.2563+           ;; If there is anything to slurp into the string, take that.
  2.2564+           ;; Otherwise, try to slurp into the enclosing list.
  2.2565+           (if (save-excursion
  2.2566+                 (goto-char (paredit-enclosing-string-start))
  2.2567+                 (paredit-handle-sexp-errors (progn (backward-sexp) nil)
  2.2568+                   t))
  2.2569+               (progn
  2.2570+                 (goto-char (paredit-enclosing-string-start))
  2.2571+                 (paredit-backward-slurp-into-list argument))
  2.2572+               (paredit-backward-slurp-into-string argument)))
  2.2573+          (t
  2.2574+           (paredit-backward-slurp-into-list argument)))))
  2.2575+
  2.2576+(defun paredit-backward-slurp-into-list (&optional argument)
  2.2577+  (let ((nestedp nil))
  2.2578+    (save-excursion
  2.2579+      (backward-up-list)
  2.2580+      (let ((open (char-after)))
  2.2581+        (delete-char +1)
  2.2582+        (catch 'return
  2.2583+          (while t
  2.2584+            (paredit-handle-sexp-errors
  2.2585+                (progn (backward-sexp)
  2.2586+                       (if argument
  2.2587+                           (paredit-ignore-sexp-errors
  2.2588+                             (while (not (bobp))
  2.2589+                               (backward-sexp))))
  2.2590+                       (throw 'return nil))
  2.2591+              (setq nestedp t)
  2.2592+              (backward-up-list)
  2.2593+              (setq open
  2.2594+                    (prog1 (char-after)
  2.2595+                      (save-excursion (insert open) (delete-char +1)))))))
  2.2596+        (insert open))
  2.2597+      ;; Reindent the line at the beginning of wherever we inserted the
  2.2598+      ;; opening delimiter, and then indent the whole S-expression.
  2.2599+      (backward-up-list)
  2.2600+      (lisp-indent-line)
  2.2601+      (indent-sexp))
  2.2602+    ;; If we slurped into an empty list, don't leave dangling space:
  2.2603+    ;; (foo |).
  2.2604+    (if (and (not nestedp)
  2.2605+             (eq (save-excursion (paredit-skip-whitespace nil) (point))
  2.2606+                 (save-excursion (backward-sexp) (forward-sexp) (point)))
  2.2607+             (eq (save-excursion (up-list) (backward-char) (point))
  2.2608+                 (save-excursion (paredit-skip-whitespace t) (point))))
  2.2609+        (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  2.2610+                       (save-excursion (paredit-skip-whitespace t) (point))))))
  2.2611+
  2.2612+(defun paredit-backward-slurp-into-string (&optional argument)
  2.2613+  (let ((start (paredit-enclosing-string-start))
  2.2614+        (end (paredit-enclosing-string-end)))
  2.2615+    (goto-char start)
  2.2616+    ;; Signal any errors that we might get first, before mucking with
  2.2617+    ;; the buffer's contents.
  2.2618+    (save-excursion (backward-sexp))
  2.2619+    (let ((open (char-after))
  2.2620+          (target (point)))
  2.2621+      ;; Skip intervening whitespace if we're slurping into an empty
  2.2622+      ;; string.  XXX What about nonempty strings?
  2.2623+      (if (and (= (+ start 2) end)
  2.2624+               (eq (save-excursion (paredit-skip-whitespace nil) (point))
  2.2625+                   (save-excursion (backward-sexp) (forward-sexp) (point))))
  2.2626+          (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  2.2627+                         (+ (point) 1))
  2.2628+          (delete-char +1))
  2.2629+      (backward-sexp)
  2.2630+      (if argument
  2.2631+          (paredit-ignore-sexp-errors
  2.2632+            (while (not (bobp))
  2.2633+              (backward-sexp))))
  2.2634+      (insert open)
  2.2635+      (paredit-forward-for-quote target))))
  2.2636+
  2.2637+(defun paredit-backward-barf-sexp (&optional argument)
  2.2638+  "Remove the first S-expression in the current list from that list
  2.2639+  by moving the closing delimiter.
  2.2640+Automatically reindent the barfed S-expression and the form from which
  2.2641+  it was barfed."
  2.2642+  (interactive "P")
  2.2643+  (paredit-lose-if-not-in-sexp 'paredit-backward-barf-sexp)
  2.2644+  (if (and (numberp argument) (< argument 0))
  2.2645+      (paredit-backward-slurp-sexp (- 0 argument))
  2.2646+    (let ((end (make-marker)))
  2.2647+      (set-marker end (point))
  2.2648+      (save-excursion
  2.2649+        (backward-up-list)
  2.2650+        (let ((open (char-after)))
  2.2651+          (delete-char +1)
  2.2652+          (paredit-ignore-sexp-errors
  2.2653+            (paredit-forward-and-indent
  2.2654+             (if (or (not argument) (numberp argument))
  2.2655+                 argument
  2.2656+                 (let ((n 0))
  2.2657+                   (save-excursion
  2.2658+                     (while (paredit-handle-sexp-errors
  2.2659+                                (save-excursion
  2.2660+                                  (forward-sexp)
  2.2661+                                  (<= (point) end))
  2.2662+                              nil)
  2.2663+                       (forward-sexp)
  2.2664+                       (setq n (+ n 1))))
  2.2665+                   n))))
  2.2666+          (while (progn (paredit-skip-whitespace t) (eq (char-after) ?\; ))
  2.2667+            (forward-line 1))
  2.2668+          (if (eobp)
  2.2669+              ;++ We'll have deleted the close, but there's no open.
  2.2670+              ;++ Is that OK?
  2.2671+              (error "Barfing all subexpressions with no close-paren?"))
  2.2672+          ;** Don't use `insert' here.  Consider, e.g., barfing from
  2.2673+          ;**   (foo|)
  2.2674+          ;** and how `save-excursion' works.
  2.2675+          (insert-before-markers open))
  2.2676+        (backward-up-list)
  2.2677+        (lisp-indent-line)
  2.2678+        (indent-sexp)))))
  2.2679+
  2.2680+;;;; Splitting & Joining
  2.2681+
  2.2682+(defun paredit-split-sexp ()
  2.2683+  "Split the list or string the point is on into two."
  2.2684+  (interactive)
  2.2685+  (cond ((paredit-in-string-p)
  2.2686+         (insert "\"")
  2.2687+         (save-excursion (insert " \"")))
  2.2688+        ((or (paredit-in-comment-p)
  2.2689+             (paredit-in-char-p))
  2.2690+         (error "Invalid context for splitting S-expression."))
  2.2691+        (t
  2.2692+         (let ((open (save-excursion (backward-up-list) (char-after)))
  2.2693+               (close (save-excursion (up-list) (char-before))))
  2.2694+           (delete-horizontal-space)
  2.2695+           (insert close)
  2.2696+           (save-excursion
  2.2697+             (insert ?\ )
  2.2698+             (insert open)
  2.2699+             (backward-char)
  2.2700+             (indent-sexp))))))
  2.2701+
  2.2702+(defun paredit-join-sexps ()
  2.2703+  "Join the S-expressions adjacent on either side of the point.
  2.2704+Both must be lists, strings, or atoms; error if there is a mismatch."
  2.2705+  (interactive)
  2.2706+  (cond ((paredit-in-comment-p) (error "Can't join S-expressions in comment."))
  2.2707+        ((paredit-in-string-p) (error "Nothing to join in a string."))
  2.2708+        ((paredit-in-char-p) (error "Can't join characters.")))
  2.2709+  (let ((left-point (paredit-point-at-sexp-end))
  2.2710+        (right-point (paredit-point-at-sexp-start)))
  2.2711+    (let ((left-char (char-before left-point))
  2.2712+          (right-char (char-after right-point)))
  2.2713+      (let ((left-syntax (char-syntax left-char))
  2.2714+            (right-syntax (char-syntax right-char)))
  2.2715+        (cond ((< right-point left-point)
  2.2716+               (error "Can't join a datum with itself."))
  2.2717+              ((and (eq left-syntax ?\) )
  2.2718+                    (eq right-syntax ?\( )
  2.2719+                    (eq left-char (matching-paren right-char))
  2.2720+                    (eq right-char (matching-paren left-char)))
  2.2721+               (paredit-join-lists-internal left-point right-point)
  2.2722+               (paredit-preserving-column
  2.2723+                 (save-excursion
  2.2724+                   (backward-up-list)
  2.2725+                   (indent-sexp))))
  2.2726+              ((and (eq left-syntax ?\" )
  2.2727+                    (eq right-syntax ?\" ))
  2.2728+               ;; Delete any intermediate formatting.
  2.2729+               (delete-region (1- left-point) (1+ right-point)))
  2.2730+              ((and (memq left-syntax '(?w ?_)) ; Word or symbol
  2.2731+                    (memq right-syntax '(?w ?_)))
  2.2732+               (delete-region left-point right-point))
  2.2733+              (t (error "Mismatched S-expressions to join.")))))))
  2.2734+
  2.2735+(defun paredit-join-lists-internal (left-point right-point)
  2.2736+  (save-excursion
  2.2737+    ;; Leave intermediate formatting alone.
  2.2738+    (goto-char right-point)
  2.2739+    (delete-char +1)
  2.2740+    (goto-char left-point)
  2.2741+    (delete-char -1)
  2.2742+    ;; Kludge: Add an extra space in several conditions.
  2.2743+    (if (or
  2.2744+         ;; (foo)| ;x\n(bar) => (foo | ;x\nbar), not (foo|  ;x\nbar).
  2.2745+         (and (not (eolp))
  2.2746+              (save-excursion
  2.2747+                (paredit-skip-whitespace t (point-at-eol))
  2.2748+                (eq (char-after) ?\;)))
  2.2749+         ;; (foo)|(bar) => (foo| bar), not (foo|bar).
  2.2750+         (and (= left-point right-point)
  2.2751+              (not (or (eq ?\  (char-syntax (char-before)))
  2.2752+                       (eq ?\  (char-syntax (char-after)))))))
  2.2753+        (insert ?\  ))))
  2.2754+
  2.2755+;++ How ought paredit-join to handle comments intervening symbols or strings?
  2.2756+;++ Idea:
  2.2757+;++
  2.2758+;++   "foo"   |        ;bar
  2.2759+;++   "baz"      ;quux
  2.2760+;++
  2.2761+;++ =>
  2.2762+;++
  2.2763+;++   "foo|baz"       ;bar
  2.2764+;++              ;quux
  2.2765+;++
  2.2766+;++ The point should stay where it is relative to the comments, and the
  2.2767+;++ the comments' columns should all be preserved, perhaps.  Hmmmm...
  2.2768+;++ What about this?
  2.2769+;++
  2.2770+;++   "foo"           ;bar
  2.2771+;++       |           ;baz
  2.2772+;++   "quux"          ;zot
  2.2773+
  2.2774+;++ Should rename:
  2.2775+;++     paredit-point-at-sexp-start     -> paredit-start-of-sexp-after-point
  2.2776+;++     paredit-point-at-sexp-end       -> paredit-end-of-sexp-before-point
  2.2777+
  2.2778+;;;; Variations on the Lurid Theme
  2.2779+
  2.2780+;;; I haven't the imagination to concoct clever names for these.
  2.2781+
  2.2782+(defun paredit-add-to-previous-list ()
  2.2783+  "Add the S-expression following point to the list preceding point."
  2.2784+  (interactive)
  2.2785+  (paredit-lose-if-not-in-sexp 'paredit-add-to-previous-list)
  2.2786+  (save-excursion
  2.2787+    (down-list -1)                      ;++ backward-down-list...
  2.2788+    (paredit-forward-slurp-sexp)))
  2.2789+
  2.2790+(defun paredit-add-to-next-list ()
  2.2791+  "Add the S-expression preceding point to the list following point.
  2.2792+If no S-expression precedes point, move up the tree until one does."
  2.2793+  (interactive)
  2.2794+  (paredit-lose-if-not-in-sexp 'paredit-add-to-next-list)
  2.2795+  (save-excursion
  2.2796+    (down-list)
  2.2797+    (paredit-backward-slurp-sexp)))
  2.2798+
  2.2799+(defun paredit-join-with-previous-list ()
  2.2800+  "Join the list the point is on with the previous list in the buffer."
  2.2801+  (interactive)
  2.2802+  (paredit-lose-if-not-in-sexp 'paredit-join-with-previous-list)
  2.2803+  (save-excursion
  2.2804+    (while (paredit-handle-sexp-errors (save-excursion (backward-sexp) nil)
  2.2805+             (backward-up-list)
  2.2806+             t))
  2.2807+    (paredit-join-sexps)))
  2.2808+
  2.2809+(defun paredit-join-with-next-list ()
  2.2810+  "Join the list the point is on with the next list in the buffer."
  2.2811+  (interactive)
  2.2812+  (paredit-lose-if-not-in-sexp 'paredit-join-with-next-list)
  2.2813+  (save-excursion
  2.2814+    (while (paredit-handle-sexp-errors (save-excursion (forward-sexp) nil)
  2.2815+             (up-list)
  2.2816+             t))
  2.2817+    (paredit-join-sexps)))
  2.2818+
  2.2819+;;;; Utilities
  2.2820+
  2.2821+(defun paredit-in-string-escape-p ()
  2.2822+  "True if the point is on a character escape of a string.
  2.2823+This is true only if the character is preceded by an odd number of
  2.2824+  backslashes.
  2.2825+This assumes that `paredit-in-string-p' has already returned true."
  2.2826+  (let ((oddp nil))
  2.2827+    (save-excursion
  2.2828+      (while (eq (char-before) ?\\ )
  2.2829+        (setq oddp (not oddp))
  2.2830+        (backward-char)))
  2.2831+    oddp))
  2.2832+
  2.2833+(defun paredit-in-char-p (&optional position)
  2.2834+  "True if point is on a character escape outside a string."
  2.2835+  (save-excursion
  2.2836+    (goto-char (or position (point)))
  2.2837+    (paredit-in-string-escape-p)))
  2.2838+
  2.2839+(defun paredit-skip-whitespace (trailing-p &optional limit)
  2.2840+  "Skip past any whitespace, or until the point LIMIT is reached.
  2.2841+If TRAILING-P is nil, skip leading whitespace; otherwise, skip trailing
  2.2842+  whitespace."
  2.2843+  (funcall (if trailing-p 'skip-chars-forward 'skip-chars-backward)
  2.2844+           " \t\n"  ; This should skip using the syntax table, but LF
  2.2845+           limit))    ; is a comment end, not newline, in Lisp mode.
  2.2846+
  2.2847+(defalias 'paredit-region-active-p
  2.2848+  (xcond ((paredit-xemacs-p) 'region-active-p)
  2.2849+         ((paredit-gnu-emacs-p)
  2.2850+          (lambda ()
  2.2851+            (and mark-active transient-mark-mode)))))
  2.2852+
  2.2853+(defun paredit-hack-kill-region (start end)
  2.2854+  "Kill the region between START and END.
  2.2855+Do not append to any current kill, and
  2.2856+ do not let the next kill append to this one."
  2.2857+  (interactive "r")                     ;Eh, why not?
  2.2858+  ;; KILL-REGION sets THIS-COMMAND to tell the next kill that the last
  2.2859+  ;; command was a kill.  It also checks LAST-COMMAND to see whether it
  2.2860+  ;; should append.  If we bind these locally, any modifications to
  2.2861+  ;; THIS-COMMAND will be masked, and it will not see LAST-COMMAND to
  2.2862+  ;; indicate that it should append.
  2.2863+  (let ((this-command nil)
  2.2864+        (last-command nil))
  2.2865+    (kill-region start end)))
  2.2866+
  2.2867+;;;;; Reindentation utilities
  2.2868+
  2.2869+;++ Should `paredit-indent-sexps' and `paredit-forward-and-indent' use
  2.2870+;++ `paredit-indent-region' rather than `indent-region'?
  2.2871+
  2.2872+(defun paredit-indent-sexps ()
  2.2873+  "If in a list, indent all following S-expressions in the list."
  2.2874+  (let* ((start (point))
  2.2875+         (end (paredit-handle-sexp-errors (progn (up-list) (point)) nil)))
  2.2876+    (if end
  2.2877+        (indent-region start end nil))))
  2.2878+
  2.2879+(defun paredit-forward-and-indent (&optional n)
  2.2880+  "Move forward by N S-expressions, indenting them with `indent-region'."
  2.2881+  (let ((start (point)))
  2.2882+    (forward-sexp n)
  2.2883+    (indent-region start (point) nil)))
  2.2884+
  2.2885+(defun paredit-indent-region (start end)
  2.2886+  "Indent the region from START to END.
  2.2887+Don't reindent the line starting at START, however."
  2.2888+  (if (not (<= start end))
  2.2889+      (error "Incorrectly related points: %S, %S" start end))
  2.2890+  (save-excursion
  2.2891+    (goto-char start)
  2.2892+    (let ((bol (point-at-bol)))
  2.2893+      ;; Skip all S-expressions that end on the starting line, but
  2.2894+      ;; don't go past `end'.
  2.2895+      (if (and (save-excursion (goto-char end) (not (eq bol (point-at-bol))))
  2.2896+               (paredit-handle-sexp-errors
  2.2897+                   (catch 'exit
  2.2898+                     (while t
  2.2899+                       (save-excursion
  2.2900+                         (forward-sexp)
  2.2901+                         (if (not (eq bol (point-at-bol)))
  2.2902+                             (throw 'exit t))
  2.2903+                         (if (not (< (point) end))
  2.2904+                             (throw 'exit nil)))
  2.2905+                       (forward-sexp)))
  2.2906+                 nil))
  2.2907+          (progn
  2.2908+            ;; Point is still on the same line, but precedes an
  2.2909+            ;; S-expression that ends on a different line.
  2.2910+            (if (not (eq bol (point-at-bol)))
  2.2911+                (error "Internal error -- we moved forward a line!"))
  2.2912+            (goto-char (+ 1 (point-at-eol)))
  2.2913+            (if (not (<= (point) end))
  2.2914+                (error "Internal error -- we frobnitzed the garfnut!"))
  2.2915+            (indent-region (point) end nil))))))
  2.2916+
  2.2917+;;;;; S-expression Parsing Utilities
  2.2918+
  2.2919+;++ These routines redundantly traverse S-expressions a great deal.
  2.2920+;++ If performance issues arise, this whole section will probably have
  2.2921+;++ to be refactored to preserve the state longer, like paredit.scm
  2.2922+;++ does, rather than to traverse the definition N times for every key
  2.2923+;++ stroke as it presently does.
  2.2924+
  2.2925+(defun paredit-current-parse-state ()
  2.2926+  "Return parse state of point from beginning of defun."
  2.2927+  (let ((point (point)))
  2.2928+    (beginning-of-defun)
  2.2929+    ;; Calling PARSE-PARTIAL-SEXP will advance the point to its second
  2.2930+    ;; argument (unless parsing stops due to an error, but we assume it
  2.2931+    ;; won't in paredit-mode).
  2.2932+    (parse-partial-sexp (point) point)))
  2.2933+
  2.2934+(defun paredit-in-string-p (&optional state)
  2.2935+  "True if the parse state is within a double-quote-delimited string.
  2.2936+If no parse state is supplied, compute one from the beginning of the
  2.2937+  defun to the point."
  2.2938+  ;; 3. non-nil if inside a string (the terminator character, really)
  2.2939+  (and (nth 3 (or state (paredit-current-parse-state)))
  2.2940+       t))
  2.2941+
  2.2942+(defun paredit-string-start+end-points (&optional state)
  2.2943+  "Return a cons of the points of open and close quotes of the string.
  2.2944+The string is determined from the parse state STATE, or the parse state
  2.2945+  from the beginning of the defun to the point.
  2.2946+This assumes that `paredit-in-string-p' has already returned true, i.e.
  2.2947+  that the point is already within a string."
  2.2948+  (save-excursion
  2.2949+    ;; 8. character address of start of comment or string; nil if not
  2.2950+    ;;    in one
  2.2951+    (let ((start (nth 8 (or state (paredit-current-parse-state)))))
  2.2952+      (goto-char start)
  2.2953+      (forward-sexp 1)
  2.2954+      (cons start (1- (point))))))
  2.2955+
  2.2956+(defun paredit-enclosing-string-start ()
  2.2957+  (car (paredit-string-start+end-points)))
  2.2958+
  2.2959+(defun paredit-enclosing-string-end ()
  2.2960+  (+ 1 (cdr (paredit-string-start+end-points))))
  2.2961+
  2.2962+(defun paredit-enclosing-list-start ()
  2.2963+  (save-excursion
  2.2964+    (backward-up-list)
  2.2965+    (point)))
  2.2966+
  2.2967+(defun paredit-enclosing-list-end ()
  2.2968+  (save-excursion
  2.2969+    (up-list)
  2.2970+    (point)))
  2.2971+
  2.2972+(defun paredit-in-comment-p (&optional state)
  2.2973+  "True if parse state STATE is within a comment.
  2.2974+If no parse state is supplied, compute one from the beginning of the
  2.2975+  defun to the point."
  2.2976+  ;; 4. nil if outside a comment, t if inside a non-nestable comment,
  2.2977+  ;;    else an integer (the current comment nesting)
  2.2978+  (and (nth 4 (or state (paredit-current-parse-state)))
  2.2979+       t))
  2.2980+
  2.2981+(defun paredit-prefix-numeric-value (argument)
  2.2982+  ;++ Kludgerific.
  2.2983+  (cond ((integerp argument) argument)
  2.2984+        ((eq argument '-) -1)
  2.2985+        ((consp argument)
  2.2986+         (cond ((equal argument '(4)) (paredit-count-sexps-forward))   ;C-u
  2.2987+               ((equal argument '(16)) (paredit-count-sexps-backward)) ;C-u C-u
  2.2988+               (t (error "Invalid prefix argument: %S" argument))))
  2.2989+        ((paredit-region-active-p)
  2.2990+         (save-excursion
  2.2991+           (save-restriction
  2.2992+             (narrow-to-region (region-beginning) (region-end))
  2.2993+             (cond ((= (point) (point-min)) (paredit-count-sexps-forward))
  2.2994+                   ((= (point) (point-max)) (paredit-count-sexps-backward))
  2.2995+                   (t
  2.2996+                    (error "Point %S is not start or end of region: %S..%S"
  2.2997+                           (point) (region-beginning) (region-end)))))))
  2.2998+        (t 1)))
  2.2999+
  2.3000+(defun paredit-count-sexps-forward ()
  2.3001+  (save-excursion
  2.3002+    (let ((n 0) (p nil))                ;hurk
  2.3003+      (paredit-ignore-sexp-errors
  2.3004+        (while (setq p (scan-sexps (point) +1))
  2.3005+          (goto-char p)
  2.3006+          (setq n (+ n 1))))
  2.3007+      n)))
  2.3008+
  2.3009+(defun paredit-count-sexps-backward ()
  2.3010+  (save-excursion
  2.3011+    (let ((n 0) (p nil))                ;hurk
  2.3012+      (paredit-ignore-sexp-errors
  2.3013+        (while (setq p (scan-sexps (point) -1))
  2.3014+          (goto-char p)
  2.3015+          (setq n (+ n 1))))
  2.3016+      n)))
  2.3017+
  2.3018+(defun paredit-point-at-sexp-boundary (n)
  2.3019+  (cond ((< n 0) (paredit-point-at-sexp-start))
  2.3020+        ((= n 0) (point))
  2.3021+        ((> n 0) (paredit-point-at-sexp-end))))
  2.3022+
  2.3023+(defun paredit-point-at-sexp-start ()
  2.3024+  (save-excursion
  2.3025+    (forward-sexp)
  2.3026+    (backward-sexp)
  2.3027+    (point)))
  2.3028+
  2.3029+(defun paredit-point-at-sexp-end ()
  2.3030+  (save-excursion
  2.3031+    (backward-sexp)
  2.3032+    (forward-sexp)
  2.3033+    (point)))
  2.3034+
  2.3035+(defun paredit-lose-if-not-in-sexp (command)
  2.3036+  (if (or (paredit-in-string-p)
  2.3037+          (paredit-in-comment-p)
  2.3038+          (paredit-in-char-p))
  2.3039+      (error "Invalid context for command `%s'." command)))
  2.3040+
  2.3041+(defun paredit-check-region (start end)
  2.3042+  "Signal an error if text between `start' and `end' is unbalanced."
  2.3043+  ;; `narrow-to-region' will move the point, so avoid calling it if we
  2.3044+  ;; don't need to.  We don't want to use `save-excursion' because we
  2.3045+  ;; want the point to move if `check-parens' reports an error.
  2.3046+  (if (not (paredit-region-ok-p start end))
  2.3047+      (save-restriction
  2.3048+        (narrow-to-region start end)
  2.3049+        (check-parens))))
  2.3050+
  2.3051+(defun paredit-region-ok-p (start end)
  2.3052+  "Return true iff the region between `start' and `end' is balanced.
  2.3053+This is independent of context -- it doesn't check what state the
  2.3054+  text at `start' is in."
  2.3055+  (save-excursion
  2.3056+    (paredit-handle-sexp-errors
  2.3057+        (progn
  2.3058+          (save-restriction
  2.3059+            (narrow-to-region start end)
  2.3060+            (scan-sexps (point-min) (point-max)))
  2.3061+          t)
  2.3062+      nil)))
  2.3063+
  2.3064+(defun paredit-current-column ()
  2.3065+  ;; Like current-column, but respects field boundaries in interactive
  2.3066+  ;; modes like ielm.  For use only with paredit-restore-column, which
  2.3067+  ;; works relative to point-at-bol.
  2.3068+  (- (point) (point-at-bol)))
  2.3069+
  2.3070+(defun paredit-current-indentation ()
  2.3071+  (save-excursion
  2.3072+    (back-to-indentation)
  2.3073+    (paredit-current-column)))
  2.3074+
  2.3075+(defun paredit-restore-column (column indentation)
  2.3076+  ;; Preserve the point's position either in the indentation or in the
  2.3077+  ;; code: if on code, move with the code; if in indentation, leave it
  2.3078+  ;; in the indentation, either where it was (if still on indentation)
  2.3079+  ;; or at the end of the indentation (if the code moved far enough
  2.3080+  ;; left).
  2.3081+  (let ((indentation* (paredit-current-indentation)))
  2.3082+    (goto-char
  2.3083+     (+ (point-at-bol)
  2.3084+        (cond ((not (< column indentation))
  2.3085+               (+ column (- indentation* indentation)))
  2.3086+              ((<= indentation* column) indentation*)
  2.3087+              (t column))))))
  2.3088+
  2.3089+;;;; Initialization
  2.3090+
  2.3091+(paredit-define-keys)
  2.3092+(paredit-annotate-mode-with-examples)
  2.3093+(paredit-annotate-functions-with-examples)
  2.3094+
  2.3095+(provide 'paredit)
  2.3096+
  2.3097+;;; Local Variables:
  2.3098+;;; outline-regexp: "\n;;;;+"
  2.3099+;;; End:
  2.3100+
  2.3101+;;; paredit.el ends here
     3.1--- a/.emacs.d/paredit.el	Tue May 21 22:20:59 2024 -0400
     3.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3@@ -1,3098 +0,0 @@
     3.4-;;; paredit.el --- minor mode for editing parentheses  -*- Mode: Emacs-Lisp -*-
     3.5-
     3.6-;; Copyright (C) 2005--2023 Taylor R. Campbell
     3.7-
     3.8-;; Author: Taylor R. Campbell <campbell@paredit.org>
     3.9-;; Version: 27beta
    3.10-;; Created: 2005-07-31
    3.11-;; Keywords: lisp
    3.12-;; URL: https://paredit.org
    3.13-
    3.14-;; Paredit is free software: you can redistribute it and/or modify it
    3.15-;; under the terms of the GNU General Public License as published by
    3.16-;; the Free Software Foundation, either version 3 of the License, or
    3.17-;; (at your option) any later version.
    3.18-;;
    3.19-;; Paredit is distributed in the hope that it will be useful, but
    3.20-;; WITHOUT ANY WARRANTY; without even the implied warranty of
    3.21-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.22-;; GNU General Public License for more details.
    3.23-;;
    3.24-;; You should have received a copy of the GNU General Public License
    3.25-;; along with paredit.  If not, see <http://www.gnu.org/licenses/>.
    3.26-
    3.27-;;; Paredit - https://paredit.org
    3.28-;;;
    3.29-;;; Latest release: https://paredit.org/paredit.el
    3.30-;;; Current development version: https://paredit.org/paredit-beta.el
    3.31-;;; Release notes: https://paredit.org/NEWS
    3.32-
    3.33-;;; Commentary:
    3.34-
    3.35-;; Paredit keeps your parentheses balanced while editing.  Paredit Mode
    3.36-;; binds keys like `(', `)', and `"' to insert or delete parentheses
    3.37-;; and string quotes in balanced pairs as you're editing without
    3.38-;; getting in your way, augments editing keys like `C-k' to handle
    3.39-;; balanced expressions, and provides advanced commands for editing
    3.40-;; balanced expressions like splicing and joining while judiciously
    3.41-;; keeping the code you're working on indented.
    3.42-
    3.43-;;; Install paredit by placing `paredit.el' in `/path/to/elisp', a
    3.44-;;; directory of your choice, and adding to your .emacs file:
    3.45-;;;
    3.46-;;;   (add-to-list 'load-path "/path/to/elisp")
    3.47-;;;   (autoload 'enable-paredit-mode "paredit"
    3.48-;;;     "Turn on pseudo-structural editing of Lisp code."
    3.49-;;;     t)
    3.50-;;;
    3.51-;;; Start Paredit Mode on the fly with `M-x enable-paredit-mode RET',
    3.52-;;; or always enable it in a major mode `M' (e.g., `lisp') with:
    3.53-;;;
    3.54-;;;   (add-hook 'M-mode-hook 'enable-paredit-mode)
    3.55-;;;
    3.56-;;; Customize paredit using `eval-after-load':
    3.57-;;;
    3.58-;;;   (eval-after-load 'paredit
    3.59-;;;     '(progn
    3.60-;;;        (define-key paredit-mode-map (kbd "ESC M-A-C-s-)")
    3.61-;;;          'paredit-dwim)))
    3.62-;;;
    3.63-;;; Send questions, bug reports, comments, feature suggestions, &c.,
    3.64-;;; via email to the author's surname at paredit.org.
    3.65-;;;
    3.66-;;; Paredit should run in GNU Emacs 21 or later and XEmacs 21.5.28 or
    3.67-;;; later.
    3.68-
    3.69-;;; The paredit minor mode, Paredit Mode, binds common character keys,
    3.70-;;; such as `(', `)', `"', and `\', to commands that carefully insert
    3.71-;;; S-expression structures in the buffer:
    3.72-;;;
    3.73-;;;   ( inserts `()', leaving the point in the middle;
    3.74-;;;   ) moves the point over the next closing delimiter;
    3.75-;;;   " inserts `""' if outside a string, or inserts an escaped
    3.76-;;;      double-quote if in the middle of a string, or moves over the
    3.77-;;;      closing double-quote if at the end of a string; and
    3.78-;;;   \ prompts for the character to escape, to avoid inserting lone
    3.79-;;;      backslashes that may break structure.
    3.80-;;;
    3.81-;;; In comments, these keys insert themselves.  If necessary, you can
    3.82-;;; insert these characters literally outside comments by pressing
    3.83-;;; `C-q' before these keys, in case a mistake has broken the
    3.84-;;; structure.
    3.85-;;;
    3.86-;;; These key bindings are designed so that when typing new code in
    3.87-;;; Paredit Mode, you can generally type exactly the same sequence of
    3.88-;;; keys you would have typed without Paredit Mode.
    3.89-;;;
    3.90-;;; Paredit Mode also binds common editing keys, such as `DEL', `C-d',
    3.91-;;; and `C-k', to commands that respect S-expression structures in the
    3.92-;;; buffer:
    3.93-;;;
    3.94-;;;   DEL deletes the previous character, unless it is a delimiter: DEL
    3.95-;;;        will move the point backward over a closing delimiter, and
    3.96-;;;        will delete a delimiter pair together if between an open and
    3.97-;;;        closing delimiter;
    3.98-;;;
    3.99-;;;   C-d deletes the next character in much the same manner; and
   3.100-;;;
   3.101-;;;   C-k kills all S-expressions that begin anywhere between the point
   3.102-;;;        and the end of the line or the closing delimiter of the
   3.103-;;;        enclosing list, whichever is first.
   3.104-;;;
   3.105-;;; If necessary, you can delete a character, kill a line, &c.,
   3.106-;;; irrespective of S-expression structure, by pressing `C-u' before
   3.107-;;; these keys, in case a mistake has broken the structure.
   3.108-;;;
   3.109-;;; Finally, Paredit Mode binds some keys to complex S-expression
   3.110-;;; editing operations.  For example, `C-<right>' makes the enclosing
   3.111-;;; list slurp up an S-expression to its right (here `|' denotes the
   3.112-;;; point):
   3.113-;;;
   3.114-;;;   (foo (bar | baz) quux)  C-<right>  (foo (bar | baz quux))
   3.115-;;;
   3.116-;;; Note: Paredit Mode is not compatible with Electric Indent Mode.
   3.117-;;; Use one or the other, not both.  If you want RET to auto-indent and
   3.118-;;; C-j to just insert newline in Paredit Mode, simply rebind the keys
   3.119-;;; with the following fragment in your .emacs file:
   3.120-;;;
   3.121-;;;     (eval-after-load 'paredit
   3.122-;;;       '(progn
   3.123-;;;          (define-key paredit-mode-map (kbd "RET") 'paredit-newline)
   3.124-;;;          (define-key paredit-mode-map (kbd "C-j") nil)))
   3.125-;;;
   3.126-;;; Some paredit commands automatically reindent code.  When they do,
   3.127-;;; they try to indent as locally as possible, to avoid interfering
   3.128-;;; with any indentation you might have manually written.  Only the
   3.129-;;; advanced S-expression manipulation commands automatically reindent,
   3.130-;;; and only the forms that they immediately operated upon (and their
   3.131-;;; subforms).
   3.132-;;;
   3.133-;;; This code is written for clarity, not efficiency.  It frequently
   3.134-;;; walks over S-expressions redundantly.  If you have problems with
   3.135-;;; the time it takes to execute some of the commands, let me know.
   3.136-
   3.137-;;; This assumes Unix-style LF line endings.
   3.138-
   3.139-(defconst paredit-version 27)
   3.140-(defconst paredit-beta-p t)
   3.141-
   3.142-(eval-and-compile
   3.143-
   3.144-  (defun paredit-xemacs-p ()
   3.145-    ;; No idea where I got this definition from.  Edward O'Connor
   3.146-    ;; (hober in #emacs) suggested the current definition.
   3.147-    ;;   (and (boundp 'running-xemacs)
   3.148-    ;;        running-xemacs)
   3.149-    (featurep 'xemacs))
   3.150-
   3.151-  (defun paredit-gnu-emacs-p ()
   3.152-    ;++ This could probably be improved.
   3.153-    (not (paredit-xemacs-p)))
   3.154-
   3.155-  (defmacro xcond (&rest clauses)
   3.156-    "Exhaustive COND.
   3.157-Signal an error if no clause matches."
   3.158-    `(cond ,@clauses
   3.159-           (t (error "XCOND lost."))))
   3.160-
   3.161-  (defalias 'paredit-warn (if (fboundp 'warn) 'warn 'message))
   3.162-
   3.163-  (defvar paredit-sexp-error-type
   3.164-    (with-temp-buffer
   3.165-      (insert "(")
   3.166-      (condition-case condition
   3.167-          (backward-sexp)
   3.168-        (error (if (eq (car condition) 'error)
   3.169-                   (paredit-warn "%s%s%s%s%s"
   3.170-                                 "Paredit is unable to discriminate"
   3.171-                                 " S-expression parse errors from"
   3.172-                                 " other errors. "
   3.173-                                 " This may cause obscure problems. "
   3.174-                                 " Please upgrade Emacs."))
   3.175-               (car condition)))))
   3.176-
   3.177-  (defmacro paredit-handle-sexp-errors (body &rest handler)
   3.178-    `(condition-case ()
   3.179-         ,body
   3.180-       (,paredit-sexp-error-type ,@handler)))
   3.181-
   3.182-  (put 'paredit-handle-sexp-errors 'lisp-indent-function 1)
   3.183-
   3.184-  (defmacro paredit-ignore-sexp-errors (&rest body)
   3.185-    `(paredit-handle-sexp-errors (progn ,@body)
   3.186-       nil))
   3.187-
   3.188-  (put 'paredit-ignore-sexp-errors 'lisp-indent-function 0)
   3.189-
   3.190-  (defmacro paredit-preserving-column (&rest body)
   3.191-    "Evaluate BODY and restore point to former column, relative to code.
   3.192-Assumes BODY will change only indentation.
   3.193-If point was on code, it moves with the code.
   3.194-If point was on indentation, it stays in indentation."
   3.195-    (let ((column (make-symbol "column"))
   3.196-          (indentation (make-symbol "indentation")))
   3.197-      `(let ((,column (paredit-current-column))
   3.198-             (,indentation (paredit-current-indentation)))
   3.199-         (let ((value (progn ,@body)))
   3.200-           (paredit-restore-column ,column ,indentation)
   3.201-           value))))
   3.202-
   3.203-  (put 'paredit-preserving-column 'lisp-indent-function 0)
   3.204-
   3.205-  nil)
   3.206-
   3.207-;;;; Minor Mode Definition
   3.208-
   3.209-(defvar paredit-lighter " Paredit"
   3.210-  "Mode line lighter Paredit Mode.")
   3.211-
   3.212-(defvar paredit-mode-map (make-sparse-keymap)
   3.213-  "Keymap for the paredit minor mode.")
   3.214-
   3.215-(defvar paredit-override-check-parens-function
   3.216-  (lambda (condition) (declare ignore condition) nil)
   3.217-  "Function to tell whether unbalanced text should inhibit Paredit Mode.")
   3.218-
   3.219-;;;###autoload
   3.220-(define-minor-mode paredit-mode
   3.221-  "Minor mode for pseudo-structurally editing Lisp code.
   3.222-With a prefix argument, enable Paredit Mode even if there are
   3.223-  unbalanced parentheses in the buffer.
   3.224-Paredit behaves badly if parentheses are unbalanced, so exercise
   3.225-  caution when forcing Paredit Mode to be enabled, and consider
   3.226-  fixing unbalanced parentheses instead.
   3.227-\\<paredit-mode-map>"
   3.228-  :lighter paredit-lighter
   3.229-  ;; Setting `paredit-mode' to false here aborts enabling Paredit Mode.
   3.230-  (if (and paredit-mode
   3.231-           (not current-prefix-arg))
   3.232-      (condition-case condition
   3.233-          (check-parens)
   3.234-        (error
   3.235-         (if (not (funcall paredit-override-check-parens-function condition))
   3.236-             (progn (setq paredit-mode nil)
   3.237-                    (signal (car condition) (cdr condition))))))))
   3.238-
   3.239-(defun paredit-override-check-parens-interactively (condition)
   3.240-  (y-or-n-p (format "Enable Paredit Mode despite condition %S? " condition)))
   3.241-
   3.242-;;;###autoload
   3.243-(defun enable-paredit-mode ()
   3.244-  "Turn on pseudo-structural editing of Lisp code."
   3.245-  (interactive)
   3.246-  (paredit-mode +1))
   3.247-
   3.248-(defun disable-paredit-mode ()
   3.249-  "Turn off pseudo-structural editing of Lisp code."
   3.250-  (interactive)
   3.251-  (paredit-mode -1))
   3.252-
   3.253-(defvar paredit-backward-delete-key
   3.254-  (xcond ((paredit-xemacs-p)    "BS")
   3.255-         ((paredit-gnu-emacs-p) "DEL")))
   3.256-
   3.257-(defvar paredit-forward-delete-keys
   3.258-  (xcond ((paredit-xemacs-p)    '("DEL"))
   3.259-         ((paredit-gnu-emacs-p) '("<delete>" "<deletechar>"))))
   3.260-
   3.261-;;;; Paredit Keys
   3.262-
   3.263-;;; Separating the definition and initialization of this variable
   3.264-;;; simplifies the development of paredit, since re-evaluating DEFVAR
   3.265-;;; forms doesn't actually do anything.
   3.266-
   3.267-(defvar paredit-commands nil
   3.268-  "List of paredit commands with their keys and examples.")
   3.269-
   3.270-;;; Each specifier is of the form:
   3.271-;;;   (key[s] function (example-input example-output) ...)
   3.272-;;; where key[s] is either a single string suitable for passing to KBD
   3.273-;;; or a list of such strings.  Entries in this list may also just be
   3.274-;;; strings, in which case they are headings for the next entries.
   3.275-
   3.276-(progn (setq paredit-commands
   3.277- `(
   3.278-   "Basic Insertion Commands"
   3.279-   ("("         paredit-open-round
   3.280-                ("(a b |c d)"
   3.281-                 "(a b (|) c d)")
   3.282-                ("(foo \"bar |baz\" quux)"
   3.283-                 "(foo \"bar (|baz\" quux)"))
   3.284-   (")"         paredit-close-round
   3.285-                ("(a b |c   )" "(a b c)|")
   3.286-                ("; Hello,| world!"
   3.287-                 "; Hello,)| world!"))
   3.288-   ("M-)"       paredit-close-round-and-newline
   3.289-                ("(defun f (x|  ))"
   3.290-                 "(defun f (x)\n  |)")
   3.291-                ("; (Foo.|"
   3.292-                 "; (Foo.)|"))
   3.293-   ("["         paredit-open-square
   3.294-                ("(a b |c d)"
   3.295-                 "(a b [|] c d)")
   3.296-                ("(foo \"bar |baz\" quux)"
   3.297-                 "(foo \"bar [|baz\" quux)"))
   3.298-   ("]"         paredit-close-square
   3.299-                ("(define-key keymap [frob|  ] 'frobnicate)"
   3.300-                 "(define-key keymap [frob]| 'frobnicate)")
   3.301-                ("; [Bar.|"
   3.302-                 "; [Bar.]|"))
   3.303-
   3.304-   ("\""        paredit-doublequote
   3.305-                ("(frob grovel |full lexical)"
   3.306-                 "(frob grovel \"|\" full lexical)"
   3.307-                 "(frob grovel \"\"| full lexical)")
   3.308-                ("(foo \"bar |baz\" quux)"
   3.309-                 "(foo \"bar \\\"|baz\" quux)")
   3.310-                ("(frob grovel)   ; full |lexical"
   3.311-                 "(frob grovel)   ; full \"|lexical"))
   3.312-   ("M-\""      paredit-meta-doublequote
   3.313-                ("(foo \"bar |baz\" quux)"
   3.314-                 "(foo \"bar baz\"| quux)")
   3.315-                ("(foo |(bar #\\x \"baz \\\\ quux\") zot)"
   3.316-                 ,(concat "(foo \"|(bar #\\\\x \\\"baz \\\\"
   3.317-                          "\\\\ quux\\\")\" zot)")))
   3.318-   ("\\"        paredit-backslash
   3.319-                ("(string #|)\n  ; Character to escape: x"
   3.320-                 "(string #\\x|)")
   3.321-                ("\"foo|bar\"\n  ; Character to escape: \""
   3.322-                 "\"foo\\\"|bar\""))
   3.323-   (";"         paredit-semicolon
   3.324-                ("|(frob grovel)"
   3.325-                 ";|(frob grovel)")
   3.326-                ("(frob |grovel)"
   3.327-                 "(frob ;|grovel\n )")
   3.328-                ("(frob |grovel (bloit\n               zargh))"
   3.329-                 "(frob ;|grovel\n (bloit\n  zargh))")
   3.330-                ("(frob grovel)          |"
   3.331-                 "(frob grovel)          ;|"))
   3.332-   ("M-;"       paredit-comment-dwim
   3.333-                ("(foo |bar)   ; baz"
   3.334-                 "(foo bar)                               ; |baz")
   3.335-                ("(frob grovel)|"
   3.336-                 "(frob grovel)                           ;|")
   3.337-                ("(zot (foo bar)\n|\n     (baz quux))"
   3.338-                 "(zot (foo bar)\n     ;; |\n     (baz quux))")
   3.339-                ("(zot (foo bar) |(baz quux))"
   3.340-                 "(zot (foo bar)\n     ;; |\n     (baz quux))")
   3.341-                ("|(defun hello-world ...)"
   3.342-                 ";;; |\n(defun hello-world ...)"))
   3.343-
   3.344-   (()          paredit-newline
   3.345-                ("(let ((n (frobbotz))) |(display (+ n 1)\nport))"
   3.346-                 ,(concat "(let ((n (frobbotz)))"
   3.347-                          "\n  |(display (+ n 1)"
   3.348-                          "\n           port))")))
   3.349-   ("RET"       paredit-RET)
   3.350-   ("C-j"       paredit-C-j)
   3.351-
   3.352-   "Deleting & Killing"
   3.353-   (,paredit-forward-delete-keys
   3.354-                paredit-forward-delete
   3.355-                ("(quu|x \"zot\")" "(quu| \"zot\")")
   3.356-                ("(quux |\"zot\")"
   3.357-                 "(quux \"|zot\")"
   3.358-                 "(quux \"|ot\")")
   3.359-                ("(foo (|) bar)" "(foo | bar)")
   3.360-                ("|(foo bar)" "(|foo bar)"))
   3.361-   (,paredit-backward-delete-key
   3.362-                paredit-backward-delete
   3.363-                ("(\"zot\" q|uux)" "(\"zot\" |uux)")
   3.364-                ("(\"zot\"| quux)"
   3.365-                 "(\"zot|\" quux)"
   3.366-                 "(\"zo|\" quux)")
   3.367-                ("(foo (|) bar)" "(foo | bar)")
   3.368-                ("(foo bar)|" "(foo bar|)"))
   3.369-   ("C-d"       paredit-delete-char
   3.370-                ("(quu|x \"zot\")" "(quu| \"zot\")")
   3.371-                ("(quux |\"zot\")"
   3.372-                 "(quux \"|zot\")"
   3.373-                 "(quux \"|ot\")")
   3.374-                ("(foo (|) bar)" "(foo | bar)")
   3.375-                ("|(foo bar)" "(|foo bar)"))
   3.376-   ("C-k"       paredit-kill
   3.377-                ("(foo bar)|     ; Useless comment!"
   3.378-                 "(foo bar)|")
   3.379-                ("(|foo bar)     ; Useful comment!"
   3.380-                 "(|)     ; Useful comment!")
   3.381-                ("|(foo bar)     ; Useless line!"
   3.382-                 "|")
   3.383-                ("(foo \"|bar baz\"\n     quux)"
   3.384-                 "(foo \"|\"\n     quux)"))
   3.385-   ("M-d"       paredit-forward-kill-word
   3.386-                ("|(foo bar)    ; baz"
   3.387-                 "(| bar)    ; baz"
   3.388-                 "(|)    ; baz"
   3.389-                 "()    ;|")
   3.390-                (";;;| Frobnicate\n(defun frobnicate ...)"
   3.391-                 ";;;|\n(defun frobnicate ...)"
   3.392-                 ";;;\n(| frobnicate ...)"))
   3.393-   (,(concat "M-" paredit-backward-delete-key)
   3.394-                paredit-backward-kill-word
   3.395-                ("(foo bar)    ; baz\n(quux)|"
   3.396-                 "(foo bar)    ; baz\n(|)"
   3.397-                 "(foo bar)    ; |\n()"
   3.398-                 "(foo |)    ; \n()"
   3.399-                 "(|)    ; \n()"))
   3.400-
   3.401-   "Movement & Navigation"
   3.402-   ("C-M-f"     paredit-forward
   3.403-                ("(foo |(bar baz) quux)"
   3.404-                 "(foo (bar baz)| quux)")
   3.405-                ("(foo (bar)|)"
   3.406-                 "(foo (bar))|"))
   3.407-   ("C-M-b"     paredit-backward
   3.408-                ("(foo (bar baz)| quux)"
   3.409-                 "(foo |(bar baz) quux)")
   3.410-                ("(|(foo) bar)"
   3.411-                 "|((foo) bar)"))
   3.412-   ("C-M-u"     paredit-backward-up)
   3.413-   ("C-M-d"     paredit-forward-down)
   3.414-   ("C-M-p"     paredit-backward-down)  ; Built-in, these are FORWARD-
   3.415-   ("C-M-n"     paredit-forward-up)     ; & BACKWARD-LIST, which have
   3.416-                                        ; no need given C-M-f & C-M-b.
   3.417-
   3.418-   "Depth-Changing Commands"
   3.419-   ("M-("       paredit-wrap-round
   3.420-                ("(foo |bar baz)"
   3.421-                 "(foo (|bar) baz)"))
   3.422-   ("M-s"       paredit-splice-sexp
   3.423-                ("(foo (bar| baz) quux)"
   3.424-                 "(foo bar| baz quux)"))
   3.425-   (("M-<up>" "ESC <up>")
   3.426-                paredit-splice-sexp-killing-backward
   3.427-                ("(foo (let ((x 5)) |(sqrt n)) bar)"
   3.428-                 "(foo |(sqrt n) bar)"))
   3.429-   (("M-<down>" "ESC <down>")
   3.430-                paredit-splice-sexp-killing-forward
   3.431-                ("(a (b c| d e) f)"
   3.432-                 "(a b c| f)"))
   3.433-   ("M-r"       paredit-raise-sexp
   3.434-                ("(dynamic-wind in (lambda () |body) out)"
   3.435-                 "(dynamic-wind in |body out)"
   3.436-                 "|body"))
   3.437-   ("M-?"       paredit-convolute-sexp
   3.438-                ("(let ((x 5) (y 3)) (frob |(zwonk)) (wibblethwop))"
   3.439-                 "(frob |(let ((x 5) (y 3)) (zwonk) (wibblethwop)))"))
   3.440-
   3.441-   "Barfage & Slurpage"
   3.442-   (("C-)" "C-<right>")
   3.443-                paredit-forward-slurp-sexp
   3.444-                ("(foo (bar |baz) quux zot)"
   3.445-                 "(foo (bar |baz quux) zot)")
   3.446-                ("(a b ((c| d)) e f)"
   3.447-                 "(a b ((c| d) e) f)"))
   3.448-   (("C-}" "C-<left>")
   3.449-                paredit-forward-barf-sexp
   3.450-                ("(foo (bar |baz quux) zot)"
   3.451-                 "(foo (bar |baz) quux zot)"))
   3.452-   (("C-(" "C-M-<left>" "ESC C-<left>")
   3.453-                paredit-backward-slurp-sexp
   3.454-                ("(foo bar (baz| quux) zot)"
   3.455-                 "(foo (bar baz| quux) zot)")
   3.456-                ("(a b ((c| d)) e f)"
   3.457-                 "(a (b (c| d)) e f)"))
   3.458-   (("C-{" "C-M-<right>" "ESC C-<right>")
   3.459-                paredit-backward-barf-sexp
   3.460-                ("(foo (bar baz |quux) zot)"
   3.461-                 "(foo bar (baz |quux) zot)"))
   3.462-
   3.463-   "Miscellaneous Commands"
   3.464-   ("M-S"       paredit-split-sexp
   3.465-                ("(hello| world)"
   3.466-                 "(hello)| (world)")
   3.467-                ("\"Hello, |world!\""
   3.468-                 "\"Hello, \"| \"world!\""))
   3.469-   ("M-J"       paredit-join-sexps
   3.470-                ("(hello)| (world)"
   3.471-                 "(hello| world)")
   3.472-                ("\"Hello, \"| \"world!\""
   3.473-                 "\"Hello, |world!\"")
   3.474-                ("hello-\n|  world"
   3.475-                 "hello-|world"))
   3.476-   ("C-c C-M-l" paredit-recenter-on-sexp)
   3.477-   ("M-q"       paredit-reindent-defun)
   3.478-   ))
   3.479-       nil)                             ; end of PROGN
   3.480-
   3.481-;;;;; Command Examples
   3.482-
   3.483-(eval-and-compile
   3.484-  (defmacro paredit-do-commands (vars string-case &rest body)
   3.485-    (let ((spec     (nth 0 vars))
   3.486-          (keys     (nth 1 vars))
   3.487-          (fn       (nth 2 vars))
   3.488-          (examples (nth 3 vars)))
   3.489-      `(dolist (,spec paredit-commands)
   3.490-         (if (stringp ,spec)
   3.491-             ,string-case
   3.492-           (let ((,keys (let ((k (car ,spec)))
   3.493-                          (cond ((stringp k) (list k))
   3.494-                                ((listp k) k)
   3.495-                                (t (error "Invalid paredit command %s."
   3.496-                                          ,spec)))))
   3.497-                 (,fn (cadr ,spec))
   3.498-                 (,examples (cddr ,spec)))
   3.499-             ,@body)))))
   3.500-
   3.501-  (put 'paredit-do-commands 'lisp-indent-function 2))
   3.502-
   3.503-(defun paredit-define-keys ()
   3.504-  (paredit-do-commands (spec keys fn examples)
   3.505-      nil       ; string case
   3.506-    (dolist (key keys)
   3.507-      (define-key paredit-mode-map (read-kbd-macro key) fn))))
   3.508-
   3.509-(defun paredit-function-documentation (fn)
   3.510-  (let ((original-doc (get fn 'paredit-original-documentation))
   3.511-        (doc (documentation fn 'function-documentation)))
   3.512-    (or original-doc
   3.513-        (progn (put fn 'paredit-original-documentation doc)
   3.514-               doc))))
   3.515-
   3.516-(defun paredit-annotate-mode-with-examples ()
   3.517-  (let ((contents
   3.518-         (list (paredit-function-documentation 'paredit-mode))))
   3.519-    (paredit-do-commands (spec keys fn examples)
   3.520-        (push (concat "\n\n" spec "\n")
   3.521-              contents)
   3.522-      (let ((name (symbol-name fn)))
   3.523-        (if (string-match (symbol-name 'paredit-) name)
   3.524-            (push (concat "\n\n\\[" name "]\t" name
   3.525-                          (if examples
   3.526-                              (mapconcat (lambda (example)
   3.527-                                           (concat
   3.528-                                            "\n"
   3.529-                                            (mapconcat 'identity
   3.530-                                                       example
   3.531-                                                       "\n  --->\n")
   3.532-                                            "\n"))
   3.533-                                         examples
   3.534-                                         "")
   3.535-                              "\n  (no examples)\n"))
   3.536-                  contents))))
   3.537-    (put 'paredit-mode 'function-documentation
   3.538-         (apply 'concat (reverse contents))))
   3.539-  ;; PUT returns the huge string we just constructed, which we don't
   3.540-  ;; want it to return.
   3.541-  nil)
   3.542-
   3.543-(defun paredit-annotate-functions-with-examples ()
   3.544-  (paredit-do-commands (spec keys fn examples)
   3.545-      nil       ; string case
   3.546-    (put fn 'function-documentation
   3.547-         (concat (paredit-function-documentation fn)
   3.548-                 "\n\n\\<paredit-mode-map>\\[" (symbol-name fn) "]\n"
   3.549-                 (mapconcat (lambda (example)
   3.550-                              (concat "\n"
   3.551-                                      (mapconcat 'identity
   3.552-                                                 example
   3.553-                                                 "\n  ->\n")
   3.554-                                      "\n"))
   3.555-                            examples
   3.556-                            "")))))
   3.557-
   3.558-;;;;; HTML Examples
   3.559-
   3.560-(defun paredit-insert-html-examples ()
   3.561-  "Insert HTML for a paredit quick reference table."
   3.562-  (interactive)
   3.563-  (let ((insert-lines
   3.564-         (lambda (&rest lines) (dolist (line lines) (insert line) (newline))))
   3.565-        (initp nil))
   3.566-    (paredit-do-commands (spec keys fn examples)
   3.567-        (progn (if initp
   3.568-                   (funcall insert-lines "</table>")
   3.569-                   (setq initp t))
   3.570-               (funcall insert-lines (concat "<h3>" spec "</h3>"))
   3.571-               (funcall insert-lines "<table>"))
   3.572-      (let ((name (symbol-name fn))
   3.573-            (keys
   3.574-             (mapconcat (lambda (key)
   3.575-                          (concat "<tt>" (paredit-html-quote key) "</tt>"))
   3.576-                        keys
   3.577-                        ", ")))
   3.578-        (funcall insert-lines "<tr>")
   3.579-        (funcall insert-lines (concat "  <th align=\"left\">" keys "</th>"))
   3.580-        (funcall insert-lines (concat "  <th align=\"left\">" name "</th>"))
   3.581-        (funcall insert-lines "</tr>")
   3.582-        (funcall insert-lines
   3.583-                 "<tr><td colspan=\"2\"><table cellpadding=\"5\"><tr>")
   3.584-        (dolist (example examples)
   3.585-          (let ((prefix "<td><table border=\"1\"><tr><td><table><tr><td><pre>")
   3.586-                (examples
   3.587-                 (mapconcat 'paredit-html-quote
   3.588-                            example
   3.589-                            (concat "</pre></td></tr>"
   3.590-                                    "<tr><th>&darr;</th></tr>"
   3.591-                                    "<tr><td><pre>")))
   3.592-                (suffix "</pre></td></tr></table></td></tr></table></td>"))
   3.593-            (funcall insert-lines (concat prefix examples suffix))))
   3.594-        (funcall insert-lines "</tr></table></td></tr>")))
   3.595-    (funcall insert-lines "</table>")))
   3.596-
   3.597-(defun paredit-html-quote (string)
   3.598-  (with-temp-buffer
   3.599-    (dotimes (i (length string))
   3.600-      (insert (let ((c (elt string i)))
   3.601-                (cond ((eq c ?\<) "&lt;")
   3.602-                      ((eq c ?\>) "&gt;")
   3.603-                      ((eq c ?\&) "&amp;")
   3.604-                      ((eq c ?\') "&apos;")
   3.605-                      ((eq c ?\") "&quot;")
   3.606-                      (t c)))))
   3.607-    (buffer-string)))
   3.608-
   3.609-;;;; Delimiter Insertion
   3.610-
   3.611-(eval-and-compile
   3.612-  (defun paredit-conc-name (&rest strings)
   3.613-    (intern (apply 'concat strings)))
   3.614-
   3.615-  (defmacro define-paredit-pair (open close name)
   3.616-    `(progn
   3.617-       (defun ,(paredit-conc-name "paredit-open-" name) (&optional n)
   3.618-         ,(concat "Insert a balanced " name " pair.
   3.619-With a prefix argument N, put the closing " name " after N
   3.620-  S-expressions forward.
   3.621-If the region is active, `transient-mark-mode' is enabled, and the
   3.622-  region's start and end fall in the same parenthesis depth, insert a
   3.623-  " name " pair around the region.
   3.624-If in a string or a comment, insert a single " name ".
   3.625-If in a character literal, do nothing.  This prevents changing what was
   3.626-  in the character literal to a meaningful delimiter unintentionally.")
   3.627-         (interactive "P")
   3.628-         (cond ((or (paredit-in-string-p)
   3.629-                    (paredit-in-comment-p))
   3.630-                (insert ,open))
   3.631-               ((not (paredit-in-char-p))
   3.632-                (paredit-insert-pair n ,open ,close 'goto-char)
   3.633-                (save-excursion (backward-up-list) (indent-sexp)))))
   3.634-       (defun ,(paredit-conc-name "paredit-close-" name) ()
   3.635-         ,(concat "Move past one closing delimiter and reindent.
   3.636-\(Agnostic to the specific closing delimiter.)
   3.637-If in a string or comment, insert a single closing " name ".
   3.638-If in a character literal, do nothing.  This prevents changing what was
   3.639-  in the character literal to a meaningful delimiter unintentionally.")
   3.640-         (interactive)
   3.641-         (paredit-move-past-close ,close))
   3.642-       (defun ,(paredit-conc-name "paredit-close-" name "-and-newline") ()
   3.643-         ,(concat "Move past one closing delimiter, add a newline,"
   3.644-                  " and reindent.
   3.645-If there was a margin comment after the closing delimiter, preserve it
   3.646-  on the same line.")
   3.647-         (interactive)
   3.648-         (paredit-move-past-close-and-newline ,close))
   3.649-       (defun ,(paredit-conc-name "paredit-wrap-" name)
   3.650-           (&optional argument)
   3.651-         ,(concat "Wrap the following S-expression.
   3.652-See `paredit-wrap-sexp' for more details.")
   3.653-         (interactive "P")
   3.654-         (paredit-wrap-sexp argument ,open ,close))
   3.655-       (add-to-list 'paredit-wrap-commands
   3.656-                    ',(paredit-conc-name "paredit-wrap-" name)))))
   3.657-
   3.658-(defvar paredit-wrap-commands '(paredit-wrap-sexp)
   3.659-  "List of paredit commands that wrap S-expressions.
   3.660-Used by `paredit-yank-pop'; for internal paredit use only.")
   3.661-
   3.662-(define-paredit-pair ?\( ?\) "round")
   3.663-(define-paredit-pair ?\[ ?\] "square")
   3.664-(define-paredit-pair ?\{ ?\} "curly")
   3.665-(define-paredit-pair ?\< ?\> "angled")
   3.666-
   3.667-;;; Aliases for the old names.
   3.668-
   3.669-(defalias 'paredit-open-parenthesis 'paredit-open-round)
   3.670-(defalias 'paredit-close-parenthesis 'paredit-close-round)
   3.671-(defalias 'paredit-close-parenthesis-and-newline
   3.672-  'paredit-close-round-and-newline)
   3.673-
   3.674-(defalias 'paredit-open-bracket 'paredit-open-square)
   3.675-(defalias 'paredit-close-bracket 'paredit-close-square)
   3.676-(defalias 'paredit-close-bracket-and-newline
   3.677-  'paredit-close-square-and-newline)
   3.678-
   3.679-(defun paredit-move-past-close (close)
   3.680-  (paredit-move-past-close-and close
   3.681-    (lambda ()
   3.682-      (paredit-blink-paren-match nil))))
   3.683-
   3.684-(defun paredit-move-past-close-and-newline (close)
   3.685-  (paredit-move-past-close-and close
   3.686-    (lambda ()
   3.687-      (let ((comment.point (paredit-find-comment-on-line)))
   3.688-        (newline)
   3.689-        (if comment.point
   3.690-            (save-excursion
   3.691-              (forward-line -1)
   3.692-              (end-of-line)
   3.693-              (indent-to (cdr comment.point))
   3.694-              (insert (car comment.point)))))
   3.695-      (lisp-indent-line)
   3.696-      (paredit-ignore-sexp-errors (indent-sexp))
   3.697-      (paredit-blink-paren-match t))))
   3.698-
   3.699-(defun paredit-move-past-close-and (close if-moved)
   3.700-  (if (or (paredit-in-string-p)
   3.701-          (paredit-in-comment-p))
   3.702-      (insert close)
   3.703-    (if (paredit-in-char-p) (forward-char))
   3.704-    (paredit-move-past-close-and-reindent close)
   3.705-    (funcall if-moved)))
   3.706-
   3.707-(defun paredit-find-comment-on-line ()
   3.708-  "Find a margin comment on the current line.
   3.709-Return nil if there is no such comment or if there is anything but
   3.710-  whitespace until such a comment.
   3.711-If such a comment exists, delete the comment (including all leading
   3.712-  whitespace) and return a cons whose car is the comment as a string
   3.713-  and whose cdr is the point of the comment's initial semicolon,
   3.714-  relative to the start of the line."
   3.715-  (save-excursion
   3.716-    (paredit-skip-whitespace t (point-at-eol))
   3.717-    (and (eq ?\; (char-after))
   3.718-         (not (eq ?\; (char-after (1+ (point)))))
   3.719-         (not (or (paredit-in-string-p)
   3.720-                  (paredit-in-char-p)))
   3.721-         (let* ((start                  ;Move to before the semicolon.
   3.722-                 (progn (backward-char) (point)))
   3.723-                (comment
   3.724-                 (buffer-substring start (point-at-eol))))
   3.725-           (paredit-skip-whitespace nil (point-at-bol))
   3.726-           (delete-region (point) (point-at-eol))
   3.727-           (cons comment (- start (point-at-bol)))))))
   3.728-
   3.729-(defun paredit-insert-pair (n open close forward)
   3.730-  (let* ((regionp
   3.731-          (and (paredit-region-active-p)
   3.732-               (paredit-region-safe-for-insert-p)))
   3.733-         (end
   3.734-          (and regionp
   3.735-               (not n)
   3.736-               (prog1 (region-end) (goto-char (region-beginning))))))
   3.737-    (let ((spacep (paredit-space-for-delimiter-p nil open)))
   3.738-      (if spacep (insert " "))
   3.739-      (insert open)
   3.740-      (save-excursion
   3.741-        ;; Move past the desired region.
   3.742-        (cond (n
   3.743-               (funcall forward
   3.744-                        (paredit-scan-sexps-hack (point)
   3.745-                                                 (prefix-numeric-value n))))
   3.746-              (regionp
   3.747-               (funcall forward (+ end (if spacep 2 1)))))
   3.748-        ;; The string case can happen if we are inserting string
   3.749-        ;; delimiters.  The comment case may happen by moving to the
   3.750-        ;; end of a buffer that has a comment with no trailing newline.
   3.751-        (if (and (not (paredit-in-string-p))
   3.752-                 (paredit-in-comment-p))
   3.753-            (newline))
   3.754-        (insert close)
   3.755-        (if (paredit-space-for-delimiter-p t close)
   3.756-            (insert " "))))))
   3.757-
   3.758-;++ This needs a better name...
   3.759-
   3.760-(defun paredit-scan-sexps-hack (point n)
   3.761-  (save-excursion
   3.762-    (goto-char point)
   3.763-    (let ((direction (if (< 0 n) +1 -1))
   3.764-          (magnitude (abs n))
   3.765-          (count 0))
   3.766-      (catch 'exit
   3.767-        (while (< count magnitude)
   3.768-          (let ((p
   3.769-                 (paredit-handle-sexp-errors (scan-sexps (point) direction)
   3.770-                   nil)))
   3.771-            (if (not p) (throw 'exit nil))
   3.772-            (goto-char p))
   3.773-          (setq count (+ count 1)))))
   3.774-    (point)))
   3.775-
   3.776-(defun paredit-region-safe-for-insert-p ()
   3.777-  (save-excursion
   3.778-    (let ((beginning (region-beginning))
   3.779-          (end (region-end)))
   3.780-      (goto-char beginning)
   3.781-      (let* ((beginning-state (paredit-current-parse-state))
   3.782-             (end-state
   3.783-              (parse-partial-sexp beginning end nil nil beginning-state)))
   3.784-        (and (=  (nth 0 beginning-state)   ; 0. depth in parens
   3.785-                 (nth 0 end-state))
   3.786-             (eq (nth 3 beginning-state)   ; 3. non-nil if inside a
   3.787-                 (nth 3 end-state))        ;    string
   3.788-             (eq (nth 4 beginning-state)   ; 4. comment status, yada
   3.789-                 (nth 4 end-state))
   3.790-             (eq (nth 5 beginning-state)   ; 5. t if following char
   3.791-                 (nth 5 end-state)))))))   ;    quote
   3.792-
   3.793-(defvar paredit-space-for-delimiter-predicates nil
   3.794-  "List of predicates for whether to put space by delimiter at point.
   3.795-Each predicate is a function that is is applied to two arguments, ENDP
   3.796-  and DELIMITER, and that returns a boolean saying whether to put a
   3.797-  space next to the delimiter -- before/after the delimiter if ENDP is
   3.798-  false/true, respectively.
   3.799-If any predicate returns false, no space is inserted: every predicate
   3.800-  has veto power.
   3.801-Each predicate may assume that the point is not at the beginning/end of
   3.802-  the buffer, and that the point is preceded/followed by a word
   3.803-  constituent, symbol constituent, string quote, or delimiter matching
   3.804-  DELIMITER, if ENDP is false/true, respectively.
   3.805-Each predicate should examine only text before/after the point if ENDP is
   3.806-  false/true, respectively.")
   3.807-
   3.808-(defun paredit-space-for-delimiter-p (endp delimiter)
   3.809-  ;; If at the buffer limit, don't insert a space.  If there is a word,
   3.810-  ;; symbol, other quote, or non-matching parenthesis delimiter (i.e. a
   3.811-  ;; close when want an open the string or an open when we want to
   3.812-  ;; close the string), do insert a space.
   3.813-  (and (not (if endp (eobp) (bobp)))
   3.814-       (memq (char-syntax (if endp (char-after) (char-before)))
   3.815-             (list ?w ?_ ?\"
   3.816-                   (let ((matching (matching-paren delimiter)))
   3.817-                     (and matching (char-syntax matching)))
   3.818-                   (and (not endp)
   3.819-                        (eq ?\" (char-syntax delimiter))
   3.820-                        ?\) )))
   3.821-       (catch 'exit
   3.822-         (dolist (predicate paredit-space-for-delimiter-predicates)
   3.823-           (if (not (funcall predicate endp delimiter))
   3.824-               (throw 'exit nil)))
   3.825-         t)))
   3.826-
   3.827-(defun paredit-move-past-close-and-reindent (close)
   3.828-  (let ((open (paredit-missing-close)))
   3.829-    (if open
   3.830-        (if (eq close (matching-paren open))
   3.831-            (save-excursion
   3.832-              (message "Missing closing delimiter: %c" close)
   3.833-              (insert close))
   3.834-            (error "Mismatched missing closing delimiter: %c ... %c"
   3.835-                   open close))))
   3.836-  (up-list)
   3.837-  (if (catch 'return                    ; This CATCH returns T if it
   3.838-        (while t                        ; should delete leading spaces
   3.839-          (save-excursion               ; and NIL if not.
   3.840-            (let ((before-paren (1- (point))))
   3.841-              (back-to-indentation)
   3.842-              (cond ((not (eq (point) before-paren))
   3.843-                     ;; Can't call PAREDIT-DELETE-LEADING-WHITESPACE
   3.844-                     ;; here -- we must return from SAVE-EXCURSION
   3.845-                     ;; first.
   3.846-                     (throw 'return t))
   3.847-                    ((save-excursion (forward-line -1)
   3.848-                                     (end-of-line)
   3.849-                                     (paredit-in-comment-p))
   3.850-                     ;; Moving the closing delimiter any further
   3.851-                     ;; would put it into a comment, so we just
   3.852-                     ;; indent the closing delimiter where it is and
   3.853-                     ;; abort the loop, telling its continuation that
   3.854-                     ;; no leading whitespace should be deleted.
   3.855-                     (lisp-indent-line)
   3.856-                     (throw 'return nil))
   3.857-                    (t (delete-indentation)))))))
   3.858-      (paredit-delete-leading-whitespace)))
   3.859-
   3.860-(defun paredit-missing-close ()
   3.861-  (save-excursion
   3.862-    (paredit-handle-sexp-errors (backward-up-list)
   3.863-      (error "Not inside a list."))
   3.864-    (let ((open (char-after)))
   3.865-      (paredit-handle-sexp-errors (progn (forward-sexp) nil)
   3.866-        open))))
   3.867-
   3.868-(defun paredit-delete-leading-whitespace ()
   3.869-  ;; This assumes that we're on the closing delimiter already.
   3.870-  (save-excursion
   3.871-    (backward-char)
   3.872-    (while (let ((syn (char-syntax (char-before))))
   3.873-             (and (or (eq syn ?\ ) (eq syn ?-))     ; whitespace syntax
   3.874-                  ;; The above line is a perfect example of why the
   3.875-                  ;; following test is necessary.
   3.876-                  (not (paredit-in-char-p (1- (point))))))
   3.877-      (delete-char -1))))
   3.878-
   3.879-(defun paredit-blink-paren-match (another-line-p)
   3.880-  (if (and blink-matching-paren
   3.881-           (or (not show-paren-mode) another-line-p))
   3.882-      (paredit-ignore-sexp-errors
   3.883-        (save-excursion
   3.884-          (backward-sexp)
   3.885-          (forward-sexp)
   3.886-          ;; SHOW-PAREN-MODE inhibits any blinking, so we disable it
   3.887-          ;; locally here.
   3.888-          (let ((show-paren-mode nil))
   3.889-            (blink-matching-open))))))
   3.890-
   3.891-(defun paredit-doublequote (&optional n)
   3.892-  "Insert a pair of double-quotes.
   3.893-With a prefix argument N, wrap the following N S-expressions in
   3.894-  double-quotes, escaping intermediate characters if necessary.
   3.895-If the region is active, `transient-mark-mode' is enabled, and the
   3.896-  region's start and end fall in the same parenthesis depth, insert a
   3.897-  pair of double-quotes around the region, again escaping intermediate
   3.898-  characters if necessary.
   3.899-Inside a comment, insert a literal double-quote.
   3.900-At the end of a string, move past the closing double-quote.
   3.901-In the middle of a string, insert a backslash-escaped double-quote.
   3.902-If in a character literal, do nothing.  This prevents accidentally
   3.903-  changing a what was in the character literal to become a meaningful
   3.904-  delimiter unintentionally."
   3.905-  (interactive "P")
   3.906-  (cond ((paredit-in-string-p)
   3.907-         (if (eq (point) (- (paredit-enclosing-string-end) 1))
   3.908-             (forward-char)             ; Just move past the closing quote.
   3.909-           ;; Don't split a \x into an escaped backslash and a string end.
   3.910-           (if (paredit-in-string-escape-p) (forward-char))
   3.911-           (insert ?\\ ?\" )))
   3.912-        ((paredit-in-comment-p)
   3.913-         (insert ?\" ))
   3.914-        ((not (paredit-in-char-p))
   3.915-         (paredit-insert-pair n ?\" ?\" 'paredit-forward-for-quote))))
   3.916-
   3.917-(defun paredit-meta-doublequote (&optional n)
   3.918-  "Move to the end of the string.
   3.919-If not in a string, act as `paredit-doublequote'; if no prefix argument
   3.920- is specified and the region is not active or `transient-mark-mode' is
   3.921- disabled, the default is to wrap one S-expression, however, not zero."
   3.922-  (interactive "P")
   3.923-  (if (not (paredit-in-string-p))
   3.924-      (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
   3.925-      (goto-char (paredit-enclosing-string-end))))
   3.926-
   3.927-(defun paredit-meta-doublequote-and-newline (&optional n)
   3.928-  "Move to the end of the string, insert a newline, and indent.
   3.929-If not in a string, act as `paredit-doublequote'; if no prefix argument
   3.930- is specified and the region is not active or `transient-mark-mode' is
   3.931- disabled, the default is to wrap one S-expression, however, not zero."
   3.932-  (interactive "P")
   3.933-  (if (not (paredit-in-string-p))
   3.934-      (paredit-doublequote (or n (and (not (paredit-region-active-p)) 1)))
   3.935-      (progn (goto-char (paredit-enclosing-string-end))
   3.936-             (newline)
   3.937-             (lisp-indent-line)
   3.938-             (paredit-ignore-sexp-errors (indent-sexp)))))
   3.939-
   3.940-(defun paredit-forward-for-quote (end)
   3.941-  (let ((state (paredit-current-parse-state)))
   3.942-    (while (< (point) end)
   3.943-      (let ((new-state (parse-partial-sexp (point) (1+ (point))
   3.944-                                           nil nil state)))
   3.945-        (if (paredit-in-string-p new-state)
   3.946-            (if (not (paredit-in-string-escape-p))
   3.947-                (setq state new-state)
   3.948-              ;; Escape character: turn it into an escaped escape
   3.949-              ;; character by appending another backslash.
   3.950-              (insert ?\\ )
   3.951-              ;; Now the point is after both escapes, and we want to
   3.952-              ;; rescan from before the first one to after the second
   3.953-              ;; one.
   3.954-              (setq state
   3.955-                    (parse-partial-sexp (- (point) 2) (point)
   3.956-                                        nil nil state))
   3.957-              ;; Advance the end point, since we just inserted a new
   3.958-              ;; character.
   3.959-              (setq end (1+ end)))
   3.960-          ;; String: escape by inserting a backslash before the quote.
   3.961-          (backward-char)
   3.962-          (insert ?\\ )
   3.963-          ;; The point is now between the escape and the quote, and we
   3.964-          ;; want to rescan from before the escape to after the quote.
   3.965-          (setq state
   3.966-                (parse-partial-sexp (1- (point)) (1+ (point))
   3.967-                                    nil nil state))
   3.968-          ;; Advance the end point for the same reason as above.
   3.969-          (setq end (1+ end)))))))
   3.970-
   3.971-;;;; Escape Insertion
   3.972-
   3.973-(defun paredit-backslash ()
   3.974-  "Insert a backslash followed by a character to escape."
   3.975-  (interactive)
   3.976-  (cond ((paredit-in-string-p) (paredit-backslash-interactive))
   3.977-        ((paredit-in-comment-p) (insert ?\\))
   3.978-        ((paredit-in-char-p) (forward-char) (paredit-backslash-interactive))
   3.979-        (t (paredit-backslash-interactive))))
   3.980-
   3.981-(defun paredit-backslash-interactive ()
   3.982-  (insert ?\\ )
   3.983-  ;; Read a character to insert after the backslash.  If anything
   3.984-  ;; goes wrong -- the user hits delete (entering the rubout
   3.985-  ;; `character'), aborts with C-g, or enters non-character input
   3.986-  ;; -- then delete the backslash to avoid a dangling escape.
   3.987-  (let ((delete-p t))
   3.988-    (unwind-protect
   3.989-        (let ((char (read-char "Character to escape: " t)))
   3.990-          (if (not (eq char ?\^?))
   3.991-              (progn (message "Character to escape: %c" char)
   3.992-                     (insert char)
   3.993-                     (setq delete-p nil))))
   3.994-      (if delete-p
   3.995-          (progn (message "Deleting escape.")
   3.996-                 (delete-char -1))))))
   3.997-
   3.998-(defun paredit-newline ()
   3.999-  "Insert a newline and indent it.
  3.1000-This is like `newline-and-indent', but it not only indents the line
  3.1001-  that the point is on but also the S-expression following the point,
  3.1002-  if there is one.
  3.1003-Move forward one character first if on an escaped character.
  3.1004-If in a string, just insert a literal newline.
  3.1005-If in a comment and if followed by invalid structure, call
  3.1006-  `indent-new-comment-line' to keep the invalid structure in a
  3.1007-  comment."
  3.1008-  (interactive)
  3.1009-  (cond ((paredit-in-string-p)
  3.1010-         (newline))
  3.1011-        ((paredit-in-comment-p)
  3.1012-         (if (paredit-region-ok-p (point) (point-at-eol))
  3.1013-             (progn (newline-and-indent)
  3.1014-                    (paredit-ignore-sexp-errors (indent-sexp)))
  3.1015-             (indent-new-comment-line)))
  3.1016-        (t
  3.1017-         (if (paredit-in-char-p)
  3.1018-             (forward-char))
  3.1019-         (newline-and-indent)
  3.1020-         ;; Indent the following S-expression, but don't signal an
  3.1021-         ;; error if there's only a closing delimiter after the point.
  3.1022-         (paredit-ignore-sexp-errors (indent-sexp)))))
  3.1023-
  3.1024-(defun paredit-electric-indent-mode-p ()
  3.1025-  "True if Electric Indent Mode is on, false if not.
  3.1026-Electric Indent Mode is generally not compatible with paredit and
  3.1027-  users are advised to disable it, since paredit does essentially
  3.1028-  everything it tries to do better.
  3.1029-However, to mitigate the negative user experience of combining
  3.1030- Electric Indent Mode with paredit, the default key bindings for
  3.1031- RET and C-j in paredit are exchanged depending on whether
  3.1032- Electric Indent Mode is enabled."
  3.1033-  (and (boundp 'electric-indent-mode)
  3.1034-       electric-indent-mode))
  3.1035-
  3.1036-(defun paredit-RET ()
  3.1037-  "Default key binding for RET in Paredit Mode.
  3.1038-Normally, inserts a newline, like traditional Emacs RET.
  3.1039-With Electric Indent Mode enabled, inserts a newline and indents
  3.1040-  the new line, as well as any subexpressions of it on subsequent
  3.1041-  lines; see `paredit-newline' for details and examples."
  3.1042-  (interactive)
  3.1043-  (if (paredit-electric-indent-mode-p)
  3.1044-      (let ((electric-indent-mode nil))
  3.1045-        (paredit-newline))
  3.1046-    (newline)))
  3.1047-
  3.1048-(defun paredit-C-j ()
  3.1049-  "Default key binding for C-j in Paredit Mode.
  3.1050-Normally, inserts a newline and indents
  3.1051-  the new line, as well as any subexpressions of it on subsequent
  3.1052-  lines; see `paredit-newline' for details and examples.
  3.1053-With Electric Indent Mode enabled, inserts a newline, like
  3.1054-  traditional Emacs RET."
  3.1055-  (interactive)
  3.1056-  (if (paredit-electric-indent-mode-p)
  3.1057-      (let ((electric-indent-mode nil))
  3.1058-        (newline))
  3.1059-    (paredit-newline)))
  3.1060-
  3.1061-(defun paredit-reindent-defun (&optional argument)
  3.1062-  "Reindent the definition that the point is on.
  3.1063-If the point is in a string or a comment, fill the paragraph instead,
  3.1064-  and with a prefix argument, justify as well."
  3.1065-  (interactive "P")
  3.1066-  (if (or (paredit-in-string-p)
  3.1067-          (paredit-in-comment-p))
  3.1068-      (if (memq fill-paragraph-function '(t nil))
  3.1069-          (lisp-fill-paragraph argument)
  3.1070-        (funcall fill-paragraph-function argument))
  3.1071-    (paredit-preserving-column
  3.1072-      (save-excursion
  3.1073-        (end-of-defun)
  3.1074-        (beginning-of-defun)
  3.1075-        (indent-sexp)))))
  3.1076-
  3.1077-;;;; Comment Insertion
  3.1078-
  3.1079-(defun paredit-semicolon (&optional n)
  3.1080-  "Insert a semicolon.
  3.1081-With a prefix argument N, insert N semicolons.
  3.1082-If in a string, do just that and nothing else.
  3.1083-If in a character literal, move to the beginning of the character
  3.1084-  literal before inserting the semicolon.
  3.1085-If the enclosing list ends on the line after the point, break the line
  3.1086-  after the last S-expression following the point.
  3.1087-If a list begins on the line after the point but ends on a different
  3.1088-  line, break the line after the last S-expression following the point
  3.1089-  before the list."
  3.1090-  (interactive "p")
  3.1091-  (if (or (paredit-in-string-p) (paredit-in-comment-p))
  3.1092-      (insert (make-string (or n 1) ?\; ))
  3.1093-    (if (paredit-in-char-p)
  3.1094-        (backward-char 2))
  3.1095-    (let ((line-break-point (paredit-semicolon-find-line-break-point)))
  3.1096-      (if line-break-point
  3.1097-          (paredit-semicolon-with-line-break line-break-point (or n 1))
  3.1098-          (insert (make-string (or n 1) ?\; ))))))
  3.1099-
  3.1100-(defun paredit-semicolon-find-line-break-point ()
  3.1101-  (and (not (eolp))                   ;Implies (not (eobp)).
  3.1102-       (let ((eol (point-at-eol)))
  3.1103-         (save-excursion
  3.1104-           (catch 'exit
  3.1105-             (while t
  3.1106-               (let ((line-break-point (point)))
  3.1107-                 (cond ((paredit-handle-sexp-errors (progn (forward-sexp) t)
  3.1108-                          nil)
  3.1109-                        ;; Successfully advanced by an S-expression.
  3.1110-                        ;; If that S-expression started on this line
  3.1111-                        ;; and ended on another one, break here.
  3.1112-                        (cond ((not (eq eol (point-at-eol)))
  3.1113-                               (throw 'exit
  3.1114-                                      (and (save-excursion
  3.1115-                                             (backward-sexp)
  3.1116-                                             (eq eol (point-at-eol)))
  3.1117-                                           line-break-point)))
  3.1118-                              ((eobp)
  3.1119-                               (throw 'exit nil))))
  3.1120-                       ((save-excursion
  3.1121-                          (paredit-skip-whitespace t (point-at-eol))
  3.1122-                          (or (eolp) (eobp) (eq (char-after) ?\;)))
  3.1123-                        ;; Can't move further, but there's no closing
  3.1124-                        ;; delimiter we're about to clobber -- either
  3.1125-                        ;; it's on the next line or we're at the end of
  3.1126-                        ;; the buffer.  Don't break the line.
  3.1127-                        (throw 'exit nil))
  3.1128-                       (t
  3.1129-                        ;; Can't move because we hit a delimiter at the
  3.1130-                        ;; end of this line.  Break here.
  3.1131-                        (throw 'exit line-break-point))))))))))
  3.1132-
  3.1133-(defun paredit-semicolon-with-line-break (line-break-point n)
  3.1134-  (let ((line-break-marker (make-marker)))
  3.1135-    (set-marker line-break-marker line-break-point)
  3.1136-    (set-marker-insertion-type line-break-marker t)
  3.1137-    (insert (make-string (or n 1) ?\; ))
  3.1138-    (save-excursion
  3.1139-      (goto-char line-break-marker)
  3.1140-      (set-marker line-break-marker nil)
  3.1141-      (newline)
  3.1142-      (lisp-indent-line)
  3.1143-      ;; This step is redundant if we are inside a list, but even if we
  3.1144-      ;; are at the top level, we want at least to indent whatever we
  3.1145-      ;; bumped off the line.
  3.1146-      (paredit-ignore-sexp-errors (indent-sexp))
  3.1147-      (paredit-indent-sexps))))
  3.1148-
  3.1149-;;; This is all a horrible, horrible hack, primarily for GNU Emacs 21,
  3.1150-;;; in which there is no `comment-or-uncomment-region'.
  3.1151-
  3.1152-(autoload 'comment-forward "newcomment")
  3.1153-(autoload 'comment-normalize-vars "newcomment")
  3.1154-(autoload 'comment-region "newcomment")
  3.1155-(autoload 'comment-search-forward "newcomment")
  3.1156-(autoload 'uncomment-region "newcomment")
  3.1157-
  3.1158-(defun paredit-initialize-comment-dwim ()
  3.1159-  (require 'newcomment)
  3.1160-  (if (not (fboundp 'comment-or-uncomment-region))
  3.1161-      (defalias 'comment-or-uncomment-region
  3.1162-        (lambda (beginning end &optional argument)
  3.1163-          (interactive "*r\nP")
  3.1164-          (if (save-excursion (goto-char beginning)
  3.1165-                              (comment-forward (point-max))
  3.1166-                              (<= end (point)))
  3.1167-              (uncomment-region beginning end argument)
  3.1168-              (comment-region beginning end argument)))))
  3.1169-  (defalias 'paredit-initialize-comment-dwim 'comment-normalize-vars)
  3.1170-  (comment-normalize-vars))
  3.1171-
  3.1172-(defvar paredit-comment-prefix-toplevel ";;; "
  3.1173-  "String of prefix for top-level comments aligned at the left margin.")
  3.1174-
  3.1175-(defvar paredit-comment-prefix-code ";; "
  3.1176-  "String of prefix for comments indented at the same depth as code.")
  3.1177-
  3.1178-(defvar paredit-comment-prefix-margin ";"
  3.1179-  "String of prefix for comments on the same line as code in the margin.")
  3.1180-
  3.1181-(defun paredit-comment-dwim (&optional argument)
  3.1182-  "Call the Lisp comment command you want (Do What I Mean).
  3.1183-This is like `comment-dwim', but it is specialized for Lisp editing.
  3.1184-If transient mark mode is enabled and the mark is active, comment or
  3.1185-  uncomment the selected region, depending on whether it was entirely
  3.1186-  commented not not already.
  3.1187-If there is already a comment on the current line, with no prefix
  3.1188-  argument, indent to that comment; with a prefix argument, kill that
  3.1189-  comment.
  3.1190-Otherwise, insert a comment appropriate for the context and ensure that
  3.1191-  any code following the comment is moved to the next line.
  3.1192-At the top level, where indentation is calculated to be at column 0,
  3.1193-  insert a triple-semicolon comment; within code, where the indentation
  3.1194-  is calculated to be non-zero, and on the line there is either no code
  3.1195-  at all or code after the point, insert a double-semicolon comment;
  3.1196-  and if the point is after all code on the line, insert a single-
  3.1197-  semicolon margin comment at `comment-column'."
  3.1198-  (interactive "*P")
  3.1199-  (paredit-initialize-comment-dwim)
  3.1200-  (cond ((paredit-region-active-p)
  3.1201-         (comment-or-uncomment-region (region-beginning)
  3.1202-                                      (region-end)
  3.1203-                                      argument))
  3.1204-        ((paredit-comment-on-line-p)
  3.1205-         (if argument
  3.1206-             (comment-kill (if (integerp argument) argument nil))
  3.1207-             (comment-indent)))
  3.1208-        (t (paredit-insert-comment))))
  3.1209-
  3.1210-(defun paredit-comment-on-line-p ()
  3.1211-  "True if there is a comment on the line following point.
  3.1212-This is expected to be called only in `paredit-comment-dwim'; do not
  3.1213-  call it elsewhere."
  3.1214-  (save-excursion
  3.1215-    (beginning-of-line)
  3.1216-    (let ((comment-p nil))
  3.1217-      ;; Search forward for a comment beginning.  If there is one, set
  3.1218-      ;; COMMENT-P to true; if not, it will be nil.
  3.1219-      (while (progn
  3.1220-               (setq comment-p          ;t -> no error
  3.1221-                     (comment-search-forward (point-at-eol) t))
  3.1222-               (and comment-p
  3.1223-                    (or (paredit-in-string-p)
  3.1224-                        (paredit-in-char-p (1- (point))))))
  3.1225-        (forward-char))
  3.1226-      comment-p)))
  3.1227-
  3.1228-(defun paredit-insert-comment ()
  3.1229-  (let ((code-after-p
  3.1230-         (save-excursion (paredit-skip-whitespace t (point-at-eol))
  3.1231-                         (not (eolp))))
  3.1232-        (code-before-p
  3.1233-         (save-excursion (paredit-skip-whitespace nil (point-at-bol))
  3.1234-                         (not (bolp)))))
  3.1235-    (cond ((and (bolp)
  3.1236-                (let ((indent
  3.1237-                       (let ((indent (calculate-lisp-indent)))
  3.1238-                         (if (consp indent) (car indent) indent))))
  3.1239-                  (and indent (zerop indent))))
  3.1240-           ;; Top-level comment
  3.1241-           (if code-after-p (save-excursion (newline)))
  3.1242-           (insert paredit-comment-prefix-toplevel))
  3.1243-          ((or code-after-p (not code-before-p))
  3.1244-           ;; Code comment
  3.1245-           (if code-before-p
  3.1246-               (newline-and-indent)
  3.1247-               (lisp-indent-line))
  3.1248-           (insert paredit-comment-prefix-code)
  3.1249-           (if code-after-p
  3.1250-               (save-excursion
  3.1251-                 (newline)
  3.1252-                 (lisp-indent-line)
  3.1253-                 (paredit-indent-sexps))))
  3.1254-          (t
  3.1255-           ;; Margin comment
  3.1256-           (indent-to comment-column 1) ; 1 -> force one leading space
  3.1257-           (insert paredit-comment-prefix-margin)))))
  3.1258-
  3.1259-;;;; Character Deletion
  3.1260-
  3.1261-(defun paredit-delete-char (&optional argument)
  3.1262-  "Delete a character forward or move forward over a delimiter.
  3.1263-If on an opening S-expression delimiter, move forward into the
  3.1264-  S-expression.
  3.1265-If on a closing S-expression delimiter, refuse to delete unless the
  3.1266-  S-expression is empty, in which case delete the whole S-expression.
  3.1267-With a numeric prefix argument N, delete N characters forward.
  3.1268-With a `C-u' prefix argument, simply delete a character forward,
  3.1269-  without regard for delimiter balancing.
  3.1270-
  3.1271-Like `delete-char', ignores `delete-active-region'."
  3.1272-  (interactive "P")
  3.1273-  (let ((delete-active-region nil))
  3.1274-    (paredit-forward-delete argument)))
  3.1275-
  3.1276-(defun paredit-delete-active-region-p ()
  3.1277-  "True if the region is active and to be deleted."
  3.1278-  (and (paredit-region-active-p)
  3.1279-       (boundp 'delete-active-region)
  3.1280-       (eq delete-active-region t)))
  3.1281-
  3.1282-(defun paredit-kill-active-region-p ()
  3.1283-  "True if the region is active and to be killed."
  3.1284-  (and (paredit-region-active-p)
  3.1285-       (boundp 'delete-active-region)
  3.1286-       (eq delete-active-region 'kill)))
  3.1287-
  3.1288-(defun paredit-forward-delete (&optional argument)
  3.1289-  "Delete a character forward or move forward over a delimiter.
  3.1290-If on an opening S-expression delimiter, move forward into the
  3.1291-  S-expression.
  3.1292-If on a closing S-expression delimiter, refuse to delete unless the
  3.1293-  S-expression is empty, in which case delete the whole S-expression.
  3.1294-With a numeric prefix argument N, delete N characters forward.
  3.1295-With a `C-u' prefix argument, simply delete a character forward,
  3.1296-  without regard for delimiter balancing.
  3.1297-
  3.1298-If `delete-active-region' is enabled and the mark is active and
  3.1299-  no prefix argument is specified, act as `paredit-delete-region'
  3.1300-  or `paredit-kill-region' as appropriate instead."
  3.1301-  (interactive "P")
  3.1302-  (cond ((consp argument)
  3.1303-         (delete-char +1))
  3.1304-        ((integerp argument)
  3.1305-         (let ((delete-active-region nil))
  3.1306-           (if (< argument 0)
  3.1307-               (paredit-backward-delete argument)
  3.1308-             (while (> argument 0)
  3.1309-               (paredit-forward-delete)
  3.1310-               (setq argument (- argument 1))))))
  3.1311-        ((paredit-delete-active-region-p)
  3.1312-         (paredit-delete-region (region-beginning) (region-end)))
  3.1313-        ((paredit-kill-active-region-p)
  3.1314-         (paredit-kill-region (region-beginning) (region-end)))
  3.1315-        ((eobp)
  3.1316-         (delete-char +1))
  3.1317-        ((paredit-in-string-p)
  3.1318-         (paredit-forward-delete-in-string))
  3.1319-        ((paredit-in-comment-p)
  3.1320-         (paredit-forward-delete-in-comment))
  3.1321-        ((paredit-in-char-p)            ; Escape -- delete both chars.
  3.1322-         (delete-char -1)
  3.1323-         (delete-char +1))
  3.1324-        ((eq (char-after) ?\\ )         ; ditto
  3.1325-         (delete-char +2))
  3.1326-        ((let ((syn (char-syntax (char-after))))
  3.1327-           (or (eq syn ?\( )
  3.1328-               (eq syn ?\" )))
  3.1329-         (if (save-excursion
  3.1330-               (paredit-handle-sexp-errors (progn (forward-sexp) t)
  3.1331-                 nil))
  3.1332-             (forward-char)
  3.1333-           (message "Deleting spurious opening delimiter.")
  3.1334-           (delete-char +1)))
  3.1335-        ((and (not (paredit-in-char-p (1- (point))))
  3.1336-              (eq (char-syntax (char-after)) ?\) )
  3.1337-              (eq (char-before) (matching-paren (char-after))))
  3.1338-         (delete-char -1)               ; Empty list -- delete both
  3.1339-         (delete-char +1))              ;   delimiters.
  3.1340-        ((eq ?\; (char-after))
  3.1341-         (paredit-forward-delete-comment-start))
  3.1342-        ((eq (char-syntax (char-after)) ?\) )
  3.1343-         (if (paredit-handle-sexp-errors
  3.1344-                 (save-excursion (forward-char) (backward-sexp) t)
  3.1345-               nil)
  3.1346-             (message "End of list!")
  3.1347-             (progn
  3.1348-               (message "Deleting spurious closing delimiter.")
  3.1349-               (delete-char +1))))
  3.1350-        ;; Just delete a single character, if it's not a closing
  3.1351-        ;; delimiter.  (The character literal case is already handled
  3.1352-        ;; by now.)
  3.1353-        (t (delete-char +1))))
  3.1354-
  3.1355-(defun paredit-forward-delete-in-string ()
  3.1356-  (let ((start+end (paredit-string-start+end-points)))
  3.1357-    (cond ((not (eq (point) (cdr start+end)))
  3.1358-           ;; If it's not the close-quote, it's safe to delete.  But
  3.1359-           ;; first handle the case that we're in a string escape.
  3.1360-           (cond ((paredit-in-string-escape-p)
  3.1361-                  ;; We're right after the backslash, so backward
  3.1362-                  ;; delete it before deleting the escaped character.
  3.1363-                  (delete-char -1))
  3.1364-                 ((eq (char-after) ?\\ )
  3.1365-                  ;; If we're not in a string escape, but we are on a
  3.1366-                  ;; backslash, it must start the escape for the next
  3.1367-                  ;; character, so delete the backslash before deleting
  3.1368-                  ;; the next character.
  3.1369-                  (delete-char +1)))
  3.1370-           (delete-char +1))
  3.1371-          ((eq (1- (point)) (car start+end))
  3.1372-           ;; If it is the close-quote, delete only if we're also right
  3.1373-           ;; past the open-quote (i.e. it's empty), and then delete
  3.1374-           ;; both quotes.  Otherwise we refuse to delete it.
  3.1375-           (delete-char -1)
  3.1376-           (delete-char +1)))))
  3.1377-
  3.1378-(defun paredit-check-forward-delete-in-comment ()
  3.1379-  ;; Point is in a comment, possibly at eol.  We are about to delete
  3.1380-  ;; some characters forward; if we are at eol, we are about to delete
  3.1381-  ;; the line break.  Refuse to do so if if moving the next line into
  3.1382-  ;; the comment would break structure.
  3.1383-  (if (eolp)
  3.1384-      (let ((next-line-start (point-at-bol 2))
  3.1385-            (next-line-end (point-at-eol 2)))
  3.1386-        (paredit-check-region next-line-start next-line-end))))
  3.1387-
  3.1388-(defun paredit-forward-delete-in-comment ()
  3.1389-  (paredit-check-forward-delete-in-comment)
  3.1390-  (delete-char +1))
  3.1391-
  3.1392-(defun paredit-forward-delete-comment-start ()
  3.1393-  ;; Point precedes a comment start (not at eol).  Refuse to delete a
  3.1394-  ;; comment start if the comment contains unbalanced junk.
  3.1395-  (paredit-check-region (+ (point) 1) (point-at-eol))
  3.1396-  (delete-char +1))
  3.1397-
  3.1398-(defun paredit-backward-delete (&optional argument)
  3.1399-  "Delete a character backward or move backward over a delimiter.
  3.1400-If on a closing S-expression delimiter, move backward into the
  3.1401-  S-expression.
  3.1402-If on an opening S-expression delimiter, refuse to delete unless the
  3.1403-  S-expression is empty, in which case delete the whole S-expression.
  3.1404-With a numeric prefix argument N, delete N characters backward.
  3.1405-With a `C-u' prefix argument, simply delete a character backward,
  3.1406-  without regard for delimiter balancing.
  3.1407-
  3.1408-If `delete-active-region' is enabled and the mark is active and
  3.1409-  no prefix argument is specified, act as `paredit-delete-region'
  3.1410-  or `paredit-kill-region' as appropriate instead."
  3.1411-  (interactive "P")
  3.1412-  (cond ((consp argument)
  3.1413-         ;++ Should this untabify?
  3.1414-         (delete-char -1))
  3.1415-        ((integerp argument)
  3.1416-         (let ((delete-active-region nil))
  3.1417-           (if (< argument 0)
  3.1418-               (paredit-forward-delete (- 0 argument))
  3.1419-             (while (> argument 0)
  3.1420-               (paredit-backward-delete)
  3.1421-               (setq argument (- argument 1))))))
  3.1422-        ((paredit-delete-active-region-p)
  3.1423-         (paredit-delete-region (region-beginning) (region-end)))
  3.1424-        ((paredit-kill-active-region-p)
  3.1425-         (paredit-kill-region (region-beginning) (region-end)))
  3.1426-        ((bobp)
  3.1427-         (delete-char -1))
  3.1428-        ((paredit-in-string-p)
  3.1429-         (paredit-backward-delete-in-string))
  3.1430-        ((paredit-in-comment-p)
  3.1431-         (paredit-backward-delete-in-comment))
  3.1432-        ((paredit-in-char-p)            ; Escape -- delete both chars.
  3.1433-         (delete-char -1)
  3.1434-         (delete-char +1))
  3.1435-        ((paredit-in-char-p (1- (point)))
  3.1436-         (delete-char -2))              ; ditto
  3.1437-        ((let ((syn (char-syntax (char-before))))
  3.1438-           (or (eq syn ?\) )
  3.1439-               (eq syn ?\" )))
  3.1440-         (if (save-excursion
  3.1441-               (paredit-handle-sexp-errors (progn (backward-sexp) t)
  3.1442-                 nil))
  3.1443-             (backward-char)
  3.1444-           (message "Deleting spurious closing delimiter.")
  3.1445-           (delete-char -1)))
  3.1446-        ((and (eq (char-syntax (char-before)) ?\( )
  3.1447-              (eq (char-after) (matching-paren (char-before))))
  3.1448-         (delete-char -1)               ; Empty list -- delete both
  3.1449-         (delete-char +1))              ;   delimiters.
  3.1450-        ((bolp)
  3.1451-         (paredit-backward-delete-maybe-comment-end))
  3.1452-        ((eq (char-syntax (char-before)) ?\( )
  3.1453-         (if (paredit-handle-sexp-errors
  3.1454-                 (save-excursion (backward-char) (forward-sexp) t)
  3.1455-               nil)
  3.1456-             (message "Beginning of list!")
  3.1457-             (progn
  3.1458-               (message "Deleting spurious closing delimiter.")
  3.1459-               (delete-char -1))))
  3.1460-        ;; Delete it, unless it's an opening delimiter.  The case of
  3.1461-        ;; character literals is already handled by now.
  3.1462-        (t
  3.1463-         ;; Turn off the @#&*&!^&(%^ botch in GNU Emacs 24 that changed
  3.1464-         ;; `backward-delete-char' and `backward-delete-char-untabify'
  3.1465-         ;; semantically so that they delete the region in transient
  3.1466-         ;; mark mode.
  3.1467-         (let ((delete-active-region nil))
  3.1468-           (backward-delete-char-untabify +1)))))
  3.1469-
  3.1470-(defun paredit-backward-delete-in-string ()
  3.1471-  (let ((start+end (paredit-string-start+end-points)))
  3.1472-    (cond ((not (eq (1- (point)) (car start+end)))
  3.1473-           ;; If it's not the open-quote, it's safe to delete.
  3.1474-           (if (paredit-in-string-escape-p)
  3.1475-               ;; If we're on a string escape, since we're about to
  3.1476-               ;; delete the backslash, we must first delete the
  3.1477-               ;; escaped char.
  3.1478-               (delete-char +1))
  3.1479-           (delete-char -1)
  3.1480-           (if (paredit-in-string-escape-p)
  3.1481-               ;; If, after deleting a character, we find ourselves in
  3.1482-               ;; a string escape, we must have deleted the escaped
  3.1483-               ;; character, and the backslash is behind the point, so
  3.1484-               ;; backward delete it.
  3.1485-               (delete-char -1)))
  3.1486-          ((eq (point) (cdr start+end))
  3.1487-           ;; If it is the open-quote, delete only if we're also right
  3.1488-           ;; past the close-quote (i.e. it's empty), and then delete
  3.1489-           ;; both quotes.  Otherwise we refuse to delete it.
  3.1490-           (delete-char -1)
  3.1491-           (delete-char +1)))))
  3.1492-
  3.1493-(defun paredit-backward-delete-in-comment ()
  3.1494-  ;; Point is in a comment, possibly just after the comment start.
  3.1495-  ;; Refuse to delete a comment start if the comment contains
  3.1496-  ;; unbalanced junk.
  3.1497-  (if (save-excursion
  3.1498-        (backward-char)
  3.1499-        ;; Must call `paredit-in-string-p' before
  3.1500-        ;; `paredit-in-comment-p'.
  3.1501-        (not (or (paredit-in-string-p) (paredit-in-comment-p))))
  3.1502-      (paredit-check-region (point) (point-at-eol)))
  3.1503-  (backward-delete-char-untabify +1))
  3.1504-
  3.1505-(defun paredit-backward-delete-maybe-comment-end ()
  3.1506-  ;; Point is at bol, possibly just after a comment end (i.e., the
  3.1507-  ;; previous line may have had a line comment).  Refuse to delete a
  3.1508-  ;; comment end if moving the current line into the previous line's
  3.1509-  ;; comment would break structure.
  3.1510-  (if (save-excursion
  3.1511-        (backward-char)
  3.1512-        (and (not (paredit-in-string-p)) (paredit-in-comment-p)))
  3.1513-      (paredit-check-region (point-at-eol) (point-at-bol)))
  3.1514-  (delete-char -1))
  3.1515-
  3.1516-;;;; Killing
  3.1517-
  3.1518-(defun paredit-kill (&optional argument)
  3.1519-  "Kill a line as if with `kill-line', but respecting delimiters.
  3.1520-In a string, act exactly as `kill-line' but do not kill past the
  3.1521-  closing string delimiter.
  3.1522-On a line with no S-expressions on it starting after the point or
  3.1523-  within a comment, act exactly as `kill-line'.
  3.1524-Otherwise, kill all S-expressions that start after the point.
  3.1525-With a `C-u' prefix argument, just do the standard `kill-line'.
  3.1526-With a numeric prefix argument N, do `kill-line' that many times.
  3.1527-
  3.1528-If `kill-whole-line' is true, kills the newline character and
  3.1529-  indentation on the next line as well.
  3.1530-In that case, ensure there is at least one space between the
  3.1531-  preceding S-expression and whatever follows on the next line."
  3.1532-  (interactive "P")
  3.1533-  (cond (argument
  3.1534-         (kill-line (if (integerp argument) argument 1)))
  3.1535-        ((paredit-in-string-p)
  3.1536-         (paredit-kill-line-in-string))
  3.1537-        ((paredit-in-comment-p)
  3.1538-         (paredit-kill-line-in-comment))
  3.1539-        ((save-excursion (paredit-skip-whitespace t (point-at-eol))
  3.1540-                         (or (eolp) (eq (char-after) ?\; )))
  3.1541-         ;** Be careful about trailing backslashes.
  3.1542-         (if (paredit-in-char-p)
  3.1543-             (backward-char))
  3.1544-         (kill-line))
  3.1545-        (t (paredit-kill-sexps-on-line))))
  3.1546-
  3.1547-(defun paredit-kill-line-in-string ()
  3.1548-  (if (save-excursion (paredit-skip-whitespace t (point-at-eol))
  3.1549-                      (eolp))
  3.1550-      (kill-line)
  3.1551-    (save-excursion
  3.1552-      ;; Be careful not to split an escape sequence.
  3.1553-      (if (paredit-in-string-escape-p)
  3.1554-          (backward-char))
  3.1555-      (kill-region (point)
  3.1556-                   (min (point-at-eol)
  3.1557-                        (cdr (paredit-string-start+end-points)))))))
  3.1558-
  3.1559-(defun paredit-kill-line-in-comment ()
  3.1560-  ;; The variable `kill-whole-line' is not relevant: the point is in a
  3.1561-  ;; comment, and hence not at the beginning of the line.
  3.1562-  (paredit-check-forward-delete-in-comment)
  3.1563-  (kill-line))
  3.1564-
  3.1565-(defun paredit-kill-sexps-on-line ()
  3.1566-  (if (paredit-in-char-p)               ; Move past the \ and prefix.
  3.1567-      (backward-char 2))                ; (# in Scheme/CL, ? in elisp)
  3.1568-  (let ((beginning (point))
  3.1569-        (eol (point-at-eol)))
  3.1570-    (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
  3.1571-      ;; If we got to the end of the list and it's on the same line,
  3.1572-      ;; move backward past the closing delimiter before killing.  (This
  3.1573-      ;; allows something like killing the whitespace in (    ).)
  3.1574-      (if end-of-list-p (progn (up-list) (backward-char)))
  3.1575-      (if kill-whole-line
  3.1576-          (paredit-kill-sexps-on-whole-line beginning)
  3.1577-        (kill-region beginning
  3.1578-                     ;; If all of the S-expressions were on one line,
  3.1579-                     ;; i.e. we're still on that line after moving past
  3.1580-                     ;; the last one, kill the whole line, including
  3.1581-                     ;; any comments; otherwise just kill to the end of
  3.1582-                     ;; the last S-expression we found.  Be sure,
  3.1583-                     ;; though, not to kill any closing parentheses.
  3.1584-                     (if (and (not end-of-list-p)
  3.1585-                              (eq (point-at-eol) eol))
  3.1586-                         eol
  3.1587-                         (point)))))))
  3.1588-
  3.1589-;;; Move to the end of the last S-expression that started on this line,
  3.1590-;;; or to the closing delimiter if the last S-expression in this list
  3.1591-;;; and the closing delimiter both lie on this line.  Return true if
  3.1592-;;; the closing delimiter of this list is on this line, false if not.
  3.1593-;;;
  3.1594-;;; beginning is (point), and eol is (point-at-eol).  Handling of
  3.1595-;;; `kill-whole-line' is trick, and probably kind of broken.
  3.1596-
  3.1597-(defun paredit-forward-sexps-to-kill (beginning eol)
  3.1598-  (let ((end-of-list-p nil) ;Have we hit a closing delimiter on this line?
  3.1599-        (firstp t))         ;Is this still the first line?
  3.1600-    (catch 'return
  3.1601-      (while t
  3.1602-        ;; This and the `kill-whole-line' business below fix a bug that
  3.1603-        ;; inhibited any S-expression at the very end of the buffer
  3.1604-        ;; (with no trailing newline) from being deleted.  It's a
  3.1605-        ;; bizarre fix that I ought to document at some point, but I am
  3.1606-        ;; too busy at the moment to do so.
  3.1607-        (if (and kill-whole-line (eobp)) (throw 'return nil))
  3.1608-        ;; See if we can move forward, and stay on an S-expression that
  3.1609-        ;; started on this line.
  3.1610-        (save-excursion
  3.1611-          (paredit-handle-sexp-errors (forward-sexp)
  3.1612-            ;; Can't move forward -- we must have hit the end of a
  3.1613-            ;; list.  Stop here, but record whether the closing
  3.1614-            ;; delimiter occurred on the starting line.
  3.1615-            (up-list)
  3.1616-            (setq end-of-list-p (eq (point-at-eol) eol))
  3.1617-            (throw 'return nil))
  3.1618-          ;; We can move forward.  Where did we move to?  Stop if:
  3.1619-          ;;
  3.1620-          ;; (a) we hit the end of the buffer in certain circumstances
  3.1621-          ;;     (XXX why are these circumstances? necessary according
  3.1622-          ;;     to tests, need explanation), because forward-sexp
  3.1623-          ;;     didn't/won't make any progress and we'll get stuck in
  3.1624-          ;;     a loop; or
  3.1625-          ;;
  3.1626-          ;; (b) the S-expression we moved to the end to actually
  3.1627-          ;;     started on line after where we started so it's not
  3.1628-          ;;     under our jurisdiction.
  3.1629-          (if (or (and (not firstp)             ;(a)
  3.1630-                       (not kill-whole-line)
  3.1631-                       (eobp))
  3.1632-                  (paredit-handle-sexp-errors   ;(b)
  3.1633-                      (progn (backward-sexp) nil)
  3.1634-                    t)
  3.1635-                  (not (eq (point-at-eol) eol)))
  3.1636-              (throw 'return nil)))
  3.1637-        ;; Determined we can and should move forward.  Do so.
  3.1638-        (forward-sexp)
  3.1639-        ;; In certain other circumstances (XXX need explanation), if we
  3.1640-        ;; hit the end of the buffer, stop here; otherwise the next
  3.1641-        ;; forward-sexp will fail to make progress and we might get
  3.1642-        ;; stuck in a loop.
  3.1643-        (if (and firstp
  3.1644-                 (not kill-whole-line)
  3.1645-                 (eobp))
  3.1646-            (throw 'return nil))
  3.1647-        ;; We have made it past one S-expression.
  3.1648-        (setq firstp nil)))
  3.1649-    end-of-list-p))
  3.1650-
  3.1651-;;; Handle the actual kill when `kill-whole-line' is enabled.
  3.1652-;;;
  3.1653-;;; XXX This has various broken edge cases (see the xfails in test.el)
  3.1654-;;; and it doesn't make paredit-kill/yank a noop on round-trip, in an
  3.1655-;;; attempt to avoid inadvertently joining S-expressions when it
  3.1656-;;; deletes the newline.  It could use some input and logic from a user
  3.1657-;;; who relies on `kill-whole-line' and has a better sense of
  3.1658-;;; expectations.
  3.1659-
  3.1660-(defun paredit-kill-sexps-on-whole-line (beginning)
  3.1661-  (kill-region beginning
  3.1662-               (or (save-excursion     ; Delete trailing indentation...
  3.1663-                     (paredit-skip-whitespace t)
  3.1664-                     (and (not (eq (char-after) ?\; ))
  3.1665-                          (point)))
  3.1666-                   ;; ...or just use the point past the newline, if
  3.1667-                   ;; we encounter a comment.
  3.1668-                   (point-at-eol)))
  3.1669-  (cond ((save-excursion (paredit-skip-whitespace nil (point-at-bol))
  3.1670-                         (bolp))
  3.1671-         ;; Nothing but indentation before the point, so indent it.
  3.1672-         (lisp-indent-line))
  3.1673-        ((eobp) nil)       ; Protect the CHAR-SYNTAX below against NIL.
  3.1674-        ;; Insert a space to avoid invalid joining if necessary.
  3.1675-        ((let ((syn-before (char-syntax (char-before)))
  3.1676-               (syn-after  (char-syntax (char-after))))
  3.1677-           (and (memq syn-before '(?\) ?\" ?_ ?w))
  3.1678-                (memq syn-after '(?\( ?\" ?_ ?w))))
  3.1679-         (save-excursion (insert " ")))))
  3.1680-
  3.1681-;;;;; Killing Words
  3.1682-
  3.1683-;;; This is tricky and asymmetrical because backward parsing is
  3.1684-;;; extraordinarily difficult or impossible, so we have to implement
  3.1685-;;; killing in both directions by parsing forward.
  3.1686-
  3.1687-(defun paredit-forward-kill-word (&optional argument)
  3.1688-  "Kill a word forward, skipping over intervening delimiters."
  3.1689-  (interactive "p")
  3.1690-  (let ((argument (or argument 1)))
  3.1691-    (if (< argument 0)
  3.1692-        (paredit-backward-kill-word (- argument))
  3.1693-      (dotimes (i argument)
  3.1694-        (let ((beginning (point)))
  3.1695-          (skip-syntax-forward " -")
  3.1696-          (let* ((parse-state (paredit-current-parse-state))
  3.1697-                 (state (paredit-kill-word-state parse-state 'char-after)))
  3.1698-            (while (not (or (eobp)
  3.1699-                            (eq ?w (char-syntax (char-after)))))
  3.1700-              (setq parse-state
  3.1701-                    (progn (forward-char 1) (paredit-current-parse-state))
  3.1702-                    ;; XXX Why did I comment this out?
  3.1703-                    ;; (parse-partial-sexp (point) (1+ (point))
  3.1704-                    ;;                     nil nil parse-state)
  3.1705-                    )
  3.1706-              (let* ((old-state state)
  3.1707-                     (new-state
  3.1708-                      (paredit-kill-word-state parse-state 'char-after)))
  3.1709-                (cond ((not (eq old-state new-state))
  3.1710-                       (setq parse-state
  3.1711-                             (paredit-kill-word-hack old-state
  3.1712-                                                     new-state
  3.1713-                                                     parse-state))
  3.1714-                       (setq state
  3.1715-                             (paredit-kill-word-state parse-state
  3.1716-                                                      'char-after))
  3.1717-                       (setq beginning (point)))))))
  3.1718-          (goto-char beginning)
  3.1719-          (kill-word 1))))))
  3.1720-
  3.1721-(defun paredit-backward-kill-word (&optional argument)
  3.1722-  "Kill a word backward, skipping over any intervening delimiters."
  3.1723-  (interactive "p")
  3.1724-  (let ((argument (or argument 1)))
  3.1725-    (if (< argument 0)
  3.1726-        (paredit-forward-kill-word (- argument))
  3.1727-      (dotimes (i argument)
  3.1728-        (if (not (or (bobp)
  3.1729-                     (eq (char-syntax (char-before)) ?w)))
  3.1730-            (let ((end (point)))
  3.1731-              (backward-word 1)
  3.1732-              (forward-word 1)
  3.1733-              (goto-char (min end (point)))
  3.1734-              (let* ((parse-state (paredit-current-parse-state))
  3.1735-                     (state
  3.1736-                      (paredit-kill-word-state parse-state 'char-before)))
  3.1737-                (while (and (< (point) end)
  3.1738-                            (progn
  3.1739-                              (setq parse-state
  3.1740-                                    (parse-partial-sexp (point) (1+ (point))
  3.1741-                                                        nil nil parse-state))
  3.1742-                              (or (eq state
  3.1743-                                      (paredit-kill-word-state parse-state
  3.1744-                                                               'char-before))
  3.1745-                                  (progn (backward-char 1) nil)))))
  3.1746-                (if (and (eq state 'comment)
  3.1747-                         (eq ?\# (char-after (point)))
  3.1748-                         (eq ?\| (char-before (point))))
  3.1749-                    (backward-char 1)))))
  3.1750-        (backward-kill-word 1)))))
  3.1751-
  3.1752-;;;;;; Word-Killing Auxiliaries
  3.1753-
  3.1754-(defun paredit-kill-word-state (parse-state adjacent-char-fn)
  3.1755-  (cond ((paredit-in-comment-p parse-state) 'comment)
  3.1756-        ((paredit-in-string-p  parse-state) 'string)
  3.1757-        ((memq (char-syntax (funcall adjacent-char-fn))
  3.1758-               '(?\( ?\) ))
  3.1759-         'delimiter)
  3.1760-        (t 'other)))
  3.1761-
  3.1762-;;; This optionally advances the point past any comment delimiters that
  3.1763-;;; should probably not be touched, based on the last state change and
  3.1764-;;; the characters around the point.  It returns a new parse state,
  3.1765-;;; starting from the PARSE-STATE parameter.
  3.1766-
  3.1767-(defun paredit-kill-word-hack (old-state new-state parse-state)
  3.1768-  (cond ((and (not (eq old-state 'comment))
  3.1769-              (not (eq new-state 'comment))
  3.1770-              (not (paredit-in-string-escape-p))
  3.1771-              (eq ?\# (char-before))
  3.1772-              (eq ?\| (char-after)))
  3.1773-         (forward-char 1)
  3.1774-         (paredit-current-parse-state)
  3.1775-;;          (parse-partial-sexp (point) (1+ (point))
  3.1776-;;                              nil nil parse-state)
  3.1777-         )
  3.1778-        ((and (not (eq old-state 'comment))
  3.1779-              (eq new-state 'comment)
  3.1780-              (eq ?\; (char-before)))
  3.1781-         (skip-chars-forward ";")
  3.1782-         (paredit-current-parse-state)
  3.1783-;;          (parse-partial-sexp (point) (save-excursion
  3.1784-;;                                        (skip-chars-forward ";"))
  3.1785-;;                              nil nil parse-state)
  3.1786-         )
  3.1787-        (t parse-state)))
  3.1788-
  3.1789-(defun paredit-copy-as-kill ()
  3.1790-  "Save in the kill ring the region that `paredit-kill' would kill."
  3.1791-  (interactive)
  3.1792-  (cond ((paredit-in-string-p)
  3.1793-         (paredit-copy-as-kill-in-string))
  3.1794-        ((paredit-in-comment-p)
  3.1795-         (copy-region-as-kill (point) (point-at-eol)))
  3.1796-        ((save-excursion (paredit-skip-whitespace t (point-at-eol))
  3.1797-                         (or (eolp) (eq (char-after) ?\; )))
  3.1798-         ;** Be careful about trailing backslashes.
  3.1799-         (save-excursion
  3.1800-           (if (paredit-in-char-p)
  3.1801-               (backward-char))
  3.1802-           (copy-region-as-kill (point) (point-at-eol))))
  3.1803-        (t (paredit-copy-sexps-as-kill))))
  3.1804-
  3.1805-(defun paredit-copy-as-kill-in-string ()
  3.1806-  (save-excursion
  3.1807-    (if (paredit-in-string-escape-p)
  3.1808-        (backward-char))
  3.1809-    (copy-region-as-kill (point)
  3.1810-                         (min (point-at-eol)
  3.1811-                              (cdr (paredit-string-start+end-points))))))
  3.1812-
  3.1813-(defun paredit-copy-sexps-as-kill ()
  3.1814-  (save-excursion
  3.1815-    (if (paredit-in-char-p)
  3.1816-        (backward-char 2))
  3.1817-    (let ((beginning (point))
  3.1818-          (eol (point-at-eol)))
  3.1819-      (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
  3.1820-        (if end-of-list-p (progn (up-list) (backward-char)))
  3.1821-        (copy-region-as-kill beginning
  3.1822-                             (cond (kill-whole-line
  3.1823-                                    (or (save-excursion
  3.1824-                                          (paredit-skip-whitespace t)
  3.1825-                                          (and (not (eq (char-after) ?\; ))
  3.1826-                                               (point)))
  3.1827-                                        (point-at-eol)))
  3.1828-                                   ((and (not end-of-list-p)
  3.1829-                                         (eq (point-at-eol) eol))
  3.1830-                                    eol)
  3.1831-                                   (t
  3.1832-                                    (point))))))))
  3.1833-
  3.1834-;;;; Deleting Regions
  3.1835-
  3.1836-(defun paredit-delete-region (start end)
  3.1837-  "Delete the text between point and mark, like `delete-region'.
  3.1838-If that text is unbalanced, signal an error instead.
  3.1839-With a prefix argument, skip the balance check."
  3.1840-  (interactive "r")
  3.1841-  (if (and start end (not current-prefix-arg))
  3.1842-      (paredit-check-region-for-delete start end))
  3.1843-  (setq this-command 'delete-region)
  3.1844-  (delete-region start end))
  3.1845-
  3.1846-(defun paredit-kill-region (start end)
  3.1847-  "Kill the text between point and mark, like `kill-region'.
  3.1848-If that text is unbalanced, signal an error instead.
  3.1849-With a prefix argument, skip the balance check."
  3.1850-  (interactive "r")
  3.1851-  (if (and start end (not current-prefix-arg))
  3.1852-      (paredit-check-region-for-delete start end))
  3.1853-  (setq this-command 'kill-region)
  3.1854-  (kill-region start end))
  3.1855-
  3.1856-(defun paredit-check-region-for-delete (start end)
  3.1857-  "Signal an error deleting text between START and END is unsafe."
  3.1858-  (save-excursion
  3.1859-    (goto-char start)
  3.1860-    (let* ((start-state (paredit-current-parse-state))
  3.1861-           (end-state (parse-partial-sexp start end nil nil start-state)))
  3.1862-      (paredit-check-region-for-delete:depth start start-state end end-state)
  3.1863-      (paredit-check-region-for-delete:string start start-state end end-state)
  3.1864-      (paredit-check-region-for-delete:comment start start-state end end-state)
  3.1865-      (paredit-check-region-for-delete:char-quote start start-state
  3.1866-                                                  end end-state))))
  3.1867-
  3.1868-(defun paredit-check-region-for-delete:depth (start start-state end end-state)
  3.1869-  (let ((start-depth (nth 0 start-state))
  3.1870-        (end-depth (nth 0 end-state)))
  3.1871-    (if (not (= start-depth end-depth))
  3.1872-        (error "Mismatched parenthesis depth: %S at start, %S at end."
  3.1873-               start-depth
  3.1874-               end-depth))))
  3.1875-
  3.1876-(defun paredit-check-region-for-delete:string (start start-state end end-state)
  3.1877-  (let ((start-string-p (nth 3 start-state))
  3.1878-        (end-string-p (nth 3 end-state)))
  3.1879-    (if (not (eq start-string-p end-string-p))
  3.1880-        (error "Mismatched string state: start %sin string, end %sin string."
  3.1881-               (if start-string-p "" "not ")
  3.1882-               (if end-string-p "" "not ")))))
  3.1883-
  3.1884-(defun paredit-check-region-for-delete:comment
  3.1885-    (start start-state end end-state)
  3.1886-  (let ((start-comment-state (nth 4 start-state))
  3.1887-        (end-comment-state (nth 4 end-state)))
  3.1888-    (if (not (or (eq start-comment-state end-comment-state)
  3.1889-                 ;; If we are moving text into or out of a line
  3.1890-                 ;; comment, make sure that the text is balanced.  (The
  3.1891-                 ;; comment state may be a number, not t or nil at all,
  3.1892-                 ;; for nestable comments, which are not handled by
  3.1893-                 ;; this heuristic (or any of paredit, really).)
  3.1894-                 (and (or (and (eq start-comment-state nil)
  3.1895-                               (eq end-comment-state t))
  3.1896-                          (and (eq start-comment-state t)
  3.1897-                               (eq end-comment-state nil)))
  3.1898-                      (save-excursion
  3.1899-                        (goto-char end)
  3.1900-                        (paredit-region-ok-p (point) (point-at-eol))))))
  3.1901-        (error "Mismatched comment state: %s"
  3.1902-               (cond ((and (integerp start-comment-state)
  3.1903-                           (integerp end-comment-state))
  3.1904-                      (format "depth %S at start, depth %S at end."
  3.1905-                              start-comment-state
  3.1906-                              end-comment-state))
  3.1907-                     ((integerp start-comment-state)
  3.1908-                      "start in nested comment, end otherwise.")
  3.1909-                     ((integerp end-comment-state)
  3.1910-                      "end in nested comment, start otherwise.")
  3.1911-                     (start-comment-state
  3.1912-                      "start in comment, end not in comment.")
  3.1913-                     (end-comment-state
  3.1914-                      "end in comment, start not in comment.")
  3.1915-                     (t
  3.1916-                      (format "start %S, end %S."
  3.1917-                              start-comment-state
  3.1918-                              end-comment-state)))))))
  3.1919-
  3.1920-(defun paredit-check-region-for-delete:char-quote
  3.1921-    (start start-state end end-state)
  3.1922-  (let ((start-char-quote (nth 5 start-state))
  3.1923-        (end-char-quote (nth 5 end-state)))
  3.1924-    (if (not (eq start-char-quote end-char-quote))
  3.1925-        (let ((phrase "character quotation"))
  3.1926-          (error "Mismatched %s: start %sin %s, end %sin %s."
  3.1927-                 phrase
  3.1928-                 (if start-char-quote "" "not ")
  3.1929-                 phrase
  3.1930-                 (if end-char-quote "" "not ")
  3.1931-                 phrase)))))
  3.1932-
  3.1933-;;;; Point Motion
  3.1934-
  3.1935-(eval-and-compile
  3.1936-  (defmacro defun-motion (name bvl doc &rest body)
  3.1937-    `(defun ,name ,bvl
  3.1938-       ,doc
  3.1939-       ,(xcond ((paredit-xemacs-p)
  3.1940-                '(interactive "_"))
  3.1941-               ((paredit-gnu-emacs-p)
  3.1942-                ;++ Not sure this is sufficient for the `^'.
  3.1943-                (if (fboundp 'handle-shift-selection)
  3.1944-                    '(interactive "^p")
  3.1945-                    '(interactive "p"))))
  3.1946-       ,@body)))
  3.1947-
  3.1948-(defun-motion paredit-forward (&optional arg)
  3.1949-  "Move forward an S-expression, or up an S-expression forward.
  3.1950-If there are no more S-expressions in this one before the closing
  3.1951-  delimiter, move past that closing delimiter; otherwise, move forward
  3.1952-  past the S-expression following the point."
  3.1953-  (let ((n (or arg 1)))
  3.1954-    (cond ((< 0 n) (dotimes (i n)       (paredit-move-forward)))
  3.1955-          ((< n 0) (dotimes (i (- n))   (paredit-move-backward))))))
  3.1956-
  3.1957-(defun-motion paredit-backward (&optional arg)
  3.1958-  "Move backward an S-expression, or up an S-expression backward.
  3.1959-If there are no more S-expressions in this one before the opening
  3.1960-  delimiter, move past that opening delimiter backward; otherwise,
  3.1961-  move backward past the S-expression preceding the point."
  3.1962-  (let ((n (or arg 1)))
  3.1963-    (cond ((< 0 n) (dotimes (i n)       (paredit-move-backward)))
  3.1964-          ((< n 0) (dotimes (i (- n))   (paredit-move-forward))))))
  3.1965-
  3.1966-(defun paredit-move-forward ()
  3.1967-  (cond ((paredit-in-string-p)
  3.1968-         (let ((end (paredit-enclosing-string-end)))
  3.1969-           ;; `forward-sexp' and `up-list' may move into the next string
  3.1970-           ;; in the buffer.  Don't do that; move out of the current one.
  3.1971-           (if (paredit-handle-sexp-errors
  3.1972-                   (progn (paredit-handle-sexp-errors (forward-sexp)
  3.1973-                            (up-list))
  3.1974-                          (<= end (point)))
  3.1975-                 t)
  3.1976-               (goto-char end))))
  3.1977-        ((paredit-in-char-p)
  3.1978-         (forward-char))
  3.1979-        (t
  3.1980-         (paredit-handle-sexp-errors (forward-sexp)
  3.1981-           (up-list)))))
  3.1982-
  3.1983-(defun paredit-move-backward ()
  3.1984-  (cond ((paredit-in-string-p)
  3.1985-         (let ((start (paredit-enclosing-string-start)))
  3.1986-           (if (paredit-handle-sexp-errors
  3.1987-                   (progn (paredit-handle-sexp-errors (backward-sexp)
  3.1988-                            (backward-up-list))
  3.1989-                          (<= (point) start))
  3.1990-                 t)
  3.1991-               (goto-char start))))
  3.1992-        ((paredit-in-char-p)
  3.1993-         ;++ Corner case: a buffer of `\|x'.  What to do?
  3.1994-         (backward-char 2))
  3.1995-        (t
  3.1996-         (paredit-handle-sexp-errors (backward-sexp)
  3.1997-           (backward-up-list)))))
  3.1998-
  3.1999-;;;; Window Positioning
  3.2000-
  3.2001-(defalias 'paredit-recentre-on-sexp 'paredit-recenter-on-sexp)
  3.2002-
  3.2003-(defun paredit-recenter-on-sexp (&optional n)
  3.2004-  "Recenter the screen on the S-expression following the point.
  3.2005-With a prefix argument N, encompass all N S-expressions forward."
  3.2006-  (interactive "P")
  3.2007-  (let* ((p (point))
  3.2008-         (end-point (progn (forward-sexp n) (point)))
  3.2009-         (start-point (progn (goto-char end-point) (backward-sexp n) (point))))
  3.2010-    ;; Point is at beginning of first S-expression.
  3.2011-    (let ((p-visible nil) (start-visible nil))
  3.2012-      (save-excursion
  3.2013-        (forward-line (/ (count-lines start-point end-point) 2))
  3.2014-        (recenter)
  3.2015-        (setq p-visible (pos-visible-in-window-p p))
  3.2016-        (setq start-visible (pos-visible-in-window-p start-point)))
  3.2017-      (cond ((not start-visible)
  3.2018-             ;; Implies (not p-visible).  Put the start at the top of
  3.2019-             ;; the screen.
  3.2020-             (recenter 0))
  3.2021-            (p-visible
  3.2022-             ;; Go back to p if we can.
  3.2023-             (goto-char p))))))
  3.2024-
  3.2025-(defun paredit-recenter-on-defun ()
  3.2026-  "Recenter the screen on the definition at point."
  3.2027-  (interactive)
  3.2028-  (save-excursion
  3.2029-    (beginning-of-defun)
  3.2030-    (paredit-recenter-on-sexp)))
  3.2031-
  3.2032-(defun paredit-focus-on-defun ()
  3.2033-  "Moves display to the top of the definition at point."
  3.2034-  (interactive)
  3.2035-  (beginning-of-defun)
  3.2036-  (recenter 0))
  3.2037-
  3.2038-;;;; Generalized Upward/Downward Motion
  3.2039-
  3.2040-(defun paredit-up/down (n vertical-direction)
  3.2041-  (let ((horizontal-direction (if (< 0 n) +1 -1)))
  3.2042-    (while (/= n 0)
  3.2043-      (goto-char
  3.2044-       (paredit-next-up/down-point horizontal-direction vertical-direction))
  3.2045-      (setq n (- n horizontal-direction)))))
  3.2046-
  3.2047-(defun paredit-next-up/down-point (horizontal-direction vertical-direction)
  3.2048-  (let ((state (paredit-current-parse-state))
  3.2049-        (scan-lists
  3.2050-         (lambda ()
  3.2051-           (scan-lists (point) horizontal-direction vertical-direction))))
  3.2052-    (cond ((paredit-in-string-p state)
  3.2053-           (let ((start+end (paredit-string-start+end-points state)))
  3.2054-             (if (< 0 vertical-direction)
  3.2055-                 (if (< 0 horizontal-direction)
  3.2056-                     (+ 1 (cdr start+end))
  3.2057-                     (car start+end))
  3.2058-                 ;; We could let the user try to descend into lists
  3.2059-                 ;; within the string, but that would be asymmetric
  3.2060-                 ;; with the up case, which rises out of the whole
  3.2061-                 ;; string and not just out of a list within the
  3.2062-                 ;; string, so this case will just be an error.
  3.2063-                 (error "Can't descend further into string."))))
  3.2064-          ((< 0 vertical-direction)
  3.2065-           ;; When moving up, just try to rise up out of the list.
  3.2066-           (or (funcall scan-lists)
  3.2067-               (buffer-end horizontal-direction)))
  3.2068-          ((< vertical-direction 0)
  3.2069-           ;; When moving down, look for a string closer than a list,
  3.2070-           ;; and use that if we find it.
  3.2071-           (let* ((list-start
  3.2072-                   (paredit-handle-sexp-errors (funcall scan-lists) nil))
  3.2073-                  (string-start
  3.2074-                   (paredit-find-next-string-start horizontal-direction
  3.2075-                                                   list-start)))
  3.2076-             (if (and string-start list-start)
  3.2077-                 (if (< 0 horizontal-direction)
  3.2078-                     (min string-start list-start)
  3.2079-                     (max string-start list-start))
  3.2080-                 (or string-start
  3.2081-                     ;; Scan again: this is a kludgey way to report the
  3.2082-                     ;; error if there really was one.
  3.2083-                     (funcall scan-lists)
  3.2084-                     (buffer-end horizontal-direction)))))
  3.2085-          (t
  3.2086-           (error "Vertical direction must be nonzero in `%s'."
  3.2087-                  'paredit-up/down)))))
  3.2088-
  3.2089-(defun paredit-find-next-string-start (horizontal-direction limit)
  3.2090-  (let ((buffer-limit-p (if (< 0 horizontal-direction) 'eobp 'bobp))
  3.2091-        (next-char (if (< 0 horizontal-direction) 'char-after 'char-before))
  3.2092-        (pastp (if (< 0 horizontal-direction) '> '<)))
  3.2093-    (paredit-handle-sexp-errors
  3.2094-        (save-excursion
  3.2095-          (catch 'exit
  3.2096-            (while t
  3.2097-              (if (or (funcall buffer-limit-p)
  3.2098-                      (and limit (funcall pastp (point) limit)))
  3.2099-                  (throw 'exit nil))
  3.2100-              (forward-sexp horizontal-direction)
  3.2101-              (save-excursion
  3.2102-                (backward-sexp horizontal-direction)
  3.2103-                (if (eq ?\" (char-syntax (funcall next-char)))
  3.2104-                    (throw 'exit (+ (point) horizontal-direction)))))))
  3.2105-      nil)))
  3.2106-
  3.2107-(defun-motion paredit-forward-down (&optional argument)
  3.2108-  "Move forward down into a list.
  3.2109-With a positive argument, move forward down that many levels.
  3.2110-With a negative argument, move backward down that many levels."
  3.2111-  (paredit-up/down (or argument +1) -1))
  3.2112-
  3.2113-(defun-motion paredit-backward-up (&optional argument)
  3.2114-  "Move backward up out of the enclosing list.
  3.2115-With a positive argument, move backward up that many levels.
  3.2116-With a negative argument, move forward up that many levels.
  3.2117-If in a string initially, that counts as one level."
  3.2118-  (paredit-up/down (- 0 (or argument +1)) +1))
  3.2119-
  3.2120-(defun-motion paredit-forward-up (&optional argument)
  3.2121-  "Move forward up out of the enclosing list.
  3.2122-With a positive argument, move forward up that many levels.
  3.2123-With a negative argument, move backward up that many levels.
  3.2124-If in a string initially, that counts as one level."
  3.2125-  (paredit-up/down (or argument +1) +1))
  3.2126-
  3.2127-(defun-motion paredit-backward-down (&optional argument)
  3.2128-  "Move backward down into a list.
  3.2129-With a positive argument, move backward down that many levels.
  3.2130-With a negative argument, move forward down that many levels."
  3.2131-  (paredit-up/down (- 0 (or argument +1)) -1))
  3.2132-
  3.2133-;;;; Depth-Changing Commands:  Wrapping, Splicing, & Raising
  3.2134-
  3.2135-(defun paredit-wrap-sexp (&optional argument open close)
  3.2136-  "Wrap the following S-expression.
  3.2137-If a `C-u' prefix argument is given, wrap all S-expressions following
  3.2138-  the point until the end of the buffer or of the enclosing list.
  3.2139-If a numeric prefix argument N is given, wrap N S-expressions.
  3.2140-Automatically indent the newly wrapped S-expression.
  3.2141-As a special case, if the point is at the end of a list, simply insert
  3.2142-  a parenthesis pair, rather than inserting a lone opening delimiter
  3.2143-  and then signalling an error, in the interest of preserving
  3.2144-  structure.
  3.2145-By default OPEN and CLOSE are round delimiters."
  3.2146-  (interactive "P")
  3.2147-  (paredit-lose-if-not-in-sexp 'paredit-wrap-sexp)
  3.2148-  (let ((open (or open ?\( ))
  3.2149-        (close (or close ?\) )))
  3.2150-    (paredit-handle-sexp-errors
  3.2151-        ((lambda (n) (paredit-insert-pair n open close 'goto-char))
  3.2152-         (cond ((integerp argument) argument)
  3.2153-               ((consp argument) (paredit-count-sexps-forward))
  3.2154-               ((paredit-region-active-p) nil)
  3.2155-               (t 1)))
  3.2156-      (insert close)
  3.2157-      (backward-char)))
  3.2158-  (save-excursion (backward-up-list) (indent-sexp)))
  3.2159-
  3.2160-(defun paredit-yank-pop (&optional argument)
  3.2161-  "Replace just-yanked text with the next item in the kill ring.
  3.2162-If this command follows a `yank', just run `yank-pop'.
  3.2163-If this command follows a `paredit-wrap-sexp', or any other paredit
  3.2164-  wrapping command (see `paredit-wrap-commands'), run `yank' and
  3.2165-  reindent the enclosing S-expression.
  3.2166-If this command is repeated, run `yank-pop' and reindent the enclosing
  3.2167-  S-expression.
  3.2168-
  3.2169-The argument is passed on to `yank' or `yank-pop'; see their
  3.2170-  documentation for details."
  3.2171-  (interactive "*p")
  3.2172-  (cond ((eq last-command 'yank)
  3.2173-         (yank-pop argument))
  3.2174-        ((memq last-command paredit-wrap-commands)
  3.2175-         (yank argument)
  3.2176-         ;; `yank' futzes with `this-command'.
  3.2177-         (setq this-command 'paredit-yank-pop)
  3.2178-         (save-excursion (backward-up-list) (indent-sexp)))
  3.2179-        ((eq last-command 'paredit-yank-pop)
  3.2180-         ;; Pretend we just did a `yank', so that we can use
  3.2181-         ;; `yank-pop' without duplicating its definition.
  3.2182-         (setq last-command 'yank)
  3.2183-         (yank-pop argument)
  3.2184-         ;; Return to our original state.
  3.2185-         (setq last-command 'paredit-yank-pop)
  3.2186-         (setq this-command 'paredit-yank-pop)
  3.2187-         (save-excursion (backward-up-list) (indent-sexp)))
  3.2188-        (t (error "Last command was not a yank or a wrap: %s" last-command))))
  3.2189-
  3.2190-(defun paredit-splice-sexp (&optional argument)
  3.2191-  "Splice the list that the point is on by removing its delimiters.
  3.2192-With a prefix argument as in `C-u', kill all S-expressions backward in
  3.2193-  the current list before splicing all S-expressions forward into the
  3.2194-  enclosing list.
  3.2195-With two prefix arguments as in `C-u C-u', kill all S-expressions
  3.2196-  forward in the current list before splicing all S-expressions
  3.2197-  backward into the enclosing list.
  3.2198-With a numerical prefix argument N, kill N S-expressions backward in
  3.2199-  the current list before splicing the remaining S-expressions into the
  3.2200-  enclosing list.  If N is negative, kill forward.
  3.2201-Inside a string, unescape all backslashes, or signal an error if doing
  3.2202-  so would invalidate the buffer's structure."
  3.2203-  (interactive "P")
  3.2204-  (if (paredit-in-string-p)
  3.2205-      (paredit-splice-string argument)
  3.2206-    (if (paredit-in-comment-p)
  3.2207-        (error "Can't splice comment."))
  3.2208-    (paredit-handle-sexp-errors (paredit-enclosing-list-start)
  3.2209-      (error "Can't splice top level."))
  3.2210-    (paredit-kill-surrounding-sexps-for-splice argument)
  3.2211-    (let ((delete-start (paredit-enclosing-list-start))
  3.2212-          (delete-end
  3.2213-           (let ((limit
  3.2214-                  (save-excursion
  3.2215-                    (paredit-ignore-sexp-errors (forward-sexp) (backward-sexp))
  3.2216-                    (point))))
  3.2217-             (save-excursion
  3.2218-               (backward-up-list)
  3.2219-               (forward-char +1)
  3.2220-               (paredit-skip-whitespace t limit)
  3.2221-               (point)))))
  3.2222-      (let ((end-marker (make-marker)))
  3.2223-        (save-excursion
  3.2224-          (up-list)
  3.2225-          (delete-char -1)
  3.2226-          (set-marker end-marker (point)))
  3.2227-        (delete-region delete-start delete-end)
  3.2228-        (paredit-splice-reindent delete-start (marker-position end-marker))))))
  3.2229-
  3.2230-(defun paredit-splice-reindent (start end)
  3.2231-  (paredit-preserving-column
  3.2232-    ;; If we changed the first subform of the enclosing list, we must
  3.2233-    ;; reindent the whole enclosing list.
  3.2234-    (if (paredit-handle-sexp-errors
  3.2235-            (save-excursion
  3.2236-              (backward-up-list)
  3.2237-              (down-list)
  3.2238-              (paredit-ignore-sexp-errors (forward-sexp))
  3.2239-              (< start (point)))
  3.2240-          nil)
  3.2241-        (save-excursion (backward-up-list) (indent-sexp))
  3.2242-        (paredit-indent-region start end))))
  3.2243-
  3.2244-(defun paredit-kill-surrounding-sexps-for-splice (argument)
  3.2245-  (cond ((or (paredit-in-string-p)
  3.2246-             (paredit-in-comment-p))
  3.2247-         (error "Invalid context for splicing S-expressions."))
  3.2248-        ((or (not argument) (eq argument 0)) nil)
  3.2249-        ((or (numberp argument) (eq argument '-))
  3.2250-         ;; Kill S-expressions before/after the point by saving the
  3.2251-         ;; point, moving across them, and killing the region.
  3.2252-         (let* ((argument (if (eq argument '-) -1 argument))
  3.2253-                (saved (paredit-point-at-sexp-boundary (- argument))))
  3.2254-           (goto-char saved)
  3.2255-           (paredit-ignore-sexp-errors (backward-sexp argument))
  3.2256-           (paredit-hack-kill-region saved (point))))
  3.2257-        ((consp argument)
  3.2258-         (let ((v (car argument)))
  3.2259-           (if (= v 4)                  ;One `C-u'.
  3.2260-               ;; Move backward until we hit the open paren; then
  3.2261-               ;; kill that selected region.
  3.2262-               (let ((end (point)))
  3.2263-                 (paredit-ignore-sexp-errors
  3.2264-                   (while (not (bobp))
  3.2265-                     (backward-sexp)))
  3.2266-                 (paredit-hack-kill-region (point) end))
  3.2267-               ;; Move forward until we hit the close paren; then
  3.2268-               ;; kill that selected region.
  3.2269-               (let ((beginning (point)))
  3.2270-                 (paredit-ignore-sexp-errors
  3.2271-                   (while (not (eobp))
  3.2272-                     (forward-sexp)))
  3.2273-                 (paredit-hack-kill-region beginning (point))))))
  3.2274-        (t (error "Bizarre prefix argument `%s'." argument))))
  3.2275-
  3.2276-(defun paredit-splice-sexp-killing-backward (&optional n)
  3.2277-  "Splice the list the point is on by removing its delimiters, and
  3.2278-  also kill all S-expressions before the point in the current list.
  3.2279-With a prefix argument N, kill only the preceding N S-expressions."
  3.2280-  (interactive "P")
  3.2281-  (paredit-splice-sexp (if n
  3.2282-                           (prefix-numeric-value n)
  3.2283-                           '(4))))
  3.2284-
  3.2285-(defun paredit-splice-sexp-killing-forward (&optional n)
  3.2286-  "Splice the list the point is on by removing its delimiters, and
  3.2287-  also kill all S-expressions after the point in the current list.
  3.2288-With a prefix argument N, kill only the following N S-expressions."
  3.2289-  (interactive "P")
  3.2290-  (paredit-splice-sexp (if n
  3.2291-                           (- (prefix-numeric-value n))
  3.2292-                           '(16))))
  3.2293-
  3.2294-(defun paredit-raise-sexp (&optional argument)
  3.2295-  "Raise the following S-expression in a tree, deleting its siblings.
  3.2296-With a prefix argument N, raise the following N S-expressions.  If N
  3.2297-  is negative, raise the preceding N S-expressions.
  3.2298-If the point is on an S-expression, such as a string or a symbol, not
  3.2299-  between them, that S-expression is considered to follow the point."
  3.2300-  (interactive "P")
  3.2301-  (save-excursion
  3.2302-    ;; Select the S-expressions we want to raise in a buffer substring.
  3.2303-    (let* ((bound
  3.2304-            (if (and (not argument) (paredit-region-active-p))
  3.2305-                (progn (if (< (mark) (point))
  3.2306-                           (paredit-check-region (mark) (point))
  3.2307-                           (paredit-check-region (point) (mark)))
  3.2308-                       (mark))
  3.2309-              (cond ((paredit-in-string-p)
  3.2310-                     (goto-char (car (paredit-string-start+end-points))))
  3.2311-                    ((paredit-in-char-p)
  3.2312-                     (backward-sexp))
  3.2313-                    ((paredit-in-comment-p)
  3.2314-                     (error "No S-expression to raise in comment.")))
  3.2315-              (scan-sexps (point) (prefix-numeric-value argument))))
  3.2316-           (sexps
  3.2317-            (if (< bound (point))
  3.2318-                (buffer-substring bound (paredit-point-at-sexp-end))
  3.2319-                (buffer-substring (paredit-point-at-sexp-start) bound))))
  3.2320-      ;; Move up to the list we're raising those S-expressions out of and
  3.2321-      ;; delete it.
  3.2322-      (backward-up-list)
  3.2323-      (delete-region (point) (scan-sexps (point) 1))
  3.2324-      (let* ((indent-start (point))
  3.2325-             (indent-end (save-excursion (insert sexps) (point))))
  3.2326-        ;; If the expression spans multiple lines, its indentation is
  3.2327-        ;; probably broken, so reindent it -- but don't reindent
  3.2328-        ;; anything that we didn't touch outside the expression.
  3.2329-        ;;
  3.2330-        ;; XXX What if the *column* of the starting point was preserved
  3.2331-        ;; too?  Should we avoid reindenting in that case?
  3.2332-        (if (not (eq (save-excursion (goto-char indent-start) (point-at-eol))
  3.2333-                     (save-excursion (goto-char indent-end) (point-at-eol))))
  3.2334-            (indent-region indent-start indent-end nil))))))
  3.2335-
  3.2336-;;; The effects of convolution on the surrounding whitespace are pretty
  3.2337-;;; random.  If you have better suggestions, please let me know.
  3.2338-
  3.2339-(defun paredit-convolute-sexp (&optional n)
  3.2340-  "Convolute S-expressions.
  3.2341-Save the S-expressions preceding point and delete them.
  3.2342-Splice the S-expressions following point.
  3.2343-Wrap the enclosing list in a new list prefixed by the saved text.
  3.2344-With a prefix argument N, move up N lists before wrapping."
  3.2345-  (interactive "p")
  3.2346-  (paredit-lose-if-not-in-sexp 'paredit-convolute-sexp)
  3.2347-  ;; Make sure we can move up before destroying anything.
  3.2348-  (save-excursion (backward-up-list n) (backward-up-list))
  3.2349-  (let (open close)                     ;++ Is this a good idea?
  3.2350-    (let ((prefix
  3.2351-           (let ((end (point)))
  3.2352-             (paredit-ignore-sexp-errors
  3.2353-               (while (not (bobp)) (backward-sexp)))
  3.2354-             (prog1 (buffer-substring (point) end)
  3.2355-               (backward-up-list)
  3.2356-               (save-excursion (forward-sexp)
  3.2357-                               (setq close (char-before))
  3.2358-                               (delete-char -1))
  3.2359-               (setq open (char-after))
  3.2360-               (delete-region (point) end)
  3.2361-               ;; I'm not sure this makes sense...
  3.2362-               (if (not (eolp)) (just-one-space))))))
  3.2363-      (backward-up-list n)
  3.2364-      (paredit-insert-pair 1 open close 'goto-char)
  3.2365-      (insert prefix)
  3.2366-      ;; I'm not sure this makes sense either...
  3.2367-      (if (not (eolp)) (just-one-space))
  3.2368-      (save-excursion
  3.2369-        (backward-up-list)
  3.2370-        (paredit-ignore-sexp-errors (indent-sexp))))))
  3.2371-
  3.2372-(defun paredit-splice-string (argument)
  3.2373-  (let ((original-point (point))
  3.2374-        (start+end (paredit-string-start+end-points)))
  3.2375-    (let ((start (car start+end))
  3.2376-          (end (cdr start+end)))
  3.2377-      ;; START and END both lie before the respective quote
  3.2378-      ;; characters, which we want to delete; thus we increment START
  3.2379-      ;; by one to extract the string, and we increment END by one to
  3.2380-      ;; delete the string.
  3.2381-      (let* ((escaped-string
  3.2382-              (cond ((not (consp argument))
  3.2383-                     (buffer-substring (1+ start) end))
  3.2384-                    ((= 4 (car argument))
  3.2385-                     (buffer-substring original-point end))
  3.2386-                    (t
  3.2387-                     (buffer-substring (1+ start) original-point))))
  3.2388-             (unescaped-string
  3.2389-              (paredit-unescape-string escaped-string)))
  3.2390-        (if (not unescaped-string)
  3.2391-            (error "Unspliceable string.")
  3.2392-          (save-excursion
  3.2393-            (goto-char start)
  3.2394-            (delete-region start (1+ end))
  3.2395-            (insert unescaped-string))
  3.2396-          (if (not (and (consp argument)
  3.2397-                        (= 4 (car argument))))
  3.2398-              (goto-char (- original-point 1))))))))
  3.2399-
  3.2400-(defun paredit-unescape-string (string)
  3.2401-  (with-temp-buffer
  3.2402-    (insert string)
  3.2403-    (goto-char (point-min))
  3.2404-    (while (and (not (eobp))
  3.2405-                ;; nil -> no bound; t -> no errors.
  3.2406-                (search-forward "\\" nil t))
  3.2407-      (delete-char -1)
  3.2408-      (forward-char))
  3.2409-    (paredit-handle-sexp-errors
  3.2410-        (progn (scan-sexps (point-min) (point-max))
  3.2411-               (buffer-string))
  3.2412-      nil)))
  3.2413-
  3.2414-;;;; Slurpage & Barfage
  3.2415-
  3.2416-(defun paredit-forward-slurp-sexp (&optional argument)
  3.2417-  "Add the S-expression following the current list into that list
  3.2418-  by moving the closing delimiter.
  3.2419-Automatically reindent the newly slurped S-expression with respect to
  3.2420-  its new enclosing form.
  3.2421-If in a string, move the opening double-quote forward by one
  3.2422-  S-expression and escape any intervening characters as necessary,
  3.2423-  without altering any indentation or formatting."
  3.2424-  (interactive "P")
  3.2425-  (save-excursion
  3.2426-    (cond ((paredit-in-comment-p)
  3.2427-           (error "Invalid context for slurping S-expressions."))
  3.2428-          ((numberp argument)
  3.2429-           (if (< argument 0)
  3.2430-               (paredit-forward-barf-sexp (- 0 argument))
  3.2431-               (while (< 0 argument)
  3.2432-                 (paredit-forward-slurp-sexp)
  3.2433-                 (setq argument (- argument 1)))))
  3.2434-          ((paredit-in-string-p)
  3.2435-           ;; If there is anything to slurp into the string, take that.
  3.2436-           ;; Otherwise, try to slurp into the enclosing list.
  3.2437-           (if (save-excursion
  3.2438-                 (goto-char (paredit-enclosing-string-end))
  3.2439-                 (paredit-handle-sexp-errors (progn (forward-sexp) nil)
  3.2440-                   t))
  3.2441-               (progn
  3.2442-                 (goto-char (paredit-enclosing-string-end))
  3.2443-                 (paredit-forward-slurp-into-list argument))
  3.2444-               (paredit-forward-slurp-into-string argument)))
  3.2445-          (t
  3.2446-           (paredit-forward-slurp-into-list argument)))))
  3.2447-
  3.2448-(defun paredit-forward-slurp-into-list (&optional argument)
  3.2449-  (let ((nestedp nil))
  3.2450-    (save-excursion
  3.2451-      (up-list)                            ; Up to the end of the list to
  3.2452-      (let ((close (char-before)))         ;   save and delete the closing
  3.2453-        (delete-char -1)                   ;   delimiter.
  3.2454-        (let ((start (point)))
  3.2455-          (catch 'return                   ; Go to the end of the desired
  3.2456-            (while t                       ;   S-expression, going up a
  3.2457-              (paredit-handle-sexp-errors  ;   list if it's not in this,
  3.2458-                  (progn (forward-sexp)
  3.2459-                         (if argument
  3.2460-                             (paredit-ignore-sexp-errors
  3.2461-                               (while (not (eobp))
  3.2462-                                 (forward-sexp))))
  3.2463-                         (throw 'return nil))
  3.2464-                (setq nestedp t)
  3.2465-                (up-list)
  3.2466-                (setq close                ; adjusting for mixed
  3.2467-                      (prog1 (char-before) ;   delimiters as necessary,
  3.2468-                        (delete-char -1)
  3.2469-                        (insert close))))))
  3.2470-          (insert close)                   ;  to insert that delimiter.
  3.2471-          (indent-region start (point) nil))))
  3.2472-    (if (and (not nestedp)
  3.2473-             (eq (save-excursion (paredit-skip-whitespace nil) (point))
  3.2474-                 (save-excursion (backward-up-list) (forward-char) (point)))
  3.2475-             (eq (save-excursion (forward-sexp) (backward-sexp) (point))
  3.2476-                 (save-excursion (paredit-skip-whitespace t) (point))))
  3.2477-        (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  3.2478-                       (save-excursion (paredit-skip-whitespace t) (point))))))
  3.2479-
  3.2480-(defun paredit-forward-slurp-into-string (&optional argument)
  3.2481-  (let ((start (paredit-enclosing-string-start))
  3.2482-        (end (paredit-enclosing-string-end)))
  3.2483-    (goto-char end)
  3.2484-    ;; Signal any errors that we might get first, before mucking with
  3.2485-    ;; the buffer's contents.
  3.2486-    (save-excursion (forward-sexp))
  3.2487-    (let ((close (char-before)))
  3.2488-      ;; Skip intervening whitespace if we're slurping into an empty
  3.2489-      ;; string.  XXX What about nonempty strings?
  3.2490-      (if (and (= (+ start 2) end)
  3.2491-               (eq (save-excursion (paredit-skip-whitespace t) (point))
  3.2492-                   (save-excursion (forward-sexp) (backward-sexp) (point))))
  3.2493-          (delete-region (- (point) 1)
  3.2494-                         (save-excursion (paredit-skip-whitespace t) (point)))
  3.2495-          (delete-char -1))
  3.2496-      (paredit-forward-for-quote
  3.2497-       (save-excursion
  3.2498-         (forward-sexp)
  3.2499-         (if argument
  3.2500-             (while (paredit-handle-sexp-errors (progn (forward-sexp) t) nil)))
  3.2501-         (point)))
  3.2502-      (insert close))))
  3.2503-
  3.2504-(defun paredit-forward-barf-sexp (&optional argument)
  3.2505-  "Remove the last S-expression in the current list from that list
  3.2506-  by moving the closing delimiter.
  3.2507-Automatically reindent the newly barfed S-expression with respect to
  3.2508-  its new enclosing form."
  3.2509-  (interactive "P")
  3.2510-  (paredit-lose-if-not-in-sexp 'paredit-forward-barf-sexp)
  3.2511-  (if (and (numberp argument) (< argument 0))
  3.2512-      (paredit-forward-slurp-sexp (- 0 argument))
  3.2513-    (let ((start (point)) (end nil))
  3.2514-      (save-excursion
  3.2515-        (up-list)                       ; Up to the end of the list to
  3.2516-        (let ((close (char-before)))    ;   save and delete the closing
  3.2517-          (delete-char -1)              ;   delimiter.
  3.2518-          (setq end (point))
  3.2519-          (paredit-ignore-sexp-errors   ; Go back to where we want to
  3.2520-            (if (or (not argument)      ;   insert the delimiter.
  3.2521-                    (numberp argument))
  3.2522-                (backward-sexp argument)
  3.2523-                (while (paredit-handle-sexp-errors
  3.2524-                           (save-excursion (backward-sexp) (<= start (point)))
  3.2525-                         nil)
  3.2526-                  (backward-sexp))))
  3.2527-          (paredit-skip-whitespace nil) ; Skip leading whitespace.
  3.2528-          (cond ((bobp)
  3.2529-                 ;++ We'll have deleted the close, but there's no open.
  3.2530-                 ;++ Is that OK?
  3.2531-                 (error "Barfing all subexpressions with no open-paren?"))
  3.2532-                ((paredit-in-comment-p) ; Don't put the close-paren in
  3.2533-                 (newline)))            ;   a comment.
  3.2534-          (insert close))
  3.2535-        ;; Reindent all of the newly barfed S-expressions.  Start at the
  3.2536-        ;; start of the first barfed S-expression, not at the close we
  3.2537-        ;; just inserted.
  3.2538-        (forward-sexp)
  3.2539-        (backward-sexp)
  3.2540-        (if (or (not argument) (numberp argument))
  3.2541-            (paredit-forward-and-indent argument)
  3.2542-            (indent-region (point) end))))))
  3.2543-
  3.2544-(defun paredit-backward-slurp-sexp (&optional argument)
  3.2545-  "Add the S-expression preceding the current list into that list
  3.2546-  by moving the closing delimiter.
  3.2547-Automatically reindent the whole form into which new S-expression was
  3.2548-  slurped.
  3.2549-If in a string, move the opening double-quote backward by one
  3.2550-  S-expression and escape any intervening characters as necessary,
  3.2551-  without altering any indentation or formatting."
  3.2552-  (interactive "P")
  3.2553-  (save-excursion
  3.2554-    (cond ((paredit-in-comment-p)
  3.2555-           (error "Invalid context for slurping S-expressions."))
  3.2556-          ((numberp argument)
  3.2557-           (if (< argument 0)
  3.2558-               (paredit-backward-barf-sexp (- 0 argument))
  3.2559-               (while (< 0 argument)
  3.2560-                 (paredit-backward-slurp-sexp)
  3.2561-                 (setq argument (- argument 1)))))
  3.2562-          ((paredit-in-string-p)
  3.2563-           ;; If there is anything to slurp into the string, take that.
  3.2564-           ;; Otherwise, try to slurp into the enclosing list.
  3.2565-           (if (save-excursion
  3.2566-                 (goto-char (paredit-enclosing-string-start))
  3.2567-                 (paredit-handle-sexp-errors (progn (backward-sexp) nil)
  3.2568-                   t))
  3.2569-               (progn
  3.2570-                 (goto-char (paredit-enclosing-string-start))
  3.2571-                 (paredit-backward-slurp-into-list argument))
  3.2572-               (paredit-backward-slurp-into-string argument)))
  3.2573-          (t
  3.2574-           (paredit-backward-slurp-into-list argument)))))
  3.2575-
  3.2576-(defun paredit-backward-slurp-into-list (&optional argument)
  3.2577-  (let ((nestedp nil))
  3.2578-    (save-excursion
  3.2579-      (backward-up-list)
  3.2580-      (let ((open (char-after)))
  3.2581-        (delete-char +1)
  3.2582-        (catch 'return
  3.2583-          (while t
  3.2584-            (paredit-handle-sexp-errors
  3.2585-                (progn (backward-sexp)
  3.2586-                       (if argument
  3.2587-                           (paredit-ignore-sexp-errors
  3.2588-                             (while (not (bobp))
  3.2589-                               (backward-sexp))))
  3.2590-                       (throw 'return nil))
  3.2591-              (setq nestedp t)
  3.2592-              (backward-up-list)
  3.2593-              (setq open
  3.2594-                    (prog1 (char-after)
  3.2595-                      (save-excursion (insert open) (delete-char +1)))))))
  3.2596-        (insert open))
  3.2597-      ;; Reindent the line at the beginning of wherever we inserted the
  3.2598-      ;; opening delimiter, and then indent the whole S-expression.
  3.2599-      (backward-up-list)
  3.2600-      (lisp-indent-line)
  3.2601-      (indent-sexp))
  3.2602-    ;; If we slurped into an empty list, don't leave dangling space:
  3.2603-    ;; (foo |).
  3.2604-    (if (and (not nestedp)
  3.2605-             (eq (save-excursion (paredit-skip-whitespace nil) (point))
  3.2606-                 (save-excursion (backward-sexp) (forward-sexp) (point)))
  3.2607-             (eq (save-excursion (up-list) (backward-char) (point))
  3.2608-                 (save-excursion (paredit-skip-whitespace t) (point))))
  3.2609-        (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  3.2610-                       (save-excursion (paredit-skip-whitespace t) (point))))))
  3.2611-
  3.2612-(defun paredit-backward-slurp-into-string (&optional argument)
  3.2613-  (let ((start (paredit-enclosing-string-start))
  3.2614-        (end (paredit-enclosing-string-end)))
  3.2615-    (goto-char start)
  3.2616-    ;; Signal any errors that we might get first, before mucking with
  3.2617-    ;; the buffer's contents.
  3.2618-    (save-excursion (backward-sexp))
  3.2619-    (let ((open (char-after))
  3.2620-          (target (point)))
  3.2621-      ;; Skip intervening whitespace if we're slurping into an empty
  3.2622-      ;; string.  XXX What about nonempty strings?
  3.2623-      (if (and (= (+ start 2) end)
  3.2624-               (eq (save-excursion (paredit-skip-whitespace nil) (point))
  3.2625-                   (save-excursion (backward-sexp) (forward-sexp) (point))))
  3.2626-          (delete-region (save-excursion (paredit-skip-whitespace nil) (point))
  3.2627-                         (+ (point) 1))
  3.2628-          (delete-char +1))
  3.2629-      (backward-sexp)
  3.2630-      (if argument
  3.2631-          (paredit-ignore-sexp-errors
  3.2632-            (while (not (bobp))
  3.2633-              (backward-sexp))))
  3.2634-      (insert open)
  3.2635-      (paredit-forward-for-quote target))))
  3.2636-
  3.2637-(defun paredit-backward-barf-sexp (&optional argument)
  3.2638-  "Remove the first S-expression in the current list from that list
  3.2639-  by moving the closing delimiter.
  3.2640-Automatically reindent the barfed S-expression and the form from which
  3.2641-  it was barfed."
  3.2642-  (interactive "P")
  3.2643-  (paredit-lose-if-not-in-sexp 'paredit-backward-barf-sexp)
  3.2644-  (if (and (numberp argument) (< argument 0))
  3.2645-      (paredit-backward-slurp-sexp (- 0 argument))
  3.2646-    (let ((end (make-marker)))
  3.2647-      (set-marker end (point))
  3.2648-      (save-excursion
  3.2649-        (backward-up-list)
  3.2650-        (let ((open (char-after)))
  3.2651-          (delete-char +1)
  3.2652-          (paredit-ignore-sexp-errors
  3.2653-            (paredit-forward-and-indent
  3.2654-             (if (or (not argument) (numberp argument))
  3.2655-                 argument
  3.2656-                 (let ((n 0))
  3.2657-                   (save-excursion
  3.2658-                     (while (paredit-handle-sexp-errors
  3.2659-                                (save-excursion
  3.2660-                                  (forward-sexp)
  3.2661-                                  (<= (point) end))
  3.2662-                              nil)
  3.2663-                       (forward-sexp)
  3.2664-                       (setq n (+ n 1))))
  3.2665-                   n))))
  3.2666-          (while (progn (paredit-skip-whitespace t) (eq (char-after) ?\; ))
  3.2667-            (forward-line 1))
  3.2668-          (if (eobp)
  3.2669-              ;++ We'll have deleted the close, but there's no open.
  3.2670-              ;++ Is that OK?
  3.2671-              (error "Barfing all subexpressions with no close-paren?"))
  3.2672-          ;** Don't use `insert' here.  Consider, e.g., barfing from
  3.2673-          ;**   (foo|)
  3.2674-          ;** and how `save-excursion' works.
  3.2675-          (insert-before-markers open))
  3.2676-        (backward-up-list)
  3.2677-        (lisp-indent-line)
  3.2678-        (indent-sexp)))))
  3.2679-
  3.2680-;;;; Splitting & Joining
  3.2681-
  3.2682-(defun paredit-split-sexp ()
  3.2683-  "Split the list or string the point is on into two."
  3.2684-  (interactive)
  3.2685-  (cond ((paredit-in-string-p)
  3.2686-         (insert "\"")
  3.2687-         (save-excursion (insert " \"")))
  3.2688-        ((or (paredit-in-comment-p)
  3.2689-             (paredit-in-char-p))
  3.2690-         (error "Invalid context for splitting S-expression."))
  3.2691-        (t
  3.2692-         (let ((open (save-excursion (backward-up-list) (char-after)))
  3.2693-               (close (save-excursion (up-list) (char-before))))
  3.2694-           (delete-horizontal-space)
  3.2695-           (insert close)
  3.2696-           (save-excursion
  3.2697-             (insert ?\ )
  3.2698-             (insert open)
  3.2699-             (backward-char)
  3.2700-             (indent-sexp))))))
  3.2701-
  3.2702-(defun paredit-join-sexps ()
  3.2703-  "Join the S-expressions adjacent on either side of the point.
  3.2704-Both must be lists, strings, or atoms; error if there is a mismatch."
  3.2705-  (interactive)
  3.2706-  (cond ((paredit-in-comment-p) (error "Can't join S-expressions in comment."))
  3.2707-        ((paredit-in-string-p) (error "Nothing to join in a string."))
  3.2708-        ((paredit-in-char-p) (error "Can't join characters.")))
  3.2709-  (let ((left-point (paredit-point-at-sexp-end))
  3.2710-        (right-point (paredit-point-at-sexp-start)))
  3.2711-    (let ((left-char (char-before left-point))
  3.2712-          (right-char (char-after right-point)))
  3.2713-      (let ((left-syntax (char-syntax left-char))
  3.2714-            (right-syntax (char-syntax right-char)))
  3.2715-        (cond ((< right-point left-point)
  3.2716-               (error "Can't join a datum with itself."))
  3.2717-              ((and (eq left-syntax ?\) )
  3.2718-                    (eq right-syntax ?\( )
  3.2719-                    (eq left-char (matching-paren right-char))
  3.2720-                    (eq right-char (matching-paren left-char)))
  3.2721-               (paredit-join-lists-internal left-point right-point)
  3.2722-               (paredit-preserving-column
  3.2723-                 (save-excursion
  3.2724-                   (backward-up-list)
  3.2725-                   (indent-sexp))))
  3.2726-              ((and (eq left-syntax ?\" )
  3.2727-                    (eq right-syntax ?\" ))
  3.2728-               ;; Delete any intermediate formatting.
  3.2729-               (delete-region (1- left-point) (1+ right-point)))
  3.2730-              ((and (memq left-syntax '(?w ?_)) ; Word or symbol
  3.2731-                    (memq right-syntax '(?w ?_)))
  3.2732-               (delete-region left-point right-point))
  3.2733-              (t (error "Mismatched S-expressions to join.")))))))
  3.2734-
  3.2735-(defun paredit-join-lists-internal (left-point right-point)
  3.2736-  (save-excursion
  3.2737-    ;; Leave intermediate formatting alone.
  3.2738-    (goto-char right-point)
  3.2739-    (delete-char +1)
  3.2740-    (goto-char left-point)
  3.2741-    (delete-char -1)
  3.2742-    ;; Kludge: Add an extra space in several conditions.
  3.2743-    (if (or
  3.2744-         ;; (foo)| ;x\n(bar) => (foo | ;x\nbar), not (foo|  ;x\nbar).
  3.2745-         (and (not (eolp))
  3.2746-              (save-excursion
  3.2747-                (paredit-skip-whitespace t (point-at-eol))
  3.2748-                (eq (char-after) ?\;)))
  3.2749-         ;; (foo)|(bar) => (foo| bar), not (foo|bar).
  3.2750-         (and (= left-point right-point)
  3.2751-              (not (or (eq ?\  (char-syntax (char-before)))
  3.2752-                       (eq ?\  (char-syntax (char-after)))))))
  3.2753-        (insert ?\  ))))
  3.2754-
  3.2755-;++ How ought paredit-join to handle comments intervening symbols or strings?
  3.2756-;++ Idea:
  3.2757-;++
  3.2758-;++   "foo"   |        ;bar
  3.2759-;++   "baz"      ;quux
  3.2760-;++
  3.2761-;++ =>
  3.2762-;++
  3.2763-;++   "foo|baz"       ;bar
  3.2764-;++              ;quux
  3.2765-;++
  3.2766-;++ The point should stay where it is relative to the comments, and the
  3.2767-;++ the comments' columns should all be preserved, perhaps.  Hmmmm...
  3.2768-;++ What about this?
  3.2769-;++
  3.2770-;++   "foo"           ;bar
  3.2771-;++       |           ;baz
  3.2772-;++   "quux"          ;zot
  3.2773-
  3.2774-;++ Should rename:
  3.2775-;++     paredit-point-at-sexp-start     -> paredit-start-of-sexp-after-point
  3.2776-;++     paredit-point-at-sexp-end       -> paredit-end-of-sexp-before-point
  3.2777-
  3.2778-;;;; Variations on the Lurid Theme
  3.2779-
  3.2780-;;; I haven't the imagination to concoct clever names for these.
  3.2781-
  3.2782-(defun paredit-add-to-previous-list ()
  3.2783-  "Add the S-expression following point to the list preceding point."
  3.2784-  (interactive)
  3.2785-  (paredit-lose-if-not-in-sexp 'paredit-add-to-previous-list)
  3.2786-  (save-excursion
  3.2787-    (down-list -1)                      ;++ backward-down-list...
  3.2788-    (paredit-forward-slurp-sexp)))
  3.2789-
  3.2790-(defun paredit-add-to-next-list ()
  3.2791-  "Add the S-expression preceding point to the list following point.
  3.2792-If no S-expression precedes point, move up the tree until one does."
  3.2793-  (interactive)
  3.2794-  (paredit-lose-if-not-in-sexp 'paredit-add-to-next-list)
  3.2795-  (save-excursion
  3.2796-    (down-list)
  3.2797-    (paredit-backward-slurp-sexp)))
  3.2798-
  3.2799-(defun paredit-join-with-previous-list ()
  3.2800-  "Join the list the point is on with the previous list in the buffer."
  3.2801-  (interactive)
  3.2802-  (paredit-lose-if-not-in-sexp 'paredit-join-with-previous-list)
  3.2803-  (save-excursion
  3.2804-    (while (paredit-handle-sexp-errors (save-excursion (backward-sexp) nil)
  3.2805-             (backward-up-list)
  3.2806-             t))
  3.2807-    (paredit-join-sexps)))
  3.2808-
  3.2809-(defun paredit-join-with-next-list ()
  3.2810-  "Join the list the point is on with the next list in the buffer."
  3.2811-  (interactive)
  3.2812-  (paredit-lose-if-not-in-sexp 'paredit-join-with-next-list)
  3.2813-  (save-excursion
  3.2814-    (while (paredit-handle-sexp-errors (save-excursion (forward-sexp) nil)
  3.2815-             (up-list)
  3.2816-             t))
  3.2817-    (paredit-join-sexps)))
  3.2818-
  3.2819-;;;; Utilities
  3.2820-
  3.2821-(defun paredit-in-string-escape-p ()
  3.2822-  "True if the point is on a character escape of a string.
  3.2823-This is true only if the character is preceded by an odd number of
  3.2824-  backslashes.
  3.2825-This assumes that `paredit-in-string-p' has already returned true."
  3.2826-  (let ((oddp nil))
  3.2827-    (save-excursion
  3.2828-      (while (eq (char-before) ?\\ )
  3.2829-        (setq oddp (not oddp))
  3.2830-        (backward-char)))
  3.2831-    oddp))
  3.2832-
  3.2833-(defun paredit-in-char-p (&optional position)
  3.2834-  "True if point is on a character escape outside a string."
  3.2835-  (save-excursion
  3.2836-    (goto-char (or position (point)))
  3.2837-    (paredit-in-string-escape-p)))
  3.2838-
  3.2839-(defun paredit-skip-whitespace (trailing-p &optional limit)
  3.2840-  "Skip past any whitespace, or until the point LIMIT is reached.
  3.2841-If TRAILING-P is nil, skip leading whitespace; otherwise, skip trailing
  3.2842-  whitespace."
  3.2843-  (funcall (if trailing-p 'skip-chars-forward 'skip-chars-backward)
  3.2844-           " \t\n"  ; This should skip using the syntax table, but LF
  3.2845-           limit))    ; is a comment end, not newline, in Lisp mode.
  3.2846-
  3.2847-(defalias 'paredit-region-active-p
  3.2848-  (xcond ((paredit-xemacs-p) 'region-active-p)
  3.2849-         ((paredit-gnu-emacs-p)
  3.2850-          (lambda ()
  3.2851-            (and mark-active transient-mark-mode)))))
  3.2852-
  3.2853-(defun paredit-hack-kill-region (start end)
  3.2854-  "Kill the region between START and END.
  3.2855-Do not append to any current kill, and
  3.2856- do not let the next kill append to this one."
  3.2857-  (interactive "r")                     ;Eh, why not?
  3.2858-  ;; KILL-REGION sets THIS-COMMAND to tell the next kill that the last
  3.2859-  ;; command was a kill.  It also checks LAST-COMMAND to see whether it
  3.2860-  ;; should append.  If we bind these locally, any modifications to
  3.2861-  ;; THIS-COMMAND will be masked, and it will not see LAST-COMMAND to
  3.2862-  ;; indicate that it should append.
  3.2863-  (let ((this-command nil)
  3.2864-        (last-command nil))
  3.2865-    (kill-region start end)))
  3.2866-
  3.2867-;;;;; Reindentation utilities
  3.2868-
  3.2869-;++ Should `paredit-indent-sexps' and `paredit-forward-and-indent' use
  3.2870-;++ `paredit-indent-region' rather than `indent-region'?
  3.2871-
  3.2872-(defun paredit-indent-sexps ()
  3.2873-  "If in a list, indent all following S-expressions in the list."
  3.2874-  (let* ((start (point))
  3.2875-         (end (paredit-handle-sexp-errors (progn (up-list) (point)) nil)))
  3.2876-    (if end
  3.2877-        (indent-region start end nil))))
  3.2878-
  3.2879-(defun paredit-forward-and-indent (&optional n)
  3.2880-  "Move forward by N S-expressions, indenting them with `indent-region'."
  3.2881-  (let ((start (point)))
  3.2882-    (forward-sexp n)
  3.2883-    (indent-region start (point) nil)))
  3.2884-
  3.2885-(defun paredit-indent-region (start end)
  3.2886-  "Indent the region from START to END.
  3.2887-Don't reindent the line starting at START, however."
  3.2888-  (if (not (<= start end))
  3.2889-      (error "Incorrectly related points: %S, %S" start end))
  3.2890-  (save-excursion
  3.2891-    (goto-char start)
  3.2892-    (let ((bol (point-at-bol)))
  3.2893-      ;; Skip all S-expressions that end on the starting line, but
  3.2894-      ;; don't go past `end'.
  3.2895-      (if (and (save-excursion (goto-char end) (not (eq bol (point-at-bol))))
  3.2896-               (paredit-handle-sexp-errors
  3.2897-                   (catch 'exit
  3.2898-                     (while t
  3.2899-                       (save-excursion
  3.2900-                         (forward-sexp)
  3.2901-                         (if (not (eq bol (point-at-bol)))
  3.2902-                             (throw 'exit t))
  3.2903-                         (if (not (< (point) end))
  3.2904-                             (throw 'exit nil)))
  3.2905-                       (forward-sexp)))
  3.2906-                 nil))
  3.2907-          (progn
  3.2908-            ;; Point is still on the same line, but precedes an
  3.2909-            ;; S-expression that ends on a different line.
  3.2910-            (if (not (eq bol (point-at-bol)))
  3.2911-                (error "Internal error -- we moved forward a line!"))
  3.2912-            (goto-char (+ 1 (point-at-eol)))
  3.2913-            (if (not (<= (point) end))
  3.2914-                (error "Internal error -- we frobnitzed the garfnut!"))
  3.2915-            (indent-region (point) end nil))))))
  3.2916-
  3.2917-;;;;; S-expression Parsing Utilities
  3.2918-
  3.2919-;++ These routines redundantly traverse S-expressions a great deal.
  3.2920-;++ If performance issues arise, this whole section will probably have
  3.2921-;++ to be refactored to preserve the state longer, like paredit.scm
  3.2922-;++ does, rather than to traverse the definition N times for every key
  3.2923-;++ stroke as it presently does.
  3.2924-
  3.2925-(defun paredit-current-parse-state ()
  3.2926-  "Return parse state of point from beginning of defun."
  3.2927-  (let ((point (point)))
  3.2928-    (beginning-of-defun)
  3.2929-    ;; Calling PARSE-PARTIAL-SEXP will advance the point to its second
  3.2930-    ;; argument (unless parsing stops due to an error, but we assume it
  3.2931-    ;; won't in paredit-mode).
  3.2932-    (parse-partial-sexp (point) point)))
  3.2933-
  3.2934-(defun paredit-in-string-p (&optional state)
  3.2935-  "True if the parse state is within a double-quote-delimited string.
  3.2936-If no parse state is supplied, compute one from the beginning of the
  3.2937-  defun to the point."
  3.2938-  ;; 3. non-nil if inside a string (the terminator character, really)
  3.2939-  (and (nth 3 (or state (paredit-current-parse-state)))
  3.2940-       t))
  3.2941-
  3.2942-(defun paredit-string-start+end-points (&optional state)
  3.2943-  "Return a cons of the points of open and close quotes of the string.
  3.2944-The string is determined from the parse state STATE, or the parse state
  3.2945-  from the beginning of the defun to the point.
  3.2946-This assumes that `paredit-in-string-p' has already returned true, i.e.
  3.2947-  that the point is already within a string."
  3.2948-  (save-excursion
  3.2949-    ;; 8. character address of start of comment or string; nil if not
  3.2950-    ;;    in one
  3.2951-    (let ((start (nth 8 (or state (paredit-current-parse-state)))))
  3.2952-      (goto-char start)
  3.2953-      (forward-sexp 1)
  3.2954-      (cons start (1- (point))))))
  3.2955-
  3.2956-(defun paredit-enclosing-string-start ()
  3.2957-  (car (paredit-string-start+end-points)))
  3.2958-
  3.2959-(defun paredit-enclosing-string-end ()
  3.2960-  (+ 1 (cdr (paredit-string-start+end-points))))
  3.2961-
  3.2962-(defun paredit-enclosing-list-start ()
  3.2963-  (save-excursion
  3.2964-    (backward-up-list)
  3.2965-    (point)))
  3.2966-
  3.2967-(defun paredit-enclosing-list-end ()
  3.2968-  (save-excursion
  3.2969-    (up-list)
  3.2970-    (point)))
  3.2971-
  3.2972-(defun paredit-in-comment-p (&optional state)
  3.2973-  "True if parse state STATE is within a comment.
  3.2974-If no parse state is supplied, compute one from the beginning of the
  3.2975-  defun to the point."
  3.2976-  ;; 4. nil if outside a comment, t if inside a non-nestable comment,
  3.2977-  ;;    else an integer (the current comment nesting)
  3.2978-  (and (nth 4 (or state (paredit-current-parse-state)))
  3.2979-       t))
  3.2980-
  3.2981-(defun paredit-prefix-numeric-value (argument)
  3.2982-  ;++ Kludgerific.
  3.2983-  (cond ((integerp argument) argument)
  3.2984-        ((eq argument '-) -1)
  3.2985-        ((consp argument)
  3.2986-         (cond ((equal argument '(4)) (paredit-count-sexps-forward))   ;C-u
  3.2987-               ((equal argument '(16)) (paredit-count-sexps-backward)) ;C-u C-u
  3.2988-               (t (error "Invalid prefix argument: %S" argument))))
  3.2989-        ((paredit-region-active-p)
  3.2990-         (save-excursion
  3.2991-           (save-restriction
  3.2992-             (narrow-to-region (region-beginning) (region-end))
  3.2993-             (cond ((= (point) (point-min)) (paredit-count-sexps-forward))
  3.2994-                   ((= (point) (point-max)) (paredit-count-sexps-backward))
  3.2995-                   (t
  3.2996-                    (error "Point %S is not start or end of region: %S..%S"
  3.2997-                           (point) (region-beginning) (region-end)))))))
  3.2998-        (t 1)))
  3.2999-
  3.3000-(defun paredit-count-sexps-forward ()
  3.3001-  (save-excursion
  3.3002-    (let ((n 0) (p nil))                ;hurk
  3.3003-      (paredit-ignore-sexp-errors
  3.3004-        (while (setq p (scan-sexps (point) +1))
  3.3005-          (goto-char p)
  3.3006-          (setq n (+ n 1))))
  3.3007-      n)))
  3.3008-
  3.3009-(defun paredit-count-sexps-backward ()
  3.3010-  (save-excursion
  3.3011-    (let ((n 0) (p nil))                ;hurk
  3.3012-      (paredit-ignore-sexp-errors
  3.3013-        (while (setq p (scan-sexps (point) -1))
  3.3014-          (goto-char p)
  3.3015-          (setq n (+ n 1))))
  3.3016-      n)))
  3.3017-
  3.3018-(defun paredit-point-at-sexp-boundary (n)
  3.3019-  (cond ((< n 0) (paredit-point-at-sexp-start))
  3.3020-        ((= n 0) (point))
  3.3021-        ((> n 0) (paredit-point-at-sexp-end))))
  3.3022-
  3.3023-(defun paredit-point-at-sexp-start ()
  3.3024-  (save-excursion
  3.3025-    (forward-sexp)
  3.3026-    (backward-sexp)
  3.3027-    (point)))
  3.3028-
  3.3029-(defun paredit-point-at-sexp-end ()
  3.3030-  (save-excursion
  3.3031-    (backward-sexp)
  3.3032-    (forward-sexp)
  3.3033-    (point)))
  3.3034-
  3.3035-(defun paredit-lose-if-not-in-sexp (command)
  3.3036-  (if (or (paredit-in-string-p)
  3.3037-          (paredit-in-comment-p)
  3.3038-          (paredit-in-char-p))
  3.3039-      (error "Invalid context for command `%s'." command)))
  3.3040-
  3.3041-(defun paredit-check-region (start end)
  3.3042-  "Signal an error if text between `start' and `end' is unbalanced."
  3.3043-  ;; `narrow-to-region' will move the point, so avoid calling it if we
  3.3044-  ;; don't need to.  We don't want to use `save-excursion' because we
  3.3045-  ;; want the point to move if `check-parens' reports an error.
  3.3046-  (if (not (paredit-region-ok-p start end))
  3.3047-      (save-restriction
  3.3048-        (narrow-to-region start end)
  3.3049-        (check-parens))))
  3.3050-
  3.3051-(defun paredit-region-ok-p (start end)
  3.3052-  "Return true iff the region between `start' and `end' is balanced.
  3.3053-This is independent of context -- it doesn't check what state the
  3.3054-  text at `start' is in."
  3.3055-  (save-excursion
  3.3056-    (paredit-handle-sexp-errors
  3.3057-        (progn
  3.3058-          (save-restriction
  3.3059-            (narrow-to-region start end)
  3.3060-            (scan-sexps (point-min) (point-max)))
  3.3061-          t)
  3.3062-      nil)))
  3.3063-
  3.3064-(defun paredit-current-column ()
  3.3065-  ;; Like current-column, but respects field boundaries in interactive
  3.3066-  ;; modes like ielm.  For use only with paredit-restore-column, which
  3.3067-  ;; works relative to point-at-bol.
  3.3068-  (- (point) (point-at-bol)))
  3.3069-
  3.3070-(defun paredit-current-indentation ()
  3.3071-  (save-excursion
  3.3072-    (back-to-indentation)
  3.3073-    (paredit-current-column)))
  3.3074-
  3.3075-(defun paredit-restore-column (column indentation)
  3.3076-  ;; Preserve the point's position either in the indentation or in the
  3.3077-  ;; code: if on code, move with the code; if in indentation, leave it
  3.3078-  ;; in the indentation, either where it was (if still on indentation)
  3.3079-  ;; or at the end of the indentation (if the code moved far enough
  3.3080-  ;; left).
  3.3081-  (let ((indentation* (paredit-current-indentation)))
  3.3082-    (goto-char
  3.3083-     (+ (point-at-bol)
  3.3084-        (cond ((not (< column indentation))
  3.3085-               (+ column (- indentation* indentation)))
  3.3086-              ((<= indentation* column) indentation*)
  3.3087-              (t column))))))
  3.3088-
  3.3089-;;;; Initialization
  3.3090-
  3.3091-(paredit-define-keys)
  3.3092-(paredit-annotate-mode-with-examples)
  3.3093-(paredit-annotate-functions-with-examples)
  3.3094-
  3.3095-(provide 'paredit)
  3.3096-
  3.3097-;;; Local Variables:
  3.3098-;;; outline-regexp: "\n;;;;+"
  3.3099-;;; End:
  3.3100-
  3.3101-;;; paredit.el ends here