purcell / exec-path-from-shell

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

Support nushell #109

Closed andrewbanchich closed 7 months ago

andrewbanchich commented 2 years ago

After setting nushell as my default shell, I don't think exec-path-from-shell is working correctly.

The output of (getenv "PATH") looks like ${PATH-kj1h2k34jh2kj3h4234}.

purcell commented 2 years ago

Try enabling exec-path-from-shell-debug, then you should get more detailed info about what's happening. (In *Messages*, iirc.)

andrewbanchich commented 2 years ago

The first line is:

Invoking shell /Users/banchich/.cargo/bin/nu with args ("-l" "-i" "-c" "/usr/bin/printf '__RESULT\\000%s\\000%s\\000__RESULT' \"${PATH-1e96998a18bbe92595e1bcb372301ea1}\" \"${MANPATH-1e96998a18bbe92595e1bcb372301ea1}\"")

Then several errors about various programs not being found.

purcell commented 2 years ago

Then several errors about various programs not being found.

Which programs?

The intention here is that for non-posix shells like fish and nu, the shell is told to invoke printf in order to print out the env var values in a reliably parseable format. If nu would require the command to be passed in a different way, let me know.

andrewbanchich commented 2 years ago

Git, for example.

Yeah, getting an equivalent path string from nu would be: $env.PATH | str collect ":"

purcell commented 2 years ago

Git, for example.

Ah right. The debug output should also display what nu printed when asked to run that command. It would be helpful if you included that too.

Yeah, getting an equivalent path string from nu would be: $env.PATH | str collect ":"

I know there are shell-specific ways of doing things, but I'm asking about how to run that printf command. Otherwise, for newfangled shells I'd need to parse all sorts of different output, and it has to all work even if there are nulls or newlines etc. in the env var values. The printf method ensures this works the same everywhere.

andrewbanchich commented 2 years ago

Output related to git:

Error: (file-missing "Searching for program" "No such file or directory" "git")

I assume that's because exec-path-from-shell thinks the output was a correct $PATH even though it wasn't?

I'm asking about how to run that printf command

Ah, gotcha! printf should just work normally. I tried:

❯ nu -l -i -c 'printf "hello"'
hello
purcell commented 2 years ago

I think this should be resolved by dff9ce3.

andrewbanchich commented 2 years ago

Hmm, I updated and (getenv "PATH") is still giving me the wrong path.

andrewbanchich commented 2 years ago

I tried clearing my local package repos and setting nu as the default shell again. Now when Emacs starts I get:

Warning (initialization): An error occurred while loading β€˜/Users/banchich/.emacs’:

error: Non-zero exit code from shell /Users/banchich/.cargo/bin/nu invoked with args ("-l" "-i" "-c" "sh -c /usr/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000\\%s\\\\000__RESULT\\'\\ \\\"\\$\\{PATH-865eec1ee635cce045535a068b81a521\\}\\\"\\ \\\"\\$\\{MANPATH-865eec1ee635cce045535a068b81a521\\}\\\"").  Output was:
"Error: ]8;;https://docs.rs/nu-parser/0.65.0/nu_parser/enum.ParseError.html#variant.UnexpectedEof\\nu::parser::unexpected_eof (link)]8;;\\

  Γ— Unexpected end of code.
   ╭─[source:1:1]
 1 β”‚ sh -c /usr/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000\\%s\\\\000__RESULT\\'\\ \\\"\\$\\{PATH-865eec1ee635cce045535a068b81a521\\}\\\"\\ \\\"\\$\\{MANPATH-865eec1ee635cce045535a068b81a521\\}\\\"
   ╰────

"

To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file.  Start Emacs with
the β€˜--debug-init’ option to view a complete error backtrace. Disable showing Disable logging

With --debug-init:

