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