Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Elvish Shell support #1066

Merged
merged 34 commits into from Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1af3e99
feat: Elvish Shell support
elijahr Oct 8, 2021
e8e631c
Fix asdf.elv, add install docs
elijahr Oct 9, 2021
6e8cf29
Update docs and tests
elijahr Oct 9, 2021
242b88d
fix shellcheck issues
elijahr Oct 9, 2021
6baada0
Fix tests
elijahr Oct 9, 2021
2b034c9
Fix test
elijahr Oct 9, 2021
5bb00bb
Fix other test
elijahr Oct 9, 2021
1f1f570
Fix tests on older elvish
elijahr Oct 9, 2021
dfdb59c
Fix test
elijahr Oct 9, 2021
8f7ea81
Install newer elvish
elijahr Oct 9, 2021
b05968f
Fix test
elijahr Oct 9, 2021
8c7fb68
Add test for running command
elijahr Oct 9, 2021
7cabf9b
Add test for running asdf subcommands
elijahr Oct 9, 2021
1a15a53
Linter
elijahr Oct 9, 2021
5186c1a
Remove command keyword
elijahr Oct 9, 2021
cec89d7
Fix test
elijahr Oct 9, 2021
6b49ba2
Fix test
elijahr Oct 9, 2021
207f1c1
-norc
elijahr Oct 9, 2021
384f450
Add completions
elijahr Oct 9, 2021
02069ff
Fix test
elijahr Oct 9, 2021
9ba6749
Single module for asdf function & completions
elijahr Oct 9, 2021
1295224
Fix uninstall instructions
elijahr Oct 9, 2021
84f073a
Cleanup debug code
elijahr Oct 9, 2021
2c9529b
Comments
elijahr Oct 9, 2021
f871425
Fix completer in unit tests
elijahr Oct 9, 2021
fa84123
Add unit test for ASDF_DATA_DIR
elijahr Oct 9, 2021
9036d91
Revert change in command-info.bash
elijahr Oct 9, 2021
ab495ff
Fix installation instructions
elijahr Oct 9, 2021
0b006ed
Add flags
elijahr Oct 10, 2021
4383fbe
Ignore downloads dir
elijahr Oct 10, 2021
624949c
Use regex for matching
elijahr Oct 10, 2021
0b41485
Add plugin-test completion
elijahr Oct 10, 2021
e697aab
Format string
elijahr Nov 13, 2021
2538279
Download elvish binary
elijahr Nov 13, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Expand Up @@ -22,6 +22,7 @@
*.sh text
*.bash text
*.fish text
*.elv text
#### asdf/bin/* explicitly define as text
*asdf text
*asdf-exec text
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/tests.yml
Expand Up @@ -28,15 +28,22 @@ jobs:

- name: Install test dependencies
if: runner.os == 'macos'
run: brew install coreutils fish
run: brew install coreutils fish elvish

- name: Install test dependencies
if: runner.os == 'linux'
run: |
PPA="ppa:fish-shell/nightly-master"
sudo add-apt-repository -y "$PPA"
sudo add-apt-repository -y ppa:fish-shell/nightly-master
sudo apt-get update
sudo apt-get -y install fish
sudo apt-get -y install fish curl

# Download elvish binary and add to path
curl https://dl.elv.sh/linux-amd64/elvish-v0.16.3.tar.gz -o elvish-v0.16.3.tar.gz
tar xzf elvish-v0.16.3.tar.gz
rm elvish-v0.16.3.tar.gz
mkdir -p "$HOME/bin"
mv elvish-v0.16.3 "$HOME/bin/elvish"
echo "$HOME/bin" >>"$GITHUB_PATH"

- name: Install bats
run: |
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
@@ -1,6 +1,7 @@
installs
/installs
/downloads
/plugins
shims
/shims
Comment on lines +1 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How were you testing that required these changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added /downloads because that directory gets populated by a call to asdf install with the --keep-download flag.

asdf install nim 1.4.8 --keep-download

I added leading slashes to the other entries because https://stackoverflow.com/a/38433961:

the leading slash anchors the match to the root

My understanding is that this makes sure other, nested items with the same name won't be excluded.

