-
Notifications
You must be signed in to change notification settings - Fork 0
/
cc-cmds.el
4718 lines (4308 loc) · 166 KB
/
cc-cmds.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; cc-cmds.el --- user level commands for CC Mode
;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
;; 2010, 2011 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; Maintainer: [email protected]
;; Created: 22-Apr-1997 (split from cc-mode.el)
;; Version: See cc-mode.el
;; Keywords: c languages oop
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, see
;; <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(eval-when-compile
(let ((load-path
(if (and (boundp 'byte-compile-dest-file)
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
(cc-require 'cc-vars)
(cc-require 'cc-engine)
;; Silence the compiler.
(cc-bytecomp-defun delete-forward-p) ; XEmacs
(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge
; which looks at this.
(cc-bytecomp-defun c-forward-subword)
(cc-bytecomp-defun c-backward-subword)
;; Indentation / Display syntax functions
(defvar c-fix-backslashes t)
(defun c-indent-line (&optional syntax quiet ignore-point-pos)
"Indent the current line according to the syntactic context,
if `c-syntactic-indentation' is non-nil. Optional SYNTAX is the
syntactic information for the current line. Be silent about syntactic
errors if the optional argument QUIET is non-nil, even if
`c-report-syntactic-errors' is non-nil. Normally the position of
point is used to decide where the old indentation is on a lines that
is otherwise empty \(ignoring any line continuation backslash), but
that's not done if IGNORE-POINT-POS is non-nil. Returns the amount of
indentation change \(in columns)."
(let ((line-cont-backslash (save-excursion
(end-of-line)
(eq (char-before) ?\\)))
(c-fix-backslashes c-fix-backslashes)
bs-col
shift-amt)
(when (and (not ignore-point-pos)
(save-excursion
(beginning-of-line)
(looking-at (if line-cont-backslash
;; Don't use "\\s " - ^L doesn't count as WS
;; here
"\\([ \t]*\\)\\\\$"
"\\([ \t]*\\)$")))
(<= (point) (match-end 1)))
;; Delete all whitespace after point if there's only whitespace
;; on the line, so that any code that does back-to-indentation
;; or similar gets the current column in this case. If this
;; removes a line continuation backslash it'll be restored
;; at the end.
(unless c-auto-align-backslashes
;; Should try to keep the backslash alignment
;; in this case.
(save-excursion
(goto-char (match-end 0))
(setq bs-col (1- (current-column)))))
(delete-region (point) (match-end 0))
(setq c-fix-backslashes t))
(if c-syntactic-indentation
(setq c-parsing-error
(or (let ((c-parsing-error nil)
(c-syntactic-context
(or syntax
(and (boundp 'c-syntactic-context)
c-syntactic-context))))
(c-save-buffer-state (indent)
(unless c-syntactic-context
(setq c-syntactic-context (c-guess-basic-syntax)))
(setq indent (c-get-syntactic-indentation
c-syntactic-context))
(and (not (c-echo-parsing-error quiet))
c-echo-syntactic-information-p
(message "syntax: %s, indent: %d"
c-syntactic-context indent))
(setq shift-amt (- indent (current-indentation))))
(c-shift-line-indentation shift-amt)
(run-hooks 'c-special-indent-hook)
c-parsing-error)
c-parsing-error))
(let ((indent 0))
(save-excursion
(while (and (= (forward-line -1) 0)
(if (looking-at "\\s *\\\\?$")
t
(setq indent (current-indentation))
nil))))
(setq shift-amt (- indent (current-indentation)))
(c-shift-line-indentation shift-amt)))
(when (and c-fix-backslashes line-cont-backslash)
(if bs-col
(save-excursion
(indent-to bs-col)
(insert ?\\))
(when c-auto-align-backslashes
;; Realign the line continuation backslash.
(c-backslash-region (point) (point) nil t))))
shift-amt))
(defun c-newline-and-indent (&optional newline-arg)
"Insert a newline and indent the new line.
This function fixes line continuation backslashes if inside a macro,
and takes care to set the indentation before calling
`indent-according-to-mode', so that lineup functions like
`c-lineup-dont-change' works better."
;; TODO: Backslashes before eol in comments and literals aren't
;; kept intact.
(let ((c-macro-start (c-query-macro-start))
;; Avoid calling c-backslash-region from c-indent-line if it's
;; called during the newline call, which can happen due to
;; c-electric-continued-statement, for example. We also don't
;; want any backslash alignment from indent-according-to-mode.
(c-fix-backslashes nil)
has-backslash insert-backslash
start col)
(save-excursion
(beginning-of-line)
(setq start (point))
(while (and (looking-at "[ \t]*\\\\?$")
(= (forward-line -1) 0)))
(setq col (current-indentation)))
(when c-macro-start
(if (and (eolp) (eq (char-before) ?\\))
(setq insert-backslash t
has-backslash t)
(setq has-backslash (eq (char-before (c-point 'eol)) ?\\))))
(newline newline-arg)
(indent-to col)
(when c-macro-start
(if insert-backslash
(progn
;; The backslash stayed on the previous line. Insert one
;; before calling c-backslash-region, so that
;; bs-col-after-end in it works better. Fixup the
;; backslashes on the newly inserted line.
(insert ?\\)
(backward-char)
(c-backslash-region (point) (point) nil t))
;; The backslash moved to the new line, if there was any. Let
;; c-backslash-region fix a backslash on the previous line,
;; and the one that might be on the new line.
;; c-auto-align-backslashes is intentionally ignored here;
;; maybe the moved backslash should be left alone if it's set,
;; but we fix both lines on the grounds that the old backslash
;; has been moved anyway and is now in a different context.
(c-backslash-region start (if has-backslash (point) start) nil t)))
(when c-syntactic-indentation
;; Reindent syntactically. The indentation done above is not
;; wasted, since c-indent-line might look at the current
;; indentation.
(let ((c-syntactic-context (c-save-buffer-state nil
(c-guess-basic-syntax))))
;; We temporarily insert another line break, so that the
;; lineup functions will see the line as empty. That makes
;; e.g. c-lineup-cpp-define more intuitive since it then
;; proceeds to the preceding line in this case.
(insert ?\n)
(delete-horizontal-space)
(setq start (- (point-max) (point)))
(unwind-protect
(progn
(backward-char)
(indent-according-to-mode))
(goto-char (- (point-max) start))
(delete-char -1)))
(when has-backslash
;; Must align the backslash again after reindentation. The
;; c-backslash-region call above can't be optimized to ignore
;; this line, since it then won't align correctly with the
;; lines below if the first line in the macro is broken.
(c-backslash-region (point) (point) nil t)))))
(defun c-show-syntactic-information (arg)
"Show syntactic information for current line.
With universal argument, inserts the analysis as a comment on that line."
(interactive "P")
(let* ((c-parsing-error nil)
(syntax (if (boundp 'c-syntactic-context)
;; Use `c-syntactic-context' in the same way as
;; `c-indent-line', to be consistent.
c-syntactic-context
(c-save-buffer-state nil
(c-guess-basic-syntax)))))
(if (not (consp arg))
(let (elem pos ols)
(message "Syntactic analysis: %s" syntax)
(unwind-protect
(progn
(while syntax
(setq elem (pop syntax))
(when (setq pos (c-langelem-pos elem))
(push (c-put-overlay pos (1+ pos)
'face 'highlight)
ols))
(when (setq pos (c-langelem-2nd-pos elem))
(push (c-put-overlay pos (1+ pos)
'face 'secondary-selection)
ols)))
(sit-for 10))
(while ols
(c-delete-overlay (pop ols)))))
(indent-for-comment)
(insert-and-inherit (format "%s" syntax))
))
(c-keep-region-active))
(defun c-syntactic-information-on-region (from to)
"Insert a comment with the syntactic analysis on every line in the region."
(interactive "*r")
(save-excursion
(save-restriction
(narrow-to-region from to)
(goto-char (point-min))
(while (not (eobp))
(c-show-syntactic-information '(0))
(forward-line)))))
;; Minor mode functions.
(defun c-update-modeline ()
(let ((fmt (format "/%s%s%s%s"
(if c-electric-flag "l" "")
(if (and c-electric-flag c-auto-newline)
"a" "")
(if c-hungry-delete-key "h" "")
(if (and
;; cc-subword might not be loaded.
(boundp 'c-subword-mode)
(symbol-value 'c-subword-mode))
"w"
"")))
(bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name)
(substring mode-name (match-beginning 1) (match-end 1))
mode-name)))
;; (setq c-submode-indicators
;; (if (> (length fmt) 1)
;; fmt))
(setq mode-name
(if (> (length fmt) 1)
(concat bare-mode-name fmt)
bare-mode-name))
(force-mode-line-update)))
(defun c-toggle-syntactic-indentation (&optional arg)
"Toggle syntactic indentation.
Optional numeric ARG, if supplied, turns on syntactic indentation when
positive, turns it off when negative, and just toggles it when zero or
left out.
When syntactic indentation is turned on (the default), the indentation
functions and the electric keys indent according to the syntactic
context keys, when applicable.
When it's turned off, the electric keys don't reindent, the indentation
functions indents every new line to the same level as the previous
nonempty line, and \\[c-indent-command] adjusts the indentation in steps
specified by `c-basic-offset'. The indentation style has no effect in
this mode, nor any of the indentation associated variables,
e.g. `c-special-indent-hook'.
This command sets the variable `c-syntactic-indentation'."
(interactive "P")
(setq c-syntactic-indentation
(c-calculate-state arg c-syntactic-indentation))
(c-keep-region-active))
(defun c-toggle-auto-newline (&optional arg)
"Toggle auto-newline feature.
Optional numeric ARG, if supplied, turns on auto-newline when
positive, turns it off when negative, and just toggles it when zero or
left out.
Turning on auto-newline automatically enables electric indentation.
When the auto-newline feature is enabled (indicated by \"/la\" on the
mode line after the mode name) newlines are automatically inserted
after special characters such as brace, comma, semi-colon, and colon."
(interactive "P")
(setq c-auto-newline
(c-calculate-state arg (and c-auto-newline c-electric-flag)))
(if c-auto-newline (setq c-electric-flag t))
(c-update-modeline)
(c-keep-region-active))
(defalias 'c-toggle-auto-state 'c-toggle-auto-newline)
(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline nil)
(defun c-toggle-hungry-state (&optional arg)
"Toggle hungry-delete-key feature.
Optional numeric ARG, if supplied, turns on hungry-delete when
positive, turns it off when negative, and just toggles it when zero or
left out.
When the hungry-delete-key feature is enabled (indicated by \"/h\" on
the mode line after the mode name) the delete key gobbles all preceding
whitespace in one fell swoop."
(interactive "P")
(setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
(c-update-modeline)
(c-keep-region-active))
(defun c-toggle-auto-hungry-state (&optional arg)
"Toggle auto-newline and hungry-delete-key features.
Optional numeric ARG, if supplied, turns on auto-newline and
hungry-delete when positive, turns them off when negative, and just
toggles them when zero or left out.
See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details."
(interactive "P")
(setq c-auto-newline (c-calculate-state arg c-auto-newline))
(setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
(c-update-modeline)
(c-keep-region-active))
(defun c-toggle-electric-state (&optional arg)
"Toggle the electric indentation feature.
Optional numeric ARG, if supplied, turns on electric indentation when
positive, turns it off when negative, and just toggles it when zero or
left out."
(interactive "P")
(setq c-electric-flag (c-calculate-state arg c-electric-flag))
(c-update-modeline)
(c-keep-region-active))
;; Electric keys
(defun c-electric-backspace (arg)
"Delete the preceding character or whitespace.
If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
line) then all preceding whitespace is consumed. If however a prefix
argument is supplied, or `c-hungry-delete-key' is nil, or point is
inside a literal then the function in the variable
`c-backspace-function' is called."
(interactive "*P")
(if (c-save-buffer-state ()
(or (not c-hungry-delete-key)
arg
(c-in-literal)))
(funcall c-backspace-function (prefix-numeric-value arg))
(c-hungry-delete-backwards)))
(defun c-hungry-delete-backwards ()
"Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character.
See also \\[c-hungry-delete-forward]."
(interactive)
(let ((here (point)))
(c-skip-ws-backward)
(if (/= (point) here)
(delete-region (point) here)
(funcall c-backspace-function 1))))
(defalias 'c-hungry-backspace 'c-hungry-delete-backwards)
(defun c-electric-delete-forward (arg)
"Delete the following character or whitespace.
If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
line) then all following whitespace is consumed. If however a prefix
argument is supplied, or `c-hungry-delete-key' is nil, or point is
inside a literal then the function in the variable `c-delete-function'
is called."
(interactive "*P")
(if (c-save-buffer-state ()
(or (not c-hungry-delete-key)
arg
(c-in-literal)))
(funcall c-delete-function (prefix-numeric-value arg))
(c-hungry-delete-forward)))
(defun c-hungry-delete-forward ()
"Delete the following character or all following whitespace
up to the next non-whitespace character.
See also \\[c-hungry-delete-backwards]."
(interactive)
(let ((here (point)))
(c-skip-ws-forward)
(if (/= (point) here)
(delete-region (point) here)
(funcall c-delete-function 1))))
;; This function is only used in XEmacs.
(defun c-electric-delete (arg)
"Deletes preceding or following character or whitespace.
This function either deletes forward as `c-electric-delete-forward' or
backward as `c-electric-backspace', depending on the configuration: If
the function `delete-forward-p' is defined and returns non-nil, it
deletes forward. Otherwise it deletes backward.
Note: This is the way in XEmacs to choose the correct action for the
\[delete] key, whichever key that means. Other flavors don't use this
function to control that."
(interactive "*P")
(if (and (fboundp 'delete-forward-p)
(delete-forward-p))
(c-electric-delete-forward arg)
(c-electric-backspace arg)))
;; This function is only used in XEmacs.
(defun c-hungry-delete ()
"Delete a non-whitespace char, or all whitespace up to the next non-whitespace char.
The direction of deletion depends on the configuration: If the
function `delete-forward-p' is defined and returns non-nil, it deletes
forward using `c-hungry-delete-forward'. Otherwise it deletes
backward using `c-hungry-backspace'.
Note: This is the way in XEmacs to choose the correct action for the
\[delete] key, whichever key that means. Other flavors don't use this
function to control that."
(interactive)
(if (and (fboundp 'delete-forward-p)
(delete-forward-p))
(c-hungry-delete-forward)
(c-hungry-delete-backwards)))
(defun c-electric-pound (arg)
"Insert a \"#\".
If `c-electric-flag' is set, handle it specially according to the variable
`c-electric-pound-behavior'. If a numeric ARG is supplied, or if point is
inside a literal or a macro, nothing special happens."
(interactive "*P")
(if (c-save-buffer-state ()
(or arg
(not c-electric-flag)
(not (memq 'alignleft c-electric-pound-behavior))
(save-excursion
(skip-chars-backward " \t")
(not (bolp)))
(save-excursion
(and (= (forward-line -1) 0)
(progn (end-of-line)
(eq (char-before) ?\\))))
(c-in-literal)))
;; do nothing special
(self-insert-command (prefix-numeric-value arg))
;; place the pound character at the left edge
(let ((pos (- (point-max) (point)))
(bolp (bolp)))
(beginning-of-line)
(delete-horizontal-space)
(insert (c-last-command-char))
(and (not bolp)
(goto-char (- (point-max) pos)))
)))
(defun c-point-syntax ()
;; Return the syntactic context of the construct at point. (This is NOT
;; nec. the same as the s.c. of the line point is on). N.B. This won't work
;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix).
(c-save-buffer-state (;; shut this up too
(c-echo-syntactic-information-p nil)
syntax)
(c-tentative-buffer-changes
;; insert a newline to isolate the construct at point for syntactic
;; analysis.
(insert-char ?\n 1)
;; In AWK (etc.) or in a macro, make sure this CR hasn't changed
;; the syntax. (There might already be an escaped NL there.)
(when (or
(save-excursion
(c-skip-ws-backward (c-point 'bopl))
(c-at-vsemi-p))
(let ((pt (point)))
(save-excursion
(backward-char)
(and (c-beginning-of-macro)
(progn (c-end-of-macro)
(< (point) pt))))))
(backward-char)
(insert-char ?\\ 1)
(forward-char))
(let ((c-syntactic-indentation-in-macros t)
(c-auto-newline-analysis t))
;; Turn on syntactic macro analysis to help with auto
;; newlines only.
(setq syntax (c-guess-basic-syntax))
nil))
syntax))
(defun c-brace-newlines (syntax)
;; A brace stands at point. SYNTAX is the syntactic context of this brace
;; (not necessarily the same as the S.C. of the line it is on). Return
;; NEWLINES, the list containing some combination of the symbols `before'
;; and `after' saying where newlines should be inserted.
(c-save-buffer-state
((syms
;; This is the list of brace syntactic symbols that can hang.
;; If any new ones are added to c-offsets-alist, they should be
;; added here as well.
;;
;; The order of this list is important; if SYNTAX has several
;; elements, the element that "wins" is the earliest in SYMS.
'(arglist-cont-nonempty ; e.g. an array literal.
class-open class-close defun-open defun-close
inline-open inline-close
brace-list-open brace-list-close
brace-list-intro brace-entry-open
block-open block-close
substatement-open statement-case-open
extern-lang-open extern-lang-close
namespace-open namespace-close
module-open module-close
composition-open composition-close
inexpr-class-open inexpr-class-close
;; `statement-cont' is here for the case with a brace
;; list opener inside a statement. C.f. CASE B.2 in
;; `c-guess-continued-construct'.
statement-cont))
;; shut this up too
(c-echo-syntactic-information-p nil)
symb-newlines) ; e.g. (substatement-open . (after))
(setq symb-newlines
;; Do not try to insert newlines around a special
;; (Pike-style) brace list.
(if (and c-special-brace-lists
(save-excursion
(c-safe (if (= (char-before) ?{)
(forward-char -1)
(c-forward-sexp -1))
(c-looking-at-special-brace-list))))
nil
;; Seek the matching entry in c-hanging-braces-alist.
(or (c-lookup-lists
syms
;; Substitute inexpr-class and class-open or
;; class-close with inexpr-class-open or
;; inexpr-class-close.
(if (assq 'inexpr-class syntax)
(cond ((assq 'class-open syntax)
'((inexpr-class-open)))
((assq 'class-close syntax)
'((inexpr-class-close)))
(t syntax))
syntax)
c-hanging-braces-alist)
'(ignore before after)))) ; Default, when not in c-h-b-l.
;; If syntax is a function symbol, then call it using the
;; defined semantics.
(if (and (not (consp (cdr symb-newlines)))
(functionp (cdr symb-newlines)))
(let ((c-syntactic-context syntax))
(funcall (cdr symb-newlines)
(car symb-newlines)
(point)))
(cdr symb-newlines))))
(defun c-try-one-liner ()
;; Point is just after a newly inserted }. If the non-whitespace
;; content of the braces is a single line of code, compact the whole
;; construct to a single line, if this line isn't too long. The Right
;; Thing is done with comments.
;;
;; Point will be left after the }, regardless of whether the clean-up is
;; done. Return NON-NIL if the clean-up happened, NIL if it didn't.
(let ((here (point))
(pos (- (point-max) (point)))
mbeg1 mend1 mbeg4 mend4
eol-col cmnt-pos cmnt-col cmnt-gap)
(when
(save-excursion
(save-restriction
;; Avoid backtracking over a very large block. The one we
;; deal with here can never be more than three lines.
(narrow-to-region (save-excursion
(forward-line -2)
(point))
(point))
(and (c-safe (c-backward-sexp))
(progn
(forward-char)
(narrow-to-region (point) (1- here)) ; innards of {.}
(looking-at
(cc-eval-when-compile
(concat
"\\(" ; (match-beginning 1)
"[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
"\\)" ; (match-end 1)
"[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS
"\\(" ; (match-beginning 4)
"[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
"\\)\\'"))))))) ; (match-end 4) at EOB.
(if (c-tentative-buffer-changes
(setq mbeg1 (match-beginning 1) mend1 (match-end 1)
mbeg4 (match-beginning 4) mend4 (match-end 4))
(backward-char) ; back over the `}'
(save-excursion
(setq cmnt-pos (and (c-backward-single-comment)
(- (point) (- mend1 mbeg1)))))
(delete-region mbeg4 mend4)
(delete-region mbeg1 mend1)
(setq eol-col (save-excursion (end-of-line) (current-column)))
;; Necessary to put the closing brace before any line
;; oriented comment to keep it syntactically significant.
;; This isn't necessary for block comments, but the result
;; looks nicer anyway.
(when cmnt-pos
(delete-char 1) ; the `}' has blundered into a comment
(goto-char cmnt-pos)
(setq cmnt-col (1+ (current-column)))
(setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}'
(c-skip-ws-backward)
(insert-char ?\} 1) ; reinsert the `}' before the comment.
(setq cmnt-gap (- cmnt-col (current-column)))
(when (zerop cmnt-gap)
(insert-char ?\ 1) ; Put a space before a bare comment.
(setq cmnt-gap 1)))
(or (null c-max-one-liner-length)
(zerop c-max-one-liner-length)
(<= eol-col c-max-one-liner-length)
;; Can we trim space before comment to make the line fit?
(and cmnt-gap
(< (- eol-col cmnt-gap) c-max-one-liner-length)
(progn (goto-char cmnt-pos)
(backward-delete-char-untabify
(- eol-col c-max-one-liner-length))
t))))
(goto-char (- (point-max) pos))))))
(defun c-electric-brace (arg)
"Insert a brace.
If `c-electric-flag' is non-nil, the brace is not inside a literal and a
numeric ARG hasn't been supplied, the command performs several electric
actions:
\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) newlines are inserted before and after the brace as
directed by the settings in `c-hanging-braces-alist'.
\(b) Any auto-newlines are indented. The original line is also
reindented unless `c-syntactic-indentation' is nil.
\(c) If auto-newline is turned on, various newline cleanups based on the
settings of `c-cleanup-list' are done."
(interactive "*P")
(let (safepos literal
;; We want to inhibit blinking the paren since this would be
;; most disruptive. We'll blink it ourselves later on.
(old-blink-paren blink-paren-function)
blink-paren-function case-fold-search)
(c-save-buffer-state ()
(setq safepos (c-safe-position (point) (c-parse-state))
literal (c-in-literal safepos)))
;; Insert the brace. Note that expand-abbrev might reindent
;; the line here if there's a preceding "else" or something.
(self-insert-command (prefix-numeric-value arg))
(when (and c-electric-flag (not literal) (not arg))
(if (not (looking-at "[ \t]*\\\\?$"))
(if c-syntactic-indentation
(indent-according-to-mode))
(let ( ;; shut this up too
(c-echo-syntactic-information-p nil)
newlines
ln-syntax br-syntax syntax) ; Syntactic context of the original line,
; of the brace itself, of the line the brace ends up on.
(c-save-buffer-state ((c-syntactic-indentation-in-macros t)
(c-auto-newline-analysis t))
(setq ln-syntax (c-guess-basic-syntax)))
(if c-syntactic-indentation
(c-indent-line ln-syntax))
(when c-auto-newline
(backward-char)
(setq br-syntax (c-point-syntax)
newlines (c-brace-newlines br-syntax))
;; Insert the BEFORE newline, if wanted, and reindent the newline.
(if (and (memq 'before newlines)
(> (current-column) (current-indentation)))
(if c-syntactic-indentation
;; Only a plain newline for now - it's indented
;; after the cleanups when the line has its final
;; appearance.
(newline)
(c-newline-and-indent)))
(forward-char)
;; `syntax' is the syntactic context of the line which ends up
;; with the brace on it.
(setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
;; Do all appropriate clean ups
(let ((here (point))
(pos (- (point-max) (point)))
mbeg mend
)
;; `}': clean up empty defun braces
(when (c-save-buffer-state ()
(and (memq 'empty-defun-braces c-cleanup-list)
(eq (c-last-command-char) ?\})
(c-intersect-lists '(defun-close class-close inline-close)
syntax)
(progn
(forward-char -1)
(c-skip-ws-backward)
(eq (char-before) ?\{))
;; make sure matching open brace isn't in a comment
(not (c-in-literal))))
(delete-region (point) (1- here))
(setq here (- (point-max) pos)))
(goto-char here)
;; `}': compact to a one-liner defun?
(save-match-data
(when
(and (eq (c-last-command-char) ?\})
(memq 'one-liner-defun c-cleanup-list)
(c-intersect-lists '(defun-close) syntax)
(c-try-one-liner))
(setq here (- (point-max) pos))))
;; `{': clean up brace-else-brace and brace-elseif-brace
(when (eq (c-last-command-char) ?\{)
(cond
((and (memq 'brace-else-brace c-cleanup-list)
(re-search-backward
(concat "}"
"\\([ \t\n]\\|\\\\\n\\)*"
"else"
"\\([ \t\n]\\|\\\\\n\\)*"
"{"
"\\=")
nil t))
(delete-region (match-beginning 0) (match-end 0))
(insert-and-inherit "} else {"))
((and (memq 'brace-elseif-brace c-cleanup-list)
(progn
(goto-char (1- here))
(setq mend (point))
(c-skip-ws-backward)
(setq mbeg (point))
(eq (char-before) ?\)))
(zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
(eq (char-after) ?\()
; (progn
; (setq tmp (point))
(re-search-backward
(concat "}"
"\\([ \t\n]\\|\\\\\n\\)*"
"else"
"\\([ \t\n]\\|\\\\\n\\)+"
"if"
"\\([ \t\n]\\|\\\\\n\\)*"
"\\=")
nil t);)
;(eq (match-end 0) tmp);
)
(delete-region mbeg mend)
(goto-char mbeg)
(insert ?\ ))))
(goto-char (- (point-max) pos))
;; Indent the line after the cleanups since it might
;; very well indent differently due to them, e.g. if
;; c-indent-one-line-block is used together with the
;; one-liner-defun cleanup.
(when c-syntactic-indentation
(c-indent-line)))
;; does a newline go after the brace?
(if (memq 'after newlines)
(c-newline-and-indent))
))))
;; blink the paren
(and (eq (c-last-command-char) ?\})
(not executing-kbd-macro)
old-blink-paren
(save-excursion
(c-save-buffer-state nil
(c-backward-syntactic-ws safepos))
(funcall old-blink-paren)))))
(defun c-electric-slash (arg)
"Insert a slash character.
If the slash is inserted immediately after the comment prefix in a c-style
comment, the comment might get closed by removing whitespace and possibly
inserting a \"*\". See the variable `c-cleanup-list'.
Indent the line as a comment, if:
1. The slash is second of a \"//\" line oriented comment introducing
token and we are on a comment-only-line, or
2. The slash is part of a \"*/\" token that closes a block oriented
comment.
If a numeric ARG is supplied, point is inside a literal, or
`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
is inhibited."
(interactive "*P")
(let ((literal (c-save-buffer-state () (c-in-literal)))
indentp
;; shut this up
(c-echo-syntactic-information-p nil))
;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or
;; `c-syntactic-indentation' set.
(when (and (not arg)
(eq literal 'c)
(memq 'comment-close-slash c-cleanup-list)
(eq (c-last-command-char) ?/)
(looking-at (concat "[ \t]*\\("
(regexp-quote comment-end) "\\)?$"))
; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
(save-excursion
(save-restriction
(narrow-to-region (point-min) (point))
(back-to-indentation)
(looking-at (concat c-current-comment-prefix "[ \t]*$")))))
(delete-region (progn (forward-line 0) (point))
(progn (end-of-line) (point)))
(insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here?
(setq indentp (and (not arg)
c-syntactic-indentation
c-electric-flag
(eq (c-last-command-char) ?/)
(eq (char-before) (if literal ?* ?/))))
(self-insert-command (prefix-numeric-value arg))
(if indentp
(indent-according-to-mode))))
(defun c-electric-star (arg)
"Insert a star character.
If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and
the star is the second character of a C style comment starter on a
comment-only-line, indent the line as a comment. If a numeric ARG is
supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
this indentation is inhibited."
(interactive "*P")
(self-insert-command (prefix-numeric-value arg))
;; if we are in a literal, or if arg is given do not reindent the
;; current line, unless this star introduces a comment-only line.
(if (c-save-buffer-state ()
(and c-syntactic-indentation
c-electric-flag
(not arg)
(eq (c-in-literal) 'c)
(eq (char-before) ?*)
(save-excursion
(forward-char -1)
(skip-chars-backward "*")
(if (eq (char-before) ?/)
(forward-char -1))
(skip-chars-backward " \t")
(bolp))))
(let (c-echo-syntactic-information-p) ; shut this up
(indent-according-to-mode))
))
(defun c-electric-semi&comma (arg)
"Insert a comma or semicolon.
If `c-electric-flag' is non-nil, point isn't inside a literal and a
numeric ARG hasn't been supplied, the command performs several electric
actions:
\(a) When the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) a newline might be inserted. See the variable
`c-hanging-semi&comma-criteria' for how newline insertion is determined.
\(b) Any auto-newlines are indented. The original line is also
reindented unless `c-syntactic-indentation' is nil.
\(c) If auto-newline is turned on, a comma following a brace list or a
semicolon following a defun might be cleaned up, depending on the
settings of `c-cleanup-list'."
(interactive "*P")
(let* (lim literal c-syntactic-context
(here (point))
;; shut this up
(c-echo-syntactic-information-p nil))
(c-save-buffer-state ()
(setq lim (c-most-enclosing-brace (c-parse-state))
literal (c-in-literal lim)))
(self-insert-command (prefix-numeric-value arg))
(if (and c-electric-flag (not literal) (not arg))
;; do all cleanups and newline insertions if c-auto-newline is on.
(if (or (not c-auto-newline)
(not (looking-at "[ \t]*\\\\?$")))
(when c-syntactic-indentation
(let ((syntax (c-guess-basic-syntax)))
(c-indent-line syntax)
;; Guard against the C hacker inserting a statement before a
;; non-compound statement in an if/while/for.
(if (eq (caar syntax) 'substatement)
(save-excursion
(if (eq 0 (forward-line))
(c-indent-line))))))
;; clean ups: list-close-comma or defun-close-semi
(let ((pos (- (point-max) (point))))
(if (c-save-buffer-state ()
(and (or (and
(eq (c-last-command-char) ?,)
(memq 'list-close-comma c-cleanup-list))
(and
(eq (c-last-command-char) ?\;)
(memq 'defun-close-semi c-cleanup-list)))
(progn
(forward-char -1)
(c-skip-ws-backward)
(eq (char-before) ?}))
;; make sure matching open brace isn't in a comment
(not (c-in-literal lim))))
(delete-region (point) here))
(goto-char (- (point-max) pos)))
;; reindent line
(when c-syntactic-indentation
(setq c-syntactic-context (c-guess-basic-syntax))
(c-indent-line c-syntactic-context))
;; check to see if a newline should be added
(let ((criteria c-hanging-semi&comma-criteria)
answer add-newline-p)
(while criteria
(setq answer (funcall (car criteria)))
;; only nil value means continue checking
(if (not answer)
(setq criteria (cdr criteria))
(setq criteria nil)
;; only 'stop specifically says do not add a newline
(setq add-newline-p (not (eq answer 'stop)))
))
(if add-newline-p
(c-newline-and-indent))
)))))
(defun c-electric-colon (arg)
"Insert a colon.
If `c-electric-flag' is non-nil, the colon is not inside a literal and a
numeric ARG hasn't been supplied, the command performs several electric
actions:
\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) newlines are inserted before and after the colon based on
the settings in `c-hanging-colons-alist'.
\(b) Any auto-newlines are indented. The original line is also
reindented unless `c-syntactic-indentation' is nil.
\(c) If auto-newline is turned on, whitespace between two colons will be