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