repository
.vagrant
keyrings
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -13,7 +13,7 @@ asdf is a CLI tool that can manage multiple language runtime versions on a per-p
- support for existing config files `.node-version`, `.nvmrc`, `.ruby-version` for easy migration
- automatically switches runtime versions as you traverse your directories
- simple plugin system to add support for your language of choice
- shell completion available for common shells (Bash, Zsh, Fish)
- shell completion available for common shells (Bash, Zsh, Fish, Elvish)

## Documentation

Expand Down
244 changes: 244 additions & 0 deletions asdf.elv
@@ -0,0 +1,244 @@

use re
use str
use path

var asdf_dir = $E:HOME'/.asdf'
if (and (has-env ASDF_DIR) (!=s $E:ASDF_DIR '')) {
asdf_dir = $E:ASDF_DIR
} else {
set-env ASDF_DIR $asdf_dir
}

var asdf_data_dir = $asdf_dir
if (and (has-env ASDF_DATA_DIR) (!=s $E:ASDF_DATA_DIR '')) {
asdf_data_dir = $E:ASDF_DATA_DIR
}

# Add function wrapper so we can export variables
fn asdf [command @args]{
if (==s $command 'shell') {
# set environment variables
parts = [($asdf_dir'/bin/asdf' export-shell-version elvish $@args)]
if (==s $parts[0] 'set-env') {
set-env $parts[1] $parts[2]
} elif (==s $parts[0] 'unset-env') {
unset-env $parts[1]
}
} else {
# forward other commands to asdf script
$asdf_dir'/bin/asdf' $command $@args
}
}

fn match [argz @pats]{
var matched = $true;
if (!= (count $argz) (count $pats)) {
matched = $false
} else {
for i [(range (count $pats))] {
pat = '^'$pats[$i]'$'
arg = $argz[$i]
if (not (re:match $pat $arg)) {
matched = $false
break
}
}
}
put $matched
}

fn ls-shims []{
ls $asdf_data_dir'/shims'
}

fn ls-executables []{
# Print all executable files and links in path
try {
find $@paths '(' -type f -o -type l ')' -print 2>/dev/null | each [p]{
try {
if (test -x $p) {
path:base $p
}
} except {
# don't fail if permission denied
}
}
} except {
# silence default non-zero exit status
}
}

fn ls-installed-versions [plugin_name]{
asdf list $plugin_name | each [version]{
put (re:replace '\s*(.*)\s*' '${1}' $version)
}
}

fn ls-all-versions [plugin_name]{
asdf list-all $plugin_name | each [version]{
put (re:replace '\s*(.*)\s*' '${1}' $version)
}
}

# Append ~/.asdf/bin and ~/.asdf/shims to PATH
for path [
$asdf_dir'/bin'
$asdf_data_dir'/shims'
] {
if (not (has-value $paths $path)) {
paths = [
$@paths
$path
]
}
}

