Files
.config/fish/functions/env.fish

486 lines
15 KiB
Fish

# Environment management system configuration
set -g __ENV_BASE_DIR "$HOME/.config/fish/environments"
set -g __ENV_CONFIGS_DIR "$__ENV_BASE_DIR/configs"
set -g __ENV_TEMPLATES_DIR "$__ENV_BASE_DIR/templates"
function env -d "Environment management system"
set -l subcommand $argv[1]
if test -z "$subcommand"
__env_help
return 0
end
switch $subcommand
case create new
__env_create $argv[2..]
case list ls
__env_list $argv[2..]
case activate use
__env_activate $argv[2..]
case deactivate exit
__env_deactivate $argv[2..]
case remove rm delete
__env_remove $argv[2..]
case link ln
__env_link $argv[2..]
case info show
__env_info $argv[2..]
case edit
__env_edit $argv[2..]
case copy clone
__env_copy $argv[2..]
case export
__env_export $argv[2..]
case help h --help -h
__env_help $argv[2..]
case "*"
echo (set_color red)"'$subcommand': Unknown subcommand (see env help)"(set_color normal)
return 1
end
end
# Internal functions (prefixed with __ to indicate they're private)
function __env_help -d "Show help for env command"
echo (set_color blue)"Environment Management System"(set_color normal)
echo
echo "usage: env <subcommand> [options]"
echo
echo (set_color green)"Subcommands:"(set_color normal)
echo " create, new <name> [template] Create a new environment"
echo " list, ls List all environments"
echo " activate, use <name> Activate an environment"
echo " deactivate, exit Deactivate current environment"
echo " remove, rm <name> Remove an environment"
echo " link, ln <name> [dir] Link environment to directory"
echo " info, show <name> Show environment information"
echo " edit <name> Edit environment configuration"
echo " copy, clone <src> <dest> Copy an environment"
echo " export <name> [dir] Export environment to directory"
echo " help, h Show this help"
echo
echo (set_color green)"Templates:"(set_color normal)
__env_list_templates
echo
echo (set_color green)"Examples:"(set_color normal)
echo " env create myproject python # Create Python environment"
echo " env activate myproject # Activate environment"
echo " env link myproject ./myapp # Link to directory"
echo " env export myproject ./myapp # Export self-contained env to directory"
echo " env list # Show all environments"
echo " env deactivate # Deactivate current environment"
end
function __env_create -d "Create a new environment"
set -l env_name $argv[1]
set -l template_type $argv[2]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env create <name> [template]"
echo "available templates:"
__env_list_templates
return 1
end
if test -z "$template_type"
set template_type basic
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l template_file "$__ENV_TEMPLATES_DIR/$template_type.fish"
if test -d "$env_dir"
echo (set_color yellow)"'$env_name': environment already exists"(set_color normal)
return 1
end
if not test -f "$template_file"
echo (set_color red)"'$template_type': template not found"(set_color normal)
echo "Available templates:"
__env_list_templates
return 1
end
# Create environment directory
mkdir -p "$env_dir"
# Copy template and customize
sed "s/{{ENV_NAME}}/$env_name/g" "$template_file" >"$env_dir/activate.fish"
chmod +x "$env_dir/activate.fish"
# Create environment config file
echo "# Environment: $env_name" >"$env_dir/config.toml"
echo "name = \"$env_name\"" >>"$env_dir/config.toml"
echo "template = \"$template_type\"" >>"$env_dir/config.toml"
echo "created = \"$(date --iso-8601)\"" >>"$env_dir/config.toml"
echo "# Add custom environment variables here" >>"$env_dir/config.toml"
echo "# [env]" >>"$env_dir/config.toml"
echo "# CUSTOM_VAR = \"value\"" >>"$env_dir/config.toml"
echo (set_color green)"environment '$env_name' ($template_type) created"(set_color normal)
echo "environment directory: $env_dir"
echo "to activate: env activate $env_name"
end
function __env_list -d "List all available environments"
set -l env_dir "$__ENV_CONFIGS_DIR"
if not test -d "$env_dir"
echo (set_color yellow)"no environments found"(set_color normal)
return 0
end
# Check if directory exists but is empty
set -l env_count (count $env_dir/*)
if test $env_count -eq 0
echo (set_color yellow)"no environments found"(set_color normal)
return 0
end
echo (set_color blue)"available environments:"(set_color normal)
echo
for env_path in $env_dir/*
if test -d "$env_path"
set env_name (basename "$env_path")
set config_file "$env_path/config.toml"
if test -f "$config_file"
set template (grep "template =" "$config_file" | cut -d'"' -f2)
set created (grep "created =" "$config_file" | cut -d'"' -f2)
echo (set_color green)" $env_name"(set_color normal)" (template: $template, created: $created)"
else
echo (set_color green)" $env_name"(set_color normal)" (no config found)"
end
end
end
if test -n "$CURRENT_ENV"
echo
echo (set_color cyan)"'$CURRENT_ENV': currently active"(set_color normal)
end
end
function __env_activate -d "Activate an environment"
set -l env_name $argv[1]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env activate <name>"
echo "available environments:"
__env_list
return 1
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l activate_file "$env_dir/activate.fish"
if not test -f "$activate_file"
echo (set_color red)"'$env_name': environment not found"(set_color normal)
echo "available environments:"
__env_list
return 1
end
# Check if another environment is already active
if test -n "$CURRENT_ENV"
echo (set_color yellow)"'$CURRENT_ENV': deactivating current environment"(set_color normal)
__env_deactivate
end
echo (set_color green)"'$env_name': activating environment"(set_color normal)
source "$activate_file"
end
function __env_deactivate -d "Deactivate the current environment"
if test -z "$CURRENT_ENV"
echo (set_color yellow)"no environment currently active"(set_color normal)
return 0
end
echo (set_color blue)"'$CURRENT_ENV': deactivating environment"(set_color normal)
# Restore original prompt if it was saved
if functions -q __env_orig_prompt
# Remove current fish_prompt first, then restore the original
functions -e fish_prompt
functions -c __env_orig_prompt fish_prompt
functions -e __env_orig_prompt
end
# Clear environment-specific variables
set -e CURRENT_ENV
set -e __ENV_INITIALIZED
# Call custom deactivation function if it exists
if functions -q __env_custom_deactivate
__env_custom_deactivate
functions -e __env_custom_deactivate
end
echo (set_color green)"environment deactivated"(set_color normal)
end
function __env_remove -d "Remove an environment"
set -l env_name $argv[1]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env remove <name>"
return 1
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
if not test -d "$env_dir"
echo (set_color red)"'$env_name': environment not found"(set_color normal)
return 1
end
# Check if this environment is currently active
if test "$CURRENT_ENV" = "$env_name"
echo (set_color yellow)"deactivating environment before removal..."(set_color normal)
__env_deactivate
end
# Confirm removal
echo (set_color yellow)"are you sure you want to remove environment '$env_name'? [y/N]"(set_color normal)
read -l confirm
if test "$confirm" = y -o "$confirm" = Y
rm -rf "$env_dir"
echo (set_color green)"Environment '$env_name' removed"(set_color normal)
else
echo (set_color blue)"Removal cancelled"(set_color normal)
end
end
function __env_link -d "Link current directory to an environment"
set -l env_name $argv[1]
set -l target_dir $argv[2]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env link <env_name> [target_directory]"
return 1
end
if test -z "$target_dir"
set target_dir (pwd)
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l activate_file "$env_dir/activate.fish"
if not test -f "$activate_file"
echo (set_color red)"environment '$env_name' not found"(set_color normal)
return 1
end
set -l target_activate "$target_dir/activate.fish"
if test -f "$target_activate"
echo (set_color yellow)"Warning: activate.fish already exists in $target_dir"(set_color normal)
echo "Overwrite? [y/N]"
read -l confirm
if test "$confirm" != y -a "$confirm" != Y
echo (set_color blue)"Link cancelled"(set_color normal)
return 0
end
end
ln -sf "$activate_file" "$target_activate"
echo (set_color green)"Linked environment '$env_name' to $target_dir"(set_color normal)
echo "The environment will be activated automatically when you cd into this directory"
end
function __env_info -d "Show environment information"
set -l env_name $argv[1]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env info <name>"
return 1
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l config_file "$env_dir/config.toml"
if not test -f "$config_file"
echo (set_color red)"environment '$env_name' not found"(set_color normal)
return 1
end
echo (set_color blue)"Environment: $env_name"(set_color normal)
echo "Config file: $config_file"
echo
cat "$config_file"
end
function __env_edit -d "Edit environment configuration"
set -l env_name $argv[1]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env edit <name>"
return 1
end
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l activate_file "$env_dir/activate.fish"
if not test -f "$activate_file"
echo (set_color red)"environment '$env_name' not found"(set_color normal)
return 1
end
$EDITOR "$activate_file"
end
function __env_copy -d "Copy an environment"
set -l src_name $argv[1]
set -l dest_name $argv[2]
if test -z "$src_name" -o -z "$dest_name"
echo (set_color red)"Error: Source and destination names required"(set_color normal)
echo "usage: env copy <source> <destination>"
return 1
end
set -l src_dir "$__ENV_CONFIGS_DIR/$src_name"
set -l dest_dir "$__ENV_CONFIGS_DIR/$dest_name"
if not test -d "$src_dir"
echo (set_color red)"Error: Source environment '$src_name' not found"(set_color normal)
return 1
end
if test -d "$dest_dir"
echo (set_color yellow)"Warning: Destination environment '$dest_name' already exists"(set_color normal)
return 1
end
# Copy the entire environment directory
cp -r "$src_dir" "$dest_dir"
# Update the activate.fish file to use the new name
sed -i "s/$src_name/$dest_name/g" "$dest_dir/activate.fish"
# Update the config file
sed -i "s/name = \"$src_name\"/name = \"$dest_name\"/" "$dest_dir/config.toml"
sed -i "s/# Environment: $src_name/# Environment: $dest_name/" "$dest_dir/config.toml"
echo "copied_from = \"$src_name\"" >>"$dest_dir/config.toml"
echo "copied_date = \"$(date --iso-8601)\"" >>"$dest_dir/config.toml"
echo (set_color green)"Copied environment '$src_name' to '$dest_name'"(set_color normal)
end
function __env_export -d "Export environment to a self-contained directory"
set -l env_name $argv[1]
set -l target_dir $argv[2]
if test -z "$env_name"
echo (set_color red)"environment name required"(set_color normal)
echo "usage: env export <name> [target_directory]"
return 1
end
if test -z "$target_dir"
set target_dir (pwd)
end
# Convert relative path to absolute path
set target_dir (realpath "$target_dir")
set -l env_dir "$__ENV_CONFIGS_DIR/$env_name"
set -l activate_source "$env_dir/activate.fish"
if not test -f "$activate_source"
echo (set_color red)"environment '$env_name' not found"(set_color normal)
return 1
end
if not test -d "$target_dir"
echo (set_color red)"Error: Target directory '$target_dir' does not exist"(set_color normal)
return 1
end
set -l fish_dir "$target_dir/.fish"
set -l target_activate "$fish_dir/activate.fish"
set -l target_readme "$fish_dir/README.md"
# Create .fish directory
if not test -d "$fish_dir"
mkdir -p "$fish_dir"
end
if test -f "$target_activate"
echo (set_color yellow)"Warning: .fish/activate.fish already exists in $target_dir"(set_color normal)
echo "Overwrite? [y/N]"
read -l confirm
if test "$confirm" != y -a "$confirm" != Y
echo (set_color blue)"Export cancelled"(set_color normal)
return 0
end
end
# Create a self-contained activate.fish in .fish directory
echo "# Self-contained environment: $env_name" >"$target_activate"
echo "# Exported on: $(date)" >>"$target_activate"
echo "# Original environment from: $env_dir" >>"$target_activate"
echo "" >>"$target_activate"
# Copy the original activate.fish content but make it self-contained
cat "$activate_source" | sed 's/{{ENV_NAME}}/'"$env_name"'/g' >>"$target_activate"
# Make it executable
chmod +x "$target_activate"
# Create a README from template
set -l readme_template "$__ENV_TEMPLATES_DIR/README.md"
if test -f "$readme_template"
sed "s/{{ENV_NAME}}/$env_name/g" "$readme_template" >"$target_readme"
else
echo "# Exported Fish Environment: $env_name" >"$target_readme"
echo "" >>"$target_readme"
echo "README template not found. Please create $readme_template for custom documentation." >>"$target_readme"
end
echo (set_color green)"Environment '$env_name' exported to: $target_dir"(set_color normal)
echo (set_color blue)"Files created:"(set_color normal)
echo " - $target_activate (main environment)"
echo " - $target_readme (documentation)"
echo
echo (set_color cyan)"To use this environment:"(set_color normal)
echo " cd $target_dir"
echo " source ./.fish/activate.fish"
end
function __env_list_templates -d "List available templates with descriptions"
set -l template_dir "$__ENV_TEMPLATES_DIR"
if not test -d "$template_dir"
echo " (no templates found)"
return 0
end
for template_file in "$template_dir"/*.fish
if test -f "$template_file"
set template_name (basename "$template_file" .fish)
# Extract description from first comment line (skip shebang if present)
set description "No description"
set first_comment_line (head -n 5 "$template_file" | grep -E "^#[^!]" | head -n 1 | sed 's/^# *//')
if test -n "$first_comment_line"
set description "$first_comment_line"
end
# Format with proper alignment
printf " %-12s %s\n" "$template_name" "$description"
end
end
end