Mercurial > hg > xemacs-beta
comparison lisp/modes/c-fill.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
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)) |