# Setup argument completions
fn arg-completer [@argz]{
argz = $argz[1:-1] # strip 'asdf' and trailing empty string
var num = (count $argz)
if (== $num 0) {
# list all subcommands
find $asdf_dir'/lib/commands' -name 'command-*' | each [cmd]{
put (re:replace '.*/command-(.*)\.bash' '${1}' $cmd)
}
put 'plugin'
} else {
if (match $argz 'current') {
# asdf current <name>
asdf plugin-list
} elif (match $argz 'env') {
# asdf env <command>
ls-shims
} elif (match $argz 'env' '.*') {
# asdf env <command> [util]
ls-executables
} elif (match $argz 'exec') {
# asdf exec <command>
ls-shims
} elif (match $argz 'global') {
# asdf global <name>
asdf plugin-list
} elif (match $argz 'global' '.*') {
# asdf global <name> <version>
ls-installed-versions $argz[-1]
} elif (match $argz 'install') {
# asdf install <name>
asdf plugin-list
} elif (match $argz 'install' '.*') {
# asdf install <name> <version>
ls-all-versions $argz[-1]
} elif (match $argz 'install' '.*' '.*') {
# asdf install <name> <version> [--keep-download]
put '--keep-download'
} elif (match $argz 'latest') {
# asdf latest <name>
asdf plugin-list
} elif (match $argz 'latest' '.*') {
# asdf latest <name> [<version>]
ls-all-versions $argz[-1]
} elif (match $argz 'list-all') {
# asdf list all <name>
asdf plugin-list
} elif (match $argz 'list-all' '.*') {
# asdf list all <name> [<version>]
ls-all-versions $argz[-1]
} elif (match $argz 'list') {
# asdf list <name>
asdf plugin-list
} elif (match $argz 'list' '.*') {
# asdf list <name> [<version>]
ls-installed-versions $argz[-1]
} elif (match $argz 'local') {
# asdf local <name> [-p|--parent]
asdf plugin-list
put '-p'
put '--parent'
} elif (match $argz 'local' '(-p|(--parent))') {
# asdf local <name> [-p|--parent] <version>
asdf plugin-list
} elif (match $argz 'local' '.*') {
# asdf local <name> [-p|--parent]
# asdf local <name> <version>
ls-installed-versions $argz[-1]
put '-p'
put '--parent'
} elif (match $argz 'local' '(-p|(--parent))' '.*') {
# asdf local [-p|--parent] <name> <version>
ls-installed-versions $argz[-1]
} elif (match $argz 'local' '.*' '(-p|(--parent))') {
# asdf local <name> [-p|--parent] <version>
ls-installed-versions $argz[-2]
} elif (match $argz 'local' '.*' '.*') {
# asdf local <name> <version> [-p|--parent]
put '-p'
put '--parent'
} elif (or (match $argz 'plugin-add') (match $argz 'plugin' 'add')) {
# asdf plugin add <name>
asdf plugin-list-all | each [line]{
put (re:replace '([^\s]+)\s+.*' '${1}' $line)
}
} elif (or (match $argz 'plugin-list') (match $argz 'plugin' 'list')) {
# asdf plugin list
put '--urls'
put '--refs'
put 'all'
} elif (or (match $argz 'plugin-push') (match $argz 'plugin' 'push')) {
# asdf plugin push <name>
asdf plugin-list
} elif (or (match $argz 'plugin-remove') (match $argz 'plugin' 'remove')) {
# asdf plugin remove <name>
asdf plugin-list
} elif (and (>= (count $argz) 3) (match $argz[:3] 'plugin-test' '.*' '.*')) {
# asdf plugin-test <plugin-name> <plugin-url> [--asdf-tool-version <version>] [--asdf-plugin-gitref <git-ref>] [test-command*]
put '--asdf-plugin-gitref'
put '--asdf-tool-version'
ls-executables
ls-shims
} elif (and (>= (count $argz) 4) (match $argz[:4] 'plugin' 'test' '.*' '.*')) {
# asdf plugin test <plugin-name> <plugin-url> [--asdf-tool-version <version>] [--asdf-plugin-gitref <git-ref>] [test-command*]
put '--asdf-plugin-gitref'
put '--asdf-tool-version'
ls-executables
ls-shims
} elif (or (match $argz 'plugin-update') (match $argz 'plugin' 'update')) {
# asdf plugin update <name>
asdf plugin-list
put '--all'
} elif (match $argz 'plugin') {
# list plugin-* subcommands
find $asdf_dir'/lib/commands' -name 'command-plugin-*' | each [cmd]{
put (re:replace '.*/command-plugin-(.*)\.bash' '${1}' $cmd)
}
} elif (match $argz 'reshim') {
# asdf reshim <name>
asdf plugin-list
} elif (match $argz 'reshim' '.*') {
# asdf reshim <name> <version>
ls-installed-versions $argz[-1]
} elif (match $argz 'shim-versions') {
# asdf shim-versions <command>
ls-shims
} elif (match $argz 'uninstall') {
# asdf uninstall <name>
asdf plugin-list
} elif (match $argz 'uninstall' '.*') {
# asdf uninstall <name> <version>
ls-installed-versions $argz[-1]
} elif (match $argz 'update') {
if (== $num 1) {
# asdf update
put '--head'
}
} elif (match $argz 'where') {
# asdf where <name>
asdf plugin-list
} elif (match $argz 'where' '.*') {
# asdf where <name> [<version>]
ls-installed-versions $argz[-1]
} elif (match $argz 'which') {
ls-shims
}
}
}
4 changes: 2 additions & 2 deletions asdf.fish
Expand Up @@ -2,9 +2,9 @@ set -x ASDF_DIR (dirname (status -f))

set -l asdf_user_shims (
if test -n "$ASDF_DATA_DIR"
echo $ASDF_DATA_DIR/shims
printf "%s\n" "$ASDF_DATA_DIR/shims"
else
echo $HOME/.asdf/shims
printf "%s\n" "$HOME/.asdf/shims"
end
)

