1 ; Problem with this RE: a) If the line before the function declaration
2 ; is a preprocessor directive (like a #define) ending in one or more
3 ; c++ type keywords they will get included into the type spec. b) if
4 ; you define a symbol like #define _const const the expression won't
7 ; Another possible regexp for c++-simple-type-regexp is "^.+". This
8 ; will make any text before the name of the function but in the same
9 ; line be the type of the function. Problem: Type cannot span multiple
12 (defvar c++-prefixes '("__inline__" "static"))
14 (defconst c++-simple-type-regexp "\\(\\([ \t\n\r]+\\(inline\\|explicit\\|unsigned\\|signed\\|short\\|long\\|const\\|static\\|friend\\)\\)*[ \t\n\r]+[a-zA-Z0-9_]+\\(<[a-zA-Z0-9_, \t\n\t]*>\\)?\\([ \t\n\r]+\\(const[ \t\n\r]+\\)\\)?\\([*&]\\|\\[[ \t\n\r]*[0-9]+[ \t\n\r]*\\]\\)*\\([ \t\n\r]+const\\)?\\)[ \t\n\r]*"
15 "*The RE for a simple type in C++ that is types that neither involve
16 blocks nor functions")
18 (defconst c++-function-regexp "[^a-zA-Z0-9_:]\\(\\([a-zA-Z0-9_]+\\(<[a-zA-Z0-9_, \t\n\r]*>\\)?::\\)*\\(\\(operator[ \t\n\r]*\\([-+*/.&^|=]\\|++\\|--\\|&&\\|||\\|new\\|delete\\|()\\|\\[\\]\\|->\\|[^();{}]+\\)=?\\)\\|~?[a-zA-Z0-e9_]+\\)\\)[ \t\n\r]*"
19 "The RE for a function definition or declaration")
21 (defconst c++-class-regexp "\\(class\\|namespace\\)[ \t\n\r]+\\([a-zA-Z0-9_:]+\\)\\([ \t\n\r]*:\\([ \t\n\r]*\\(public\\|protected\\|private\\)?[ \t\n\r]*\\([a-zA-Z0-9_]+\\(<[^>]*>\\)?\\(::\\)?\\)*[ \t\n\r]*,?\\)*\\)?[ \t\n\r]*"
22 "The RE for a class declaration")
24 (defconst c++-template-regexp "template[ \t\n\r]*<\\([^>]*\\)>[ \t\n\r]*"
25 "The RE for matching template clauses.")
27 (defconst c++-function-keywords
28 '( "if" "while" "for" "repeat" "class" "struct" "union" "switch" )
29 "C++ Keywords which may introduce a block")
31 (defconst c++-keywords
32 '( "if" "while" "for" "repeat" "class" "struct" "union" "typedef"
33 "char" "int" "float" "double" "signed" "unsigned" "long" "const"
34 "switch" "case" "repeat" "until" "do" "class" "public"
35 "protected" "private" "friend" "operator" "void" "static" "explicit" )
38 (defvar c++-smart-wrap-column 80)
43 (defun c++-scan-type-backward ()
44 "Scans backward to find the longest valid simple type ending at POINT.
45 Assumes POINT is at the end of a C++ simple type expression.
46 Leaves POINT at the beginning of the type expression and returns
47 ( TYPE-START . TYPE-END )"
51 (re-search-backward c++-simple-type-regexp 'nil 't)
53 (while (and (re-search-forward c++-simple-type-regexp end 't)
54 (< (abs (- end (match-end 0))) 2))
55 (goto-char (match-beginning 0))
57 (if (not (re-search-backward c++-simple-type-regexp 'nil 't))
62 (skip-chars-forward " \t\n\r")
65 (skip-chars-backward " \t\n\r" start)
69 (defun c++-get-function ()
70 "Get the last function declared or called at or after POINT.
72 ( ( DECL-START . DECL-END )
73 ( TYPE-START . TYPE-END )
74 ( NAME-START . NAME_END )
75 ( ARGLIST-START . ARGLIST-END )
76 ( FLAGS-START . FLAGS-END ) )"
78 (if (re-search-backward (concat c++-function-regexp "(") 'nil 'true)
79 (goto-char (match-end 0)))
80 (if (re-search-forward (concat c++-function-regexp "(") 'nil 't)
81 (let (type name arglist flags)
82 (setq name (cons (match-beginning 1) (match-end 1)))
83 (goto-char (1- (match-end 0)))
84 (setq arglist (cons (point) 'nil))
85 (if (condition-case nil
86 (progn (forward-list 1) t)
89 (setcdr arglist (point))
90 (if (looking-at "\\([ \t\n\r]*\\(const\\|throw[ \t\n\r]*([^();{}]*)\\|__throw__[ \t\n\t]*(([^();{}]*))\\)\\)*")
92 (setq flags (cons (match-beginning 0) (match-end 0)))
93 (goto-char (match-end 0)))
94 (setq flags (cons (cdr arglist) (cdr arglist))))
95 (if (looking-at "[ \t\n\r]*:[^;{]*")
96 (goto-char (match-end 0)))
97 (if (looking-at "[ \t\n\r]*[{;]")
99 (goto-char (car name))
100 (setq type (c++-scan-type-backward))
101 (if (not type) (setq type (cons (car name) (car name))))
102 (list (cons (car type) (cdr flags)) type name arglist flags)))))))))
104 (defun c++-get-function-defn ()
105 "Get the function defined at POINT.
107 ( ( DECL-START . DECL-END )
108 ( TYPE-START . TYPE-END )
109 ( NAME-START . NAME_END )
110 ( ARGLIST-START . ARGLIST-END )
111 ( FLAGS-START . FLAGS-END )
112 ( BODY-START . BODY-END) )"
116 (if (condition-case nil
117 (progn (up-list -1) t)
118 (error (setq fn t) nil))
120 (setq body (cons (point) (save-excursion
124 (while (condition-case nil
130 (while (re-search-backward (concat c++-function-regexp "(") end t)
131 (let ((tryfn (c++-get-function)))
134 (goto-char (cdar tryfn))
135 (if (and (looking-at "[ \t\n\r]*\\(:[^;{]*\\)?{")
136 (eq (1- (match-end 0)) (car body)))
138 (if (match-beginning 1)
139 (setcar body (match-beginning 1)))
140 (setq fn tryfn))))))))))
143 (nconc fn (list body))))))
145 (defun c++-get-classname ()
146 "Get classname which is active at POINT"
151 (if (and (condition-case nil
152 (progn (up-list -1) 't)
153 (error (setq re 'nil)))
154 (re-search-backward (concat c++-class-regexp "\\=") 'nil 't))
155 (setq class (concat (match-string 2)
160 (defun c++-get-current-class-prefix ()
161 "Get the class prefix currently active at POINT.
162 If within a class decl, returns that class name (nested classes
163 are supported). If within a function definition at global level,
164 returns the class prefix of this function. Returns 'nil if no
165 class prefix can be found"
166 (let ((x (c++-get-classname)))
169 (let ((x (or (c++-get-function-defn)
170 (c++-get-function))))
173 (goto-char (car (nth 2 x)))
174 (if (re-search-forward "\\=\\([a-zA-Z_0-9]+::\\)+")
175 (buffer-substring (match-beginning 0) (- (match-end 0) 2))
179 (defun c++-split-template-arg (arg)
180 "Split ARG, a template argument list, and return list of arg names."
181 (let ((raw-args (split-string arg "[ \t\n\r]*,[ \t\n\r]")))
182 (loop for raw-arg in raw-args
183 if (string-match "[a-zA-Z0-9_-]+$" raw-arg)
184 collect (match-string 0 raw-arg)
188 (defun c++-get-classname-with-templates ()
189 (let (classname template-args
193 (if (and (condition-case nil
194 (progn (up-list -1) 't)
195 (error (setq re 'nil)))
196 (re-search-backward (concat c++-class-regexp "\\=") nil t))
197 (let ((template-suffix "")
198 (class (match-string 2)))
199 (if (re-search-backward (concat c++-template-regexp "\\=") nil t)
200 (let* ((s (match-string 1))
201 (args (c++-split-template-arg s))
202 (raw-args (split-string s "[ \t\n\r]*,[ \t\n\r]")))
203 (setq template-suffix
204 (concat "<" (mapconcat 'identity args ",") ">"))
205 (loop for arg in raw-args
206 if (not (member arg template-args))
207 do (setq template-args
208 (nconc template-args (list arg))))))
209 (setq classname (concat class
211 (if classname "::" "")
216 (mapconcat 'identity template-args ", "))))))
218 (defun c++-get-current-class-prefix-with-templates ()
219 "Get the class prefix currently active at POINT.
220 If within a class decl, returns that class name (nested classes
221 are supported). If within a function definition at global level,
222 returns the class prefix of this function. Returns 'nil if no
223 class prefix can be found"
224 (let ((x (c++-get-classname-with-templates)))
227 (let ((x (or (c++-get-function-defn)
228 (c++-get-function))))
231 (goto-char (car (nth 2 x)))
232 (if (re-search-forward "\\=\\([a-zA-Z_0-9]+\\(<[a-zA-Z0-9_, \t\n\r]*>\\)?::\\)+")
233 (buffer-substring (match-beginning 0) (- (match-end 0) 2))
237 (defun c++-grab-inline-decl ()
238 "Grab the inline declaration at POINT and change it into a standard
239 declaration. This function deletes the declaration found at POINT and
240 places the new declaration into the top of the kill ring"
242 (let ((fn (c++-get-function-defn))
243 (class (c++-get-classname-with-templates)))
246 (kill-new (concat (if (cdr class)
247 (concat "template <" (cdr class) ">\n")
250 (buffer-substring (car (nth 0 fn)) (car (nth 2 fn)))
252 (buffer-substring (car (nth 2 fn)) (cdr (nth 5 fn)))
254 (delete-region (cdr (nth 4 fn)) (cdr (nth 5 fn)))
255 (goto-char (cdr (nth 4 fn)))
257 (delete-blank-lines))
259 (message "Not inside inline function definition body")))))
261 (defun c++-insert-class-prefix ()
262 "Insert the current class prefix at POINT.
263 See also c++-get-current-class-prefix"
265 (let ((x (c++-get-current-class-prefix-with-templates)))
268 (message "Not in scope of any class"))))
270 (defun c++-next-user-symbol ()
271 "Move POINT to next non-keyword symbol."
274 (if (looking-at "[a-zA-Z_:]+")
275 (setq pos (re-search-forward "[a-zA-Z_:]+" 'nil 't)))
276 (while (and (setq pos (re-search-forward "[a-zA-Z_:]*[a-zA-Z_]" 'nil 't))
277 (or (member (match-string 0) c++-keywords)
281 (defun c++-previous-user-symbol ()
282 "Move POINT to previous non-keyword symbol."
284 (while (and (re-search-backward "[a-zA-Z_]" 'nil 't)
285 (progn (skip-chars-backward "a-zA-Z_:")
286 (or (member (buffer-substring (point) (match-end 0))
290 (defun c++-next-function-call ()
291 "Move POINT to next function call"
293 (let ((start (point))
295 (while (and (setq fn (c++-get-function))
296 (or (>= start (car (nth 0 fn)))
297 (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn)))
298 c++-function-keywords)
299 (/= (car (nth 1 fn)) (car (nth 2 fn)))))
300 (goto-char (cdr (nth 0 fn)))
301 (re-search-forward "{;" 'nil 't))
302 (goto-char (if fn (car (nth 0 fn)) start))))
304 (defun c++-next-function-definition ()
305 "Move POINT to the next function definition or declaration"
307 (let ((start (point))
309 (while (and (setq fn (c++-get-function))
310 (or (>= start (car (nth 0 fn)))
311 (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn)))
312 c++-function-keywords)
313 (= (car (nth 1 fn)) (car (nth 2 fn)))))
314 (goto-char (cdr (nth 0 fn)))
315 (re-search-forward "[{;]" 'nil 't))
316 (goto-char (if fn (car (nth 0 fn)) start))))
318 (defun c++-smart-yank ()
319 "Yank-pop top of kill ring and reformat the yanked object."
322 (let ((text (current-kill 0))
326 (setq end-mark (point-marker)))
327 (while (< (point) (marker-position end-mark))
330 (setq line-start (point))
332 (if (> (current-column) c++-smart-wrap-column)
334 (move-to-column c++-smart-wrap-column)
335 (if (search-backward ",")