(defvar ccide-new-file-hook nil)
+(defvar ccide-new-file-command nil)
+
+(defvar ccide-clang-format-command nil)
+
+(defvar ccide-uncrustify-command "uncrustify")
+(defvar ccide-uncrustify-config nil)
+(defvar ccide-auto-format-tag nil)
+
(defconst c-user-prefix-re (regexp-opt c-user-prefixes t))
(defconst ccide-doxy-tag-re
;; file level
("fc" ccide-file-comment "File comment")
("fs" ccide-syncronize-includes "Sync includes")
+ ("ff" ccide-clang-format-buffer "Reformat buffer")
(nil nil separator)
;; class level
("csm" ccide-set-class-defaults-my "Set class defaults comment" "My")
("cS" ccide-gen-struct-constructors "Generate structure constructors")
+ ("c<" ccide-gen-struct-compare "Generate structure compare operators")
("ci" ccide-class-impl-comment "Generate class implemenation comment")
(nil nil separator)
;; documentation
- ("h" ccide-hide-all-doxy-comments "Hide all Doxygen comments")
- ("s" ccide-show-all-comments "Show all Doxygen comments")
+ ("h" ccide-hide-all-doxy-comments "Hide all Doxygen comments")
+ ("s" ccide-show-all-comments "Show all Doxygen comments")
+
+ ;; cython
+ ("yp" ccide-grab-pxd-fn "Generate pxd function/method decl")
; ;; CORBA
; ("Cg" ccide-gen-corba-impl "Generate CORBA impl")
(while (re-search-forward
(concat "^\\(//\\)?#\\s-*include \""
(regexp-quote (car include))
- "\"\\s-*$")
+ "\"\\s-*")
nil t)
(goto-char (match-beginning 0))
(if (looking-at "//")
(defun ccide-auto-decorate-new-files ()
(if (and (buffer-file-name) (= (point-min) (point-max)))
- (let ((status (buffer-modified-p)))
- (ccide-file-comment)
- (set-buffer-modified-p status))))
+ (if (or (not ccide-new-file-command)
+ (not (progn
+ (save-buffer)
+ (condition-case nil
+ (progn
+ (shell-command (format "%s %s" ccide-new-file-command (buffer-file-name)))
+ (revert-buffer t t t)
+ t)
+ (error nil nil)))))
+ (let ((status (buffer-modified-p)))
+ (ccide-file-comment)
+ (set-buffer-modified-p status)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; class level
(ccide-build-class-defaults-f disabled)
(defun ccide-gen-struct-constructors ()
+ (interactive)
(save-excursion
(beginning-of-line)
(open-line 1)
(in (make-string (current-indentation) ? ))
(inin (make-string (+ (current-indentation) c-basic-offset) ? )))
(insert name "()\n" inin ": ")
- (indent-according-to-mode)
(loop for var in variables
for first = t then nil
if (not first) do (insert ", ")
- do (insert (car var) "()"))
- (insert "\n" in "{}\n"
+ do (insert (car var) " ()"))
+ (insert " {}\n\n"
in name "(")
(loop for var in variables
for first = t then nil
(loop for var in variables
for first = t then nil
if (not first) do (insert ", ")
- do (insert (car var) "(" (car var) "_)"))
- (insert "\n" in "{}"))))
+ do (insert (car var) " (" (car var) "_)"))
+ (insert " {}"))))
+
+
+(defun ccide-gen-struct-compare ()
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (open-line 1)
+ (indent-according-to-mode)
+ (let* ((scope (c-get-block-scope))
+ (class (c-parse-class scope))
+ (variables (c-get-variable-members-with-type class))
+ (name (c-scope-name (aref (car (last scope)) 1)))
+ (in (make-string (current-indentation) ? ))
+ (inin (make-string (+ (current-indentation) c-basic-offset) ? )))
+
+ (insert "bool operator<(" name " const & other) const\n"
+ in "{ return\n")
+ (loop for ((varName . varType) . tail) on variables
+ do (insert inin varName " < other." varName " ? true :")
+ do (if tail
+ (insert "\n" inin "other." varName " < " varName " ? false :\n")
+ (insert " false; }\n\n")))
+ (insert in "bool operator==(" name " const & other) const\n"
+ in "{ return\n")
+ (loop for ((varName . varType) . tail) on variables
+ do (insert inin varName " == other." varName)
+ do (if tail (insert " &&\n") (insert "; }\n\n")))
+ (insert in "std::size_type hash_value() const\n"
+ in "{ std::size_t current (0);\n")
+ (loop for ((varName . varType) . tail) on variables
+ do (insert inin "boost::hash_combine(current, " varName ");\n"))
+ (insert inin "return current; }\n\n")
+ (insert in "void write(std::ostream & os) const\n"
+ in "{ os << \"{ \"")
+ (loop for ((varName . varType) . tail) on variables
+ do (insert "\n" inin "<< " varName)
+ do (if tail (insert " << ' '")))
+ (insert " << \" }\"; }\n"))))
(defun ccide-class-impl-comment ()
"Get implementation comment for current class"
(provide 'cc-ide)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; cython support
+
+(defun ccide-grab-pxd-fn ()
+ (interactive)
+ (save-excursion
+ (c-beginning-of-defun-or-decl)
+ (let ((defn (c-build-pxd)))
+ (kill-new (cadr defn))
+ (message (concat (car defn))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; other stuff
(defun ccide-open-compilation-frame ()
(auto-fill-mode -1)
(ccide-project-load-config)
(ccide-directory-load-config)
- (ccide-auto-decorate-new-files))
+ (ccide-auto-decorate-new-files)
+ (if ccide-clang-format-command
+ (add-hook 'write-contents-functions 'ccide-clang-format-buffer nil t))
+ (if ccide-uncrustify-config
+ (add-hook 'write-contents-functions 'ccide-uncrustify-format-buffer nil t)))
+
+(defun ccide-match-auto-format-tag ()
+ (or (not ccide-auto-format-tag)
+ (and (save-excursion
+ (goto-char (point-min))
+ (search-forward ccide-auto-format-tag
+ (save-excursion (forward-line 4) (point))
+ t)) t)))
+
+(require 'xmltok)
+
+(defun clang-format-xmltok-attribute (name)
+ (loop for attribute in xmltok-attributes
+ if (string= (buffer-substring-no-properties (xmltok-attribute-name-start attribute)
+ (xmltok-attribute-name-end attribute))
+ name)
+ return (buffer-substring-no-properties (xmltok-attribute-value-start attribute)
+ (xmltok-attribute-value-end attribute))))
+
+(defun clang-format-parse-replacement-text ()
+ (cond ((eq tok 'char-ref)
+ (let ((number-start (+ xmltok-start 2))
+ (number-end (1- (point))))
+ (if (not (string= (buffer-substring-no-properties xmltok-start number-start)
+ "&#"))
+ (error "invalid character reference"))
+ (char-to-string (string-to-number (buffer-substring-no-properties number-start
+ number-end)))))
+
+ (t
+ (buffer-substring-no-properties xmltok-start (point)))))
+
+(defun clang-format-parse-replacement ()
+ (let ((offset (string-to-number (clang-format-xmltok-attribute "offset")))
+ (length (string-to-number (clang-format-xmltok-attribute "length"))))
+ (list offset
+ length
+ (loop for tok = (xmltok-forward)
+ while (not (eq tok 'end-tag))
+ concat (clang-format-parse-replacement-text)))))
+
+(defun clang-format-parse-header ()
+ (let ((incflag (clang-format-xmltok-attribute "incomplete_format")))
+ (if (string= incflag "true")
+ (warn "clang-format: C++ syntax error in file"))))
+
+(defun clang-format-parse-replacements (buffer)
+ (save-excursion
+ (set-buffer buffer)
+ (goto-char (point-min))
+ (xmltok-forward-prolog)
+ (loop for tok = (xmltok-forward)
+ while tok
+ for n = (buffer-substring-no-properties (1+ xmltok-start) xmltok-name-end)
+ if (and (eq tok 'start-tag)
+ (string= n "replacement")) collect (clang-format-parse-replacement)
+ else if (and (eq tok ' start-tag)
+ (string= n "replacements")) do (clang-format-parse-header))))
+
+(defun clang-format-apply-replacements (replacements)
+ (loop for (offset length replacement) in (nreverse replacements)
+ do (progn
+ (goto-char (1+ offset))
+ (delete-char length)
+ (insert replacement))))
+
+(defun ccide-clang-format-buffer ()
+ (interactive)
+ (if (and ccide-clang-format-command (ccide-match-auto-format-tag))
+ (let ((replacementsBuffer (get-buffer-create " *clang-format-replacements*")))
+ (save-excursion (set-buffer replacementsBuffer) (erase-buffer))
+ (shell-command-on-region (point-min) (point-max) ccide-clang-format-command
+ replacementsBuffer nil)
+ (let ((replacements (clang-format-parse-replacements replacementsBuffer)))
+ (save-excursion
+ (clang-format-apply-replacements replacements)))))
+ nil)
-(defun ccide-project-load-config ()
- (if (buffer-file-name)
- (let ((conf (ccide-project-search-upwards '(".project.el" "project.el")
- (file-name-directory (buffer-file-name)))))
+(defun ccide-parse-ed-diff (buffer)
+ ;; an ed-diff already has the replacements in reverse order
+ (save-excursion
+ (set-buffer buffer)
+ (goto-char (point-min))
+ (loop while (= (forward-line 1) 0)
+ if (looking-at "Unmatched")
+ do (error (buffer-substring-no-properties (point) (progn (end-of-line) (point))))
+ for b = (point)
+ for e = (save-excursion (end-of-line) (point))
+ for k = (search-forward "," e t)
+ for m = (buffer-substring-no-properties (1- e) e)
+ for rb = (when (not (equal m "d"))
+ (forward-line 1) (point))
+ for re = (when (not (equal m "d"))
+ (while (and (not (looking-at "\\.$")) (= (forward-line 1) 0))) (point))
+ for bl = (string-to-number (buffer-substring-no-properties b (1- (or k e))))
+ for el = (string-to-number (buffer-substring-no-properties (or k b) (1- e)))
+ collect (list (if (equal m "a") (1+ bl) bl)
+ (1+ el)
+ (if (not (equal m "d"))
+ (buffer-substring-no-properties rb re)
+ "")))))
+
+(defun ccide-apply-ed-diff (replacements)
+ (loop for (first last replacement) in replacements
+ do (progn
+ (goto-line first)
+ (delete-region (point) (progn (goto-line last) (point)))
+ (insert replacement))))
+
+(defun ccide-uncrustify-format-buffer ()
+ (interactive)
+ (if (and ccide-uncrustify-config (ccide-match-auto-format-tag))
+ (let ((tempFile (make-temp-file "ccideuncrustify"))
+ (diffBuffer (get-buffer-create " *uncrustify-format-diff*")))
+ (unwind-protect
+ (progn
+ (write-region (point-min) (point-max) tempFile)
+ (shell-command (concat (shell-quote-argument ccide-uncrustify-command)
+ " -c " (shell-quote-argument
+ (expand-file-name ccide-uncrustify-config))
+ " -l CPP -f " (shell-quote-argument tempFile)
+ " | diff -e " (shell-quote-argument tempFile) " -")
+ diffBuffer nil))
+ (delete-file tempFile))
+ (let ((replacements (ccide-parse-ed-diff diffBuffer)))
+ (save-excursion
+ (ccide-apply-ed-diff replacements))))
+ nil))
+
+(defun ccide-project-load-config (&optional force)
+ (if (or force (buffer-file-name))
+ (let ((conf (ccide-project-search-upwards '(".project.el" "project.el") default-directory)))
(when conf
(set (make-local-variable 'ccide-project-root) (file-name-directory conf))
(load-file conf)))))
(if (> (- (point-max) pos) (point))
(goto-char (- (point-max) pos))))))))
-
\f
;;; Local Variables:
;;; elisp-project-autoload-file-name: "cc-autoload.el"