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