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