1 ;;; cc-ide.el --- C++ IDE
5 ;; Copyright (C) 2000 Stefan Bund
7 ;; cc-ide.el is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 2, or (at your
10 ;; option) any later version.
12 ;; cc-ide.el is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
26 (defvar ccide-compile-opts "DEBUG=1"
27 "*Additional options to make command")
29 (defvar ccide-file-vars nil)
31 (defvar ccide-default-author "")
32 (defvar ccide-default-copyright "")
34 (defvar ccide-corba-skel-dir "")
35 (defvar ccide-corba-idl-dir "")
36 (defvar ccide-corba-idl-command "omniidl2 -w")
38 (defvar c-user-prefixes '("inline" "static" "prefix_")
39 "*List of possible prefixes for function definitions.")
41 (defvar ccide-default-prefix "prefix_"
42 "*Prefix added to every implementation header. Probably eiter empty or 'prefix_'")
44 (defvar ccide-gen-throw nil
45 "*If non-nil, generate throw_ specs")
47 (defconst c-user-prefix-re (regexp-opt c-user-prefixes t))
49 (defconst ccide-doxy-tag-re
50 (concat "\\\\\\(group\\|defgroup\\|see\\|author\\|version\\|id\\|since"
51 "\\|returns?\\|throws?\\|exception\\|raises\\|param\\|li\\|brief"
52 "\\|internal\\|bug\\|fixme\\|todo\\|idea\\|implementation\\)\\b"))
54 (defconst ccide-special-extensions
55 '(".h" ".hh" ".mpp" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci"))
57 (defconst ccide-implementation-extensions
58 '(".h" ".hh" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci"))
60 (defconst ccide-class-defaults-word
61 "// \\(default\\|no\\|protected\\|private\\|disabled\\|my\\)")
63 (defconst ccide-bindings
66 ("fc" ccide-file-comment "File comment")
67 ("fs" ccide-syncronize-includes "Sync includes")
71 ("cc" ccide-class-comment "Class comment")
72 ("cg" ccide-gen-class "Generate class")
73 ("cd" ccide-gen-class-defaults "Generate class defaults")
74 ("cD" ccide-gen-class-defaults-impl "Generate class defaults impl")
76 ("csd" ccide-set-class-defaults-default "Set class defaults comment" "Default")
77 ("csn" ccide-set-class-defaults-no "Set class defaults comment" "No")
78 ("csp" ccide-set-class-defaults-protected "Set class defaults comment" "Protected")
79 ("csr" ccide-set-class-defaults-private "Set class defaults comment" "Private")
80 ("csx" ccide-set-class-defaults-disabled "Set class defaults comment" "Disabled")
81 ("csm" ccide-set-class-defaults-my "Set class defaults comment" "My")
83 ("cS" ccide-gen-struct-constructors "Generate structure constructors")
85 ("ci" ccide-class-impl-comment "Generate class implemenation comment")
90 ("mc" ccide-function-comment "Method comment")
91 ("mp" ccide-grab-prototype "Grab prototype")
92 ("mr" ccide-reformat-defun "Reformat defun")
93 ("mx" ccide-replace-defun "Replace defun")
94 ("mt" ccide-prefix-defun-type-with-class "Prefix defun type with class")
95 ("mn" ccide-prefix-defun-type-with-namespace "Prefix defun type with namespace")
96 ("mi" ccide-grab-inline-decl "Grab inline decl")
97 ("mA" ccide-grab-all-inlines "Grab ALL inline decls")
98 ("mC" ccide-grab-create-constructor "Grab CREATE constructor")
99 ("mI" ccide-grab-create-constructor-impl "Build CREATE cosntructor")
100 ("mf" ccide-find-implementation "Find method implementation")
101 ("mT" ccide-insert-defun-prefix "Insert current defun prefix at point")
105 ("vc" ccide-variable-comment "Variable comment")
106 ("vf" ccide-grab-acces-fn "Grab access methods")
110 ("h" ccide-hide-all-doxy-comments "Hide all Doxygen comments")
111 ("s" ccide-show-all-comments "Show all Doxygen comments")
114 ; ("Cg" ccide-gen-corba-impl "Generate CORBA impl")
115 ; ("Cm" ccide-gen-corba-impl-methods "Generate CORBA impl methods")
116 ; (nil nil separator)
119 ; ("ts" ccide-scan-mantemps "Scan mantemps")
120 ; (nil nil separator)
123 ; ("of" ccide-open-compilation-frame "Open *compilation* frame")
124 ; ("oc" ccide-compile-compile "Make -> Compile")
125 ; ("ox" ccide-compile-clean "Make -> Clean")
126 ; ("od" ccide-compile-cleandepends "Make -> Clean depends")
127 ; ("ok" ccide-compile-kill "Kill compilation")
128 ; ("oh" ccide-hide-compilation "Hide *compilation* buffer")
134 (require 'cc-engine-2)
143 (require 'misc-local)
145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
148 (defsubst ccide-match-string (n)
149 (buffer-substring-no-properties (match-beginning n) (match-end n)))
151 (defun ccide-file-macro-name (&optional file-name)
152 (concat (upcase (file-name-extension (or file-name (buffer-file-name))))
154 (string-replace "\\." "_" (file-name-sans-extension
155 (file-name-nondirectory
156 (or file-name (buffer-file-name))))
160 (defun ccide-file-name (&optional extension file-name directory)
161 (concat (if directory (file-name-as-directory directory) "")
162 (file-name-sans-extension
163 (file-name-nondirectory
164 (or file-name (buffer-file-name))))
167 (defun ccide-in-doxy-comment ()
169 (back-to-indentation)
170 (if (eq (c-in-literal) 'c)
172 (goto-char (car (c-literal-limits)))
173 (and (looking-at "/\\*\\*[ \t\n\r@]")
174 (current-column))))))
176 (defun ccide-shell-command (command)
177 (let ((obuf (get-buffer-create "*ccide shell command*"))
182 (insert command "\n"))
183 (setq exit-status (call-process shell-file-name nil "*ccide shell command*" nil
184 shell-command-switch command))
185 (and exit-status (equal exit-status 0))))
187 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190 (defun ccide-file-comment ()
191 "Add a comment to this source file."
196 (goto-char (point-min))
199 "// Copyright (C) " (number-to-string (nth 5 (decode-time)))
200 " " ccide-default-author "\n"
201 ccide-default-copyright
203 (cond ((string-match "\\.hh?$" (buffer-file-name))
204 (insert "#ifndef " (ccide-file-macro-name) "\n"
205 "#define " (ccide-file-macro-name) " 1\n\n"
206 "// Custom includes\n\n"
207 "//#include \"" (ccide-file-name ".mpp") "\"\n"
208 "///////////////////////////////hh.p////////////////////////////////////////\n\n")
210 (goto-char (point-max))
211 (insert "\n\n///////////////////////////////hh.e////////////////////////////////////////\n"
212 "//#include \"" (ccide-file-name ".cci") "\"\n"
213 "//#include \"" (ccide-file-name ".ct") "\"\n"
214 "//#include \"" (ccide-file-name ".cti") "\"\n"
215 "//#include \"" (ccide-file-name ".mpp") "\"\n"
217 ((string-match "\\.mpp$" (buffer-file-name))
218 (insert "#if !BOOST_PP_IS_ITERATING\n"
219 "#ifndef " (ccide-file-macro-name) "\n\n"
220 "// Custom includes\n\n"
221 "//////////////////////////////mpp.p////////////////////////////////////////\n"
222 "// Local Macros\n\n"
226 "///////////////////////////////////////////////////////////////////////////\n\n"
228 "#if BOOST_PP_ITERATION_FLAGS()==1\n"
229 "///////////////////////////////////////////////////////////////////////////\n\n")
231 (goto-char (point-max))
232 (insert "\n\n//////\n"
235 "#if !BOOST_PP_IS_ITERATING\n"
236 "#ifdef " (ccide-file-macro-name) "\n"
237 "///////////////////////////////////////////////////////////////////////////\n"
238 "// Undefine local Macros\n\n"
239 "//////////////////////////////mpp.e////////////////////////////////////////\n"
241 "#define " (ccide-file-macro-name) " 1\n"
244 ((string-match "\\.ih$" (buffer-file-name))
245 (insert "#ifndef " (ccide-file-macro-name) "\n"
246 "#define " (ccide-file-macro-name) " 1\n\n"
247 "// Custom includes\n\n"
248 "///////////////////////////////ih.p////////////////////////////////////////\n\n")
250 (goto-char (point-max))
251 (insert "\n\n///////////////////////////////ih.e////////////////////////////////////////\n"
253 ((or (string-match "\\.test\\.cc$" (buffer-file-name))
254 (string-match "\\.test\\.cpp$" (buffer-file-name)))
255 (insert "// Unit tests\n\n"
256 "//#include \"" (ccide-file-name ".hh") "\"\n"
257 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
258 "// Custom includes\n"
259 "#include \"" (ccide-file-name ".hh" (ccide-file-name)) "\"\n\n"
260 "#include <boost/test/auto_unit_test.hpp>\n"
261 "#include <boost/test/test_tools.hpp>\n\n"
263 "///////////////////////////////cc.p////////////////////////////////////////\n\n")
265 (goto-char (point-max))
266 (insert "\n\n///////////////////////////////cc.e////////////////////////////////////////\n"
268 ((or (string-match "\\.cc$" (buffer-file-name))
269 (string-match "\\.cpp$" (buffer-file-name)))
270 (insert "// Definition of non-inline non-template functions\n\n"
271 "//#include \"" (ccide-file-name ".hh") "\"\n"
272 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
273 "// Custom includes\n\n"
274 "//#include \"" (ccide-file-name ".mpp") "\"\n"
276 "///////////////////////////////cc.p////////////////////////////////////////\n\n")
278 (goto-char (point-max))
279 (insert "\n\n///////////////////////////////cc.e////////////////////////////////////////\n"
281 "//#include \"" (ccide-file-name ".mpp") "\""))
282 ((string-match "\\.cci$" (buffer-file-name))
283 (insert "// Definition of inline non-template functions\n\n"
284 "// Custom includes\n\n"
285 "#define prefix_ inline\n"
286 "///////////////////////////////cci.p///////////////////////////////////////\n\n")
288 (goto-char (point-max))
289 (insert "\n\n///////////////////////////////cci.e///////////////////////////////////////\n"
291 ((string-match "\\.ct$" (buffer-file-name))
292 (insert "// Definition of non-inline template functions\n\n"
293 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
294 "// Custom includes\n\n"
296 "///////////////////////////////ct.p////////////////////////////////////////\n\n")
298 (goto-char (point-max))
299 (insert "\n\n///////////////////////////////ct.e////////////////////////////////////////\n"
301 ((string-match "\\.cti$" (buffer-file-name))
302 (insert "// Definition of inline template functions\n\n"
303 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
304 "// Custom includes\n\n"
305 "#define prefix_ inline\n"
306 "///////////////////////////////cti.p///////////////////////////////////////\n\n")
308 (goto-char (point-max))
309 (insert "\n\n///////////////////////////////cti.e///////////////////////////////////////\n"
311 ((string-match "\\.java$" (buffer-file-name))
314 (goto-char (point-max)))
317 (goto-char (point-max))))
319 "// Local Variables:\n"
320 "// mode: " mode "\n")
321 (loop for (var . value) in ccide-file-vars
322 do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
326 (if (equal mode "jde")
327 (let ((package (file-name-directory (buffer-file-name))))
328 (jdeap-initialize-setup)
329 (if (not (equal jdeap-current-source-directory "."))
331 (concat "^" (regexp-quote jdeap-current-source-directory))
334 (setq package (substring package
336 (1- (length package))))
338 (string-replace "/" "." package t)
340 (insert "class " (file-name-sans-extension
341 (file-name-nondirectory
342 (buffer-file-name))) "\n{}")
343 (beginning-of-line)))))
345 (defun ccide-syncronize-includes ()
346 "Syncronize include's in all other files"
349 (loop for extension in ccide-special-extensions
350 for file-name = (ccide-file-name extension)
352 (cons (cons file-name
353 (or (find-buffer-visiting file-name)
354 (and (file-readable-p file-name)
355 (find-file-noselect file-name))))
358 (loop for buffer in buffer-map
361 (set-buffer (cdr buffer))
363 (loop for include in buffer-map
365 (goto-char (point-min))
366 (while (re-search-forward
367 (concat "^\\(//\\)?#\\s-*include \""
368 (regexp-quote (car include))
371 (goto-char (match-beginning 0))
372 (if (looking-at "//")
375 (if (not (cdr include))
377 (forward-line 1))))))))))
379 (defun ccide-auto-decorate-new-files ()
380 (if (= (point-min) (point-max))
381 (let ((status (buffer-modified-p)))
383 (set-buffer-modified-p status))))
385 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
388 (defun ccide-class-comment ()
389 "Add comment to start of current class definition"
391 (let ((class (c-get-class-at-point)))
393 (error "No class found")
394 (goto-char (or (aref (car class) 3)
395 (aref (car class) 1)))
398 (ccide-in-doxy-comment))
400 (search-backward "/**" nil t)
402 (let ((indent (make-string (current-indentation) ? )))
410 (defun ccide-gen-class (name &optional defns)
411 "Generate class declaration template"
412 (interactive (list (read-string (concat "Class name (default "
415 nil nil (ccide-file-name))))
416 (insert "class " name)
417 (indent-according-to-mode)
418 (let ((in (make-string c-basic-offset ? ))
419 (ofs (make-string (current-indentation) ? )))
423 (insert ofs "/** \\brief\n"
429 ofs in "///////////////////////////////////////////////////////////////////////////\n"
430 ofs in "// Types\n\n"
431 ofs in "///////////////////////////////////////////////////////////////////////////\n"
432 ofs in "///\\name Structors and default members\n"
434 ofs in "// default default constructor\n"
435 ofs in "// default copy constructor\n"
436 ofs in "// default copy assignment\n"
437 ofs in "// default destructor\n\n"
438 ofs in "// no conversion constructors\n\n"
440 ofs in "///////////////////////////////////////////////////////////////////////////\n"
441 ofs in "///\\name Accessors\n"
444 ofs in "///////////////////////////////////////////////////////////////////////////\n"
445 ofs in "///\\name Mutators\n"
448 (loop for defn in defns
449 do (insert ofs in defn ";\n"))
452 (insert ofs "protected:\n\n"
456 (defun ccide-gen-class-defaults ()
457 "Generate signatures of the default functions: default constructor,
458 copy constructor, assignment operator and destructor."
459 (indent-according-to-mode)
460 (let* ((name (c-scope-name (aref (car (c-get-class-at-point)) 1)))
461 (in (make-string c-basic-offset ? ))
462 (ofs (make-string (current-indentation) ? ))
463 (tspec (if ccide-gen-throw (concat "\n" ofs in "throw_(());\n") ";\n"))
465 (while (string-match "::" name colon)
466 (setq colon (match-end 0)))
467 (setq name (substring name colon))
469 (delete-horizontal-space)
470 (loop with exit = nil
471 do (message (concat "1-dflt constr, 2-destr, "
472 "3-copy constr, 4-copy assmnt, "
473 "c-all copy, d-all dflt, RET-all/done: "))
474 for ch = (read-event)
475 for first = t then nil
476 do (cond ((eq ch 'return)
478 (insert ofs name "()"
480 ofs name "(const " name "& other)"
483 ofs name "& operator=(const " name "& other)"
487 (insert ofs name "()"
490 (insert ofs "~" name "();\n"))
492 (insert ofs name "(const " name "& other)"
495 (insert ofs name "& operator=(const " name "& other)"
498 (insert ofs name "(const " name "& other)"
500 ofs name "& operator=(const " name "& other)"
503 (insert ofs name "()"
505 ofs "~" name "();\n"))
506 (t (setq unread-command-events (cons ch unread-command-events))
510 (defun ccide-gen-class-defaults-impl ()
511 "Generate default implementations for class default functions"
513 (let ((defn (c-build-default-funcions-impl)))
514 (kill-new (cadr defn))
515 (message (concat (car defn) " default members"))))
517 (defun ccide-set-class-defaults-comment (word)
519 (back-to-indentation)
520 (if (not (looking-at ccide-class-defaults-word))
521 (message "Not at class defaults commnet")
522 (replace-match word t t nil 1))))
524 (defmacro ccide-build-class-defaults-f (sym)
525 (let ((fn (intern (concat "ccide-set-class-defaults-"
526 (symbol-name sym)))))
529 (ccide-set-class-defaults-comment ,(symbol-name sym)))))
531 (ccide-build-class-defaults-f no)
532 (ccide-build-class-defaults-f default)
533 (ccide-build-class-defaults-f my)
534 (ccide-build-class-defaults-f protected)
535 (ccide-build-class-defaults-f private)
536 (ccide-build-class-defaults-f disabled)
538 (defun ccide-gen-struct-constructors ()
542 (indent-according-to-mode)
543 (let* ((scope (c-get-block-scope))
544 (class (c-parse-class scope))
545 (variables (c-get-variable-members-with-type class))
546 (name (c-scope-name (aref (car (last scope)) 1)))
547 (in (make-string (current-indentation) ? ))
548 (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
549 (insert name "()\n" inin ": ")
550 (indent-according-to-mode)
551 (loop for var in variables
552 for first = t then nil
553 if (not first) do (insert ", ")
554 do (insert (car var) "()"))
555 (insert "\n" in "{}\n"
557 (loop for var in variables
558 for first = t then nil
559 if (not first) do (insert ", ")
560 do (insert (cdr var) " " (car var) "_"))
561 (insert ")\n" inin ": ")
562 (loop for var in variables
563 for first = t then nil
564 if (not first) do (insert ", ")
565 do (insert (car var) "(" (car var) "_)"))
566 (insert "\n" in "{}"))))
568 (defun ccide-class-impl-comment ()
569 "Get implementation comment for current class"
571 (let* ((scope (c-get-block-scope))
572 (name (c-get-full-prefix scope)))
573 (kill-new (concat (make-string 75 ?/) "\n"
579 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
580 ;; function/method level
582 (defun ccide-function-comment ()
583 "Add comment to start of current function"
585 (c-forward-out-of-comment)
586 (let ((defun (c-get-defun-state))
588 (c-goto-beginning-of-defun defun)
589 (setq indent (make-string (current-indentation) ? ))
592 (ccide-in-doxy-comment))
597 indent " @li @em PRE : \n"
598 indent " @li @em POST : \n\n"
600 indent " */\n" indent)
601 (setq defun (c-get-defun-state)))
602 (ccide-function-comment-adjust defun indent)
603 (if place (goto-char place))))
605 (defun ccide-function-comment-grab-args ()
606 (let ((limit (save-excursion
607 (search-backward "/**" nil t)
609 (end (progn (forward-line -1) (point)))
610 begin start args argend)
611 (if (search-backward "@throws" limit t)
612 (setq argend (progn (beginning-of-line) (point)))
614 (while (or (search-backward "@param" limit t)
615 (search-backward "@return" limit t)))
619 (while (search-forward "@param" argend t)
620 (or (search-forward "@param" argend t)
621 (search-forward "@return" argend t)
622 (search-forward "@throws" argend t)
625 (setq args (cons (ccide-function-comment-parse-arg start (point))
627 (setq start (point)))
629 (if (not (search-forward "@return" argend t))
632 (cons (buffer-substring (point) argend) args))
633 (delete-region begin end))))
635 (defun ccide-function-comment-parse-arg (start end)
638 (re-search-forward "@param\\s-*\\(\\S-*\\)" end t)
639 (cons (match-string 1)
640 (cons (buffer-substring start (match-beginning 1))
641 (buffer-substring (match-end 1) end)))))
643 (defun ccide-function-comment-get-throws (defun)
646 (goto-char (car (aref defun 4)))
647 (if (re-search-forward "\\(throw_\\|throw\\)((?\\s-*\\([^()]*\\))?)"
648 (cdr (aref defun 4)) t)
649 (let ((spec (match-string 2)))
650 (if (> (length spec) 0)
653 (defun ccide-function-comment-adjust (defun indent)
654 (let* ((defargs (mapcar (function (lambda (x)
655 (c-get-template-argument-name (car x) (cdr x))))
657 (defret (and (aref defun 1)
658 (not (string-match (concat "^\\("
660 "\\s-*\\)*\\s-*void$")
661 (buffer-substring (car (aref defun 1))
662 (cdr (aref defun 1)))))))
663 (throws (ccide-function-comment-get-throws defun))
664 (xargs (ccide-function-comment-grab-args))
665 (docargs (cdr xargs))
667 (def-in-doc (loop for defarg in defargs always (assoc defarg docargs)))
668 (doc-in-def (loop for docarg in docargs always (member (car docarg) defargs)))
669 (size-eq (= (length defargs) (length docargs))))
670 (if (or defargs defret throws)
671 (if (not (save-excursion
673 (looking-at "\\s-*$")))
675 ;; We differentiate four types changes
677 ;; - removed arguments
678 ;; - reordered arguments
679 ;; - renamed arguments
681 ;; If the change cannot be described by one of the above, it has
682 ;; to be resolved manually
685 ;; reordered arguments or new arguments (or no change)
686 (loop for defarg in defargs
687 for docarg = (assoc defarg docargs)
689 (insert (cadr docarg) (car docarg) (cddr docarg))
690 (insert indent " @param " defarg " \n"))))
691 (size-eq ; and (not doc-in-def)
693 (loop for defarg in defargs
694 for docarg in docargs
695 do (insert (cadr docarg) defarg (cddr docarg))))
698 (loop for defarg in defargs
699 for docarg = (assoc defarg docargs)
700 do (insert (cadr docarg) (car docarg) (cddr docarg))))
701 (t (error "Arg change too complex. Resolve manualy.")))
702 ;; return value is simple
706 (insert indent " @return \n")))
708 (insert indent " @throws " throws "\n")))
709 (back-to-indentation)))
711 (defun ccide-grab-prototype (&optional prefix)
712 "Grab prototype of function defined or declared at point. Prefix
713 arg, if given, specifies the kind of prefix (inline, static, ...) to use."
715 (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
716 ccide-default-prefix))
717 (defn (c-build-defun prfx)))
718 (kill-new (concat (cadr defn) "\n{}\n"))
719 (message (concat (or prfx "")
723 (defun ccide-reformat-defun ()
724 "Reformat the defn of the current defun."
727 (c-beginning-of-defun-or-decl)
728 (let ((defn (c-build-defun nil t)))
729 (delete-region (or (caar (aref (caddr defn) 0))
730 (car (aref (caddr defn) 1))
731 (car (aref (caddr defn) 2)))
732 (or (car (aref (caddr defn) 6))
733 (aref (caddr defn) 7)))
734 (insert (cadr defn) "\n"))))
736 (defun ccide-replace-defun ()
737 "Replace the function header with the one on the top of the kill
738 ring (presumably placed there using c++-grab-prototype)."
741 (c-beginning-of-defun-or-decl)
742 (let ((parse (c-parse-defun)))
743 (delete-region (or (aref parse 0)
751 (defun ccide-prefix-defun-type-with-class (&optional strip)
752 "If a non-keyword type symbol is found prefixing the current defun,
753 it will be prefixed with the current class prefix."
756 (c-beginning-of-defun-or-decl)
757 (let* ((parse (c-parse-defun))
758 (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
759 (goto-char (aref parse 1))
760 (while (and (or (looking-at c-any-key)
761 (looking-at c-user-prefix-re)
762 (not (c-at-symbol-p)))
763 (< (point) (aref parse 2))
766 (c-forward-syntactic-ws))
767 (if (and (c-at-symbol-p)
768 (< (point) (aref parse 2))
769 (not (looking-at (regexp-quote prefix))))
770 (let ((pos (string-match "<" prefix)))
771 (if (and pos (looking-at (concat (substring prefix 0 pos)
774 (goto-char (match-end 0))
775 (c-backward-syntactic-ws)
776 (insert (substring prefix pos)))
777 (insert prefix "::"))
778 (ccide-reformat-defun))))))
780 (defun ccide-prefix-defun-type-with-namespace (&optional strip)
782 (ccide-prefix-defun-type-with-class (+ (or strip 0) 1)))
784 (defun ccide-insert-defun-prefix (&optional strip)
785 "Insert the current defun prefix at point."
787 (let* ((parse (c-parse-defun))
788 (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
789 (insert prefix "::")))
791 (defun ccide-kill-inline-decl (defn)
793 (if (aref (caddr defn) 6)
795 (goto-char (cdr (aref (caddr defn) 6)))
796 (let ((end-mark (point-marker)))
797 (goto-char (car (aref (caddr defn) 6)))
798 (indent-rigidly (point) end-mark
799 (- (current-column)))
803 (buffer-substring-no-properties (point) end-mark)
805 (when (aref (caddr defn) 5)
806 (goto-char (caar (aref (caddr defn) 5)))
807 (c-backward-syntactic-ws)
808 (skip-chars-backward ":"))
809 (c-backward-syntactic-ws)
810 (delete-region (point) end-mark)
812 (concat (cadr defn) "\n{}\n"))))
814 (defun ccide-grab-inline-decl ()
815 "Grab the inline decl at point at turn it into an out-of-line inline
816 declaration at the top of the kill ring."
818 (let ((defn (c-build-defun (or ccide-default-prefix "inline"))))
819 (kill-new (ccide-kill-inline-decl defn))
820 (message (concat (or ccide-default-prefix "indline")
824 (defun ccide-grab-all-inlines ()
825 "Grab all inline decls in the current class"
827 (let ((class (c-parse-class (c-get-block-scope)))
830 (loop for method in (nreverse (aref class 4))
831 do (when (eq (car method) 'method)
832 (let ((defn (save-excursion
833 (goto-char (cdr method))
834 (c-build-defun (or ccide-default-prefix "inline")))))
835 (if (aref (caddr defn) 6)
836 (setq defns (nconc defns (list (ccide-kill-inline-decl defn))))))))
837 (kill-new (loop for defn in (nreverse defns)
838 for next = nil then t
841 (message (format "%d inlines grabed to kill ring" (length defns))))))
844 (defun ccide-grab-create-constructor ()
846 (let ((defn (c-build-create-constructor)))
847 (kill-new (cadr defn))
848 (message (car defn))))
850 (defun ccide-grab-create-constructor-impl (&optional prefix)
852 (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
853 ccide-default-prefix))
854 (defn (c-build-create-constructor-impl prfx)))
855 (kill-new (cadr defn))
856 (message (concat (or prfx "")
860 ;; (defun ccide-find-implementation (&optional other-window)
861 ;; "Find implementation of method declared at point."
863 ;; (let ((def (c-build-defun))
865 ;; (setq match (concat (regexp-quote (car def)) "[ \t\n\r]*("))
866 ;; (setq match (string-replace "::" "::[ \t\n\r]*" match t nil t t))
868 ;; (loop for ext in ccide-implementation-extensions
869 ;; do (let* ((filename (ccide-file-name ext))
870 ;; (buf (and (file-readable-p filename) (find-file-noselect filename))))
874 ;; (goto-char (point-min))
875 ;; (if (loop while (search-forward-regexp match nil t)
876 ;; do (forward-char -1)
877 ;; thereis (c-at-toplevel-p))
878 ;; (setq pos (cons buf (point)))))))
881 ;; (let ((win (get-buffer-window (car pos))))
883 ;; (select-window win)
885 ;; (switch-to-buffer-other-window (car pos))
886 ;; (switch-to-buffer (car pos))))
887 ;; (goto-char (cdr pos))
889 ;; (c-beginning-of-defun-or-decl))
890 ;; (message (concat "Implementation of " (car def) " not found.")))))
892 (defun ccide-find-implementation (&optional other-window)
893 "Find implementation of method declared at point."
895 (let* ((state (c-get-defun-state))
896 (name (c-defun-short-name state))
897 (scoped-name (c-defun-full-name state))
898 (args (ccide-implementation-args state))
901 (loop for ext in ccide-implementation-extensions
902 for filename = (ccide-file-name ext)
905 (let ((buf (or (find-buffer-visiting filename)
906 (and (file-readable-p filename)
907 (find-file-noselect filename)))))
909 (let ((found (save-excursion
911 (ccide-find-implementation-1 name scoped-name args
912 (car (aref state 2))))))
915 (setq rv (cons buf found))
916 (if (not fallback) (setq fallback (cons buf found))))))))))
917 (if (not rv) (setq rv fallback))
919 (let* ((buf (car rv))
921 (win (get-buffer-window buf)))
925 (switch-to-buffer-other-window buf)
926 (switch-to-buffer buf)))
929 (c-beginning-of-defun-or-decl))
930 (message (concat "Implementation of " scoped-name " not found.")))))
932 (defun ccide-implementation-args (state)
933 (string-replace "[ \t\n\r]+" ""
934 (loop for (start . end) in (aref state 3)
935 for sep = "" then ","
937 concat (buffer-substring-no-properties
938 start (save-excursion
940 (if (search-forward "=" end 'move) (forward-char -1))
945 (defun ccide-find-implementation-1 (name scoped-name args skip-def)
946 ;; Within the current buffer, search for all implementations of the
947 ;; given function. The rv is a list of conses. The car holds the
948 ;; buffer position of the implementation, the cdr is t if the name,
949 ;; scoped-name and args are matched, otherwise the args did not match.
951 (goto-char (point-min))
952 (let (fallback rv check-state)
953 (while (and (not rv) (search-forward name nil t))
954 (if (and (c-at-toplevel-p)
956 (setq check-state (condition-case nil (c-get-defun-state) (error nil)))
957 (not (= (car (aref check-state 2)) skip-def)))
958 (if (string= scoped-name (c-defun-full-name check-state))
959 (if (string= args (ccide-implementation-args check-state))
960 (setq rv (cons (point) t))
962 (setq fallback (cons (point) nil)))))))
965 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
966 ;; variable/type level
968 (defun ccide-variable-comment ()
969 "Add a comment to current variable declaration."
975 (indent-according-to-mode))
977 (defun ccide-grab-access-fn ()
981 (if (looking-at (concat c++-simple-type-regexp "[ \t\n\r][a-zA-Z0-9_]+[ \t\n\r]*;"))
982 (let ((vardef (match-string 0))
983 (in (make-string c-basic-offset ? ))
986 (back-to-indentation)
987 (if (looking-at "///[ \t\n\r]*")
988 (setq doc (buffer-substring (match-end 0)
989 (progn (end-of-line) (point)))))
990 (string-match "^[ \t\n\r]*\\(.*\\)[ \t\n\r]\\([a-zA-Z0-9_]+\\)[ \t\n\r]*;$"
992 (setq varname (match-string 2 vardef)
993 type (match-string 1 vardef)
994 ws (substring vardef 0 (match-beginning 1)))
995 (if (string-match "^[ \t\n\r]*" type)
996 (setq type (substring type (match-end 0))))
997 (kill-new (concat (if doc
998 (concat ws "/** Setze " doc ".\n\n"
999 ws " @param _" varname " neu: " doc "\n"
1000 ws " @return alt: " doc "\n"
1003 ws type " q_" varname "(" type " _" varname ")\n"
1005 ws in in type " old" varname " = " varname ";\n"
1006 ws in in varname " = _" varname ";\n"
1007 ws in in "return(old" varname ");\n"
1010 (concat ws "/** Hole " doc ".\n\n"
1011 ws " @return " doc "\n"
1014 ws type " q_" varname "(void) const\n"
1015 ws in "{ return(" varname "); }\n"))
1018 (message "No variable found"))))
1020 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1021 ;; doxy comment support functions
1023 (defun ccide-special-indent-function ()
1024 "Function to indent doxy comments correctly"
1025 (let ((indent (ccide-in-doxy-comment)))
1027 (let ((lim (save-excursion
1028 (back-to-indentation)
1029 (c-literal-limits)))
1030 (pos (- (point-max) (point))))
1033 (back-to-indentation)
1034 (if (looking-at "*/")
1036 (let ((para (or (save-excursion (re-search-backward "^\\s-*$" (car lim) t))
1038 (if (and (not (looking-at ccide-doxy-tag-re))
1039 (re-search-backward (concat "^\\s-*"
1043 (delete-region (progn (beginning-of-line) (point))
1044 (progn (back-to-indentation) (point)))
1046 (if (> (- (point-max) pos) (point))
1047 (goto-char (- (point-max) pos)))))))
1049 (defun ccide-fill-function ()
1050 "auto-fill function for doxy comments"
1052 (if (not fill-prefix)
1053 (indent-according-to-mode))))
1055 (defun ccide-hide-all-doxy-comments ()
1056 "Hide all doxy comments"
1059 (goto-char (point-min))
1060 (while (re-search-forward "^\\s-*/\\*\\*" nil t)
1063 (if (not (looking-at "\\s-*$"))
1066 (let ((start (point)))
1067 (if (re-search-forward "\\*/" nil t)
1069 (if (looking-at "\\s-*\n")
1072 (let ((overlay (make-overlay start (point))))
1073 (overlay-put overlay 'intangible 'hs)
1074 (overlay-put overlay 'invisible 'hs)))))))
1077 (defun ccide-show-all-comments ()
1081 (goto-char (point-min))
1083 (goto-char (next-overlay-change (point)))
1084 (loop for overlay in (overlays-at (point))
1085 if (eq (overlay-get overlay 'invisible) 'hs)
1086 do (delete-overlay overlay))))
1091 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1092 ;; CORBA support (omniORB2)
1094 (defun ccide-get-corba-headers ()
1097 (goto-char (point-min))
1098 (while (re-search-forward "#include\\s-*[\"<]\\([^\">]*\\)\\.hh[\">]" nil t)
1099 (setq files (cons (ccide-match-string 1) files)))
1102 (defun ccide-corba-maybe-build-hh (file)
1103 (let ((skel (ccide-file-name ".hh" file ccide-corba-skel-dir))
1104 (idl (ccide-file-name ".idl" file ccide-corba-idl-dir)))
1105 (if (and (file-readable-p idl)
1106 (or (not (file-readable-p skel))
1107 (file-newer-than-file-p idl skel)))
1108 (let ((buffer (find-buffer-visiting (ccide-file-name ".hh" file))))
1110 (kill-buffer buffer))
1111 (message "Please wait ... building %s" (ccide-file-name ".hh" file))
1112 (if (ccide-shell-command (concat "cd "
1113 (real-path-name ccide-corba-skel-dir)
1115 ccide-corba-idl-command
1116 (if (> (length ccide-corba-idl-dir) 0)
1117 (concat " -I" ccide-corba-idl-dir))
1121 (display-buffer (get-buffer-create "*ccide shell command*"))
1122 (error "Generation of %s failed" (ccide-file-name ".hh")))))
1123 (if (not (file-readable-p skel))
1124 (error "No file %s or %s"
1125 (ccide-file-name ".hh" file) (ccide-file-name ".idl" file)))))
1127 (defun ccide-corba-list-skeletons-1 (hh-file)
1128 (ccide-corba-maybe-build-hh hh-file)
1129 (let ((hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file)))
1134 (goto-char (point-min))
1135 (while (re-search-forward "^\\s-*class\\s-+_sk_\\([a-zA-Z0-9_]+\\)\\s-+:"
1137 (setq skels (cons (ccide-match-string 1) skels)))))
1138 (mapcar (function (lambda (x) (cons x hh-file)))
1139 (sort skels 'string-lessp))))
1141 (defun ccide-corba-list-skeletons ()
1142 (let ((files (ccide-get-corba-headers)))
1143 (loop for file in files
1144 append (ccide-corba-list-skeletons-1 file))))
1146 (defun ccide-gen-corba-impl (class)
1147 (interactive (list (completing-read "Class name of skeleton: "
1148 (ccide-corba-list-skeletons)
1150 (let* ((skels (ccide-corba-list-skeletons))
1151 (hh-file (ccide-file-name ".hh" (cdr (assoc class skels))
1152 ccide-corba-skel-dir))
1153 (hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file
1154 ccide-corba-skel-dir))))
1155 (ccide-gen-class (concat class "_i"))
1156 (insert (make-string c-basic-offset ? ) ": public virtual _sk_" class "\n")
1158 (search-forward "protected:" nil t)
1160 (ccide-gen-corba-impl-methods)
1163 (defun ccide-get-corba-defns (hh-file class)
1164 (let ((hh-buf (find-file-noselect hh-file))
1169 (goto-char (point-min))
1170 (if (not (re-search-forward (concat "^\\s-*class\\s-+_sk_" class "\\s-+:")
1172 (error "CORBA skeleton class not found.")
1173 (search-forward "{")
1175 (let ((end (save-excursion (forward-sexp) (point))))
1176 (while (and (< (point) end)
1177 (< (forward-line 1) 1))
1178 (if (looking-at "\\s-+virtual\\s-+\\(.*)\\)\\s-*=\\s-*0;\\s-*$")
1179 (setq defns (cons (match-string 1) defns))))))))
1182 (defun ccide-gen-corba-impl-methods ()
1184 (let* ((class (c-get-class-at-point))
1187 (error "No class at point."))
1189 (goto-char (aref (car class) 1))
1190 (if (not (re-search-forward ":\\s-*public\\s-*virtual\\s-*_sk_\\([^ \t\n\r{},:]*\\)"
1192 (error "No CORBA impl at point."))
1193 (let* ((name (ccide-match-string 1))
1194 (skels (ccide-corba-list-skeletons))
1195 (hh-file (ccide-file-name ".hh" (cdr (assoc name skels))
1196 ccide-corba-skel-dir))
1197 (defns (ccide-get-corba-defns hh-file name))
1199 (goto-char (aref (car class) 2))
1203 (if (re-search-forward "^\\s-*// CORBA$" end t)
1204 (let ((start (match-beginning 0)))
1205 (if (re-search-forward "^\\s-*// END-CORBA$" end t)
1206 (let ((eend (match-end 0)))
1209 (if (re-search-forward "/\\*\\|//" (match-beginning 0) t)
1210 (if (y-or-n-p "Remove CORBA Funktion comments? (y/n)")
1211 (delete-region start (1+ eend))
1214 (delete-region (point) (progn
1219 (delete-region (point) (progn
1223 (delete-region start (1+ eend))))))
1225 (indent-according-to-mode)
1226 (insert "// CORBA\n")
1227 (loop for defn in defns
1229 (save-excursion (insert defn ";"))
1230 (indent-according-to-mode)
1231 (let ((start (point)) end)
1235 (while (re-search-forward "\\s-+" end t)
1237 (setq end (- end (- (match-end 0) (match-beginning 0) 1))))
1239 (loop with done = nil
1240 while (> (current-column) c-max-def-column)
1241 do (while (and (> (current-column) c-max-def-column)
1242 (search-backward "," start t)))
1243 do (if (looking-at ",")
1248 (indent-according-to-mode)
1250 (setq start (point))
1255 (indent-according-to-mode)
1256 (insert "// END-CORBA\n")))))
1258 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1261 (defun ccide-scan-mantemps ()
1262 "Scan *compilation* buffer for errors and generate manual template
1263 instatiations at point."
1266 (set-buffer "*compilation*")
1267 (goto-char (point-min)))
1269 (set-buffer (get-buffer-create "*mantemps*"))
1271 (loop for temp = (ccide-get-mantemp)
1273 do (insert temp "\n"))
1274 (mantemp-make-mantemps-buffer)
1275 (goto-char (point-min))
1278 (< (forward-line 1) 1))))
1279 (insert-buffer-substring "*mantemps*"))
1281 (defun ccide-get-mantemp ()
1283 (set-buffer "*compilation*")
1284 (if (search-forward "undefined reference to `" nil t)
1285 (let ((start (point)))
1287 (search-backward "'" nil t)
1288 (buffer-substring start (point))))))
1290 (defun ccide-fix-mantemp ()
1291 (let ((end (save-excursion
1292 (end-of-line) (point))))
1293 (if (and (save-excursion (search-forward "(" end t))
1294 (search-forward " class" end t))
1301 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1304 (defun ccide-open-compilation-frame ()
1306 (let ((c-frame (selected-frame))
1307 (compilation-frame (make-frame '((minibuffer . nil)
1309 (menu-bar-lines . 0)
1314 (select-frame compilation-frame)
1315 (switch-to-buffer "*compilation*")
1316 (set-window-dedicated-p (selected-window) t)))
1318 (defun ccide-compile (command)
1319 (delete-other-windows)
1320 (split-window-horizontally)
1323 (set-buffer "*compilation*")
1324 (let ((point (point-max)))
1326 (loop for window in (get-buffer-window-list "*compilation*" nil t)
1327 do (set-window-point window point)))))
1329 (defun ccide-compile-compile ()
1331 (ccide-compile (concat "make -k " ccide-compile-opts)))
1333 (defun ccide-compile-clean ()
1335 (ccide-compile (concat "make -k " ccide-compile-opts " clean")))
1337 (defun ccide-compile-cleandepends ()
1339 (ccide-compile (concat "make -k " ccide-compile-opts " cleandepends")))
1341 (defun ccide-compile-kill ()
1343 (set-buffer "*compilation*")
1346 (defun ccide-hide-compilation ()
1348 (let ((active (selected-window)))
1350 (loop for window in (get-buffer-window-list "*compilation*")
1351 do (progn (select-window window)
1352 (switch-to-buffer (other-buffer "*compilation*"))))
1353 (select-window active))))
1355 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1356 ;; keymap and installation
1358 (defun ccide-bind-keys (prefix map)
1359 (loop for binding in ccide-bindings
1360 do (apply 'vcmd-define-key
1362 (concat prefix (car binding))
1367 (defun ccide-install-it ()
1371 (local-unset-key "\C-c;")
1372 (local-unset-key [menu-bar IDE])
1373 (ccide-bind-keys "\C-c;" (current-local-map))
1374 (local-set-key "\C-cC" 'ccide-hide-all-doxy-comments)
1375 (local-set-key "\C-cS" 'ccide-show-all-comments)
1376 (set (make-local-variable 'auto-fill-function) 'ccide-fill-function)
1378 (ccide-auto-decorate-new-files))
1380 (add-hook 'c-mode-hook 'ccide-install-it)
1381 (add-hook 'c++-mode-hook 'ccide-install-it)
1382 (add-hook 'c-special-indent-hook 'ccide-special-indent-function)
1384 (loop for extension in ccide-special-extensions
1385 for re = (concat (regexp-quote extension) "$")
1386 if (not (assoc re auto-mode-alist))
1387 do (setq auto-mode-alist (append auto-mode-alist
1388 (list (cons re 'c++-mode)))))
1390 (defadvice c-indent-line (after c-indent-less compile disable) ;activate
1391 ;; new indent function for c-mode: do standard indentation first. If line
1392 ;; is to long using standard indentation, just indent by c-basic-indentation.
1393 (let ((cc (save-excursion (end-of-line) (current-column)))
1396 (let ((pos (- (point-max) (point))))
1398 (let ((point (point))
1399 (line (1+ (count-lines 1 (point))))
1401 (c-beginning-of-statement-2)
1402 (if (and (not (c-crosses-statement-barrier-p (point) point))
1403 (not (eq (+ (count-lines 1 (point))
1407 (setq indent (+ (current-indentation) c-basic-offset))
1409 (if (< indent (current-indentation))
1411 (setq ad-return-value
1413 (- (current-indentation) indent)))
1414 (delete-region (c-point 'bol) (c-point 'boi))
1415 (indent-to indent))))))
1416 (if (< (point) (c-point 'boi))
1417 (back-to-indentation)
1418 (if (> (- (point-max) pos) (point))
1419 (goto-char (- (point-max) pos))))))))
1423 ;;; Local Variables:
1424 ;;; elisp-project-autoload-file-name: "cc-autoload.el"