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-project-name nil)
36 (defvar ccide-all-includes nil
37 "*If non-nil, this is the name of a file to include to fetch all
38 includes of a project. This is used if single include files cannot be
41 (defvar ccide-corba-skel-dir "")
42 (defvar ccide-corba-idl-dir "")
43 (defvar ccide-corba-idl-command "omniidl2 -w")
45 (defvar c-user-prefixes '("inline" "static" "prefix_")
46 "*List of possible prefixes for function definitions.")
48 (defvar ccide-default-prefix "prefix_"
49 "*Prefix added to every implementation header. Probably eiter empty or 'prefix_'")
51 (defvar ccide-gen-throw nil
52 "*If non-nil, generate throw_ specs")
54 (defvar ccide-project-root nil)
56 (defvar ccide-new-file-hook nil)
58 (defvar ccide-new-file-command nil)
60 (defvar ccide-clang-format-command nil)
62 (defvar ccide-uncrustify-command "uncrustify")
63 (defvar ccide-uncrustify-config nil)
64 (defvar ccide-auto-format-tag nil)
66 (defconst c-user-prefix-re (regexp-opt c-user-prefixes t))
68 (defconst ccide-doxy-tag-re
69 (concat "\\\\\\(group\\|defgroup\\|see\\|author\\|version\\|id\\|since"
70 "\\|returns?\\|throws?\\|exception\\|raises\\|param\\|li\\|brief"
71 "\\|internal\\|bug\\|fixme\\|todo\\|idea\\|implementation"
72 "\\|note\\|attention\\|warning\\|par\\|code\\|endcode"
73 "\\|post\\|pre\\|deprecated\\)\\b"))
75 (defconst ccide-special-extensions
76 '(".h" ".hh" ".mpp" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci" ".dox"))
78 (defconst ccide-implementation-extensions
79 '(".h" ".hh" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci"))
81 (defconst ccide-class-defaults-word
82 "// \\(default\\|no\\|protected\\|private\\|disabled\\|my\\)")
84 (defconst ccide-bindings
87 ("fc" ccide-file-comment "File comment")
88 ("fs" ccide-syncronize-includes "Sync includes")
89 ("ff" ccide-clang-format-buffer "Reformat buffer")
93 ("cc" ccide-class-comment "Class comment")
94 ("cg" ccide-gen-class "Generate class")
95 ("cd" ccide-gen-class-defaults "Generate class defaults")
96 ("cD" ccide-gen-class-defaults-impl "Generate class defaults impl")
98 ("csd" ccide-set-class-defaults-default "Set class defaults comment" "Default")
99 ("csn" ccide-set-class-defaults-no "Set class defaults comment" "No")
100 ("csp" ccide-set-class-defaults-protected "Set class defaults comment" "Protected")
101 ("csr" ccide-set-class-defaults-private "Set class defaults comment" "Private")
102 ("csx" ccide-set-class-defaults-disabled "Set class defaults comment" "Disabled")
103 ("csm" ccide-set-class-defaults-my "Set class defaults comment" "My")
105 ("cS" ccide-gen-struct-constructors "Generate structure constructors")
106 ("c<" ccide-gen-struct-compare "Generate structure compare operators")
108 ("ci" ccide-class-impl-comment "Generate class implemenation comment")
110 ("ce" ccide-gen-exception "Generate an exception class")
115 ("mc" ccide-function-comment "Method comment")
116 ("mp" ccide-grab-prototype "Grab prototype")
117 ("mr" ccide-reformat-defun "Reformat defun")
118 ("mx" ccide-replace-defun "Replace defun")
119 ("mt" ccide-prefix-defun-type-with-class "Prefix defun type with class")
120 ("mn" ccide-prefix-defun-type-with-namespace "Prefix defun type with namespace")
121 ("mi" ccide-grab-inline-decl "Grab inline decl")
122 ("mA" ccide-grab-all-inlines "Grab ALL inline decls")
123 ("mC" ccide-grab-create-constructor "Grab CREATE constructor")
124 ("mI" ccide-grab-create-constructor-impl "Build CREATE cosntructor")
125 ("mf" ccide-find-implementation "Find method implementation")
126 ("mT" ccide-insert-defun-prefix "Insert current defun prefix at point")
130 ("vc" ccide-variable-comment "Variable comment")
131 ("vf" ccide-grab-access-fn "Grab access methods")
135 ("h" ccide-hide-all-doxy-comments "Hide all Doxygen comments")
136 ("s" ccide-show-all-comments "Show all Doxygen comments")
139 ("yp" ccide-grab-pxd-fn "Generate pxd function/method decl")
142 ; ("Cg" ccide-gen-corba-impl "Generate CORBA impl")
143 ; ("Cm" ccide-gen-corba-impl-methods "Generate CORBA impl methods")
144 ; (nil nil separator)
147 ; ("ts" ccide-scan-mantemps "Scan mantemps")
148 ; (nil nil separator)
151 ; ("of" ccide-open-compilation-frame "Open *compilation* frame")
152 ; ("oc" ccide-compile-compile "Make -> Compile")
153 ; ("ox" ccide-compile-clean "Make -> Clean")
154 ; ("od" ccide-compile-cleandepends "Make -> Clean depends")
155 ; ("ok" ccide-compile-kill "Kill compilation")
156 ; ("oh" ccide-hide-compilation "Hide *compilation* buffer")
162 (require 'cc-engine-2)
171 (require 'misc-local)
173 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
176 (defsubst ccide-match-string (n)
177 (buffer-substring-no-properties (match-beginning n) (match-end n)))
179 (defun ccide-file-macro-name (&optional file-name)
180 (concat (upcase (file-name-extension (or file-name (buffer-file-name))))
182 (if ccide-project-name (concat ccide-project-name "_") "")
183 (if ccide-project-root
184 (string-replace "/" "_"
185 (substring (file-name-directory
186 (expand-file-name (or file-name buffer-file-name)))
187 (length ccide-project-root))
190 (string-replace "\\." "_" (file-name-sans-extension
191 (file-name-nondirectory
192 (or file-name (buffer-file-name))))
196 (defun ccide-file-name (&optional extension file-name directory)
197 (concat (if directory (file-name-as-directory directory) "")
198 (file-name-sans-extension
199 (file-name-nondirectory
200 (or file-name (buffer-file-name))))
203 (defun ccide-in-doxy-comment ()
205 (back-to-indentation)
206 (let ((lit (c-in-literal)))
207 (when (and (memq lit '(c c++))
208 (progn (goto-char (car (c-literal-limits)))
209 (looking-at "/\\(\\*\\*\\|///\\)<?[ \t\n\r@]")))
210 (goto-char (match-end 0))
213 (defun ccide-shell-command (command)
214 (let ((obuf (get-buffer-create "*ccide shell command*"))
219 (insert command "\n"))
220 (setq exit-status (call-process shell-file-name nil "*ccide shell command*" nil
221 shell-command-switch command))
222 (and exit-status (equal exit-status 0))))
224 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
227 (defun ccide-file-comment ()
228 "Add a comment to this source file."
233 (goto-char (point-min))
236 "// Copyright (C) " (number-to-string (nth 5 (decode-time)))
237 " " ccide-default-author "\n"
238 ccide-default-copyright
241 (cond ((string-match "\\.hh?$" (buffer-file-name))
242 (insert "/** \\file\n"
243 " \\brief " (ccide-file-name) " public header */\n\n"
244 "#ifndef " (ccide-file-macro-name) "\n"
245 "#define " (ccide-file-macro-name) " 1\n\n")
246 (if ccide-all-includes
247 (insert "#ifndef " (ccide-file-macro-name ccide-all-includes) "\n"
248 "#error \"Don't include '" (file-name-nondirectory (buffer-file-name)) "'"
249 " directly, include '" ccide-all-includes "'\"\n"
251 (insert "// Custom includes\n\n"
252 "//#include \"" (ccide-file-name ".mpp") "\"\n"
253 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
255 (goto-char (point-max))
256 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n")
257 (if ccide-all-includes
259 "#if !defined(" (ccide-file-macro-name ccide-all-includes) "_decls_) "
260 "&& !defined(" (ccide-file-macro-name) "i_)\n"
261 "#define " (ccide-file-macro-name) "i_\n"))
262 (insert "//#include \"" (ccide-file-name ".cci") "\"\n"
263 "//#include \"" (ccide-file-name ".ct") "\"\n"
264 "//#include \"" (ccide-file-name ".cti") "\"\n"
267 ((string-match "\\.mpp$" (buffer-file-name))
268 (insert "/** \\file\n"
269 " \\brief " (ccide-file-name) " Boost.Preprocesser external iteration include */\n\n"
272 "#if !BOOST_PP_IS_ITERATING && !defined(" (ccide-file-macro-name) ")\n"
273 "#define " (ccide-file-macro-name) " 1\n\n"
274 "// Custom includes\n\n\n"
275 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
276 "#elif BOOST_PP_IS_ITERATING //-/////////////////////////////////////////////////////////////////////\n"
277 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
278 "// Local Macros\n\n\n"
279 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
280 "#if BOOST_PP_ITERATION_FLAGS()==1 //-///////////////////////////////////////////////////////////////\n"
281 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
283 (goto-char (point-max))
284 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
285 "#endif //-//////////////////////////////////////////////////////////////////////////////////////////\n"
286 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
287 "// Undefine local Macros\n\n\n"
288 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
289 "#endif //-//////////////////////////////////////////////////////////////////////////////////////////\n"
290 "//-/////////////////////////////////////////////////////////////////////////////////////////////////"))
292 ((string-match "\\.ih$" (buffer-file-name))
293 (insert "/** \\file\n"
294 " \\brief " (ccide-file-name) " internal header */\n\n"
295 "#ifndef " (ccide-file-macro-name) "\n"
296 "#define " (ccide-file-macro-name) " 1\n\n"
297 "// Custom includes\n\n"
298 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
300 (goto-char (point-max))
301 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
304 ((or (string-match "\\.test\\.cc$" (buffer-file-name))
305 (string-match "\\.test\\.cpp$" (buffer-file-name)))
306 (insert "/** \\file\n"
307 " \\brief " (ccide-file-name) " unit tests */\n\n"
308 "//#include \"" (ccide-file-name ".hh") "\"\n"
309 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
310 "// Custom includes\n"
311 "#include \"" (or ccide-all-includes
312 (ccide-file-name ".hh" (ccide-file-name))) "\"\n\n"
313 "#include <boost/test/auto_unit_test.hpp>\n"
314 "#include <boost/test/test_tools.hpp>\n\n"
316 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
318 (goto-char (point-max))
319 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
322 ((or (string-match "\\.cc$" (buffer-file-name))
323 (string-match "\\.cpp$" (buffer-file-name)))
324 (insert "/** \\file\n"
325 " \\brief " (ccide-file-name) " non-inline non-template implementation */\n\n"
326 (if ccide-all-includes "" "//")
327 "#include \"" (or ccide-all-includes (ccide-file-name ".hh")) "\"\n"
328 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
329 "// Custom includes\n\n"
330 "//#include \"" (ccide-file-name ".mpp") "\"\n"
332 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
334 (goto-char (point-max))
335 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
337 "//#include \"" (ccide-file-name ".mpp") "\""))
339 ((string-match "\\.cci$" (buffer-file-name))
340 (insert "/** \\file\n"
341 " \\brief " (ccide-file-name) " inline non-template implementation */\n\n"
342 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
343 "// Custom includes\n\n"
344 "#define prefix_ inline\n"
345 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
347 (goto-char (point-max))
348 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
351 ((string-match "\\.ct$" (buffer-file-name))
352 (insert "/** \\file\n"
353 " \\brief " (ccide-file-name) " non-inline template implementation */\n\n"
354 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
355 "// Custom includes\n\n"
357 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
359 (goto-char (point-max))
360 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
363 ((string-match "\\.cti$" (buffer-file-name))
364 (insert "/** \\file\n"
365 " \\brief " (ccide-file-name) " inline template implementation */\n\n"
366 "//#include \"" (ccide-file-name ".ih") "\"\n\n"
367 "// Custom includes\n\n"
368 "#define prefix_ inline\n"
369 "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
371 (goto-char (point-max))
372 (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
375 ((string-match "\\.dox$" (buffer-file-name))
376 (insert "/** \\mainpage\n\n ")
379 (setq add-file-vars '(( mode . flyspell)
380 ( mode . auto-fill))))
382 ((string-match "\\.java$" (buffer-file-name))
385 (goto-char (point-max)))
389 (goto-char (point-max))))
392 "// Local Variables:\n"
393 "// mode: " mode "\n")
394 (loop for (var . value) in ccide-file-vars
395 do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
396 (loop for (var . value) in add-file-vars
397 do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
401 (if (equal mode "jde")
402 (let ((package (file-name-directory (buffer-file-name))))
403 (jdeap-initialize-setup)
404 (if (not (equal jdeap-current-source-directory "."))
406 (concat "^" (regexp-quote jdeap-current-source-directory))
409 (setq package (substring package
411 (1- (length package))))
413 (string-replace "/" "." package t)
415 (insert "class " (file-name-sans-extension
416 (file-name-nondirectory
417 (buffer-file-name))) "\n{}")
418 (beginning-of-line))))
419 (run-hooks 'ccide-new-file-hooks))
421 (defun ccide-sync-file-variables ()
422 "Syncronize file variables to the current value of ccide-file-vars"
425 (goto-char (point-max))
426 (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
427 (let ((case-fold-search t))
428 (if (search-forward "Local Variables:" nil t)
429 (let (prefix suffix vars)
430 (skip-chars-forward " \t")
432 (setq suffix (buffer-substring (point) (progn (end-of-line) (point)))))
433 (goto-char (match-beginning 0))
435 (setq prefix (buffer-substring (point) (progn (beginning-of-line) (point)))))
438 (if (and prefix (looking-at prefix))
439 (goto-char (match-end 0)))
440 (skip-chars-forward " \t"))
441 while (not (looking-at "end:"))
443 (setq vars (cons (intern (buffer-substring
445 (progn (skip-chars-forward "^:\n") (point))))
448 (loop for (var . value) in ccide-file-vars
449 do (if (not (memq var vars))
450 (insert (or prefix "")
451 (symbol-name var) ": " (prin1-to-string value)
452 (or suffix "") "\n"))))))))
454 (defun ccide-syncronize-includes ()
455 "Syncronize include's in all other files"
458 (loop for extension in ccide-special-extensions
459 for file-name = (ccide-file-name extension)
461 (cons (cons file-name
462 (or (find-buffer-visiting file-name)
463 (and (file-readable-p file-name)
464 (find-file-noselect file-name))))
467 (loop for buffer in buffer-map
470 (set-buffer (cdr buffer))
472 (loop for include in buffer-map
474 (goto-char (point-min))
475 (while (re-search-forward
476 (concat "^\\(//\\)?#\\s-*include \""
477 (regexp-quote (car include))
480 (goto-char (match-beginning 0))
481 (if (looking-at "//")
484 (if (not (cdr include))
486 (forward-line 1))))))))))
488 (defun ccide-auto-decorate-new-files ()
489 (if (and (buffer-file-name) (= (point-min) (point-max)))
490 (if (or (not ccide-new-file-command)
495 (shell-command (format "%s %s" ccide-new-file-command (buffer-file-name)))
496 (revert-buffer t t t)
499 (let ((status (buffer-modified-p)))
501 (set-buffer-modified-p status)))))
503 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
506 (defun ccide-class-comment ()
507 "Add comment to start of current class definition"
509 (let ((class (c-get-class-at-point)))
511 (error "No class found")
512 (goto-char (or (aref (car class) 3)
513 (aref (car class) 1)))
516 (ccide-in-doxy-comment))
518 (search-backward "/**" nil t)
520 (let ((indent (make-string (current-indentation) ? )))
521 (insert "/** \\brief ")
527 (defun ccide-gen-class (name &optional defns)
528 "Generate class declaration template"
529 (interactive (list (read-string (concat "Class name (default "
532 nil nil (ccide-file-name))))
533 (insert "class " name)
534 (indent-according-to-mode)
535 (let ((in (make-string c-basic-offset ? ))
536 (ofs (make-string (current-indentation) ? ))
537 (sl (make-string (- 100 3 c-basic-offset (current-indentation)) ?/)))
541 (insert ofs "/** \\brief\n"
548 ofs in "// Types\n\n"
550 ofs in "///\\name Structors and default members\n"
552 ofs in "// default default constructor\n"
553 ofs in "// default copy constructor\n"
554 ofs in "// default copy assignment\n"
555 ofs in "// default destructor\n\n"
556 ofs in "// no conversion constructors\n\n"
559 ofs in "///\\name Accessors\n"
563 ofs in "///\\name Mutators\n"
566 (loop for defn in defns
567 do (insert ofs in defn ";\n"))
570 (insert ofs "protected:\n\n"
574 (defun ccide-gen-class-defaults ()
575 "Generate signatures of the default functions: default constructor,
576 copy constructor, assignment operator and destructor."
577 (indent-according-to-mode)
578 (let* ((name (c-scope-name (aref (car (c-get-class-at-point)) 1)))
579 (in (make-string c-basic-offset ? ))
580 (ofs (make-string (current-indentation) ? ))
581 (tspec (if ccide-gen-throw (concat "\n" ofs in "throw_(());\n") ";\n"))
583 (while (string-match "::" name colon)
584 (setq colon (match-end 0)))
585 (setq name (substring name colon))
587 (delete-horizontal-space)
588 (loop with exit = nil
589 do (message (concat "1-dflt constr, 2-destr, "
590 "3-copy constr, 4-copy assmnt, "
591 "c-all copy, d-all dflt, RET-all/done: "))
592 for ch = (read-event)
593 for first = t then nil
594 do (cond ((eq ch 'return)
596 (insert ofs name "()"
598 ofs name "(const " name "& other)"
601 ofs name "& operator=(const " name "& other)"
605 (insert ofs name "()"
608 (insert ofs "~" name "();\n"))
610 (insert ofs name "(const " name "& other)"
613 (insert ofs name "& operator=(const " name "& other)"
616 (insert ofs name "(const " name "& other)"
618 ofs name "& operator=(const " name "& other)"
621 (insert ofs name "()"
623 ofs "~" name "();\n"))
624 (t (setq unread-command-events (cons ch unread-command-events))
628 (defun ccide-gen-class-defaults-impl ()
629 "Generate default implementations for class default functions"
631 (let ((defn (c-build-default-funcions-impl)))
632 (kill-new (cadr defn))
633 (message (concat (car defn) " default members"))))
635 (defun ccide-set-class-defaults-comment (word)
637 (back-to-indentation)
638 (if (not (looking-at ccide-class-defaults-word))
639 (message "Not at class defaults commnet")
640 (replace-match word t t nil 1))))
642 (defmacro ccide-build-class-defaults-f (sym)
643 (let ((fn (intern (concat "ccide-set-class-defaults-"
644 (symbol-name sym)))))
647 (ccide-set-class-defaults-comment ,(symbol-name sym)))))
649 (ccide-build-class-defaults-f no)
650 (ccide-build-class-defaults-f default)
651 (ccide-build-class-defaults-f my)
652 (ccide-build-class-defaults-f protected)
653 (ccide-build-class-defaults-f private)
654 (ccide-build-class-defaults-f disabled)
656 (defun ccide-gen-struct-constructors ()
661 (indent-according-to-mode)
662 (let* ((scope (c-get-block-scope))
663 (class (c-parse-class scope))
664 (variables (c-get-variable-members-with-type class))
665 (name (c-scope-name (aref (car (last scope)) 1)))
666 (in (make-string (current-indentation) ? ))
667 (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
668 (insert name "()\n" inin ": ")
669 (loop for var in variables
670 for first = t then nil
671 if (not first) do (insert ", ")
672 do (insert (car var) " ()"))
675 (loop for var in variables
676 for first = t then nil
677 if (not first) do (insert ", ")
678 do (insert (cdr var) " " (car var) "_"))
679 (insert ")\n" inin ": ")
680 (loop for var in variables
681 for first = t then nil
682 if (not first) do (insert ", ")
683 do (insert (car var) " (" (car var) "_)"))
687 (defun ccide-gen-struct-compare ()
692 (indent-according-to-mode)
693 (let* ((scope (c-get-block-scope))
694 (class (c-parse-class scope))
695 (variables (c-get-variable-members-with-type class))
696 (name (c-scope-name (aref (car (last scope)) 1)))
697 (in (make-string (current-indentation) ? ))
698 (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
700 (insert "bool operator<(" name " const & other) const\n"
702 (loop for ((varName . varType) . tail) on variables
703 do (insert inin varName " < other." varName " ? true :")
705 (insert "\n" inin "other." varName " < " varName " ? false :\n")
706 (insert " false; }\n\n")))
707 (insert in "bool operator==(" name " const & other) const\n"
709 (loop for ((varName . varType) . tail) on variables
710 do (insert inin varName " == other." varName)
711 do (if tail (insert " &&\n") (insert "; }\n\n")))
712 (insert in "std::size_type hash_value() const\n"
713 in "{ std::size_t current (0);\n")
714 (loop for ((varName . varType) . tail) on variables
715 do (insert inin "boost::hash_combine(current, " varName ");\n"))
716 (insert inin "return current; }\n\n")
717 (insert in "void write(std::ostream & os) const\n"
719 (loop for ((varName . varType) . tail) on variables
720 do (insert "\n" inin "<< " varName)
721 do (if tail (insert " << ' '")))
722 (insert " << \" }\"; }\n"))))
724 (defun ccide-class-impl-comment ()
725 "Get implementation comment for current class"
727 (let* ((scope (c-get-block-scope))
728 (name (c-get-full-prefix scope)))
729 (kill-new (concat (make-string 75 ?/) "\n"
735 (defun ccide-gen-exception (class &optional description)
736 (interactive "sException name: \nsDescription (defaults to full class name): ")
739 (indent-according-to-mode)
741 (let ((in (make-string c-basic-offset ? ))
742 (ofs (make-string (current-indentation) ? ))
743 (prefix (c-get-full-prefix (c-get-block-scope)))
745 (insert "struct " class " : public std::exception\n"
746 ofs "{ virtual char const * what() const throw() ")
748 (insert "{ return \""
749 (if (and description (> (length description) 0))
751 (concat prefix "::" class))
753 (if (> (current-column) fill-column)
756 (insert "\n" ofs in in))))))
758 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
759 ;; function/method level
761 (defun ccide-function-comment ()
762 "Add comment for current function"
764 (if (memq (c-in-literal) '(c c++))
765 ; Assume, we are in the functions comment ...
767 (c-forward-out-of-comment)
768 (c-backward-syntactic-ws)
771 (c-beginning-of-defun-or-decl)
772 (let ((defun (c-get-defun-state))
773 (indent (make-string comment-column ? ))
775 (goto-char (or (aref defun 7) (car (aref defun 6))))
776 (c-backward-syntactic-ws)
777 (if (looking-at "[ \t\n\r]*///<")
779 (delete-region (point) (progn (skip-chars-forward " \t\n\r") (point)))
780 (if (> (current-column) comment-column)
782 (indent-to-column comment-column)
783 (search-forward "*/")
785 (if (> (current-column) comment-column)
787 (indent-to-column comment-column)
795 (goto-char (car (aref defun 2)))
796 (setq defun (c-get-defun-state)))
798 (ccide-function-comment-adjust defun (concat indent " "))
799 (if place (goto-char place))))
801 (defun ccide-function-comment-grab-args ()
802 (let ((limit (save-excursion
803 (search-backward "/**" nil t)
806 begin start args argend)
808 (while (or (search-backward "\\param" limit t)
809 (search-backward "\\return" limit t)))
813 (while (search-forward "\\param" argend t)
814 (or (search-forward "\\param" argend t)
815 (search-forward "\\return" argend t)
818 (setq args (cons (ccide-function-comment-parse-arg start (point))
820 (setq start (point)))
822 (if (not (search-forward "\return" argend t))
825 (cons (buffer-substring (point) argend) args))
826 (delete-region begin end))))
828 (defun ccide-function-comment-parse-arg (start end)
831 (re-search-forward "\\\\param\\(\\[[^]]*\\]\\)?\\s-*\\(\\S-*\\)" end t)
832 (cons (match-string 2)
833 (cons (buffer-substring start (match-beginning 2))
834 (buffer-substring (match-end 2) end)))))
836 (defun ccide-function-comment-get-throws (defun)
839 (goto-char (car (aref defun 4)))
840 (if (re-search-forward "\\(throw_\\|throw\\)((?\\s-*\\([^()]*\\))?)"
841 (cdr (aref defun 4)) t)
842 (let ((spec (match-string 2)))
843 (if (> (length spec) 0)
846 (defun ccide-function-comment-adjust (defun indent)
848 (let* ((defargs (mapcar (function (lambda (x)
849 (c-get-template-argument-name (car x) (cdr x))))
851 (defret (and (aref defun 1)
852 (not (string-match (concat "^\\("
854 "\\s-*\\)*\\s-*void$")
855 (buffer-substring (car (aref defun 1))
856 (cdr (aref defun 1)))))))
857 (throws (ccide-function-comment-get-throws defun))
858 (xargs (ccide-function-comment-grab-args))
859 (docargs (cdr xargs))
861 (def-in-doc (loop for defarg in defargs always (assoc defarg docargs)))
862 (doc-in-def (loop for docarg in docargs always (member (car docarg) defargs)))
863 (size-eq (= (length defargs) (length docargs))))
864 ;; We differentiate four types changes
866 ;; - removed arguments
867 ;; - reordered arguments
868 ;; - renamed arguments
870 ;; If the change cannot be described by one of the above, it has
871 ;; to be resolved manually
873 (insert indent "\\throws " throws "\n"))
875 ;; reordered arguments or new arguments (or no change)
876 (loop for defarg in defargs
877 for docarg = (assoc defarg docargs)
879 (insert (cadr docarg) (car docarg) (cddr docarg))
880 (insert indent "\\param " defarg " \n"))))
881 (size-eq ; and (not doc-in-def)
883 (loop for defarg in defargs
884 for docarg in docargs
885 do (insert (cadr docarg) defarg (cddr docarg))))
888 (loop for defarg in defargs
889 for docarg = (assoc defarg docargs)
890 do (insert (cadr docarg) (car docarg) (cddr docarg))))
891 (t (error "Arg change too complex. Resolve manualy.")))
892 ;; return value is simple
896 (insert indent "\\return \n"))))
898 (delete-horizontal-space)
901 (defun ccide-grab-prototype (&optional prefix)
902 "Grab prototype of function defined or declared at point. Prefix
903 arg, if given, specifies the kind of prefix (inline, static, ...) to use."
906 (c-beginning-of-defun-or-decl)
907 (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
908 ccide-default-prefix))
909 (defn (c-build-defun prfx)))
910 (kill-new (concat (cadr defn) "\n{}\n"))
911 (message (concat (or prfx "")
915 (defun ccide-reformat-defun ()
916 "Reformat the defn of the current defun."
919 (c-beginning-of-defun-or-decl)
920 (let ((defn (c-build-defun nil t)))
921 (delete-region (or (caar (aref (caddr defn) 0))
922 (car (aref (caddr defn) 1))
923 (car (aref (caddr defn) 2)))
924 (or (car (aref (caddr defn) 6))
925 (aref (caddr defn) 7)))
926 (insert (cadr defn) "\n"))))
928 (defun ccide-replace-defun ()
929 "Replace the function header with the one on the top of the kill
930 ring (presumably placed there using c++-grab-prototype)."
933 (c-beginning-of-defun-or-decl)
934 (let ((parse (c-parse-defun)))
935 (delete-region (or (aref parse 0)
944 (defun ccide-prefix-defun-type-with-class (&optional strip)
945 "If a non-keyword type symbol is found prefixing the current defun,
946 it will be prefixed with the current class prefix."
949 (c-beginning-of-defun-or-decl)
950 (let* ((parse (c-parse-defun))
951 (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
952 (goto-char (aref parse 1))
953 (while (and (or (looking-at c-any-key)
954 (looking-at c-user-prefix-re)
955 (not (c-at-symbol-p)))
956 (< (point) (aref parse 2))
959 (c-forward-syntactic-ws))
960 (if (and (c-at-symbol-p)
961 (< (point) (aref parse 2))
962 (not (looking-at (regexp-quote prefix))))
963 (let ((pos (string-match "<" prefix)))
965 (insert "typename "))
966 (if (and pos (looking-at (concat (substring prefix 0 pos)
969 (goto-char (match-end 0))
970 (c-backward-syntactic-ws)
971 (insert (substring prefix pos)))
972 (insert prefix "::"))
973 (ccide-reformat-defun))))))
975 (defun ccide-prefix-defun-type-with-namespace (&optional strip)
977 (ccide-prefix-defun-type-with-class (+ (or strip 0) 1)))
979 (defun ccide-insert-defun-prefix (&optional strip)
980 "Insert the current defun prefix at point."
982 (let* ((parse (c-parse-defun))
983 (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
984 (insert prefix "::")))
986 (defun ccide-kill-inline-decl (defn)
988 (if (aref (caddr defn) 6)
990 (goto-char (cdr (aref (caddr defn) 6)))
991 (let ((end-mark (point-marker)))
992 (goto-char (car (aref (caddr defn) 6)))
993 (indent-rigidly (point) end-mark
994 (- (current-column)))
998 (buffer-substring-no-properties (point) end-mark)
1000 (when (aref (caddr defn) 5)
1001 (goto-char (caar (aref (caddr defn) 5)))
1002 (c-backward-syntactic-ws)
1003 (skip-chars-backward ":"))
1004 (c-backward-syntactic-ws)
1005 (delete-region (point) end-mark)
1007 (concat (cadr defn) "\n{}\n"))))
1009 (defun ccide-grab-inline-decl ()
1010 "Grab the inline decl at point at turn it into an out-of-line inline
1011 declaration at the top of the kill ring."
1013 (let ((defn (c-build-defun (or ccide-default-prefix "inline"))))
1014 (kill-new (ccide-kill-inline-decl defn))
1015 (message (concat (or ccide-default-prefix "indline")
1019 (defun ccide-grab-all-inlines ()
1020 "Grab all inline decls in the current class"
1022 (let ((class (c-parse-class (c-get-block-scope)))
1025 (loop for method in (nreverse (aref class 4))
1026 do (when (eq (car method) 'method)
1027 (let ((defn (save-excursion
1028 (goto-char (cdr method))
1029 (c-build-defun (or ccide-default-prefix "inline")))))
1030 (if (aref (caddr defn) 6)
1031 (setq defns (nconc defns (list (ccide-kill-inline-decl defn))))))))
1032 (setq defns (nreverse defns))
1033 (kill-new (loop for defn in defns
1034 for next = nil then t
1035 if next concat "\n";
1037 (message (format "%d inlines grabed to kill ring" (length defns))))))
1039 (defun ccide-grab-create-constructor ()
1041 (let ((defn (c-build-create-constructor)))
1042 (kill-new (cadr defn))
1043 (message (car defn))))
1045 (defun ccide-grab-create-constructor-impl (&optional prefix)
1047 (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
1048 ccide-default-prefix))
1049 (defn (c-build-create-constructor-impl prfx)))
1050 (kill-new (cadr defn))
1051 (message (concat (or prfx "")
1055 (defun ccide-find-implementation (&optional other-window)
1056 "Find implementation of method declared at point."
1058 (let* ((state (c-get-defun-state))
1059 (name (c-defun-short-name state))
1060 (scoped-name (c-defun-full-name state))
1061 (args (ccide-implementation-args state))
1062 (targs (ccide-implementation-template-args state))
1065 (loop for ext in ccide-implementation-extensions
1066 for filename = (ccide-file-name ext)
1069 (let ((buf (or (find-buffer-visiting filename)
1070 (and (file-readable-p filename)
1071 (find-file-noselect filename)))))
1073 (let ((found (save-excursion
1075 (ccide-find-implementation-1 name scoped-name args targs
1076 (not (aref state 6))
1077 (car (aref state 2))))))
1080 (setq rv (cons buf found))
1081 (if (not fallback) (setq fallback (cons buf found))))))))))
1082 (if (not rv) (setq rv fallback))
1084 (let* ((buf (car rv))
1086 (win (get-buffer-window buf)))
1090 (switch-to-buffer-other-window buf)
1091 (switch-to-buffer buf)))
1094 (c-beginning-of-defun-or-decl))
1095 (message (concat "Implementation of " scoped-name " not found.")))))
1097 (defun ccide-implementation-args (state)
1098 (string-replace "[ \t\n\r]+" ""
1099 (loop for (start . end) in (aref state 3)
1100 for sep = "" then ","
1102 concat (buffer-substring-no-properties
1103 start (save-excursion
1105 (if (search-forward "=" end 'move) (forward-char -1))
1110 (defun ccide-implementation-template-args (state)
1112 (string-replace "[ \t\n\r]+" ""
1113 (loop for (start . end) in (save-excursion
1114 (goto-char (caar (last (aref state 0))))
1115 (c-parse-template-declaration))
1116 for sep = "" then ","
1118 concat (buffer-substring-no-properties
1119 start (save-excursion
1121 (if (search-forward "=" end 'move) (forward-char -1))
1125 (defun ccide-find-implementation-1 (name scoped-name args targs with-body skip-def)
1126 ;; Within the current buffer, search for all implementations of the
1127 ;; given function. The rv is a list of conses. The car holds the
1128 ;; buffer position of the implementation, the cdr is t if the name,
1129 ;; scoped-name and args are matched, otherwise the args did not match.
1131 (goto-char (point-min))
1132 (let ((re (concat (if (eq (char-syntax (aref name 0)) ?w) "\\<" "")
1134 (if (eq (char-syntax (aref name (1- (length name)))) ?w) "\\>" "")))
1135 fallback rv check-state)
1136 (while (and (not rv) (re-search-forward re nil t))
1137 (if (c-save-buffer-state ()
1138 (and (c-at-toplevel-p)
1139 (not (c-in-literal))
1140 (setq check-state (condition-case nil (c-get-defun-state) (error nil)))
1141 (not (= (car (aref check-state 2)) skip-def))))
1142 (if (string= scoped-name (c-defun-full-name check-state))
1143 (if (and (if with-body (aref check-state 6) (not (aref check-state 6)))
1144 (string= args (ccide-implementation-args check-state))
1145 (string= targs (ccide-implementation-template-args check-state)))
1146 (setq rv (cons (point) t))
1148 (setq fallback (cons (point) nil)))))))
1151 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1152 ;; variable/type level
1154 (defun ccide-variable-comment ()
1155 "Add a comment to current variable declaration."
1157 (c-forward-out-of-comment)
1158 (c-forward-syntactic-ws)
1159 (while (not (looking-at ";"))
1161 (c-forward-syntactic-ws))
1163 (if (> (current-column) comment-column)
1164 (insert "\n" (make-string comment-column ? ) "///< ")
1165 (indent-to-column comment-column)
1168 (defun ccide-grab-access-fn ()
1172 (if (looking-at (concat c++-simple-type-regexp "[ \t\n\r][a-zA-Z0-9_]+[ \t\n\r]*;"))
1173 (let ((vardef (match-string 0))
1174 (in (make-string c-basic-offset ? ))
1175 type reftype varname fnname argname ws)
1177 (back-to-indentation)
1178 (string-match "^[ \t\n\r]*\\(.*\\)[ \t\n\r]\\([a-zA-Z0-9_]+\\)[ \t\n\r]*;$"
1180 (setq varname (match-string 2 vardef)
1181 type (match-string 1 vardef)
1182 ws (substring vardef 0 (match-beginning 1)))
1183 (if (string-match "_$" varname)
1184 (setq fnname (string-replace "_$" "" varname)
1185 argname (concat "a_" fnname))
1186 (setq fnname (concat "q_" varname)
1187 argname (concat "a_" varname)))
1188 (if (string-match "^[ \t\n\r]*" type)
1189 (setq type (substring type (match-end 0))))
1190 (if (string-match "^[A-Z]" type)
1191 (setq reftype (concat type " const &"))
1192 (setq reftype type))
1193 (kill-new (concat ws type " " fnname "(" reftype " " argname ")\n"
1195 ws in in type " old" varname " = " varname ";\n"
1196 ws in in varname " = " argname ";\n"
1197 ws in in "return old" varname ";\n"
1199 ws reftype " " fnname "() const\n"
1200 ws in "{ return " varname "; }\n"))
1203 (message "No variable found"))))
1205 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1206 ;; doxy comment support functions
1208 (defun ccide-special-indent-function ()
1209 "Function to indent doxy comments correctly"
1210 (let ((indent (ccide-in-doxy-comment)))
1212 (let ((lim (save-excursion
1213 (back-to-indentation)
1214 (c-literal-limits)))
1215 (pos (- (point-max) (point))))
1217 (back-to-indentation)
1218 (if (looking-at "*/")
1220 (let ((para (or (save-excursion (re-search-backward "^\\s-*$" (car lim) t))
1222 (if (and (not (looking-at ccide-doxy-tag-re))
1223 (re-search-backward (concat "^\\s-*"
1227 (delete-region (progn (beginning-of-line) (point))
1228 (progn (back-to-indentation) (point)))
1230 (if (> (- (point-max) pos) (point))
1231 (goto-char (- (point-max) pos)))))))
1233 (defun ccide-fill-function ()
1234 "auto-fill function for doxy comments"
1236 (if (not fill-prefix)
1237 (indent-according-to-mode))))
1239 (defun ccide-hide-all-doxy-comments ()
1240 "Hide all doxy comments"
1243 (goto-char (point-min))
1244 (while (re-search-forward "^\\s-*/\\*\\*" nil t)
1247 (if (not (looking-at "\\s-*$"))
1250 (let ((start (point)))
1251 (if (re-search-forward "\\*/" nil t)
1253 (if (looking-at "\\s-*\n")
1256 (let ((overlay (make-overlay start (point))))
1257 (overlay-put overlay 'intangible 'hs)
1258 (overlay-put overlay 'invisible 'hs)))))))
1261 (defun ccide-show-all-comments ()
1265 (goto-char (point-min))
1267 (goto-char (next-overlay-change (point)))
1268 (loop for overlay in (overlays-at (point))
1269 if (eq (overlay-get overlay 'invisible) 'hs)
1270 do (delete-overlay overlay))))
1273 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1274 ;; CORBA support (omniORB2)
1276 (defun ccide-get-corba-headers ()
1279 (goto-char (point-min))
1280 (while (re-search-forward "#include\\s-*[\"<]\\([^\">]*\\)\\.hh[\">]" nil t)
1281 (setq files (cons (ccide-match-string 1) files)))
1284 (defun ccide-corba-maybe-build-hh (file)
1285 (let ((skel (ccide-file-name ".hh" file ccide-corba-skel-dir))
1286 (idl (ccide-file-name ".idl" file ccide-corba-idl-dir)))
1287 (if (and (file-readable-p idl)
1288 (or (not (file-readable-p skel))
1289 (file-newer-than-file-p idl skel)))
1290 (let ((buffer (find-buffer-visiting (ccide-file-name ".hh" file))))
1292 (kill-buffer buffer))
1293 (message "Please wait ... building %s" (ccide-file-name ".hh" file))
1294 (if (ccide-shell-command (concat "cd "
1295 (real-path-name ccide-corba-skel-dir)
1297 ccide-corba-idl-command
1298 (if (> (length ccide-corba-idl-dir) 0)
1299 (concat " -I" ccide-corba-idl-dir))
1303 (display-buffer (get-buffer-create "*ccide shell command*"))
1304 (error "Generation of %s failed" (ccide-file-name ".hh")))))
1305 (if (not (file-readable-p skel))
1306 (error "No file %s or %s"
1307 (ccide-file-name ".hh" file) (ccide-file-name ".idl" file)))))
1309 (defun ccide-corba-list-skeletons-1 (hh-file)
1310 (ccide-corba-maybe-build-hh hh-file)
1311 (let ((hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file)))
1316 (goto-char (point-min))
1317 (while (re-search-forward "^\\s-*class\\s-+_sk_\\([a-zA-Z0-9_]+\\)\\s-+:"
1319 (setq skels (cons (ccide-match-string 1) skels)))))
1320 (mapcar (function (lambda (x) (cons x hh-file)))
1321 (sort skels 'string-lessp))))
1323 (defun ccide-corba-list-skeletons ()
1324 (let ((files (ccide-get-corba-headers)))
1325 (loop for file in files
1326 append (ccide-corba-list-skeletons-1 file))))
1328 (defun ccide-gen-corba-impl (class)
1329 (interactive (list (completing-read "Class name of skeleton: "
1330 (ccide-corba-list-skeletons)
1332 (let* ((skels (ccide-corba-list-skeletons))
1333 (hh-file (ccide-file-name ".hh" (cdr (assoc class skels))
1334 ccide-corba-skel-dir))
1335 (hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file
1336 ccide-corba-skel-dir))))
1337 (ccide-gen-class (concat class "_i"))
1338 (insert (make-string c-basic-offset ? ) ": public virtual _sk_" class "\n")
1340 (search-forward "protected:" nil t)
1342 (ccide-gen-corba-impl-methods)
1345 (defun ccide-get-corba-defns (hh-file class)
1346 (let ((hh-buf (find-file-noselect hh-file))
1351 (goto-char (point-min))
1352 (if (not (re-search-forward (concat "^\\s-*class\\s-+_sk_" class "\\s-+:")
1354 (error "CORBA skeleton class not found.")
1355 (search-forward "{")
1357 (let ((end (save-excursion (forward-sexp) (point))))
1358 (while (and (< (point) end)
1359 (< (forward-line 1) 1))
1360 (if (looking-at "\\s-+virtual\\s-+\\(.*)\\)\\s-*=\\s-*0;\\s-*$")
1361 (setq defns (cons (match-string 1) defns))))))))
1364 (defun ccide-gen-corba-impl-methods ()
1366 (let* ((class (c-get-class-at-point))
1369 (error "No class at point."))
1371 (goto-char (aref (car class) 1))
1372 (if (not (re-search-forward ":\\s-*public\\s-*virtual\\s-*_sk_\\([^ \t\n\r{},:]*\\)"
1374 (error "No CORBA impl at point."))
1375 (let* ((name (ccide-match-string 1))
1376 (skels (ccide-corba-list-skeletons))
1377 (hh-file (ccide-file-name ".hh" (cdr (assoc name skels))
1378 ccide-corba-skel-dir))
1379 (defns (ccide-get-corba-defns hh-file name))
1381 (goto-char (aref (car class) 2))
1385 (if (re-search-forward "^\\s-*// CORBA$" end t)
1386 (let ((start (match-beginning 0)))
1387 (if (re-search-forward "^\\s-*// END-CORBA$" end t)
1388 (let ((eend (match-end 0)))
1391 (if (re-search-forward "/\\*\\|//" (match-beginning 0) t)
1392 (if (y-or-n-p "Remove CORBA Funktion comments? (y/n)")
1393 (delete-region start (1+ eend))
1396 (delete-region (point) (progn
1401 (delete-region (point) (progn
1405 (delete-region start (1+ eend))))))
1407 (indent-according-to-mode)
1408 (insert "// CORBA\n")
1409 (loop for defn in defns
1411 (save-excursion (insert defn ";"))
1412 (indent-according-to-mode)
1413 (let ((start (point)) end)
1417 (while (re-search-forward "\\s-+" end t)
1419 (setq end (- end (- (match-end 0) (match-beginning 0) 1))))
1421 (loop with done = nil
1422 while (> (current-column) c-max-def-column)
1423 do (while (and (> (current-column) c-max-def-column)
1424 (search-backward "," start t)))
1425 do (if (looking-at ",")
1430 (indent-according-to-mode)
1432 (setq start (point))
1437 (indent-according-to-mode)
1438 (insert "// END-CORBA\n")))))
1440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1443 (defun ccide-scan-mantemps ()
1444 "Scan *compilation* buffer for errors and generate manual template
1445 instatiations at point."
1448 (set-buffer "*compilation*")
1449 (goto-char (point-min)))
1451 (set-buffer (get-buffer-create "*mantemps*"))
1453 (loop for temp = (ccide-get-mantemp)
1455 do (insert temp "\n"))
1456 (mantemp-make-mantemps-buffer)
1457 (goto-char (point-min))
1460 (< (forward-line 1) 1))))
1461 (insert-buffer-substring "*mantemps*"))
1463 (defun ccide-get-mantemp ()
1465 (set-buffer "*compilation*")
1466 (if (search-forward "undefined reference to `" nil t)
1467 (let ((start (point)))
1469 (search-backward "'" nil t)
1470 (buffer-substring start (point))))))
1472 (defun ccide-fix-mantemp ()
1473 (let ((end (save-excursion
1474 (end-of-line) (point))))
1475 (if (and (save-excursion (search-forward "(" end t))
1476 (search-forward " class" end t))
1483 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1486 (defun ccide-grab-pxd-fn ()
1489 (c-beginning-of-defun-or-decl)
1490 (let ((defn (c-build-pxd)))
1491 (kill-new (cadr defn))
1492 (message (concat (car defn))))))
1494 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1497 (defun ccide-open-compilation-frame ()
1499 (let ((c-frame (selected-frame))
1500 (compilation-frame (make-frame '((minibuffer . nil)
1502 (menu-bar-lines . 0)
1507 (select-frame compilation-frame)
1508 (switch-to-buffer "*compilation*")
1509 (set-window-dedicated-p (selected-window) t)))
1511 (defun ccide-compile (command)
1512 (delete-other-windows)
1513 (split-window-horizontally)
1516 (set-buffer "*compilation*")
1517 (let ((point (point-max)))
1519 (loop for window in (get-buffer-window-list "*compilation*" nil t)
1520 do (set-window-point window point)))))
1522 (defun ccide-compile-compile ()
1524 (ccide-compile (concat "make -k " ccide-compile-opts)))
1526 (defun ccide-compile-clean ()
1528 (ccide-compile (concat "make -k " ccide-compile-opts " clean")))
1530 (defun ccide-compile-cleandepends ()
1532 (ccide-compile (concat "make -k " ccide-compile-opts " cleandepends")))
1534 (defun ccide-compile-kill ()
1536 (set-buffer "*compilation*")
1539 (defun ccide-hide-compilation ()
1541 (let ((active (selected-window)))
1543 (loop for window in (get-buffer-window-list "*compilation*")
1544 do (progn (select-window window)
1545 (switch-to-buffer (other-buffer "*compilation*"))))
1546 (select-window active))))
1548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1549 ;; keymap and installation
1551 (defun ccide-bind-keys (prefix map)
1552 (loop for binding in ccide-bindings
1553 do (apply 'vcmd-define-key
1555 (concat prefix (car binding))
1560 (defun ccide-install-it ()
1564 (local-unset-key "\C-c;")
1565 (local-unset-key [menu-bar IDE])
1566 (ccide-bind-keys "\C-c;" (current-local-map))
1567 (local-set-key "\C-cC" 'ccide-hide-all-doxy-comments)
1568 (local-set-key "\C-cS" 'ccide-show-all-comments)
1569 (set (make-local-variable 'auto-fill-function) 'ccide-fill-function)
1570 (set (make-local-variable 'paragraph-start) (concat "[ \t\f]*$\\|[ \t\f]*" ccide-doxy-tag-re))
1571 (set (make-local-variable 'paragraph-separate) "[ \t\f]*$")
1573 (ccide-project-load-config)
1574 (ccide-directory-load-config)
1575 (ccide-auto-decorate-new-files)
1576 (if ccide-clang-format-command
1577 (add-hook 'write-contents-functions 'ccide-clang-format-buffer nil t))
1578 (if ccide-uncrustify-config
1579 (add-hook 'write-contents-functions 'ccide-uncrustify-format-buffer nil t)))
1581 (defun ccide-match-auto-format-tag ()
1582 (or (not ccide-auto-format-tag)
1583 (and (save-excursion
1584 (goto-char (point-min))
1585 (search-forward ccide-auto-format-tag
1586 (save-excursion (forward-line 4) (point))
1591 (defun clang-format-xmltok-attribute (name)
1592 (loop for attribute in xmltok-attributes
1593 if (string= (buffer-substring-no-properties (xmltok-attribute-name-start attribute)
1594 (xmltok-attribute-name-end attribute))
1596 return (buffer-substring-no-properties (xmltok-attribute-value-start attribute)
1597 (xmltok-attribute-value-end attribute))))
1599 (defun clang-format-parse-replacement-text ()
1600 (cond ((eq tok 'char-ref)
1601 (let ((number-start (+ xmltok-start 2))
1602 (number-end (1- (point))))
1603 (if (not (string= (buffer-substring-no-properties xmltok-start number-start)
1605 (error "invalid character reference"))
1606 (char-to-string (string-to-number (buffer-substring-no-properties number-start
1610 (buffer-substring-no-properties xmltok-start (point)))))
1612 (defun clang-format-parse-replacement ()
1613 (let ((offset (string-to-number (clang-format-xmltok-attribute "offset")))
1614 (length (string-to-number (clang-format-xmltok-attribute "length"))))
1617 (loop for tok = (xmltok-forward)
1618 while (not (eq tok 'end-tag))
1619 concat (clang-format-parse-replacement-text)))))
1621 (defun clang-format-parse-replacements (buffer)
1624 (goto-char (point-min))
1625 (xmltok-forward-prolog)
1626 (loop for tok = (xmltok-forward)
1628 if (and (eq tok 'start-tag)
1629 (string= (buffer-substring-no-properties (1+ xmltok-start) xmltok-name-end)
1631 collect (clang-format-parse-replacement))))
1633 (defun clang-format-apply-replacements (replacements)
1634 (loop for (offset length replacement) in (nreverse replacements)
1636 (goto-char (1+ offset))
1637 (delete-char length)
1638 (insert replacement))))
1640 (defun ccide-clang-format-buffer ()
1642 (if (and ccide-clang-format-command (ccide-match-auto-format-tag))
1643 (let ((replacementsBuffer (get-buffer-create " *clang-format-replacements*")))
1644 (save-excursion (set-buffer replacementsBuffer) (erase-buffer))
1645 (shell-command-on-region (point-min) (point-max) ccide-clang-format-command
1646 replacementsBuffer nil)
1647 (let ((replacements (clang-format-parse-replacements replacementsBuffer)))
1649 (clang-format-apply-replacements replacements)))))
1652 (defun ccide-parse-ed-diff (buffer)
1653 ;; an ed-diff already has the replacements in reverse order
1656 (goto-char (point-min))
1657 (loop while (= (forward-line 1) 0)
1659 for e = (save-excursion (end-of-line) (point))
1660 for k = (search-forward "," e t)
1661 for m = (buffer-substring-no-properties (1- e) e)
1662 for rb = (when (not (equal m "d"))
1663 (forward-line 1) (point))
1664 for re = (when (not (equal m "d"))
1665 (while (and (not (looking-at "\\.$")) (= (forward-line 1) 0))) (point))
1666 for bl = (string-to-number (buffer-substring-no-properties b (1- (or k e))))
1667 for el = (string-to-number (buffer-substring-no-properties (or k b) (1- e)))
1668 collect (list (if (equal m "a") (1+ bl) bl)
1670 (if (not (equal m "d"))
1671 (buffer-substring-no-properties rb re)
1674 (defun ccide-apply-ed-diff (replacements)
1675 (loop for (first last replacement) in replacements
1678 (delete-region (point) (progn (goto-line last) (point)))
1679 (insert replacement))))
1681 (defun ccide-uncrustify-format-buffer ()
1683 (if (and ccide-uncrustify-config (ccide-match-auto-format-tag))
1684 (let ((tempFile (make-temp-file "ccideuncrustify"))
1685 (diffBuffer (get-buffer-create " *uncrustify-format-diff*")))
1688 (write-region (point-min) (point-max) tempFile)
1689 (shell-command (concat (shell-quote-argument ccide-uncrustify-command)
1690 " -c " (shell-quote-argument
1691 (expand-file-name ccide-uncrustify-config))
1692 " -l CPP -f " (shell-quote-argument tempFile)
1693 " | diff -e " (shell-quote-argument tempFile) " -")
1695 (delete-file tempFile))
1696 (let ((replacements (ccide-parse-ed-diff diffBuffer)))
1698 (ccide-apply-ed-diff replacements))))
1701 (defun ccide-project-load-config ()
1702 (if (buffer-file-name)
1703 (let ((conf (ccide-project-search-upwards '(".project.el" "project.el")
1704 (file-name-directory (buffer-file-name)))))
1706 (set (make-local-variable 'ccide-project-root) (file-name-directory conf))
1707 (load-file conf)))))
1709 (defun ccide-project-search-upwards (names &optional base)
1710 "Search for FILE in all directories starting at DIR and going up the directory hierarchy.
1711 DIR defaults to ccide-project-root. If FILE is a list, search for any file in list."
1712 (if (not (consp names))
1713 (setq names (list names)))
1714 (loop for dir = (or base ccide-project-root) then (directory-file-name (file-name-directory dir))
1715 while (not (string= dir "/"))
1716 thereis (loop for name in names
1717 for path = (expand-file-name name dir)
1718 thereis (and (file-readable-p path) path))))
1720 (defun ccide-directory-load-config ()
1721 (if (file-readable-p ".dir.el")
1722 (load-file ".dir.el")))
1724 (add-hook 'c-mode-hook 'ccide-install-it)
1725 (add-hook 'c++-mode-hook 'ccide-install-it)
1726 (add-hook 'c-special-indent-hook 'ccide-special-indent-function)
1728 (loop for extension in ccide-special-extensions
1729 for re = (concat (regexp-quote extension) "$")
1730 if (not (assoc re auto-mode-alist))
1731 do (setq auto-mode-alist (append auto-mode-alist
1732 (list (cons re 'c++-mode)))))
1734 (defadvice c-indent-line (after c-indent-less compile disable) ;activate
1735 ;; new indent function for c-mode: do standard indentation first. If line
1736 ;; is to long using standard indentation, just indent by c-basic-indentation.
1737 (let ((cc (save-excursion (end-of-line) (current-column)))
1740 (let ((pos (- (point-max) (point))))
1742 (let ((point (point))
1743 (line (1+ (count-lines 1 (point))))
1745 (c-beginning-of-statement-2)
1746 (if (and (not (c-crosses-statement-barrier-p (point) point))
1747 (not (eq (+ (count-lines 1 (point))
1751 (setq indent (+ (current-indentation) c-basic-offset))
1753 (if (< indent (current-indentation))
1755 (setq ad-return-value
1757 (- (current-indentation) indent)))
1758 (delete-region (c-point 'bol) (c-point 'boi))
1759 (indent-to indent))))))
1760 (if (< (point) (c-point 'boi))
1761 (back-to-indentation)
1762 (if (> (- (point-max) pos) (point))
1763 (goto-char (- (point-max) pos))))))))
1766 ;;; Local Variables:
1767 ;;; elisp-project-autoload-file-name: "cc-autoload.el"