Skip to content

Commit 9116e84

Browse files
committed
Add "shell" subcommand for setting versions in shell session
Add a "shell" command similar to the existing "global" and "local" commands, which sets the version in an environment variable instead of writing it to a file. This was inspired by the similar functionality in rbenv. It works by adding a wrapper function for the asdf command. It forwards to a "sh-shell" command that returns the exports as shell code which is then evaled by the wrapper. This is a little gross, but we need to run the code in the shell context in order to set variables. Resolves asdf-vm#378
1 parent 9e30218 commit 9116e84

File tree

7 files changed

+122
-2
lines changed

7 files changed

+122
-2
lines changed

asdf.fish

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,18 @@ for x in $asdf_bin_dirs
1313
set -gx fish_user_paths $fish_user_paths $x
1414
end
1515
end
16+
17+
# Add function wrapper so we can export variables
18+
function asdf
19+
set command $argv[1]
20+
set -e argv[1]
21+
22+
switch "$command"
23+
case "shell"
24+
# eval commands that need to export variables
25+
source (env ASDF_SHELL=fish asdf "sh-$command" $argv | psub)
26+
case '*'
27+
# forward other commands to asdf script
28+
command asdf "$command" $argv
29+
end
30+
end

asdf.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ ASDF_USER_SHIMS="${ASDF_DATA_DIR:-$HOME/.asdf}/shims"
2323
PATH="${ASDF_BIN}:$PATH"
2424
PATH="${ASDF_USER_SHIMS}:$PATH"
2525

26+
# Add function wrapper so we can export variables
27+
asdf() {
28+
local command
29+
command="$1"
30+
if [ "$#" -gt 0 ]; then
31+
shift
32+
fi
33+
34+
case "$command" in
35+
"shell")
36+
# eval commands that need to export variables
37+
eval "$(asdf "sh-$command" "$@")";;
38+
*)
39+
# forward other commands to asdf script
40+
command asdf "$command" "$@";;
41+
42+
esac
43+
}
44+
2645
if [ -n "$ZSH_VERSION" ]; then
2746
autoload -U bashcompinit
2847
bashcompinit

bin/asdf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ case "$1" in
4646
load_cmd "current" "plugin-list"
4747
current_command "${cmd_args[@]}";;
4848

49+
"sh-shell")
50+
load_cmd "version_commands"
51+
shell_command "${cmd_args[@]}";;
52+
53+
"shell")
54+
echo "Shell integration is not enabled. Please ensure you source asdf in your shell setup."
55+
exit 1;;
56+
4957
"local")
5058
load_cmd "version_commands"
5159
local_command "${cmd_args[@]}";;

completions/asdf.bash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ _asdf () {
4646
# shellcheck disable=SC2207
4747
COMPREPLY=($(compgen -W "--head" -- "$cur"))
4848
;;
49-
uninstall|where|reshim|local|global)
49+
uninstall|where|reshim|local|global|shell)
5050
if [[ "$plugins" == *"$prev"* ]] ; then
5151
local versions
5252
versions=$(asdf list "$prev" 2> /dev/null)
@@ -58,7 +58,7 @@ _asdf () {
5858
fi
5959
;;
6060
*)
61-
local cmds='current global help install list list-all local plugin-add plugin-list plugin-list-all plugin-remove plugin-update reshim uninstall update where which '
61+
local cmds='current global help install list list-all local plugin-add plugin-list plugin-list-all plugin-remove plugin-update reshim shell uninstall update where which '
6262
# shellcheck disable=SC2207
6363
COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
6464
;;

completions/asdf.fish

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ complete -f -c asdf -n '__fish_asdf_needs_command' -a global -d "Set global vers
105105
complete -f -c asdf -n '__fish_asdf_using_command global; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)'
106106
complete -f -c asdf -n '__fish_asdf_using_command global; and test (count (commandline -opc)) -gt 2' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3)) system'
107107

