Golevka / emacs-clang-complete-async

An emacs plugin to complete C and C++ code using libclang
360 stars 71 forks source link

appending to ac-clang-cflags by project specific .dir-locals.el #79

Open psteinb opened 9 years ago

psteinb commented 9 years ago

Dear all,

I love the idea of this package and think it is a great addition to emacs to push it to be a performant C++/C IDE. So I am working on a project that uses a cmake based setup for source code:

inc/
src/
build/
.dir-locals.el

As you can see, I'd like to equip this root directory with a .dir-locals.el that appends inc and src to ac-clang-cflags. I have come up with a minimal example of what I want to do under http://idisk-srv1.mpi-cbg.de/~steinbac/dir-locals-example.zip

The thing is, I can see that the correct value (i.e. the inc path stated above) is added to ac-clang-cflags, but when I open test.cpp and want to tab-complete foo_bar nothing happens!

Any help would be appreciated! Thanks -

psteinb commented 9 years ago

After trying around a bit, I found a working solution:

;;;contents of .dir-locals.el
 ((nil . (
         (eval . (progn
                   (defun my-project-specific-function ()
                     (setq ac-clang-cflags (
                                            append ac-clang-cflags '("-I/path/to/local/inc")
                                                   )
                           )
                     ;;;tell ac-clang that we updated the cflags
                     (ac-clang-update-cmdlineargs)
                     )
                   (my-project-specific-function)
                   )
               )
         )
))

with this, it is possible to include the per project paths in addition to the global ones defined in ~/.emacs or alike.

Feel free to close this issue. I'll keep it open for people to see this solution. Best -

ackalker commented 9 years ago

The problem isn't only with directory-local variables, it is with file-local variables as well. From a lot of searching and debugging, I finally arrived right back at EmacsWiki:

EmacsWiki: Local Variables : http://www.emacswiki.org/emacs/LocalVariables#toc2

TL;DR: Mode hooks are executed before local variables are defined.

Using Method A, I came up with a working solution. Adapting the suggested config from the README.org:

(require 'auto-complete-clang-async)

(defun ac-cc-mode-setup ()
  (setq ac-clang-complete-executable "~/.emacs.d/clang-complete")
  (setq ac-sources '(ac-source-clang-async))
  (add-hook 'hack-local-variables-hook
            (lambda () (ac-clang-launch-completion-process))))

(defun my-ac-config ()
  (add-hook 'c-mode-common-hook 'ac-cc-mode-setup)
  (add-hook 'auto-complete-mode-hook 'ac-common-setup)
  (global-auto-complete-mode t))

(my-ac-config)
ackalker commented 9 years ago

To be clear, the above solution works for both file and directory local variables in the usual way, without the need to manually call ac-clang-update-cmdlineargs. Of course it also works when no local variables are in use.

baohaojun commented 9 years ago

Thank you very much @ackalker !

oracleyue commented 9 years ago

I still got confused at the beginning. Here is a solution, based on explanations in http://stackoverflow.com/questions/5147060/how-can-i-access-directory-local-variables-in-my-major-mode-hooks

.dir-locals.el under your project root:

((c++-mode . ((project-local-include-path . ("-I./include" "-I.")))))

(set whatever local paths for header files you like)

.emacs after defining your system-wide include paths:

  ;; read in project-level include-paths via ".dir-locals.el"
  ;; an example of ".dir-locals.el":
  ;;    ((c++-mode . ((project-local-include-path . ("-I./include" "-I.")))))
  (defun y:readin-dir-local-path ()
    (setq ac-clang-cflags (append ac-clang-cflags project-local-include-path))
    (ac-clang-update-cmdlineargs)
    )
  ;; hook functions defined generally to read in per-directory variables
  (add-hook 'hack-local-variables-hook 'run-local-vars-mode-hook)
  (defun run-local-vars-mode-hook ()
    "Run a hook for the major-mode after the local variables have been processed."
    (run-hooks (intern (concat (symbol-name major-mode) "-local-vars-hook"))))
  ;; use for c++-mode to read in include-path defined under project roots
  (add-hook 'c++-mode-local-vars-hook 'y:readin-dir-local-path)

Cheers~

Version: Emacs 24.4.1