Code Completion with Exuberant Ctags in Emacs

I’ve put some effort into getting code completion with TAGS files working. I couldn’t get it to work with auto-complete no matter what I tried, there were some addons that I tried but none of them worked. I also tried company-mode but could not get it to work.

I finally stumbled upon Completion UI and at last found the package that would just work. Here are my completion-ui specific lines in my setup:

(add-to-list 'load-path "/home/henrik/.emacs.d/henrik/completion-ui")
(require 'completion-ui)
(auto-completion-mode nil)
(global-set-key (kbd "s-i") 'complete-etags)
(custom-set-faces
 '(completion-highlight-face ((t (:background "grey" :foreground "white")))))

Furthermore, M-down will show the completion menu.

To automatically load my TAGS files and setup Projectile I’ve created the following function for my project which is actually two projects with separate .hg folders:

(setq projectile-indexing-method 'native)
(setq projectile-enable-caching t)

(defun load-project-x ()
  (interactive)
  (let ((bdir "/var/www/project-x"))
    (cd bdir)
    (shell-command "ctags-exuberant -e -R --languages=php")
    (visit-tags-table "TAGS")    
    (find-file "index.php")))

Note the last line that opens index.php in the project, this is to “orient” Projectile in order to make find file in project to work on startup. Note also that I use native indexing, ie elisp only. This is to being able to use a single .projectile file in /var/www/project-x to define my project, it looks like this:

-*.gif
-*.png
-*.jpg
-*.jpeg
-TAGS
+/sub-project1
+/sub-project2
-/sub-project1/.hg
-/sub-project2/.hg

Note the exclusion of the .hg folders to avoid having their *.i files showing up in C-c p f searches. Use C-u C-c p f to refresh the cache, it can be needed if it gets corrupt. Default behaviour should be to index your whole project, if that doesn’t happen you need to refresh.

(global-set-key (kbd "s-y") 'yas-expand)
(add-to-list 'auto-mode-alist '("\\.js$" . web-mode))
(global-set-key (kbd "C-c e t") 'ecb-toggle-ecb-windows)
(global-set-key "\M-n" "\C-u1\C-v")
(global-set-key "\M-p" "\C-u1\M-v")

Since the prior post I’ve noticed that auto-complete and yasnippet had a conflict of sorts. Auto-complete will show completions inline after a set amount of time, these completions are completed with TAB which makes it impossible to trigger snippet completion. The solution is to trigger snippet completion by another combo, in my case Super-y.

I’ve also thrown out js2-mode in favor of web-mode for editing .js files, js2-mode just proved to be too buggy.

Since I navigate by way of Projectile’s find file in project I don’t need the ECB file view any more and have therefore setup so I can toggle it on and off to avoid having a lot of dead space.

I’ve also remapped moving the buffer with the cursor in position to easier key combos.

(defun duplicate-line ()
  (interactive)
  (save-excursion
    (let ((kill-read-only-ok t) deactivate-mark)
      (toggle-read-only 1)
      (kill-whole-line)
      (toggle-read-only 0)
      (yank))))
(global-set-key (kbd "C-d") 'duplicate-line)

Being able to duplicate the current line with the cursor staying in one place is also something I do a lot, just got tired of C-k C-y C-y all the time so I searched for, and found, the above solution.

Some new key combos:
C-c p f search for files.
C-c p g grep project.
M-r cycle top, bottom and middle of current screen.
M-g M-g to go line.
M-n move buffer down one line
M-p move buffer up one line
M-m move back to the first non-white space on current line
M-^ merge the previous and current line
C-x C-t to transpose lines
s-i etags complete
M-down show completion menu
C-x C-v reload buffer (if same file is chosen)

Related Posts

Tags: , ,