1 |
;;; cc-menus.el --- imenu support for CC Mode |
;;; cc-menus.el --- imenu support for CC Mode |
2 |
|
|
3 |
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. |
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Authors: 2000- Martin Stjernholm |
;; Authors: 1998- Martin Stjernholm |
6 |
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm |
;; 1992-1999 Barry A. Warsaw |
|
;; 1992-1997 Barry A. Warsaw |
|
7 |
;; 1987 Dave Detlefs and Stewart Clamen |
;; 1987 Dave Detlefs and Stewart Clamen |
8 |
;; 1985 Richard M. Stallman |
;; 1985 Richard M. Stallman |
9 |
;; Maintainer: bug-cc-mode@gnu.org |
;; Maintainer: bug-cc-mode@gnu.org |
38 |
(stringp byte-compile-dest-file)) |
(stringp byte-compile-dest-file)) |
39 |
(cons (file-name-directory byte-compile-dest-file) load-path) |
(cons (file-name-directory byte-compile-dest-file) load-path) |
40 |
load-path))) |
load-path))) |
41 |
(require 'cc-bytecomp))) |
(load "cc-bytecomp" nil t))) |
42 |
|
|
43 |
|
(cc-require 'cc-defs) |
44 |
|
|
45 |
;; The things referenced in imenu, which we don't require. |
;; The things referenced in imenu, which we don't require. |
46 |
(cc-bytecomp-defvar imenu-case-fold-search) |
(cc-bytecomp-defvar imenu-case-fold-search) |
47 |
(cc-bytecomp-defvar imenu-generic-expression) |
(cc-bytecomp-defvar imenu-generic-expression) |
48 |
|
(cc-bytecomp-defvar imenu-create-index-function) |
49 |
(cc-bytecomp-defun imenu-progress-message) |
(cc-bytecomp-defun imenu-progress-message) |
50 |
|
|
51 |
|
|
73 |
(nil |
(nil |
74 |
,(concat |
,(concat |
75 |
"^\\<.*" |
"^\\<.*" |
76 |
"[^a-zA-Z0-9_:<>~]" ; match any non-identifier char |
"[^" c-alnum "_:<>~]" ; match any non-identifier char |
77 |
; (note: this can be `\n') |
; (note: this can be `\n') |
78 |
"\\(" |
"\\(" |
79 |
"\\([a-zA-Z0-9_:<>~]*::\\)?" ; match an operator |
"\\([" c-alnum "_:<>~]*::\\)?" ; match an operator |
80 |
"operator\\>[ \t]*" |
"operator\\>[ \t]*" |
81 |
"\\(()\\|[^(]*\\)" ; special case for `()' operator |
"\\(()\\|[^(]*\\)" ; special case for `()' operator |
82 |
"\\)" |
"\\)" |
95 |
(nil |
(nil |
96 |
,(concat |
,(concat |
97 |
"^" |
"^" |
98 |
"\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name |
"\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name |
99 |
"[ \t]*(" ; see above, BUT |
"[ \t]*(" ; see above, BUT |
100 |
"[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start |
"[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start |
101 |
"[ \t]*[^ \t;(]" ; with an asterisk or parentheses |
"[ \t]*[^ \t;(]" ; with an asterisk or parentheses |
105 |
,(concat |
,(concat |
106 |
"^\\<" ; line MUST start with word char |
"^\\<" ; line MUST start with word char |
107 |
"[^()]*" ; no parentheses before |
"[^()]*" ; no parentheses before |
108 |
"[^a-zA-Z0-9_:<>~]" ; match any non-identifier char |
"[^" c-alnum "_:<>~]" ; match any non-identifier char |
109 |
"\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name |
"\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name |
110 |
"\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list |
"\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list |
111 |
"\\([ \t\n]\\|\\\\\n\\)*\\([^ \t\n(*][^)]*\\)?)" ; must not start |
"\\([ \t\n]\\|\\\\\n\\)*\\([^ \t\n(*][^)]*\\)?)" ; must not start |
112 |
"\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ; with an asterisk or parentheses |
"\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ; with an asterisk or parentheses |
119 |
`((nil |
`((nil |
120 |
,(concat |
,(concat |
121 |
"^\\<.*" ; line MUST start with word char |
"^\\<.*" ; line MUST start with word char |
122 |
"[^a-zA-Z0-9_]" ; match any non-identifier char |
"[^" c-alnum "_]" ; match any non-identifier char |
123 |
"\\([a-zA-Z_][a-zA-Z0-9_]*\\)" ; match function name |
"\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name |
124 |
"[ \t]*" ; whitespace before macro name |
"[ \t]*" ; whitespace before macro name |
125 |
cc-imenu-c-prototype-macro-regexp |
cc-imenu-c-prototype-macro-regexp |
126 |
"[ \t]*(" ; ws followed by first paren. |
"[ \t]*(" ; ws followed by first paren. |
127 |
"[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above |
"[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above |
128 |
) 1))) |
) 1))) |
129 |
;; Class definitions |
;; Class definitions |
130 |
("Class" |
("Class" |
131 |
,(concat |
,(concat |
132 |
"^" ; beginning of line is required |
"^" ; beginning of line is required |
133 |
"\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' |
"\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' |
134 |
"\\(class\\|struct\\)[ \t]+" |
"\\(class\\|struct\\)[ \t]+" |
135 |
"\\(" ; the string we want to get |
"\\(" ; the string we want to get |
136 |
"[a-zA-Z0-9_]+" ; class name |
"[" c-alnum "_]+" ; class name |
137 |
"\\(<[^>]+>\\)?" ; possibly explicitly specialized |
"\\(<[^>]+>\\)?" ; possibly explicitly specialized |
138 |
"\\)" |
"\\)" |
139 |
"\\([ \t\n]\\|\\\\\n\\)*[:{]" |
"\\([ \t\n]\\|\\\\\n\\)*[:{]" |
140 |
) 3)) |
) 3)) |
141 |
"Imenu generic expression for C++ mode. See `imenu-generic-expression'.") |
"Imenu generic expression for C++ mode. See `imenu-generic-expression'.") |
142 |
|
|
143 |
(defvar cc-imenu-c-generic-expression |
(defvar cc-imenu-c-generic-expression |
144 |
cc-imenu-c++-generic-expression |
cc-imenu-c++-generic-expression |
145 |
"Imenu generic expression for C mode. See `imenu-generic-expression'.") |
"Imenu generic expression for C mode. See `imenu-generic-expression'.") |
147 |
(defvar cc-imenu-java-generic-expression |
(defvar cc-imenu-java-generic-expression |
148 |
`((nil |
`((nil |
149 |
,(concat |
,(concat |
150 |
"^\\([ \t]\\)*" |
"[" c-alpha "_][\]\[." c-alnum "_]+[ \t\n\r]+" ; type spec |
151 |
"\\([.A-Za-z0-9_-]+[ \t]+\\)?" ; type specs; there can be |
"\\([" c-alpha "_][" c-alnum "_]+\\)" ; method name |
152 |
"\\([.A-Za-z0-9_-]+[ \t]+\\)?" ; more than 3 tokens, right? |
"[ \t\n\r]*" |
153 |
"\\([.A-Za-z0-9_-]+[ \t]*[[]?[]]?\\)" |
;; An argument list that is either empty or contains at least |
154 |
"\\([ \t]\\)" |
;; two identifiers with only space between them. This avoids |
155 |
"\\([A-Za-z0-9_-]+\\)" ; the string we want to get |
;; matching e.g. "else if (foo)". |
156 |
"\\([ \t]*\\)+(" |
(concat "([ \t\n\r]*" |
157 |
"[][a-zA-Z,_1-9\n \t]*" ; arguments |
"\\([\]\[.," c-alnum "_]+" |
158 |
")[ \t]*" |
"[ \t\n\r]+" |
159 |
; "[^;(]" |
"[\]\[.," c-alnum "_]" |
160 |
"[,a-zA-Z_1-9\n \t]*{" |
"[\]\[.," c-alnum "_ \t\n\r]*" |
161 |
) 6)) |
"\\)?)") |
162 |
|
"[.," c-alnum "_ \t\n\r]*" |
163 |
|
"{" |
164 |
|
) 1)) |
165 |
"Imenu generic expression for Java mode. See `imenu-generic-expression'.") |
"Imenu generic expression for Java mode. See `imenu-generic-expression'.") |
166 |
|
|
167 |
;; *Warning for cc-mode developers* |
;; *Warning for cc-mode developers* |
168 |
;; |
;; |
169 |
;; `cc-imenu-objc-generic-expression' elements depend on |
;; `cc-imenu-objc-generic-expression' elements depend on |
170 |
;; `cc-imenu-c++-generic-expression'. So if you change this |
;; `cc-imenu-c++-generic-expression'. So if you change this |
174 |
;; order to know where the each regexp *group \\(foobar\\)* elements |
;; order to know where the each regexp *group \\(foobar\\)* elements |
175 |
;; are started. |
;; are started. |
176 |
;; |
;; |
177 |
;; *-index variables are initialized during `cc-imenu-objc-generic-expression' |
;; *-index variables are initialized during `cc-imenu-objc-generic-expression' |
178 |
;; being initialized. |
;; being initialized. |
179 |
;; |
;; |
180 |
|
|
181 |
;; Internal variables |
;; Internal variables |
184 |
(defvar cc-imenu-objc-generic-expression-proto-index nil) |
(defvar cc-imenu-objc-generic-expression-proto-index nil) |
185 |
(defvar cc-imenu-objc-generic-expression-objc-base-index nil) |
(defvar cc-imenu-objc-generic-expression-objc-base-index nil) |
186 |
|
|
187 |
(defvar cc-imenu-objc-generic-expression |
(defvar cc-imenu-objc-generic-expression |
188 |
(concat |
(concat |
189 |
;; |
;; |
190 |
;; For C |
;; For C |
191 |
;; |
;; |
192 |
;; > Special case to match a line like `main() {}' |
;; > Special case to match a line like `main() {}' |
193 |
;; > e.g. no return type, not even on the previous line. |
;; > e.g. no return type, not even on the previous line. |
197 |
"\\|" |
"\\|" |
198 |
;; > General function name regexp |
;; > General function name regexp |
199 |
;; Pick a token by (match-string 3) |
;; Pick a token by (match-string 3) |
200 |
(car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 2 |
(car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 5 |
201 |
(prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "") |
(prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "") |
202 |
;; > Special case for definitions using phony prototype macros like: |
;; > Special case for definitions using phony prototype macros like: |
203 |
;; > `int main _PROTO( (int argc,char *argv[]) )'. |
;; > `int main _PROTO( (int argc,char *argv[]) )'. |
204 |
;; Pick a token by (match-string 5) |
;; Pick a token by (match-string 8) |
205 |
(if cc-imenu-c-prototype-macro-regexp |
(if cc-imenu-c-prototype-macro-regexp |
206 |
(concat |
(concat |
207 |
"\\|" |
"\\|" |
208 |
(car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1 |
(car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1 |
209 |
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 6) "") |
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "") |
210 |
) |
) |
211 |
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 5) "") |
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 8) "") |
212 |
"") ; -> index += 0 |
"") ; -> index += 0 |
213 |
(prog2 (setq cc-imenu-objc-generic-expression-proto-index 5) "") |
(prog2 (setq cc-imenu-objc-generic-expression-proto-index 8) "") |
214 |
;; |
;; |
215 |
;; For Objective-C |
;; For Objective-C |
216 |
;; Pick a token by (match-string 5 or 6) |
;; Pick a token by (match-string 8 or 9) |
217 |
;; |
;; |
218 |
"\\|\\(" |
"\\|\\(" |
219 |
"^[-+][:a-zA-Z0-9()*_<>\n\t ]*[;{]" ; Methods |
"^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods |
220 |
"\\|" |
"\\|" |
221 |
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*:" |
"^@interface[\t ]+[" c-alnum "_]+[\t ]*:" |
222 |
"\\|" |
"\\|" |
223 |
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" |
"^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" |
224 |
"\\|" |
"\\|" |
225 |
;; For NSObject, NSProxy and Object... They don't have super class. |
;; For NSObject, NSProxy and Object... They don't have super class. |
226 |
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*.*$" |
"^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$" |
227 |
"\\|" |
"\\|" |
228 |
"^@implementation[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" |
"^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" |
229 |
"\\|" |
"\\|" |
230 |
"^@implementation[\t ]+[a-zA-Z0-9_]+" |
"^@implementation[\t ]+[" c-alnum "_]+" |
231 |
"\\|" |
"\\|" |
232 |
"^@protocol[\t ]+[a-zA-Z0-9_]+" "\\)") |
"^@protocol[\t ]+[" c-alnum "_]+" "\\)") |
233 |
"Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") |
"Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") |
234 |
|
|
235 |
|
|
236 |
;; Imenu support for objective-c uses functions. |
;; Imenu support for objective-c uses functions. |
237 |
(defsubst cc-imenu-objc-method-to-selector (method) |
(defsubst cc-imenu-objc-method-to-selector (method) |
238 |
"Return the objc selector style string of METHOD. |
"Return the objc selector style string of METHOD. |
239 |
Example: |
Example: |
240 |
- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ |
- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ |
241 |
=> |
=> |
242 |
-perform:withObject:withObject:withObject: /* selector */" |
-perform:withObject:withObject:withObject: /* selector */" |
243 |
|
;; This function does not do any hidden buffer changes. |
244 |
(let ((return "") ; String to be returned |
(let ((return "") ; String to be returned |
245 |
(p 0) ; Current scanning position in METHOD |
(p 0) ; Current scanning position in METHOD |
246 |
(pmax (length method)) ; |
(pmax (length method)) ; |
247 |
char ; Current scanning target |
char ; Current scanning target |
248 |
(betweenparen 0) ; CHAR is in parentheses. |
(betweenparen 0) ; CHAR is in parentheses. |
249 |
argreq ; An argument is required. |
argreq ; An argument is required. |
259 |
(and (<= ?A char) (<= char ?Z)) |
(and (<= ?A char) (<= char ?Z)) |
260 |
(and (<= ?0 char) (<= char ?9)) |
(and (<= ?0 char) (<= char ?9)) |
261 |
(= ?_ char))) |
(= ?_ char))) |
262 |
(if argreq |
(if argreq |
263 |
(setq inargvar t |
(setq inargvar t |
264 |
argreq nil) |
argreq nil) |
265 |
(setq return (concat return (char-to-string char))))) |
(setq return (concat return (char-to-string char))))) |
266 |
;; Or a white space? |
;; Or a white space? |
267 |
((and inargvar (or (eq ?\ char) (eq ?\n char)) |
((and inargvar (or (eq ?\ char) (eq ?\n char)) |
268 |
(setq inargvar nil))) |
(setq inargvar nil))) |
269 |
;; Or a method separator? |
;; Or a method separator? |
270 |
;; If a method separator, the next token will be an argument variable. |
;; If a method separator, the next token will be an argument variable. |
271 |
((eq ?: char) |
((eq ?: char) |
272 |
(setq argreq t |
(setq argreq t |
273 |
return (concat return (char-to-string char)))) |
return (concat return (char-to-string char)))) |
274 |
;; Or an open parentheses? |
;; Or an open parentheses? |
275 |
((eq ?\( char) |
((eq ?\( char) |
281 |
|
|
282 |
(defun cc-imenu-objc-remove-white-space (str) |
(defun cc-imenu-objc-remove-white-space (str) |
283 |
"Remove all spaces and tabs from STR." |
"Remove all spaces and tabs from STR." |
284 |
|
;; This function does not do any hidden buffer changes. |
285 |
(let ((return "") |
(let ((return "") |
286 |
(p 0) |
(p 0) |
287 |
(max (length str)) |
(max (length str)) |
288 |
char) |
char) |
289 |
(while (< p max) |
(while (< p max) |
290 |
(setq char (aref str p)) |
(setq char (aref str p)) |
296 |
|
|
297 |
(defun cc-imenu-objc-function () |
(defun cc-imenu-objc-function () |
298 |
"imenu supports for objc-mode." |
"imenu supports for objc-mode." |
299 |
|
;; This function does not do any hidden buffer changes. |
300 |
(let (methodlist |
(let (methodlist |
301 |
clist |
clist |
302 |
;; |
;; |
303 |
;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants. |
;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants. |
304 |
;; |
;; |
305 |
;; *Warning for developers* |
;; *Warning for developers* |
306 |
;; These constants depend on `cc-imenu-c++-generic-expression'. |
;; These constants depend on `cc-imenu-c++-generic-expression'. |
307 |
;; |
;; |
308 |
(OBJC cc-imenu-objc-generic-expression-objc-base-index) |
(OBJC cc-imenu-objc-generic-expression-objc-base-index) |
318 |
toplist |
toplist |
319 |
stupid |
stupid |
320 |
str |
str |
321 |
str2 |
str2 |
322 |
(intflen (length "@interface")) |
(intflen (length "@interface")) |
323 |
(implen (length "@implementation")) |
(implen (length "@implementation")) |
324 |
(prtlen (length "@protocol")) |
(prtlen (length "@protocol")) |
325 |
(func |
(func |
326 |
;; |
;; |
327 |
;; Does this emacs has buffer-substring-no-properties? |
;; Does this emacs has buffer-substring-no-properties? |
328 |
;; |
;; |
329 |
(if (fboundp 'buffer-substring-no-properties) |
(if (fboundp 'buffer-substring-no-properties) |
330 |
'buffer-substring-no-properties |
'buffer-substring-no-properties |
334 |
;; |
;; |
335 |
(while (re-search-backward cc-imenu-objc-generic-expression nil t) |
(while (re-search-backward cc-imenu-objc-generic-expression nil t) |
336 |
(imenu-progress-message stupid) |
(imenu-progress-message stupid) |
337 |
(setq langnum (if (match-beginning OBJC) |
(setq langnum (if (match-beginning OBJC) |
338 |
OBJC |
OBJC |
339 |
(cond |
(cond |
340 |
((match-beginning Cproto) Cproto) |
((match-beginning Cproto) Cproto) |
342 |
((match-beginning Cnoreturn) Cnoreturn)))) |
((match-beginning Cnoreturn) Cnoreturn)))) |
343 |
(setq str (funcall func (match-beginning langnum) (match-end langnum))) |
(setq str (funcall func (match-beginning langnum) (match-end langnum))) |
344 |
;; |
;; |
345 |
(cond |
(cond |
346 |
;; |
;; |
347 |
;; C |
;; C |
348 |
;; |
;; |
350 |
(setq clist (cons (cons str (match-beginning langnum)) clist))) |
(setq clist (cons (cons str (match-beginning langnum)) clist))) |
351 |
;; |
;; |
352 |
;; ObjC |
;; ObjC |
353 |
;; |
;; |
354 |
;; An instance Method |
;; An instance Method |
355 |
((eq (aref str 0) ?-) |
((eq (aref str 0) ?-) |
356 |
(setq str (concat "-" (cc-imenu-objc-method-to-selector str))) |
(setq str (concat "-" (cc-imenu-objc-method-to-selector str))) |
363 |
(setq methodlist (cons (cons str |
(setq methodlist (cons (cons str |
364 |
(match-beginning langnum)) |
(match-beginning langnum)) |
365 |
methodlist))) |
methodlist))) |
366 |
;; Interface or implementation or protocol |
;; Interface or implementation or protocol |
367 |
((eq (aref str 0) ?@) |
((eq (aref str 0) ?@) |
368 |
(setq classcount (1+ classcount)) |
(setq classcount (1+ classcount)) |
369 |
(cond |
(cond |
370 |
((and (> (length str) implen) |
((and (> (length str) implen) |
371 |
(string= (substring str 0 implen) "@implementation")) |
(string= (substring str 0 implen) "@implementation")) |
372 |
(setq str (substring str implen) |
(setq str (substring str implen) |
384 |
(setq toplist (cons nil (cons (cons str |
(setq toplist (cons nil (cons (cons str |
385 |
methodlist) toplist)) |
methodlist) toplist)) |
386 |
methodlist nil)))) |
methodlist nil)))) |
387 |
;; |
;; |
388 |
(imenu-progress-message stupid 100) |
(imenu-progress-message stupid 100) |
389 |
(if (eq (car toplist) nil) |
(if (eq (car toplist) nil) |
390 |
(setq toplist (cdr toplist))) |
(setq toplist (cdr toplist))) |
403 |
(setq last (cdr last))) |
(setq last (cdr last))) |
404 |
(setcdr last clist)))) |
(setcdr last clist)))) |
405 |
;; Add C lang tokens as a sub menu |
;; Add C lang tokens as a sub menu |
406 |
(setq toplist (cons (cons "C" clist) toplist))) |
(if clist |
407 |
|
(setq toplist (cons (cons "C" clist) toplist)))) |
408 |
;; |
;; |
409 |
toplist |
toplist |
410 |
)) |
)) |
413 |
; ()) |
; ()) |
414 |
; FIXME: Please contribute one! |
; FIXME: Please contribute one! |
415 |
|
|
416 |
(defun cc-imenu-init (mode-generic-expression) |
(defun cc-imenu-init (mode-generic-expression |
417 |
|
&optional mode-create-index-function) |
418 |
|
;; This function does not do any hidden buffer changes. |
419 |
(setq imenu-generic-expression mode-generic-expression |
(setq imenu-generic-expression mode-generic-expression |
420 |
imenu-case-fold-search nil)) |
imenu-case-fold-search nil) |
421 |
|
(when mode-create-index-function |
422 |
|
(setq imenu-create-index-function mode-create-index-function))) |
423 |
|
|
424 |
|
|
425 |
(cc-provide 'cc-menus) |
(cc-provide 'cc-menus) |