source: vendor/m4/1.4.8/c-boxes.el@ 3090

Last change on this file since 3090 was 3090, checked in by bird, 18 years ago

m4 1.4.8

File size: 12.6 KB
Line 
1;;; Boxed comments for C mode.
2;;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3;;; Francois Pinard <pinard@iro.umontreal.ca>, April 1991.
4;;;
5;;; I often refill paragraphs inside C comments, while stretching or
6;;; shrinking the surrounding box as needed. This is a real pain to
7;;; do by hand. Here is the code I made to ease my life on this,
8;;; usable from within GNU Emacs. It would not be fair giving all
9;;; sources for a product without also giving the means for nicely
10;;; modifying them.
11;;;
12;;; The function rebox-c-comment adjust comment boxes without
13;;; refilling comment paragraphs, while reindent-c-comment adjust
14;;; comment boxes after refilling. Numeric prefixes are used to add,
15;;; remove, or change the style of the box surrounding the comment.
16;;; Since refilling paragraphs in C mode does make sense only for
17;;; comments, this code redefines the M-q command in C mode. I use
18;;; this hack by putting, in my .emacs file:
19;;;
20;;; (setq c-mode-hook
21;;; '(lambda ()
22;;; (define-key c-mode-map "\M-q" 'reindent-c-comment)))
23;;; (autoload 'rebox-c-comment "c-boxes" nil t)
24;;; (autoload 'reindent-c-comment "c-boxes" nil t)
25;;;
26;;; The cursor should be within a comment before any of these
27;;; commands, or else it should be between two comments, in which case
28;;; the command applies to the next comment. When the command is
29;;; given without prefix, the current comment box type is recognized
30;;; and preserved. Given 0 as a prefix, the comment box disappears
31;;; and the comment stays between a single opening `/*' and a single
32;;; closing `*/'. Given 1 or 2 as a prefix, a single or doubled lined
33;;; comment box is forced. Given 3 as a prefix, a Taarna style box is
34;;; forced, but you do not even want to hear about those. When a
35;;; negative prefix is given, the absolute value is used, but the
36;;; default style is changed. Any other value (like C-u alone) forces
37;;; the default box style.
38;;;
39;;; I observed rounded corners first in some code from Warren Tucker
40;;; <wht@n4hgf.mt-park.ga.us>.
41
42(defvar c-box-default-style 'single "*Preferred style for box comments.")
43(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
44
45;;; Set or reset the Taarna team's own way for a C style.
46
47(defun taarna-mode ()
48 (interactive)
49 (if c-mode-taarna-style
50 (progn
51
52 (setq c-mode-taarna-style nil)
53 (setq c-indent-level 2)
54 (setq c-continued-statement-offset 2)
55 (setq c-brace-offset 0)
56 (setq c-argdecl-indent 5)
57 (setq c-label-offset -2)
58 (setq c-tab-always-indent t)
59 (setq c-box-default-style 'single)
60 (message "C mode: GNU style"))
61
62 (setq c-mode-taarna-style t)
63 (setq c-indent-level 4)
64 (setq c-continued-statement-offset 4)
65 (setq c-brace-offset -4)
66 (setq c-argdecl-indent 4)
67 (setq c-label-offset -4)
68 (setq c-tab-always-indent t)
69 (setq c-box-default-style 'taarna)
70 (message "C mode: Taarna style")))
71
72;;; Return the minimum value of the left margin of all lines, or -1 if
73;;; all lines are empty.
74
75(defun buffer-left-margin ()
76 (let ((margin -1))
77 (goto-char (point-min))
78 (while (not (eobp))
79 (skip-chars-forward " \t")
80 (if (not (looking-at "\n"))
81 (setq margin
82 (if (< margin 0)
83 (current-column)
84 (min margin (current-column)))))
85 (forward-line 1))
86 margin))
87
88;;; Return the maximum value of the right margin of all lines. Any
89;;; sentence ending a line has a space guaranteed before the margin.
90
91(defun buffer-right-margin ()
92 (let ((margin 0) period)
93 (goto-char (point-min))
94 (while (not (eobp))
95 (end-of-line)
96 (if (bobp)
97 (setq period 0)
98 (backward-char 1)
99 (setq period (if (looking-at "[.?!]") 1 0))
100 (forward-char 1))
101 (setq margin (max margin (+ (current-column) period)))
102 (forward-char 1))
103 margin))
104
105;;; Add, delete or adjust a C comment box. If FLAG is nil, the
106;;; current boxing style is recognized and preserved. When 0, the box
107;;; is removed; when 1, a single lined box is forced; when 2, a double
108;;; lined box is forced; when 3, a Taarna style box is forced. If
109;;; negative, the absolute value is used, but the default style is
110;;; changed. For any other value (like C-u), the default style is
111;;; forced. If REFILL is not nil, refill the comment paragraphs prior
112;;; to reboxing.
113
114(defun rebox-c-comment-engine (flag refill)
115 (save-restriction
116 (let ((undo-list buffer-undo-list)
117 (marked-point (point-marker))
118 (saved-point (point))
119 box-style left-margin right-margin)
120
121 ;; First, find the limits of the block of comments following or
122 ;; enclosing the cursor, or return an error if the cursor is not
123 ;; within such a block of comments, narrow the buffer, and
124 ;; untabify it.
125
126 ;; - insure the point is into the following comment, if any
127
128 (skip-chars-forward " \t\n")
129 (if (looking-at "/\\*")
130 (forward-char 2))
131
132 (let ((here (point)) start end temp)
133
134 ;; - identify a minimal comment block
135
136 (search-backward "/*")
137 (setq temp (point))
138 (beginning-of-line)
139 (setq start (point))
140 (skip-chars-forward " \t")
141 (if (< (point) temp)
142 (progn
143 (goto-char saved-point)
144 (error "text before comment's start")))
145 (search-forward "*/")
146 (setq temp (point))
147 (end-of-line)
148 (if (looking-at "\n")
149 (forward-char 1))
150 (setq end (point))
151 (skip-chars-backward " \t\n")
152 (if (> (point) temp)
153 (progn
154 (goto-char saved-point)
155 (error "text after comment's end")))
156 (if (< end here)
157 (progn
158 (goto-char saved-point)
159 (error "outside any comment block")))
160
161 ;; - try to extend the comment block backwards
162
163 (goto-char start)
164 (while (and (not (bobp))
165 (progn (previous-line 1)
166 (beginning-of-line)
167 (looking-at "[ \t]*/\\*.*\\*/[ \t]*$")))
168 (setq start (point)))
169
170 ;; - try to extend the comment block forward
171
172 (goto-char end)
173 (while (looking-at "[ \t]*/\\*.*\\*/[ \t]*$")
174 (forward-line 1)
175 (beginning-of-line)
176 (setq end (point)))
177
178 ;; - narrow to the whole block of comments
179
180 (narrow-to-region start end))
181
182 ;; Second, remove all the comment marks, and move all the text
183 ;; rigidly to the left to insure the left margin stays at the
184 ;; same place. At the same time, recognize and save the box
185 ;; style in BOX-STYLE.
186
187 (let ((previous-margin (buffer-left-margin))
188 actual-margin)
189
190 ;; - remove all comment marks
191
192 (goto-char (point-min))
193 (replace-regexp "^\\([ \t]*\\)/\\*" "\\1 ")
194 (goto-char (point-min))
195 (replace-regexp "^\\([ \t]*\\)|" "\\1 ")
196 (goto-char (point-min))
197 (replace-regexp "\\(\\*/\\||\\)[ \t]*" "")
198 (goto-char (point-min))
199 (replace-regexp "\\*/[ \t]*/\\*" " ")
200
201 ;; - remove the first and last dashed lines
202
203 (setq box-style 'plain)
204 (goto-char (point-min))
205 (if (looking-at "^[ \t]*-*[.\+\\]?[ \t]*\n")
206 (progn
207 (setq box-style 'single)
208 (replace-match ""))
209 (if (looking-at "^[ \t]*=*[.\+\\]?[ \t]*\n")
210 (progn
211 (setq box-style 'double)
212 (replace-match ""))))
213 (goto-char (point-max))
214 (previous-line 1)
215 (beginning-of-line)
216 (if (looking-at "^[ \t]*[`\+\\]?*[-=]+[ \t]*\n")
217 (progn
218 (if (eq box-style 'plain)
219 (setq box-style 'taarna))
220 (replace-match "")))
221
222 ;; - remove all spurious whitespace
223
224 (goto-char (point-min))
225 (replace-regexp "[ \t]+$" "")
226 (goto-char (point-min))
227 (if (looking-at "\n+")
228 (replace-match ""))
229 (goto-char (point-max))
230 (skip-chars-backward "\n")
231 (if (looking-at "\n\n+")
232 (replace-match "\n"))
233 (goto-char (point-min))
234 (replace-regexp "\n\n\n+" "\n\n")
235
236 ;; - move the text left is adequate
237
238 (setq actual-margin (buffer-left-margin))
239 (if (not (= previous-margin actual-margin))
240 (indent-rigidly (point-min) (point-max)
241 (- previous-margin actual-margin))))
242
243 ;; Third, select the new box style from the old box style and
244 ;; the argument, choose the margins for this style and refill
245 ;; each paragraph.
246
247 ;; - modify box-style only if flag is defined
248
249 (if flag
250 (setq box-style
251 (cond ((eq flag 0) 'plain)
252 ((eq flag 1) 'single)
253 ((eq flag 2) 'double)
254 ((eq flag 3) 'taarna)
255 ((eq flag '-) (setq c-box-default-style 'plain) 'plain)
256 ((eq flag -1) (setq c-box-default-style 'single) 'single)
257 ((eq flag -2) (setq c-box-default-style 'double) 'double)
258 ((eq flag -3) (setq c-box-default-style 'taarna) 'taarna)
259 (t c-box-default-style))))
260
261 ;; - compute the left margin
262
263 (setq left-margin (buffer-left-margin))
264
265 ;; - temporarily set the fill prefix and column, then refill
266
267 (untabify (point-min) (point-max))
268
269 (if refill
270 (let ((fill-prefix (make-string left-margin ? ))
271 (fill-column (- fill-column
272 (if (memq box-style '(single double)) 4 6))))
273 (fill-region (point-min) (point-max))))
274
275 ;; - compute the right margin after refill
276
277 (setq right-margin (buffer-right-margin))
278
279 ;; Fourth, put the narrowed buffer back into a comment box,
280 ;; according to the value of box-style. Values may be:
281 ;; plain: insert between a single pair of comment delimiters
282 ;; single: complete box, overline and underline with dashes
283 ;; double: complete box, overline and underline with equal signs
284 ;; taarna: comment delimiters on each line, underline with dashes
285
286 ;; - move the right margin to account for left inserts
287
288 (setq right-margin (+ right-margin
289 (if (memq box-style '(single double))
290 2
291 3)))
292
293 ;; - construct the box comment, from top to bottom
294
295 (goto-char (point-min))
296 (cond ((eq box-style 'plain)
297
298 ;; - construct a plain style comment
299
300 (skip-chars-forward " " (+ (point) left-margin))
301 (insert (make-string (- left-margin (current-column)) ? )
302 "/* ")
303 (end-of-line)
304 (forward-char 1)
305 (while (not (eobp))
306 (skip-chars-forward " " (+ (point) left-margin))
307 (insert (make-string (- left-margin (current-column)) ? )
308 " ")
309 (end-of-line)
310 (forward-char 1))
311 (backward-char 1)
312 (insert " */"))
313 ((eq box-style 'single)
314
315 ;; - construct a single line style comment
316
317 (indent-to left-margin)
318 (insert "/*")
319 (insert (make-string (- right-margin (current-column)) ?-)
320 "-.\n")
321 (while (not (eobp))
322 (skip-chars-forward " " (+ (point) left-margin))
323 (insert (make-string (- left-margin (current-column)) ? )
324 "| ")
325 (end-of-line)
326 (indent-to right-margin)
327 (insert " |")
328 (forward-char 1))
329 (indent-to left-margin)
330 (insert "`")
331 (insert (make-string (- right-margin (current-column)) ?-)
332 "*/\n"))
333 ((eq box-style 'double)
334
335 ;; - construct a double line style comment
336
337 (indent-to left-margin)
338 (insert "/*")
339 (insert (make-string (- right-margin (current-column)) ?=)
340 "=\\\n")
341 (while (not (eobp))
342 (skip-chars-forward " " (+ (point) left-margin))
343 (insert (make-string (- left-margin (current-column)) ? )
344 "| ")
345 (end-of-line)
346 (indent-to right-margin)
347 (insert " |")
348 (forward-char 1))
349 (indent-to left-margin)
350 (insert "\\")
351 (insert (make-string (- right-margin (current-column)) ?=)
352 "*/\n"))
353 ((eq box-style 'taarna)
354
355 ;; - construct a Taarna style comment
356
357 (while (not (eobp))
358 (skip-chars-forward " " (+ (point) left-margin))
359 (insert (make-string (- left-margin (current-column)) ? )
360 "/* ")
361 (end-of-line)
362 (indent-to right-margin)
363 (insert " */")
364 (forward-char 1))
365 (indent-to left-margin)
366 (insert "/* ")
367 (insert (make-string (- right-margin (current-column)) ?-)
368 " */\n"))
369 (t (error "unknown box style")))
370
371 ;; Fifth, retabify, restore the point position, then cleanup the
372 ;; undo list of any boundary since we started.
373
374 ;; - retabify before left margin only (adapted from tabify.el)
375
376 (goto-char (point-min))
377 (while (re-search-forward "^[ \t][ \t][ \t]*" nil t)
378 (let ((column (current-column))
379 (indent-tabs-mode t))
380 (delete-region (match-beginning 0) (point))
381 (indent-to column)))
382
383 ;; - restore the point position
384
385 (goto-char (marker-position marked-point))
386
387 ;; - remove all intermediate boundaries from the undo list
388
389 (if (not (eq buffer-undo-list undo-list))
390 (let ((cursor buffer-undo-list))
391 (while (not (eq (cdr cursor) undo-list))
392 (if (car (cdr cursor))
393 (setq cursor (cdr cursor))
394 (rplacd cursor (cdr (cdr cursor))))))))))
395
396;;; Rebox a C comment without refilling it.
397
398(defun rebox-c-comment (flag)
399 (interactive "P")
400 (rebox-c-comment-engine flag nil))
401
402;;; Rebox a C comment after refilling.
403
404(defun reindent-c-comment (flag)
405 (interactive "P")
406 (rebox-c-comment-engine flag t))
Note: See TracBrowser for help on using the repository browser.