Expand Down
2 changes: 1 addition & 1 deletion asdf.sh
Expand Up @@ -14,7 +14,7 @@ fi
export ASDF_DIR
ASDF_DIR="$(dirname "$current_script_path")"
# shellcheck disable=SC2016
[ -d "$ASDF_DIR" ] || echo '$ASDF_DIR is not a directory'
[ -d "$ASDF_DIR" ] || printf '$ASDF_DIR is not a directory'

# Add asdf to PATH
#
Expand Down
40 changes: 40 additions & 0 deletions docs/guide/getting-started.md
Expand Up @@ -142,6 +142,46 @@ source /opt/asdf-vm/asdf.fish
Completions are automatically configured on installation by the AUR package.
:::

::: details Elvish & Git

Add `asdf.elv` to your `~/.elvish/rc.elv` with:

```shell:no-line-numbers
mkdir -p ~/.elvish/lib; ln -s ~/.asdf/asdf.elv ~/.elvish/lib/asdf.elv
echo "\n"'use asdf _asdf; fn asdf [@args]{_asdf:asdf $@args}' >> ~/.elvish/rc.elv
echo "\n"'edit:completion:arg-completer[asdf] = $_asdf:arg-completer~' >> ~/.elvish/rc.elv
```

Completions are automatically configured.

:::

::: details Elvish & Homebrew

Add `asdf.elv` to your `~/.elvish/rc.elv` with:

```shell:no-line-numbers
mkdir -p ~/.elvish/lib; ln -s (brew --prefix asdf)/libexec/asdf.elv ~/.elvish/lib/asdf.elv
echo "\n"'use asdf _asdf; fn asdf [@args]{_asdf:asdf $@args}' >> ~/.elvish/rc.elv
echo "\n"'edit:completion:arg-completer[asdf] = $_asdf:arg-completer~' >> ~/.elvish/rc.elv
```

Completions are automatically configured.
:::

::: details Elvish & Pacman

Add `asdf.elv` to your `~/.elvish/rc.elv` with:

```shell:no-line-numbers
mkdir -p ~/.elvish/lib; ln -s /opt/asdf-vm/asdf.elv ~/.elvish/lib/asdf.elv
echo "\n"'use asdf _asdf; fn asdf [@args]{_asdf:asdf $@args}' >> ~/.elvish/rc.elv
echo "\n"'edit:completion:arg-completer[asdf] = $_asdf:arg-completer~' >> ~/.elvish/rc.elv
```

Completions are automatically configured.
:::

::: details ZSH & Git

Add the following to `~/.zshrc`:
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Expand Up @@ -19,7 +19,7 @@ features:
- title: "One Config File"
details: ".tool-versions to manage all your tools, runtimes and their versions in a single, sharable place."
- title: "Shells"
details: "Supports Bash, ZSH & Fish with completions available."
details: "Supports Bash, ZSH, Fish & Elvish with completions available."
- title: "GitHub Actions"
details: "Provides a GitHub Action to install and utilize your .tool-versions in your CI/CD workflows."
# footer: MIT Licensed
Expand Down
2 changes: 1 addition & 1 deletion docs/manage/configuration.md
Expand Up @@ -93,7 +93,7 @@ Configure the duration since the last asdf plugin repository sync to the next. C
- `ASDF_CONFIG_FILE` - Defaults to `~/.asdfrc` as described above. Can be set to any location.
- `ASDF_DEFAULT_TOOL_VERSIONS_FILENAME` - The filename of the file storing the tool names and versions. Defaults to `.tool-versions`. Can be any valid filename. Typically you should not override the default value unless you know you want asdf to ignore `.tool-versions` files.
- `ASDF_DIR` - Defaults to `~/.asdf` - Location of the `asdf` scripts. If you install `asdf` to some other directory, set this to that directory. For example, if you are installing via the AUR, you should set this to `/opt/asdf-vm`.
- `ASDF_DATA_DIR` - Defaults to `~/.asdf` - Location where `asdf` install plugins, shims and installs. Can be set to any location before sourcing `asdf.sh` or `asdf.fish` mentioned in the section above.
- `ASDF_DATA_DIR` - Defaults to `~/.asdf` - Location where `asdf` install plugins, shims and installs. Can be set to any location before sourcing `asdf.sh` or `asdf.fish` mentioned in the section above. For Elvish, this can be set above `use asdf`.

## Internal Configuration

Expand Down