cc-menus.el 15 KB

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