0
|
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
|