108+
# shell completion
109+
complete -f -c asdf -n '__fish_asdf_needs_command' -a shell -d "Set version for a plugin in current shell session"
110+
complete -f -c asdf -n '__fish_asdf_using_command shell; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)'
111+
complete -f -c asdf -n '__fish_asdf_using_command shell; and test (count (commandline -opc)) -gt 2' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3)) system'
112+
108113
# misc
109114
complete -f -c asdf -n '__fish_asdf_needs_command' -l "help" -d "Displays help"
110115
complete -f -c asdf -n '__fish_asdf_needs_command' -l "version" -d "Displays asdf version"

lib/commands/version_commands.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,31 @@ global_command() {
7777
# shellcheck disable=2068
7878
version_command "global" $@
7979
}
80+
81+
# Output from this command must be executable shell code
82+
shell_command() {
83+
if [ "$#" -lt "2" ]; then
84+
echo "Usage: asdf shell <name> <version>" >&2
85+
echo 'false'
86+
exit 1
87+
fi
88+
89+
local plugin=$1
90+
local version=$2
91+
92+
if ! (check_if_version_exists "$plugin" "$version"); then
93+
echo 'false'
94+
exit 1
95+
fi
96+
97+
local upcase_name
98+
upcase_name=$(echo "$plugin" | tr '[:lower:]-' '[:upper:]_')
99+
local version_env_var="ASDF_${upcase_name}_VERSION"
100+
101+
case $ASDF_SHELL in
102+
fish )
103+
echo "set -gx $version_env_var \"$version\"";;
104+
* )
105+
echo "export $version_env_var=\"$version\"";;
106+
esac
107+
}

test/version_commands.bats

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,48 @@ teardown() {
230230
[ -L $HOME/.tool-versions ]
231231
[ "$(cat other-dir/.tool-versions)" = "dummy 1.1.0" ]
232232
}
233+
234+
@test "shell wrapper function should export ENV var" {
235+
source $(dirname "$BATS_TEST_DIRNAME")/asdf.sh
236+
asdf shell "dummy" "1.1.0"
237+
[ $(echo $ASDF_DUMMY_VERSION) = "1.1.0" ]
238+
unset ASDF_DUMMY_VERSION
239+
}
240+
241+
@test "shell wrapper function should return an error for missing plugins" {
242+
source $(dirname "$BATS_TEST_DIRNAME")/asdf.sh
243+
run asdf shell "nonexistent" "1.0.0"
244+
[ "$status" -eq 1 ]
245+
[ "$output" = "No such plugin: nonexistent" ]
246+
}
247+
248+
@test "shell should emit an error when wrapper function is not loaded" {
249+
run asdf shell "dummy" "1.1.0"
250+
echo $output
251+
[ "$status" -eq 1 ]
252+
[ "$output" = "Shell integration is not enabled. Please ensure you source asdf in your shell setup." ]
253+
}
254+
255+
@test "sh-shell should emit an error when plugin does not exist" {
256+
run asdf sh-shell "nonexistent" "1.0.0"
257+
[ "$status" -eq 1 ]
258+
[ "$output" = $'No such plugin: nonexistent\nfalse' ]
259+
}
260+
261+
@test "sh-shell should emit an error when version does not exist" {
262+
run asdf sh-shell "dummy" "nonexistent"
263+
[ "$status" -eq 1 ]
264+
[ "$output" = $'version nonexistent is not installed for dummy\nfalse' ]
265+
}
266+
267+
@test "sh-shell should export version if it exists" {
268+
run asdf sh-shell "dummy" "1.1.0"
269+
[ "$status" -eq 0 ]
270+
[ "$output" = "export ASDF_DUMMY_VERSION=\"1.1.0\"" ]
271+
}
272+
273+
@test "sh-shell should use set when shell is fish" {
274+
ASDF_SHELL=fish run asdf sh-shell "dummy" "1.1.0"
275+
[ "$status" -eq 0 ]
276+
[ "$output" = "set -gx ASDF_DUMMY_VERSION \"1.1.0\"" ]
277+
}

0 commit comments

Comments
 (0)