pyv
This commit is contained in:
parent
58ce450595
commit
7628281e93
3 changed files with 195 additions and 1 deletions
29
README.md
29
README.md
|
@ -1,3 +1,30 @@
|
|||
# pyv
|
||||
|
||||
Wrapper for python-venv
|
||||
Wrapper for python-venv
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
git clone https://git.tavo.one/tavo/pyv.git ~/.local/share/pyv
|
||||
printf 'for f in pyv pyv_comp.bash ; do if [ -f ~/.local/share/pyv/$f ] ; then . ~/.local/share/pyv/$f ; fi ; done' >> ~/.bashrc
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`pyv [ls|new|rm|enter|exit] myvenv`
|
||||
|
||||
```sh
|
||||
pyv new v1 # create venv named v1
|
||||
pyv new v2 # create venv named v2
|
||||
pyv ls # list venvs
|
||||
pyv rm v2 # delete venv named v2
|
||||
pyv enter v1 # enter venv named v1
|
||||
pyv exit # exit current venv
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
```sh
|
||||
rm -rf ~/.local/share/pyv
|
||||
# Also remove corresponding line in ~/.bashrc
|
||||
```
|
||||
|
|
139
pyv
Normal file
139
pyv
Normal file
|
@ -0,0 +1,139 @@
|
|||
#!/bin/sh
|
||||
|
||||
_pyv_err() {
|
||||
printf '\033[91mError:\033[0m \033[2m%s\033[0m\n' "$1"
|
||||
}
|
||||
|
||||
_pyv_warn() {
|
||||
printf '\033[93mWarn:\033[0m \033[2m%s\033[0m\n' "$1"
|
||||
}
|
||||
|
||||
_pyv_log() {
|
||||
printf '\033[94mpyv:\033[0m \033[2m%s\033[0m\n' "$1"
|
||||
}
|
||||
|
||||
_pyv_help() {
|
||||
printf 'Usage:\n \033[92mpyv\033[0m \033[94m[ls|new|rm|enter|exit]\033[0m \033[95mmyvenv\033[0m\n'
|
||||
}
|
||||
|
||||
_pyv_avail() {
|
||||
venvs="$(for v in "$VENV_DIR"/* ; do
|
||||
if [ -d "$v" ] ; then
|
||||
if [ "$VIRTUAL_ENV" == "$v" ] ; then
|
||||
printf '\033[95m%s\033[0m, ' "*${v##*/}"
|
||||
else
|
||||
printf '\033[95m%s\033[0m, ' "${v##*/}"
|
||||
fi
|
||||
fi
|
||||
done)"
|
||||
venvs="${venvs%,*}"
|
||||
[ -n "$venvs" ] && printf 'Available venvs:\n %s\n' "$venvs"
|
||||
}
|
||||
|
||||
_pyv_prompt() {
|
||||
printf '%s [y/N]: ' "$1"
|
||||
read -r s
|
||||
case "$(echo "$s" | tr '[:upper:]' '[:lower:]')" in
|
||||
y|yes) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
pyv() {
|
||||
VENV_OPT=
|
||||
VENV_LIST=
|
||||
|
||||
PYTHON="${PYTHON:=$(command -v python 2>&-)}"
|
||||
PYTHON="${PYTHON:=$(command -v python3 2>&-)}"
|
||||
[ -z "$PYTHON" ] && _pyv_err "Could not find python in PATH" && return 1
|
||||
|
||||
if ! $PYTHON -m venv -h >&- 2>&- ; then
|
||||
_pyv_err "python-venv module not available" && return 1
|
||||
fi
|
||||
|
||||
if [ -z "$VENV_DIR" ] ; then
|
||||
if [ -n "$XDG_DATA_HOME" ] ; then
|
||||
VENV_DIR="$XDG_DATA_HOME/pyv"
|
||||
else
|
||||
[ -z "$HOME" ] && _pyv_err "No safe venv location" && return 1
|
||||
VENV_DIR="$HOME/.local/share/pyv"
|
||||
fi
|
||||
fi
|
||||
mkdir -p "$VENV_DIR"
|
||||
|
||||
case "$1" in
|
||||
new|enter|rm)
|
||||
VENV_OPT="$1" ; VENV_LIST="${@#${VENV_OPT}}" ; VENV_LIST="${VENV_LIST#* }" ;;
|
||||
-d)
|
||||
VENV_OPT="rm" ; VENV_LIST="${@#${VENV_OPT}}" ; VENV_LIST="${VENV_LIST#* }" ;;
|
||||
exit|quit|q)
|
||||
if command -v deactivate >&- 2>&- ; then
|
||||
_pyv_log "Deactivating venv ${VIRTUAL_ENV##*/}..."
|
||||
deactivate
|
||||
else
|
||||
_pyv_warn "No currently active venv"
|
||||
fi
|
||||
return 0 ;;
|
||||
-l*|--l*|l|ls|list)
|
||||
_pyv_avail
|
||||
return 0 ;;
|
||||
-*|help|h|"")
|
||||
_pyv_help
|
||||
avail="$(_pyv_avail)"
|
||||
[ -n "$avail" ] && printf '\n%s\n' "$avail"
|
||||
return 0 ;;
|
||||
*)
|
||||
VENV_OPT="enter" ; VENV_LIST="$@" ;;
|
||||
esac
|
||||
|
||||
for v in $VENV_LIST ; do
|
||||
if ! [ -d "$VENV_DIR/$v" ] && [ "$VENV_OPT" != "new" ] ; then
|
||||
_pyv_err "venv $v not found"
|
||||
VENV_LIST=
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$VENV_LIST" ] ; then
|
||||
_pyv_help
|
||||
echo
|
||||
_pyv_avail
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$VENV_OPT" == "new" ] ; then
|
||||
for v in $VENV_LIST ; do
|
||||
if [ -d "$VENV_DIR/$v" ] ; then
|
||||
_pyv_warn "venv $v already exists, skipping..."
|
||||
else
|
||||
_pyv_log "Creating new venv $v..."
|
||||
$PYTHON -m venv "$VENV_DIR/$v"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$VENV_OPT" == "rm" ] ; then
|
||||
for v in $VENV_LIST ; do
|
||||
if _pyv_prompt "Remove venv at '$VENV_DIR/$v'?" ; then
|
||||
_pyv_log "Removing venv $v..."
|
||||
rm -rf "$VENV_DIR/$v" && _pyv_log "Done"
|
||||
else
|
||||
_pyv_log "Keeping venv $v"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$VENV_OPT" == "enter" ] ; then
|
||||
command -v deactivate >&- 2>&- && deactivate
|
||||
venv="${VENV_LIST%% *}"
|
||||
_pyv_log "Activating $venv..."
|
||||
|
||||
case "${0##*/}" in
|
||||
bash|zsh|dash|ksh|sh)
|
||||
. "$VENV_DIR/$venv/bin/activate" ;;
|
||||
fish)
|
||||
source "$VENV_DIR/$venv/bin/activate.fish" ;;
|
||||
csh|tcsh)
|
||||
source "$VENV_DIR/$venv/bin/activate.csh" ;;
|
||||
esac
|
||||
fi
|
||||
}
|
28
pyv_comp.bash
Normal file
28
pyv_comp.bash
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
_pyv_comp() {
|
||||
if [ -z "$VENV_DIR" ] ; then
|
||||
if [ -n "$XDG_DATA_HOME" ] ; then
|
||||
VENV_DIR="$XDG_DATA_HOME/pyv"
|
||||
else
|
||||
[ -z "$HOME" ] && return 1
|
||||
VENV_DIR="$HOME/.local/share/pyv"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${#COMP_WORDS[@]}" == "2" ]; then
|
||||
COMPREPLY=($(compgen -W "ls new rm enter exit" "${COMP_WORDS[1]}"))
|
||||
fi
|
||||
|
||||
if [ "${#COMP_WORDS[@]}" -gt 2 ]; then
|
||||
venvs="$(for v in "$VENV_DIR"/* ; do
|
||||
if [ -d "$v" ] ; then
|
||||
printf '%s ' "${v##*/}"
|
||||
fi
|
||||
done)"
|
||||
venvs="${venvs% *}"
|
||||
COMPREPLY=($(compgen -W "$venvs" -- "${COMP_WORDS[-1]}"))
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _pyv_comp pyv
|
Loading…
Reference in a new issue