xref: /openbsd-src/gnu/llvm/clang/tools/clang-rename/clang-rename.el (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick;;; clang-rename.el --- Renames every occurrence of a symbol found at <offset>.  -*- lexical-binding: t; -*-
2*e5dd7070Spatrick
3*e5dd7070Spatrick;; Keywords: tools, c
4*e5dd7070Spatrick
5*e5dd7070Spatrick;;; Commentary:
6*e5dd7070Spatrick
7*e5dd7070Spatrick;; To install clang-rename.el make sure the directory of this file is in your
8*e5dd7070Spatrick;; `load-path' and add
9*e5dd7070Spatrick;;
10*e5dd7070Spatrick;;   (require 'clang-rename)
11*e5dd7070Spatrick;;
12*e5dd7070Spatrick;; to your .emacs configuration.
13*e5dd7070Spatrick
14*e5dd7070Spatrick;;; Code:
15*e5dd7070Spatrick
16*e5dd7070Spatrick(defgroup clang-rename nil
17*e5dd7070Spatrick  "Integration with clang-rename"
18*e5dd7070Spatrick  :group 'c)
19*e5dd7070Spatrick
20*e5dd7070Spatrick(defcustom clang-rename-binary "clang-rename"
21*e5dd7070Spatrick  "Path to clang-rename executable."
22*e5dd7070Spatrick  :type '(file :must-match t)
23*e5dd7070Spatrick  :group 'clang-rename)
24*e5dd7070Spatrick
25*e5dd7070Spatrick;;;###autoload
26*e5dd7070Spatrick(defun clang-rename (new-name)
27*e5dd7070Spatrick  "Rename all instances of the symbol at point to NEW-NAME using clang-rename."
28*e5dd7070Spatrick  (interactive "sEnter a new name: ")
29*e5dd7070Spatrick  (save-some-buffers :all)
30*e5dd7070Spatrick  ;; clang-rename should not be combined with other operations when undoing.
31*e5dd7070Spatrick  (undo-boundary)
32*e5dd7070Spatrick  (let ((output-buffer (get-buffer-create "*clang-rename*")))
33*e5dd7070Spatrick    (with-current-buffer output-buffer (erase-buffer))
34*e5dd7070Spatrick    (let ((exit-code (call-process
35*e5dd7070Spatrick                      clang-rename-binary nil output-buffer nil
36*e5dd7070Spatrick                      (format "-offset=%d"
37*e5dd7070Spatrick                              ;; clang-rename wants file (byte) offsets, not
38*e5dd7070Spatrick                              ;; buffer (character) positions.
39*e5dd7070Spatrick                              (clang-rename--bufferpos-to-filepos
40*e5dd7070Spatrick                               ;; Emacs treats one character after a symbol as
41*e5dd7070Spatrick                               ;; part of the symbol, but clang-rename doesn’t.
42*e5dd7070Spatrick                               ;; Use the beginning of the current symbol, if
43*e5dd7070Spatrick                               ;; available, to resolve the inconsistency.
44*e5dd7070Spatrick                               (or (car (bounds-of-thing-at-point 'symbol))
45*e5dd7070Spatrick                                   (point))
46*e5dd7070Spatrick                               'exact))
47*e5dd7070Spatrick                      (format "-new-name=%s" new-name)
48*e5dd7070Spatrick                      "-i" (buffer-file-name))))
49*e5dd7070Spatrick      (if (and (integerp exit-code) (zerop exit-code))
50*e5dd7070Spatrick          ;; Success; revert current buffer so it gets the modifications.
51*e5dd7070Spatrick          (progn
52*e5dd7070Spatrick            (kill-buffer output-buffer)
53*e5dd7070Spatrick            (revert-buffer :ignore-auto :noconfirm :preserve-modes))
54*e5dd7070Spatrick        ;; Failure; append exit code to output buffer and display it.
55*e5dd7070Spatrick        (let ((message (clang-rename--format-message
56*e5dd7070Spatrick                        "clang-rename failed with %s %s"
57*e5dd7070Spatrick                        (if (integerp exit-code) "exit status" "signal")
58*e5dd7070Spatrick                        exit-code)))
59*e5dd7070Spatrick          (with-current-buffer output-buffer
60*e5dd7070Spatrick            (insert ?\n message ?\n))
61*e5dd7070Spatrick          (message "%s" message)
62*e5dd7070Spatrick          (display-buffer output-buffer))))))
63*e5dd7070Spatrick
64*e5dd7070Spatrick(defalias 'clang-rename--bufferpos-to-filepos
65*e5dd7070Spatrick  (if (fboundp 'bufferpos-to-filepos)
66*e5dd7070Spatrick      'bufferpos-to-filepos
67*e5dd7070Spatrick    ;; Emacs 24 doesn’t have ‘bufferpos-to-filepos’, simulate it using
68*e5dd7070Spatrick    ;; ‘position-bytes’.
69*e5dd7070Spatrick    (lambda (position &optional _quality _coding-system)
70*e5dd7070Spatrick      (1- (position-bytes position)))))
71*e5dd7070Spatrick
72*e5dd7070Spatrick;; ‘format-message’ is new in Emacs 25.1.  Provide a fallback for older
73*e5dd7070Spatrick;; versions.
74*e5dd7070Spatrick(defalias 'clang-rename--format-message
75*e5dd7070Spatrick  (if (fboundp 'format-message) 'format-message 'format))
76*e5dd7070Spatrick
77*e5dd7070Spatrick(provide 'clang-rename)
78*e5dd7070Spatrick
79*e5dd7070Spatrick;;; clang-rename.el ends here
80