diff options
| author | Karl Heuer | 1997-10-23 07:31:26 +0000 |
|---|---|---|
| committer | Karl Heuer | 1997-10-23 07:31:26 +0000 |
| commit | 05896d7773b24b3268416f023de318fb950625d2 (patch) | |
| tree | 6f8e5d0b7c3a506a89ea585ab76a98414e13c696 | |
| parent | cf4320b8bfefaa43c6bfba9d056a806fafd98102 (diff) | |
| download | emacs-05896d7773b24b3268416f023de318fb950625d2.tar.gz emacs-05896d7773b24b3268416f023de318fb950625d2.zip | |
(cc-imenu-c-prototype-macro-regexp): New var.
(cc-imenu-c++-generic-expression): Patches to better match C++ code.
Given by jan.dubois@ibm.net (Jan Dubois)
(cc-imenu-java-generic-expression):
Removed test for declaration
statements. Patch given by Ake Stenhoff <etxaksf@aom.ericsson.se>, as
forwarded to me by RMS.
Imenu support for Objective-C given by Masatake (jet) YAMATO.
| -rw-r--r-- | lisp/progmodes/cc-menus.el | 301 |
1 files changed, 261 insertions, 40 deletions
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el index 20c7640b606..d758d0707f8 100644 --- a/lisp/progmodes/cc-menus.el +++ b/lisp/progmodes/cc-menus.el | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | ;; 1985 Richard M. Stallman | 7 | ;; 1985 Richard M. Stallman |
| 8 | ;; Maintainer: cc-mode-help@python.org | 8 | ;; Maintainer: cc-mode-help@python.org |
| 9 | ;; Created: 22-Apr-1997 (split from cc-mode.el) | 9 | ;; Created: 22-Apr-1997 (split from cc-mode.el) |
| 10 | ;; Version: 5.17 | 10 | ;; Version: 5.18 |
| 11 | ;; Keywords: c languages oop | 11 | ;; Keywords: c languages oop |
| 12 | 12 | ||
| 13 | ;; This file is part of GNU Emacs. | 13 | ;; This file is part of GNU Emacs. |
| @@ -29,56 +29,97 @@ | |||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | ;; imenu integration | 31 | ;; imenu integration |
| 32 | (defvar cc-imenu-c-prototype-macro-regexp nil | ||
| 33 | "RE matching macro names used to conditionally specify function prototypes. | ||
| 34 | |||
| 35 | For example: | ||
| 36 | |||
| 37 | #ifdef __STDC__ | ||
| 38 | #define _P(x) x | ||
| 39 | #else | ||
| 40 | #define _P(x) /*nothing*/ | ||
| 41 | #endif | ||
| 42 | |||
| 43 | int main _P( (int argc, char *argv[]) ) | ||
| 44 | |||
| 45 | A sample value might look like: `\\(_P\\|_PROTO\\)'.") | ||
| 46 | |||
| 32 | (defvar cc-imenu-c++-generic-expression | 47 | (defvar cc-imenu-c++-generic-expression |
| 33 | (` | 48 | (` |
| 34 | ((nil | 49 | ( |
| 50 | ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' | ||
| 51 | ;; will be incorrectly recognised as function `new ()' because the regexps | ||
| 52 | ;; work by backtracking from the end of the definition. | ||
| 53 | (nil | ||
| 54 | (, | ||
| 55 | (concat | ||
| 56 | "^\\<.*" | ||
| 57 | "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char | ||
| 58 | ; (note: this can be `\n') | ||
| 59 | "\\(" | ||
| 60 | "\\([a-zA-Z0-9_:<>~]*::\\)?" ; match an operator | ||
| 61 | "operator\\>[ \t]*" | ||
| 62 | "\\(()\\|[^(]*\\)" ; special case for `()' operator | ||
| 63 | "\\)" | ||
| 64 | |||
| 65 | "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, | ||
| 66 | ; require something other than | ||
| 67 | ; a `;' after the (...) to | ||
| 68 | ; avoid prototypes. Can't | ||
| 69 | ; catch cases with () inside | ||
| 70 | ; the parentheses surrounding | ||
| 71 | ; the parameters. e.g.: | ||
| 72 | ; `int foo(int a=bar()) {...}' | ||
| 73 | )) 1) | ||
| 74 | ;; Special case to match a line like `main() {}' | ||
| 75 | ;; e.g. no return type, not even on the previous line. | ||
| 76 | (nil | ||
| 35 | (, | 77 | (, |
| 36 | (concat | 78 | (concat |
| 37 | "^" ; beginning of line is required | 79 | "^" |
| 38 | "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>" | 80 | "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name |
| 39 | "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no | 81 | "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above |
| 40 | "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right? | 82 | )) 1) |
| 41 | 83 | ;; Special case for definitions using phony prototype macros like: | |
| 42 | "\\(" ; last type spec including */& | 84 | ;; `int main _PROTO( (int argc,char *argv[]) )'. |
| 43 | "[a-zA-Z0-9_:]+" | 85 | ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. |
| 44 | "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either ptr/ref sign or ws | 86 | ;; Only supported in c-code, so no `:<>~' chars in function name! |
| 45 | "\\)?" ; if there is a last type spec | 87 | (,@ (if cc-imenu-c-prototype-macro-regexp |
| 46 | "\\(" ; name, take into the imenu entry | 88 | (` ((nil |
| 47 | "[a-zA-Z0-9_:~]+" ; member func, ctor or dtor... | 89 | (, |
| 48 | ; (may not contain * because then | 90 | (concat |
| 49 | ; "a::operator char*" would | 91 | "^\\<.*" ; line MUST start with word char |
| 50 | ; become "char*"!) | 92 | "[^a-zA-Z0-9_]" ; match any non-identifier char |
| 51 | "\\|" | 93 | "\\([a-zA-Z_][a-zA-Z0-9_]*\\)" ; match function name |
| 52 | "\\([a-zA-Z0-9_:~]*::\\)?operator" | 94 | "[ \t]*" ; whitespace before macro name |
| 53 | "[^a-zA-Z1-9_][^(]*" ; ...or operator | 95 | cc-imenu-c-prototype-macro-regexp |
| 54 | " \\)" | 96 | "[ \t]*(" ; ws followed by first paren. |
| 55 | "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than | 97 | "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above |
| 56 | ; a `;' after the (...) to | 98 | )) 1))))) |
| 57 | ; avoid prototypes. Can't | 99 | ;; General function name regexp |
| 58 | ; catch cases with () inside | 100 | (nil |
| 59 | ; the parentheses surrounding | 101 | (, |
| 60 | ; the parameters. e.g.: | 102 | (concat |
| 61 | ; "int foo(int a=bar()) {...}" | 103 | "^\\<.*" ; line MUST start with word char |
| 62 | 104 | "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char | |
| 63 | )) 6) | 105 | "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name |
| 106 | "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above | ||
| 107 | )) 1) | ||
| 108 | ;; Class definitions | ||
| 64 | ("Class" | 109 | ("Class" |
| 65 | (, (concat | 110 | (, (concat |
| 66 | "^" ; beginning of line is required | 111 | "^" ; beginning of line is required |
| 67 | "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>" | 112 | "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' |
| 68 | "class[ \t]+" | 113 | "class[ \t]+" |
| 69 | "\\([a-zA-Z0-9_]+\\)" ; the string we want to get | 114 | "\\([a-zA-Z0-9_]+\\)" ; the string we want to get |
| 70 | "[ \t]*[:{]" | 115 | "[ \t]*[:{]" |
| 71 | )) 2))) | 116 | )) 2))) |
| 72 | "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") | 117 | "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") |
| 73 | 118 | ||
| 74 | (defvar cc-imenu-c-generic-expression | 119 | (defvar cc-imenu-c-generic-expression |
| 75 | cc-imenu-c++-generic-expression | 120 | cc-imenu-c++-generic-expression |
| 76 | "Imenu generic expression for C mode. See `imenu-generic-expression'.") | 121 | "Imenu generic expression for C mode. See `imenu-generic-expression'.") |
| 77 | 122 | ||
| 78 | ;(defvar cc-imenu-objc-generic-expression | ||
| 79 | ; ()) | ||
| 80 | ; Please contribute one! | ||
| 81 | |||
| 82 | (defvar cc-imenu-java-generic-expression | 123 | (defvar cc-imenu-java-generic-expression |
| 83 | (` | 124 | (` |
| 84 | ((nil | 125 | ((nil |
| @@ -93,11 +134,191 @@ | |||
| 93 | "\\([ \t]*\\)+(" | 134 | "\\([ \t]*\\)+(" |
| 94 | "\\([a-zA-Z,_1-9\n \t]*[[]?[]]?\\)*" ; arguments | 135 | "\\([a-zA-Z,_1-9\n \t]*[[]?[]]?\\)*" ; arguments |
| 95 | ")[ \t]*" | 136 | ")[ \t]*" |
| 96 | "[^;(]" | 137 | ; "[^;(]" |
| 97 | "[,a-zA-Z_1-9\n \t]*{" | 138 | "[,a-zA-Z_1-9\n \t]*{" |
| 98 | )) 6))) | 139 | )) 6))) |
| 99 | "Imenu generic expression for Java mode. See `imenu-generic-expression'.") | 140 | "Imenu generic expression for Java mode. See `imenu-generic-expression'.") |
| 100 | 141 | ||
| 142 | (defvar cc-imenu-objc-generic-expression | ||
| 143 | (concat | ||
| 144 | ;; For C | ||
| 145 | ;; Pick a token by (match-string 6) | ||
| 146 | (car (cdr (car cc-imenu-c++-generic-expression))) | ||
| 147 | ;; For Objective-C | ||
| 148 | ;; Pick a token by (match-string 8) | ||
| 149 | "\\|\\(" | ||
| 150 | "^[-+][:a-zA-Z0-9()*_<>\n\t ]*[;{]" ; Methods | ||
| 151 | "\\|" | ||
| 152 | "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*:" | ||
| 153 | "\\|" | ||
| 154 | "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" | ||
| 155 | "\\|" | ||
| 156 | ;; For NSObject, NSProxy and Object... They don't have super class. | ||
| 157 | "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*.*$" | ||
| 158 | "\\|" | ||
| 159 | "^@implementation[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" | ||
| 160 | "\\|" | ||
| 161 | "^@implementation[\t ]+[a-zA-Z0-9_]+" | ||
| 162 | "\\|" | ||
| 163 | "^@protocol[\t ]+[a-zA-Z0-9_]+" "\\)") | ||
| 164 | "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") | ||
| 165 | |||
| 166 | |||
| 167 | ;; Imenu support for objective-c uses functions. | ||
| 168 | (defsubst cc-imenu-objc-method-to-selector (method) | ||
| 169 | "Return the objc selector style string of METHOD. | ||
| 170 | Example: | ||
| 171 | - perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ | ||
| 172 | => | ||
| 173 | -perform:withObject:withObject:withObject: /* selector */" | ||
| 174 | (let ((return "") ; String to be returned | ||
| 175 | (p 0) ; Current scanning position in METHOD | ||
| 176 | (pmax (length method)) ; | ||
| 177 | char ; Current scanning target | ||
| 178 | (betweenparen 0) ; CHAR is in parentheses. | ||
| 179 | argreq ; An argument is required. | ||
| 180 | inargvar) ; position of CHAR is in an argument variable. | ||
| 181 | (while (< p pmax) | ||
| 182 | (setq char (aref method p) | ||
| 183 | p (1+ p)) | ||
| 184 | (cond | ||
| 185 | ;; Is CHAR part of a objc token? | ||
| 186 | ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. | ||
| 187 | (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. | ||
| 188 | (or (and (<= ?a char) (<= char ?z)) | ||
| 189 | (and (<= ?A char) (<= char ?Z)) | ||
| 190 | (and (<= ?0 char) (<= char ?9)) | ||
| 191 | (= ?_ char))) | ||
| 192 | (if argreq | ||
| 193 | (setq inargvar t | ||
| 194 | argreq nil) | ||
| 195 | (setq return (concat return (char-to-string char))))) | ||
| 196 | ;; Or a white space? | ||
| 197 | ((and inargvar (or (eq ?\ char) (eq ?\n char)) | ||
| 198 | (setq inargvar nil))) | ||
| 199 | ;; Or a method separator? | ||
| 200 | ;; If a method separator, the next token will be an argument variable. | ||
| 201 | ((eq ?: char) | ||
| 202 | (setq argreq t | ||
| 203 | return (concat return (char-to-string char)))) | ||
| 204 | ;; Or an open parentheses? | ||
| 205 | ((eq ?\( char) | ||
| 206 | (setq betweenparen (1+ betweenparen))) | ||
| 207 | ;; Or a close parentheses? | ||
| 208 | ((eq ?\) char) | ||
| 209 | (setq betweenparen (1- betweenparen))))) | ||
| 210 | return)) | ||
| 211 | |||
| 212 | (defun cc-imenu-objc-remove-white-space (str) | ||
| 213 | "Remove all spaces and tabs from STR." | ||
| 214 | (let ((return "") | ||
| 215 | (p 0) | ||
| 216 | (max (length str)) | ||
| 217 | char) | ||
| 218 | (while (< p max) | ||
| 219 | (setq char (aref str p)) | ||
| 220 | (setq p (1+ p)) | ||
| 221 | (if (or (= char ?\ ) (= char ?\t)) | ||
| 222 | () | ||
| 223 | (setq return (concat return (char-to-string char))))) | ||
| 224 | return)) | ||
| 225 | |||
| 226 | (defun cc-imenu-objc-function () | ||
| 227 | "imenu supports for objc-mode." | ||
| 228 | (let (methodlist | ||
| 229 | clist | ||
| 230 | (C 6) | ||
| 231 | (OBJC 8) | ||
| 232 | langnum | ||
| 233 | (classcount 0) | ||
| 234 | toplist | ||
| 235 | stupid | ||
| 236 | str | ||
| 237 | str2 | ||
| 238 | (intflen (length "@interface")) | ||
| 239 | (implen (length "@implementation")) | ||
| 240 | (prtlen (length "@protocol")) | ||
| 241 | bufsubst-fun) | ||
| 242 | ;; | ||
| 243 | ;; Does this emacs has buffer-substring-no-properties? | ||
| 244 | ;; | ||
| 245 | (fset 'bufsubst-fun (if (fboundp 'buffer-substring-no-properties) | ||
| 246 | (symbol-function 'buffer-substring-no-properties) | ||
| 247 | (symbol-function 'buffer-substring))) | ||
| 248 | (goto-char (point-max)) | ||
| 249 | (imenu-progress-message stupid 0) | ||
| 250 | ;; | ||
| 251 | (while (re-search-backward cc-imenu-objc-generic-expression nil t) | ||
| 252 | (imenu-progress-message stupid) | ||
| 253 | (setq langnum (if (match-beginning C) C OBJC)) | ||
| 254 | (setq str (bufsubst-fun (match-beginning langnum) (match-end langnum))) | ||
| 255 | ;; | ||
| 256 | (cond | ||
| 257 | ;; | ||
| 258 | ;; C | ||
| 259 | ;; | ||
| 260 | ((eq langnum C) | ||
| 261 | (setq clist (cons (cons str (match-beginning langnum)) clist))) | ||
| 262 | ;; | ||
| 263 | ;; ObjC | ||
| 264 | ;; | ||
| 265 | ;; An instance Method | ||
| 266 | ((eq (aref str 0) ?-) | ||
| 267 | (setq str (concat "-" (cc-imenu-objc-method-to-selector str))) | ||
| 268 | (setq methodlist (cons (cons str | ||
| 269 | (match-beginning langnum)) | ||
| 270 | methodlist))) | ||
| 271 | ;; A factory Method | ||
| 272 | ((eq (aref str 0) ?+) | ||
| 273 | (setq str (concat "+" (cc-imenu-objc-method-to-selector str))) | ||
| 274 | (setq methodlist (cons (cons str | ||
| 275 | (match-beginning langnum)) | ||
| 276 | methodlist))) | ||
| 277 | ;; Interface or implementation or protocol | ||
| 278 | ((eq (aref str 0) ?@) | ||
| 279 | (setq classcount (1+ classcount)) | ||
| 280 | (cond | ||
| 281 | ((and (> (length str) implen) | ||
| 282 | (string= (substring str 0 implen) "@implementation")) | ||
| 283 | (setq str (substring str implen) | ||
| 284 | str2 "@implementation")) | ||
| 285 | ((string= (substring str 0 intflen) "@interface") | ||
| 286 | (setq str (substring str intflen) | ||
| 287 | str2 "@interface")) | ||
| 288 | ((string= (substring str 0 prtlen) "@protocol") | ||
| 289 | (setq str (substring str prtlen) | ||
| 290 | str2 "@protocol"))) | ||
| 291 | (setq str (cc-imenu-objc-remove-white-space str)) | ||
| 292 | (setq methodlist (cons (cons str2 | ||
| 293 | (match-beginning langnum)) | ||
| 294 | methodlist)) | ||
| 295 | (setq toplist (cons nil (cons (cons str | ||
| 296 | methodlist) toplist)) | ||
| 297 | methodlist nil)))) | ||
| 298 | ;; | ||
| 299 | (imenu-progress-message stupid 100) | ||
| 300 | (if (eq (car toplist) nil) | ||
| 301 | (setq toplist (cdr toplist))) | ||
| 302 | |||
| 303 | ;; In this buffer, there is only one or zero @{interface|implementation|protocol}. | ||
| 304 | (if (< classcount 2) | ||
| 305 | (let ((classname (car (car toplist))) | ||
| 306 | (p (cdr (car (cdr (car toplist))))) | ||
| 307 | last) | ||
| 308 | (setq toplist (cons (cons classname p) (cdr (cdr (car toplist))))) | ||
| 309 | ;; Add C lang token | ||
| 310 | (if clist | ||
| 311 | (progn | ||
| 312 | (setq last toplist) | ||
| 313 | (while (cdr last) | ||
| 314 | (setq last (cdr last))) | ||
| 315 | (setcdr last clist)))) | ||
| 316 | ;; Add C lang tokens as a sub menu | ||
| 317 | (setq toplist (cons (cons "C" clist) toplist))) | ||
| 318 | ;; | ||
| 319 | toplist | ||
| 320 | )) | ||
| 321 | |||
| 101 | 322 | ||
| 102 | (provide 'cc-menus) | 323 | (provide 'cc-menus) |
| 103 | ;;; cc-menus.el ends here | 324 | ;;; cc-menus.el ends here |