senny / rvm.el

use rvm to manage ruby versions within emacs
214 stars 42 forks source link

rvm-use doesn't work when no trailing slash in PATH #56

Open bilus opened 4 years ago

bilus commented 4 years ago

Nice package! Unfortunately, I found it doesn't quite work with my setup, possibly because I'm using fish.

Here's what my PATH looks like:

 λ printenv "PATH"
/Users/martinb/.rvm/gems/ruby-2.6.5/bin:/Users/martinb/.rvm/gems/ruby-2.6.5@global/bin:/Users/martinb/.rvm/rubies/ruby-2.6.5/bin:/Users/martinb/.rvm/bin:[..snip]

Notice the lack of a trailing slash. It makes the rvm--change-path function to fail because rvm/info returns a path to the binary, which you strip of the executable name using file-name-directory in the rvm-use function.

I patched it locally, can submit a PR if you don't think it's a particularly awful solution:

(defun rvm--normalize-dir (path)
  (if (string-suffix-p "/" path)
      (substring path 0 (- (length path) 1))
    path))

(defun rvm--change-path (current-binary-var new-binaries)
  (let ((current-binaries-for-path
         (rvm--normalize-dir
          (mapconcat 'identity (eval current-binary-var) ":")))
        (new-binaries-for-path
         (rvm--normalize-dir
          (mapconcat 'identity new-binaries ":"))))
    (if (and (eval current-binary-var)
             (not (string= (first (eval current-binary-var)) "/bin")))
        (progn
          (setenv "PATH" (replace-regexp-in-string
                          (regexp-quote current-binaries-for-path)
                          new-binaries-for-path
                          (getenv "PATH")))
          (dolist (binary (eval current-binary-var))
            (setq exec-path (remove binary exec-path))))
      (setenv "PATH" (concat new-binaries-for-path ":" (getenv "PATH"))))
    (dolist (binary new-binaries)
      (add-to-list 'exec-path binary))
    (setq eshell-path-env (getenv "PATH"))
    (set current-binary-var new-binaries)))

I could rewrite it using regexp if you insist. :) I haven't tested it with other shells but I believe it should work with slashes in PATH as well.

sshaw commented 4 years ago

Hi @bilus, my path does not end with a slash either:

ELISP> (getenv "PATH")
"/Users/sshaw/.rvm/gems/ruby-2.3.7/bin:/Users/sshaw/.rvm/gems/ruby-2.3.7@global/bin:/Users/sshaw/.rvm/rubies/ruby-2.3.7/bin:/Users/sshaw/.rvm/bin:/Users/sshaw/perl5/perlbrew/bin:/Users/sshaw/perl5/perlbrew/perls/perl-5.20.0/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/Library/TeX/texbin:/Applications/Emacs.app/Contents/MacOS/bin-x86_64-10_9:/Applications/Emacs.app/Contents/MacOS/libexec-x86_64-10_9:/Users/sshaw/.rvm/bin:/Users/sshaw/bin:/Users/sshaw/usr/bin:/usr/sbin:/usr/local/sbin:/Users/sshaw/.go/bin:/Users/sshaw/.cask/bin:/Users/sshaw/.jenv/bin"

But rvm-use does work for me.

One thing I did notices is that rvm/info returns two elements with the key "ruby":

ELISP> (rvm/info "2.5.2")
(("IRBRC" . "/Users/sshaw/.rvm/rubies/ruby-2.5.2/.irbrc")
 ;; <snip a ton of stuff> 
 ("ruby" . "/Users/sshaw/.rvm/rubies/ruby-2.5.2/bin/ruby")
 ("ruby" . "/Users/sshaw/.rvm/rubies/ruby-2.5.2")
 ("gem" . "/Users/sshaw/.rvm/gems/ruby-2.5.2")
 ;; <snip more>

Mine works because assoc finds the one with a binary since it comes first. Maybe this is the issue? Can you check what (rvm/info whatever-version) returns for the "ruby" key?