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