From: g0dil Date: Thu, 12 Oct 2006 07:51:22 +0000 (+0000) Subject: Added missing c++.el X-Git-Url: http://g0dil.de/git?p=emacsstuff.git;a=commitdiff_plain;h=5f46aa1c07fe8b06f2b70c4714c2561644bc9572 Added missing c++.el --- diff --git a/cc-ide/c++.el b/cc-ide/c++.el new file mode 100644 index 0000000..bda95c9 --- /dev/null +++ b/cc-ide/c++.el @@ -0,0 +1,341 @@ +; Problem with this RE: a) If the line before the function declaration +; is a preprocessor directive (like a #define) ending in one or more +; c++ type keywords they will get included into the type spec. b) if +; you define a symbol like #define _const const the expression won't +; work at all + +; Another possible regexp for c++-simple-type-regexp is "^.+". This +; will make any text before the name of the function but in the same +; line be the type of the function. Problem: Type cannot span multiple +; lines. + +(defvar c++-prefixes '("__inline__" "static")) + +(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]*" + "*The RE for a simple type in C++ that is types that neither involve + blocks nor functions") + +(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]*" + "The RE for a function definition or declaration") + +(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]*" + "The RE for a class declaration") + +(defconst c++-template-regexp "template[ \t\n\r]*<\\([^>]*\\)>[ \t\n\r]*" + "The RE for matching template clauses.") + +(defconst c++-function-keywords + '( "if" "while" "for" "repeat" "class" "struct" "union" "switch" ) + "C++ Keywords which may introduce a block") + +(defconst c++-keywords + '( "if" "while" "for" "repeat" "class" "struct" "union" "typedef" + "char" "int" "float" "double" "signed" "unsigned" "long" "const" + "switch" "case" "repeat" "until" "do" "class" "public" + "protected" "private" "friend" "operator" "void" "static" "explicit" ) + "C++ keywords") + +(defvar c++-smart-wrap-column 80) + +(require 'cc-cmds) +(require 'cc-engine) + +(defun c++-scan-type-backward () + "Scans backward to find the longest valid simple type ending at POINT. +Assumes POINT is at the end of a C++ simple type expression. +Leaves POINT at the beginning of the type expression and returns + ( TYPE-START . TYPE-END )" + (save-excursion + (let ((end (point)) + start) + (re-search-backward c++-simple-type-regexp 'nil 't) + (catch 'exit + (while (and (re-search-forward c++-simple-type-regexp end 't) + (< (abs (- end (match-end 0))) 2)) + (goto-char (match-beginning 0)) + (setq start (point)) + (if (not (re-search-backward c++-simple-type-regexp 'nil 't)) + (throw 'exit)))) + (if start + (progn + (goto-char start) + (skip-chars-forward " \t\n\r") + (setq start (point)) + (goto-char end) + (skip-chars-backward " \t\n\r" start) + (cons start (point))) + 'nil )))) + +(defun c++-get-function () + "Get the last function declared or called at or after POINT. +Returns a list + ( ( DECL-START . DECL-END ) + ( TYPE-START . TYPE-END ) + ( NAME-START . NAME_END ) + ( ARGLIST-START . ARGLIST-END ) + ( FLAGS-START . FLAGS-END ) )" + (save-excursion + (if (re-search-backward (concat c++-function-regexp "(") 'nil 'true) + (goto-char (match-end 0))) + (if (re-search-forward (concat c++-function-regexp "(") 'nil 't) + (let (type name arglist flags) + (setq name (cons (match-beginning 1) (match-end 1))) + (goto-char (1- (match-end 0))) + (setq arglist (cons (point) 'nil)) + (if (condition-case nil + (progn (forward-list 1) t) + (scan-error nil)) + (progn + (setcdr arglist (point)) + (if (looking-at "\\([ \t\n\r]*\\(const\\|throw[ \t\n\r]*([^();{}]*)\\|__throw__[ \t\n\t]*(([^();{}]*))\\)\\)*") + (progn + (setq flags (cons (match-beginning 0) (match-end 0))) + (goto-char (match-end 0))) + (setq flags (cons (cdr arglist) (cdr arglist)))) + (if (looking-at "[ \t\n\r]*:[^;{]*") + (goto-char (match-end 0))) + (if (looking-at "[ \t\n\r]*[{;]") + (progn + (goto-char (car name)) + (setq type (c++-scan-type-backward)) + (if (not type) (setq type (cons (car name) (car name)))) + (list (cons (car type) (cdr flags)) type name arglist flags))))))))) + +(defun c++-get-function-defn () + "Get the function defined at POINT. +Returns a list + ( ( DECL-START . DECL-END ) + ( TYPE-START . TYPE-END ) + ( NAME-START . NAME_END ) + ( ARGLIST-START . ARGLIST-END ) + ( FLAGS-START . FLAGS-END ) + ( BODY-START . BODY-END) )" + (save-excursion + (let (body fn end) + (while (not fn) + (if (condition-case nil + (progn (up-list -1) t) + (error (setq fn t) nil)) + (save-excursion + (setq body (cons (point) (save-excursion + (forward-list 1) + (point)))) + (save-excursion + (while (condition-case nil + (progn + (up-list -1) + (setq end (point)) + t) + (scan-error nil)))) + (while (re-search-backward (concat c++-function-regexp "(") end t) + (let ((tryfn (c++-get-function))) + (if tryfn + (save-excursion + (goto-char (cdar tryfn)) + (if (and (looking-at "[ \t\n\r]*\\(:[^;{]*\\)?{") + (eq (1- (match-end 0)) (car body))) + (progn + (if (match-beginning 1) + (setcar body (match-beginning 1))) + (setq fn tryfn)))))))))) + (if (eq fn t) + nil + (nconc fn (list body)))))) + +(defun c++-get-classname () + "Get classname which is active at POINT" + (let (class + (re 't)) + (save-excursion + (while re + (if (and (condition-case nil + (progn (up-list -1) 't) + (error (setq re 'nil))) + (re-search-backward (concat c++-class-regexp "\\=") 'nil 't)) + (setq class (concat (match-string 2) + (if class "::" "") + class ))))) + class)) + +(defun c++-get-current-class-prefix () + "Get the class prefix currently active at POINT. +If within a class decl, returns that class name (nested classes +are supported). If within a function definition at global level, +returns the class prefix of this function. Returns 'nil if no +class prefix can be found" + (let ((x (c++-get-classname))) + (if x + x + (let ((x (or (c++-get-function-defn) + (c++-get-function)))) + (if x + (save-excursion + (goto-char (car (nth 2 x))) + (if (re-search-forward "\\=\\([a-zA-Z_0-9]+::\\)+") + (buffer-substring (match-beginning 0) (- (match-end 0) 2)) + 'nil)) + 'nil))))) + +(defun c++-split-template-arg (arg) + "Split ARG, a template argument list, and return list of arg names." + (let ((raw-args (split-string arg "[ \t\n\r]*,[ \t\n\r]"))) + (loop for raw-arg in raw-args + if (string-match "[a-zA-Z0-9_-]+$" raw-arg) + collect (match-string 0 raw-arg) + else + collect raw-arg))) + +(defun c++-get-classname-with-templates () + (let (classname template-args + (re 't)) + (save-excursion + (while re + (if (and (condition-case nil + (progn (up-list -1) 't) + (error (setq re 'nil))) + (re-search-backward (concat c++-class-regexp "\\=") nil t)) + (let ((template-suffix "") + (class (match-string 2))) + (if (re-search-backward (concat c++-template-regexp "\\=") nil t) + (let* ((s (match-string 1)) + (args (c++-split-template-arg s)) + (raw-args (split-string s "[ \t\n\r]*,[ \t\n\r]"))) + (setq template-suffix + (concat "<" (mapconcat 'identity args ",") ">")) + (loop for arg in raw-args + if (not (member arg template-args)) + do (setq template-args + (nconc template-args (list arg)))))) + (setq classname (concat class + template-suffix + (if classname "::" "") + classname)))))) + (and classname + (cons classname + (and template-args + (mapconcat 'identity template-args ", ")))))) + +(defun c++-get-current-class-prefix-with-templates () + "Get the class prefix currently active at POINT. +If within a class decl, returns that class name (nested classes +are supported). If within a function definition at global level, +returns the class prefix of this function. Returns 'nil if no +class prefix can be found" + (let ((x (c++-get-classname-with-templates))) + (if x + (car x) + (let ((x (or (c++-get-function-defn) + (c++-get-function)))) + (if x + (save-excursion + (goto-char (car (nth 2 x))) + (if (re-search-forward "\\=\\([a-zA-Z_0-9]+\\(<[a-zA-Z0-9_, \t\n\r]*>\\)?::\\)+") + (buffer-substring (match-beginning 0) (- (match-end 0) 2)) + 'nil)) + 'nil))))) + +(defun c++-grab-inline-decl () + "Grab the inline declaration at POINT and change it into a standard +declaration. This function deletes the declaration found at POINT and +places the new declaration into the top of the kill ring" + (interactive) + (let ((fn (c++-get-function-defn)) + (class (c++-get-classname-with-templates))) + (if (and fn class) + (progn + (kill-new (concat (if (cdr class) + (concat "template <" (cdr class) ">\n") + "") + "inline " + (buffer-substring (car (nth 0 fn)) (car (nth 2 fn))) + (car class) "::" + (buffer-substring (car (nth 2 fn)) (cdr (nth 5 fn))) + "\n")) + (delete-region (cdr (nth 4 fn)) (cdr (nth 5 fn))) + (goto-char (cdr (nth 4 fn))) + (insert ";") + (delete-blank-lines)) + (if (interactive-p) + (message "Not inside inline function definition body"))))) + +(defun c++-insert-class-prefix () + "Insert the current class prefix at POINT. +See also c++-get-current-class-prefix" + (interactive) + (let ((x (c++-get-current-class-prefix-with-templates))) + (if x + (insert x "::") + (message "Not in scope of any class")))) + +(defun c++-next-user-symbol () + "Move POINT to next non-keyword symbol." + (interactive) + (let (pos) + (if (looking-at "[a-zA-Z_:]+") + (setq pos (re-search-forward "[a-zA-Z_:]+" 'nil 't))) + (while (and (setq pos (re-search-forward "[a-zA-Z_:]*[a-zA-Z_]" 'nil 't)) + (or (member (match-string 0) c++-keywords) + (c-in-literal)))) + (goto-char pos))) + +(defun c++-previous-user-symbol () + "Move POINT to previous non-keyword symbol." + (interactive) + (while (and (re-search-backward "[a-zA-Z_]" 'nil 't) + (progn (skip-chars-backward "a-zA-Z_:") + (or (member (buffer-substring (point) (match-end 0)) + c++-keywords) + (c-in-literal)))))) + +(defun c++-next-function-call () + "Move POINT to next function call" + (interactive) + (let ((start (point)) + fn) + (while (and (setq fn (c++-get-function)) + (or (>= start (car (nth 0 fn))) + (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn))) + c++-function-keywords) + (/= (car (nth 1 fn)) (car (nth 2 fn))))) + (goto-char (cdr (nth 0 fn))) + (re-search-forward "{;" 'nil 't)) + (goto-char (if fn (car (nth 0 fn)) start)))) + +(defun c++-next-function-definition () + "Move POINT to the next function definition or declaration" + (interactive) + (let ((start (point)) + fn) + (while (and (setq fn (c++-get-function)) + (or (>= start (car (nth 0 fn))) + (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn))) + c++-function-keywords) + (= (car (nth 1 fn)) (car (nth 2 fn))))) + (goto-char (cdr (nth 0 fn))) + (re-search-forward "[{;]" 'nil 't)) + (goto-char (if fn (car (nth 0 fn)) start)))) + +(defun c++-smart-yank () + "Yank-pop top of kill ring and reformat the yanked object." + (interactive) + (push-mark) + (let ((text (current-kill 0)) + end-mark line-start) + (save-excursion + (insert text) + (setq end-mark (point-marker))) + (while (< (point) (marker-position end-mark)) + (beginning-of-line) + (c-indent-command) + (setq line-start (point)) + (end-of-line) + (if (> (current-column) c++-smart-wrap-column) + (progn + (move-to-column c++-smart-wrap-column) + (if (search-backward ",") + (progn + (forward-char 1) + (open-line 1))))) + (forward-line 1)))) + +(provide 'c++)