0
|
1 ;;; C comment mode - An auto-filled comment mode for gnu c-mode.
|
|
2 ;;;
|
|
3 ;;; Author: Robert Mecklenburg
|
|
4 ;;; Computer Science Dept.
|
|
5 ;;; University of Utah
|
|
6 ;;; From: mecklen@utah-gr.UUCP (Robert Mecklenburg)
|
|
7 ;;; Also hartzell@Boulder.Colorado.EDU
|
|
8 ;;; (c) 1986, University of Utah
|
|
9 ;;;
|
|
10 ;;; Everyone is granted permission to copy, modify and redistribute
|
|
11 ;;; this file, provided the people they give it to can.
|
|
12
|
|
13 ;;; Synched up with: Not in FSF.
|
|
14
|
|
15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
16 ;;;
|
|
17 ;;; I have written a "global comment" minor-mode which performs auto-fill,
|
|
18 ;;; fill-paragraph, and auto-indentation functions. This function only
|
|
19 ;;; works for comments which occupy an entire line (not comments to the
|
|
20 ;;; right of code). The mode has several options set through variables.
|
|
21 ;;; If the variable c-comment-starting-blank is non-nil multi-line
|
|
22 ;;; comments come out like this:
|
|
23 ;;;
|
|
24 ;;; /*
|
|
25 ;;; * Your favorite
|
|
26 ;;; * multi-line comment.
|
|
27 ;;; */
|
|
28 ;;;
|
|
29 ;;; otherwise they look like this:
|
|
30 ;;;
|
|
31 ;;; /* Your Favorite
|
|
32 ;;; * multi-line comment.
|
|
33 ;;; */
|
|
34 ;;;
|
|
35 ;;; If the variable c-comment-hanging-indent is non-nil K&R style comments
|
|
36 ;;; are indented automatically like this:
|
|
37 ;;;
|
|
38 ;;; /* my_func - For multi-line comments with hanging indent
|
|
39 ;;; * the text is lined up after the dash.
|
|
40 ;;; */
|
|
41 ;;;
|
|
42 ;;; otherwise the text "the text" (!) is lined up under my_func. If a
|
|
43 ;;; comment fits (as typed) on a single line it remains a single line
|
|
44 ;;; comment even if c-comment-starting-blank is set. If
|
|
45 ;;; c-comment-indenting is non-nil hitting carriage return resets the
|
|
46 ;;; indentation for the next line to the current line's indentation
|
|
47 ;;; (within the comment) like this:
|
|
48 ;;;
|
|
49 ;;; /* Typing along merrily....
|
|
50 ;;; * Now I indent with spaces, when I hit return
|
|
51 ;;; * the indentation is automatically set to
|
|
52 ;;; * ^ here.
|
|
53 ;;; */
|
|
54 ;;;
|
|
55 ;;; Due to my lack of understanding of keymaps this permanently resets M-q
|
|
56 ;;; to my own fill function. I would like to have the comment mode
|
|
57 ;;; bindings only in comment mode but I can't seem to get that to work.
|
|
58 ;;; If some gnu guru can clue me in, I'd appreciate it.
|
|
59 ;;;
|
|
60 (defvar c-comment-starting-blank t
|
|
61 "*Controls whether global comments have an initial blank line.")
|
|
62 (defvar c-comment-indenting t
|
|
63 "*If set global comments are indented to the level of the previous line.")
|
|
64 (defvar c-comment-hanging-indent t
|
|
65 "*If true, comments will be automatically indented to the dash.")
|
|
66 (defvar c-hang-already-done t
|
|
67 "If true we have performed the haning indent already for this comment.")
|
|
68
|
|
69
|
|
70 ;;;
|
|
71 ;;; c-comment-map - This is a sparse keymap for comment mode which
|
|
72 ;;; gets inserted when c-comment is called.
|
|
73 ;;;
|
|
74 (defvar c-comment-mode-map ()
|
|
75 "Keymap used in C comment mode.")
|
|
76 (if c-comment-mode-map
|
|
77 ()
|
|
78 (setq c-comment-mode-map (copy-keymap c-mode-map))
|
|
79 (define-key c-comment-mode-map "\e\r" 'newline)
|
|
80 (define-key c-comment-mode-map "\eq" 'set-fill-and-fill)
|
|
81 (define-key c-comment-mode-map "\r" 'set-fill-and-return))
|
|
82
|
|
83 ;;;
|
|
84 ;;; c-comment - This is a filled comment mode which can format
|
|
85 ;;; indented text, do hanging indents, and symetric
|
|
86 ;;; placement of comment delimiters.
|
|
87 ;;;
|
|
88 (defun c-comment ()
|
|
89 "Edit a C comment with filling and indentation.
|
|
90 This performs hanging indentation, symmetric placement of delimiters,
|
|
91 and Indented-Text mode style indentation. Type 'M-x apropos
|
|
92 c-comment' for information on options."
|
|
93 (interactive)
|
|
94 (let
|
|
95 ;; Save old state.
|
|
96 ((auto-fill-function (if c-comment-indenting
|
|
97 'do-indented-auto-fill 'do-auto-fill))
|
|
98 ; (comment-start nil)
|
|
99 (comment-multi-line t)
|
|
100 (comment-start-skip "/*\\*+[ ]*")
|
|
101 (paragraph-start-ref paragraph-start)
|
|
102 fill-prefix paragraph-start paragraph-separate opoint)
|
|
103
|
|
104 ;; Determine if we are inside a comment.
|
|
105 (setq in-comment
|
|
106 (save-excursion
|
|
107 (and (re-search-backward "/\\*\\|\\*/" 0 t)
|
|
108 (string= "/*" (buffer-substring (point) (+ (point) 2))))))
|
|
109
|
|
110 ;; Indent the comment and set the fill prefix to comment continuation
|
|
111 ;; string. If we are already in a comment get the indentation on
|
|
112 ;; the current line.
|
|
113 (setq c-hang-already-done nil)
|
|
114
|
|
115 ;; Set the beginning of the comment and insert the blank line if needed.
|
|
116 (use-local-map c-comment-mode-map)
|
|
117 (if (not in-comment)
|
|
118 (progn (c-indent-line)
|
|
119 (insert "/* ")
|
|
120 (setq fill-prefix (get-current-fill (point)))
|
|
121 (recursive-edit)
|
|
122
|
|
123 ;; If the comment fits on one line, place the close
|
|
124 ;; comment at the end of the line. Otherwise, newline.
|
|
125 (setq opoint (point))
|
|
126 (if (and (save-excursion (beginning-of-line)
|
|
127 (search-forward "/*" opoint t))
|
|
128 (<= (+ (current-column) 3) 79))
|
|
129 (insert " */")
|
|
130 (insert "\n*/"))
|
|
131
|
|
132 (c-indent-line))
|
|
133 (progn (setq fill-prefix (get-current-fill (point)))
|
|
134 (recursive-edit)
|
|
135 (search-forward "*/" (buffer-size) t)
|
|
136 (forward-line 1)))
|
|
137
|
|
138 ;; If starting blank enabled, insert a newline, etc., but only if
|
|
139 ;; this comment requires multiple lines.
|
|
140 (if c-comment-starting-blank
|
|
141 (save-excursion
|
|
142 (setq opoint (point))
|
|
143 (forward-line -1)
|
|
144 (if (or (null (search-forward "/*" opoint t))
|
|
145 (null (search-forward "*/" opoint t)))
|
|
146 (progn
|
|
147 (search-backward "/*")
|
|
148 (re-search-forward comment-start-skip opoint t)
|
|
149 (setq fill-prefix (get-current-fill (point)))
|
|
150 (if (not (looking-at "\n"))
|
|
151 (insert ?\n fill-prefix))))))
|
|
152 ; (indent-new-comment-line))))))
|
|
153
|
|
154 ;; Move cursor to indentation.
|
|
155 (c-indent-line)
|
|
156 (use-local-map c-mode-map)
|
|
157 )
|
|
158 )
|
|
159
|
|
160
|
|
161 ;;;
|
|
162 ;;; set-fill-and-fill - Get the current fill for this line and fill
|
|
163 ;;; the paragraph.
|
|
164 ;;;
|
|
165 (defun set-fill-and-fill (arg)
|
|
166 "Get the fill-prefix and fill the current paragraph."
|
|
167
|
|
168 (interactive "P")
|
|
169 (setq fill-prefix (get-current-fill (point)))
|
|
170 (fill-paragraph arg))
|
|
171
|
|
172 ;;;
|
|
173 ;;; set-fill-and-return - Set the current fill prefix and
|
|
174 ;;; indent-new-comment-line.
|
|
175 ;;;
|
|
176 (defun set-fill-and-return ()
|
|
177 "Set the current fill prefix and move to the next line."
|
|
178
|
|
179 (interactive)
|
|
180 (if c-comment-indenting
|
|
181 (setq fill-prefix (get-current-fill (point))))
|
|
182 (insert ?\n fill-prefix))
|
|
183
|
|
184 ;;;
|
|
185 ;;; do-indented-auto-fill - Perform the auto-fill function, but get
|
|
186 ;;; the fill-prefix first.
|
|
187 ;;;
|
|
188 (defun do-indented-auto-fill ()
|
|
189 "Perform auto-fill, but get fill-prefix first."
|
|
190
|
|
191 (let ((opoint (point)))
|
|
192 (save-excursion
|
|
193 (move-to-column (1+ fill-column))
|
|
194 (skip-chars-backward "^ \t\n")
|
|
195 (if (bolp)
|
|
196 (re-search-forward "[ \t]" opoint t))
|
|
197 ;; If there is a space on the line before fill-point,
|
|
198 ;; and nonspaces precede it, break the line there.
|
|
199 (if (save-excursion
|
|
200 (skip-chars-backward " \t")
|
|
201 (not (bolp)))
|
|
202
|
|
203 ;; If we are wrapping to a new line, figure out the indentation on
|
|
204 ;; the current line first.
|
|
205 (progn
|
|
206 (setq fill-prefix (get-current-fill opoint))
|
|
207 (insert ?\n fill-prefix)))))
|
|
208 ; (indent-new-comment-line)))))
|
|
209 )
|
|
210
|
|
211
|
|
212 ;;;
|
|
213 ;;; get-current-fill - Get the fill-prefix for the current line. This
|
|
214 ;;; assumes that the valid fill prefix is between
|
|
215 ;;; (beginning-of-line) and (point).
|
|
216 ;;;
|
|
217 (defun get-current-fill (pnt)
|
|
218 "Get the current fill prefix.
|
|
219 A valid fill prefix must be between the beginning of the line and point."
|
|
220
|
|
221 (let ((opoint pnt) fill last-char)
|
|
222 (save-excursion
|
|
223 (beginning-of-line)
|
|
224 (setq fill
|
|
225 (buffer-substring (point)
|
|
226 (progn
|
|
227 (re-search-forward comment-start-skip opoint t)
|
|
228 (point))))
|
|
229
|
|
230 ;; Be sure there is trailing white space.
|
|
231 (setq last-char (substring fill (1- (length fill)) (length fill)))
|
|
232 (if (and (not (string= " " last-char))
|
|
233 (not (string= " " last-char)))
|
|
234 (setq fill (concat fill " ")))
|
|
235
|
|
236 (setq fill (replace-letter fill "/" " "))
|
|
237
|
|
238 ;; Get the hanging indentation if we haven't already.
|
|
239 (if (and c-comment-hanging-indent (not c-hang-already-done))
|
|
240 (let ((curr (point))
|
|
241 (opnt (progn (end-of-line) (point))))
|
|
242 (beginning-of-line)
|
|
243 (if (search-forward " - " opnt t)
|
|
244 (progn
|
|
245 (setq fill (concat fill (make-string (- (point) curr) 32)))
|
|
246 (setq c-hang-already-done t)))))
|
|
247
|
|
248 ;; Set the paragraph delimiters.
|
|
249 (setq paragraph-start (concat paragraph-start-ref
|
|
250 "\\|^"
|
|
251 (regexp-quote
|
|
252 (substring fill
|
|
253 0 (1- (length fill))))
|
|
254 "$"))
|
|
255 (setq paragraph-separate paragraph-start))
|
|
256 fill)
|
|
257 )
|
|
258
|
|
259
|
|
260 ;;;
|
|
261 ;;; replace-letter - Given a string, an old letter and a new letter,
|
|
262 ;;; perform the substitution.
|
|
263 ;;;
|
|
264 (defun replace-letter (str old-letter new-letter)
|
|
265 (let (new-str c
|
|
266 (sp 0)
|
|
267 (size (length str)))
|
|
268 (while (< sp size)
|
|
269 (setq c (substring str sp (1+ sp)))
|
|
270 (setq new-str (concat new-str (if (string= c old-letter) new-letter c)))
|
|
271 (setq sp (1+ sp)))
|
|
272 new-str))
|