blob: b6c3ed4c686b76961f0554d65f46a7b86b3dc33d [file] [log] [blame]
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +00001;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>. -*- lexical-binding: t; -*-
Kirill Bobyrevaa484502016-08-02 08:51:26 +00002
3;; Keywords: tools, c
4
5;;; Commentary:
6
7;; To install clang-rename.el make sure the directory of this file is in your
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +00008;; `load-path' and add
Kirill Bobyrevaa484502016-08-02 08:51:26 +00009;;
10;; (require 'clang-rename)
11;;
12;; to your .emacs configuration.
13
14;;; Code:
15
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000016(defgroup clang-rename nil
17 "Integration with clang-rename"
18 :group 'c)
19
Kirill Bobyrevaa484502016-08-02 08:51:26 +000020(defcustom clang-rename-binary "clang-rename"
21 "Path to clang-rename executable."
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000022 :type '(file :must-match t)
23 :group 'clang-rename)
Kirill Bobyrevaa484502016-08-02 08:51:26 +000024
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000025;;;###autoload
Kirill Bobyrevaa484502016-08-02 08:51:26 +000026(defun clang-rename (new-name)
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000027 "Rename all instances of the symbol at point to NEW-NAME using clang-rename."
Kirill Bobyrevaa484502016-08-02 08:51:26 +000028 (interactive "sEnter a new name: ")
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000029 (save-some-buffers :all)
30 ;; clang-rename should not be combined with other operations when undoing.
31 (undo-boundary)
32 (let ((output-buffer (get-buffer-create "*clang-rename*")))
33 (with-current-buffer output-buffer (erase-buffer))
34 (let ((exit-code (call-process
35 clang-rename-binary nil output-buffer nil
36 (format "-offset=%d"
37 ;; clang-rename wants file (byte) offsets, not
38 ;; buffer (character) positions.
39 (clang-rename--bufferpos-to-filepos
40 ;; Emacs treats one character after a symbol as
41 ;; part of the symbol, but clang-rename doesn’t.
42 ;; Use the beginning of the current symbol, if
43 ;; available, to resolve the inconsistency.
44 (or (car (bounds-of-thing-at-point 'symbol))
45 (point))
46 'exact))
47 (format "-new-name=%s" new-name)
48 "-i" (buffer-file-name))))
49 (if (and (integerp exit-code) (zerop exit-code))
50 ;; Success; revert current buffer so it gets the modifications.
51 (progn
52 (kill-buffer output-buffer)
53 (revert-buffer :ignore-auto :noconfirm :preserve-modes))
54 ;; Failure; append exit code to output buffer and display it.
Manuel Klimek750f6a72016-10-11 09:15:10 +000055 (let ((message (clang-rename--format-message
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000056 "clang-rename failed with %s %s"
57 (if (integerp exit-code) "exit status" "signal")
58 exit-code)))
59 (with-current-buffer output-buffer
60 (insert ?\n message ?\n))
61 (message "%s" message)
62 (display-buffer output-buffer))))))
Kirill Bobyrevaa484502016-08-02 08:51:26 +000063
Kirill Bobyrevbbce7e22016-10-02 14:51:33 +000064(defalias 'clang-rename--bufferpos-to-filepos
65 (if (fboundp 'bufferpos-to-filepos)
66 'bufferpos-to-filepos
67 ;; Emacs 24 doesn’t have ‘bufferpos-to-filepos’, simulate it using
68 ;; ‘position-bytes’.
69 (lambda (position &optional _quality _coding-system)
70 (1- (position-bytes position)))))
Kirill Bobyrevaa484502016-08-02 08:51:26 +000071
Manuel Klimek750f6a72016-10-11 09:15:10 +000072;; ‘format-message’ is new in Emacs 25.1. Provide a fallback for older
73;; versions.
74(defalias 'clang-rename--format-message
75 (if (fboundp 'format-message) 'format-message 'format))
76
Kirill Bobyrevaa484502016-08-02 08:51:26 +000077(provide 'clang-rename)
78
79;;; clang-rename.el ends here