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