diff --git a/README.md b/README.md index bf1756e..68f7060 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,25 @@ How verbosely to report program actions - 2 general (default) - `>2` debug +## Activating and Deactivating wrapped environments +A `tykky` convenience shell function is provided to mimic the conda activate and +deactivate helpers. To use it, you must load those functions into your shell with: + +`source etc/profile.d/tykky` + +Then you may activate a tykky installation with + +`tykky activate ` + +If you define the environment variable `TYKKY_PATH`, environments may also be +found by name inside that colon-separated list of paths in `TYKKY_PATH`. + +You may deactivate the tykky environment in your shell with: + +`tykky deactivate` + +Alternatively, you may also manually add `/bin` to your `$PATH`. + ## Misc features ideas diff --git a/etc/bash_completion.d/tykky_completion b/etc/bash_completion.d/tykky_completion new file mode 100644 index 0000000..fabab84 --- /dev/null +++ b/etc/bash_completion.d/tykky_completion @@ -0,0 +1,36 @@ +__tykky_completions() { + if [ "${#COMP_WORDS[@]}" == "2" ]; then + COMPREPLY=($(compgen -W "activate deactivate" "${COMP_WORDS[1]}")) + return + fi + if [[ ${#COMP_WORDS[@]} -gt 2 ]]; then + if [[ "${COMP_WORDS[1]}" == "activate" && "${COMP_WORDS[2]}" != *"/"* ]]; then + local __tykky_env_list="" + local __tykky_path __candidate + local oldIFS=$IFS + IFS=: + for __tykky_path in ${TYKKY_PATH:-~/.tykky}; do + IFS=$oldIFS + for __candidate in $__tykky_path/*; do + if [[ -d "$__candidate" && -f "$__candidate/common.sh" && -d "$__candidate/bin" ]]; then + __tykky_env_list+="$(basename $__candidate) " + fi + done + done + COMPREPLY=($(compgen -W "$__tykky_env_list" "${COMP_WORDS[2]}")) + return + elif [[ "${COMP_WORDS[1]}" == "activate" && "${COMP_WORDS[2]}" == *"/"* ]]; then + COMPREPLY=( $(compgen -d -- "${COMP_WORDS[2]}") ) + local i + for i in "${!COMPREPLY[@]}"; do + if [[ -d "${COMPREPLY[$i]}" && ! -f "${COMPREPLY[$i]}/common.sh" && ! -d "${COMPREPLY[$i]}/bin" ]]; then + COMPREPLY[$i]="${COMPREPLY[$i]}/" + fi + done + compopt -o nospace + fi + fi + return +} + +complete -F __tykky_completions tykky diff --git a/etc/profile.d/tykky.sh b/etc/profile.d/tykky.sh new file mode 100644 index 0000000..1e55baf --- /dev/null +++ b/etc/profile.d/tykky.sh @@ -0,0 +1,42 @@ +# Tykky shell functions to activate/deactivate environments + +__tykky_dir="" +if [ -n "${BASH_SOURCE:-}" ]; then + __tykky_dir="$(dirname "${BASH_SOURCE[0]}")" +elif [ -n "${ZSH_VERSION:-}" ]; then + __tykky_dir="$(dirname "${(%):-%N}")" +elif [ -n "${KSH_VERSION:-}" ]; then + __tykky_dir="$(dirname "${.sh.file}")" +else + # Generic POSIX shell case or dash + __tykky_dir="$(dirname "$0")" +fi + +__tykky_dir="$(realpath $(dirname $(dirname "$__tykky_dir")))" + +# Add the tykky tools to PATH if not present +if [ "${PATH#*$__tykky_dir/bin:}" = "$PATH" ]; then + export PATH="$__tykky_dir/bin:$PATH" +fi + +# Make available tykky functions for this shell and subshells +for __function in $__tykky_dir/share/sh_functions/*; do + source $__function + if [ -z "$KSH_VERSION" ]; then + export -f $(basename $__function) + fi +done +unset __function + +# KSH does not support exporting functions +if [ "${FPATH#*$__tykky_dir/share/sh_functions:}" = "$FPATH" ]; then + export FPATH="$__tykky_dir/share/sh_functions:$FPATH" +fi + +# Enable BASH autocompletion +if [ -n "${BASH_VERSIONi:-}" ] && [ -n "${PS1:-}" ]; then + __tykky_bash_completion_file="$_tykky_dir/etc/bash_completion.d/tykky_completion" + [ -f "$__tykky_bash_completion_file" ] && . "$__tykky_bash_completion_file" + unset __tykky_bash_completion_file +fi +unset __tykky_dir diff --git a/frontends/containerize b/frontends/containerize index f6259f4..106021f 100755 --- a/frontends/containerize +++ b/frontends/containerize @@ -124,8 +124,27 @@ fi $M_SCRIPT_DIR/../post.sh || { print_err "Failed to move to install dir"; false ; } test -f "$_usr_yaml" && rm "$_usr_yaml" end=`date +%s` -print_info "Done, duration: $((end-start))s" 1 -print_info "Program has been installed to $CW_INSTALLATION_PREFIX -\tTo use add the bin folder to your path e.g: -\texport PATH=\"$_inst_path/bin:\$PATH\"" 1 + +if command -v tykky &>/dev/null ; then + _env_root=$(realpath $(dirname $_inst_path)) + _env_name=$CW_INSTALLATION_PREFIX + IFS=':' read -r -a _paths <<< "${TYKKY_PATH:-$HOME/.tykky}" + for _path in "${_paths[@]}"; do + if [ "$_env_root" = "$(realpath $_path)" ]; then + _env_name=$(basename $CW_INSTALLATION_PREFIX) + break + fi + done + info_msg="Environment has been installed to $CW_INSTALLATION_PREFIX +\tTo use, activate with: +\ttykky activate $_env_name +\tAlternatively, add the bin folder to your path e.g: +\texport PATH=\"$_inst_path/bin:\$PATH\"" +else + info_msg="Program has been installed to $CW_INSTALLATION_PREFIX +\tTo use add the bin folder to your path e.g: +\texport PATH=\"$_inst_path/bin:\$PATH\"" +fi +print_info "Done, duration: $((end-start))s" 1 +print_info "$info_msg" 1 diff --git a/share/sh_functions/__tykky_activate b/share/sh_functions/__tykky_activate new file mode 100644 index 0000000..521b345 --- /dev/null +++ b/share/sh_functions/__tykky_activate @@ -0,0 +1,25 @@ +# Tykky shell functions to activate/deactivate environments +__tykky_activate() { + # Activate a Tykky environment. Change PS1 if interactive by default, + # unless TYKKY_CHANGE_PS1 is set to 0 + + if [ -z "${2:-}" ]; then + echo "ERROR: You must specify a valid tykky environment to activate" >&2 + false + return + fi + __candidate=$(__tykky_get_env_path $2) + if [ "$?" -ne 0 ]; then + false + return + fi + if [ -n "$__candidate" ]; then + __tykky_deactivate + export TYKKY_PREFIX="$(realpath $__candidate)" + export PATH=$TYKKY_PREFIX/bin:$PATH + if [ -n "${PS1:-}" ] && [ "${TYKKY_CHANGE_PS1:-}" != "0" ]; then + PS1="($(basename $(echo $TYKKY_PREFIX))) $PS1" + fi + fi + unset __candidate +} diff --git a/share/sh_functions/__tykky_deactivate b/share/sh_functions/__tykky_deactivate new file mode 100644 index 0000000..560d4bb --- /dev/null +++ b/share/sh_functions/__tykky_deactivate @@ -0,0 +1,13 @@ +# Tykky shell functions to activate/deactivate environments +__tykky_deactivate() { + # Deactivate a Tykky environment. Change PS1 if interactive by default, + + if [ -n "${TYKKY_PREFIX:-}" ]; then + export PATH=$(echo $PATH | sed -e "s|$TYKKY_PREFIX/bin:||g") + if [ -n "${PS1:-}" ]; then + PS1="$(echo "$PS1" | sed -e "s|^($(basename $TYKKY_PREFIX)) ||")" + fi + unset TYKKY_PREFIX + fi +} + diff --git a/share/sh_functions/__tykky_get_env_path b/share/sh_functions/__tykky_get_env_path new file mode 100644 index 0000000..686954a --- /dev/null +++ b/share/sh_functions/__tykky_get_env_path @@ -0,0 +1,68 @@ +# Tykky shell functions to activate/deactivate environments +__tykky_get_env_path() { + # Get and validate installation path of a tykky environment. + # If a name is passed as an argument, try to find it in colon-separated + # list TYKKY_PATH + + __candidate="" + case "$1" in + */*) + __candidate="${1%/}" + ;; + *) + oldIFS=$IFS + IFS=: + for __tykky_path in ${TYKKY_PATH:-""}; do + IFS=$oldIFS + if [ -d "$__tykky_path/$1" ]; then + if [ -n "$__candidate" ]; then + echo "WARNING: Additional candidate tykky environments found in TYKKY_PATH for $1, only the first one will be considered" >&2 + echo -e "\tfirst candidate: $__candidate" >&2 + echo -e "\tnew candidate: $__tykky_path/$1" >&2 + else + __candidate="${__tykky_path%/}/${1%/}" + fi + #break + fi + done + if [ -d "$1" ];then + # If there is a matching foldername in the current directory + # and the name does not match anyhing in tykky_path, also test that for convinience + # this is to be consistent with that the first case allows relative paths + # so then relative paths in the current directory withouth / should also work + if [ -z "$__candidate" ];then + __candidate=$PWD/$1 + + # Ambiguous reference as we might have multiple matches + else + _tp_candidate=$(readlink -f $__candidate) + _d_candidate=$(readlink -f $1) + # if same folder let's not emit a warning + # following pseudo standard -> command line arguments override environment settings + if [ ! "$_tp_candidate" = "$_d_candidate" ];then + echo "WARNING: Multiple candidate tykky environments for $1, activating the one in the current directory" >&2 + echo -e "\tfrom TYKKY_PATH: $_tp_candidate" >&2 + echo -e "\tfrom current directory: $_d_candidate" >&2 + fi + + fi + fi + + ;; + esac + + # Validation of genunine tykky installation + if [ -f "$__candidate/common.sh" ] && [ -d "$__candidate/bin" ]; then + echo "$__candidate" + unset __candidate __tykky_path + else + unset __candidate __tykky_path + echo "ERROR: $1 is not a valid tykky environment" >&2 + if [ ! -d "$1" ] ; then + echo -e "\t$1 does not exists or parent folder is not in TYKKY_PATH" >&2 + echo -e "\tCurrent value: TYKKY_PATH=$TYKKY_PATH" >&2 + fi + false + fi + +} diff --git a/share/sh_functions/tykky b/share/sh_functions/tykky new file mode 100644 index 0000000..0285671 --- /dev/null +++ b/share/sh_functions/tykky @@ -0,0 +1,17 @@ +# Tykky shell functions to activate/deactivate environments +tykky() { + # Top level shell function to activate and deactivate Tykky environments + + case "${1:-}" in + activate) + __tykky_activate "$@" + ;; + deactivate) + __tykky_deactivate "$@" + ;; + *) + echo "Usage: tykky activate " + echo " tykky deactivate" + ;; + esac +}