Mercurial > hg > xemacs-beta
comparison lisp/modes/old-c++-mode.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 0293115a14e9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; c++-mode.el --- major mode for editing C++ (and C) code | |
2 | |
3 ;; Author: 1992 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com> | |
4 ;; 1987 Dave Detlefs and Stewart Clamen | |
5 ;; 1985 Richard M. Stallman | |
6 ;; Maintainer: c++-mode-help@anthem.nlm.nih.gov | |
7 ;; Created: a long, long, time ago. adapted from the original c-mode.el | |
8 ;; Version: 2.353 | |
9 ;; Last Modified: 1993/06/23 13:58:52 | |
10 ;; Keywords: c | |
11 | |
12 ;; Copyright (C) 1992, 1993 Free Software Foundation, Inc. | |
13 | |
14 ;; This file is part of XEmacs. | |
15 | |
16 ;; XEmacs is free software; you can redistribute it and/or modify it | |
17 ;; under the terms of the GNU General Public License as published by | |
18 ;; the Free Software Foundation; either version 2, or (at your option) | |
19 ;; any later version. | |
20 | |
21 ;; XEmacs is distributed in the hope that it will be useful, but | |
22 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
24 ;; General Public License for more details. | |
25 | |
26 ;; You should have received a copy of the GNU General Public License | |
27 ;; along with XEmacs; see the file COPYING. If not, write to the Free | |
28 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | |
30 ;; Introduction | |
31 ;; ============ | |
32 ;; Do a "C-h m" in a c++-mode buffer for more information on | |
33 ;; customizing c++-mode. To submit bug reports hit "C-c C-b" in a | |
34 ;; c++-mode buffer. This runs the command c++-submit-bug-report and | |
35 ;; automatically sets up the mail buffer with all the necessary | |
36 ;; information. If you have other questions contact me at the | |
37 ;; following address: c++-mode-help@anthem.nlm.nih.gov. Please don't | |
38 ;; send bug reports to my personal account, I may not get it for a | |
39 ;; long time. | |
40 | |
41 ;; Notes for Novice Users | |
42 ;; ====================== | |
43 ;; c++-mode facilitates editing of C++ code by automatically handling | |
44 ;; the indentation of lines of code in a manner very similar to c-mode | |
45 ;; as distributed with GNU Emacs. Refer to the GNU Emacs manual, | |
46 ;; chapter 21 for more information on "Editing Programs". In fact, | |
47 ;; c++-mode (through its companion mode entry point c++-c-mode) can | |
48 ;; also be used to edit both K&R and ANSI C code! | |
49 ;; | |
50 ;; To use c++-mode, add the following to your .emacs file. This | |
51 ;; assumes you will use .cc or .C extensions for your C++ source: | |
52 ;; | |
53 ;; (autoload 'c++-mode "c++-mode" "C++ Editing Mode" t) | |
54 ;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t) | |
55 ;; (setq auto-mode-alist | |
56 ;; (append '(("\\.C$" . c++-mode) | |
57 ;; ("\\.cc$" . c++-mode) | |
58 ;; ("\\.c$" . c++-c-mode) ; to edit C code | |
59 ;; ("\\.h$" . c++-c-mode) ; to edit C code | |
60 ;; ) auto-mode-alist)) | |
61 ;; | |
62 ;; If you want to use the default c-mode for editing C code, then just | |
63 ;; omit the lines marked "to edit C code". | |
64 ;; | |
65 ;; Finally, you may want to customize certain c++-mode variables. The | |
66 ;; best place to do this is in the mode hook variable called | |
67 ;; c++-mode-hook. Again, see the Emacs manual, chapter 21 for more | |
68 ;; information. | |
69 | |
70 ;; Important Note about Escapes in Comments, and Performance | |
71 ;; ========================================================= | |
72 ;; You may notice that certain characters, when typed in comment | |
73 ;; regions, get escaped with a backslash. This is a workaround for | |
74 ;; bugs in Emacs' syntax parsing algorithms. In brief, syntax parsing | |
75 ;; in Emacs 18 and derivatives is broken because syntax tables are not | |
76 ;; rich enough to support more than 1 comment style per mode (as C++ | |
77 ;; requires). The result is that Emacs will sometimes choke on | |
78 ;; unbalanced parentheses and single quotes in comments. Please do a | |
79 ;; "C-h v c++-untame-characters" for more information. | |
80 ;; | |
81 ;; This problem affect both the accuracy and performance of c++-mode | |
82 ;; because some parsing must be performed in Emacs lisp instead of | |
83 ;; relying on the C primitives. In general, I've chosen accuracy over | |
84 ;; performance, but have worked hard to give moderately acceptable | |
85 ;; speed in all but the most uncommon situations. You will most likely | |
86 ;; notice c++-mode slowing when you're editing a file of preprocessor | |
87 ;; commands, or inside long functions or class definitions. | |
88 ;; Optimization is an ongoing concern, but the real solution is to fix | |
89 ;; Emacs. | |
90 ;; | |
91 ;; As of release 19.4, Lucid Emacs is distributed with the fixes in | |
92 ;; place, and c++-mode will automatically take advantage of them so | |
93 ;; none of the above applies to you. Similar patches will be part of | |
94 ;; FSF GNU Emacs 19. Some patches for GNU Emacs 18 have been released | |
95 ;; on the beta site, but they are unsupported. Email for more | |
96 ;; information. | |
97 | |
98 ;; Beta Testers Mailing List | |
99 ;; ========================= | |
100 ;; Want to be a c++-mode victim, er, beta-tester? Send add/drop | |
101 ;; requests to c++-mode-victims-request@anthem.nlm.nih.gov. | |
102 ;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug | |
103 ;; reports and such should still be sent to c++-mode-help only. | |
104 ;; | |
105 ;; Many, many thanks go out to all the folks on the beta test list. | |
106 ;; Without their patience, testing, insight, and code contribution, | |
107 ;; c++-mode.el would be a far inferior package. | |
108 | |
109 ;; Getting c++-mode.el | |
110 ;; =================== | |
111 ;; The latest public release version of this file should always be | |
112 ;; available for anonymous ftp on the Emacs lisp archive machine. The | |
113 ;; path to the file is: | |
114 ;; | |
115 ;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z | |
116 ;; | |
117 ;; For those of you without anon-ftp access, you can use the DEC's | |
118 ;; ftpmail'er at the address ftpmail@decwrl.dec.com. Send the | |
119 ;; following message in the body of your mail to that address to get | |
120 ;; c++-mode: | |
121 ;; | |
122 ;; reply <a valid net address back to you> | |
123 ;; connect archive.cis.ohio-state.edu | |
124 ;; binary | |
125 ;; uuencode | |
126 ;; chdir pub/gnu/emacs/elisp-archive/modes | |
127 ;; get c++-mode.el.Z | |
128 ;; | |
129 ;; or just send the message "help" for more information on ftpmail. | |
130 ;; Response times will vary with the number of requests in the queue. | |
131 | |
132 ;; LCD Archive Entry: | |
133 ;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov | |
134 ;; |Mode for editing C++, and ANSI/K&R C code (was Detlefs' c++-mode.el) | |
135 ;; |1993/06/23 13:58:52|2.353| | |
136 | |
137 ;;; Code: | |
138 | |
139 ;; some people may not have c-mode loaded in by default. c++-mode.el | |
140 ;; unfortunately still depends on distrib c-mode. c-mode doesn't | |
141 ;; provide itself so this hack is best known way to ensure its loaded | |
142 (or (fboundp 'c-mode) | |
143 (load "c-mode" nil t)) | |
144 | |
145 | |
146 ;; ====================================================================== | |
147 ;; user definable variables | |
148 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
149 | |
150 (defconst c++-emacs-features | |
151 (let ((mse-spec 'no-dual-comments) | |
152 (scanner 'v18)) | |
153 ;; vanilla GNU18/Epoch 4 uses default values | |
154 (if (= 8 (length (parse-partial-sexp (point) (point)))) | |
155 ;; we know we're using v19 style dual-comment specifications. | |
156 ;; All Lemacsen use 8-bit modify-syntax-entry flags, as do all | |
157 ;; patched FSF19, GNU18, Epoch4's. Only vanilla FSF19 uses | |
158 ;; 1-bit flag. Lets be as smart as we can about figuring this | |
159 ;; out. | |
160 (let ((table (copy-syntax-table))) | |
161 (modify-syntax-entry ?a ". 12345678" table) | |
162 (if (= (logand (lsh (aref table ?a) -16) 255) 255) | |
163 (setq mse-spec '8-bit) | |
164 (setq mse-spec '1-bit)) | |
165 ;; we also know we're using a quicker, built-in comment | |
166 ;; scanner, but we don't know if its old-style or new. | |
167 ;; Fortunately we can ask emacs directly | |
168 (if (fboundp 'forward-comment) | |
169 (setq scanner 'v19) | |
170 (setq scanner 'old-v19)))) | |
171 ;; now cobble up the necessary list | |
172 (list mse-spec scanner)) | |
173 "A list of needed features extant in the Emacs you are using. | |
174 There are many flavors of Emacs out on the net, each with different | |
175 features supporting those needed by c++-mode. Here's the current | |
176 known list, along with the values for this variable: | |
177 | |
178 Vanilla GNU 18/Epoch 4: (no-dual-comments v18) | |
179 GNU 18/Epoch 4 (patch1): (8-bit old-v19) | |
180 GNU 18/Epoch 4 (patch2): (8-bit v19) | |
181 Lemacs 19.4 - 19.7: (8-bit old-v19) | |
182 Lemacs 19.8 and over: (8-bit v19) | |
183 FSF 19: (1-bit v19) | |
184 FSF 19 (patched): (8-bit v19)") | |
185 | |
186 (defvar c++-mode-abbrev-table nil | |
187 "Abbrev table in use in c++-mode buffers.") | |
188 (define-abbrev-table 'c++-mode-abbrev-table ()) | |
189 | |
190 (defvar c++-mode-map () | |
191 "Keymap used in c++-mode.") | |
192 (if c++-mode-map | |
193 () | |
194 (setq c++-mode-map (make-sparse-keymap)) | |
195 (define-key c++-mode-map "\C-j" 'reindent-then-newline-and-indent) | |
196 (define-key c++-mode-map "\C-m" 'newline-and-indent) | |
197 (define-key c++-mode-map "{" 'c++-electric-brace) | |
198 (define-key c++-mode-map "}" 'c++-electric-brace) | |
199 (define-key c++-mode-map ";" 'c++-electric-semi) | |
200 (define-key c++-mode-map "#" 'c++-electric-pound) | |
201 (define-key c++-mode-map "\e\C-h" 'mark-c-function) | |
202 (define-key c++-mode-map "\e\C-q" 'c++-indent-exp) | |
203 (define-key c++-mode-map "\t" 'c++-indent-command) | |
204 (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header) | |
205 (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region) | |
206 (define-key c++-mode-map "\C-c\C-c" 'c++-comment-region) | |
207 (define-key c++-mode-map "\C-c\C-u" 'c++-uncomment-region) | |
208 (define-key c++-mode-map "\C-c\C-x" 'c++-match-paren) | |
209 (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun) | |
210 (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun) | |
211 (define-key c++-mode-map "\e\C-x" 'c++-indent-defun) | |
212 (define-key c++-mode-map "/" 'c++-electric-slash) | |
213 (define-key c++-mode-map "*" 'c++-electric-star) | |
214 (define-key c++-mode-map ":" 'c++-electric-colon) | |
215 (define-key c++-mode-map "\177" 'c++-electric-delete) | |
216 (define-key c++-mode-map "\C-c\C-t" 'c++-toggle-auto-hungry-state) | |
217 (define-key c++-mode-map "\C-c\C-h" 'c++-toggle-hungry-state) | |
218 (define-key c++-mode-map "\C-c\C-a" 'c++-toggle-auto-state) | |
219 (if (memq 'v18 c++-emacs-features) | |
220 (progn | |
221 (define-key c++-mode-map "\C-c'" 'c++-tame-comments) | |
222 (define-key c++-mode-map "'" 'c++-tame-insert) | |
223 (define-key c++-mode-map "[" 'c++-tame-insert) | |
224 (define-key c++-mode-map "]" 'c++-tame-insert) | |
225 (define-key c++-mode-map "(" 'c++-tame-insert) | |
226 (define-key c++-mode-map ")" 'c++-tame-insert))) | |
227 (define-key c++-mode-map "\C-c\C-b" 'c++-submit-bug-report) | |
228 (define-key c++-mode-map "\C-c\C-v" 'c++-version) | |
229 ;; these are necessary because default forward-sexp and | |
230 ;; backward-sexp don't automatically let-bind | |
231 ;; parse-sexp-ignore-comments, which is needed for them to work | |
232 ;; properly in a C++ buffer. | |
233 (define-key c++-mode-map "\e\C-f" 'c++-forward-sexp) | |
234 (define-key c++-mode-map "\e\C-b" 'c++-backward-sexp) | |
235 ) | |
236 | |
237 (defvar c++-mode-syntax-table nil | |
238 "Syntax table used in c++-mode buffers.") | |
239 (defvar c++-c-mode-syntax-table nil | |
240 "Syntax table used in c++-c-mode buffers.") | |
241 | |
242 (if c++-mode-syntax-table | |
243 () | |
244 (setq c++-mode-syntax-table (make-syntax-table)) | |
245 (modify-syntax-entry ?\\ "\\" c++-mode-syntax-table) | |
246 (modify-syntax-entry ?+ "." c++-mode-syntax-table) | |
247 (modify-syntax-entry ?- "." c++-mode-syntax-table) | |
248 (modify-syntax-entry ?= "." c++-mode-syntax-table) | |
249 (modify-syntax-entry ?% "." c++-mode-syntax-table) | |
250 (modify-syntax-entry ?< "." c++-mode-syntax-table) | |
251 (modify-syntax-entry ?> "." c++-mode-syntax-table) | |
252 (modify-syntax-entry ?& "." c++-mode-syntax-table) | |
253 (modify-syntax-entry ?| "." c++-mode-syntax-table) | |
254 (modify-syntax-entry ?\' "\"" c++-mode-syntax-table) | |
255 ;; comment syntax | |
256 (cond | |
257 ((memq '8-bit c++-emacs-features) | |
258 ;; Lucid emacs has the best implementation | |
259 (modify-syntax-entry ?/ ". 1456" c++-mode-syntax-table) | |
260 (modify-syntax-entry ?* ". 23" c++-mode-syntax-table) | |
261 (modify-syntax-entry ?\n "> b" c++-mode-syntax-table)) | |
262 ((memq '1-bit c++-emacs-features) | |
263 ;; FSF19 has sub-optimal, but workable implementation | |
264 ;; Some strange behavior may be encountered. LOBBY FSF! | |
265 (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table) | |
266 (modify-syntax-entry ?* ". 23b" c++-mode-syntax-table) | |
267 (modify-syntax-entry ?\n ">" c++-mode-syntax-table)) | |
268 (t | |
269 ;; Vanilla GNU18 is just plain busted. We'll do the best we can, | |
270 ;; but some strange behavior may be encountered. PATCH or UPGRADE! | |
271 (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table) | |
272 (modify-syntax-entry ?* ". 23" c++-mode-syntax-table) | |
273 (modify-syntax-entry ?\n ">" c++-mode-syntax-table)) | |
274 )) | |
275 | |
276 (if c++-c-mode-syntax-table | |
277 () | |
278 (setq c++-c-mode-syntax-table (make-syntax-table)) | |
279 (modify-syntax-entry ?\\ "\\" c++-c-mode-syntax-table) | |
280 (modify-syntax-entry ?+ "." c++-c-mode-syntax-table) | |
281 (modify-syntax-entry ?- "." c++-c-mode-syntax-table) | |
282 (modify-syntax-entry ?= "." c++-c-mode-syntax-table) | |
283 (modify-syntax-entry ?% "." c++-c-mode-syntax-table) | |
284 (modify-syntax-entry ?< "." c++-c-mode-syntax-table) | |
285 (modify-syntax-entry ?> "." c++-c-mode-syntax-table) | |
286 (modify-syntax-entry ?& "." c++-c-mode-syntax-table) | |
287 (modify-syntax-entry ?| "." c++-c-mode-syntax-table) | |
288 (modify-syntax-entry ?\' "\"" c++-c-mode-syntax-table) | |
289 (modify-syntax-entry ?/ ". 14" c++-c-mode-syntax-table) | |
290 (modify-syntax-entry ?* ". 23" c++-c-mode-syntax-table) | |
291 ) | |
292 | |
293 (defvar c++-tab-always-indent | |
294 (if (boundp 'c-tab-always-indent) c-tab-always-indent t) | |
295 "*Controls the operation of the TAB key. | |
296 If t (the default), always just indent the current line. If nil, | |
297 indent the current line only if point is at the left margin or in the | |
298 line's indentation; otherwise insert a tab. If not-nil-or-t, then tab | |
299 is inserted only within literals (comments and strings) and inside | |
300 preprocessor directives, but line is always reindented.") | |
301 (defvar c++-always-arglist-indent-p nil | |
302 "*Control indentation of continued arglists. | |
303 When non-nil, arglists continued on subsequent lines will always | |
304 indent `c++-empty-arglist-indent' spaces, otherwise, they will indent to | |
305 just under previous line's argument indentation.") | |
306 (defvar c++-block-close-brace-offset 0 | |
307 "*Extra indentation given to close braces which close a block. | |
308 This variable can be either an integer or a list. If an integer, it | |
309 describes the extra offset given a block closing brace (and a closing | |
310 paren if `c++-paren-as-block-close-p' is non-nil), treating all | |
311 closing parens the same. If a list of the form (OTHERS . TOPLEVEL), | |
312 OTHERS is an integer describing the offset given to all but top-level | |
313 (e.g. function) closing braces, while TOPLEVEL is an integer | |
314 describing offset given only to braces which close top-level | |
315 constructs.") | |
316 (defvar c++-paren-as-block-close-p nil | |
317 "*Treat a parenthesis which is the first non-whitespace on a line as | |
318 a paren which closes a block. When non-nil, `c-indent-level' is | |
319 subtracted, and `c++-block-close-brace-offset' is added to the line's | |
320 offset.") | |
321 (defvar c++-continued-member-init-offset nil | |
322 "*Extra indent for continuation lines of member inits; nil means to align | |
323 with previous initializations rather than with the colon on the first line.") | |
324 (defvar c++-member-init-indent 0 | |
325 "*Indentation level of member initializations in function declarations.") | |
326 (defvar c++-friend-offset -4 | |
327 "*Offset of C++ friend class declarations relative to member declarations.") | |
328 (defvar c++-access-specifier-offset c-label-offset | |
329 "*Extra indentation given to public, protected, and private labels.") | |
330 (defvar c++-empty-arglist-indent nil | |
331 "*Indicates how far to indent a line following an empty argument list. | |
332 Nil means indent to just after the paren.") | |
333 (defvar c++-comment-only-line-offset 0 | |
334 "*Indentation offset for line which contains only C or C++ style comments. | |
335 This variable can take either a single integer or a list of integers. | |
336 If a single integer this is the extra indentation offset to apply to | |
337 all comment-only lines, except those which start in column zero. If a | |
338 list is used, the first integer is for all non-column-zero | |
339 comment-only lines and the second integer is for all column-zero | |
340 lines. You can also use a list containing only 1 integer, in which | |
341 case, this value is used for all comment-only lines. For example: | |
342 | |
343 value meaning | |
344 ===== ======= | |
345 0 comment-only lines do not indent | |
346 4 non-col0 lines indent 4 spaces, col0 lines don't indent | |
347 '(4) all comment-only lines indent 4 spaces | |
348 '(4 1) non-col0 lines indent 4 spaces, col0 lines indent 1 space") | |
349 | |
350 (defvar c++-C-block-comments-indent-p nil | |
351 "*4 styles of C block comments are supported. If this variable is nil, | |
352 then styles 1-3 are supported. If this variable is non-nil, style 4 is | |
353 supported. | |
354 style 1: style 2: style 3: style 4: | |
355 /* /* /* /* | |
356 blah * blah ** blah blah | |
357 blah * blah ** blah blah | |
358 */ */ */ */ | |
359 ") | |
360 (defvar c++-cleanup-list nil | |
361 "*List of various C++ constructs to ``clean up''. | |
362 These cleanups only take place when the auto-newline feature is turned | |
363 on, as evidenced by the `/a' or `/ah' appearing next to the mode name. | |
364 | |
365 Current legal values are: | |
366 `brace-else-brace' -- clean up ``} else {'' constructs by placing entire | |
367 construct on a single line. This cleanup only | |
368 takes place when there is nothing but white | |
369 space between the braces and the else. | |
370 `empty-defun-braces' -- cleans up empty C++ function braces by | |
371 placing them on the same line. | |
372 `defun-close-semi' -- cleans up the terminating semi-colon on class | |
373 definitions and functions by placing the semi | |
374 on the same line as the closing brace.") | |
375 (defvar c++-hanging-braces t | |
376 "*Controls the insertion of newlines before open (left) braces. | |
377 This variable only has effect when auto-newline is on, as evidenced by | |
378 the `/a' or `/ah' appearing next to the mode name. If nil, open | |
379 braces do not hang (i.e. a newline is inserted before all open | |
380 braces). If t, all open braces hang -- no newline is inserted before | |
381 open braces. If not nil or t, newlines are only inserted before | |
382 top-level open braces; all other braces hang.") | |
383 (defvar c++-hanging-member-init-colon 'before | |
384 "*Defines how colons which introduce member initializations are formatted. | |
385 Legal values are: | |
386 t -- no newlines inserted before or after colon | |
387 nil -- newlines inserted before and after colon | |
388 `after' -- newlines inserted only after colon | |
389 `before` -- newlines inserted only before colon") | |
390 (defvar c++-auto-hungry-initial-state 'none | |
391 "*Initial state of auto/hungry features when buffer is first visited. | |
392 Legal values are: | |
393 `none' -- no auto-newline and no hungry-delete-key. | |
394 `auto-only' -- auto-newline, but no hungry-delete-key. | |
395 `hungry-only' -- no auto-newline, but hungry-delete-key. | |
396 `auto-hungry' -- both auto-newline and hungry-delete-key enabled. | |
397 Nil is synonymous for `none' and t is synonymous for `auto-hungry'.") | |
398 | |
399 (defvar c++-auto-hungry-toggle t | |
400 "*Enable/disable toggling of auto/hungry features. | |
401 Legal values are: | |
402 `none' -- auto-newline and hungry-delete-key cannot be enabled. | |
403 `auto-only' -- only auto-newline feature can be toggled. | |
404 `hungry-only' -- only hungry-delete-key feature can be toggled. | |
405 `auto-hungry' -- both auto-newline and hungry-delete-key can be toggled. | |
406 Nil is synonymous for `none' and t is synonymous for `auto-hungry'.") | |
407 | |
408 (defvar c++-relative-offset-p t | |
409 "*Control the calculation for indentation. | |
410 When non-nil (the default), indentation is calculated relative to the | |
411 first statement in the block. When nil, the indentation is calculated | |
412 without regard to how the first statement is indented.") | |
413 | |
414 (defvar c++-untame-characters (and (memq 'v18 c++-emacs-features) '(?\')) | |
415 "*Utilize a backslashing workaround of an Emacs syntax parsing bug. | |
416 If non-nil, this variable should contain a list of characters which | |
417 will be prepended by a backslash in comment regions. By default, the | |
418 list contains only the most troublesome character, the single quote. | |
419 To be completely safe, set this variable to: | |
420 | |
421 '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\]) | |
422 | |
423 This is the full list of characters which can potentially cause | |
424 problems if they exist unbalanced within comments. Setting this | |
425 variable to nil will defeat this feature, but be forewarned! Such | |
426 un-escaped characters in comment regions can potentially break many | |
427 things such as some indenting and blinking of parenthesis. | |
428 | |
429 Note further that only the default set of characters will be escaped | |
430 automatically as they are typed. But, executing `c++-tame-comments' | |
431 (\\[c++-tame-comments]) will escape all characters which are members | |
432 of this set, and which are found in comments throughout the file. | |
433 | |
434 Finally, c++-mode can tell if you're running a patched Emacs. If so, | |
435 taming characters isn't necessary and this variable is automatically | |
436 set to nil.") | |
437 | |
438 (defvar c++-default-macroize-column 78 | |
439 "*Column to insert backslashes.") | |
440 (defvar c++-special-indent-hook nil | |
441 "*Hook for user defined special indentation adjustments. | |
442 This hook gets called after a line is indented by the mode. By | |
443 supplying a hook, you can make adjustments to the line's standard | |
444 indentation. If you do use this hook, you will likely need to also | |
445 set `c++-relative-offset-p' to nil. The call to this hook is wrapped in | |
446 a `save-excursion' so you don't need to worry about restoring point and | |
447 mark inside the hook function.") | |
448 (defvar c++-delete-function 'backward-delete-char-untabify | |
449 "*Function called by `c++-electric-delete' when deleting a single char.") | |
450 (defvar c++-electric-pound-behavior nil | |
451 "*List of behaviors for electric pound insertion. | |
452 Only currently supported behavior is `alignleft'.") | |
453 (defvar c++-backscan-limit 2000 | |
454 "*Limit in characters for looking back while skipping syntactic ws. | |
455 If you typically write really big methods, and start noticing | |
456 incorrect indentations, try cranking this value up. The larger this | |
457 value is, though, the slower parts of c++-mode can become. Setting | |
458 this variable to nil defeats backscan limits.") | |
459 | |
460 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
461 ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT | |
462 ;; | |
463 (defvar c++-hungry-delete-key nil | |
464 "Internal state of hungry delete key feature.") | |
465 (defvar c++-auto-newline nil | |
466 "Internal state of auto newline feature.") | |
467 | |
468 (make-variable-buffer-local 'c++-auto-newline) | |
469 (make-variable-buffer-local 'c++-hungry-delete-key) | |
470 | |
471 (defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:" | |
472 "Regexp which describes access specification keywords.") | |
473 (defconst c++-class-key | |
474 (concat | |
475 "\\(\\(extern\\|typedef\\)\\s +\\)?" | |
476 "\\(template\\s *<[^>]*>\\s *\\)?" | |
477 "\\<\\(class\\|struct\\|union\\)\\>") | |
478 "Regexp which describes a class declaration, including templates.") | |
479 (defconst c++-inher-key | |
480 (concat "\\(\\<static\\>\\s +\\)?" | |
481 c++-class-key | |
482 "[ \t]+\\(\\(\\w\\|_\\)+[ \t]*:[ \t]*\\)?") | |
483 "Regexp which describes a class inheritance declaration.") | |
484 | |
485 | |
486 ;; ====================================================================== | |
487 ;; c++-mode main entry point | |
488 ;; ====================================================================== | |
489 ;;##autoload ;; don't autoload an obsolete package | |
490 (defun c++-mode () | |
491 "Major mode for editing C++ code. 2.353 | |
492 To submit a problem report, enter `\\[c++-submit-bug-report]' from a | |
493 c++-mode buffer. This automatically sets up a mail buffer with | |
494 version information already added. You just need to add a description | |
495 of the problem and send the message. | |
496 | |
497 1. Very much like editing C code, | |
498 2. Expression and list commands understand all C++ brackets, | |
499 3. Tab at left margin indents for C++ code, | |
500 4. Both C++ and C style block comments are recognized, | |
501 5. Paragraphs are separated by blank lines only, | |
502 6. Hungry delete key and auto newline features are optional. | |
503 | |
504 IMPORTANT NOTE: You may notice that some characters (by default, only | |
505 single quote) will get escaped with a backslash when typed in a | |
506 comment region. This is a necessary workaround of a bug present in | |
507 GNU Emacs 18 and derivatives. Enter `\\[describe-variable] c++-untame-characters RET' | |
508 for more information. If you are running a patched Emacs, no | |
509 characters will be escaped in comment regions, and many functions will | |
510 run much faster. | |
511 | |
512 Key bindings: | |
513 \\{c++-mode-map} | |
514 | |
515 These variables control indentation style. Those with names like | |
516 c-<thing> are inherited from c-mode. Those with names like | |
517 c++-<thing> are unique for this mode, or have extended functionality | |
518 from their c-mode cousins. | |
519 | |
520 c-argdecl-indent | |
521 Indentation level of declarations of C function arguments. | |
522 c-brace-imaginary-offset | |
523 An open brace following other text is treated as if it were | |
524 this far to the right of the start of its line. | |
525 c-brace-offset | |
526 Extra indentation for line if it starts with an open brace. | |
527 c-continued-brace-offset | |
528 Extra indentation given to a brace that starts a substatement. | |
529 This is in addition to `c-continued-statement-offset'. | |
530 c-continued-statement-offset | |
531 Extra indentation given to a substatement, such as the | |
532 then-clause of an if or body of a while. | |
533 c-indent-level | |
534 Indentation of C statements within surrounding block. | |
535 The surrounding block's indentation is the indentation | |
536 of the line on which the open-brace appears. | |
537 c-label-offset | |
538 Extra indentation for line that is a label, or case or ``default:'' | |
539 | |
540 c++-C-block-comments-indent-p | |
541 Style of C block comments to support. | |
542 c++-access-specifier-offset | |
543 Extra indentation given to public, protected, and private keyword lines. | |
544 c++-always-arglist-indent-p | |
545 Control indentation of continued arglists. When non-nil, arglists | |
546 continued on subsequent lines will always indent | |
547 `c++-empty-arglist-indent' spaces, otherwise, they will indent to | |
548 just under previous line's argument indentation. | |
549 c++-auto-hungry-initial-state | |
550 Initial state of auto/hungry feature when a C++ buffer is first visited. | |
551 c++-auto-hungry-toggle | |
552 Enable/disable toggling of auto/hungry features. | |
553 c++-backscan-limit | |
554 Limit in characters for looking back while skipping syntactic | |
555 whitespace. This variable is only used in an un-patched Emacs to | |
556 help improve performance at the expense of some accuracy. Patched | |
557 Emacses are both fast and accurate. | |
558 c++-block-close-brace-offset | |
559 Extra indentation give to braces which close a block. | |
560 c++-cleanup-list | |
561 A list of construct ``clean ups'' which c++-mode will perform when | |
562 auto-newline feature is on. Current legal values are: | |
563 `brace-else-brace', `empty-defun-braces', `defun-close-semi'. | |
564 c++-comment-only-line-offset | |
565 Extra indentation for a line containing only a C or C++ style | |
566 comment. Can be an integer or list, specifying the various styles | |
567 of comment-only line special indentations. | |
568 c++-continued-member-init-offset | |
569 Extra indentation for continuation lines of member initializations; nil | |
570 means to align with previous initializations rather than with the colon. | |
571 c++-default-macroize-column | |
572 Column to insert backslashes when macroizing a region. | |
573 c++-delete-function | |
574 Function called by `c++-electric-delete' when deleting a single char. | |
575 c++-electric-pound-behavior | |
576 List of behaviors for electric pound insertion. | |
577 c++-empty-arglist-indent | |
578 Extra indentation to apply to a line following an empty argument | |
579 list. nil means to line it up with the left paren. | |
580 c++-friend-offset | |
581 Offset of C++ friend class declarations relative to member declarations. | |
582 c++-hanging-braces | |
583 Controls open brace hanging behavior when using auto-newline feature. | |
584 nil says no braces hang, t says all open braces hang. non-nil-or-t | |
585 means top-level open braces don't hang, all others do. | |
586 c++-hanging-member-init-colon | |
587 Defines how colons which introduce member initialization lists are | |
588 formatted. t means no newlines are inserted either before or after | |
589 the colon. nil means newlines are inserted both before and after | |
590 the colon. `before' inserts newlines only before the colon, and | |
591 `after' inserts newlines only after colon. | |
592 c++-member-init-indent | |
593 Indentation level of member initializations in function declarations, | |
594 if they are on a separate line beginning with a colon. | |
595 c++-paren-as-block-close-p | |
596 If non-nil, treat a parenthesis which is the first non-whitespace | |
597 on a line as a paren which closes a block (i.e. treat it similar | |
598 to right curly brace). | |
599 c++-relative-offset-p | |
600 Control the calculation for indentation. When non-nil (the | |
601 default), indentation is calculated relative to the first | |
602 statement in the block. When nil, the indentation is calculated | |
603 without regard to how the first statement is indented. Useful when | |
604 using a `c++-special-indent-hook'. | |
605 c++-special-indent-hook | |
606 Hook for user defined special indentation adjustments. You can use | |
607 this hook, which gets called after a line is indented by the mode, | |
608 to customize indentations of the line. | |
609 c++-tab-always-indent | |
610 Controls the operation of the TAB key. t means always just indent | |
611 the current line. nil means indent the current line only if point | |
612 is at the left margin or in the line's indentation; otherwise | |
613 insert a tab. If not-nil-or-t, then tab is inserted only within | |
614 literals (comments and strings) and inside preprocessor | |
615 directives, but the line is always reindented. Default is value | |
616 for `c-tab-always-indent'. | |
617 c++-untame-characters | |
618 When non-nil, inserts backslash escapes before certain untamed | |
619 characters in comment regions. It is recommended that you keep the | |
620 default setting to workaround a nasty Emacs bug, unless you are | |
621 running a patched Emacs. | |
622 | |
623 Auto-newlining is no longer an all or nothing proposition. In my | |
624 opinion, I don't believe it is possible to implement a perfect | |
625 auto-newline algorithm. Sometimes you want it and sometimes you don't. | |
626 So now auto-newline (and its companion feature, hungry-delete-key) can | |
627 be toggled on and off on the fly. Hungry-delete-key is the optional | |
628 behavior of the delete key so that, when enabled, hitting the delete | |
629 key once consumes all preceding whitespace, unless point is within a | |
630 literal (defined as a C or C++ comment, or string). Inside literals, | |
631 and with hungry-delete-key disabled, the delete key just calls the | |
632 function in variable `c++-delete-function'. | |
633 | |
634 Selection and toggling of these features is controlled by the | |
635 variables `c++-auto-hungry-initial-state' and `c++-auto-hungry-toggle'. | |
636 Legal values for both variables are: | |
637 | |
638 `none' (or nil) -- no auto-newline or hungry-delete-key. | |
639 `auto-only' -- function affects only auto-newline feature. | |
640 `hungry-only' -- function affects only hungry-delete-key feature. | |
641 `auto-hungry' (or t) -- function affects both features. | |
642 | |
643 Thus if `c++-auto-hungry-initial-state' is `hungry-only', then only | |
644 hungry-delete-key feature is turned on when the buffer is first | |
645 visited. If `c++-auto-hungry-toggle' is `auto-hungry', and both | |
646 auto-newline and hungry-delete-key features are on, then hitting | |
647 `\\[c++-toggle-auto-hungry-state]' will toggle both features. Hitting | |
648 `\\[c++-toggle-hungry-state]' will always toggle hungry-delete-key | |
649 feature and hitting `\\[c++-toggle-auto-state]' will always toggle | |
650 auto-newline feature, regardless of the value of | |
651 `c++-auto-hungry-toggle'. | |
652 | |
653 Settings for K&R, BSD, and Stroustrup indentation styles are | |
654 c-indent-level 5 8 4 | |
655 c-continued-statement-offset 5 8 4 | |
656 c-continued-brace-offset 0 | |
657 c-brace-offset -5 -8 0 | |
658 c-brace-imaginary-offset 0 | |
659 c-argdecl-indent 0 8 4 | |
660 c-label-offset -5 -8 -4 | |
661 c++-access-specifier-offset -5 -8 -4 | |
662 c++-empty-arglist-indent 4 | |
663 c++-friend-offset 0 | |
664 | |
665 Turning on C++ mode calls the value of the variable `c++-mode-hook' with | |
666 no args, if that value is non-nil." | |
667 (interactive) | |
668 (kill-all-local-variables) | |
669 (use-local-map c++-mode-map) | |
670 (set-syntax-table c++-mode-syntax-table) | |
671 (setq major-mode 'c++-mode | |
672 mode-name "C++" | |
673 local-abbrev-table c++-mode-abbrev-table) | |
674 (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter)) | |
675 (set (make-local-variable 'paragraph-separate) paragraph-start) | |
676 (set (make-local-variable 'paragraph-ignore-fill-prefix) t) | |
677 (set (make-local-variable 'require-final-newline) t) | |
678 (set (make-local-variable 'parse-sexp-ignore-comments) nil) | |
679 ;; | |
680 (set (make-local-variable 'indent-line-function) 'c++-indent-line) | |
681 (set (make-local-variable 'comment-start) "// ") | |
682 (set (make-local-variable 'comment-end) "") | |
683 (set (make-local-variable 'comment-column) 32) | |
684 (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *") | |
685 (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent) | |
686 ;; hack auto-hungry designators into modeline-format | |
687 (if (listp modeline-format) | |
688 (setq modeline-format | |
689 (let ((modeline nil)) | |
690 (mapcar | |
691 (function | |
692 (lambda (element) | |
693 (setq modeline | |
694 (append modeline | |
695 (if (eq element 'mode-name) | |
696 '(mode-name (c++-hungry-delete-key | |
697 (c++-auto-newline "/ah" "/h") | |
698 (c++-auto-newline "/a"))) | |
699 (list element)))))) | |
700 modeline-format) | |
701 modeline))) | |
702 (run-hooks 'c++-mode-hook) | |
703 (c++-set-auto-hungry-state | |
704 (memq c++-auto-hungry-initial-state '(auto-only auto-hungry t)) | |
705 (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t)))) | |
706 | |
707 ;;##autoload ;; don't autoload an obsolete package | |
708 (defun c++-c-mode () | |
709 "Major mode for editing K&R and ANSI C code. 2.353 | |
710 This mode is based on c++-mode. Documentation for this mode is | |
711 available by doing a `\\[describe-function] c++-mode'." | |
712 (interactive) | |
713 (c++-mode) | |
714 (setq major-mode 'c++-c-mode | |
715 mode-name "C" | |
716 local-abbrev-table c-mode-abbrev-table) | |
717 (setq comment-start "/* " | |
718 comment-end " */") | |
719 ;; some syntax differences are necessary for C vs. C++ | |
720 (set-syntax-table c++-c-mode-syntax-table) | |
721 (run-hooks 'c++-c-mode-hook)) | |
722 | |
723 (defun c++-comment-indent () | |
724 "Used by `indent-for-comment' to decide how much to indent a comment | |
725 in C++ code based on its context." | |
726 (if (looking-at "^\\(/\\*\\|//\\)") | |
727 0 ; Existing comment at bol stays there. | |
728 (save-excursion | |
729 (skip-chars-backward " \t") | |
730 (max | |
731 ;; leave at least one space on non-empty lines. | |
732 (if (zerop (current-column)) | |
733 0 | |
734 (1+ (current-column))) | |
735 ;; use comment-column if previous line is comment only line | |
736 ;; indented to the left of comment-column | |
737 (save-excursion | |
738 (beginning-of-line) | |
739 (if (not (bobp)) (forward-line -1)) | |
740 (skip-chars-forward " \t") | |
741 (if (looking-at "/\\*\\|//") | |
742 (if (< (current-column) comment-column) | |
743 comment-column | |
744 (current-column)) | |
745 0)) | |
746 (let ((cur-pt (point))) | |
747 (beginning-of-line 0) | |
748 ;; If previous line had a comment, use it's indent | |
749 (if (re-search-forward comment-start-skip cur-pt t) | |
750 (progn | |
751 (goto-char (match-beginning 0)) | |
752 (current-column)) | |
753 comment-column)))))) ; otherwise indent at comment column. | |
754 | |
755 | |
756 ;; ====================================================================== | |
757 ;; most command level (interactive) and related | |
758 ;; ====================================================================== | |
759 (defun c++-set-auto-hungry-state (auto-p hungry-p) | |
760 "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P. | |
761 Update modeline to indicate state to user." | |
762 (setq c++-auto-newline auto-p | |
763 c++-hungry-delete-key hungry-p) | |
764 (set-buffer-modified-p (buffer-modified-p))) | |
765 | |
766 (defun c++-toggle-auto-state (arg) | |
767 "Toggle auto-newline feature. | |
768 This function ignores `c++-auto-hungry-toggle' variable. Optional | |
769 numeric ARG, if supplied turns on auto-newline when positive, turns | |
770 off auto-newline when negative and toggles when zero." | |
771 (interactive "P") | |
772 (let ((auto (cond | |
773 ((not arg) | |
774 (not c++-auto-newline)) | |
775 ((zerop (setq arg (prefix-numeric-value arg))) | |
776 (not c++-auto-newline)) | |
777 ((< arg 0) nil) | |
778 (t t)))) | |
779 (c++-set-auto-hungry-state auto c++-hungry-delete-key))) | |
780 | |
781 (defun c++-toggle-hungry-state (arg) | |
782 "Toggle hungry-delete-key feature. | |
783 This function ignores `c++-auto-hungry-toggle' variable. Optional | |
784 numeric ARG, if supplied turns on hungry-delete-key when positive, | |
785 turns off hungry-delete-key when negative and toggles when zero." | |
786 (interactive "P") | |
787 (let ((hungry (cond | |
788 ((not arg) | |
789 (not c++-hungry-delete-key)) | |
790 ((zerop (setq arg (prefix-numeric-value arg))) | |
791 (not c++-hungry-delete-key)) | |
792 ((< arg 0) nil) | |
793 (t t)))) | |
794 (c++-set-auto-hungry-state c++-auto-newline hungry))) | |
795 | |
796 (defun c++-toggle-auto-hungry-state (arg) | |
797 "Toggle auto-newline and hungry-delete-key features. | |
798 Actual toggling of these features is controlled by | |
799 `c++-auto-hungry-toggle' variable. | |
800 | |
801 Optional argument has the following meanings when supplied: | |
802 Universal argument \\[universal-argument] | |
803 resets features to c++-auto-hungry-initial-state. | |
804 negative number | |
805 turn off both auto-newline and hungry-delete-key features. | |
806 positive number | |
807 turn on both auto-newline and hungry-delete-key features. | |
808 zero | |
809 toggle both features regardless of `c++-auto-hungry-toggle-p'." | |
810 (interactive "P") | |
811 (let* ((numarg (prefix-numeric-value arg)) | |
812 (apl (list 'auto-only 'auto-hungry t)) | |
813 (hpl (list 'hungry-only 'auto-hungry t)) | |
814 (auto (cond | |
815 ((not arg) | |
816 (if (memq c++-auto-hungry-toggle apl) | |
817 (not c++-auto-newline) | |
818 c++-auto-newline)) | |
819 ((listp arg) | |
820 (memq c++-auto-hungry-initial-state apl)) | |
821 ((zerop numarg) | |
822 (not c++-auto-newline)) | |
823 ((< arg 0) nil) | |
824 (t t))) | |
825 (hungry (cond | |
826 ((not arg) | |
827 (if (memq c++-auto-hungry-toggle hpl) | |
828 (not c++-hungry-delete-key) | |
829 c++-hungry-delete-key)) | |
830 ((listp arg) | |
831 (memq c++-auto-hungry-initial-state hpl)) | |
832 ((zerop numarg) | |
833 (not c++-hungry-delete-key)) | |
834 ((< arg 0) nil) | |
835 (t t)))) | |
836 (c++-set-auto-hungry-state auto hungry))) | |
837 | |
838 (defun c++-tame-insert (arg) | |
839 "Safely inserts certain troublesome characters in comment regions. | |
840 Because of syntax bugs in Emacs, characters with string or parenthesis | |
841 syntax must be escaped with a backslash or lots of things get messed | |
842 up. Unfortunately, setting `parse-sexp-ignore-comments' to non-nil does | |
843 not fix the problem, but this function is unnecessary if you are | |
844 running a patched Emacs. | |
845 | |
846 See also the variable `c++-untame-characters'." | |
847 (interactive "p") | |
848 (if (and (memq last-command-char c++-untame-characters) | |
849 (memq (c++-in-literal) '(c c++))) | |
850 (insert "\\")) | |
851 (self-insert-command arg)) | |
852 | |
853 (defun c++-electric-delete (arg) | |
854 "If `c++-hungry-delete-key' is non-nil, consumes all preceding | |
855 whitespace unless ARG is supplied, or point is inside a C or C++ style | |
856 comment or string. If ARG is supplied, this just calls | |
857 `backward-delete-char-untabify' passing along ARG. | |
858 | |
859 If `c++-hungry-delete-key' is nil, just call `backward-delete-char-untabify'." | |
860 (interactive "P") | |
861 (cond | |
862 ((or (not c++-hungry-delete-key) arg) | |
863 (funcall c++-delete-function (prefix-numeric-value arg))) | |
864 ((let ((bod (c++-point 'bod))) | |
865 (not (or (memq (c++-in-literal bod) '(c c++ string)) | |
866 (save-excursion | |
867 (skip-chars-backward " \t") | |
868 (= (preceding-char) ?#))))) | |
869 (let ((here (point))) | |
870 (skip-chars-backward " \t\n") | |
871 (if (/= (point) here) | |
872 (delete-region (point) here) | |
873 (funcall c++-delete-function 1)))) | |
874 (t (funcall c++-delete-function 1)))) | |
875 | |
876 (defun c++-electric-pound (arg) | |
877 "Electric pound command." | |
878 (interactive "p") | |
879 (if (memq (c++-in-literal) '(c c++ string)) | |
880 (self-insert-command arg) | |
881 (let ((here (point-marker)) | |
882 (bobp (bobp)) | |
883 (bolp (bolp))) | |
884 (if (memq 'alignleft c++-electric-pound-behavior) | |
885 (progn (beginning-of-line) | |
886 (delete-horizontal-space))) | |
887 (if bobp | |
888 (insert (make-string arg last-command-char)) | |
889 (insert-before-markers (make-string arg last-command-char))) | |
890 (if (not bolp) | |
891 (goto-char here)) | |
892 (set-marker here nil)))) | |
893 | |
894 (defun c++-electric-brace (arg) | |
895 "Insert character and correct line's indentation." | |
896 (interactive "P") | |
897 (let (insertpos | |
898 (last-command-char last-command-char) | |
899 (bod (c++-point 'bod))) | |
900 (if (and (not arg) | |
901 (save-excursion | |
902 (skip-chars-forward " \t") | |
903 (eolp)) | |
904 (or (save-excursion | |
905 (skip-chars-backward " \t") | |
906 (bolp)) | |
907 (let ((c++-auto-newline c++-auto-newline) | |
908 (open-brace-p (= last-command-char ?{))) | |
909 (if (and open-brace-p | |
910 (or (eq c++-hanging-braces t) | |
911 (and c++-hanging-braces | |
912 (not (c++-at-top-level-p t bod))))) | |
913 (setq c++-auto-newline nil)) | |
914 (if (c++-auto-newline) | |
915 ;; this may have auto-filled so we need to | |
916 ;; indent the previous line. we also need to | |
917 ;; indent the currently line, or | |
918 ;; c++-beginning-of-defun will not be able to | |
919 ;; correctly find the bod when | |
920 ;; c++-match-headers-strongly is nil. | |
921 (progn (c++-indent-line) | |
922 (save-excursion | |
923 (forward-line -1) | |
924 (c++-indent-line)))) | |
925 t))) | |
926 (progn | |
927 (if (and (memq last-command-char c++-untame-characters) | |
928 (memq (c++-in-literal bod) '(c c++))) | |
929 (insert "\\")) | |
930 ;; we need to work around a bogus feature of Emacs where an | |
931 ;; open brace at bolp means a beginning-of-defun. but it | |
932 ;; really might not. | |
933 (and (= last-command-char ?{) | |
934 (bolp) | |
935 (c++-indent-line)) | |
936 (insert last-command-char) | |
937 ;; try to clean up empty defun braces if conditions apply | |
938 (let ((here (point-marker))) | |
939 (and (memq 'empty-defun-braces c++-cleanup-list) | |
940 (c++-at-top-level-p t bod) | |
941 c++-auto-newline | |
942 (= last-command-char ?\}) | |
943 (progn (forward-char -1) | |
944 (skip-chars-backward " \t\n") | |
945 (= (preceding-char) ?\{)) | |
946 (not (memq (c++-in-literal) '(c c++ string))) | |
947 (delete-region (point) (1- here))) | |
948 (goto-char here) | |
949 (set-marker here nil)) | |
950 (let ((here (point-marker)) | |
951 mbeg mend) | |
952 (if (and (memq 'brace-else-brace c++-cleanup-list) | |
953 (= last-command-char ?\{) | |
954 (let ((status | |
955 (re-search-backward "}[ \t\n]*else[ \t\n]*{" | |
956 nil t))) | |
957 (setq mbeg (match-beginning 0) | |
958 mend (match-end 0)) | |
959 status) | |
960 (= mend here) | |
961 (not (memq (c++-in-literal bod) '(c c++ string)))) | |
962 (progn | |
963 ;; we should clean up brace-else-brace syntax | |
964 (delete-region mbeg mend) | |
965 (insert-before-markers "} else {") | |
966 (goto-char here) | |
967 (set-marker here nil)) | |
968 (goto-char here) | |
969 (set-marker here nil))) | |
970 (c++-indent-line) | |
971 (if (c++-auto-newline) | |
972 (progn | |
973 ;; c++-auto-newline may have done an auto-fill | |
974 (save-excursion | |
975 (let ((here (point-marker))) | |
976 (goto-char (- (point) 2)) | |
977 (c++-indent-line) | |
978 (setq insertpos (- (goto-char here) 2)) | |
979 (set-marker here nil))) | |
980 (c++-indent-line))) | |
981 (save-excursion | |
982 (if insertpos (goto-char (1+ insertpos))) | |
983 (delete-char -1)))) | |
984 (if insertpos | |
985 (save-excursion | |
986 (goto-char insertpos) | |
987 (self-insert-command (prefix-numeric-value arg))) | |
988 (self-insert-command (prefix-numeric-value arg))))) | |
989 | |
990 (defun c++-electric-slash (arg) | |
991 "Insert slash, and if slash is second of a double-slash comment | |
992 introducing construct, indent line as comment. This only indents if | |
993 we're on a comment-only line, otherwise use `indent-for-comment' (\\[indent-for-comment])." | |
994 (interactive "P") | |
995 (let ((here (point)) char) | |
996 (self-insert-command (prefix-numeric-value arg)) | |
997 (and (setq char (char-after (1- here))) | |
998 (= char ?/) | |
999 (save-excursion | |
1000 (goto-char here) | |
1001 (c++-indent-line))))) | |
1002 | |
1003 (defun c++-electric-star (arg) | |
1004 "Works with `c++-electric-slash' to auto indent C style comment lines." | |
1005 (interactive "P") | |
1006 (let ((here (point)) char) | |
1007 (self-insert-command (prefix-numeric-value arg)) | |
1008 (if (and (setq char (char-after (1- here))) | |
1009 (memq (c++-in-literal) '(c)) | |
1010 (memq char '(?/ ?* ?\t 32 ?\n)) | |
1011 (save-excursion | |
1012 (skip-chars-backward "* \t") | |
1013 (if (= (preceding-char) ?/) | |
1014 (progn | |
1015 (forward-char -1) | |
1016 (skip-chars-backward " \t"))) | |
1017 (bolp))) | |
1018 (save-excursion | |
1019 (goto-char here) | |
1020 (c++-indent-line))))) | |
1021 | |
1022 (defun c++-electric-semi (arg) | |
1023 "Insert character and correct line's indentation." | |
1024 (interactive "P") | |
1025 (if (c++-in-literal) | |
1026 (self-insert-command (prefix-numeric-value arg)) | |
1027 (let ((here (point-marker))) | |
1028 (if (and (memq 'defun-close-semi c++-cleanup-list) | |
1029 c++-auto-newline | |
1030 (progn | |
1031 (skip-chars-backward " \t\n") | |
1032 (= (preceding-char) ?}))) | |
1033 (delete-region here (point))) | |
1034 (goto-char here) | |
1035 (set-marker here nil)) | |
1036 (c++-electric-terminator arg))) | |
1037 | |
1038 (defun c++-electric-colon (arg) | |
1039 "Electrify colon. | |
1040 De-auto-newline double colons. No auto-new-lines for member | |
1041 initialization list." | |
1042 (interactive "P") | |
1043 (if (c++-in-literal) | |
1044 (self-insert-command (prefix-numeric-value arg)) | |
1045 (let ((c++-auto-newline c++-auto-newline) | |
1046 (insertion-point (point)) | |
1047 (bod (c++-point 'bod))) | |
1048 (save-excursion | |
1049 (cond | |
1050 ;; check for double-colon where the first colon is not in a | |
1051 ;; comment or literal region | |
1052 ((progn (skip-chars-backward " \t\n") | |
1053 (and (= (preceding-char) ?:) | |
1054 (not (memq (c++-in-literal bod) '(c c++ string))))) | |
1055 (progn (delete-region insertion-point (point)) | |
1056 (setq c++-auto-newline nil | |
1057 insertion-point (point)))) | |
1058 ;; check for ?: construct which may be at any level | |
1059 ((progn (goto-char insertion-point) | |
1060 (condition-case premature-end | |
1061 (backward-sexp 1) | |
1062 (error nil)) | |
1063 ;; is possible that the sexp we just skipped was a | |
1064 ;; negative number. in that case the minus won't be | |
1065 ;; gobbled | |
1066 (skip-chars-backward "-") | |
1067 (c++-backward-syntactic-ws bod) | |
1068 (= (preceding-char) ?\?)) | |
1069 (setq c++-auto-newline nil)) | |
1070 ;; check for being at top level or top with respect to the | |
1071 ;; class. if not, process as normal | |
1072 ((progn (goto-char insertion-point) | |
1073 (not (c++-at-top-level-p t bod)))) | |
1074 ;; if at top level, check to see if we are introducing a member | |
1075 ;; init list. if not, continue | |
1076 ((progn (c++-backward-syntactic-ws bod) | |
1077 (= (preceding-char) ?\))) | |
1078 (goto-char insertion-point) | |
1079 ;; at a member init list, figure out about auto newlining. if | |
1080 ;; nil or before then put a newline before the colon and | |
1081 ;; adjust the insertion point, but *only* if there is no | |
1082 ;; newline already before the insertion point | |
1083 (if (and (memq c++-hanging-member-init-colon '(nil before)) | |
1084 c++-auto-newline) | |
1085 (if (not (save-excursion (skip-chars-backward " \t") | |
1086 (bolp))) | |
1087 (let ((c++-auto-newline t)) | |
1088 (c++-auto-newline) | |
1089 (setq insertion-point (point))))) | |
1090 ;; if hanging colon is after or nil, then newline is inserted | |
1091 ;; after colon. set up variable so c++-electric-terminator | |
1092 ;; places the newline correctly | |
1093 (setq c++-auto-newline | |
1094 (and c++-auto-newline | |
1095 (memq c++-hanging-member-init-colon '(nil after))))) | |
1096 ;; last condition is always put newline after colon | |
1097 (t (setq c++-auto-newline nil)) | |
1098 )) ; end-cond, end-save-excursion | |
1099 (goto-char insertion-point) | |
1100 (c++-electric-terminator arg)))) | |
1101 | |
1102 (defun c++-electric-terminator (arg) | |
1103 "Insert character and correct line's indentation." | |
1104 (interactive "P") | |
1105 (let (insertpos (end (point))) | |
1106 (if (and (not arg) | |
1107 (save-excursion | |
1108 (skip-chars-forward " \t") | |
1109 (eolp)) | |
1110 (not (save-excursion | |
1111 (beginning-of-line) | |
1112 (skip-chars-forward " \t") | |
1113 (or (= (following-char) ?#) | |
1114 ;; Colon is special only after a label, or | |
1115 ;; case, or another colon. | |
1116 ;; So quickly rule out most other uses of colon | |
1117 ;; and do no indentation for them. | |
1118 (and (eq last-command-char ?:) | |
1119 (not (looking-at "case[ \t]")) | |
1120 (save-excursion | |
1121 (forward-word 1) | |
1122 (skip-chars-forward " \t") | |
1123 (< (point) end)) | |
1124 ;; Do re-indent double colons | |
1125 (save-excursion | |
1126 (end-of-line 1) | |
1127 (looking-at ":"))) | |
1128 (progn | |
1129 (c++-beginning-of-defun) | |
1130 (let* ((parse-sexp-ignore-comments t) | |
1131 (pps (parse-partial-sexp (point) end))) | |
1132 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) | |
1133 (progn | |
1134 (insert last-command-char) | |
1135 (c++-indent-line) | |
1136 (and c++-auto-newline | |
1137 (not (c++-in-parens-p)) | |
1138 (progn | |
1139 ;; the new marker object, used to be just an integer | |
1140 (setq insertpos (make-marker)) | |
1141 ;; changed setq to set-marker | |
1142 (set-marker insertpos (1- (point))) | |
1143 ;; do this before the newline, since in auto fill can break | |
1144 (newline) | |
1145 (c++-indent-line))) | |
1146 (save-excursion | |
1147 (if insertpos (goto-char (1+ insertpos))) | |
1148 (delete-char -1)))) | |
1149 (if insertpos | |
1150 (save-excursion | |
1151 (goto-char insertpos) | |
1152 (self-insert-command (prefix-numeric-value arg))) | |
1153 (self-insert-command (prefix-numeric-value arg))))) | |
1154 | |
1155 (defun c++-indent-command (&optional whole-exp) | |
1156 "Indent current line as C++ code, or in some cases insert a tab character. | |
1157 | |
1158 If `c++-tab-always-indent' is t, always just indent the current line. | |
1159 If nil, indent the current line only if point is at the left margin or | |
1160 in the line's indentation; otherwise insert a tab. If not-nil-or-t, | |
1161 then tab is inserted only within literals (comments and strings) and | |
1162 inside preprocessor directives, but line is always reindented. | |
1163 | |
1164 A numeric argument, regardless of its value, means indent rigidly all | |
1165 the lines of the expression starting after point so that this line | |
1166 becomes properly indented. The relative indentation among the lines | |
1167 of the expression are preserved." | |
1168 (interactive "P") | |
1169 (let ((bod (c++-point 'bod))) | |
1170 (if whole-exp | |
1171 ;; If arg, always indent this line as C | |
1172 ;; and shift remaining lines of expression the same amount. | |
1173 (let ((shift-amt (c++-indent-line bod)) | |
1174 beg end) | |
1175 (save-excursion | |
1176 (if (eq c++-tab-always-indent t) | |
1177 (beginning-of-line)) | |
1178 (setq beg (point)) | |
1179 (forward-sexp 1) | |
1180 (setq end (point)) | |
1181 (goto-char beg) | |
1182 (forward-line 1) | |
1183 (setq beg (point))) | |
1184 (if (> end beg) | |
1185 (indent-code-rigidly beg end shift-amt "#"))) | |
1186 (cond | |
1187 ;; CASE 1: indent when at column zero or in lines indentation, | |
1188 ;; otherwise insert a tab | |
1189 ((not c++-tab-always-indent) | |
1190 (if (and (save-excursion | |
1191 (skip-chars-backward " \t") | |
1192 (bolp)) | |
1193 (or (looking-at "[ \t]*$") | |
1194 (/= (point) (c++-point 'boi)) | |
1195 (bolp))) | |
1196 (c++-indent-line bod) | |
1197 (insert-tab))) | |
1198 ;; CASE 2: just indent the line | |
1199 ((eq c++-tab-always-indent t) | |
1200 (c++-indent-line bod)) | |
1201 ;; CASE 3: if in a literal, insert a tab, but always indent the line | |
1202 ((or (memq (c++-in-literal bod) '(c c++ string)) | |
1203 (save-excursion | |
1204 (skip-chars-backward " \t") | |
1205 (= (preceding-char) ?#))) | |
1206 (let ((here (point)) | |
1207 (boi (save-excursion (back-to-indentation) (point))) | |
1208 (indent-p nil)) | |
1209 (c++-indent-line bod) | |
1210 (save-excursion | |
1211 (back-to-indentation) | |
1212 (setq indent-p (and (> here boi) (= (point) boi)))) | |
1213 (if indent-p (insert-tab)))) | |
1214 ;; CASE 4: bogus, just indent the line | |
1215 (t (c++-indent-line bod)))))) | |
1216 | |
1217 (defun c++-indent-exp () | |
1218 "Indent each line of the C++ grouping following point." | |
1219 (interactive) | |
1220 (let ((indent-stack (list nil)) | |
1221 (contain-stack (list (point))) | |
1222 (case-fold-search nil) | |
1223 restart outer-loop-done inner-loop-done state ostate | |
1224 this-indent last-sexp last-depth | |
1225 at-else at-brace | |
1226 (parse-sexp-ignore-comments t) | |
1227 (opoint (point)) | |
1228 (next-depth 0)) | |
1229 (save-excursion | |
1230 (forward-sexp 1)) | |
1231 (save-excursion | |
1232 (setq outer-loop-done nil) | |
1233 (while (and (not (eobp)) (not outer-loop-done)) | |
1234 (setq last-depth next-depth) | |
1235 ;; Compute how depth changes over this line | |
1236 ;; plus enough other lines to get to one that | |
1237 ;; does not end inside a comment or string. | |
1238 ;; Meanwhile, do appropriate indentation on comment lines. | |
1239 (setq inner-loop-done nil) | |
1240 (while (and (not inner-loop-done) | |
1241 (not (and (eobp) (setq outer-loop-done t)))) | |
1242 (setq ostate state) | |
1243 ;; fix by reed@adapt.net.com | |
1244 ;; must pass in the return past the end of line, so that | |
1245 ;; parse-partial-sexp finds it, and recognizes that a "//" | |
1246 ;; comment is over. otherwise, state is set that we're in a | |
1247 ;; comment, and never gets unset, causing outer-loop to only | |
1248 ;; terminate in (eobp). old: | |
1249 ;;(setq state (parse-partial-sexp (point) | |
1250 ;;(progn (end-of-line) (point)) | |
1251 ;;nil nil state)) | |
1252 (let ((start (point)) | |
1253 (line-end | |
1254 (progn (end-of-line) | |
1255 (while (eq (c++-in-literal) 'c) | |
1256 (forward-line 1) | |
1257 (c++-indent-line) | |
1258 (end-of-line)) | |
1259 (skip-chars-backward " \t") | |
1260 (end-of-line) | |
1261 (point))) | |
1262 (end (progn (if (not (eobp)) (forward-char)) (point)))) | |
1263 (setq state (parse-partial-sexp start end nil nil state)) | |
1264 (goto-char line-end)) | |
1265 (setq next-depth (car state)) | |
1266 (if (and (car (cdr (cdr state))) | |
1267 (>= (car (cdr (cdr state))) 0)) | |
1268 (setq last-sexp (car (cdr (cdr state))))) | |
1269 (if (or (nth 4 ostate)) | |
1270 (c++-indent-line)) | |
1271 (if (or (nth 3 state)) | |
1272 (forward-line 1) | |
1273 (setq inner-loop-done t))) | |
1274 (if (<= next-depth 0) | |
1275 (setq outer-loop-done t)) | |
1276 (if outer-loop-done | |
1277 nil | |
1278 ;; If this line had ..))) (((.. in it, pop out of the levels | |
1279 ;; that ended anywhere in this line, even if the final depth | |
1280 ;; doesn't indicate that they ended. | |
1281 (while (> last-depth (nth 6 state)) | |
1282 (setq indent-stack (cdr indent-stack) | |
1283 contain-stack (cdr contain-stack) | |
1284 last-depth (1- last-depth))) | |
1285 (if (/= last-depth next-depth) | |
1286 (setq last-sexp nil)) | |
1287 ;; Add levels for any parens that were started in this line. | |
1288 (while (< last-depth next-depth) | |
1289 (setq indent-stack (cons nil indent-stack) | |
1290 contain-stack (cons nil contain-stack) | |
1291 last-depth (1+ last-depth))) | |
1292 (if (null (car contain-stack)) | |
1293 (setcar contain-stack (or (car (cdr state)) | |
1294 (save-excursion (forward-sexp -1) | |
1295 (point))))) | |
1296 (forward-line 1) | |
1297 (skip-chars-forward " \t") | |
1298 ;; check for C comment block | |
1299 (if (memq (c++-in-literal) '(c)) | |
1300 (let ((eoc (save-excursion | |
1301 (re-search-forward "\\*/" (point-max) 'move) | |
1302 (point)))) | |
1303 (while (< (point) eoc) | |
1304 (c++-indent-line) | |
1305 (forward-line 1)))) | |
1306 (if (eolp) | |
1307 nil | |
1308 (if (and (car indent-stack) | |
1309 (>= (car indent-stack) 0)) | |
1310 ;; Line is on an existing nesting level. | |
1311 ;; Lines inside parens are handled specially. | |
1312 (if (or (/= (char-after (car contain-stack)) ?{) | |
1313 ;;(c++-at-top-level-p t)) | |
1314 ;; baw hack for continued statement offsets | |
1315 ;; repercussions??? | |
1316 t) | |
1317 (setq this-indent (car indent-stack)) | |
1318 ;; Line is at statement level. | |
1319 ;; Is it a new statement? Is it an else? | |
1320 ;; Find last non-comment character before this line | |
1321 (save-excursion | |
1322 (setq at-else (looking-at "else\\W")) | |
1323 (setq at-brace (= (following-char) ?{)) | |
1324 (c++-backward-syntactic-ws opoint) | |
1325 (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) | |
1326 ;; Preceding line did not end in comma or semi; | |
1327 ;; indent this line c-continued-statement-offset | |
1328 ;; more than previous. | |
1329 (progn | |
1330 (c-backward-to-start-of-continued-exp | |
1331 (car contain-stack)) | |
1332 (setq this-indent | |
1333 (+ c-continued-statement-offset | |
1334 (current-column) | |
1335 (if at-brace c-continued-brace-offset 0)))) | |
1336 ;; Preceding line ended in comma or semi; | |
1337 ;; use the standard indent for this level. | |
1338 (if at-else | |
1339 (progn (c++-backward-to-start-of-if opoint) | |
1340 (back-to-indentation) | |
1341 (skip-chars-forward "{ \t") | |
1342 (setq this-indent (current-column))) | |
1343 (setq this-indent (car indent-stack)))))) | |
1344 ;; Just started a new nesting level. | |
1345 ;; Compute the standard indent for this level. | |
1346 (let ((val (c++-calculate-indent | |
1347 (if (car indent-stack) | |
1348 (- (car indent-stack)))))) | |
1349 (setcar indent-stack | |
1350 (setq this-indent val)))) | |
1351 ;; Adjust line indentation according to its contents | |
1352 (cond | |
1353 ;; looking at public, protected, private line | |
1354 ((looking-at c++-access-key) | |
1355 (setq this-indent (+ this-indent c++-access-specifier-offset))) | |
1356 ;; looking at a case, default, or other label | |
1357 ((or (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):") | |
1358 (and (looking-at "[A-Za-z]") | |
1359 (save-excursion | |
1360 (forward-sexp 1) | |
1361 (looking-at ":[^:]")))) | |
1362 (setq this-indent (max 0 (+ this-indent c-label-offset)))) | |
1363 ;; looking at a comment only line? | |
1364 ((looking-at comment-start-skip) | |
1365 ;; different indentation base on whether this is a col0 | |
1366 ;; comment only line or not. also, if comment is in, or | |
1367 ;; to the right of comment-column, the comment doesn't | |
1368 ;; move | |
1369 (progn | |
1370 (skip-chars-forward " \t") | |
1371 (setq this-indent | |
1372 (if (>= (current-column) comment-column) | |
1373 (current-column) | |
1374 (c++-comment-offset | |
1375 (bolp) | |
1376 (+ this-indent | |
1377 (if (save-excursion | |
1378 (c++-backward-syntactic-ws | |
1379 (car contain-stack)) | |
1380 (memq (preceding-char) | |
1381 '(nil ?\, ?\; ?} ?: ?{))) | |
1382 0 c-continued-statement-offset)) | |
1383 ))))) | |
1384 ;; looking at a friend declaration | |
1385 ((looking-at "friend[ \t]") | |
1386 (setq this-indent (+ this-indent c++-friend-offset))) | |
1387 ;; looking at a close brace | |
1388 ((= (following-char) ?}) | |
1389 (setq this-indent (- this-indent c-indent-level))) | |
1390 ;; looking at an open brace | |
1391 ((= (following-char) ?{) | |
1392 (setq this-indent | |
1393 (+ this-indent c-brace-offset | |
1394 (if (c++-at-top-level-p t (car contain-stack)) | |
1395 0 c-indent-level)))) | |
1396 ;; check for continued statements | |
1397 ((save-excursion | |
1398 (c++-backward-syntactic-ws (car contain-stack)) | |
1399 (and (not (c++-in-parens-p)) | |
1400 (not (memq (preceding-char) '(nil ?\000 ?\; ?\} ?\: ?\{))) | |
1401 (progn | |
1402 (beginning-of-line) | |
1403 (skip-chars-forward " \t") | |
1404 (not (looking-at c++-class-key))))) | |
1405 (setq this-indent | |
1406 (+ this-indent | |
1407 c-continued-statement-offset | |
1408 ;; are we in a member init list? | |
1409 (if (not (looking-at "[ \t]*:")) | |
1410 (save-excursion | |
1411 (let ((lim (car contain-stack))) | |
1412 (c++-backward-syntactic-ws lim) | |
1413 (while (and (< lim (point)) | |
1414 (= (preceding-char) ?,)) | |
1415 (beginning-of-line) | |
1416 (c++-backward-syntactic-ws)) | |
1417 (forward-line 1) | |
1418 (beginning-of-line) | |
1419 (if (looking-at "[ \t]*:") | |
1420 (- (save-excursion | |
1421 (skip-chars-forward " \t") | |
1422 (point)) | |
1423 (point)) | |
1424 0))) | |
1425 0) | |
1426 ))) | |
1427 ;; check for stream operator | |
1428 ((looking-at "\\(<<\\|>>\\)") | |
1429 (setq this-indent (c++-calculate-indent))) | |
1430 ) ;; end-cond | |
1431 ;; Put chosen indentation into effect. | |
1432 (or (= (current-column) this-indent) | |
1433 (= (following-char) ?\#) | |
1434 (progn | |
1435 (delete-region (point) (progn (beginning-of-line) (point))) | |
1436 (indent-to this-indent))) | |
1437 ;; Indent any comment following the text. | |
1438 (or (looking-at comment-start-skip) | |
1439 (if (re-search-forward | |
1440 comment-start-skip | |
1441 (c++-point 'eol) t) | |
1442 (progn (indent-for-comment) | |
1443 (beginning-of-line)))) | |
1444 )))))) | |
1445 | |
1446 (defun c++-insert-header () | |
1447 "Insert header denoting C++ code at top of buffer." | |
1448 (interactive) | |
1449 (save-excursion | |
1450 (goto-char (point-min)) | |
1451 (insert "// " | |
1452 "This may look like C code, but it is really " | |
1453 "-*- C++ -*-" | |
1454 "\n\n"))) | |
1455 | |
1456 (defun c++-tame-comments () | |
1457 "Backslashifies all untamed in comment regions found in the buffer. | |
1458 This is a workaround for Emacs syntax bugs. This function is | |
1459 unnecessary (and un-used automatically) if you are running a patched | |
1460 Emacs. Untamed characters to escape are defined in the variable | |
1461 `c++-untame-characters'." | |
1462 (interactive) | |
1463 ;; make the list into a valid charset, escaping where necessary | |
1464 (let ((charset (concat "^" (mapconcat | |
1465 (function | |
1466 (lambda (char) | |
1467 (if (memq char '(?\\ ?^ ?-)) | |
1468 (concat "\\" (char-to-string char)) | |
1469 (char-to-string char)))) | |
1470 c++-untame-characters "")))) | |
1471 (save-excursion | |
1472 (beginning-of-buffer) | |
1473 (while (not (eobp)) | |
1474 (skip-chars-forward charset) | |
1475 (if (and (not (zerop (following-char))) | |
1476 (memq (c++-in-literal) '(c c++)) | |
1477 (/= (preceding-char) ?\\ )) | |
1478 (insert "\\")) | |
1479 (if (not (eobp)) | |
1480 (forward-char 1)))))) | |
1481 | |
1482 ;; taken from match-paren.el. Author: unknown | |
1483 (defun c++-match-paren () | |
1484 "Jumps to the paren matching the one under point, if there is one." | |
1485 (interactive) | |
1486 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) | |
1487 (cond | |
1488 ((looking-at "[\(\[{]") | |
1489 (forward-sexp 1) | |
1490 (backward-char)) | |
1491 ((looking-at "[])}]") | |
1492 (forward-char) | |
1493 (backward-sexp 1)) | |
1494 (t (message "Could not find matching paren."))))) | |
1495 | |
1496 (defun c++-forward-sexp (&optional arg) | |
1497 "Safe forward-sexp call." | |
1498 (interactive "_p") | |
1499 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) | |
1500 (forward-sexp arg))) | |
1501 | |
1502 (defun c++-backward-sexp (&optional arg) | |
1503 "Safe backward-sexp call." | |
1504 (interactive "_p") | |
1505 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features))) | |
1506 (backward-sexp arg))) | |
1507 | |
1508 | |
1509 ;; ====================================================================== | |
1510 ;; compatibility between emacsen | |
1511 ;; ====================================================================== | |
1512 | |
1513 ;; This is the best we can do in vanilla GNU 18 emacsen. Note that the | |
1514 ;; following problems exist: | |
1515 ;; 1. We only look back to LIM, and that could place us inside a | |
1516 ;; literal if we are scanning backwards over lots of comments | |
1517 ;; 2. This can potentially get slower the larger LIM is | |
1518 ;; If anybody has a better solution, I'll all ears | |
1519 (defun c++-backward-syntactic-ws-v18 (&optional lim) | |
1520 "Skip backwards over syntactic whitespace. | |
1521 Syntactic whitespace is defined as lexical whitespace, C and C++ style | |
1522 comments, and preprocessor directives. Search no farther back than | |
1523 optional LIM. If LIM is omitted, `beginning-of-defun' is used." | |
1524 (let ((lim (or lim (c++-point 'bod))) | |
1525 literal stop) | |
1526 (if (and c++-backscan-limit | |
1527 (> (- (point) lim) c++-backscan-limit)) | |
1528 (setq lim (- (point) c++-backscan-limit))) | |
1529 (while (not stop) | |
1530 (skip-chars-backward " \t\n\r\f" lim) | |
1531 ;; c++ comment | |
1532 (if (eq (setq literal (c++-in-literal lim)) 'c++) | |
1533 (progn | |
1534 (skip-chars-backward "^/" lim) | |
1535 (skip-chars-backward "/" lim) | |
1536 (while (not (or (and (= (following-char) ?/) | |
1537 (= (char-after (1+ (point))) ?/)) | |
1538 (<= (point) lim))) | |
1539 (skip-chars-backward "^/" lim) | |
1540 (skip-chars-backward "/" lim))) | |
1541 ;; c comment | |
1542 (if (eq literal 'c) | |
1543 (progn | |
1544 (skip-chars-backward "^*" lim) | |
1545 (skip-chars-backward "*" lim) | |
1546 (while (not (or (and (= (following-char) ?*) | |
1547 (= (preceding-char) ?/)) | |
1548 (<= (point) lim))) | |
1549 (skip-chars-backward "^*" lim) | |
1550 (skip-chars-backward "*" lim)) | |
1551 (or (bobp) (forward-char -1))) | |
1552 ;; preprocessor directive | |
1553 (if (eq literal 'pound) | |
1554 (progn | |
1555 (beginning-of-line) | |
1556 (setq stop (<= (point) lim))) | |
1557 ;; just outside of c block | |
1558 (if (and (= (preceding-char) ?/) | |
1559 (= (char-after (- (point) 2)) ?*)) | |
1560 (progn | |
1561 (skip-chars-backward "^*" lim) | |
1562 (skip-chars-backward "*" lim) | |
1563 (while (not (or (and (= (following-char) ?*) | |
1564 (= (preceding-char) ?/)) | |
1565 (<= (point) lim))) | |
1566 (skip-chars-backward "^*" lim) | |
1567 (skip-chars-backward "*" lim)) | |
1568 (or (bobp) (forward-char -1))) | |
1569 ;; none of the above | |
1570 (setq stop t)))))))) | |
1571 | |
1572 ;; This defun works well for Lemacs 19.4-7, which implemented a first | |
1573 ;; shot at doing this via a C built-in backward-syntactic-ws. This | |
1574 ;; has been obsoleted in future Lemacsen and in FSF19 | |
1575 (defun c++-fast-backward-syntactic-ws-1 (&optional lim) | |
1576 "Skip backwards over syntactic whitespace. | |
1577 Syntactic whitespace is defined as lexical whitespace, C and C++ style | |
1578 comments, and preprocessor directives. Search no farther back than | |
1579 optional LIM. If LIM is omitted, `beginning-of-defun' is used." | |
1580 (save-restriction | |
1581 (let ((parse-sexp-ignore-comments t) | |
1582 donep boi char | |
1583 (lim (or lim (c++-point 'bod)))) | |
1584 (if (< lim (point)) | |
1585 (unwind-protect | |
1586 (progn | |
1587 (narrow-to-region lim (point)) | |
1588 ;; cpp statements are comments for our purposes here | |
1589 (if (eq major-mode 'c++-mode) | |
1590 (modify-syntax-entry ?# "< b" c++-mode-syntax-table) | |
1591 (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table) | |
1592 (modify-syntax-entry ?# "< b" c++-c-mode-syntax-table)) | |
1593 (while (not donep) | |
1594 ;; if you're not running a patched XEmacs, the new byte | |
1595 ;; compiler will complain about this function. ignore that | |
1596 (backward-syntactic-ws) | |
1597 (if (not (looking-at "#\\|/\\*\\|//\\|\n")) | |
1598 (forward-char 1)) | |
1599 (setq boi (c++-point 'boi) | |
1600 char (char-after boi)) | |
1601 (if (and char (= char ?#)) | |
1602 (progn (goto-char boi) | |
1603 (setq donep (<= (point) lim))) | |
1604 (setq donep t)) | |
1605 )) | |
1606 ;; cpp statements are not comments anywhere else | |
1607 (if (eq major-mode 'c++-mode) | |
1608 (modify-syntax-entry ?# "." c++-mode-syntax-table) | |
1609 (modify-syntax-entry ?\n " " c++-c-mode-syntax-table) | |
1610 (modify-syntax-entry ?# "." c++-c-mode-syntax-table)))) | |
1611 ))) | |
1612 | |
1613 ;; This is the way it should be done for all post 19.7 Lemacsen and | |
1614 ;; for all FSF19 implementations | |
1615 (defun c++-fast-backward-syntactic-ws-2 (&optional lim) | |
1616 "Skip backwards over syntactic whitespace. | |
1617 Syntactic whitespace is defined as lexical whitespace, C and C++ style | |
1618 comments, and preprocessor directives. Search no farther back than | |
1619 optional LIM. If LIM is omitted, `beginning-of-defun' is used." | |
1620 (save-restriction | |
1621 (let* ((lim (or lim (c++-point 'bod))) | |
1622 (here lim)) | |
1623 (if (< lim (point)) | |
1624 (unwind-protect | |
1625 (progn | |
1626 (narrow-to-region lim (point)) | |
1627 ;; cpp statements are comments for our purposes here | |
1628 (if (eq major-mode 'c++-mode) | |
1629 (modify-syntax-entry ?# "< b" c++-mode-syntax-table) | |
1630 (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table) | |
1631 (modify-syntax-entry ?# "< b" c++-c-mode-syntax-table)) | |
1632 (while (/= here (point)) | |
1633 (setq here (point)) | |
1634 (forward-comment -1))) | |
1635 ;; cpp statements are not comments everywhere else | |
1636 (if (eq major-mode 'c++-mode) | |
1637 (modify-syntax-entry ?# "." c++-mode-syntax-table) | |
1638 (modify-syntax-entry ?\n " " c++-c-mode-syntax-table) | |
1639 (modify-syntax-entry ?# "." c++-c-mode-syntax-table)))) | |
1640 ))) | |
1641 | |
1642 ;; This is the slow and ugly way, but its the best we can do in | |
1643 ;; vanilla GNU18 emacsen | |
1644 (defun c++-in-literal-v18 (&optional lim) | |
1645 "Determine if point is in a C++ ``literal''. | |
1646 Return `c' if in a C-style comment, `c++' if in a C++ style comment, | |
1647 `string' if in a string literal, `pound' if on a preprocessor line, or | |
1648 nil if not in a comment at all. Optional LIM is used as the backward | |
1649 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is | |
1650 used." | |
1651 (save-excursion | |
1652 (let* ((here (point)) | |
1653 (state nil) | |
1654 (match nil) | |
1655 (backlim (or lim (c++-point 'bod)))) | |
1656 (goto-char backlim) | |
1657 (while (< (point) here) | |
1658 (setq match | |
1659 (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)" | |
1660 here 'move) | |
1661 (buffer-substring (match-beginning 0) (match-end 0)))) | |
1662 (setq state | |
1663 (cond | |
1664 ;; no match | |
1665 ((null match) nil) | |
1666 ;; looking at the opening of a C++ style comment | |
1667 ((string= "//" match) | |
1668 (if (<= here (progn (end-of-line) (point))) 'c++)) | |
1669 ;; looking at the opening of a C block comment | |
1670 ((string= "/*" match) | |
1671 (if (not (re-search-forward "*/" here 'move)) 'c)) | |
1672 ;; looking at the opening of a double quote string | |
1673 ((string= "\"" match) | |
1674 (if (not (save-restriction | |
1675 ;; this seems to be necessary since the | |
1676 ;; re-search-forward will not work without it | |
1677 (narrow-to-region (point) here) | |
1678 (re-search-forward | |
1679 ;; this regexp matches a double quote | |
1680 ;; which is preceded by an even number | |
1681 ;; of backslashes, including zero | |
1682 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move))) | |
1683 'string)) | |
1684 ;; looking at the opening of a single quote string | |
1685 ((string= "'" match) | |
1686 (if (not (save-restriction | |
1687 ;; see comments from above | |
1688 (narrow-to-region (point) here) | |
1689 (re-search-forward | |
1690 ;; this matches a single quote which is | |
1691 ;; preceded by zero or two backslashes. | |
1692 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'" | |
1693 here 'move))) | |
1694 'string)) | |
1695 ((string-match "[ \t]*#" match) | |
1696 (if (<= here (progn (end-of-line) (point))) 'pound)) | |
1697 (t nil))) | |
1698 ) ; end-while | |
1699 state))) | |
1700 | |
1701 ;; This is for all 8-bit emacsen (Lucid 19, patched GNU18) | |
1702 (defun c++-in-literal-8-bit (&optional lim) | |
1703 "Determine if point is in a C++ ``literal''. | |
1704 Return `c' if in a C-style comment, `c++' if in a C++ style comment, | |
1705 `string' if in a string literal, `pound' if on a preprocessor line, or | |
1706 nil if not in a comment at all. Optional LIM is used as the backward | |
1707 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is | |
1708 used." | |
1709 (save-excursion | |
1710 (let* ((backlim (or lim (c++-point 'bod))) | |
1711 (here (point)) | |
1712 (parse-sexp-ignore-comments t) ; may not be necessary | |
1713 (state (parse-partial-sexp backlim (point)))) | |
1714 (cond | |
1715 ((nth 3 state) 'string) | |
1716 ((nth 4 state) (if (nth 7 state) 'c++ 'c)) | |
1717 ((progn | |
1718 (goto-char here) | |
1719 (beginning-of-line) | |
1720 (looking-at "[ \t]*#")) | |
1721 'pound) | |
1722 (t nil))))) | |
1723 | |
1724 ;; This is for all 1-bit emacsen (FSF19) | |
1725 (defun c++-in-literal-1-bit (&optional lim) | |
1726 "Determine if point is in a C++ ``literal''. | |
1727 Return `c' if in a C-style comment, `c++' if in a C++ style comment, | |
1728 `string' if in a string literal, `pound' if on a preprocessor line, or | |
1729 nil if not in a comment at all. Optional LIM is used as the backward | |
1730 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is | |
1731 used." | |
1732 (save-excursion | |
1733 (let* ((backlim (or lim (c++-point 'bod))) | |
1734 (here (point)) | |
1735 (parse-sexp-ignore-comments t) ; may not be necessary | |
1736 (state (parse-partial-sexp backlim (point)))) | |
1737 (cond | |
1738 ((nth 3 state) 'string) | |
1739 ((nth 4 state) (if (nth 7 state) 'c 'c++)) | |
1740 ((progn | |
1741 (goto-char here) | |
1742 (beginning-of-line) | |
1743 (looking-at "[ \t]*#")) | |
1744 'pound) | |
1745 (t nil))))) | |
1746 | |
1747 (cond | |
1748 ((memq 'old-v19 c++-emacs-features) | |
1749 (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-1)) | |
1750 ((memq 'v19 c++-emacs-features) | |
1751 (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-2)) | |
1752 (t | |
1753 (fset 'c++-backward-syntactic-ws 'c++-backward-syntactic-ws-v18)) | |
1754 ) | |
1755 (cond | |
1756 ((memq '8-bit c++-emacs-features) | |
1757 (fset 'c++-in-literal 'c++-in-literal-8-bit)) | |
1758 ((memq '1-bit c++-emacs-features) | |
1759 (fset 'c++-in-literal 'c++-in-literal-1-bit)) | |
1760 (t | |
1761 (fset 'c++-in-literal 'c++-in-literal-v18)) | |
1762 ) | |
1763 | |
1764 | |
1765 ;; ====================================================================== | |
1766 ;; defuns for parsing syntactic elements | |
1767 ;; ====================================================================== | |
1768 (defun c++-parse-state (&optional limit) | |
1769 "Determinate the syntactic state of the code at point. | |
1770 Iteratively uses `parse-partial-sexp' from point to LIMIT and returns | |
1771 the result of `parse-partial-sexp' at point. LIMIT is optional and | |
1772 defaults to `point-max'." | |
1773 (let ((limit (or limit (point-max))) | |
1774 (parse-sexp-ignore-comments t) | |
1775 state) | |
1776 (while (< (point) limit) | |
1777 (setq state (parse-partial-sexp (point) limit 0))) | |
1778 state)) | |
1779 | |
1780 (defun c++-at-top-level-p (wrt &optional bod) | |
1781 "Return t if point is not inside a containing C++ expression, nil | |
1782 if it is embedded in an expression. When WRT is non-nil, returns nil | |
1783 if not at the top level with respect to an enclosing class, or the | |
1784 depth of class nesting at point. With WRT nil, returns nil if not at | |
1785 the ``real'' top level. Optional BOD is the beginning of defun." | |
1786 (save-excursion | |
1787 (let ((indent-point (point)) | |
1788 (case-fold-search nil) | |
1789 state containing-sexp paren-depth | |
1790 (bod (or bod (c++-point 'bod))) | |
1791 foundp) | |
1792 (goto-char bod) | |
1793 (setq state (c++-parse-state indent-point) | |
1794 containing-sexp (nth 1 state) | |
1795 paren-depth (nth 0 state)) | |
1796 (cond | |
1797 ((eq major-mode 'c++-c-mode) | |
1798 (and (null containing-sexp) 0)) | |
1799 ((not wrt) | |
1800 (null containing-sexp)) | |
1801 ((null containing-sexp) 0) | |
1802 ((c++-in-parens-p) nil) | |
1803 (t | |
1804 ;; calculate depth wrt containing (possibly nested) classes | |
1805 (goto-char containing-sexp) | |
1806 (while (and (setq foundp (re-search-backward | |
1807 (concat "[;}]\\|" c++-class-key) | |
1808 (point-min) t)) | |
1809 (let ((bod (c++-point 'bod))) | |
1810 (or (c++-in-literal bod) | |
1811 (c++-in-parens-p bod) | |
1812 ;; see if class key is inside a template spec | |
1813 (and (looking-at c++-class-key) | |
1814 (progn (skip-chars-backward " \t\n") | |
1815 (memq (preceding-char) '(?, ?<)))))))) | |
1816 (if (memq (following-char) '(?} ?\;)) | |
1817 nil | |
1818 (setq state (c++-parse-state containing-sexp)) | |
1819 (and foundp | |
1820 (not (nth 1 state)) | |
1821 (nth 2 state) | |
1822 paren-depth)) | |
1823 ))))) | |
1824 | |
1825 (defun c++-in-parens-p (&optional lim) | |
1826 "Return t if inside a paren expression. | |
1827 Optional LIM is used as the backward limit of the search." | |
1828 (let ((lim (or lim (c++-point 'bod)))) | |
1829 (condition-case var | |
1830 (save-excursion | |
1831 (save-restriction | |
1832 (narrow-to-region (point) lim) | |
1833 (goto-char (point-max)) | |
1834 (= (char-after (or (scan-lists (point) -1 1) | |
1835 (point-min))) | |
1836 ?\())) | |
1837 (error nil) | |
1838 ))) | |
1839 | |
1840 (defun c++-in-function-p (&optional containing) | |
1841 "Return t if inside a C++ function definition. | |
1842 Optional CONTAINING is position of containing s-exp open brace. If not | |
1843 supplied, point is used as search start." | |
1844 (save-excursion | |
1845 (let ((here (if (not containing) | |
1846 (point) | |
1847 (goto-char containing) | |
1848 (c++-backward-syntactic-ws) | |
1849 (point)))) | |
1850 (if (and (= (preceding-char) ?t) | |
1851 (forward-word -1) | |
1852 (looking-at "\\<const\\>")) | |
1853 (c++-backward-syntactic-ws) | |
1854 (goto-char here)) | |
1855 (= (preceding-char) ?\))))) | |
1856 | |
1857 | |
1858 ;; ====================================================================== | |
1859 ;; defuns for calculating indentation | |
1860 ;; ====================================================================== | |
1861 (defun c++-indent-line (&optional bod) | |
1862 "Indent current line as C++ code. | |
1863 Return the amount the indentation changed by. Optional BOD is the | |
1864 point of the beginning of the C++ definition." | |
1865 (let* ((bod (or bod (c++-point 'bod))) | |
1866 (indent (c++-calculate-indent nil bod)) | |
1867 beg shift-amt | |
1868 close-paren top-close-paren | |
1869 (case-fold-search nil) | |
1870 (pos (- (point-max) (point)))) | |
1871 ;; calculate block close paren offset | |
1872 (if (listp c++-block-close-brace-offset) | |
1873 (setq close-paren (car c++-block-close-brace-offset) | |
1874 top-close-paren (cdr c++-block-close-brace-offset)) | |
1875 (setq close-paren c++-block-close-brace-offset | |
1876 top-close-paren c++-block-close-brace-offset)) | |
1877 ;; now start cleanup | |
1878 (beginning-of-line) | |
1879 (setq beg (point)) | |
1880 (cond | |
1881 ((eq indent nil) | |
1882 (setq indent (current-indentation))) | |
1883 ((eq indent t) | |
1884 (setq indent (c++-calculate-c-indent-within-comment))) | |
1885 ((looking-at "[ \t]*#") | |
1886 (setq indent 0)) | |
1887 ((save-excursion | |
1888 (back-to-indentation) | |
1889 (looking-at "//\\|/\\*")) | |
1890 ;; we've found a comment-only line. we now must try to determine | |
1891 ;; if the line is a continuation from a comment on the previous | |
1892 ;; line. we check to see if the comment starts in or to the | |
1893 ;; right of comment-column and if so, we don't change its | |
1894 ;; indentation. | |
1895 (skip-chars-forward " \t") | |
1896 (if (>= (current-column) comment-column) | |
1897 (setq indent (current-column)) | |
1898 (setq indent (c++-comment-offset (bolp) indent)))) | |
1899 (t | |
1900 (skip-chars-forward " \t") | |
1901 (if (listp indent) (setq indent (car indent))) | |
1902 (cond | |
1903 ((looking-at c++-access-key) | |
1904 (setq indent (+ indent c++-access-specifier-offset))) | |
1905 ((looking-at "default[ \t]*:") | |
1906 (setq indent (+ indent c-label-offset))) | |
1907 ((or (looking-at "case[ \t]+.*:") | |
1908 (and (looking-at "[A-Za-z]") | |
1909 (save-excursion | |
1910 (forward-sexp 1) | |
1911 (looking-at ":[^:]")))) | |
1912 (setq indent (max 1 (+ indent c-label-offset)))) | |
1913 ((and (looking-at "else\\b") | |
1914 (not (looking-at "else\\s_"))) | |
1915 (setq indent (save-excursion | |
1916 (c++-backward-to-start-of-if) | |
1917 (back-to-indentation) | |
1918 (skip-chars-forward "{ \t") | |
1919 (current-column)))) | |
1920 ((looking-at "\\<friend\\>") | |
1921 (setq indent (+ indent c++-friend-offset))) | |
1922 ((and (= (following-char) ?\)) | |
1923 c++-paren-as-block-close-p) | |
1924 (setq indent (+ (- indent c-indent-level) | |
1925 (if (save-excursion | |
1926 (forward-char 1) | |
1927 (c++-at-top-level-p nil bod)) | |
1928 top-close-paren | |
1929 close-paren)))) | |
1930 ((= (following-char) ?}) | |
1931 (setq indent (+ (- indent c-indent-level) | |
1932 (if (save-excursion | |
1933 (forward-char 1) | |
1934 (c++-at-top-level-p nil bod)) | |
1935 top-close-paren | |
1936 close-paren)))) | |
1937 ((= (following-char) ?{) | |
1938 (setq indent (+ indent c-brace-offset)))))) | |
1939 (skip-chars-forward " \t") | |
1940 (setq shift-amt (- indent (current-column))) | |
1941 (if (zerop shift-amt) | |
1942 (if (> (- (point-max) pos) (point)) | |
1943 (goto-char (- (point-max) pos))) | |
1944 (delete-region beg (point)) | |
1945 (indent-to indent) | |
1946 ;; If initial point was within line's indentation, | |
1947 ;; position after the indentation. Else stay at same point in text. | |
1948 (if (> (- (point-max) pos) (point)) | |
1949 (goto-char (- (point-max) pos)))) | |
1950 ;; save-excursion is necessary because things break if the hook | |
1951 ;; changes point or mark | |
1952 (save-excursion | |
1953 (run-hooks 'c++-special-indent-hook)) | |
1954 shift-amt)) | |
1955 | |
1956 (defun c++-cont-indent (ipnt char lim) | |
1957 "Calculate the indentation for a continued statement. | |
1958 IPNT is the indentation point; CHAR is the character before the | |
1959 indentation point, excluding any intervening whitespace; LIM is the | |
1960 minimum point to search backwards to." | |
1961 (let ((charlist '(nil ?\000 ?\, ?\; ?\} ?\: ?\{)) | |
1962 streamop-pos here) | |
1963 (goto-char ipnt) | |
1964 (c++-backward-syntactic-ws lim) | |
1965 (if (not (memq char charlist)) | |
1966 ;; This line is continuation of preceding line's statement | |
1967 (progn | |
1968 (c-backward-to-start-of-continued-exp lim) | |
1969 ;; take care of << and >> while in streams | |
1970 (setq here (point)) | |
1971 (if (save-excursion | |
1972 (and (progn (goto-char ipnt) | |
1973 (looking-at "[ \t]*\\(<<\\|>>\\)")) | |
1974 (progn (goto-char here) | |
1975 (skip-chars-forward "^><\n") | |
1976 (setq streamop-pos (current-column)) | |
1977 (looking-at "\\(<<\\|>>\\)")))) | |
1978 streamop-pos | |
1979 (+ (current-column) | |
1980 ;; prevent repeated continued indentation | |
1981 (if (save-excursion | |
1982 (beginning-of-line 1) | |
1983 (c++-backward-syntactic-ws lim) | |
1984 (memq (preceding-char) charlist)) | |
1985 c-continued-statement-offset | |
1986 ;; the following statements *do* indent even | |
1987 ;; for single statements (are there others?) | |
1988 (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b") | |
1989 c-continued-statement-offset | |
1990 ;; else may be a continued statement inside | |
1991 ;; a simple for/else/while/if/do loop | |
1992 (beginning-of-line 1) | |
1993 (forward-char -1) | |
1994 (c++-backward-syntactic-ws lim) | |
1995 (c-backward-to-start-of-continued-exp lim) | |
1996 (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b") | |
1997 c-continued-statement-offset | |
1998 0))) | |
1999 (save-excursion | |
2000 (goto-char ipnt) | |
2001 (skip-chars-forward " \t") | |
2002 (cond | |
2003 ((= (following-char) ?\{) | |
2004 c-continued-brace-offset) | |
2005 ((and (= (following-char) ?\}) | |
2006 (progn (forward-char 1) | |
2007 (c++-at-top-level-p nil lim))) | |
2008 (- c-continued-statement-offset)) | |
2009 (t 0)))))) | |
2010 nil))) | |
2011 | |
2012 (defun c++-calculate-indent (&optional parse-start bod) | |
2013 "Return appropriate indentation for current line as C++ code. | |
2014 In usual case returns an integer: the column to indent to. | |
2015 Returns nil if line starts inside a string, t if in a comment. | |
2016 Optional PARSE-START is the location to start parsing, and optional | |
2017 BOD is the beginning of the C++ definition." | |
2018 (save-excursion | |
2019 (beginning-of-line) | |
2020 (let ((indent-point (point)) | |
2021 (case-fold-search nil) | |
2022 state do-indentation literal in-meminit-p | |
2023 containing-sexp streamop-pos char-before-ip | |
2024 (inclass-shift 0) inclass-depth inclass-unshift | |
2025 (bod (or bod (c++-point 'bod)))) | |
2026 (if parse-start | |
2027 (goto-char parse-start) | |
2028 (goto-char bod)) | |
2029 (setq parse-start (point) | |
2030 state (c++-parse-state indent-point) | |
2031 containing-sexp (nth 1 state)) | |
2032 ;; it is possible that c++-defun-header-weak could not find the | |
2033 ;; beginning of the C++ definition. The following code attempts | |
2034 ;; to work around this. It is probably better to just use | |
2035 ;; c++-match-header-strongly, but there are performance questions | |
2036 (if (null state) | |
2037 (let* ((c++-match-header-strongly t) | |
2038 (bod (c++-point 'bod))) | |
2039 (goto-char bod) | |
2040 (setq state (c++-parse-state indent-point) | |
2041 containing-sexp (nth 1 state) | |
2042 parse-start (point)))) | |
2043 (setq literal (c++-in-literal bod)) | |
2044 ;; cache char before indent point | |
2045 (save-excursion | |
2046 (goto-char indent-point) | |
2047 (c++-backward-syntactic-ws bod) | |
2048 (setq char-before-ip (preceding-char))) | |
2049 (cond | |
2050 ;; CASE 1: in a string. | |
2051 ((memq literal '(string)) nil) | |
2052 ;; CASE 2: in a C or C++ style comment. | |
2053 ((memq literal '(c c++)) t) | |
2054 ;; CASE 3: Line is at top level. May be comment-only line, | |
2055 ;; data or function definition, or may be function argument | |
2056 ;; declaration or member initialization. Indent like the | |
2057 ;; previous top level line unless: | |
2058 ;; | |
2059 ;; 1. the previous line ends in a closeparen without | |
2060 ;; semicolon, in which case this line is the first | |
2061 ;; argument declaration or member initialization, or | |
2062 ;; | |
2063 ;; 2. the previous line ends with a closeparen | |
2064 ;; (closebrace), optional spaces, and a semicolon, in | |
2065 ;; which case this line follows a multiline function | |
2066 ;; declaration (class definition), or | |
2067 ;; | |
2068 ;; 3. the previous line begins with a colon, in which | |
2069 ;; case this is the second line of member inits. It is | |
2070 ;; assumed that arg decls and member inits are not mixed. | |
2071 ;; | |
2072 ((setq inclass-depth (c++-at-top-level-p t bod)) | |
2073 (+ | |
2074 ;; add an offset if we are inside a class defun body, i.e. we | |
2075 ;; are at the top level, but only wrt a containing class | |
2076 (let ((shift/level (+ c-indent-level c-brace-imaginary-offset))) | |
2077 (setq inclass-shift (* shift/level inclass-depth) | |
2078 inclass-unshift (* shift/level (max 0 (1- inclass-depth)))) | |
2079 inclass-shift) | |
2080 (progn | |
2081 (goto-char indent-point) | |
2082 (skip-chars-forward " \t") | |
2083 (cond | |
2084 ;; | |
2085 ((or (= (following-char) ?{) | |
2086 (progn | |
2087 (c++-backward-syntactic-ws parse-start) | |
2088 (bobp))) | |
2089 0) | |
2090 ;; first arg decl or member init | |
2091 ((c++-in-function-p) | |
2092 (goto-char indent-point) | |
2093 (skip-chars-forward " \t") | |
2094 (if (= (following-char) ?:) | |
2095 c++-member-init-indent | |
2096 c-argdecl-indent)) | |
2097 ;; | |
2098 ((progn | |
2099 (if (= (preceding-char) ?\;) | |
2100 (progn | |
2101 (backward-char 1) | |
2102 (skip-chars-backward " \t"))) | |
2103 ;; may be first line after a hanging member init colon. | |
2104 ;; check to be sure its not a scope operator meaning we | |
2105 ;; are inside a member def | |
2106 (or (= (preceding-char) ?:) | |
2107 (save-excursion | |
2108 (forward-line 1) | |
2109 (skip-chars-forward " \t") | |
2110 (or (eobp) (forward-char 1)) | |
2111 (and (= (preceding-char) ?:) | |
2112 (/= (following-char) ?:))) | |
2113 (save-excursion | |
2114 (and (= (preceding-char) ?,) | |
2115 (let ((bol (c++-point 'bol))) | |
2116 (skip-chars-backward "^:" bol) | |
2117 (= (preceding-char) ?:)) | |
2118 (not (c++-in-parens-p)) | |
2119 (progn | |
2120 (forward-char -1) | |
2121 (skip-chars-backward " \t") | |
2122 (not (bolp))) | |
2123 ;; make sure its not a multiple inheritance | |
2124 ;; continuation line | |
2125 (progn | |
2126 (beginning-of-line) | |
2127 (not (looking-at c++-inher-key))) | |
2128 )))) | |
2129 ;; check to see if we're looking at a member init, or | |
2130 ;; access specifier | |
2131 (if (progn | |
2132 (beginning-of-line) | |
2133 (skip-chars-forward " \t") | |
2134 (looking-at c++-access-key)) | |
2135 ;; access specifier. class defun opening brace may | |
2136 ;; not be in col zero, and derived classes could be | |
2137 ;; on a separate line than class intro | |
2138 (progn | |
2139 (goto-char (or containing-sexp bod)) | |
2140 (beginning-of-line) | |
2141 (skip-chars-forward " \t") | |
2142 (if (looking-at | |
2143 ":[ \t]*\\<\\(public\\|protected\\|private\\)\\>") | |
2144 (forward-line -1)) | |
2145 (- (current-indentation) | |
2146 ;; remove some nested inclass indentation | |
2147 inclass-unshift)) | |
2148 ;; member init, so add offset. add additional offset if | |
2149 ;; looking at line with just a member init colon | |
2150 (+ c++-member-init-indent | |
2151 (if (looking-at ":[ \t]*$") | |
2152 (or c++-continued-member-init-offset 0) 0)))) | |
2153 ((or (= (preceding-char) ?}) | |
2154 (= (preceding-char) ?\)) | |
2155 (save-excursion | |
2156 (beginning-of-line) | |
2157 (looking-at "[ \t]*\\<friend\\>"))) | |
2158 ;; indentation of class defun opening brace may not be | |
2159 ;; zero | |
2160 (goto-char (or containing-sexp bod)) | |
2161 (- (current-indentation) | |
2162 ;; remove some nested inclass indentation | |
2163 inclass-unshift)) | |
2164 ;; cont arg decls or member inits. we might be inside a | |
2165 ;; K&R C arg decl | |
2166 ((save-excursion | |
2167 (while (and (< bod (point)) | |
2168 (memq (preceding-char) '(?\, ?\;))) | |
2169 (beginning-of-line) | |
2170 (c++-backward-syntactic-ws bod)) | |
2171 (and (eq major-mode 'c++-c-mode) | |
2172 (= (preceding-char) ?\)))) | |
2173 (+ c-argdecl-indent | |
2174 (progn | |
2175 (goto-char indent-point) | |
2176 (c++-backward-syntactic-ws bod) | |
2177 (if (= (preceding-char) ?,) | |
2178 c-continued-statement-offset | |
2179 0)))) | |
2180 ((progn | |
2181 (beginning-of-line) | |
2182 (skip-chars-forward " \t") | |
2183 (or (memq (c++-in-literal bod) '(c c++)) | |
2184 (looking-at "/[/*]"))) | |
2185 0) | |
2186 ;; are we looking at the first member init? | |
2187 ((and (= (following-char) ?:) | |
2188 (save-excursion | |
2189 (c++-backward-syntactic-ws bod) | |
2190 (= (preceding-char) ?\)))) | |
2191 (if c++-continued-member-init-offset | |
2192 (+ (current-indentation) | |
2193 c++-continued-member-init-offset) | |
2194 (progn | |
2195 (forward-char 1) | |
2196 (skip-chars-forward " \t") | |
2197 (- (current-column) | |
2198 inclass-shift)))) | |
2199 ;; else first check to see if its a multiple inheritance | |
2200 ;; continuation line, but not a K&R C arg decl | |
2201 ((and (not (eq major-mode 'c++-c-mode)) | |
2202 (looking-at c++-inher-key)) | |
2203 (if (= char-before-ip ?,) | |
2204 (progn (goto-char (match-end 0)) | |
2205 (current-column)) | |
2206 ;; nope, its probably a nested class | |
2207 0)) | |
2208 ;; we might be looking at the opening brace of a class | |
2209 ;; defun | |
2210 ((= (following-char) ?\{) | |
2211 ;; indentation of opening brace may not be zero | |
2212 (- (current-indentation) | |
2213 ;; remove some nested inclass indentation | |
2214 inclass-unshift)) | |
2215 ((eolp) | |
2216 ;; looking at a blank line, indent next line to zero | |
2217 0) | |
2218 ;; at beginning of buffer, if nothing else, indent to zero | |
2219 ((save-excursion | |
2220 (goto-char indent-point) | |
2221 (beginning-of-line) | |
2222 (bobp)) | |
2223 0) | |
2224 ;; this could be a compound statement, but make sure its | |
2225 ;; not a member init list | |
2226 ((save-excursion | |
2227 (goto-char indent-point) | |
2228 (c++-backward-syntactic-ws bod) | |
2229 (and (= (preceding-char) ?,) | |
2230 (save-excursion | |
2231 (while (and (< bod (point)) | |
2232 (= (preceding-char) ?,)) | |
2233 (beginning-of-line) | |
2234 (c++-backward-syntactic-ws bod)) | |
2235 (forward-line 1) | |
2236 (not (setq in-meminit-p (looking-at "[ \t]*:")))))) | |
2237 c-continued-statement-offset) | |
2238 (t | |
2239 (if (c++-in-parens-p) | |
2240 ;; we are perhaps inside a member init call | |
2241 (while (and (c++-in-parens-p) | |
2242 (< bod (point))) | |
2243 (forward-line -1) | |
2244 (skip-chars-forward " \t"))) | |
2245 ;; check to be sure that we're not on the first line of | |
2246 ;; the member init list | |
2247 (if (and (= (following-char) ?:) | |
2248 (save-excursion | |
2249 (c++-backward-syntactic-ws bod) | |
2250 (= (preceding-char) ?\)))) | |
2251 (progn | |
2252 (forward-char 1) | |
2253 (skip-chars-forward " \t"))) | |
2254 ;; skip to start of compound statement, but only if we're | |
2255 ;; not in a member initialization list | |
2256 (if (not in-meminit-p) | |
2257 (let ((ipnt (point))) | |
2258 (c++-backward-syntactic-ws bod) | |
2259 (while (and (= (preceding-char) ?,) | |
2260 (< bod (point))) | |
2261 (beginning-of-line) | |
2262 (skip-chars-forward " \t") | |
2263 (setq ipnt (point)) | |
2264 (c++-backward-syntactic-ws bod)) | |
2265 (goto-char ipnt))) | |
2266 ;; subtract inclass-shift since its already incorporated | |
2267 ;; by default in current-column | |
2268 (- (current-column) inclass-shift) | |
2269 ))))) | |
2270 ;; CASE 4: line is expression, not statement. indent to just | |
2271 ;; after the surrounding open -- unless empty arg list, in | |
2272 ;; which case we do what c++-empty-arglist-indent says to do. | |
2273 ((/= (char-after containing-sexp) ?{) | |
2274 (if (and c++-empty-arglist-indent | |
2275 (or c++-always-arglist-indent-p | |
2276 (null (nth 2 state)) | |
2277 ;; indicates empty arg list. Use a heuristic: if | |
2278 ;; the first non-whitespace following left paren | |
2279 ;; on same line is not a comment, is not an empty | |
2280 ;; arglist. | |
2281 (save-excursion | |
2282 (goto-char (1+ containing-sexp)) | |
2283 (looking-at "[ \t]*[/\n]")))) | |
2284 (progn | |
2285 (goto-char containing-sexp) | |
2286 (beginning-of-line) | |
2287 (skip-chars-forward " \t") | |
2288 (goto-char (min (+ (point) c++-empty-arglist-indent) | |
2289 (1+ containing-sexp))) | |
2290 (current-column)) | |
2291 ;; In C-mode, we would always indent to one after the | |
2292 ;; left paren. Here, though, we may have an | |
2293 ;; empty-arglist, so we'll indent to the min of that | |
2294 ;; and the beginning of the first argument. | |
2295 (goto-char (1+ containing-sexp)) | |
2296 ;; we want to skip any whitespace b/w open paren and | |
2297 ;; first argument. this handles while (thing) style | |
2298 ;; and while( thing ) style | |
2299 (skip-chars-forward " \t") | |
2300 (current-column))) | |
2301 ;; CASE 5: Statement. Find previous non-comment character. | |
2302 (t | |
2303 (or (c++-cont-indent indent-point char-before-ip containing-sexp) | |
2304 ;; This line may start a new statement, or it could | |
2305 ;; represent the while closure of a do/while construct | |
2306 (if (save-excursion | |
2307 (and (progn (goto-char indent-point) | |
2308 (skip-chars-forward " \t\n") | |
2309 (looking-at "while\\b")) | |
2310 (progn | |
2311 (c++-backward-to-start-of-do containing-sexp) | |
2312 (looking-at "do\\b")) | |
2313 (setq do-indentation (current-column)))) | |
2314 do-indentation | |
2315 ;; this could be a case statement. if so we want to | |
2316 ;; indent it like the first case statement after a switch | |
2317 (if (save-excursion | |
2318 (goto-char indent-point) | |
2319 (skip-chars-forward " \t\n") | |
2320 (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")) | |
2321 (progn | |
2322 (goto-char containing-sexp) | |
2323 (back-to-indentation) | |
2324 (+ (current-column) c-indent-level)) | |
2325 ;; else, this is the start of a new statement | |
2326 ;; Position following last unclosed open. | |
2327 (goto-char containing-sexp) | |
2328 ;; Is line first statement after an open-brace? | |
2329 (or | |
2330 (and c++-relative-offset-p | |
2331 ;; If no, find that first statement and | |
2332 ;; indent like it. | |
2333 (save-excursion | |
2334 (forward-char 1) | |
2335 (while | |
2336 (progn | |
2337 (skip-chars-forward " \t\n") | |
2338 (looking-at | |
2339 (concat | |
2340 "#\\|/\\*\\|//" | |
2341 "\\|\\(case[ \t]+.*\\|default[ \t]*\\):" | |
2342 "\\|[a-zA-Z0-9_$]*:[^:]" | |
2343 "\\|friend[ \t]" | |
2344 c++-class-key | |
2345 "[ \t]"))) | |
2346 ;; Skip over comments and labels | |
2347 ;; following openbrace. | |
2348 (cond | |
2349 ((= (following-char) ?\#) | |
2350 (forward-line 1)) | |
2351 ((looking-at "/\\*") | |
2352 (search-forward "*/" nil 'move)) | |
2353 ((looking-at | |
2354 (concat "//\\|friend[ \t]" c++-class-key | |
2355 "[ \t]")) | |
2356 (forward-line 1)) | |
2357 ((looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):") | |
2358 (forward-line 1)) | |
2359 (t | |
2360 (re-search-forward ":[^:]" nil 'move)))) | |
2361 ;; The first following code counts | |
2362 ;; if it is before the line we want to indent. | |
2363 (and (< (point) indent-point) | |
2364 (+ (current-column) | |
2365 (c++-compound-offset | |
2366 char-before-ip containing-sexp bod))))) | |
2367 ;; If no previous statement, indent it relative to | |
2368 ;; line brace is on. For open brace in column | |
2369 ;; zero, don't let statement start there too. If | |
2370 ;; c-indent-offset is zero, use c-brace-offset + | |
2371 ;; c-continued-statement-offset instead. For | |
2372 ;; open-braces not the first thing in a line, add | |
2373 ;; in c-brace-imaginary-offset. | |
2374 (+ (if (and (bolp) (zerop c-indent-level)) | |
2375 (+ c-brace-offset c-continued-statement-offset) | |
2376 c-indent-level) | |
2377 ;; Move back over whitespace before the openbrace. | |
2378 ;; If openbrace is not first nonwhite thing on the line, | |
2379 ;; add the c-brace-imaginary-offset. | |
2380 (progn (skip-chars-backward " \t") | |
2381 (if (bolp) 0 c-brace-imaginary-offset)) | |
2382 ;; If the openbrace is preceded by a parenthesized exp, | |
2383 ;; move to the beginning of that; | |
2384 ;; possibly a different line | |
2385 (progn | |
2386 (if (eq (preceding-char) ?\)) | |
2387 (forward-sexp -1)) | |
2388 ;; Get initial indentation of the line we are on. | |
2389 (current-indentation)))))))) ; end t outer cond | |
2390 )))) | |
2391 | |
2392 (defun c++-calculate-c-indent-within-comment () | |
2393 "Return the indentation amount for line, assuming that | |
2394 the current line is to be regarded as part of a block comment." | |
2395 (let (end stars indent) | |
2396 (save-excursion | |
2397 (beginning-of-line) | |
2398 (skip-chars-forward " \t") | |
2399 (setq stars (if (looking-at "\\*\\*?") | |
2400 (- (match-end 0) (match-beginning 0)) | |
2401 0)) | |
2402 (skip-chars-backward " \t\n") | |
2403 (setq end (point)) | |
2404 (beginning-of-line) | |
2405 (skip-chars-forward " \t") | |
2406 (if (re-search-forward "/\\*[ \t]*" end t) | |
2407 (goto-char (+ (match-beginning 0) | |
2408 (cond | |
2409 (c++-C-block-comments-indent-p 0) | |
2410 ((= stars 1) 1) | |
2411 ((= stars 2) 0) | |
2412 (t (- (match-end 0) (match-beginning 0))))))) | |
2413 (current-column)))) | |
2414 | |
2415 (defun c++-comment-offset (col0-line-p indent) | |
2416 "Calculates and returns the comment-only line offset. | |
2417 Offset is based on the value of `c++-comment-only-line-offset', the | |
2418 argument COL0-LINE-P, and the current indentation INDENT." | |
2419 (let ((offset 0)) | |
2420 (if col0-line-p | |
2421 ;; col0 means we need to look at the second member of the var's | |
2422 ;; list value. if value is not a list, then zero is used | |
2423 (if (listp c++-comment-only-line-offset) | |
2424 ;; it is a list, so second element must be nil or a number | |
2425 (setq offset | |
2426 (+ indent | |
2427 (or (car (cdr c++-comment-only-line-offset)) | |
2428 (car c++-comment-only-line-offset))))) | |
2429 ;; not in column zero so indentation is car or value of variable | |
2430 (setq offset | |
2431 (+ indent | |
2432 (if (listp c++-comment-only-line-offset) | |
2433 (car c++-comment-only-line-offset) | |
2434 c++-comment-only-line-offset)))) | |
2435 offset)) | |
2436 | |
2437 (defun c++-compound-offset (char-before-ip containing-sexp bod) | |
2438 "Calculates any addition offset due a comma separated compound statement. | |
2439 CHAR-BEFORE-IP is the character before the indentation point and | |
2440 CONTAINING-SEXP is the buffer position of the open brace or paren. | |
2441 BOD is the `beginning-of-defun' point." | |
2442 (cond | |
2443 ;; not a compound statement | |
2444 ((/= char-before-ip ?,) 0) | |
2445 ;; open brace could be at column zero == bod | |
2446 ((and (= containing-sexp bod) | |
2447 (or (let ((lim (progn | |
2448 (goto-char containing-sexp) | |
2449 (forward-line -1) | |
2450 (point)))) | |
2451 (end-of-line) | |
2452 (c++-backward-syntactic-ws lim) | |
2453 (= (preceding-char) ?=)) | |
2454 (progn | |
2455 (beginning-of-line) | |
2456 (looking-at "\\(^\\|[ \t]*\\)enum[ \t]")) | |
2457 )) | |
2458 0) | |
2459 ;; check for inside an enum | |
2460 ((let ((parse-sexp-ignore-comments t) | |
2461 in-enum-p) | |
2462 (goto-char containing-sexp) | |
2463 (while (< bod (point)) | |
2464 (c++-backward-syntactic-ws) | |
2465 (if (memq (preceding-char) '(?\) ?\" ?\; ?\})) | |
2466 (goto-char bod) | |
2467 (forward-sexp -1) | |
2468 (if (looking-at "\\(enum[ \t\n]\\|\\[.*\\]\\)") | |
2469 (progn (goto-char bod) | |
2470 (setq in-enum-p t))))) | |
2471 in-enum-p) | |
2472 0) | |
2473 ;; assume we're not in a list of enums or static array elems | |
2474 (t c-continued-statement-offset) | |
2475 )) | |
2476 | |
2477 | |
2478 | |
2479 ;; ====================================================================== | |
2480 ;; defuns to look backwards for things | |
2481 ;; ====================================================================== | |
2482 | |
2483 (defun c++-backward-to-start-of-do (&optional limit) | |
2484 "Move to the start of the last ``unbalanced'' do." | |
2485 (let ((do-level 1) | |
2486 (case-fold-search nil) | |
2487 (limit (or limit (c++-point 'bod)))) | |
2488 (while (not (zerop do-level)) | |
2489 ;; we protect this call because trying to execute this when the | |
2490 ;; while is not associated with a do will throw an error | |
2491 (condition-case err | |
2492 (progn | |
2493 (backward-sexp 1) | |
2494 (cond | |
2495 ((memq (c++-in-literal limit) '(c c++))) | |
2496 ((looking-at "while\\b") | |
2497 (setq do-level (1+ do-level))) | |
2498 ((looking-at "do\\b") | |
2499 (setq do-level (1- do-level))) | |
2500 ((< (point) limit) | |
2501 (setq do-level 0) | |
2502 (goto-char limit)))) | |
2503 (error | |
2504 (goto-char limit) | |
2505 (setq do-level 0)))))) | |
2506 | |
2507 (defun c++-backward-to-start-of-if (&optional limit) | |
2508 "Move to the start of the last ``unbalanced'' if." | |
2509 (let ((if-level 1) | |
2510 (case-fold-search nil) | |
2511 (limit (or limit (c++-point 'bod)))) | |
2512 (while (and (not (bobp)) | |
2513 (not (zerop if-level))) | |
2514 (c++-backward-syntactic-ws) | |
2515 (c++-backward-sexp 1) | |
2516 (cond ((looking-at "else\\b") | |
2517 (setq if-level (1+ if-level))) | |
2518 ((looking-at "if\\b") | |
2519 (setq if-level (1- if-level))) | |
2520 ((< (point) limit) | |
2521 (setq if-level 0) | |
2522 (goto-char limit)))))) | |
2523 | |
2524 (defun c++-auto-newline () | |
2525 "Insert a newline iff we're not in a literal. | |
2526 Literals are defined as being inside a C or C++ style comment or open | |
2527 string according to mode's syntax." | |
2528 (let ((bod (c++-point 'bod))) | |
2529 (and c++-auto-newline | |
2530 (not (c++-in-literal bod)) | |
2531 (not (newline))))) | |
2532 | |
2533 (defun c++-point (position) | |
2534 "Returns the value of point at certain commonly referenced POSITIONs. | |
2535 POSITION can be one of the following symbols: | |
2536 `bol' -- beginning of line | |
2537 `eol' -- end of line | |
2538 `bod' -- beginning of defun | |
2539 `boi' -- back to indentation | |
2540 This function does not modify point or mark." | |
2541 (let ((here (point)) bufpos) | |
2542 (cond | |
2543 ((eq position 'bol) (beginning-of-line)) | |
2544 ((eq position 'eol) (end-of-line)) | |
2545 ((eq position 'bod) (c++-beginning-of-defun)) | |
2546 ((eq position 'boi) (back-to-indentation)) | |
2547 ) | |
2548 (setq bufpos (point)) | |
2549 (goto-char here) | |
2550 bufpos)) | |
2551 | |
2552 | |
2553 ;; ====================================================================== | |
2554 ;; defuns for "macroizations" -- making C++ parameterized types via macros | |
2555 ;; ====================================================================== | |
2556 (defun c++-macroize-region (from to arg) | |
2557 "Insert backslashes at end of every line in region. | |
2558 Useful for defining cpp macros. If called with a prefix argument, | |
2559 it will remove trailing backslashes." | |
2560 (interactive "r\nP") | |
2561 (save-excursion | |
2562 (goto-char from) | |
2563 (beginning-of-line 1) | |
2564 (let ((line (count-lines (point-min) (point))) | |
2565 (to-line (save-excursion (goto-char to) | |
2566 (count-lines (point-min) (point))))) | |
2567 (while (< line to-line) | |
2568 (c++-backslashify-current-line (null arg)) | |
2569 (forward-line 1) (setq line (1+ line)))))) | |
2570 | |
2571 (defun c++-backslashify-current-line (doit) | |
2572 "Backslashifies current line." | |
2573 (end-of-line 1) | |
2574 (cond | |
2575 (doit | |
2576 ;; Note that "\\\\" is needed to get one backslash. | |
2577 (if (not (save-excursion (forward-char -1) (looking-at "\\\\"))) | |
2578 (progn | |
2579 (if (>= (current-column) c++-default-macroize-column) | |
2580 (insert " \\") | |
2581 (while (<= (current-column) c++-default-macroize-column) | |
2582 (insert "\t") (end-of-line)) | |
2583 (delete-char -1) | |
2584 (while (< (current-column) c++-default-macroize-column) | |
2585 (insert " ") (end-of-line)) | |
2586 (insert "\\"))))) | |
2587 (t | |
2588 (forward-char -1) | |
2589 (if (looking-at "\\\\") | |
2590 (progn (skip-chars-backward " \t") | |
2591 (kill-line)))))) | |
2592 | |
2593 | |
2594 ;; ====================================================================== | |
2595 ;; defuns for commenting out multiple lines. | |
2596 ;; ====================================================================== | |
2597 (defun c++-comment-region (beg end) | |
2598 "Comment out all lines in a region between mark and current point by | |
2599 inserting `comment-start' in front of each line." | |
2600 (interactive "*r") | |
2601 (save-excursion | |
2602 (save-restriction | |
2603 (narrow-to-region | |
2604 (progn (goto-char beg) (beginning-of-line) (point)) | |
2605 (progn (goto-char end) (or (bolp) (forward-line 1)) (point))) | |
2606 (goto-char (point-min)) | |
2607 (while (not (eobp)) | |
2608 (insert comment-start) | |
2609 (forward-line 1)) | |
2610 (if (eq major-mode 'c++-c-mode) | |
2611 (insert comment-end))))) | |
2612 | |
2613 (defun c++-uncomment-region (beg end) | |
2614 "Uncomment all lines in region between mark and current point by deleting | |
2615 the leading ``// '' from each line, if any." | |
2616 (interactive "*r") | |
2617 (save-excursion | |
2618 (save-restriction | |
2619 (narrow-to-region | |
2620 (progn (goto-char beg) (beginning-of-line) (point)) | |
2621 (progn (goto-char end) (forward-line 1) (point))) | |
2622 (goto-char (point-min)) | |
2623 (let ((comment-regexp | |
2624 (if (eq major-mode 'c++-c-mode) | |
2625 (concat "\\s *\\(" (regexp-quote comment-start) | |
2626 "\\|" (regexp-quote comment-end) | |
2627 "\\)") | |
2628 (concat "\\s *" (regexp-quote comment-start))))) | |
2629 (while (not (eobp)) | |
2630 (if (looking-at comment-regexp) | |
2631 (delete-region (match-beginning 0) (match-end 0))) | |
2632 (forward-line 1)))))) | |
2633 | |
2634 | |
2635 ;; ====================================================================== | |
2636 ;; grammar parsing | |
2637 ;; ====================================================================== | |
2638 | |
2639 ;;; Below are two regular expressions that attempt to match defuns | |
2640 ;;; "strongly" and "weakly." The strong one almost reconstructs the | |
2641 ;;; grammar of C++; the weak one just figures anything id or curly on | |
2642 ;;; the left begins a defun. The constant "c++-match-header-strongly" | |
2643 ;;; determines which to use; the default is the weak one. | |
2644 | |
2645 (defvar c++-match-header-strongly nil | |
2646 "*If nil, use `c++-defun-header-weak' to identify beginning of definitions, | |
2647 if non-nil, use `c++-defun-header-strong'.") | |
2648 | |
2649 (defvar c++-defun-header-strong-struct-equivs | |
2650 "\\(class\\|struct\\|union\\|enum\\)" | |
2651 "Regexp to match names of structure declaration blocks in C++") | |
2652 | |
2653 (defconst c++-defun-header-strong | |
2654 (let* | |
2655 (; valid identifiers | |
2656 ;; There's a real weirdness here -- if I switch the below | |
2657 (id "\\(\\w\\|_\\)+") | |
2658 ;; to be | |
2659 ;; (id "\\(_\\|\\w\\)+") | |
2660 ;; things no longer work right. Try it and see! | |
2661 | |
2662 ; overloadable operators | |
2663 (op-sym1 | |
2664 "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?") | |
2665 (op-sym2 | |
2666 "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]") | |
2667 (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)")) | |
2668 ; whitespace | |
2669 (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*") | |
2670 (c-comment (concat "/\\*" middle "\\*+/")) | |
2671 (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)")) | |
2672 (wh-opt (concat wh "*")) | |
2673 (wh-nec (concat wh "+")) | |
2674 (oper (concat "\\(" "operator" "\\(" | |
2675 wh-opt op-sym "\\|" wh-nec id "\\)" "\\)")) | |
2676 (dcl-list "([^():]*)") | |
2677 (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)")) | |
2678 (inits | |
2679 (concat "\\(:" | |
2680 "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*" | |
2681 wh-opt id "(.*)" wh-opt "{" | |
2682 "\\|" wh-opt "{\\)")) | |
2683 (type-name (concat | |
2684 "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?" | |
2685 id)) | |
2686 (type (concat "\\(const" wh-nec "\\)?" | |
2687 "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|" | |
2688 type-name wh-opt "&" "\\)")) | |
2689 (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)") | |
2690 (modifiers (concat "\\(" modifier wh-nec "\\)*")) | |
2691 (func-header | |
2692 ;; type arg-dcl | |
2693 (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits)) | |
2694 (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?" | |
2695 wh-nec id "\\)")) | |
2696 (cs-header (concat | |
2697 c++-defun-header-strong-struct-equivs | |
2698 wh-nec id wh-opt inherit "?" wh-opt "{"))) | |
2699 (concat "^\\(" func-header "\\|" cs-header "\\)")) | |
2700 "Strongly-defined regexp to match beginning of structure or | |
2701 function definition.") | |
2702 | |
2703 | |
2704 ;; This part has to do with recognizing defuns. | |
2705 | |
2706 ;; The weak convention we will use is that a defun begins any time | |
2707 ;; there is a left curly brace, or some identifier on the left margin, | |
2708 ;; followed by a left curly somewhere on the line. (This will also | |
2709 ;; incorrectly match some continued strings, but this is after all | |
2710 ;; just a weak heuristic.) Suggestions for improvement (short of the | |
2711 ;; strong scheme shown above) are welcomed. | |
2712 | |
2713 (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{" | |
2714 "Weakly-defined regexp to match beginning of structure or function | |
2715 definition.") | |
2716 | |
2717 | |
2718 (defun c++-beginning-of-defun (&optional arg) | |
2719 "Find the beginning of the C++ function or class." | |
2720 (interactive "_p") | |
2721 (if (not arg) (setq arg 1)) | |
2722 (let ((c++-defun-header (if c++-match-header-strongly | |
2723 c++-defun-header-strong | |
2724 c++-defun-header-weak))) | |
2725 (cond | |
2726 ((or (= arg 0) (and (> arg 0) (bobp))) nil) | |
2727 ((and (not (looking-at c++-defun-header)) | |
2728 (let ((curr-pos (point)) | |
2729 (open-pos (if (search-forward "{" nil 'move) | |
2730 (point))) | |
2731 (beg-pos | |
2732 (if (re-search-backward c++-defun-header nil 'move) | |
2733 (match-beginning 0)))) | |
2734 (if (and open-pos beg-pos | |
2735 (< beg-pos curr-pos) | |
2736 (> open-pos curr-pos)) | |
2737 (progn | |
2738 (goto-char beg-pos) | |
2739 (if (= arg 1) t nil));; Are we done? | |
2740 (goto-char curr-pos) | |
2741 nil)))) | |
2742 (t | |
2743 (if (and (looking-at c++-defun-header) (not (bobp))) | |
2744 (forward-char (if (< arg 0) 1 -1))) | |
2745 (and (re-search-backward c++-defun-header nil 'move (or arg 1)) | |
2746 (goto-char (match-beginning 0))))))) | |
2747 | |
2748 | |
2749 (defun c++-end-of-defun (arg) | |
2750 "Find the end of the C++ function or class." | |
2751 (interactive "_p") | |
2752 (let ((c++-defun-header (if c++-match-header-strongly | |
2753 c++-defun-header-strong | |
2754 c++-defun-header-weak)) | |
2755 (parse-sexp-ignore-comments t)) | |
2756 (if (and (eobp) (> arg 0)) | |
2757 nil | |
2758 (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1)) | |
2759 (let ((pos (point))) | |
2760 (c++-beginning-of-defun | |
2761 (if (< arg 0) | |
2762 (- (- arg (if (eobp) 0 1))) | |
2763 arg)) | |
2764 (if (and (< arg 0) (bobp)) | |
2765 t | |
2766 (if (re-search-forward c++-defun-header nil 'move) | |
2767 (progn (forward-char -1) | |
2768 (forward-sexp) | |
2769 (beginning-of-line 2))) | |
2770 (if (and (= pos (point)) | |
2771 (re-search-forward c++-defun-header nil 'move)) | |
2772 (c++-end-of-defun 1)))) | |
2773 t))) | |
2774 | |
2775 (defun c++-indent-defun () | |
2776 "Indents the current function def, struct or class declaration." | |
2777 (interactive) | |
2778 (let ((restore (point))) | |
2779 (c++-end-of-defun 1) | |
2780 (beginning-of-line 1) | |
2781 (let ((end (point-marker))) | |
2782 (c++-beginning-of-defun) | |
2783 (while (and (< (point) end)) | |
2784 (c++-indent-line) | |
2785 (forward-line 1) | |
2786 (beginning-of-line 1)) | |
2787 (set-marker end nil)) | |
2788 (goto-char restore))) | |
2789 | |
2790 | |
2791 ;; ====================================================================== | |
2792 ;; defuns for submitting bug reports | |
2793 ;; ====================================================================== | |
2794 (defconst c++-version "2.353" | |
2795 "c++-mode version number.") | |
2796 (defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov" | |
2797 "Address accepting submission of bug reports.") | |
2798 | |
2799 (defun c++-version () | |
2800 "Echo the current version of c++-mode." | |
2801 (interactive) | |
2802 (message "Using c++-mode.el %s" c++-version)) | |
2803 | |
2804 (defun c++-submit-bug-report () | |
2805 "Submit via mail a bug report on c++-mode." | |
2806 (interactive) | |
2807 (require 'reporter) | |
2808 (and | |
2809 (y-or-n-p "Do you want to submit a report on c++-mode? ") | |
2810 (reporter-submit-bug-report | |
2811 c++-mode-help-address | |
2812 (concat "c++-mode.el " c++-version " (editing " | |
2813 (if (eq major-mode 'c++-mode) "C++" "C") | |
2814 " code)") | |
2815 (list | |
2816 'c++-emacs-features | |
2817 'c++-C-block-comments-indent-p | |
2818 'c++-access-specifier-offset | |
2819 'c++-always-arglist-indent-p | |
2820 'c++-auto-hungry-initial-state | |
2821 'c++-auto-hungry-toggle | |
2822 'c++-auto-newline | |
2823 'c++-backscan-limit | |
2824 'c++-block-close-brace-offset | |
2825 'c++-cleanup-list | |
2826 'c++-comment-only-line-offset | |
2827 'c++-continued-member-init-offset | |
2828 'c++-default-macroize-column | |
2829 'c++-defun-header-strong-struct-equivs | |
2830 'c++-delete-function | |
2831 'c++-electric-pound-behavior | |
2832 'c++-empty-arglist-indent | |
2833 'c++-friend-offset | |
2834 'c++-hanging-braces | |
2835 'c++-hanging-member-init-colon | |
2836 'c++-hungry-delete-key | |
2837 'c++-match-header-strongly | |
2838 'c++-member-init-indent | |
2839 'c++-paren-as-block-close-p | |
2840 'c++-relative-offset-p | |
2841 'c++-tab-always-indent | |
2842 'c++-untame-characters | |
2843 'c-argdecl-indent | |
2844 'c-brace-imaginary-offset | |
2845 'c-brace-offset | |
2846 'c-continued-brace-offset | |
2847 'c-continued-statement-offset | |
2848 'c-indent-level | |
2849 'c-label-offset | |
2850 'tab-width | |
2851 ) | |
2852 (function | |
2853 (lambda () | |
2854 (insert | |
2855 (if c++-special-indent-hook | |
2856 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" | |
2857 "c++-special-indent-hook is set to '" | |
2858 (format "%s" c++-special-indent-hook) | |
2859 ".\nPerhaps this is your problem?\n" | |
2860 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n") | |
2861 "\n") | |
2862 ))) | |
2863 ))) | |
2864 | |
2865 | |
2866 ;; this is sometimes useful | |
2867 (provide 'c++-mode) | |
2868 | |
2869 ;;; c++-mode.el ends here |