Index: clang-rename/tool/clang-rename.el =================================================================== --- clang-rename/tool/clang-rename.el +++ clang-rename/tool/clang-rename.el @@ -1,11 +1,11 @@ -;;; clang-rename.el --- Renames every occurrence of a symbol found at . +;;; clang-rename.el --- Renames every occurrence of a symbol found at . -*- lexical-binding: t; -*- ;; Keywords: tools, c ;;; Commentary: ;; To install clang-rename.el make sure the directory of this file is in your -;; 'load-path' and add +;; `load-path' and add ;; ;; (require 'clang-rename) ;; @@ -13,31 +13,61 @@ ;;; Code: +(defgroup clang-rename nil + "Integration with clang-rename" + :group 'c) + (defcustom clang-rename-binary "clang-rename" "Path to clang-rename executable." - :type 'hook - :options '(turn-on-auto-fill flyspell-mode) - :group 'wp) + :type '(file :must-match t) + :group 'clang-rename) +;;;###autoload (defun clang-rename (new-name) - "Rename all instances of the symbol at the point using clang-rename" + "Rename all instances of the symbol at point to NEW-NAME using clang-rename." (interactive "sEnter a new name: ") - (let (;; Emacs offset is 1-based. - (offset (- (point) 1)) - (orig-buf (current-buffer)) - (file-name (buffer-file-name))) - - (let ((rename-command - (format "bash -f -c '%s -offset=%s -new-name=%s -i %s'" - clang-rename-binary offset new-name file-name))) - (message (format "Running clang-rename command %s" rename-command)) - ;; Run clang-rename via bash. - (shell-command rename-command) - ;; Reload buffer. - (revert-buffer t t) - ) - ) -) + (save-some-buffers :all) + ;; clang-rename should not be combined with other operations when undoing. + (undo-boundary) + (let ((output-buffer (get-buffer-create "*clang-rename*"))) + (with-current-buffer output-buffer (erase-buffer)) + (let ((exit-code (call-process + clang-rename-binary nil output-buffer nil + (format "-offset=%d" + ;; clang-rename wants file (byte) offsets, not + ;; buffer (character) positions. + (clang-rename--bufferpos-to-filepos + ;; Emacs treats one character after a symbol as + ;; part of the symbol, but clang-rename doesn’t. + ;; Use the beginning of the current symbol, if + ;; available, to resolve the inconsistency. + (or (car (bounds-of-thing-at-point 'symbol)) + (point)) + 'exact)) + (format "-new-name=%s" new-name) + "-i" (buffer-file-name)))) + (if (and (integerp exit-code) (zerop exit-code)) + ;; Success; revert current buffer so it gets the modifications. + (progn + (kill-buffer output-buffer) + (revert-buffer :ignore-auto :noconfirm :preserve-modes)) + ;; Failure; append exit code to output buffer and display it. + (let ((message (format-message + "clang-rename failed with %s %s" + (if (integerp exit-code) "exit status" "signal") + exit-code))) + (with-current-buffer output-buffer + (insert ?\n message ?\n)) + (message "%s" message) + (display-buffer output-buffer)))))) + +(defalias 'clang-rename--bufferpos-to-filepos + (if (fboundp 'bufferpos-to-filepos) + 'bufferpos-to-filepos + ;; Emacs 24 doesn’t have ‘bufferpos-to-filepos’, simulate it using + ;; ‘position-bytes’. + (lambda (position &optional _quality _coding-system) + (1- (position-bytes position))))) (provide 'clang-rename)