xref: /minix3/external/bsd/llvm/dist/clang/utils/clang-completion-mode.el (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc;;; Clang Code-Completion minor mode, for use with C/Objective-C/C++.
2*f4a2713aSLionel Sambuc
3*f4a2713aSLionel Sambuc;;; Commentary:
4*f4a2713aSLionel Sambuc
5*f4a2713aSLionel Sambuc;; This minor mode uses Clang's command line interface for code
6*f4a2713aSLionel Sambuc;; completion to provide code completion results for C, Objective-C,
7*f4a2713aSLionel Sambuc;; and C++ source files. When enabled, Clang will provide
8*f4a2713aSLionel Sambuc;; code-completion results in a secondary buffer based on the code
9*f4a2713aSLionel Sambuc;; being typed. For example, after typing "struct " (triggered via the
10*f4a2713aSLionel Sambuc;; space), Clang will provide the names of all structs visible from
11*f4a2713aSLionel Sambuc;; the current scope. After typing "p->" (triggered via the ">"),
12*f4a2713aSLionel Sambuc;; Clang will provide the names of all of the members of whatever
13*f4a2713aSLionel Sambuc;; class/struct/union "p" points to. Note that this minor mode isn't
14*f4a2713aSLionel Sambuc;; meant for serious use: it is meant to help experiment with code
15*f4a2713aSLionel Sambuc;; completion based on Clang. It needs your help to make it better!
16*f4a2713aSLionel Sambuc;;
17*f4a2713aSLionel Sambuc;; To use the Clang code completion mode, first make sure that the
18*f4a2713aSLionel Sambuc;; "clang" variable below refers to the "clang" executable,
19*f4a2713aSLionel Sambuc;; which is typically installed in libexec/. Then, place
20*f4a2713aSLionel Sambuc;; clang-completion-mode.el somewhere in your Emacs load path. You can
21*f4a2713aSLionel Sambuc;; add a new load path to Emacs by adding some like the following to
22*f4a2713aSLionel Sambuc;; your .emacs:
23*f4a2713aSLionel Sambuc;;
24*f4a2713aSLionel Sambuc;;   (setq load-path (cons "~/.emacs.d" load-path))
25*f4a2713aSLionel Sambuc;;
26*f4a2713aSLionel Sambuc;; Then, use
27*f4a2713aSLionel Sambuc;;
28*f4a2713aSLionel Sambuc;;   M-x load-library
29*f4a2713aSLionel Sambuc;;
30*f4a2713aSLionel Sambuc;; to load the library in your Emacs session or add the following to
31*f4a2713aSLionel Sambuc;; your .emacs to always load this mode (not recommended):
32*f4a2713aSLionel Sambuc;;
33*f4a2713aSLionel Sambuc;;   (load-library "clang-completion-mode")
34*f4a2713aSLionel Sambuc;;
35*f4a2713aSLionel Sambuc;; Once you have done this, you can set various parameters with
36*f4a2713aSLionel Sambuc;;
37*f4a2713aSLionel Sambuc;;   M-x customize-group RET clang-completion-mode RET
38*f4a2713aSLionel Sambuc;;
39*f4a2713aSLionel Sambuc;; Finally, to try Clang-based code completion in a particular buffer,
40*f4a2713aSLionel Sambuc;; use M-x clang-completion-mode. When "Clang" shows up in the mode
41*f4a2713aSLionel Sambuc;; line, Clang's code-completion is enabled.
42*f4a2713aSLionel Sambuc;;
43*f4a2713aSLionel Sambuc;; Clang's code completion is based on parsing the complete source
44*f4a2713aSLionel Sambuc;; file up to the point where the cursor is located. Therefore, Clang
45*f4a2713aSLionel Sambuc;; needs all of the various compilation flags (include paths, dialect
46*f4a2713aSLionel Sambuc;; options, etc.) to provide code-completion results. Currently, these
47*f4a2713aSLionel Sambuc;; need to be placed into the clang-flags variable in a format
48*f4a2713aSLionel Sambuc;; acceptable to clang. This is a hack: patches are welcome to
49*f4a2713aSLionel Sambuc;; improve the interface between this Emacs mode and Clang!
50*f4a2713aSLionel Sambuc;;
51*f4a2713aSLionel Sambuc
52*f4a2713aSLionel Sambuc;;; Code:
53*f4a2713aSLionel Sambuc;;; The clang executable
54*f4a2713aSLionel Sambuc(defcustom clang "clang"
55*f4a2713aSLionel Sambuc  "The location of the Clang compiler executable"
56*f4a2713aSLionel Sambuc  :type 'file
57*f4a2713aSLionel Sambuc  :group 'clang-completion-mode)
58*f4a2713aSLionel Sambuc
59*f4a2713aSLionel Sambuc;;; Extra compilation flags to pass to clang.
60*f4a2713aSLionel Sambuc(defcustom clang-flags nil
61*f4a2713aSLionel Sambuc  "Extra flags to pass to the Clang executable.
62*f4a2713aSLionel SambucThis variable will typically contain include paths, e.g., -I~/MyProject."
63*f4a2713aSLionel Sambuc  :type '(repeat (string :tag "Argument" ""))
64*f4a2713aSLionel Sambuc  :group 'clang-completion-mode)
65*f4a2713aSLionel Sambuc
66*f4a2713aSLionel Sambuc;;; The prefix header to use with Clang code completion.
67*f4a2713aSLionel Sambuc(setq clang-completion-prefix-header "")
68*f4a2713aSLionel Sambuc
69*f4a2713aSLionel Sambuc;;; The substring we will use to filter completion results
70*f4a2713aSLionel Sambuc(setq clang-completion-substring "")
71*f4a2713aSLionel Sambuc
72*f4a2713aSLionel Sambuc;;; The current completion buffer
73*f4a2713aSLionel Sambuc(setq clang-completion-buffer nil)
74*f4a2713aSLionel Sambuc
75*f4a2713aSLionel Sambuc(setq clang-result-string "")
76*f4a2713aSLionel Sambuc
77*f4a2713aSLionel Sambuc;;; Compute the current line in the buffer
78*f4a2713aSLionel Sambuc(defun current-line ()
79*f4a2713aSLionel Sambuc  "Return the vertical position of point..."
80*f4a2713aSLionel Sambuc  (+ (count-lines (point-min) (point))
81*f4a2713aSLionel Sambuc     (if (= (current-column) 0) 1 0)
82*f4a2713aSLionel Sambuc     -1))
83*f4a2713aSLionel Sambuc
84*f4a2713aSLionel Sambuc;;; Set the Clang prefix header
85*f4a2713aSLionel Sambuc(defun clang-prefix-header ()
86*f4a2713aSLionel Sambuc  (interactive)
87*f4a2713aSLionel Sambuc  (setq clang-completion-prefix-header
88*f4a2713aSLionel Sambuc        (read-string "Clang prefix header> " "" clang-completion-prefix-header
89*f4a2713aSLionel Sambuc                     "")))
90*f4a2713aSLionel Sambuc
91*f4a2713aSLionel Sambuc;; Process "filter" that keeps track of the code-completion results
92*f4a2713aSLionel Sambuc;; produced. We store all of the results in a string, then the
93*f4a2713aSLionel Sambuc;; sentinel processes the entire string at once.
94*f4a2713aSLionel Sambuc(defun clang-completion-stash-filter (proc string)
95*f4a2713aSLionel Sambuc  (setq clang-result-string (concat clang-result-string string)))
96*f4a2713aSLionel Sambuc
97*f4a2713aSLionel Sambuc;; Filter the given list based on a predicate.
98*f4a2713aSLionel Sambuc(defun filter (condp lst)
99*f4a2713aSLionel Sambuc    (delq nil
100*f4a2713aSLionel Sambuc          (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
101*f4a2713aSLionel Sambuc
102*f4a2713aSLionel Sambuc;; Determine whether FIXME: explain better
103*f4a2713aSLionel Sambuc(defun is-completion-line (line)
104*f4a2713aSLionel Sambuc  (or (string-match "OVERLOAD:" line)
105*f4a2713aSLionel Sambuc      (string-match (concat "COMPLETION: " clang-completion-substring) line)))
106*f4a2713aSLionel Sambuc
107*f4a2713aSLionel Sambuc
108*f4a2713aSLionel Sambuc;; re-process the completions when further input narrows the field
109*f4a2713aSLionel Sambuc(defun clang-completion-display (buffer)
110*f4a2713aSLionel Sambuc  (fill-buffer buffer))
111*f4a2713aSLionel Sambuc
112*f4a2713aSLionel Sambuc(defun fill-buffer (buffer)
113*f4a2713aSLionel Sambuc  (let* ((all-lines (split-string clang-result-string "\n"))
114*f4a2713aSLionel Sambuc         (completion-lines (filter 'is-completion-line all-lines)))
115*f4a2713aSLionel Sambuc    (if (consp completion-lines)
116*f4a2713aSLionel Sambuc        (progn
117*f4a2713aSLionel Sambuc         ;; Erase the process buffer.
118*f4a2713aSLionel Sambuc         (let ((cur (current-buffer)))
119*f4a2713aSLionel Sambuc           (set-buffer buffer)
120*f4a2713aSLionel Sambuc           (goto-char (point-min))
121*f4a2713aSLionel Sambuc           (erase-buffer)
122*f4a2713aSLionel Sambuc           (set-buffer cur))
123*f4a2713aSLionel Sambuc
124*f4a2713aSLionel Sambuc         ;; Display the process buffer.
125*f4a2713aSLionel Sambuc         (display-buffer buffer)
126*f4a2713aSLionel Sambuc
127*f4a2713aSLionel Sambuc         ;; Insert the code-completion string into the process buffer.
128*f4a2713aSLionel Sambuc         (with-current-buffer buffer
129*f4a2713aSLionel Sambuc           (insert (mapconcat 'identity completion-lines "\n")))
130*f4a2713aSLionel Sambuc         ))))
131*f4a2713aSLionel Sambuc
132*f4a2713aSLionel Sambuc;; Process "sentinel" that, on successful code completion, replaces the
133*f4a2713aSLionel Sambuc;; contents of the code-completion buffer with the new code-completion results
134*f4a2713aSLionel Sambuc;; and ensures that the buffer is visible.
135*f4a2713aSLionel Sambuc(defun clang-completion-sentinel (proc event)
136*f4a2713aSLionel Sambuc  (fill-buffer (process-buffer proc)))
137*f4a2713aSLionel Sambuc
138*f4a2713aSLionel Sambuc(defun clang-complete ()
139*f4a2713aSLionel Sambuc  (let* ((cc-point (concat (buffer-file-name)
140*f4a2713aSLionel Sambuc                           ":"
141*f4a2713aSLionel Sambuc                           (number-to-string (+ 1 (current-line)))
142*f4a2713aSLionel Sambuc                           ":"
143*f4a2713aSLionel Sambuc                           (number-to-string (+ 1 (current-column)))))
144*f4a2713aSLionel Sambuc         (cc-pch (if (equal clang-completion-prefix-header "") nil
145*f4a2713aSLionel Sambuc                   (list "-include-pch"
146*f4a2713aSLionel Sambuc                         (concat clang-completion-prefix-header ".pch"))))
147*f4a2713aSLionel Sambuc         (cc-flags (if (listp clang-flags) clang-flags nil))
148*f4a2713aSLionel Sambuc         (cc-command (append `(,clang "-cc1" "-fsyntax-only")
149*f4a2713aSLionel Sambuc                             cc-flags
150*f4a2713aSLionel Sambuc                             cc-pch
151*f4a2713aSLionel Sambuc                             `("-code-completion-at" ,cc-point)
152*f4a2713aSLionel Sambuc                             (list (buffer-file-name))))
153*f4a2713aSLionel Sambuc         (cc-buffer-name (concat "*Clang Completion for " (buffer-name) "*")))
154*f4a2713aSLionel Sambuc    ;; Start the code-completion process.
155*f4a2713aSLionel Sambuc    (if (buffer-file-name)
156*f4a2713aSLionel Sambuc        (progn
157*f4a2713aSLionel Sambuc          ;; If there is already a code-completion process, kill it first.
158*f4a2713aSLionel Sambuc          (let ((cc-proc (get-process "Clang Code-Completion")))
159*f4a2713aSLionel Sambuc            (if cc-proc
160*f4a2713aSLionel Sambuc                (delete-process cc-proc)))
161*f4a2713aSLionel Sambuc
162*f4a2713aSLionel Sambuc          (setq clang-completion-substring "")
163*f4a2713aSLionel Sambuc          (setq clang-result-string "")
164*f4a2713aSLionel Sambuc          (setq clang-completion-buffer cc-buffer-name)
165*f4a2713aSLionel Sambuc
166*f4a2713aSLionel Sambuc          (let ((cc-proc (apply 'start-process
167*f4a2713aSLionel Sambuc                                (append (list "Clang Code-Completion" cc-buffer-name)
168*f4a2713aSLionel Sambuc                                        cc-command))))
169*f4a2713aSLionel Sambuc            (set-process-filter cc-proc 'clang-completion-stash-filter)
170*f4a2713aSLionel Sambuc            (set-process-sentinel cc-proc 'clang-completion-sentinel)
171*f4a2713aSLionel Sambuc            )))))
172*f4a2713aSLionel Sambuc
173*f4a2713aSLionel Sambuc;; Code-completion when one of the trigger characters is typed into
174*f4a2713aSLionel Sambuc;; the buffer, e.g., '(', ',' or '.'.
175*f4a2713aSLionel Sambuc(defun clang-complete-self-insert (arg)
176*f4a2713aSLionel Sambuc  (interactive "p")
177*f4a2713aSLionel Sambuc  (self-insert-command arg)
178*f4a2713aSLionel Sambuc  (save-buffer)
179*f4a2713aSLionel Sambuc  (clang-complete))
180*f4a2713aSLionel Sambuc
181*f4a2713aSLionel Sambuc;; When the user has typed a character that requires the filter to be
182*f4a2713aSLionel Sambuc;; updated, do so (and update the display of results).
183*f4a2713aSLionel Sambuc(defun clang-update-filter ()
184*f4a2713aSLionel Sambuc  (setq clang-completion-substring (thing-at-point 'symbol))
185*f4a2713aSLionel Sambuc  (if (get-process "Clang Code-Completion")
186*f4a2713aSLionel Sambuc      ()
187*f4a2713aSLionel Sambuc    (clang-completion-display clang-completion-buffer)
188*f4a2713aSLionel Sambuc    ))
189*f4a2713aSLionel Sambuc
190*f4a2713aSLionel Sambuc;; Invoked when the user types an alphanumeric character or "_" to
191*f4a2713aSLionel Sambuc;; update the filter for the currently-active code completion.
192*f4a2713aSLionel Sambuc(defun clang-filter-self-insert (arg)
193*f4a2713aSLionel Sambuc  (interactive "p")
194*f4a2713aSLionel Sambuc  (self-insert-command arg)
195*f4a2713aSLionel Sambuc  (clang-update-filter)
196*f4a2713aSLionel Sambuc  )
197*f4a2713aSLionel Sambuc
198*f4a2713aSLionel Sambuc;; Invoked when the user types the backspace key to update the filter
199*f4a2713aSLionel Sambuc;; for the currently-active code completion.
200*f4a2713aSLionel Sambuc(defun clang-backspace ()
201*f4a2713aSLionel Sambuc  (interactive)
202*f4a2713aSLionel Sambuc  (delete-backward-char 1)
203*f4a2713aSLionel Sambuc  (clang-update-filter))
204*f4a2713aSLionel Sambuc
205*f4a2713aSLionel Sambuc;; Invoked when the user types the delete key to update the filter
206*f4a2713aSLionel Sambuc;; for the currently-active code completion.
207*f4a2713aSLionel Sambuc(defun clang-delete ()
208*f4a2713aSLionel Sambuc  (interactive)
209*f4a2713aSLionel Sambuc  (delete-backward-char 1)
210*f4a2713aSLionel Sambuc  (clang-update-filter))
211*f4a2713aSLionel Sambuc
212*f4a2713aSLionel Sambuc;; Set up the keymap for the Clang minor mode.
213*f4a2713aSLionel Sambuc(defvar clang-completion-mode-map nil
214*f4a2713aSLionel Sambuc  "Keymap for Clang Completion Mode.")
215*f4a2713aSLionel Sambuc
216*f4a2713aSLionel Sambuc(if (null clang-completion-mode-map)
217*f4a2713aSLionel Sambuc    (fset 'clang-completion-mode-map
218*f4a2713aSLionel Sambuc          (setq clang-completion-mode-map (make-sparse-keymap))))
219*f4a2713aSLionel Sambuc
220*f4a2713aSLionel Sambuc(if (not (assq 'clang-completion-mode minor-mode-map-alist))
221*f4a2713aSLionel Sambuc    (setq minor-mode-map-alist
222*f4a2713aSLionel Sambuc          (cons (cons 'clang-completion-mode clang-completion-mode-map)
223*f4a2713aSLionel Sambuc                minor-mode-map-alist)))
224*f4a2713aSLionel Sambuc
225*f4a2713aSLionel Sambuc;; Punctuation characters trigger code completion.
226*f4a2713aSLionel Sambuc(dolist (char '("(" "," "." ">" ":" "=" ")" " "))
227*f4a2713aSLionel Sambuc  (define-key clang-completion-mode-map char 'clang-complete-self-insert))
228*f4a2713aSLionel Sambuc
229*f4a2713aSLionel Sambuc;; Alphanumeric characters (and "_") filter the results of the
230*f4a2713aSLionel Sambuc;; currently-active code completion.
231*f4a2713aSLionel Sambuc(dolist (char '("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O"
232*f4a2713aSLionel Sambuc                "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
233*f4a2713aSLionel Sambuc                "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
234*f4a2713aSLionel Sambuc                "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
235*f4a2713aSLionel Sambuc                "_" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))
236*f4a2713aSLionel Sambuc  (define-key clang-completion-mode-map char 'clang-filter-self-insert))
237*f4a2713aSLionel Sambuc
238*f4a2713aSLionel Sambuc;; Delete and backspace filter the results of the currently-active
239*f4a2713aSLionel Sambuc;; code completion.
240*f4a2713aSLionel Sambuc(define-key clang-completion-mode-map [(backspace)] 'clang-backspace)
241*f4a2713aSLionel Sambuc(define-key clang-completion-mode-map [(delete)] 'clang-delete)
242*f4a2713aSLionel Sambuc
243*f4a2713aSLionel Sambuc;; Set up the Clang minor mode.
244*f4a2713aSLionel Sambuc(define-minor-mode clang-completion-mode
245*f4a2713aSLionel Sambuc  "Clang code-completion mode"
246*f4a2713aSLionel Sambuc  nil
247*f4a2713aSLionel Sambuc  " Clang"
248*f4a2713aSLionel Sambuc  clang-completion-mode-map)
249*f4a2713aSLionel Sambuc
250