18

Currently, my compilation command is as follow:

cd ~/somedir && ./somescript.sh

This prevents emacs from finding the file in which an error happens (and opening it).

Of course I can run M-x cd manually but is there a way to tell the buffer to change its current directory programmatically?

Thomas Moulard
  • 391
  • 3
  • 11
  • 1
    This is something I've been trying to do, too. Ideally, there'd be something you can put in .dir-locals.el in the base directory that would work (hacks I've seen to set default-directory there cause undesirable side effects, and setting it only for compilation-mode doesn't seem to work). – Julian Squires Nov 26 '14 at 17:55

4 Answers4

11

Finally, I abandoned relying on the current directory as it was too intrusive and other things like ido where ending being affected...

Instead, I use added my build directory to compilation-search-path

(add-to-list 'compilation-search-path "/path/to/build")

Found on this question: How to adjust the path that Emacs' compile-goto-error gets from the compilation buffer?

The question also explains that the directory matcher can change the directory automatically if some particular strings are emitted:

Entering directory `...'
... 
Leaving directory `...'

This is also customizable apparently.

Thomas Moulard
  • 391
  • 3
  • 11
6

This alternate command should do the trick:

(defun compile-in-dir (dir command)
  (interactive "DCompile in directory: \nsCommand: ")
  (let ((default-directory dir))
    (compile command)))

Alternatively, after you have run the compilation using the regular compile command, you can eval (setq default-directory "~/somedir") in the *compilation* buffer. That should make the error navigation work, but it might stop recompile and friends from doing the right thing.

sanityinc
  • 2,871
  • 13
  • 17
6

You can simply make a Dired buffer of the directory where you want to invoke compile command, to serve as an anchor. When you want to compile, switch to the Dired buffer and run compile command. compile will run its command at this directory of the Dired buffer. The advantage of this is that you don't have to M-x cd or traverse directories when you want to compile.

If you use projectile, it has a command named projectile-compile that automatically runs compile command at project root recognized by projectile.

Tu Do
  • 6,772
  • 20
  • 39
0

If you have a rule for creating the source search path, you can add it as advice to the function that compile uses for finding paths. For example, the default directory for building with bazel is ~/.cache/bazel. So I want to find all those and strip out that part of the file. I added an "advice" to the compilation-find-file function so that it will rename the file before calling the function. That elisp is:

;; Rewrite the names of bazel error filenames.
(defun rename-bazel (orig-fun marker filename &rest args)
  (let ((new-filename (or (and (string-match "^\\(.*\\)/.cache/bazel/.*/__main__/\\(.*\\)" filename)
                               (concat (match-string 1 filename) "/" (match-string 2 filename)))
                          filename)))
    (apply orig-fun marker new-filename args)))

(advice-add 'compilation-find-file :around #'rename-bazel)

Now when I click on errors in the compilation buffer, it goes to the right place.

Eyal
  • 101
  • 2