uncrustify-mode.el (5449B)
1 ;;; uncrustify-mode.el --- Minor mode to automatically uncrustify. 2 3 ;; Copyright (C) 2012 tabi 4 ;; Author: Tabito Ohtani <koko1000ban@gmail.com> 5 ;; Version: 0.01 6 ;; Keywords: uncrustify 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 ;;; Installation: 22 23 ;; drop requirements and this file into a directory in your `load-path', 24 ;; and put these lines into your .emacs file. 25 26 ;; (require 'uncrustify-mode) 27 ;; (add-hook 'c-mode-common-hook 28 ;; '(lambda () 29 ;; (uncrustify-mode 1))) 30 31 ;;; ChangeLog: 32 ;; * 0.0.1: 33 ;; Initial version. 34 35 36 ;; case 37 (eval-when-compile 38 (require 'cl)) 39 40 ;;; Variables: 41 42 (defcustom uncrustify-config-path 43 "~/.uncrustify.cfg" 44 "uncrustify config file path" 45 :group 'uncrustify 46 :type 'file) 47 (make-variable-buffer-local 'uncrustify-config-path) 48 49 (defcustom uncrustify-bin 50 "uncrustify -q" 51 "The command to run uncrustify." 52 :group 'uncrustify) 53 54 ;;; Functions: 55 56 (defun uncrustify-get-lang-from-mode (&optional mode) 57 "uncrustify lang option" 58 (let ((m (or mode major-mode))) 59 (case m 60 ('c-mode "C") 61 ('c++-mode "CPP") 62 ('d-mode "D") 63 ('java-mode "JAVA") 64 ('objc-mode "OC") 65 (t 66 nil)))) 67 68 (defun uncrustify-point->line (point) 69 "Get the line number that POINT is on." 70 ;; I'm not bothering to use save-excursion because I think I'm 71 ;; calling this function from inside other things that are likely to 72 ;; use that and all I really need to do is restore my current 73 ;; point. So that's what I'm doing manually. 74 (let ((line 1) 75 (original-point (point))) 76 (goto-char (point-min)) 77 (while (< (point) point) 78 (incf line) 79 (forward-line)) 80 (goto-char original-point) 81 line)) 82 83 (defun uncrustify-invoke-command (lang start-in end-in) 84 "Run uncrustify on the current region or buffer." 85 (if lang 86 (let ((start (or start-in (point-min))) 87 (end (or end-in (point-max))) 88 (original-line (uncrustify-point->line (point))) 89 (cmd (concat uncrustify-bin " -c " uncrustify-config-path " -l " lang)) 90 (out-buf (get-buffer-create "*uncrustify-out*")) 91 (error-buf (get-buffer-create "*uncrustify-errors*"))) 92 93 (with-current-buffer error-buf (erase-buffer)) 94 (with-current-buffer out-buf (erase-buffer)) 95 96 ;; Inexplicably, save-excursion doesn't work to restore the 97 ;; point. I'm using it to restore the mark and point and manually 98 ;; navigating to the proper new-line. 99 (let ((result 100 (save-excursion 101 (let ((ret (shell-command-on-region start end cmd t t error-buf nil))) 102 (if (and 103 (numberp ret) 104 (zerop ret)) 105 ;; Success! Clean up. 106 (progn 107 (message "Success! uncrustify modify buffer.") 108 (kill-buffer error-buf) 109 t) 110 ;; Oops! Show our error and give back the text that 111 ;; shell-command-on-region stole. 112 (progn (undo) 113 (with-current-buffer error-buf 114 (message "uncrustify error: <%s> <%s>" ret (buffer-string))) 115 nil)))))) 116 117 ;; This goto-line is outside the save-excursion because it'd get 118 ;; removed otherwise. I hate this bug. It makes things so ugly. 119 (goto-line original-line) 120 (not result))) 121 (message "uncrustify not support this mode : %s" major-mode))) 122 123 (defun uncrustify () 124 (interactive) 125 (save-restriction 126 (widen) 127 (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (region-beginning) (region-end)))) 128 129 (defun uncrustify-buffer () 130 (interactive) 131 (save-restriction 132 (widen) 133 (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max)))) 134 135 ;;; mode 136 137 (defun uncrustify-write-hook () 138 "Uncrustifys a buffer during `write-file-hooks' for `uncrustify-mode'. 139 if uncrustify returns not nil then the buffer isn't saved." 140 (if uncrustify-mode 141 (save-restriction 142 (widen) 143 (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max))))) 144 145 ;;;###autoload 146 (define-minor-mode uncrustify-mode 147 "Automatically `uncrustify' when saving." 148 :lighter " Uncrustify" 149 (if (not (uncrustify-get-lang-from-mode)) 150 (message "uncrustify not support this mode : %s" major-mode) 151 (if (version<= "24" emacs-version) 152 (if uncrustify-mode 153 (add-hook 'write-file-hooks 'uncrustify-write-hook nil t) 154 (remove-hook 'uncrustify-write-hook t)) 155 (make-local-hook 'write-file-hooks) 156 (funcall (if uncrustify-mode #'add-hook #'remove-hook) 157 'write-file-hooks 'uncrustify-write-hook)))) 158 159 (provide 'uncrustify-mode) 160 161 ;;; uncrustify-mode.el ends here