purcell / exec-path-from-shell

Make Emacs use the $PATH set up by the user's shell
Other
1.41k stars 81 forks source link

The rc shell is not supported #114

Open dertuxmalwieder opened 1 year ago

dertuxmalwieder commented 1 year ago

The README claims:

Further, if you use a non-POSIX-standard shell (...), your shell will be asked to execute sh as a subshell in order to print out the variables in a format which can be reliably parsed. sh must be a POSIX-compliant shell in this case.

My init.el says:

(when (eq system-type 'darwin)
  (elpaca exec-path-from-shell
    (setq exec-path-from-shell-check-startup-files nil)
    (exec-path-from-shell-initialize)))

I can confirm that tcsh works just well. Anyway, my login (= default) shell on this computer is the rc shell, arguably a UNIX-y shell (being the default shell of the last Research Unix version 10). Emacs does not like that:

Warning (emacs): Config Error exec-path-from-shell: (error "Expected printf output from shell, but got: \"rc: syntax error \"")

Suggestion: Add the rc executable to the list of non-standard shells:

; echo $SHELL
/Users/tux0r/bin/rc

edit: Actually, there are two ways to fix it:

  1. Add rc to the list of non-standard shells or
  2. support rc's $path syntax - that would be elegant, as it is a list:
; echo $path
/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /opt/schily/bin /opt/homebrew/bin (... truncated)

Note that rc uses $path, not $PATH, though. I'd gladly send a patch if you decide on one... :-)

purcell commented 1 year ago

Thanks, I'd potentially be open to a patch, and there's another minority shell (nushell) in a similar situation ā€” see #109. Essentially, I guess those shells use different quoting/escaping rules, so the printf command needs to be assembled differently. Ideally we'd figure out a way to generalise this a little.

dertuxmalwieder commented 1 year ago

Depending on the implementation of rc, quoting is only one of the things which are different. Having used the Nushell for a while, I doubt that a common denominator will be rather hard to find, to be honest. It would probably still require a separate handling for special shells and their needs.

purcell commented 1 year ago

Yeah, I'm imagining maybe an overriding argument quoting function that's specified in an alist.

dertuxmalwieder commented 5 months ago

The recent addition of support for Nushell has made the code even harder for me to understand, I'm afraid. I had just tried a shot in the dark by trying to get anything sensible out of rc (essentially: rc -c 'echo $path', so nothing too uncommon, minus the lower case) in *scratch*. The command works, but now I have no idea how to get the result into an Emacs list. šŸ˜‚

purcell commented 5 months ago

The reason rc doesn't work turns out mostly because the existing code uses the ${SOMEVAR-somedefaultvalue} syntax, which the rc author decided to drop from Bourne shell (see "Design Principles" here). Fixing it properly will involve adding some extension points to the code: having added nushell now, I have a better idea of how that would look, so I'll try to have a tinker with it sometime soon.

dertuxmalwieder commented 5 months ago

If you need any second pair of eyes, Iā€™m here. :-) My hands seem to be useless this time.

purcell commented 5 months ago

Well....

What would be helpful would be if you could share an rc command line that would print several environment variables in such a way that their values can be unambiguously parsed from the output afterwards. This should work even if the values contain newlines or other non-null special characters, and it should be possible to tell from the output which variables are absent (vs. simply empty string values).

In the nushell case we do this by printing the values as JSON. For other shells we use printf to construct a null-delimited output string, book-ended with __RESULT, with a special marker value (a long hash) to indicate undefined values.

dertuxmalwieder commented 5 months ago

Hmm. Printing as many environment variables as you wish is easy (echo $home $path $something...), but my approach to check undefined values would be to use rc's built-in counter:

; echo $#path
12                    # $path has 12 values

; echo $#home
1                     # unsurprisingly, $home has 1 value

; echo $#undefined
0                     # $undefined has 0 values ;-)

So, in this example, echo $path $undefined $home would be "the first 12 tokens are the path, the last token is $home, $undefined are 0 tokens".