|
|
- (require 'slime)
- (require 'slime-repl)
- (require 'cl-lib)
-
- (define-slime-contrib slime-editing-commands
- "Editing commands without server interaction."
- (:authors "Thomas F. Burdick <tfb@OCF.Berkeley.EDU>"
- "Luke Gorrie <luke@synap.se>"
- "Bill Clementson <billclem@gmail.com>"
- "Tobias C. Rittweiler <tcr@freebits.de>")
- (:license "GPL")
- (:on-load
- (define-key slime-mode-map "\M-\C-a" 'slime-beginning-of-defun)
- (define-key slime-mode-map "\M-\C-e" 'slime-end-of-defun)
- (define-key slime-mode-map "\C-c\M-q" 'slime-reindent-defun)
- (define-key slime-mode-map "\C-c\C-]" 'slime-close-all-parens-in-sexp)))
-
- (defun slime-beginning-of-defun ()
- (interactive)
- (if (and (boundp 'slime-repl-input-start-mark)
- slime-repl-input-start-mark)
- (slime-repl-beginning-of-defun)
- (let ((this-command 'beginning-of-defun)) ; needed for push-mark
- (call-interactively 'beginning-of-defun))))
-
- (defun slime-end-of-defun ()
- (interactive)
- (if (eq major-mode 'slime-repl-mode)
- (slime-repl-end-of-defun)
- (end-of-defun)))
-
- (defvar slime-comment-start-regexp
- "\\(\\(^\\|[^\n\\\\]\\)\\([\\\\][\\\\]\\)*\\);+[ \t]*"
- "Regexp to match the start of a comment.")
-
- (defun slime-beginning-of-comment ()
- "Move point to beginning of comment.
- If point is inside a comment move to beginning of comment and return point.
- Otherwise leave point unchanged and return NIL."
- (let ((boundary (point)))
- (beginning-of-line)
- (cond ((re-search-forward slime-comment-start-regexp boundary t)
- (point))
- (t (goto-char boundary)
- nil))))
-
- (defvar slime-close-parens-limit nil
- "Maxmimum parens for `slime-close-all-sexp' to insert. NIL
- means to insert as many parentheses as necessary to correctly
- close the form.")
-
- (defun slime-close-all-parens-in-sexp (&optional region)
- "Balance parentheses of open s-expressions at point.
- Insert enough right parentheses to balance unmatched left parentheses.
- Delete extra left parentheses. Reformat trailing parentheses
- Lisp-stylishly.
-
- If REGION is true, operate on the region. Otherwise operate on
- the top-level sexp before point."
- (interactive "P")
- (let ((sexp-level 0)
- point)
- (save-excursion
- (save-restriction
- (when region
- (narrow-to-region (region-beginning) (region-end))
- (goto-char (point-max)))
- ;; skip over closing parens, but not into comment
- (skip-chars-backward ") \t\n")
- (when (slime-beginning-of-comment)
- (forward-line)
- (skip-chars-forward " \t"))
- (setq point (point))
- ;; count sexps until either '(' or comment is found at first column
- (while (and (not (looking-at "^[(;]"))
- (ignore-errors (backward-up-list 1) t))
- (incf sexp-level))))
- (when (> sexp-level 0)
- ;; insert correct number of right parens
- (goto-char point)
- (dotimes (i sexp-level) (insert ")"))
- ;; delete extra right parens
- (setq point (point))
- (skip-chars-forward " \t\n)")
- (skip-chars-backward " \t\n")
- (let* ((deleted-region (delete-and-extract-region point (point)))
- (deleted-text (substring-no-properties deleted-region))
- (prior-parens-count (cl-count ?\) deleted-text)))
- ;; Remember: we always insert as many parentheses as necessary
- ;; and only afterwards delete the superfluously-added parens.
- (when slime-close-parens-limit
- (let ((missing-parens (- sexp-level prior-parens-count
- slime-close-parens-limit)))
- (dotimes (i (max 0 missing-parens))
- (delete-char -1))))))))
-
- (defun slime-insert-balanced-comments (arg)
- "Insert a set of balanced comments around the s-expression
- containing the point. If this command is invoked repeatedly
- \(without any other command occurring between invocations), the
- comment progressively moves outward over enclosing expressions.
- If invoked with a positive prefix argument, the s-expression arg
- expressions out is enclosed in a set of balanced comments."
- (interactive "*p")
- (save-excursion
- (when (eq last-command this-command)
- (when (search-backward "#|" nil t)
- (save-excursion
- (delete-char 2)
- (while (and (< (point) (point-max)) (not (looking-at " *|#")))
- (forward-sexp))
- (replace-match ""))))
- (while (> arg 0)
- (backward-char 1)
- (cond ((looking-at ")") (incf arg))
- ((looking-at "(") (decf arg))))
- (insert "#|")
- (forward-sexp)
- (insert "|#")))
-
- (defun slime-remove-balanced-comments ()
- "Remove a set of balanced comments enclosing point."
- (interactive "*")
- (save-excursion
- (when (search-backward "#|" nil t)
- (delete-char 2)
- (while (and (< (point) (point-max)) (not (looking-at " *|#")))
- (forward-sexp))
- (replace-match ""))))
-
-
- ;; SLIME-CLOSE-PARENS-AT-POINT is obsolete:
-
- ;; It doesn't work correctly on the REPL, because there
- ;; BEGINNING-OF-DEFUN-FUNCTION and END-OF-DEFUN-FUNCTION is bound to
- ;; SLIME-REPL-MODE-BEGINNING-OF-DEFUN (and
- ;; SLIME-REPL-MODE-END-OF-DEFUN respectively) which compromises the
- ;; way how they're expect to work (i.e. END-OF-DEFUN does not signal
- ;; an UNBOUND-PARENTHESES error.)
-
- ;; Use SLIME-CLOSE-ALL-PARENS-IN-SEXP instead.
-
- ;; (defun slime-close-parens-at-point ()
- ;; "Close parenthesis at point to complete the top-level-form. Simply
- ;; inserts ')' characters at point until `beginning-of-defun' and
- ;; `end-of-defun' execute without errors, or `slime-close-parens-limit'
- ;; is exceeded."
- ;; (interactive)
- ;; (loop for i from 1 to slime-close-parens-limit
- ;; until (save-excursion
- ;; (slime-beginning-of-defun)
- ;; (ignore-errors (slime-end-of-defun) t))
- ;; do (insert ")")))
-
- (defun slime-reindent-defun (&optional force-text-fill)
- "Reindent the current defun, or refill the current paragraph.
- If point is inside a comment block, the text around point will be
- treated as a paragraph and will be filled with `fill-paragraph'.
- Otherwise, it will be treated as Lisp code, and the current defun
- will be reindented. If the current defun has unbalanced parens,
- an attempt will be made to fix it before reindenting.
-
- When given a prefix argument, the text around point will always
- be treated as a paragraph. This is useful for filling docstrings."
- (interactive "P")
- (save-excursion
- (if (or force-text-fill (slime-beginning-of-comment))
- (fill-paragraph nil)
- (let ((start (progn (unless (or (and (zerop (current-column))
- (eq ?\( (char-after)))
- (and slime-repl-input-start-mark
- (slime-repl-at-prompt-start-p)))
- (slime-beginning-of-defun))
- (point)))
- (end (ignore-errors (slime-end-of-defun) (point))))
- (unless end
- (forward-paragraph)
- (slime-close-all-parens-in-sexp)
- (slime-end-of-defun)
- (setf end (point)))
- (indent-region start end nil)))))
-
- (provide 'slime-editing-commands)
|