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