Debugger entered--Lisp error: (error "Non-zero exit code from shell /Users/banchich/.cargo/bin/nu invoked with args (\"-l\" \"-i\" \"-c\" \"sh -c /usr/bin/printf\\\\ \\\\'__RESULT\\\\\\\\000\\\\%s\\\\\\\\000\\\\%s\\\\\\\\000__RESULT\\\\'\\\\ \\\\\\\"\\\\$\\\\{PATH-0d51d145bc12...")
  signal(error ("Non-zero exit code from shell /Users/banchich/.cargo/bin/nu invoked with args (\"-l\" \"-i\" \"-c\" \"sh -c..."))
  error("Non-zero exit code from shell %s invoked with args..." "/Users/banchich/.cargo/bin/nu" ("-l" "-i" "-c" "sh -c /usr/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000\\%s\\...") "Error: \33]8;;https://docs.rs/nu-parser/0.65.0/nu_pa...")
  exec-path-from-shell-printf("%s\\000%s" ("${PATH-0d51d145bc127182e7e7a8ef4d79c309}" "${MANPATH-0d51d145bc127182e7e7a8ef4d79c309}"))
  exec-path-from-shell-getenvs(("PATH" "MANPATH"))
  exec-path-from-shell-copy-envs(("PATH" "MANPATH"))
  exec-path-from-shell-initialize()
  eval-buffer(#<buffer  *load*> nil "/Users/banchich/.emacs" nil t)  ; Reading at buffer position 1968
  load-with-code-conversion("/Users/banchich/.emacs" "/Users/banchich/.emacs" t t)
  load("~/.emacs" noerror nomessage)
  startup--load-user-init-file(#f(compiled-function () #<bytecode -0x1493b59c6f7613b>) #f(compiled-function () #<bytecode -0x1f3c686ddc0d6275>) t)
  command-line()
  normal-top-level()
purcell commented 2 years ago

Looks like nu handles escaping completely differently even to other non-standard shells like fish.

Here are the invocations with various shells, with the same command passed each time:

❯ zsh -c "sh -c /etc/profiles/per-user/steve/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000__RESULT\\'\\ \\\"\\$\\{MANPATH-08ccc6cf287832a08d51789038f15a72\\}\\\""
__RESULT08ccc6cf287832a08d51789038f15a72__RESULT%

fish:

❯ fish -c "sh -c /etc/profiles/per-user/steve/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000__RESULT\\'\\ \\\"\\$\\{MANPATH-08ccc6cf287832a08d51789038f15a72\\}\\\""
zsh: correct 'fish' to 'vis' [nyae]? n
__RESULT08ccc6cf287832a08d51789038f15a72__RESULT%

nu:

nu -c "sh -c /etc/profiles/per-user/steve/bin/printf\\ \\'__RESULT\\\\000\\%s\\\\000__RESULT\\'\\ \\\"\\$\\{MANPATH-08ccc6cf287832a08d51789038f15a72\\}\\\""
Error: nu::parser::unexpected_eof (link)

  Γ— Unexpected end of code.
   ╭─[source:1:1]
 1 β”‚ sh -c /etc/profiles/per-user/steve/bin/printf\ \'__RESULT\\000\%s\\000__RESULT\'\ \"\$\{MANPATH-08ccc6cf287832a08d51789038f15a72\}\"
   ╰────

Some special case handling would have to be done for nu. Perhaps you could advise? The goal is to print out __RESULT followed by a NULL character, followed by either the env var (if it exists) or the provided hex string (08ccc6cf287832a08d51789038f15a72 in this case), then finally a NULL and __RESULT again.

andrewbanchich commented 2 years ago

I'll have to get back to you on that - I'm not a nushell expert yet, and can't figure it out myself right now.

Is there a way for exec-path-from-shell users to override that shell command themselves? That way you wouldn't need to handle all the edge cases yourself.

andrewbanchich commented 2 years ago

Relevant discussion here: https://github.com/nushell/nushell/discussions/6435

andrewbanchich commented 2 years ago

Looks like the nushell command that will work is $"/usr/bin/printf '__RESULT\u0000%s\u0000__RESULT' \"${MANPATH-08ccc6cf287832a08d51789038f15a72}\"" | sh

KaranAhlawat commented 7 months ago

@andrewbanchich Did you figure out how to get this working? I see you've shared a snippet, but I'm not sure whete it goes exactly.

andrewbanchich commented 7 months ago

No I haven't. IIRC there would need to be some update to this package to support it.

KaranAhlawat commented 7 months ago

Alright, thank you for responding. I've moved away from Nushell for the time being.

purcell commented 7 months ago

Okay, you guys nerd-sniped me. Maybe grab the code in #119 and let me know if it works for you?

purcell commented 7 months ago

(I figured out that instead of the command above, I could construct a proper nu expression like [ $env."PATH"?, $env."MANPATH"? ] | to json and then read the result from Emacs.)

KaranAhlawat commented 7 months ago

Okay, you guys nerd-sniped me. Maybe grab the code in #119 and let me know if it works for you?

I'm sorry, that was not my intention. Ideally this shouldn't fall on the maintainer since the shell isn't POSIX(?) compliant.

But also I'm grateful that you did! I'll check it in a bit and update you guys. πŸ˜„

purcell commented 7 months ago

I'm sorry, that was not my intention. Ideally this shouldn't fall on the maintainer since the shell isn't POSIX(?) compliant.

Don't worry, I got genuinely curious. But I appreciate the sentiment!

KaranAhlawat commented 7 months ago

Confirmed, it does work from MELPA.

purcell commented 7 months ago

Great, thanks @KaranAhlawat!