90d422c70c58927cf5dc0393193bf4a59d37e80c
[emacsstuff.git] / cc-ide / cc-ide.el
1 ;;; cc-ide.el --- C++ IDE
2 ;;
3 ;; $Id$
4 ;;
5 ;; Copyright (C) 2000 Stefan Bund
6
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.
11
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.
16
17 ;;; Commentary:
18
19 ;;; Change-Log:
20
21 ;; $Log$
22 ;;
23
24 ;;; Variables:
25
26 (defvar ccide-compile-opts "DEBUG=1"
27   "*Additional options to make command")
28
29 (defvar ccide-file-vars nil)
30
31 (defvar ccide-default-author "")
32 (defvar ccide-default-copyright "")
33
34 (defvar ccide-project-name nil)
35
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
39 correctly included.")
40
41 (defvar ccide-corba-skel-dir "")
42 (defvar ccide-corba-idl-dir "")
43 (defvar ccide-corba-idl-command "omniidl2 -w")
44
45 (defvar c-user-prefixes '("inline" "static" "prefix_")
46   "*List of possible prefixes for function definitions.")
47
48 (defvar ccide-default-prefix "prefix_"
49   "*Prefix added to every implementation header. Probably eiter empty or 'prefix_'")
50
51 (defvar ccide-gen-throw nil
52   "*If non-nil, generate throw_ specs")
53
54 (defvar ccide-project-root nil)
55
56 (defvar ccide-new-file-hook nil)
57
58 (defvar ccide-new-file-command nil)
59
60 (defvar ccide-format-command nil)
61
62 (defconst c-user-prefix-re (regexp-opt c-user-prefixes t))
63
64 (defconst ccide-doxy-tag-re
65   (concat "\\\\\\(group\\|defgroup\\|see\\|author\\|version\\|id\\|since"
66           "\\|returns?\\|throws?\\|exception\\|raises\\|param\\|li\\|brief"
67           "\\|internal\\|bug\\|fixme\\|todo\\|idea\\|implementation"
68           "\\|note\\|attention\\|warning\\|par\\|code\\|endcode"
69           "\\|post\\|pre\\|deprecated\\)\\b"))
70
71 (defconst ccide-special-extensions
72   '(".h" ".hh" ".mpp" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci" ".dox"))
73
74 (defconst ccide-implementation-extensions
75   '(".h" ".hh" ".ih" ".cc" ".cpp" ".ct" ".cti" ".cci"))
76
77 (defconst ccide-class-defaults-word
78   "// \\(default\\|no\\|protected\\|private\\|disabled\\|my\\)")
79
80 (defconst  ccide-bindings
81   '(
82     ;; file level
83     ("fc"  ccide-file-comment                 "File comment")
84     ("fs"  ccide-syncronize-includes          "Sync includes")
85     (nil   nil                                separator)
86
87     ;; class level
88     ("cc"  ccide-class-comment                "Class comment")
89     ("cg"  ccide-gen-class                    "Generate class")
90     ("cd"  ccide-gen-class-defaults           "Generate class defaults")
91     ("cD"  ccide-gen-class-defaults-impl      "Generate class defaults impl")
92
93     ("csd" ccide-set-class-defaults-default   "Set class defaults comment" "Default")
94     ("csn" ccide-set-class-defaults-no        "Set class defaults comment" "No")
95     ("csp" ccide-set-class-defaults-protected "Set class defaults comment" "Protected")
96     ("csr" ccide-set-class-defaults-private   "Set class defaults comment" "Private")
97     ("csx" ccide-set-class-defaults-disabled  "Set class defaults comment" "Disabled")
98     ("csm" ccide-set-class-defaults-my        "Set class defaults comment" "My")
99
100     ("cS"  ccide-gen-struct-constructors      "Generate structure constructors")
101     ("c<"  ccide-gen-struct-compare           "Generate structure compare operators")
102
103     ("ci"  ccide-class-impl-comment           "Generate class implemenation comment")
104
105     ("ce"  ccide-gen-exception                "Generate an exception class")
106
107     (nil   nil                                separator)
108
109     ;; method level
110     ("mc"  ccide-function-comment             "Method comment")
111     ("mp"  ccide-grab-prototype               "Grab prototype")
112     ("mr"  ccide-reformat-defun               "Reformat defun")
113     ("mx"  ccide-replace-defun                "Replace defun")
114     ("mt"  ccide-prefix-defun-type-with-class "Prefix defun type with class")
115     ("mn"  ccide-prefix-defun-type-with-namespace "Prefix defun type with namespace")
116     ("mi"  ccide-grab-inline-decl             "Grab inline decl")
117     ("mA"  ccide-grab-all-inlines             "Grab ALL inline decls")
118     ("mC"  ccide-grab-create-constructor      "Grab CREATE constructor")
119     ("mI"  ccide-grab-create-constructor-impl "Build CREATE cosntructor")
120     ("mf"  ccide-find-implementation          "Find method implementation")
121     ("mT"  ccide-insert-defun-prefix          "Insert current defun prefix at point")
122     (nil   nil                                separator)
123
124     ;; variable level
125     ("vc"  ccide-variable-comment             "Variable comment")
126     ("vf"  ccide-grab-access-fn               "Grab access methods")
127     (nil   nil                                separator)
128
129     ;; documentation
130     ("h"   ccide-hide-all-doxy-comments        "Hide all Doxygen comments")
131     ("s"   ccide-show-all-comments             "Show all Doxygen comments")
132
133     ;; cython
134     ("yp"  ccide-grab-pxd-fn                   "Generate pxd function/method decl")
135
136 ;    ;; CORBA
137 ;    ("Cg"  ccide-gen-corba-impl                      "Generate CORBA impl")
138 ;    ("Cm"  ccide-gen-corba-impl-methods       "Generate CORBA impl methods")
139 ;    (nil   nil                               separator)
140
141     ;; templates
142 ;    ("ts"  ccide-scan-mantemps               "Scan mantemps")
143 ;    (nil   nil                                separator)
144
145 ;    ;; other
146 ;    ("of"  ccide-open-compilation-frame       "Open *compilation* frame")
147 ;    ("oc"  ccide-compile-compile              "Make -> Compile")
148 ;    ("ox"  ccide-compile-clean                "Make -> Clean")
149 ;    ("od"  ccide-compile-cleandepends         "Make -> Clean depends")
150 ;    ("ok"  ccide-compile-kill                 "Kill compilation")
151 ;    ("oh"  ccide-hide-compilation             "Hide *compilation* buffer")
152
153     ))
154
155 ;;; Code:
156
157 (require 'cc-engine-2)
158 (require 'cc-helper)
159 (require 'c++)
160 (require 'cl)
161 (require 'hideshow)
162 ;(require 'mantemp)
163 (require 'locate)
164 (require 'lucid)
165 (require 'varcmd)
166 (require 'misc-local)
167
168 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
169 ;; utils
170
171 (defsubst ccide-match-string (n)
172   (buffer-substring-no-properties (match-beginning n) (match-end n)))
173
174 (defun ccide-file-macro-name (&optional file-name)
175   (concat (upcase (file-name-extension (or file-name (buffer-file-name))))
176           "_"
177           (if ccide-project-name (concat ccide-project-name "_") "")
178           (if ccide-project-root
179               (string-replace "/" "_"
180                               (substring (file-name-directory
181                                           (expand-file-name (or file-name buffer-file-name)))
182                                          (length ccide-project-root))
183                               t)
184             "")
185           (string-replace "\\." "_" (file-name-sans-extension
186                                      (file-name-nondirectory
187                                       (or file-name (buffer-file-name))))
188                           t nil t t)
189           "_"))
190
191 (defun ccide-file-name (&optional extension file-name directory)
192   (concat (if directory (file-name-as-directory directory) "")
193           (file-name-sans-extension
194            (file-name-nondirectory
195             (or file-name (buffer-file-name))))
196           extension))
197
198 (defun ccide-in-doxy-comment ()
199   (save-excursion
200     (back-to-indentation)
201     (let ((lit (c-in-literal)))
202       (when (and (memq lit '(c c++))
203                  (progn (goto-char (car (c-literal-limits)))
204                         (looking-at "/\\(\\*\\*\\|///\\)<?[ \t\n\r@]")))
205         (goto-char (match-end 0))
206         (current-column)))))
207
208 (defun ccide-shell-command (command)
209   (let ((obuf (get-buffer-create "*ccide shell command*"))
210         exit-status)
211     (save-excursion
212       (set-buffer obuf)
213       (erase-buffer)
214       (insert command "\n"))
215     (setq exit-status (call-process shell-file-name nil "*ccide shell command*" nil
216                                     shell-command-switch command))
217     (and exit-status (equal exit-status 0))))
218
219 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
220 ;; file level
221
222 (defun ccide-file-comment ()
223   "Add a comment to this source file."
224   (interactive)
225   (let ((mode "c++")
226         point add-file-vars)
227     (push-mark)
228     (goto-char (point-min))
229     (insert "// $Id$\n"
230             "//\n"
231             "// Copyright (C) " (number-to-string (nth 5 (decode-time)))
232             " " ccide-default-author "\n"
233             ccide-default-copyright
234             "\n")
235
236     (cond ((string-match "\\.hh?$" (buffer-file-name))
237            (insert "/** \\file\n"
238                    "    \\brief " (ccide-file-name) " public header */\n\n"
239                    "#ifndef " (ccide-file-macro-name) "\n"
240                    "#define " (ccide-file-macro-name) " 1\n\n")
241            (if ccide-all-includes
242                (insert "#ifndef " (ccide-file-macro-name ccide-all-includes) "\n"
243                        "#error \"Don't include '" (file-name-nondirectory (buffer-file-name)) "'"
244                        " directly, include '" ccide-all-includes "'\"\n"
245                        "#endif\n\n"))
246            (insert "// Custom includes\n\n"
247                    "//#include \"" (ccide-file-name ".mpp") "\"\n"
248                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
249            (setq point (point))
250            (goto-char (point-max))
251            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n")
252            (if ccide-all-includes
253                (insert "#endif\n"
254                        "#if !defined(" (ccide-file-macro-name ccide-all-includes) "_decls_) "
255                        "&& !defined(" (ccide-file-macro-name) "i_)\n"
256                        "#define " (ccide-file-macro-name) "i_\n"))
257            (insert "//#include \"" (ccide-file-name ".cci") "\"\n"
258                    "//#include \"" (ccide-file-name ".ct") "\"\n"
259                    "//#include \"" (ccide-file-name ".cti") "\"\n"
260                    "#endif"))
261
262           ((string-match "\\.mpp$" (buffer-file-name))
263            (insert "/** \\file\n"
264                    "    \\brief " (ccide-file-name) " Boost.Preprocesser external iteration include */\n\n"
265
266
267                    "#if !BOOST_PP_IS_ITERATING && !defined(" (ccide-file-macro-name) ")\n"
268                    "#define " (ccide-file-macro-name) " 1\n\n"
269                    "// Custom includes\n\n\n"
270                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
271                    "#elif BOOST_PP_IS_ITERATING //-/////////////////////////////////////////////////////////////////////\n"
272                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
273                    "// Local Macros\n\n\n"
274                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
275                    "#if BOOST_PP_ITERATION_FLAGS()==1 //-///////////////////////////////////////////////////////////////\n"
276                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
277            (setq point (point))
278            (goto-char (point-max))
279            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
280                    "#endif //-//////////////////////////////////////////////////////////////////////////////////////////\n"
281                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
282                    "// Undefine local Macros\n\n\n"
283                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
284                    "#endif //-//////////////////////////////////////////////////////////////////////////////////////////\n"
285                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////"))
286
287           ((string-match "\\.ih$" (buffer-file-name))
288            (insert "/** \\file\n"
289                    "    \\brief " (ccide-file-name) " internal header */\n\n"
290                    "#ifndef " (ccide-file-macro-name) "\n"
291                    "#define " (ccide-file-macro-name) " 1\n\n"
292                    "// Custom includes\n\n"
293                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
294            (setq point (point))
295            (goto-char (point-max))
296            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
297                    "#endif"))
298
299           ((or (string-match "\\.test\\.cc$" (buffer-file-name))
300                (string-match "\\.test\\.cpp$" (buffer-file-name)))
301            (insert "/** \\file\n"
302                    "    \\brief " (ccide-file-name) " unit tests */\n\n"
303                    "//#include \"" (ccide-file-name ".hh") "\"\n"
304                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
305                    "// Custom includes\n"
306                    "#include \"" (or ccide-all-includes
307                                      (ccide-file-name ".hh" (ccide-file-name))) "\"\n\n"
308                    "#include <boost/test/auto_unit_test.hpp>\n"
309                    "#include <boost/test/test_tools.hpp>\n\n"
310                    "#define prefix_\n"
311                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
312            (setq point (point))
313            (goto-char (point-max))
314            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
315                    "#undef prefix_"))
316
317           ((or (string-match "\\.cc$" (buffer-file-name))
318                (string-match "\\.cpp$" (buffer-file-name)))
319            (insert "/** \\file\n"
320                    "    \\brief " (ccide-file-name) " non-inline non-template implementation */\n\n"
321                    (if ccide-all-includes "" "//")
322                    "#include \"" (or ccide-all-includes (ccide-file-name ".hh")) "\"\n"
323                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
324                    "// Custom includes\n\n"
325                    "//#include \"" (ccide-file-name ".mpp") "\"\n"
326                    "#define prefix_\n"
327                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
328            (setq point (point))
329            (goto-char (point-max))
330            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
331                    "#undef prefix_\n"
332                    "//#include \"" (ccide-file-name ".mpp") "\""))
333
334           ((string-match "\\.cci$" (buffer-file-name))
335            (insert "/** \\file\n"
336                    "    \\brief " (ccide-file-name) " inline non-template implementation */\n\n"
337                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
338                    "// Custom includes\n\n"
339                    "#define prefix_ inline\n"
340                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
341            (setq point (point))
342            (goto-char (point-max))
343            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
344                    "#undef prefix_"))
345
346           ((string-match "\\.ct$" (buffer-file-name))
347            (insert "/** \\file\n"
348                    "    \\brief " (ccide-file-name) " non-inline template implementation  */\n\n"
349                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
350                    "// Custom includes\n\n"
351                    "#define prefix_\n"
352                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
353            (setq point (point))
354            (goto-char (point-max))
355            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
356                    "#undef prefix_"))
357
358           ((string-match "\\.cti$" (buffer-file-name))
359            (insert "/** \\file\n"
360                    "    \\brief " (ccide-file-name) " inline template implementation */\n\n"
361                    "//#include \"" (ccide-file-name ".ih") "\"\n\n"
362                    "// Custom includes\n\n"
363                    "#define prefix_ inline\n"
364                    "//-/////////////////////////////////////////////////////////////////////////////////////////////////\n\n")
365            (setq point (point))
366            (goto-char (point-max))
367            (insert "\n\n//-/////////////////////////////////////////////////////////////////////////////////////////////////\n"
368                    "#undef prefix_"))
369
370           ((string-match "\\.dox$" (buffer-file-name))
371            (insert "/** \\mainpage\n\n    ")
372            (setq point (point))
373            (insert "\n */")
374            (setq add-file-vars '(( mode . flyspell)
375                                  ( mode . auto-fill))))
376
377           ((string-match "\\.java$" (buffer-file-name))
378            (setq mode "jde")
379            (setq point (point))
380            (goto-char (point-max)))
381
382           (t
383            (setq point (point))
384            (goto-char (point-max))))
385
386     (insert "\n\n\f\n"
387             "// Local Variables:\n"
388             "// mode: " mode "\n")
389     (loop for (var . value) in ccide-file-vars
390           do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
391     (loop for (var . value) in add-file-vars
392           do (insert "// " (symbol-name var) ": " (prin1-to-string value) "\n"))
393     (insert "// End:\n")
394     (if point
395         (goto-char point))
396     (if (equal mode "jde")
397         (let ((package (file-name-directory (buffer-file-name))))
398           (jdeap-initialize-setup)
399           (if (not (equal jdeap-current-source-directory "."))
400               (if (string-match
401                    (concat "^" (regexp-quote jdeap-current-source-directory))
402                    package)
403                   (progn
404                     (setq package (substring package
405                                              (match-end 0)
406                                              (1- (length package))))
407                     (insert "package "
408                             (string-replace "/" "." package t)
409                             ";\n\n"))))
410           (insert "class " (file-name-sans-extension
411                             (file-name-nondirectory
412                              (buffer-file-name))) "\n{}")
413           (beginning-of-line))))
414   (run-hooks 'ccide-new-file-hooks))
415
416 (defun ccide-sync-file-variables ()
417   "Syncronize file variables to the current value of ccide-file-vars"
418   (interactive)
419   (save-excursion
420     (goto-char (point-max))
421     (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
422     (let ((case-fold-search t))
423       (if (search-forward "Local Variables:" nil t)
424           (let (prefix suffix vars)
425             (skip-chars-forward " \t")
426             (or (eolp)
427                 (setq suffix (buffer-substring (point) (progn (end-of-line) (point)))))
428             (goto-char (match-beginning 0))
429             (or (bolp)
430                 (setq prefix (buffer-substring (point) (progn (beginning-of-line) (point)))))
431             (loop do (progn
432                        (forward-line 1)
433                        (if (and prefix (looking-at prefix))
434                            (goto-char (match-end 0)))
435                        (skip-chars-forward " \t"))
436                   while (not (looking-at "end:"))
437                   do (progn
438                        (setq vars (cons (intern (buffer-substring
439                                                  (point)
440                                                  (progn (skip-chars-forward "^:\n") (point))))
441                                         vars))))
442             (beginning-of-line)
443             (loop for (var . value) in ccide-file-vars
444                   do (if (not (memq var vars))
445                          (insert (or prefix "")
446                                  (symbol-name var) ": " (prin1-to-string value)
447                                  (or suffix "") "\n"))))))))
448
449 (defun ccide-syncronize-includes ()
450   "Syncronize include's in all other files"
451   (interactive)
452   (let (buffer-map)
453     (loop for extension in ccide-special-extensions
454           for file-name = (ccide-file-name extension)
455           do (setq buffer-map
456                    (cons (cons file-name
457                                (or (find-buffer-visiting file-name)
458                                    (and (file-readable-p file-name)
459                                         (find-file-noselect file-name))))
460                          buffer-map)))
461     (save-excursion
462       (loop for buffer in buffer-map
463             if (cdr buffer)
464               do (progn
465                    (set-buffer (cdr buffer))
466                    (save-excursion
467                      (loop for include in buffer-map
468                            do (progn
469                                 (goto-char (point-min))
470                                 (while (re-search-forward
471                                         (concat "^\\(//\\)?#\\s-*include \""
472                                                 (regexp-quote (car include))
473                                                 "\"\\s-*")
474                                         nil t)
475                                   (goto-char (match-beginning 0))
476                                   (if (looking-at "//")
477                                       (if (cdr include)
478                                           (delete-char 2))
479                                     (if (not (cdr include))
480                                         (insert "//")))
481                                   (forward-line 1))))))))))
482
483 (defun ccide-auto-decorate-new-files ()
484   (if (and (buffer-file-name) (= (point-min) (point-max)))
485       (if (or (not ccide-new-file-command)
486               (not (progn
487                      (save-buffer)
488                      (condition-case nil
489                          (progn
490                            (shell-command (format "%s %s" ccide-new-file-command (buffer-file-name)))
491                            (revert-buffer t t t)
492                            t)
493                        (error nil nil)))))
494           (let ((status (buffer-modified-p)))
495             (ccide-file-comment)
496             (set-buffer-modified-p status)))))
497
498 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
499 ;; class level
500
501 (defun ccide-class-comment ()
502   "Add comment to start of current class definition"
503   (interactive)
504   (let ((class (c-get-class-at-point)))
505     (if (not class)
506         (error "No class found")
507       (goto-char (or (aref (car class) 3)
508                      (aref (car class) 1)))
509       (if (save-excursion
510             (forward-line -1)
511             (ccide-in-doxy-comment))
512           (progn
513             (search-backward "/**" nil t)
514             (forward-char 4))
515         (let ((indent (make-string (current-indentation) ? )))
516           (insert "/** \\brief  ")
517           (save-excursion
518             (insert "\n"
519                     indent " */\n"
520                     indent)))))))
521
522 (defun ccide-gen-class (name &optional defns)
523   "Generate class declaration template"
524   (interactive (list (read-string (concat "Class name (default "
525                                           (ccide-file-name)
526                                           "): ")
527                                   nil nil (ccide-file-name))))
528   (insert "class " name)
529   (indent-according-to-mode)
530   (let ((in (make-string c-basic-offset ? ))
531         (ofs (make-string (current-indentation) ? ))
532         (sl (make-string (- 100 3 c-basic-offset (current-indentation)) ?/)))
533     (save-excursion
534       (beginning-of-line)
535       (open-line 1)
536       (insert ofs "/** \\brief\n"
537               ofs "  */"))
538     (insert "\n" ofs)
539     (save-excursion
540       (insert "{\n"
541               ofs "public:\n"
542               ofs in "//-" sl "\n"
543               ofs in "// Types\n\n"
544               ofs in "//-" sl "\n"
545               ofs in "///\\name Structors and default members\n"
546               ofs in "//\\{\n\n"
547               ofs in "// default default constructor\n"
548               ofs in "// default copy constructor\n"
549               ofs in "// default copy assignment\n"
550               ofs in "// default destructor\n\n"
551               ofs in "// no conversion constructors\n\n"
552               ofs in "//\\}\n"
553               ofs in "//-" sl "\n"
554               ofs in "///\\name Accessors\n"
555               ofs in "//\\{\n\n"
556               ofs in "//\\}\n"
557               ofs in "//-" sl "\n"
558               ofs in "///\\name Mutators\n"
559               ofs in "//\\{\n\n"
560               ofs in "//\\}\n\n")
561       (loop for defn in defns
562             do (insert ofs in defn ";\n"))
563       (if defns
564           (insert "\n"))
565       (insert ofs "protected:\n\n"
566               ofs "private:\n\n"
567               ofs "};\n"))))
568
569 (defun ccide-gen-class-defaults ()
570   "Generate signatures of the default functions: default constructor,
571 copy constructor, assignment operator and destructor."
572   (indent-according-to-mode)
573   (let* ((name (c-scope-name (aref (car (c-get-class-at-point)) 1)))
574          (in (make-string c-basic-offset ? ))
575          (ofs (make-string (current-indentation) ? ))
576          (tspec (if ccide-gen-throw (concat "\n" ofs in "throw_(());\n") ";\n"))
577          (colon 0))
578     (while (string-match "::" name colon)
579       (setq colon (match-end 0)))
580     (setq name (substring name colon))
581     (beginning-of-line)
582     (delete-horizontal-space)
583     (loop with exit = nil
584           do (message (concat "1-dflt constr, 2-destr, "
585                               "3-copy constr, 4-copy assmnt, "
586                               "c-all copy, d-all dflt, RET-all/done: "))
587           for ch = (read-event)
588           for first = t then nil
589           do (cond ((eq ch 'return)
590                     (if first
591                         (insert ofs name "()"
592                                 tspec
593                                 ofs name "(const " name "& other)"
594                                 tspec
595                                 ofs "~" name "();\n"
596                                 ofs name "& operator=(const " name "& other)"
597                                 tspec))
598                     (setq exit t))
599                    ((eq ch ?1)
600                     (insert ofs name "()"
601                             tspec))
602                    ((eq ch ?2)
603                     (insert ofs "~" name "();\n"))
604                    ((eq ch ?3)
605                     (insert ofs name "(const " name "& other)"
606                             tspec))
607                    ((eq ch ?4)
608                     (insert ofs name "& operator=(const " name "& other)"
609                             tspec))
610                    ((eq ch ?c)
611                     (insert ofs name "(const " name "& other)"
612                             tspec
613                             ofs name "& operator=(const " name "& other)"
614                             tspec))
615                    ((eq ch ?d)
616                     (insert ofs name "()"
617                             tspec
618                             ofs "~" name "();\n"))
619                    (t (setq unread-command-events (cons ch unread-command-events))
620                       (setq exit t)))
621           while (not exit))))
622
623 (defun ccide-gen-class-defaults-impl ()
624   "Generate default implementations for class default functions"
625   (interactive)
626   (let ((defn (c-build-default-funcions-impl)))
627     (kill-new (cadr defn))
628     (message (concat (car defn) " default members"))))
629
630 (defun ccide-set-class-defaults-comment (word)
631   (save-excursion
632     (back-to-indentation)
633     (if (not (looking-at ccide-class-defaults-word))
634         (message "Not at class defaults commnet")
635       (replace-match word t t nil 1))))
636
637 (defmacro ccide-build-class-defaults-f (sym)
638   (let ((fn (intern (concat "ccide-set-class-defaults-"
639                             (symbol-name sym)))))
640     `(defun ,fn ()
641        (interactive)
642        (ccide-set-class-defaults-comment ,(symbol-name sym)))))
643
644 (ccide-build-class-defaults-f no)
645 (ccide-build-class-defaults-f default)
646 (ccide-build-class-defaults-f my)
647 (ccide-build-class-defaults-f protected)
648 (ccide-build-class-defaults-f private)
649 (ccide-build-class-defaults-f disabled)
650
651 (defun ccide-gen-struct-constructors ()
652   (interactive)
653   (save-excursion
654     (beginning-of-line)
655     (open-line 1)
656     (indent-according-to-mode)
657     (let* ((scope (c-get-block-scope))
658            (class (c-parse-class scope))
659            (variables (c-get-variable-members-with-type class))
660            (name (c-scope-name (aref (car (last scope)) 1)))
661            (in (make-string (current-indentation) ? ))
662            (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
663       (insert name "()\n" inin ": ")
664       (loop for var in variables
665             for first = t then nil
666             if (not first) do (insert ", ")
667             do (insert (car var) " ()"))
668       (insert " {}\n\n"
669               in name "(")
670       (loop for var in variables
671             for first = t then nil
672             if (not first) do (insert ", ")
673             do (insert (cdr var) " " (car var) "_"))
674       (insert ")\n" inin ": ")
675       (loop for var in variables
676             for first = t then nil
677             if (not first) do (insert ", ")
678             do (insert (car var) " (" (car var) "_)"))
679       (insert " {}"))))
680
681
682 (defun ccide-gen-struct-compare ()
683   (interactive)
684   (save-excursion
685     (beginning-of-line)
686     (open-line 1)
687     (indent-according-to-mode)
688     (let* ((scope (c-get-block-scope))
689            (class (c-parse-class scope))
690            (variables (c-get-variable-members-with-type class))
691            (name (c-scope-name (aref (car (last scope)) 1)))
692            (in (make-string (current-indentation) ? ))
693            (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
694
695       (insert "bool operator<(" name " const & other) const\n"
696               in "{ return\n")
697       (loop for ((varName . varType) . tail) on variables
698             do (insert inin varName " < other." varName " ? true :")
699             do (if tail
700                    (insert "\n" inin "other." varName " < " varName " ? false :\n")
701                  (insert " false; }\n\n")))
702       (insert in "bool operator==(" name " const & other) const\n"
703               in "{ return\n")
704       (loop for ((varName . varType) . tail) on variables
705             do (insert inin varName " == other." varName)
706             do (if tail (insert " &&\n") (insert "; }\n\n")))
707       (insert in "std::size_type hash_value() const\n"
708               in "{ std::size_t current (0);\n")
709       (loop for ((varName . varType) . tail) on variables
710             do (insert inin "boost::hash_combine(current, " varName ");\n"))
711       (insert inin "return current; }\n\n")
712       (insert in "void write(std::ostream & os) const\n"
713               in "{ os << \"{ \"")
714       (loop for ((varName . varType) . tail) on variables
715             do (insert "\n" inin "<< " varName)
716             do (if tail (insert " << ' '")))
717       (insert " << \" }\"; }\n"))))
718
719 (defun ccide-class-impl-comment ()
720   "Get implementation comment for current class"
721   (interactive)
722   (let* ((scope (c-get-block-scope))
723          (name (c-get-full-prefix scope)))
724     (kill-new (concat (make-string 75 ?/) "\n"
725                       "// " name "\n\n"
726                       "// protected\n\n"
727                       "// private\n\n"))
728     (message name)))
729
730 (defun ccide-gen-exception (class &optional description)
731   (interactive "sException name: \nsDescription (defaults to full class name): ")
732   (beginning-of-line)
733   (open-line 1)
734   (indent-according-to-mode)
735   (save-excursion
736     (let ((in (make-string c-basic-offset ? ))
737           (ofs (make-string (current-indentation) ? ))
738           (prefix (c-get-full-prefix (c-get-block-scope)))
739           p)
740       (insert "struct " class " : public std::exception\n"
741               ofs "{ virtual char const * what() const throw() ")
742       (setq p (point))
743       (insert "{ return \""
744               (if (and description (> (length description) 0))
745                   description
746                 (concat prefix "::" class))
747               "\"; } };")
748       (if (> (current-column) fill-column)
749           (save-excursion
750             (goto-char p)
751             (insert "\n" ofs in in))))))
752
753 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
754 ;; function/method level
755
756 (defun ccide-function-comment ()
757   "Add comment for current function"
758   (interactive)
759   (if (memq (c-in-literal) '(c c++))
760       ; Assume, we are in the functions comment ...
761       (progn
762         (c-forward-out-of-comment)
763         (c-backward-syntactic-ws)
764         (c-backward-sexp))
765     (beginning-of-line))
766   (c-beginning-of-defun-or-decl)
767   (let ((defun (c-get-defun-state))
768         (indent (make-string comment-column ? ))
769         place)
770     (goto-char (or (aref defun 7) (car (aref defun 6))))
771     (c-backward-syntactic-ws)
772     (if (looking-at "[ \t\n\r]*///<")
773         (progn
774           (delete-region (point) (progn (skip-chars-forward " \t\n\r") (point)))
775           (if (> (current-column) comment-column)
776               (insert "\n"))
777           (indent-to-column comment-column)
778           (search-forward "*/")
779           (forward-char -2))
780       (if (> (current-column) comment-column)
781           (insert "\n"))
782       (indent-to-column comment-column)
783       (insert "///< ")
784       (setq place (point))
785       (insert "\n"
786               indent "/**< ")
787       (insert             "\\pre \n"
788                           indent "     \\post */")
789       (save-excursion
790         (goto-char (car (aref defun 2)))
791         (setq defun (c-get-defun-state)))
792       (forward-char -2))
793     (ccide-function-comment-adjust defun (concat indent "     "))
794     (if place (goto-char place))))
795
796 (defun ccide-function-comment-grab-args ()
797   (let ((limit (save-excursion
798                  (search-backward "/**" nil t)
799                  (point)))
800         (end  (point))
801         begin start args argend)
802     (setq argend end)
803     (while (or (search-backward "\\param" limit t)
804                (search-backward "\\return" limit t)))
805     (beginning-of-line)
806     (setq start (point))
807     (setq begin start)
808     (while (search-forward "\\param" argend t)
809       (or (search-forward "\\param" argend t)
810           (search-forward "\\return" argend t)
811           (goto-char argend))
812       (beginning-of-line)
813       (setq args (cons (ccide-function-comment-parse-arg start (point))
814                        args))
815       (setq start (point)))
816     (prog1
817         (if (not (search-forward "\return" argend t))
818             (cons nil args)
819           (beginning-of-line)
820           (cons (buffer-substring (point) argend) args))
821       (delete-region begin end))))
822
823 (defun ccide-function-comment-parse-arg (start end)
824   (save-excursion
825     (goto-char start)
826     (re-search-forward "\\\\param\\(\\[[^]]*\\]\\)?\\s-*\\(\\S-*\\)" end t)
827     (cons (match-string 2)
828           (cons (buffer-substring start (match-beginning 2))
829                 (buffer-substring (match-end 2) end)))))
830
831 (defun ccide-function-comment-get-throws (defun)
832   (if (aref defun 4)
833       (save-excursion
834         (goto-char (car (aref defun 4)))
835         (if (re-search-forward "\\(throw_\\|throw\\)((?\\s-*\\([^()]*\\))?)"
836                                (cdr (aref defun 4)) t)
837             (let ((spec (match-string 2)))
838               (if (> (length spec) 0)
839                   spec))))))
840
841 (defun ccide-function-comment-adjust (defun indent)
842   (insert "\n")
843   (let* ((defargs (mapcar (function (lambda (x)
844                                       (c-get-template-argument-name (car x) (cdr x))))
845                           (aref defun 3)))
846          (defret (and (aref defun 1)
847                       (not (string-match (concat "^\\("
848                                                  c-special-key
849                                                  "\\s-*\\)*\\s-*void$")
850                                          (buffer-substring (car (aref defun 1))
851                                                            (cdr (aref defun 1)))))))
852          (throws (ccide-function-comment-get-throws defun))
853          (xargs (ccide-function-comment-grab-args))
854          (docargs (cdr xargs))
855          (docret (car xargs))
856          (def-in-doc (loop for defarg in defargs always (assoc defarg docargs)))
857          (doc-in-def (loop for docarg in docargs always (member (car docarg) defargs)))
858          (size-eq (= (length defargs) (length docargs))))
859     ;; We differentiate four types changes
860     ;;  - new arguments
861     ;;  - removed arguments
862     ;;  - reordered arguments
863     ;;  - renamed arguments
864     ;;
865     ;; If the change cannot be described by one of the above, it has
866     ;; to be resolved manually
867     (if throws
868         (insert indent "\\throws " throws "\n"))
869     (cond (doc-in-def
870            ;; reordered arguments or new arguments (or no change)
871            (loop for defarg in defargs
872                  for docarg = (assoc defarg docargs)
873                  do (if docarg
874                         (insert (cadr docarg) (car docarg) (cddr docarg))
875                       (insert indent "\\param " defarg " \n"))))
876           (size-eq ; and (not doc-in-def)
877            ;; renamed arguments
878            (loop for defarg in defargs
879                  for docarg in docargs
880                  do (insert (cadr docarg) defarg (cddr docarg))))
881           (def-in-doc
882             ;; removed arguments
883             (loop for defarg in defargs
884                   for docarg = (assoc defarg docargs)
885                   do (insert (cadr docarg) (car docarg) (cddr docarg))))
886           (t (error "Arg change too complex. Resolve manualy.")))
887     ;; return value is simple
888     (if defret
889         (if docret
890             (insert docret)
891           (insert indent "\\return \n"))))
892   (delete-char -1)
893   (delete-horizontal-space)
894   (insert " "))
895
896 (defun ccide-grab-prototype (&optional prefix)
897   "Grab prototype of function defined or declared at point. Prefix
898 arg, if given, specifies the kind of prefix (inline, static, ...) to use."
899   (interactive "P")
900   (save-excursion
901     (c-beginning-of-defun-or-decl)
902     (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
903                      ccide-default-prefix))
904            (defn (c-build-defun prfx)))
905       (kill-new (concat (cadr defn) "\n{}\n"))
906       (message (concat (or prfx "")
907                        (if prfx " " "")
908                        (car defn))))))
909
910 (defun ccide-reformat-defun ()
911   "Reformat the defn of the current defun."
912   (interactive)
913   (save-excursion
914     (c-beginning-of-defun-or-decl)
915     (let ((defn (c-build-defun nil t)))
916       (delete-region (or (caar (aref (caddr defn) 0))
917                          (car (aref (caddr defn) 1))
918                          (car (aref (caddr defn) 2)))
919                      (or (car (aref (caddr defn) 6))
920                          (aref (caddr defn) 7)))
921       (insert (cadr defn) "\n"))))
922
923 (defun ccide-replace-defun ()
924   "Replace the function header with the one on the top of the kill
925 ring (presumably placed there using c++-grab-prototype)."
926   (interactive)
927   (save-excursion
928     (c-beginning-of-defun-or-decl)
929     (let ((parse (c-parse-defun)))
930       (delete-region (or (aref parse 0)
931                          (aref parse 1)
932                          (aref parse 2))
933                      (or (aref parse 5)
934                          (aref parse 6)
935                          (aref parse 7)))
936       (yank)
937       (delete-char -3))))
938
939 (defun ccide-prefix-defun-type-with-class (&optional strip)
940   "If a non-keyword type symbol is found prefixing the current defun,
941 it will be prefixed with the current class prefix."
942   (interactive "p")
943   (save-excursion
944     (c-beginning-of-defun-or-decl)
945     (let* ((parse (c-parse-defun))
946            (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
947       (goto-char (aref parse 1))
948       (while (and (or (looking-at c-any-key)
949                       (looking-at c-user-prefix-re)
950                       (not (c-at-symbol-p)))
951                   (< (point) (aref parse 2))
952                   (not (eobp)))
953         (c-forward-token-1)
954         (c-forward-syntactic-ws))
955       (if (and (c-at-symbol-p)
956                (< (point) (aref parse 2))
957                (not (looking-at (regexp-quote prefix))))
958           (let ((pos (string-match "<" prefix)))
959             (if pos
960                 (insert "typename "))
961             (if (and pos (looking-at (concat (substring prefix 0 pos)
962                                              "\\b[^_]")))
963                 (progn
964                   (goto-char (match-end 0))
965                   (c-backward-syntactic-ws)
966                   (insert (substring prefix pos)))
967               (insert prefix "::"))
968             (ccide-reformat-defun))))))
969
970 (defun ccide-prefix-defun-type-with-namespace (&optional strip)
971   (interactive "p")
972   (ccide-prefix-defun-type-with-class (+ (or strip 0) 1)))
973
974 (defun ccide-insert-defun-prefix (&optional strip)
975   "Insert the current defun prefix at point."
976   (interactive "p")
977   (let* ((parse (c-parse-defun))
978          (prefix (c-scope-name (aref parse 2) (+ (or strip 0) 0))))
979     (insert prefix "::")))
980
981 (defun ccide-kill-inline-decl (defn)
982   (save-excursion
983     (if (aref (caddr defn) 6)
984         (progn
985           (goto-char (cdr (aref (caddr defn) 6)))
986           (let ((end-mark (point-marker)))
987             (goto-char (car (aref (caddr defn) 6)))
988             (indent-rigidly (point) end-mark
989                             (- (current-column)))
990             (prog1
991                 (concat (cadr defn)
992                         "\n"
993                         (buffer-substring-no-properties (point) end-mark)
994                         "\n")
995               (when (aref (caddr defn) 5)
996                 (goto-char (caar (aref (caddr defn) 5)))
997                 (c-backward-syntactic-ws)
998                 (skip-chars-backward ":"))
999               (c-backward-syntactic-ws)
1000               (delete-region (point) end-mark)
1001               (insert ";"))))
1002       (concat (cadr defn) "\n{}\n"))))
1003
1004 (defun ccide-grab-inline-decl ()
1005   "Grab the inline decl at point at turn it into an out-of-line inline
1006 declaration at the top of the kill ring."
1007   (interactive)
1008   (let ((defn (c-build-defun (or ccide-default-prefix "inline"))))
1009     (kill-new (ccide-kill-inline-decl defn))
1010     (message (concat (or ccide-default-prefix "indline")
1011                      " "
1012                      (car defn)))))
1013
1014 (defun ccide-grab-all-inlines ()
1015   "Grab all inline decls in the current class"
1016   (interactive)
1017   (let ((class (c-parse-class (c-get-block-scope)))
1018         defns)
1019     (when class
1020       (loop for method in (nreverse (aref class 4))
1021             do (when (eq (car method) 'method)
1022                  (let ((defn (save-excursion
1023                                (goto-char (cdr method))
1024                                (c-build-defun (or ccide-default-prefix "inline")))))
1025                    (if (aref (caddr defn) 6)
1026                        (setq defns (nconc defns (list (ccide-kill-inline-decl defn))))))))
1027       (setq defns (nreverse defns))
1028       (kill-new (loop for defn in defns
1029                       for next = nil then t
1030                       if next concat "\n";
1031                       concat defn))
1032       (message (format "%d inlines grabed to kill ring" (length defns))))))
1033
1034 (defun ccide-grab-create-constructor ()
1035   (interactive)
1036   (let ((defn (c-build-create-constructor)))
1037     (kill-new (cadr defn))
1038     (message (car defn))))
1039
1040 (defun ccide-grab-create-constructor-impl (&optional prefix)
1041   (interactive "P")
1042   (let* ((prfx (or (and prefix (nth (prefix-numeric-value prefix) c-user-prefixes))
1043                    ccide-default-prefix))
1044          (defn (c-build-create-constructor-impl prfx)))
1045     (kill-new (cadr defn))
1046     (message (concat (or prfx "")
1047                      (if prfx " " "")
1048                      (car defn)))))
1049
1050 (defun ccide-find-implementation (&optional other-window)
1051   "Find implementation of method declared at point."
1052   (interactive "P")
1053   (let* ((state (c-get-defun-state))
1054          (name (c-defun-short-name state))
1055          (scoped-name (c-defun-full-name state))
1056          (args (ccide-implementation-args state))
1057          (targs (ccide-implementation-template-args state))
1058          rv fallback)
1059
1060     (loop for ext in ccide-implementation-extensions
1061           for filename = (ccide-file-name ext)
1062           while (not rv)
1063           do (progn
1064                (let ((buf (or (find-buffer-visiting filename)
1065                                   (and (file-readable-p filename)
1066                                        (find-file-noselect filename)))))
1067                  (when buf
1068                    (let ((found (save-excursion
1069                                   (set-buffer buf)
1070                                   (ccide-find-implementation-1 name scoped-name args targs
1071                                                                (not (aref state 6))
1072                                                                (car (aref state 2))))))
1073                      (if found
1074                          (if (cdr found)
1075                              (setq rv (cons buf found))
1076                            (if (not fallback) (setq fallback (cons buf found))))))))))
1077     (if (not rv) (setq rv fallback))
1078     (if rv
1079         (let* ((buf (car rv))
1080                (pos (cadr rv))
1081                (win (get-buffer-window buf)))
1082           (if win
1083               (select-window win)
1084             (if other-window
1085                 (switch-to-buffer-other-window buf)
1086               (switch-to-buffer buf)))
1087           (goto-char pos)
1088           (forward-char -1)
1089           (c-beginning-of-defun-or-decl))
1090       (message (concat "Implementation of " scoped-name " not found.")))))
1091
1092 (defun ccide-implementation-args (state)
1093   (string-replace "[ \t\n\r]+" ""
1094                   (loop for (start . end) in (aref state 3)
1095                         for sep = "" then ","
1096                         concat sep
1097                         concat (buffer-substring-no-properties
1098                                 start (save-excursion
1099                                         (goto-char start)
1100                                         (if (search-forward "=" end 'move) (forward-char -1))
1101                                         (point))))
1102
1103                   t))
1104
1105 (defun ccide-implementation-template-args (state)
1106   (and (aref state 0)
1107        (string-replace "[ \t\n\r]+" ""
1108                        (loop for (start . end) in   (save-excursion
1109                                                       (goto-char (caar (last (aref state 0))))
1110                                                       (c-parse-template-declaration))
1111                              for sep = "" then ","
1112                              concat sep
1113                              concat (buffer-substring-no-properties
1114                                      start (save-excursion
1115                                              (goto-char start)
1116                                              (if (search-forward "=" end 'move) (forward-char -1))
1117                                              (point))))
1118                        t)))
1119
1120 (defun ccide-find-implementation-1 (name scoped-name args targs with-body skip-def)
1121   ;; Within the current buffer, search for all implementations of the
1122   ;; given function. The rv is a list of conses. The car holds the
1123   ;; buffer position of the implementation, the cdr is t if the name,
1124   ;; scoped-name and args are matched, otherwise the args did not match.
1125   (save-excursion
1126     (goto-char (point-min))
1127     (let ((re (concat (if (eq (char-syntax (aref name 0)) ?w) "\\<" "")
1128                       (regexp-quote name)
1129                       (if (eq (char-syntax (aref name (1- (length name)))) ?w) "\\>" "")))
1130           fallback rv check-state)
1131       (while (and (not rv) (re-search-forward re nil t))
1132         (if (c-save-buffer-state ()
1133               (and (c-at-toplevel-p)
1134                    (not (c-in-literal))
1135                    (setq check-state (condition-case nil (c-get-defun-state) (error nil)))
1136                    (not (= (car (aref check-state 2)) skip-def))))
1137             (if (string= scoped-name (c-defun-full-name check-state))
1138                 (if (and (if with-body (aref check-state 6) (not (aref check-state 6)))
1139                          (string= args (ccide-implementation-args check-state))
1140                          (string= targs (ccide-implementation-template-args check-state)))
1141                     (setq rv (cons (point) t))
1142                   (if (not fallback)
1143                       (setq fallback (cons (point) nil)))))))
1144       (or rv fallback))))
1145
1146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1147 ;; variable/type level
1148
1149 (defun ccide-variable-comment ()
1150   "Add a comment to current variable declaration."
1151   (interactive)
1152   (c-forward-out-of-comment)
1153   (c-forward-syntactic-ws)
1154   (while (not (looking-at ";"))
1155     (c-forward-sexp)
1156     (c-forward-syntactic-ws))
1157   (forward-char 1)
1158   (if (> (current-column) comment-column)
1159       (insert "\n" (make-string comment-column ? ) "///< ")
1160     (indent-to-column comment-column)
1161     (insert "///< ")))
1162
1163 (defun ccide-grab-access-fn ()
1164   (interactive)
1165   (save-excursion
1166     (beginning-of-line)
1167     (if (looking-at (concat c++-simple-type-regexp "[ \t\n\r][a-zA-Z0-9_]+[ \t\n\r]*;"))
1168         (let ((vardef (match-string 0))
1169               (in (make-string c-basic-offset ? ))
1170               type reftype varname fnname argname ws)
1171           (forward-line -1)
1172           (back-to-indentation)
1173           (string-match "^[ \t\n\r]*\\(.*\\)[ \t\n\r]\\([a-zA-Z0-9_]+\\)[ \t\n\r]*;$"
1174                         vardef)
1175           (setq varname (match-string 2 vardef)
1176                 type (match-string 1 vardef)
1177                 ws (substring vardef 0 (match-beginning 1)))
1178           (if (string-match "_$" varname)
1179               (setq fnname (string-replace "_$" "" varname)
1180                     argname (concat "a_" fnname))
1181             (setq fnname (concat "q_" varname)
1182                   argname (concat "a_" varname)))
1183           (if (string-match "^[ \t\n\r]*" type)
1184               (setq type (substring type (match-end 0))))
1185           (if (string-match "^[A-Z]" type)
1186               (setq reftype (concat type " const &"))
1187             (setq reftype type))
1188           (kill-new (concat ws type " " fnname "(" reftype " " argname ")\n"
1189                             ws in "{\n"
1190                             ws in in type " old" varname " = " varname ";\n"
1191                             ws in in varname " = " argname ";\n"
1192                             ws in in "return old" varname ";\n"
1193                             ws in "}\n\n"
1194                             ws reftype " " fnname "() const\n"
1195                             ws in "{ return " varname "; }\n"))
1196
1197           (message varname))
1198       (message "No variable found"))))
1199
1200 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1201 ;; doxy comment support functions
1202
1203 (defun ccide-special-indent-function ()
1204   "Function to indent doxy comments correctly"
1205   (let ((indent (ccide-in-doxy-comment)))
1206     (if indent
1207         (let ((lim (save-excursion
1208                      (back-to-indentation)
1209                      (c-literal-limits)))
1210               (pos (- (point-max) (point))))
1211           (save-excursion
1212             (back-to-indentation)
1213             (if (looking-at "*/")
1214                 (incf indent -3)
1215               (let ((para (or (save-excursion (re-search-backward "^\\s-*$" (car lim) t))
1216                               (car lim))))
1217                 (if (and (not (looking-at ccide-doxy-tag-re))
1218                          (re-search-backward (concat "^\\s-*"
1219                                                      ccide-doxy-tag-re)
1220                                              para t))
1221                     (incf indent 4)))))
1222           (delete-region (progn (beginning-of-line) (point))
1223                          (progn (back-to-indentation) (point)))
1224           (indent-to indent)
1225           (if (> (- (point-max) pos) (point))
1226               (goto-char (- (point-max) pos)))))))
1227
1228 (defun ccide-fill-function ()
1229   "auto-fill function for doxy comments"
1230   (if (do-auto-fill)
1231       (if (not fill-prefix)
1232           (indent-according-to-mode))))
1233
1234 (defun ccide-hide-all-doxy-comments ()
1235   "Hide all doxy comments"
1236   (interactive)
1237   (save-excursion
1238     (goto-char (point-min))
1239     (while (re-search-forward "^\\s-*/\\*\\*" nil t)
1240       (beginning-of-line)
1241       (forward-line -1)
1242       (if (not (looking-at "\\s-*$"))
1243           (forward-line 1))
1244       (forward-char -1)
1245       (let ((start (point)))
1246         (if (re-search-forward "\\*/" nil t)
1247             (progn
1248               (if (looking-at "\\s-*\n")
1249                   (forward-line 1))
1250               (forward-char -1)
1251               (let ((overlay (make-overlay start (point))))
1252                 (overlay-put overlay 'intangible 'hs)
1253                 (overlay-put overlay 'invisible 'hs)))))))
1254   (message "Done."))
1255
1256 (defun ccide-show-all-comments ()
1257   "Show all comments"
1258   (interactive)
1259   (save-excursion
1260     (goto-char (point-min))
1261     (while (not (eobp))
1262       (goto-char (next-overlay-change (point)))
1263       (loop for overlay in (overlays-at (point))
1264             if (eq (overlay-get overlay 'invisible) 'hs)
1265             do (delete-overlay overlay))))
1266   (message "Done."))
1267
1268 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1269 ;; CORBA support (omniORB2)
1270
1271 (defun ccide-get-corba-headers ()
1272   (let (files)
1273     (save-excursion
1274       (goto-char (point-min))
1275       (while (re-search-forward "#include\\s-*[\"<]\\([^\">]*\\)\\.hh[\">]" nil t)
1276         (setq files (cons (ccide-match-string 1) files)))
1277       (nreverse files))))
1278
1279 (defun ccide-corba-maybe-build-hh (file)
1280   (let ((skel (ccide-file-name ".hh" file ccide-corba-skel-dir))
1281         (idl (ccide-file-name ".idl" file ccide-corba-idl-dir)))
1282     (if (and (file-readable-p idl)
1283              (or (not (file-readable-p skel))
1284                  (file-newer-than-file-p idl skel)))
1285         (let ((buffer (find-buffer-visiting (ccide-file-name ".hh" file))))
1286           (if buffer
1287               (kill-buffer buffer))
1288           (message "Please wait ... building %s" (ccide-file-name ".hh" file))
1289           (if (ccide-shell-command (concat "cd "
1290                                            (real-path-name ccide-corba-skel-dir)
1291                                            " && "
1292                                            ccide-corba-idl-command
1293                                            (if (> (length ccide-corba-idl-dir) 0)
1294                                                (concat " -I" ccide-corba-idl-dir))
1295                                            " "
1296                                            idl))
1297               ()
1298             (display-buffer (get-buffer-create "*ccide shell command*"))
1299             (error "Generation of %s failed" (ccide-file-name ".hh")))))
1300     (if (not (file-readable-p skel))
1301         (error "No file %s or %s"
1302                (ccide-file-name ".hh" file) (ccide-file-name ".idl" file)))))
1303
1304 (defun ccide-corba-list-skeletons-1 (hh-file)
1305   (ccide-corba-maybe-build-hh hh-file)
1306   (let ((hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file)))
1307         skels)
1308     (save-excursion
1309       (set-buffer hh-buf)
1310       (save-excursion
1311         (goto-char (point-min))
1312         (while (re-search-forward "^\\s-*class\\s-+_sk_\\([a-zA-Z0-9_]+\\)\\s-+:"
1313                                   nil t)
1314           (setq skels (cons (ccide-match-string 1) skels)))))
1315     (mapcar (function (lambda (x) (cons x hh-file)))
1316             (sort skels 'string-lessp))))
1317
1318 (defun ccide-corba-list-skeletons ()
1319   (let ((files (ccide-get-corba-headers)))
1320     (loop for file in files
1321           append (ccide-corba-list-skeletons-1 file))))
1322
1323 (defun ccide-gen-corba-impl (class)
1324   (interactive (list (completing-read "Class name of skeleton: "
1325                                       (ccide-corba-list-skeletons)
1326                                       nil t)))
1327   (let* ((skels (ccide-corba-list-skeletons))
1328          (hh-file (ccide-file-name ".hh" (cdr (assoc class skels))
1329                                    ccide-corba-skel-dir))
1330          (hh-buf (find-file-noselect (ccide-file-name ".hh" hh-file
1331                                                       ccide-corba-skel-dir))))
1332     (ccide-gen-class (concat class "_i"))
1333     (insert (make-string c-basic-offset ? ) ": public virtual _sk_" class "\n")
1334     (save-excursion
1335       (search-forward "protected:" nil t)
1336       (forward-line -1)
1337       (ccide-gen-corba-impl-methods)
1338       (insert "\n"))))
1339
1340 (defun ccide-get-corba-defns (hh-file class)
1341   (let ((hh-buf (find-file-noselect hh-file))
1342         defns)
1343     (save-excursion
1344       (set-buffer hh-buf)
1345       (save-excursion
1346         (goto-char (point-min))
1347         (if (not (re-search-forward (concat "^\\s-*class\\s-+_sk_" class "\\s-+:")
1348                                     nil t))
1349             (error "CORBA skeleton class not found.")
1350           (search-forward "{")
1351           (forward-char -1)
1352           (let ((end (save-excursion (forward-sexp) (point))))
1353             (while (and (< (point) end)
1354                         (< (forward-line 1) 1))
1355               (if (looking-at "\\s-+virtual\\s-+\\(.*)\\)\\s-*=\\s-*0;\\s-*$")
1356                   (setq defns (cons (match-string 1) defns))))))))
1357     (nreverse defns)))
1358
1359 (defun ccide-gen-corba-impl-methods ()
1360   (interactive)
1361   (let* ((class (c-get-class-at-point))
1362          (point (point)))
1363     (if (not class)
1364         (error "No class at point."))
1365     (save-excursion
1366       (goto-char (aref (car class) 1))
1367       (if (not (re-search-forward ":\\s-*public\\s-*virtual\\s-*_sk_\\([^ \t\n\r{},:]*\\)"
1368                                   nil t))
1369           (error "No CORBA impl at point."))
1370       (let* ((name (ccide-match-string 1))
1371              (skels (ccide-corba-list-skeletons))
1372              (hh-file (ccide-file-name ".hh" (cdr (assoc name skels))
1373                                        ccide-corba-skel-dir))
1374              (defns (ccide-get-corba-defns hh-file name))
1375              end)
1376         (goto-char (aref (car class) 2))
1377         (save-excursion
1378           (c-forward-sexp)
1379           (setq end (point)))
1380         (if (re-search-forward "^\\s-*// CORBA$" end t)
1381             (let ((start (match-beginning 0)))
1382               (if (re-search-forward "^\\s-*// END-CORBA$" end t)
1383                   (let ((eend (match-end 0)))
1384                     (goto-char start)
1385                     (forward-line 1)
1386                     (if (re-search-forward "/\\*\\|//" (match-beginning 0) t)
1387                         (if (y-or-n-p "Remove CORBA Funktion comments? (y/n)")
1388                             (delete-region start (1+ eend))
1389                           (goto-char eend)
1390                           (beginning-of-line)
1391                           (delete-region (point) (progn
1392                                                    (end-of-line)
1393                                                    (1+ (point))))
1394                           (save-excursion
1395                             (goto-char start)
1396                             (delete-region (point) (progn
1397                                                      (end-of-line)
1398                                                      (1+ (point)))))
1399                           (insert "\n"))
1400                       (delete-region start (1+ eend))))))
1401           (goto-char point))
1402         (indent-according-to-mode)
1403         (insert "// CORBA\n")
1404         (loop for defn in defns
1405               do (progn
1406                    (save-excursion (insert defn ";"))
1407                    (indent-according-to-mode)
1408                    (let ((start (point)) end)
1409                      (end-of-line)
1410                      (setq end (point))
1411                      (goto-char start)
1412                      (while (re-search-forward "\\s-+" end t)
1413                        (replace-match " ")
1414                        (setq end (- end (- (match-end 0) (match-beginning 0) 1))))
1415                      (end-of-line)
1416                      (loop with done = nil
1417                            while (> (current-column) c-max-def-column)
1418                            do (while (and (> (current-column) c-max-def-column)
1419                                           (search-backward "," start t)))
1420                            do (if (looking-at ",")
1421                                   (progn
1422                                     (forward-char 1)
1423                                     (insert "\n")
1424                                     (open-line 1)
1425                                     (indent-according-to-mode)
1426                                     (delete-char 2)
1427                                     (setq start (point))
1428                                     (end-of-line))
1429                                 (setq done t))
1430                            while (not done)))
1431                    (insert "\n")))
1432         (indent-according-to-mode)
1433         (insert "// END-CORBA\n")))))
1434
1435 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1436 ;; template support
1437
1438 (defun ccide-scan-mantemps ()
1439   "Scan *compilation* buffer for errors and generate manual template
1440 instatiations at point."
1441   (interactive)
1442   (save-excursion
1443     (set-buffer "*compilation*")
1444     (goto-char (point-min)))
1445   (save-excursion
1446     (set-buffer (get-buffer-create "*mantemps*"))
1447     (erase-buffer)
1448     (loop for temp = (ccide-get-mantemp)
1449           while temp
1450           do (insert temp "\n"))
1451     (mantemp-make-mantemps-buffer)
1452     (goto-char (point-min))
1453     (while (progn
1454              (ccide-fix-mantemp)
1455              (< (forward-line 1) 1))))
1456   (insert-buffer-substring "*mantemps*"))
1457
1458 (defun ccide-get-mantemp ()
1459   (save-excursion
1460     (set-buffer "*compilation*")
1461     (if (search-forward "undefined reference to `" nil t)
1462         (let ((start (point)))
1463           (end-of-line)
1464           (search-backward "'" nil t)
1465           (buffer-substring start (point))))))
1466
1467 (defun ccide-fix-mantemp ()
1468   (let ((end (save-excursion
1469                (end-of-line) (point))))
1470     (if (and (save-excursion (search-forward "(" end t))
1471              (search-forward " class" end t))
1472         (progn
1473           (forward-char -6)
1474           (delete-char 6)))))
1475
1476 (provide 'cc-ide)
1477
1478 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1479 ;; cython support
1480
1481 (defun ccide-grab-pxd-fn ()
1482   (interactive)
1483   (save-excursion
1484     (c-beginning-of-defun-or-decl)
1485     (let ((defn (c-build-pxd)))
1486       (kill-new (cadr defn))
1487       (message (concat (car defn))))))
1488
1489 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1490 ;; other stuff
1491
1492 (defun ccide-open-compilation-frame ()
1493   (interactive)
1494   (let ((c-frame (selected-frame))
1495         (compilation-frame (make-frame '((minibuffer . nil)
1496                                          (unsplittable . t)
1497                                          (menu-bar-lines . 0)
1498                                          (top . -87)
1499                                          (left . 36)
1500                                          (width . 169)
1501                                          (height . 9)))))
1502     (select-frame compilation-frame)
1503     (switch-to-buffer "*compilation*")
1504     (set-window-dedicated-p (selected-window) t)))
1505
1506 (defun ccide-compile (command)
1507   (delete-other-windows)
1508   (split-window-horizontally)
1509   (compile command)
1510   (save-excursion
1511     (set-buffer "*compilation*")
1512     (let ((point (point-max)))
1513       (goto-char point)
1514       (loop for window in (get-buffer-window-list "*compilation*" nil t)
1515             do (set-window-point window point)))))
1516
1517 (defun ccide-compile-compile ()
1518   (interactive)
1519   (ccide-compile (concat "make -k " ccide-compile-opts)))
1520
1521 (defun ccide-compile-clean ()
1522   (interactive)
1523   (ccide-compile (concat "make -k " ccide-compile-opts " clean")))
1524
1525 (defun ccide-compile-cleandepends ()
1526   (interactive)
1527   (ccide-compile (concat "make -k " ccide-compile-opts " cleandepends")))
1528
1529 (defun ccide-compile-kill ()
1530   (interactive)
1531   (set-buffer "*compilation*")
1532   (kill-compilation))
1533
1534 (defun ccide-hide-compilation ()
1535   (interactive)
1536   (let ((active (selected-window)))
1537     (unwind-protect
1538         (loop for window in (get-buffer-window-list "*compilation*")
1539               do (progn (select-window window)
1540                         (switch-to-buffer (other-buffer "*compilation*"))))
1541       (select-window active))))
1542
1543 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1544 ;; keymap and installation
1545
1546 (defun ccide-bind-keys (prefix map)
1547   (loop for binding in ccide-bindings
1548         do (apply 'vcmd-define-key
1549                   map
1550                   (concat prefix (car binding))
1551                   (cadr binding)
1552                   "IDE"
1553                   (cddr binding))))
1554
1555 (defun ccide-install-it ()
1556   (save-excursion
1557     (hs-minor-mode 1)
1558     (hs-show-all))
1559   (local-unset-key "\C-c;")
1560   (local-unset-key [menu-bar IDE])
1561   (ccide-bind-keys "\C-c;" (current-local-map))
1562   (local-set-key "\C-cC" 'ccide-hide-all-doxy-comments)
1563   (local-set-key "\C-cS" 'ccide-show-all-comments)
1564   (set (make-local-variable 'auto-fill-function) 'ccide-fill-function)
1565   (set (make-local-variable 'paragraph-start) (concat "[ \t\f]*$\\|[ \t\f]*" ccide-doxy-tag-re))
1566   (set (make-local-variable 'paragraph-separate) "[ \t\f]*$")
1567   (auto-fill-mode -1)
1568   (ccide-project-load-config)
1569   (ccide-directory-load-config)
1570   (ccide-auto-decorate-new-files)
1571   (if ccide-format-command
1572       (add-hook 'write-contents-functions 'ccide-format-buffer nil t)))
1573
1574 (defun ccide-format-buffer ()
1575   (interactive)
1576   (if ccide-format-command
1577       (let ((bkmp (bookmark-make-record)))
1578         (unwind-protect
1579             (shell-command-on-region (point-min) (point-max) ccide-format-command nil t)
1580           (goto-char (cdr (bookmark-jump-noselect bkmp))))))
1581   nil)
1582
1583 (defun ccide-project-load-config ()
1584   (if (buffer-file-name)
1585       (let ((conf (ccide-project-search-upwards '(".project.el" "project.el")
1586                                                 (file-name-directory (buffer-file-name)))))
1587         (when conf
1588           (set (make-local-variable 'ccide-project-root) (file-name-directory conf))
1589           (load-file conf)))))
1590
1591 (defun ccide-project-search-upwards (names &optional base)
1592   "Search for FILE in all directories starting at DIR and going up the directory hierarchy.
1593 DIR defaults to ccide-project-root. If FILE is a list, search for any file in list."
1594   (if (not (consp names))
1595       (setq names (list names)))
1596   (loop for dir = (or base ccide-project-root) then (directory-file-name (file-name-directory dir))
1597         while (not (string= dir "/"))
1598         thereis (loop for name in names
1599                       for path = (expand-file-name name dir)
1600                       thereis (and (file-readable-p path) path))))
1601
1602 (defun ccide-directory-load-config ()
1603   (if (file-readable-p ".dir.el")
1604       (load-file ".dir.el")))
1605
1606 (add-hook 'c-mode-hook 'ccide-install-it)
1607 (add-hook 'c++-mode-hook 'ccide-install-it)
1608 (add-hook 'c-special-indent-hook 'ccide-special-indent-function)
1609
1610 (loop for extension in ccide-special-extensions
1611       for re = (concat (regexp-quote extension) "$")
1612       if (not (assoc re auto-mode-alist))
1613         do (setq auto-mode-alist (append auto-mode-alist
1614                                          (list (cons re 'c++-mode)))))
1615
1616 (defadvice c-indent-line (after c-indent-less compile disable) ;activate
1617   ;; new indent function for c-mode: do standard indentation first. If line
1618   ;; is to long using standard indentation, just indent by c-basic-indentation.
1619   (let ((cc (save-excursion (end-of-line) (current-column)))
1620         indent)
1621     (if (> cc  85)
1622         (let ((pos (- (point-max) (point))))
1623           (beginning-of-line)
1624           (let ((point (point))
1625                 (line (1+ (count-lines 1 (point))))
1626                 indent)
1627             (c-beginning-of-statement-2)
1628             (if (and (not (c-crosses-statement-barrier-p (point) point))
1629                      (not (eq (+ (count-lines 1 (point))
1630                                  (if (bolp) 1 0))
1631                               line)))
1632                 (progn
1633                   (setq indent (+ (current-indentation) c-basic-offset))
1634                   (goto-char point)
1635                   (if (< indent (current-indentation))
1636                       (progn
1637                         (setq ad-return-value
1638                               (+ ad-return-value
1639                                  (- (current-indentation) indent)))
1640                         (delete-region (c-point 'bol) (c-point 'boi))
1641                         (indent-to indent))))))
1642           (if (< (point) (c-point 'boi))
1643               (back-to-indentation)
1644             (if (> (- (point-max) pos) (point))
1645                 (goto-char (- (point-max) pos))))))))
1646
1647 \f
1648 ;;; Local Variables:
1649 ;;; elisp-project-autoload-file-name: "cc-autoload.el"
1650 ;;; End: