direnv / direnv

unclutter your .profile
http://direnv.net
MIT License
13.01k stars 654 forks source link

Picking up aliases and functions #73

Open pwaller opened 11 years ago

pwaller commented 11 years ago

Just come across a case where someone was expecting functions and aliases to be picked up from the source script.

I realise what a pain this is. Any way we can reasonably make that work?

zimbatm commented 11 years ago

Hey Peter,

It sure would be handy. If you want to contribute that feature I will gladly accept a patch.

Bash can export functions but I don't know how it works exactly. Also target shells like fish wouldn't support that feature but it's alright.

Separately from that I don't know how to better educate the user to make him understand that the .envrc is loaded in a separate bash process who also has the direnv stdlib and ~/.direnvrc loaded. On Aug 20, 2013 2:57 PM, "Peter Waller" notifications@github.com wrote:

Just come across a case where someone was expecting functions and aliases to be picked up from the source script.

I realise what a pain this is. Any way we can reasonably make that work?

— Reply to this email directly or view it on GitHubhttps://github.com/zimbatm/direnv/issues/73 .

winmillwill commented 11 years ago

A few things:

I like this answer which explains how to get the bash export -f behavior in zsh and why it may be a bad idea: http://unix.stackexchange.com/a/59431

I think it may be cool to allow function templating in an includes directory for fish and zsh, but this begs the question of whether those functions are then really part of a shell package and should be distributed some other way. The annoying thing is that (to the best of my knowledge) there is no such thing as a package manager for shell packages, let alone a shell-agnostic shell package manager.

I feel like any alias or function we would put in a .envrc file should really just be a function available to the whole system that takes configuration from variables that direnv (or anything else) could set. Is there a use case we can think of that falls outside of this?

If I'm correct, then the only directive we need to add to dotenv is the 'source' directive, which should be to our shell packages as bundler is to ruby packages, but without the update and install functionality because, again, we don't actually have a package manager or package repository.

zimbatm commented 11 years ago

Hey @winmillwill , I think the idea was that in the context of a project you might want to add some shortcuts as functions or aliases that are really specific. Let's say you have a ruby project, you could set r to be an alias of bundle exec rake or have a special filter function that sanitizes the rails logs ; I'm not sure that as global functions they would be very useful.

That being said I think that in most cases aliases and functions can be replaced by proper bash scripts that's references using the PATH_add directive. Like you said function export is probably a hack, if the project can be kept simple it's probably better :)

zimbatm commented 11 years ago

Some of these tickets are also placeholders for some ideas, like here I'm not super convinced it's useful but I could be convinced otherwise. Ideas are best when simmered :)

winmillwill commented 11 years ago

All of that makes sense. It's just a style point for me that something like alias r='bundle exec rake' ought to belong to a ruby aliases package, and then we could conditionally load that plugin based on the presence and value of something like BUNDLE_EXEC_RAKE_IS_R. In other words, set globals, and then indicate to direnv that you want to load the plugin, and if it has a version for your shell, it can do so. This particular example is bit dumb, but something more usable/useful could certainly be thought up.

I can't claim to understand the indirection you discussed about running all of this in a subshell, so I don't know if source and alias would work in bash with that strategy.

On Mon, Dec 2, 2013 at 6:45 AM, zimbatm notifications@github.com wrote:

Some of these tickets are also placeholders for some ideas, like here I'm not super convinced it's useful but I could be convinced otherwise. Ideas are best when simmered :)

— Reply to this email directly or view it on GitHubhttps://github.com/zimbatm/direnv/issues/73#issuecomment-29585608 .

zimbatm commented 11 years ago

Yeah there's so many ways to do the same things but only few are good :)

I can't claim to understand the indirection you discussed about running all of this in a subshell, so I don't know if source and alias would work in bash with that strategy.

When you run direnv export $target_shell (which is used by direnv hook $target_shell), direnv runs bash in a sub-process that loads the .envrc and then runs direnv dump. Direnv then reads and compares both environment to finally export the diff in the $target_shell format.

It's a bit complex but that way the .envrc is always executed in bash and you don't have to worry about shell compatibility. Any function or others defined in the sub-process don't leak into the current environment (which coincidentally also prevents this feature).

pwaller commented 9 years ago

I'm going to close this one since there hasn't been much interest and I haven't missed it much myself. But if there is demand, please open up another issue. Even better if you can suggest ways to implement it.

jneen commented 9 years ago

I would use this feature. At the very least support for export -f. I have projects, both personal and for work, that require particular startup scripts tailored to my environment, and it'd be really useful to just throw a function in .envrc.

aeonaut commented 9 years ago

+1! I could definitely use this. I've been using my own little cd hook for a while to load some functions and aliases when I change into a directory; direnv is a much more robust solution but not if I have to still keep my old hook around. As mentioned above, I use aliases like alias s="rails server", alias c="rails console", and at the moment alias ee="stty echo" as a workaround for a bug in pry that routinely kills my terminal echo -- I don't really want any of those in my global namespace. Another use case: I have a local function called migrate (for database migrations) in my Rails project that shadows a completely different (and rarely used) executable that has nothing to do with Rails. (As mentioned above, this is perhaps a less pressing use case than the aliases because I could just drop that in a ./bin directory and PATH_add ./bin; still, it's handy to throw that function in my .envrc).

airtoxin commented 9 years ago

+1 for export -f

zimbatm commented 9 years ago

Unfortunately BASHFUNC* environment variables cause issues for other shell so we had to ignore them. See https://github.com/direnv/direnv/pull/157

If you want to maintain all your aliases in the .envrc you could add something like that in your main ~/.direnvrc file:

export_function() {
  local name=$1
  local alias_dir=$PWD/.direnv/aliases
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  local target="$alias_dir/$name"
  if declare -f "$name" >/dev/null; then
    echo "#!/usr/bin/env bash" > "$target"
    declare -f "$name" >> "$target" 2>/dev/null
    echo "$name" >> "$target"
    chmod +x "$target"
  fi
}

then in your .envrc you can write something like:

woot() {
  echo woot
}
export_function woot

An executable file is then automatically generate on each .envrc load inside of the project's .direnv/aliases folder and made available on the PATH.

I suppose a similar export_alias ee "stty echo" could also be crafted

wbolster commented 9 years ago

It seems that the complexity is mostly related to function exports.

Exporting aliases seems easier, at least on bash and ksh, where the alias command prints out the currently defined aliases in such a way that they can be directly passed to the eval built-in, i.e. all the quoting is correct (though slightly non-functionally different between bash and ksh). It looks to me that diffing the outputs of alias before and after evaluating .envrc should be relatively straightforward.

Dr-Terrible commented 9 years ago

I suppose a similar export_alias ee "stty echo" could also be crafted

:+1: I could definitely use this feature.

Generally speaking, exporting aliases is a per project setting in the majority of cases; they would be rarely useful as global settings. This feature will allow me to declutter a lot of junk-aliases and hacks from my global namespace, hence greatly speeding up the bootstrap of all my virtual consoles (which could took quite a toll on terminal multiplexers with a very large number of connections).

zimbatm commented 9 years ago

@wbolster it seems easy on the surface but I don't know how if it will work for all shells. It also means to re-write the whole context serialisation to include the aliases.

@Dr-Terrible it's a bit of a hack but you can add this to your ~/.direnvrc:

# Example: export_alias zz "ls -la"
export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  echo "#!/usr/bin/env bash -e" > "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}
anpol commented 7 years ago

I've prototyped another version of direnv hook that runs a user-defined function direnv_postload when the environment is just loaded. The function is executed in the context of current interactive shell, so it could easily define local functions and aliases associated with the current .envrc.

In addition, a function direnv_preunload could be defined to revert any environment-specific changes when the environment is unloaded (#129, #195), or when the shell exits.

Only zsh version is prototyped by now, I guess it could be ported to bash. https://gist.github.com/anpol/7a2706c2766eff454e047b7513fa511b


I imagine that $(direnv hook zsh) would output a runtime code similar to mine; then the code returned by $(direnv export zsh) would call all the necessary functions without any tricks, like so:

$ direnv export zsh
_direnv_notify_preunload '/path-to/prev-dir' '/path-to/next-dir'
_direnv_log_status 'loading /path-to/next-dir'
_direnv_log_diff '+VAR1' '~VAR2'
export VAR1=value; export VAR2=value;
_direnv_notify_postreload '/path-to/prev-dir' '/path-to/next-dir'

That would even allow for better customization of log messages (#68, #104, #219).

anpol commented 7 years ago

We should decide whether direnv_postload/preunload are worth implementing for all shells. To move forward, some additional feedback is desired.

amosbird commented 7 years ago

Hi, i did some modification with this.

export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases/$(pwd)
  local target="$alias_dir/$name"
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  echo "#!/usr/bin/env bash" > "$target"
  echo "$@ \"\$@\"" >> "$target"
  chmod +x "$target"
}

How can I make direnv remove the pwd's aliase directory when eval so that it won't conflict with the new one?

zimbatm commented 7 years ago

You could rm the folder on each load since it's going to be recreated.

alias_dir=$PWD/.direnv/aliases
rm -rf "$alias_dir"

export_alias() {
  local name=$1
  shift
  local target="$alias_dir/$name"
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  echo "#!/usr/bin/env bash" > "$target"
  echo "$@ \"\$@\"" >> "$target"
  chmod +x "$target"
}
amosbird commented 7 years ago

@zimbatm thanks!

zimbatm commented 7 years ago
alias_dir=$PWD/.direnv/aliases
rm -rf "$alias_dir"

should be set in the .envrc so that $PWD resolves to the .envrc folder

amosbird commented 7 years ago

Hmm, isn't .direnvrc evaled everytime when shell prompts? If that's not the case, it doesn't help much for simplicity since every .envrc needs those lines added.

dereke commented 6 years ago

for those of you using zsh you might like to try this technique: https://coderwall.com/p/a3xreg/per-directory-zsh-config

letientai299 commented 6 years ago

I would like to suggest a minor enhancement for above export_function by @zimbatm

export_function() {
  local name=$1
  local alias_dir=$PWD/.direnv/aliases
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  local target="$alias_dir/$name"
  if declare -f "$name" >/dev/null; then
    echo "#!$SHELL" > "$target"
    declare -f "$name" >> "$target" 2>/dev/null
    # Notice that we add shell variables to the function trigger.
    echo "$name \$*" >> "$target"
    chmod +x "$target"
  fi
}

So, the exported function could pickup shell variables, and use user default shell.

rgov commented 5 years ago

It should be noted that the export_function script here is probably unsound, because it does not traverse the call graph to find other functions that are referenced. Splitting functions into separate scripts may not work properly. Consider:

#!/bin/sh
X=1
function a() {
    echo "$X";
}
a

If we split a into a separate file, and invoke it with ./a instead, the variable X is not available inside ./a and so the output is empty.

It might be better to diff the output of declare -F before and after loading the environment. Then, create a __functions__.sh script which contains the definitions of all new functions (with declare -f), with a final line, "$(basename -- "$0")" "$@", and then make a link to this file with the name ./<func_name> for each new function.

You may also have to capture shell options (such as nullglob) and reproduce them in __functions__.sh. And additionally global variables...

There is a command, set, which just dumps out the state of the shell, and you could use that, but it includes some read-only variables like SHELLOPTS which you will have to handle separately. Not easy! Something like this.

bersace commented 5 years ago

That would be great to have direnv to manage alias map just like environment. Being able to compute diff before and after .envrc execution and adding/removing alias according.

The rc in .envrc suggest that more than env vars could be written in, unlike .env.

Maybe something similar could be done for function using declare -f.

My 2 cents.

jneen commented 5 years ago

The problem with using executables in the first place is that they do not behave like shell functions in a lot of ways. They're isolated from the environment and cannot see non-exported variables. In bash at least, the only sound way would be to eval or source a script that defines the functions, then use unset -f to remove it.

zimbatm commented 5 years ago

It's unlikely that this issue will ever be solved with the current design. Environment variables are unique in the sense that they are cross-shell compatible and inherited in sub-shells. Direnv is relying quite heavily on these two properties to work reliably and undo the changes when changing directory.

It's unfortunate because @jcpetruzza put quite a bit of effort in #443 but it relies on add/remove handlers to revert to the original config. It also would break down if a sub-shell is started as direnv doesn't know how to restore those aliases and functions in the sub-shell.

PierreR commented 4 years ago

@zimbatm as a aside question are aliases defined in shell.nix (shellHook) supposed to work ? It does not seem to be the case here with bash.

zimbatm commented 4 years ago

It's the same issue. The aliases are defined in the .envrc evaluation context but then cannot be exported to the host shell.

wderezin commented 4 years ago

I got aliases working for fish shell using a lib function and a modified hook. It could easily be extended to support other shell.

Overview: 1) Export aliases in the environment variable DIRENV_ALIASES 2) The destroy/create the aliases anytime the DIRENV_ALIASES changes.

I added this to my .config/direnv/lib

export_alias() {
  local name=$1
  shift
  if [ "$DIRENV_ALIASES" = "" ]
  then
    export DIRENV_ALIASES="${name} \"$@\""
  else
    DIRENV_ALIASES="$DIRENV_ALIASES:alias:${name} \"$@\""
  fi
}

And I'm using this for my fish hook. This an update from the hook I submitted in PR #732 but the alias logic is in the __direnv_update function.

function direnv-hook 
    function __direnv_update
        command direnv export fish | source

        if test "$direnv_set_aliases" != "$DIRENV_ALIASES"
            for name in $direnv_alias_names
                functions --erase $name
            end
            set -e direnv_alias_names

            for cmd in (echo $DIRENV_ALIASES | string split --no-empty ':alias:')
                echo "direnv: alias $cmd"
                eval alias $cmd
                set parts (echo $cmd | string split --no-empty ' ')
                set -g -a direnv_alias_names $parts[1]
            end

            set -g direnv_set_aliases $DIRENV_ALIASES
        end
    end

    function __direnv_export_eval --on-event fish_prompt
        # Run on each prompt to update the state
        __direnv_update

        if test "$direnv_fish_mode" != "disable_arrow"
            # Handle cd history arrows between now and the next prompt
            function __direnv_cd_hook --on-variable PWD
                if test "$direnv_fish_mode" = "eval_after_arrow"
                    set -g __direnv_export_again 0
                else
                    # default mode (eval_on_pwd)
                    __direnv_update
                end
            end
        end
    end

    function __direnv_export_eval_2 --on-event fish_preexec
        if set -q __direnv_export_again
            set -e __direnv_export_again
            __direnv_update
            echo
        end

        # Once we're running commands, stop monitoring cd changes
        # until we get to the prompt again
        functions --erase __direnv_cd_hook
    end
end
noel-yap commented 3 years ago

I like the postload and preunload hook idea. Does that exist already? If so, it can be used to cover many scenarios. For example, something like:

# .envrc
hook postload load-aliases.sh
hook postunload unload-aliases.sh
# load-aliases.sh
alias m=make
# unload-aliases.sh
unalias m

The above is for bash but the contents of the load-aliases.sh and unload-aliases.sh scripts can be shell-specific.

noel-yap commented 3 years ago

FYI, I've come up with a solution that works with bash (at least for the aliases and functions I'm working with -- it may break with more complicated quoting in definitions).

In .bashrc:

function direnv-reset-def() {
  eval "${DIRENV_RESET_DEF}"
}

function direnv-set-def() {
  eval "${DIRENV_SET_DEF}"
}

eval "$(direnv hook bash)"
export PROMPT_COMMAND="direnv-reset-def;${PROMPT_COMMAND};direnv-set-def"

In ~/.bash/def.shlib:

function is-def() {
  flag=$1
  name=$2

  case "${flag}" in
    -a)
      [[ "$(type -t ${name} 2>/dev/null)" == 'alias' ]]
      ;;

    -f)
      [[ "$(type -t ${name} 2>/dev/null)" == 'function' ]]
      ;;

    -v)
      [[ -n "${!name+defined}" ]]
      ;;
  esac
}

function get-set-def() {
  flag=$1
  name=$2

  local def
  case "${flag}" in
    -a)
      alias ${name}
      ;;

    -f)
      declare -f ${name}
      ;;

    -v)
      echo "${name}=${!name})"
      ;;
  esac 
}

function get-unset-def() {
  flag=$1
  name=$2

  case "${flag}" in
    -a)
      echo "unalias ${name}"
      ;;

    -f)
      echo "unset -f ${name}"
      ;;

    -v)
      echo "unset ${name}"
      ;;
  esac
}

function get-reset-def() {
  flag=$1
  varname=$2

  if is-def ${flag} ${varname}
  then
    get-set-def ${flag} ${varname}
  else
    get-unset-def ${flag} ${varname}
  fi
} 

In .envrc:

. ~/.bash/def.shlib

export DIRENV_RESET_DEF=$(cat <<EOF
    $(get-reset-def -f some-func)

    $(get-reset-def -a some-alias)
EOF
)

# typical direnv var settings go here

export DIRENV_SET_DEF=$(cat <<'EOF'
    alias some-alias='true'

    function some-function() {
      cd "${GRAIL}/go/src/grail.com/${1:-${SERVICE}}"
    }
EOF
)
eval "${DIRENV_SET_DEF}" # if DIRENV_SET_DEF has exported vars (eg whose values should automatically change when other var values change)
martyzz1 commented 3 years ago

@wbolster it seems easy on the surface but I don't know how if it will work for all shells. It also means to re-write the whole context serialisation to include the aliases.

@Dr-Terrible it's a bit of a hack but you can add this to your ~/.direnvrc:

# Example: export_alias zz "ls -la"
export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  echo "#!/usr/bin/env bash -e" > "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}

I noticed this adds multiple instances of the alias path to the PATH for every export_alias you have, so I tweaked it to check the PATH...

export_alias() {                                                                                                       
  local name=$1                                                                                                        
  shift                                                                                                                
  local alias_dir=$PWD/.direnv/aliases                                                                                 
  local target="$alias_dir/$name"                                                                                      
  mkdir -p "$alias_dir"                                                                                                
  if ! [[ ":$PATH:" == *":$alias_dir:"* ]]; then                                                                       
    PATH_add "$alias_dir"                                                                                              
  fi                                                                                                                   

  echo "#!/usr/bin/env bash -e" > "$target"                                                                            
  echo "$@" >> "$target"                                                                                               
  chmod +x "$target"                                                                                                   
}                                                                                                                      
rationalthinker1 commented 3 years ago

https://stackoverflow.com/questions/17051123/source-a-file-in-zsh-when-entering-a-directory

alexreg commented 3 years ago

Is there any update on this? What is the current recommended solution?

Hubro commented 2 years ago

After years of using direnv, this must be the feature I miss the most. Having simple aliases and functions to simplify tedious development tasks is so nice, for example:

function import-form() {
    cat devdata/form-$1.json \
        | docker-compose -f docker-compose.dev.yaml exec -T db mongoimport -d myproject -c forms
}

Are there any known plugins for direnv that allows it to export functions and aliases for ZSH? Is the plugin API powerful enough that I could implement this myself?

sandangel commented 2 years ago

Hi, I'm using fish shell together with nix-direnv (nix flake). I wonder if the work around mentioned by @wderezin still work since there is no such command direnv export now.

wderezin commented 2 years ago

Hi, I'm using fish shell together with nix-direnv (nix flake). I wonder if the work around mentioned by @wderezin still work since there is no such command direnv export now.

@sandangel I just upgraded to v2.31.0 and my work around is still working for me. Can you provide a reference to where the export command was deprecated so I can research this?

sandangel commented 2 years ago

I just saw there is no such direnv export command in direnv --help. So I wasn't sure if your workaround is still up-to-date. Let me try it. @wderezin . May I ask where do you define the direnv-hook function? Is that in the .config/fish/config.fish file?

alexreg commented 2 years ago

@sandangel Yeah, it's not documented, but it definitely still exists.

wderezin commented 2 years ago

@sandangel

I have a public repo you can look through. I use it so I can easily install my different shell environments and scripts on any system I use. https://github.com/wderezin/cli-tools

But in summary: I have a functions directory that the hook lives in. Then during fish init I add the functions directory to the path, and init the hook.

Links to the code parts:

Hope that helps.

sandangel commented 2 years ago

@wderezin hmm, it doesn't work for me. I run the direnv-hook function when I start fish interactive shell, also added the direnv.sh file that has export_alias function to ~/.config/direnv/lib/direnv.sh. and finally used

export_alias tf "terraform"

in flake.nix shellHook or .envrc but neither of them work.

TjenWellens commented 2 years ago

@wbolster it seems easy on the surface but I don't know how if it will work for all shells. It also means to re-write the whole context serialisation to include the aliases. @Dr-Terrible it's a bit of a hack but you can add this to your ~/.direnvrc:

# Example: export_alias zz "ls -la"
export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  echo "#!/usr/bin/env bash -e" > "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}

I noticed this adds multiple instances of the alias path to the PATH for every export_alias you have, so I tweaked it to check the PATH...

export_alias() {                                                                                                       
  local name=$1                                                                                                        
  shift                                                                                                                
  local alias_dir=$PWD/.direnv/aliases                                                                                 
  local target="$alias_dir/$name"                                                                                      
  mkdir -p "$alias_dir"                                                                                                
  if ! [[ ":$PATH:" == *":$alias_dir:"* ]]; then                                                                       
    PATH_add "$alias_dir"                                                                                              
  fi                                                                                                                   

  echo "#!/usr/bin/env bash -e" > "$target"                                                                            
  echo "$@" >> "$target"                                                                                               
  chmod +x "$target"                                                                                                   
}                                                                                                                      

For those who rely on an alias to add arguments at the end (example where greet world outputs hello world)

# without direnv
alias greet="echo hello"

# with direnv
export_alias greet 'echo hello $@'

PS: I tried adding it into the script first echo "$@" '$@' >> "$target", this worked but broke where I used alias as macros. eg. I used if statements etc inside an alias. But if you don't use such complex functionality, this might be sufficient and much cleaner.

TheLastProject commented 2 years ago

Thanks everyone for their helpful notes on workarounds. Especially https://github.com/direnv/direnv/issues/73#issuecomment-979504909 (and all previous iterations) were extremely helpful.

In my case I need to alias an existing command to add some extra flags to it, which caused an infinite loop. However, explicitly setting PATH back to the old path in export_alias worked for me:

export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  local oldpath="$PATH"
  mkdir -p "$alias_dir"
  if ! [[ ":$PATH:" == *":$alias_dir:"* ]]; then
    PATH_add "$alias_dir"
  fi

  echo "#!/usr/bin/env bash" > "$target"
  echo "PATH=$oldpath" >> "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}
export_alias ansible-playbook 'ansible-playbook -e ara_playbook_labels=$(whoami) $@'

A native solution would still be great, but hopefully this little extra note helps others :)

jmauro commented 2 years ago
export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  local oldpath="$PATH"
  mkdir -p "$alias_dir"
  if ! [[ ":$PATH:" == *":$alias_dir:"* ]]; then
    PATH_add "$alias_dir"
  fi

  echo "#!/usr/bin/env bash" > "$target"
  echo "PATH=$oldpath" >> "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}
export_alias ansible-playbook 'ansible-playbook -e ara_playbook_labels=$(whoami) $@'

Hello,

In case you are using direnv inside WSL and wish to use the previous trick, do not forget to quote your path:

export_alias() {
  local name=$1
  shift
  local alias_dir=$PWD/.direnv/aliases
  local target="$alias_dir/$name"
  local oldpath="$PATH"
  mkdir -p "$alias_dir"
  if ! [[ ":$PATH:" == *":$alias_dir:"* ]]; then
    PATH_add "$alias_dir"
  fi

  echo "#!/usr/bin/env bash" > "$target"
  echo "PATH=\"$oldpath\"" >> "$target"
  echo "$@" >> "$target"
  chmod +x "$target"
}

Otherwise, you will have this kind of error when using Windows path:

<repo>/.direnv/aliases/tg: line 2: syntax error near unexpected token `('
<repo>/.direnv/aliases/tg: line 2: `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/Program Files/dotnet/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common'

Kind regards, JM

gotjoshua commented 1 year ago

as this is still open after centuries....

devenv handles this quite simply https://devenv.sh/scripts/

easily integrates with direnv for per repo/folder dev shell setups

quentinmit commented 1 year ago

devenv handles this quite simply https://devenv.sh/scripts/

easily integrates with direnv for per repo/folder dev shell setups

AFAICT, devenv's scripts defines new binaries it puts in PATH, and its enterShell hook gets run by direnv in the usual child process, so it doesn't have any more ability to set aliases than native direnv.

lindhe commented 1 year ago

I just wanted to pitch in saying that to me this is a complete deal breaker, so I'll have to move to another alternative. Have not looked into them yet, but probably autoenv or dotenv since they are native plugins in OMZ.

adrian-gierakowski commented 1 year ago

@lindhe unless you actually found a working alternative, posting messages like this is just noise for people watching this issue

lindhe commented 1 year ago

It might be useful for the devs to know that this drives people away from their (otherwise excellent) software.