Path: blob/master/elisp/slime/contrib/slime-editing-commands.el
990 views
1(define-slime-contrib slime-editing-commands2"Editing commands without server interaction."3(:authors "Thomas F. Burdick <[email protected]>"4"Luke Gorrie <[email protected]>"5"Bill Clementson <[email protected]>"6"Tobias C. Rittweiler <[email protected]>")7(:license "GPL")8(:on-load9(define-key slime-mode-map "\M-\C-a" 'slime-beginning-of-defun)10(define-key slime-mode-map "\M-\C-e" 'slime-end-of-defun)11(define-key slime-mode-map "\C-c\M-q" 'slime-reindent-defun)12(define-key slime-mode-map "\C-c\C-]" 'slime-close-all-parens-in-sexp)))1314(defun slime-beginning-of-defun ()15(interactive)16(if (and (boundp 'slime-repl-input-start-mark)17slime-repl-input-start-mark)18(slime-repl-beginning-of-defun)19(beginning-of-defun)))2021(defun slime-end-of-defun ()22(interactive)23(if (eq major-mode 'slime-repl-mode)24(slime-repl-end-of-defun)25(end-of-defun)))2627(defvar slime-comment-start-regexp28"\\(\\(^\\|[^\n\\\\]\\)\\([\\\\][\\\\]\\)*\\);+[ \t]*"29"Regexp to match the start of a comment.")3031(defun slime-beginning-of-comment ()32"Move point to beginning of comment.33If point is inside a comment move to beginning of comment and return point.34Otherwise leave point unchanged and return NIL."35(let ((boundary (point)))36(beginning-of-line)37(cond ((re-search-forward slime-comment-start-regexp boundary t)38(point))39(t (goto-char boundary)40nil))))4142(defun slime-close-all-parens-in-sexp (&optional region)43"Balance parentheses of open s-expressions at point.44Insert enough right parentheses to balance unmatched left parentheses.45Delete extra left parentheses. Reformat trailing parentheses46Lisp-stylishly.4748If REGION is true, operate on the region. Otherwise operate on49the top-level sexp before point."50(interactive "P")51(let ((sexp-level 0)52point)53(save-excursion54(save-restriction55(when region56(narrow-to-region (region-beginning) (region-end))57(goto-char (point-max)))58;; skip over closing parens, but not into comment59(skip-chars-backward ") \t\n")60(when (slime-beginning-of-comment)61(forward-line)62(skip-chars-forward " \t"))63(setq point (point))64;; count sexps until either '(' or comment is found at first column65(while (and (not (looking-at "^[(;]"))66(ignore-errors (backward-up-list 1) t))67(incf sexp-level))))68(when (> sexp-level 0)69;; insert correct number of right parens70(goto-char point)71(dotimes (i sexp-level) (insert ")"))72;; delete extra right parens73(setq point (point))74(skip-chars-forward " \t\n)")75(skip-chars-backward " \t\n")76(let* ((deleted-region (slime-delete-and-extract-region point (point)))77(deleted-text (substring-no-properties deleted-region))78(prior-parens-count (count ?\) deleted-text)))79;; Remember: we always insert as many parentheses as necessary80;; and only afterwards delete the superfluously-added parens.81(when slime-close-parens-limit82(let ((missing-parens (- sexp-level prior-parens-count83slime-close-parens-limit)))84(dotimes (i (max 0 missing-parens))85(delete-char -1))))))))8687(defvar slime-close-parens-limit nil88"Maxmimum parens for `slime-close-all-sexp' to insert. NIL89means to insert as many parentheses as necessary to correctly90close the form.")9192(defun slime-insert-balanced-comments (arg)93"Insert a set of balanced comments around the s-expression94containing the point. If this command is invoked repeatedly95\(without any other command occurring between invocations), the96comment progressively moves outward over enclosing expressions.97If invoked with a positive prefix argument, the s-expression arg98expressions out is enclosed in a set of balanced comments."99(interactive "*p")100(save-excursion101(when (eq last-command this-command)102(when (search-backward "#|" nil t)103(save-excursion104(delete-char 2)105(while (and (< (point) (point-max)) (not (looking-at " *|#")))106(forward-sexp))107(replace-match ""))))108(while (> arg 0)109(backward-char 1)110(cond ((looking-at ")") (incf arg))111((looking-at "(") (decf arg))))112(insert "#|")113(forward-sexp)114(insert "|#")))115116(defun slime-remove-balanced-comments ()117"Remove a set of balanced comments enclosing point."118(interactive "*")119(save-excursion120(when (search-backward "#|" nil t)121(delete-char 2)122(while (and (< (point) (point-max)) (not (looking-at " *|#")))123(forward-sexp))124(replace-match ""))))125126127;; SLIME-CLOSE-PARENS-AT-POINT is obsolete:128129;; It doesn't work correctly on the REPL, because there130;; BEGINNING-OF-DEFUN-FUNCTION and END-OF-DEFUN-FUNCTION is bound to131;; SLIME-REPL-MODE-BEGINNING-OF-DEFUN (and132;; SLIME-REPL-MODE-END-OF-DEFUN respectively) which compromises the133;; way how they're expect to work (i.e. END-OF-DEFUN does not signal134;; an UNBOUND-PARENTHESES error.)135136;; Use SLIME-CLOSE-ALL-PARENS-IN-SEXP instead.137138;; (defun slime-close-parens-at-point ()139;; "Close parenthesis at point to complete the top-level-form. Simply140;; inserts ')' characters at point until `beginning-of-defun' and141;; `end-of-defun' execute without errors, or `slime-close-parens-limit'142;; is exceeded."143;; (interactive)144;; (loop for i from 1 to slime-close-parens-limit145;; until (save-excursion146;; (slime-beginning-of-defun)147;; (ignore-errors (slime-end-of-defun) t))148;; do (insert ")")))149150(defun slime-reindent-defun (&optional force-text-fill)151"Reindent the current defun, or refill the current paragraph.152If point is inside a comment block, the text around point will be153treated as a paragraph and will be filled with `fill-paragraph'.154Otherwise, it will be treated as Lisp code, and the current defun155will be reindented. If the current defun has unbalanced parens,156an attempt will be made to fix it before reindenting.157158When given a prefix argument, the text around point will always159be treated as a paragraph. This is useful for filling docstrings."160(interactive "P")161(save-excursion162(if (or force-text-fill (slime-beginning-of-comment))163(fill-paragraph nil)164(let ((start (progn (unless (or (and (zerop (current-column))165(eq ?\( (char-after)))166(and slime-repl-input-start-mark167(slime-repl-at-prompt-start-p)))168(slime-beginning-of-defun))169(point)))170(end (ignore-errors (slime-end-of-defun) (point))))171(unless end172(forward-paragraph)173(slime-close-all-parens-in-sexp)174(slime-end-of-defun)175(setf end (point)))176(indent-region start end nil)))))177178(provide 'slime-editing-commands)179180181