gokcehan / lf

Terminal file manager
MIT License
7.63k stars 325 forks source link

ZSH does not respect export of $OLDPWD #955

Open michaelferon opened 1 year ago

michaelferon commented 1 year ago

lf exports the environment variable $OLDPWD to subshells with the value of the initial working directory from where lf was launched. Unfortunately, it looks like zsh initializes this (shell built-in) environment variable to the current directory (where the subshell is launched) regardless of whatever value was exported. As far as I can tell, zsh performs this initialization irrespective of the way in which it is invoked (-c flag does not prevent this, nor does NO_RCS, etc.).

There doesn't seem to be any way around this (though if anyone has any ideas, please let me know). The only fix I can think of would be to add an additional environment variable (say $OLD_PWD) for users of zsh to have access to the value of the initial working directory.

michaelferon commented 1 year ago

Just to clarify, a workaround involving storing the initial working directory in a temporary file and accessing that from lf would work, of course. But it would be nice if there were a way to stop zsh from interfering with the export of $OLDPWD

horriblename commented 1 year ago

This is from the bash man page:

OLDPWD The previous working directory as set by the cd command.

After some searching, it seems this is 'intended behavior' on part of the subshell (bash has slightly different behavior than zsh but it also overwrites $OLDPWD)

In any case, I think this variable is only meant for use within lf (e.g. to cd back to initial dir)

you could use a launcher script and set up a separate environment variable for this I guess

file ~/.local/bin/lfwrap

#!/bin/zsh
export OLD_PWD="$PWD"
lf

then alias lf=~/.local/bin/lfwrap

michaelferon commented 1 year ago

Well there is no way to use this variable within lf as far as I'm aware. It is just exported to the shell environment. And if you use zsh, it will always report the current working directory (equivalent to $PWD), i.e. %echo $OLDPWD and &echo OLDPWD and $echo $OLDPWD will always report the current directory if you have set shell zsh in your lfrc.

I think that $OLDPWD should be available as described in the documentation, but this is not possible in zsh. A workaround like you've described is really not ideal, though I do appreciate the response.

horriblename commented 1 year ago

from my testing $OLDPWD was not changed in non-interactive subshells, I could be wrong tho

but if i'm not wrong, you could do something like this:

map gg $lf -remote "send $id cd $OLDPWD" 

and yea i agree it's a wierd design

michaelferon commented 1 year ago

Interesting. I'm getting this behavior in interactive and non-interactive zsh shells. I guess now would be the time to say I'm running zsh 5.9 (x86_64-apple-darwin21.3.0) on mac (installed via Homebrew).

horriblename commented 1 year ago

I made a mistake in my sample above, edited and fixed.

I tried this on zsh and bash, and they work as I expected (linux)

could you try opening lf, go into a different directory then run :!echo $OLDPWD to see if its the directory you started with?

michaelferon commented 1 year ago

Yes this yields the current working directory for me. If I were using bash it would work as you describe it, but with zsh it doesn't work. I've tried this with an empty zshrc and empty lfrc (empty except for set shell zsh).

ilyagr commented 8 months ago

This affects more than just zsh.

I had this happen to me on MacOS when lf's shell option was unset (defaulting to sh) and /bin/sh was symlinked (via /private/bar/select/sh) to Apple's ancient version of bash, as it is by default.

If sh is symlinked to /bin/dash or /bin/zsh, there is no problem AFAICT.

Just wanted to leave a note for people to find. Perhaps Apple will change the default sh at some point, making this go away.

Perhaps we could have an OLD_PWD variable as well. I'm a bit conflicted on what the best resolution on lf's side would be and whether one is needed.

joelim-work commented 8 months ago

One other method is to have a user-defined option store this value, by adding the following to your config file:

&lf -remote "send $id set user_OLDPWD \"$PWD\""

Which can then be used as follows:

map go &lf -remote "send $id cd \"$lf_user_OLDPWD\""