Commit | Line | Data |
---|---|---|
785eecbb RS |
1 | ;;; cc-menus.el --- imenu support for CC Mode |
2 | ||
ba318903 | 3 | ;; Copyright (C) 1985, 1987, 1992-2014 Free Software Foundation, Inc. |
785eecbb | 4 | |
d9e94c22 MS |
5 | ;; Authors: 1998- Martin Stjernholm |
6 | ;; 1992-1999 Barry A. Warsaw | |
5858f68c GM |
7 | ;; 1987 Dave Detlefs |
8 | ;; 1987 Stewart Clamen | |
785eecbb | 9 | ;; 1985 Richard M. Stallman |
0ec8351b | 10 | ;; Maintainer: bug-cc-mode@gnu.org |
785eecbb | 11 | ;; Created: 22-Apr-1997 (split from cc-mode.el) |
bd78fa1d CY |
12 | ;; Keywords: c languages |
13 | ;; Package: cc-mode | |
785eecbb RS |
14 | |
15 | ;; This file is part of GNU Emacs. | |
16 | ||
b1fc2b50 | 17 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
785eecbb | 18 | ;; it under the terms of the GNU General Public License as published by |
b1fc2b50 GM |
19 | ;; the Free Software Foundation, either version 3 of the License, or |
20 | ;; (at your option) any later version. | |
785eecbb RS |
21 | |
22 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
23 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | ;; GNU General Public License for more details. | |
26 | ||
27 | ;; You should have received a copy of the GNU General Public License | |
b1fc2b50 | 28 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
785eecbb | 29 | |
3afbc435 PJ |
30 | ;;; Commentary: |
31 | ||
32 | ;;; Code: | |
33 | ||
0ec8351b | 34 | (eval-when-compile |
51f606de | 35 | (let ((load-path |
130c507e GM |
36 | (if (and (boundp 'byte-compile-dest-file) |
37 | (stringp byte-compile-dest-file)) | |
38 | (cons (file-name-directory byte-compile-dest-file) load-path) | |
51f606de | 39 | load-path))) |
d9e94c22 MS |
40 | (load "cc-bytecomp" nil t))) |
41 | ||
42 | (cc-require 'cc-defs) | |
51f606de | 43 | |
130c507e GM |
44 | ;; The things referenced in imenu, which we don't require. |
45 | (cc-bytecomp-defvar imenu-case-fold-search) | |
46 | (cc-bytecomp-defvar imenu-generic-expression) | |
d9e94c22 | 47 | (cc-bytecomp-defvar imenu-create-index-function) |
0ec8351b | 48 | |
785eecbb RS |
49 | \f |
50 | ;; imenu integration | |
05896d77 KH |
51 | (defvar cc-imenu-c-prototype-macro-regexp nil |
52 | "RE matching macro names used to conditionally specify function prototypes. | |
53 | ||
54 | For example: | |
55 | ||
56 | #ifdef __STDC__ | |
57 | #define _P(x) x | |
58 | #else | |
59 | #define _P(x) /*nothing*/ | |
60 | #endif | |
61 | ||
62 | int main _P( (int argc, char *argv[]) ) | |
63 | ||
64 | A sample value might look like: `\\(_P\\|_PROTO\\)'.") | |
65 | ||
57f845ee AM |
66 | ;; *Warning for cc-mode developers* |
67 | ;; | |
68 | ;; `cc-imenu-objc-generic-expression' elements depend on | |
69 | ;; `cc-imenu-c++-generic-expression'. So if you change this | |
70 | ;; expression, you need to change following variables, | |
71 | ;; `cc-imenu-objc-generic-expression-*-index', | |
72 | ;; too. `cc-imenu-objc-function' uses these *-index variables, in | |
73 | ;; order to know where the each regexp *group \\(foobar\\)* elements | |
74 | ;; are started. | |
75 | ;; | |
76 | ;; *-index variables are initialized during `cc-imenu-objc-generic-expression' | |
77 | ;; being initialized. | |
78 | ;; | |
79 | ||
785eecbb | 80 | (defvar cc-imenu-c++-generic-expression |
51f606de | 81 | `( |
05896d77 | 82 | ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' |
e1dbe924 | 83 | ;; will be incorrectly recognized as function `new ()' because the regexps |
05896d77 KH |
84 | ;; work by backtracking from the end of the definition. |
85 | (nil | |
51f606de | 86 | ,(concat |
05896d77 | 87 | "^\\<.*" |
d9e94c22 | 88 | "[^" c-alnum "_:<>~]" ; match any non-identifier char |
05896d77 KH |
89 | ; (note: this can be `\n') |
90 | "\\(" | |
d9e94c22 | 91 | "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator |
05896d77 KH |
92 | "operator\\>[ \t]*" |
93 | "\\(()\\|[^(]*\\)" ; special case for `()' operator | |
94 | "\\)" | |
95 | ||
96 | "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, | |
97 | ; require something other than | |
98 | ; a `;' after the (...) to | |
99 | ; avoid prototypes. Can't | |
100 | ; catch cases with () inside | |
101 | ; the parentheses surrounding | |
102 | ; the parameters. e.g.: | |
103 | ; `int foo(int a=bar()) {...}' | |
51f606de | 104 | ) 1) |
05896d77 KH |
105 | ;; Special case to match a line like `main() {}' |
106 | ;; e.g. no return type, not even on the previous line. | |
107 | (nil | |
51f606de | 108 | ,(concat |
05896d77 | 109 | "^" |
d9e94c22 | 110 | "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name |
f1063b2f RS |
111 | "[ \t]*(" ; see above, BUT |
112 | "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start | |
113 | "[ \t]*[^ \t;(]" ; with an asterisk or parentheses | |
51f606de | 114 | ) 1) |
8729df59 KH |
115 | ;; General function name regexp |
116 | (nil | |
51f606de GM |
117 | ,(concat |
118 | "^\\<" ; line MUST start with word char | |
41a962dd GM |
119 | ;; \n added to prevent overflow in regexp matcher. |
120 | ;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2007-02/msg00021.html | |
121 | "[^()\n]*" ; no parentheses before | |
d9e94c22 MS |
122 | "[^" c-alnum "_:<>~]" ; match any non-identifier char |
123 | "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name | |
a66cd3ee | 124 | "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list |
3fc9b218 AM |
125 | "\\([ \t\n]\\|\\\\\n\\)*" ; must not start |
126 | "\\([^ \t\n(*]" ; with an asterisk or parentheses | |
127 | "[^()]*\\(([^()]*)[^()]*\\)*" ; Maybe function pointer arguments | |
128 | "\\)?)" | |
129 | "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" | |
51f606de | 130 | ) 1) |
05896d77 KH |
131 | ;; Special case for definitions using phony prototype macros like: |
132 | ;; `int main _PROTO( (int argc,char *argv[]) )'. | |
133 | ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. | |
134 | ;; Only supported in c-code, so no `:<>~' chars in function name! | |
51f606de GM |
135 | ,@(if cc-imenu-c-prototype-macro-regexp |
136 | `((nil | |
137 | ,(concat | |
05896d77 | 138 | "^\\<.*" ; line MUST start with word char |
d9e94c22 MS |
139 | "[^" c-alnum "_]" ; match any non-identifier char |
140 | "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name | |
05896d77 KH |
141 | "[ \t]*" ; whitespace before macro name |
142 | cc-imenu-c-prototype-macro-regexp | |
143 | "[ \t]*(" ; ws followed by first paren. | |
8729df59 | 144 | "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above |
51f606de | 145 | ) 1))) |
05896d77 | 146 | ;; Class definitions |
304515db | 147 | ("Class" |
51f606de | 148 | ,(concat |
05896d77 KH |
149 | "^" ; beginning of line is required |
150 | "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' | |
130c507e | 151 | "\\(class\\|struct\\)[ \t]+" |
0ec8351b | 152 | "\\(" ; the string we want to get |
d9e94c22 | 153 | "[" c-alnum "_]+" ; class name |
130c507e | 154 | "\\(<[^>]+>\\)?" ; possibly explicitly specialized |
0ec8351b | 155 | "\\)" |
a66cd3ee | 156 | "\\([ \t\n]\\|\\\\\n\\)*[:{]" |
130c507e | 157 | ) 3)) |
785eecbb | 158 | "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") |
304515db | 159 | |
785eecbb RS |
160 | (defvar cc-imenu-c-generic-expression |
161 | cc-imenu-c++-generic-expression | |
162 | "Imenu generic expression for C mode. See `imenu-generic-expression'.") | |
163 | ||
85c9ab64 AM |
164 | |
165 | ;; Auxiliary regexps for Java try to match their trailing whitespace where | |
166 | ;; appropriate, but _not_ starting whitespace. | |
167 | ||
168 | (defconst cc-imenu-java-ellipsis-regexp | |
169 | (concat | |
170 | "\\.\\{3\\}" | |
171 | "[ \t\n\r]*")) | |
172 | ||
173 | (defun cc-imenu-java-build-type-args-regex (depth) | |
174 | "Builds regexp for type arguments list with DEPTH allowed | |
175 | nested angle brackets constructs." | |
176 | (if (> depth 0) | |
177 | (concat "<" | |
178 | "[][.," c-alnum "_? \t\n\r]+" | |
179 | (if (> depth 1) | |
180 | "\\(") | |
181 | (cc-imenu-java-build-type-args-regex (1- depth)) | |
182 | (if (> depth 1) | |
183 | (concat "[][.," c-alnum "_? \t\n\r]*" | |
184 | "\\)*")) | |
185 | ">"))) | |
186 | ||
187 | (defconst cc-imenu-java-type-spec-regexp | |
188 | (concat | |
189 | ;; zero or more identifiers followed by a dot | |
190 | "\\(" | |
191 | "[" c-alpha "_][" c-alnum "_]*\\." | |
192 | "\\)*" | |
193 | ;; a single mandatory identifier without a dot | |
194 | "[" c-alpha "_][" c-alnum "_]*" | |
195 | ;; then choice: | |
196 | "\\(" | |
197 | ;; (option 1) type arguments list which _may_ be followed with brackets | |
198 | ;; and/or spaces, then optional variable arity | |
199 | "[ \t\n\r]*" | |
200 | (cc-imenu-java-build-type-args-regex 3) | |
201 | "[][ \t\n\r]*" | |
202 | "\\(" cc-imenu-java-ellipsis-regexp "\\)?" | |
203 | "\\|" | |
204 | ;; (option 2) just brackets and/or spaces (there should be at least one), | |
205 | ;; then optional variable arity | |
206 | "[][ \t\n\r]+" | |
207 | "\\(" cc-imenu-java-ellipsis-regexp "\\)?" | |
208 | "\\|" | |
209 | ;; (option 3) just variable arity | |
210 | cc-imenu-java-ellipsis-regexp | |
211 | "\\)")) | |
212 | ||
213 | (defconst cc-imenu-java-comment-regexp | |
214 | (concat | |
215 | "/" | |
216 | "\\(" | |
217 | ;; a traditional comment | |
218 | "\\*" | |
219 | "\\(" | |
220 | "[^*]" | |
221 | "\\|" | |
222 | "\\*+[^/*]" | |
223 | "\\)*" | |
224 | "\\*+/" | |
225 | "\\|" | |
226 | ;; an end-of-line comment | |
227 | "/[^\n\r]*[\n\r]" | |
228 | "\\)" | |
229 | "[ \t\n\r]*" | |
230 | )) | |
231 | ||
232 | ;; Comments are allowed before the argument, after any of the | |
233 | ;; modifiers and after the identifier. | |
234 | (defconst cc-imenu-java-method-arg-regexp | |
235 | (concat | |
236 | "\\(" cc-imenu-java-comment-regexp "\\)*" | |
237 | ;; optional modifiers | |
238 | "\\(" | |
239 | ;; a modifier is either an annotation or "final" | |
240 | "\\(" | |
241 | "@[" c-alpha "_]" | |
242 | "[" c-alnum "._]*" | |
243 | ;; TODO support element-value pairs! | |
244 | "\\|" | |
245 | "final" | |
246 | "\\)" | |
247 | ;; a modifier ends with comments and/or ws | |
248 | "\\(" | |
249 | "\\(" cc-imenu-java-comment-regexp "\\)+" | |
250 | "\\|" | |
251 | "[ \t\n\r]+" | |
252 | "\\(" cc-imenu-java-comment-regexp "\\)*" | |
253 | "\\)" | |
254 | "\\)*" | |
255 | ;; type spec | |
256 | cc-imenu-java-type-spec-regexp | |
257 | ;; identifier | |
258 | "[" c-alpha "_]" | |
259 | "[" c-alnum "_]*" | |
260 | ;; optional comments and/or ws | |
261 | "[ \t\n\r]*" | |
262 | "\\(" cc-imenu-java-comment-regexp "\\)*" | |
263 | )) | |
264 | ||
265 | (defconst cc-imenu-java-generic-expression | |
51f606de GM |
266 | `((nil |
267 | ,(concat | |
85c9ab64 AM |
268 | cc-imenu-java-type-spec-regexp |
269 | "\\(" ; method name which gets captured | |
270 | ; into index | |
271 | "[" c-alpha "_]" | |
272 | "[" c-alnum "_]*" | |
273 | "\\)" | |
d9e94c22 | 274 | "[ \t\n\r]*" |
85c9ab64 AM |
275 | ;; An argument list that contains zero or more arguments. |
276 | (concat | |
277 | "(" | |
278 | "[ \t\n\r]*" | |
279 | "\\(" | |
280 | "\\(" cc-imenu-java-method-arg-regexp ",[ \t\n\r]*\\)*" | |
281 | cc-imenu-java-method-arg-regexp | |
282 | "\\)?" | |
283 | ")" | |
284 | "[.,_" c-alnum " \t\n\r]*" ; throws etc. | |
285 | "{" | |
286 | )) 7)) | |
57f845ee | 287 | "Imenu generic expression for Java mode. See `imenu-generic-expression'.") |
f1063b2f | 288 | |
85c9ab64 | 289 | |
f1063b2f RS |
290 | ;; Internal variables |
291 | (defvar cc-imenu-objc-generic-expression-noreturn-index nil) | |
292 | (defvar cc-imenu-objc-generic-expression-general-func-index nil) | |
293 | (defvar cc-imenu-objc-generic-expression-proto-index nil) | |
294 | (defvar cc-imenu-objc-generic-expression-objc-base-index nil) | |
295 | ||
304515db GM |
296 | (defvar cc-imenu-objc-generic-expression |
297 | (concat | |
8729df59 | 298 | ;; |
304515db | 299 | ;; For C |
8729df59 KH |
300 | ;; |
301 | ;; > Special case to match a line like `main() {}' | |
302 | ;; > e.g. no return type, not even on the previous line. | |
303 | ;; Pick a token by (match-string 1) | |
f1063b2f RS |
304 | (car (cdr (nth 1 cc-imenu-c++-generic-expression))) ; -> index += 2 |
305 | (prog2 (setq cc-imenu-objc-generic-expression-noreturn-index 1) "") | |
8729df59 KH |
306 | "\\|" |
307 | ;; > General function name regexp | |
f1063b2f | 308 | ;; Pick a token by (match-string 3) |
57f845ee | 309 | (car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 6 |
f1063b2f | 310 | (prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "") |
8729df59 KH |
311 | ;; > Special case for definitions using phony prototype macros like: |
312 | ;; > `int main _PROTO( (int argc,char *argv[]) )'. | |
d9e94c22 | 313 | ;; Pick a token by (match-string 8) |
8729df59 | 314 | (if cc-imenu-c-prototype-macro-regexp |
304515db | 315 | (concat |
8729df59 | 316 | "\\|" |
f1063b2f | 317 | (car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1 |
57f845ee | 318 | (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 10) "") |
f1063b2f | 319 | ) |
57f845ee | 320 | (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "") |
f1063b2f | 321 | "") ; -> index += 0 |
57f845ee | 322 | (prog2 (setq cc-imenu-objc-generic-expression-proto-index 9) "") |
8729df59 | 323 | ;; |
05896d77 | 324 | ;; For Objective-C |
d9e94c22 | 325 | ;; Pick a token by (match-string 8 or 9) |
8729df59 | 326 | ;; |
304515db | 327 | "\\|\\(" |
d9e94c22 | 328 | "^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods |
304515db | 329 | "\\|" |
d9e94c22 | 330 | "^@interface[\t ]+[" c-alnum "_]+[\t ]*:" |
304515db | 331 | "\\|" |
d9e94c22 | 332 | "^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" |
304515db | 333 | "\\|" |
05896d77 | 334 | ;; For NSObject, NSProxy and Object... They don't have super class. |
d9e94c22 | 335 | "^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$" |
304515db | 336 | "\\|" |
d9e94c22 | 337 | "^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" |
304515db | 338 | "\\|" |
d9e94c22 | 339 | "^@implementation[\t ]+[" c-alnum "_]+" |
304515db | 340 | "\\|" |
d9e94c22 | 341 | "^@protocol[\t ]+[" c-alnum "_]+" "\\)") |
05896d77 KH |
342 | "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") |
343 | ||
344 | ||
345 | ;; Imenu support for objective-c uses functions. | |
346 | (defsubst cc-imenu-objc-method-to-selector (method) | |
347 | "Return the objc selector style string of METHOD. | |
304515db | 348 | Example: |
05896d77 KH |
349 | - perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ |
350 | => | |
351 | -perform:withObject:withObject:withObject: /* selector */" | |
352 | (let ((return "") ; String to be returned | |
304515db GM |
353 | (p 0) ; Current scanning position in METHOD |
354 | (pmax (length method)) ; | |
05896d77 KH |
355 | char ; Current scanning target |
356 | (betweenparen 0) ; CHAR is in parentheses. | |
357 | argreq ; An argument is required. | |
358 | inargvar) ; position of CHAR is in an argument variable. | |
359 | (while (< p pmax) | |
360 | (setq char (aref method p) | |
361 | p (1+ p)) | |
362 | (cond | |
363 | ;; Is CHAR part of a objc token? | |
364 | ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. | |
365 | (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. | |
366 | (or (and (<= ?a char) (<= char ?z)) | |
367 | (and (<= ?A char) (<= char ?Z)) | |
368 | (and (<= ?0 char) (<= char ?9)) | |
369 | (= ?_ char))) | |
33ee2fc8 | 370 | (if argreq |
05896d77 KH |
371 | (setq inargvar t |
372 | argreq nil) | |
373 | (setq return (concat return (char-to-string char))))) | |
374 | ;; Or a white space? | |
304515db | 375 | ((and inargvar (or (eq ?\ char) (eq ?\n char)) |
05896d77 KH |
376 | (setq inargvar nil))) |
377 | ;; Or a method separator? | |
378 | ;; If a method separator, the next token will be an argument variable. | |
304515db GM |
379 | ((eq ?: char) |
380 | (setq argreq t | |
05896d77 KH |
381 | return (concat return (char-to-string char)))) |
382 | ;; Or an open parentheses? | |
383 | ((eq ?\( char) | |
384 | (setq betweenparen (1+ betweenparen))) | |
385 | ;; Or a close parentheses? | |
386 | ((eq ?\) char) | |
387 | (setq betweenparen (1- betweenparen))))) | |
388 | return)) | |
389 | ||
390 | (defun cc-imenu-objc-remove-white-space (str) | |
391 | "Remove all spaces and tabs from STR." | |
392 | (let ((return "") | |
393 | (p 0) | |
304515db | 394 | (max (length str)) |
05896d77 KH |
395 | char) |
396 | (while (< p max) | |
397 | (setq char (aref str p)) | |
398 | (setq p (1+ p)) | |
399 | (if (or (= char ?\ ) (= char ?\t)) | |
400 | () | |
401 | (setq return (concat return (char-to-string char))))) | |
402 | return)) | |
403 | ||
404 | (defun cc-imenu-objc-function () | |
33ee2fc8 | 405 | "Imenu support for Objective C mode." |
05896d77 KH |
406 | (let (methodlist |
407 | clist | |
8729df59 | 408 | ;; |
f1063b2f | 409 | ;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants. |
8729df59 | 410 | ;; |
304515db | 411 | ;; *Warning for developers* |
8729df59 KH |
412 | ;; These constants depend on `cc-imenu-c++-generic-expression'. |
413 | ;; | |
f1063b2f RS |
414 | (OBJC cc-imenu-objc-generic-expression-objc-base-index) |
415 | ;; Special case to match a line like `main() {}' | |
416 | (Cnoreturn cc-imenu-objc-generic-expression-noreturn-index) | |
417 | ;; General function name regexp | |
418 | (Cgeneralfunc cc-imenu-objc-generic-expression-general-func-index) | |
419 | ;; Special case for definitions using phony prototype macros like: | |
420 | (Cproto cc-imenu-objc-generic-expression-proto-index) | |
05896d77 | 421 | langnum |
8729df59 | 422 | ;; |
05896d77 KH |
423 | (classcount 0) |
424 | toplist | |
05896d77 | 425 | str |
304515db | 426 | str2 |
05896d77 KH |
427 | (intflen (length "@interface")) |
428 | (implen (length "@implementation")) | |
429 | (prtlen (length "@protocol")) | |
f1063b2f RS |
430 | (func |
431 | ;; | |
304515db | 432 | ;; Does this emacs have buffer-substring-no-properties? |
f1063b2f RS |
433 | ;; |
434 | (if (fboundp 'buffer-substring-no-properties) | |
435 | 'buffer-substring-no-properties | |
436 | 'buffer-substring))) | |
0ec8351b | 437 | (goto-char (point-max)) |
05896d77 KH |
438 | ;; |
439 | (while (re-search-backward cc-imenu-objc-generic-expression nil t) | |
304515db | 440 | (setq langnum (if (match-beginning OBJC) |
8729df59 KH |
441 | OBJC |
442 | (cond | |
f1063b2f RS |
443 | ((match-beginning Cproto) Cproto) |
444 | ((match-beginning Cgeneralfunc) Cgeneralfunc) | |
445 | ((match-beginning Cnoreturn) Cnoreturn)))) | |
446 | (setq str (funcall func (match-beginning langnum) (match-end langnum))) | |
05896d77 | 447 | ;; |
304515db | 448 | (cond |
05896d77 KH |
449 | ;; |
450 | ;; C | |
451 | ;; | |
8729df59 | 452 | ((not (eq langnum OBJC)) |
05896d77 KH |
453 | (setq clist (cons (cons str (match-beginning langnum)) clist))) |
454 | ;; | |
455 | ;; ObjC | |
304515db | 456 | ;; |
05896d77 KH |
457 | ;; An instance Method |
458 | ((eq (aref str 0) ?-) | |
459 | (setq str (concat "-" (cc-imenu-objc-method-to-selector str))) | |
460 | (setq methodlist (cons (cons str | |
461 | (match-beginning langnum)) | |
462 | methodlist))) | |
463 | ;; A factory Method | |
464 | ((eq (aref str 0) ?+) | |
465 | (setq str (concat "+" (cc-imenu-objc-method-to-selector str))) | |
466 | (setq methodlist (cons (cons str | |
467 | (match-beginning langnum)) | |
468 | methodlist))) | |
304515db | 469 | ;; Interface or implementation or protocol |
05896d77 KH |
470 | ((eq (aref str 0) ?@) |
471 | (setq classcount (1+ classcount)) | |
304515db | 472 | (cond |
05896d77 KH |
473 | ((and (> (length str) implen) |
474 | (string= (substring str 0 implen) "@implementation")) | |
475 | (setq str (substring str implen) | |
476 | str2 "@implementation")) | |
477 | ((string= (substring str 0 intflen) "@interface") | |
478 | (setq str (substring str intflen) | |
479 | str2 "@interface")) | |
480 | ((string= (substring str 0 prtlen) "@protocol") | |
481 | (setq str (substring str prtlen) | |
482 | str2 "@protocol"))) | |
483 | (setq str (cc-imenu-objc-remove-white-space str)) | |
484 | (setq methodlist (cons (cons str2 | |
9a0f8f2e | 485 | (match-beginning langnum)) |
05896d77 | 486 | methodlist)) |
9a0f8f2e | 487 | (setq toplist (cons (cons str methodlist) toplist) |
05896d77 | 488 | methodlist nil)))) |
05896d77 KH |
489 | |
490 | ;; In this buffer, there is only one or zero @{interface|implementation|protocol}. | |
491 | (if (< classcount 2) | |
492 | (let ((classname (car (car toplist))) | |
493 | (p (cdr (car (cdr (car toplist))))) | |
494 | last) | |
495 | (setq toplist (cons (cons classname p) (cdr (cdr (car toplist))))) | |
496 | ;; Add C lang token | |
497 | (if clist | |
498 | (progn | |
499 | (setq last toplist) | |
500 | (while (cdr last) | |
501 | (setq last (cdr last))) | |
502 | (setcdr last clist)))) | |
503 | ;; Add C lang tokens as a sub menu | |
d9e94c22 MS |
504 | (if clist |
505 | (setq toplist (cons (cons "C" clist) toplist)))) | |
05896d77 KH |
506 | ;; |
507 | toplist | |
508 | )) | |
509 | ||
0ec8351b BW |
510 | ;(defvar cc-imenu-pike-generic-expression |
511 | ; ()) | |
512 | ; FIXME: Please contribute one! | |
513 | ||
d9e94c22 MS |
514 | (defun cc-imenu-init (mode-generic-expression |
515 | &optional mode-create-index-function) | |
51f606de | 516 | (setq imenu-generic-expression mode-generic-expression |
d9e94c22 MS |
517 | imenu-case-fold-search nil) |
518 | (when mode-create-index-function | |
519 | (setq imenu-create-index-function mode-create-index-function))) | |
51f606de | 520 | |
785eecbb | 521 | \f |
130c507e | 522 | (cc-provide 'cc-menus) |
3afbc435 | 523 | |
785eecbb | 524 | ;;; cc-menus.el ends here |