Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 line
7.1 KiB

4 年之前
  1. (require 'slime)
  2. (require 'slime-repl)
  3. (require 'cl-lib)
  4. (define-slime-contrib slime-editing-commands
  5. "Editing commands without server interaction."
  6. (:authors "Thomas F. Burdick <tfb@OCF.Berkeley.EDU>"
  7. "Luke Gorrie <luke@synap.se>"
  8. "Bill Clementson <billclem@gmail.com>"
  9. "Tobias C. Rittweiler <tcr@freebits.de>")
  10. (:license "GPL")
  11. (:on-load
  12. (define-key slime-mode-map "\M-\C-a" 'slime-beginning-of-defun)
  13. (define-key slime-mode-map "\M-\C-e" 'slime-end-of-defun)
  14. (define-key slime-mode-map "\C-c\M-q" 'slime-reindent-defun)
  15. (define-key slime-mode-map "\C-c\C-]" 'slime-close-all-parens-in-sexp)))
  16. (defun slime-beginning-of-defun ()
  17. (interactive)
  18. (if (and (boundp 'slime-repl-input-start-mark)
  19. slime-repl-input-start-mark)
  20. (slime-repl-beginning-of-defun)
  21. (let ((this-command 'beginning-of-defun)) ; needed for push-mark
  22. (call-interactively 'beginning-of-defun))))
  23. (defun slime-end-of-defun ()
  24. (interactive)
  25. (if (eq major-mode 'slime-repl-mode)
  26. (slime-repl-end-of-defun)
  27. (end-of-defun)))
  28. (defvar slime-comment-start-regexp
  29. "\\(\\(^\\|[^\n\\\\]\\)\\([\\\\][\\\\]\\)*\\);+[ \t]*"
  30. "Regexp to match the start of a comment.")
  31. (defun slime-beginning-of-comment ()
  32. "Move point to beginning of comment.
  33. If point is inside a comment move to beginning of comment and return point.
  34. Otherwise 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)
  40. nil))))
  41. (defvar slime-close-parens-limit nil
  42. "Maxmimum parens for `slime-close-all-sexp' to insert. NIL
  43. means to insert as many parentheses as necessary to correctly
  44. close the form.")
  45. (defun slime-close-all-parens-in-sexp (&optional region)
  46. "Balance parentheses of open s-expressions at point.
  47. Insert enough right parentheses to balance unmatched left parentheses.
  48. Delete extra left parentheses. Reformat trailing parentheses
  49. Lisp-stylishly.
  50. If REGION is true, operate on the region. Otherwise operate on
  51. the top-level sexp before point."
  52. (interactive "P")
  53. (let ((sexp-level 0)
  54. point)
  55. (save-excursion
  56. (save-restriction
  57. (when region
  58. (narrow-to-region (region-beginning) (region-end))
  59. (goto-char (point-max)))
  60. ;; skip over closing parens, but not into comment
  61. (skip-chars-backward ") \t\n")
  62. (when (slime-beginning-of-comment)
  63. (forward-line)
  64. (skip-chars-forward " \t"))
  65. (setq point (point))
  66. ;; count sexps until either '(' or comment is found at first column
  67. (while (and (not (looking-at "^[(;]"))
  68. (ignore-errors (backward-up-list 1) t))
  69. (incf sexp-level))))
  70. (when (> sexp-level 0)
  71. ;; insert correct number of right parens
  72. (goto-char point)
  73. (dotimes (i sexp-level) (insert ")"))
  74. ;; delete extra right parens
  75. (setq point (point))
  76. (skip-chars-forward " \t\n)")
  77. (skip-chars-backward " \t\n")
  78. (let* ((deleted-region (delete-and-extract-region point (point)))
  79. (deleted-text (substring-no-properties deleted-region))
  80. (prior-parens-count (cl-count ?\) deleted-text)))
  81. ;; Remember: we always insert as many parentheses as necessary
  82. ;; and only afterwards delete the superfluously-added parens.
  83. (when slime-close-parens-limit
  84. (let ((missing-parens (- sexp-level prior-parens-count
  85. slime-close-parens-limit)))
  86. (dotimes (i (max 0 missing-parens))
  87. (delete-char -1))))))))
  88. (defun slime-insert-balanced-comments (arg)
  89. "Insert a set of balanced comments around the s-expression
  90. containing the point. If this command is invoked repeatedly
  91. \(without any other command occurring between invocations), the
  92. comment progressively moves outward over enclosing expressions.
  93. If invoked with a positive prefix argument, the s-expression arg
  94. expressions out is enclosed in a set of balanced comments."
  95. (interactive "*p")
  96. (save-excursion
  97. (when (eq last-command this-command)
  98. (when (search-backward "#|" nil t)
  99. (save-excursion
  100. (delete-char 2)
  101. (while (and (< (point) (point-max)) (not (looking-at " *|#")))
  102. (forward-sexp))
  103. (replace-match ""))))
  104. (while (> arg 0)
  105. (backward-char 1)
  106. (cond ((looking-at ")") (incf arg))
  107. ((looking-at "(") (decf arg))))
  108. (insert "#|")
  109. (forward-sexp)
  110. (insert "|#")))
  111. (defun slime-remove-balanced-comments ()
  112. "Remove a set of balanced comments enclosing point."
  113. (interactive "*")
  114. (save-excursion
  115. (when (search-backward "#|" nil t)
  116. (delete-char 2)
  117. (while (and (< (point) (point-max)) (not (looking-at " *|#")))
  118. (forward-sexp))
  119. (replace-match ""))))
  120. ;; SLIME-CLOSE-PARENS-AT-POINT is obsolete:
  121. ;; It doesn't work correctly on the REPL, because there
  122. ;; BEGINNING-OF-DEFUN-FUNCTION and END-OF-DEFUN-FUNCTION is bound to
  123. ;; SLIME-REPL-MODE-BEGINNING-OF-DEFUN (and
  124. ;; SLIME-REPL-MODE-END-OF-DEFUN respectively) which compromises the
  125. ;; way how they're expect to work (i.e. END-OF-DEFUN does not signal
  126. ;; an UNBOUND-PARENTHESES error.)
  127. ;; Use SLIME-CLOSE-ALL-PARENS-IN-SEXP instead.
  128. ;; (defun slime-close-parens-at-point ()
  129. ;; "Close parenthesis at point to complete the top-level-form. Simply
  130. ;; inserts ')' characters at point until `beginning-of-defun' and
  131. ;; `end-of-defun' execute without errors, or `slime-close-parens-limit'
  132. ;; is exceeded."
  133. ;; (interactive)
  134. ;; (loop for i from 1 to slime-close-parens-limit
  135. ;; until (save-excursion
  136. ;; (slime-beginning-of-defun)
  137. ;; (ignore-errors (slime-end-of-defun) t))
  138. ;; do (insert ")")))
  139. (defun slime-reindent-defun (&optional force-text-fill)
  140. "Reindent the current defun, or refill the current paragraph.
  141. If point is inside a comment block, the text around point will be
  142. treated as a paragraph and will be filled with `fill-paragraph'.
  143. Otherwise, it will be treated as Lisp code, and the current defun
  144. will be reindented. If the current defun has unbalanced parens,
  145. an attempt will be made to fix it before reindenting.
  146. When given a prefix argument, the text around point will always
  147. be treated as a paragraph. This is useful for filling docstrings."
  148. (interactive "P")
  149. (save-excursion
  150. (if (or force-text-fill (slime-beginning-of-comment))
  151. (fill-paragraph nil)
  152. (let ((start (progn (unless (or (and (zerop (current-column))
  153. (eq ?\( (char-after)))
  154. (and slime-repl-input-start-mark
  155. (slime-repl-at-prompt-start-p)))
  156. (slime-beginning-of-defun))
  157. (point)))
  158. (end (ignore-errors (slime-end-of-defun) (point))))
  159. (unless end
  160. (forward-paragraph)
  161. (slime-close-all-parens-in-sexp)
  162. (slime-end-of-defun)
  163. (setf end (point)))
  164. (indent-region start end nil)))))
  165. (provide 'slime-editing-commands)