tags:

views:

451

answers:

5

I'm trying to get a compile command (rake cucumber) to run with a specific ruby version on my Mac OS X system, I use rvm to do this currently in the terminal. My ~/.MacOSX/environment.plist has the correct path in it, but emacs insists on prepending to this path and therefore making it useless. I've also tried:

(when (equal system-type 'darwin)
  (setenv "PATH" (concat "/Users/fearoffish/.rvm/bin:/Users/fearoffish/.rvm/rubies/ruby-1.8.7-p249/bin:/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249/bin:/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249%global/bin:/Users/fearoffish/.rvm/bin"))
  (push "/Users/fearoffish/.rvm/bin" exec-path)
  (push "/Users/fearoffish/.rvm/rubies/ruby-1.8.7-p249/bin" exec-path)
  (push "/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249/bin" exec-path)
  (push "/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249%global/bin" exec-path)
  (push "/Users/fearoffish/.rvm/bin" exec-path))

It was the desperate attempt of an emacs beginner to get what I wanted. It still prepends in front of it, so my path ends up being:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/Users/fearoffish/.rvm/bin:/Users/fearoffish/.rvm/rubies/ruby-1.8.7-p249/bin:/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249/bin:/Users/fearoffish/.rvm/gems/ruby-1.8.7-p249%global/bin

I don't want /usr/bin and others prepending, I want my path first and the emacs prepended path to be at the end, I reckon this would fix my problem.

I test this by simply opening Aquamacs and running meta-x compile and then echo $PATH.

Any ideas?

A: 

try this maybe. replace path string with yours.

(add-to-list 'load-path "~/opt/swank-clojure/src/emacs")

Dmitry
+1  A: 

I don't have a Mac, so I cannot test this directly, but this can all be found in the *info* page Interactive Inferior Shell.

When you start a shell in Emacs, the process that gets spawned is the program in the Emacs variable explicit-shell-file-name (and if that is nil, the environment variables ESHELL and SHELL are used).

It then sends the contents of ~/.emacs_*shellname* (e.g. if your shell is csh, then ~/.emacs_csh would be sent over. Also, the appropriate .rc files for csh program is sourced, so you can update that as well (in my case .cshrc). Additionally, you can wrap customizations in the .rc file with a check for the environment variable INSIDE_EMACS (which which Emacs sets before it runs a shell).

You need to update those files to change the path in the shell, not the Emacs variable exec-path. exec-path - which is just a list of directories Emacs uses to find executable programs. The behavior of the executables are not affected by changes to exec-path.

Trey Jackson
A: 

As far as I observed, Emacs takes the path variable from the shell it is launched from, so one solution is to change $PATH in the shell before you launch Emacs.

One other approach I used, which is more flexible, is to use a Makefile and append a "source ~/script_that_set_path" in front of each make commands you have.

polyglot
On a Mac, that's not the case; GUI programs launched from Finder don't inherit the environment of the desktop or the user's shell.
sanityinc
Ah sorry but I never used a Mac; my observation only pertains to windows and linux. Does starting Emacs from terminal (or equivalents in Mac) work? I would (again) suggest trying the Makefile method since that's the only way I found that reliably works (I also struggled a lots with getting PATH right for compilation).
polyglot
A: 

I find the environment.plist scheme on Macs pretty ugly, so I use the following snippet, which assumes you want Emacs to use the same PATH that you see in your Terminal.app:

(defun set-exec-path-from-shell-PATH ()
  (let ((path-from-shell (shell-command-to-string "$SHELL -i -c 'echo $PATH'")))
    (setenv "PATH" path-from-shell)
    (setq exec-path (split-string path-from-shell path-separator))))

(This works for me in Emacs 23; haven't tried it in other versions, but I'd expect it to work.)

sanityinc
Is this for compile commands as well as shell commands?
Jamie van Dyke
Yes, should be.
sanityinc
+2  A: 

A small modification to the solution by sanityinc (couldn't find a way to enter it in the comments above -- is that just me?)

  • I use -l option to the shell to force a login shell (which reads .profile or .bash_profile), rather than an interactive shell (which only reads .bashrc).
  • I do some string trimming on the returned path (as inspection shows a newline sneaking in).

Modified code:

(defun set-exec-path-from-shell-PATH ()
  (let ((path-from-shell 
      (replace-regexp-in-string "[[:space:]\n]*$" "" 
        (shell-command-to-string "$SHELL -l -c 'echo $PATH'"))))
    (setenv "PATH" path-from-shell)
    (setq exec-path (split-string path-from-shell path-separator))))
(when (equal system-type 'darwin) (set-exec-path-from-shell-PATH))
Janus