306 lines
9.3 KiB
Bash
306 lines
9.3 KiB
Bash
#!/bin/sh
|
|
# finish.sh installer
|
|
# Usage: curl -sSL https://git.appmodel.nl/tour/finish/raw/branch/main/docs/install.sh | bash
|
|
|
|
set -e
|
|
|
|
ACSH_VERSION="v0.6.0"
|
|
BRANCH_OR_VERSION=${1:-main}
|
|
REPO_URL="https://git.appmodel.nl/tour/finish/raw/branch"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo_green() {
|
|
printf "${GREEN}%s${NC}\n" "$1"
|
|
}
|
|
|
|
echo_error() {
|
|
printf "${RED}ERROR: %s${NC}\n" "$1" >&2
|
|
}
|
|
|
|
echo_warning() {
|
|
printf "${YELLOW}WARNING: %s${NC}\n" "$1"
|
|
}
|
|
|
|
# Detect the current shell
|
|
detect_shell() {
|
|
if [ -n "$ZSH_VERSION" ]; then
|
|
echo "zsh"
|
|
elif [ -n "$BASH_VERSION" ]; then
|
|
echo "bash"
|
|
else
|
|
parent_shell=$(ps -p $PPID -o comm= 2>/dev/null || echo "")
|
|
case "$parent_shell" in
|
|
*zsh*) echo "zsh" ;;
|
|
*bash*) echo "bash" ;;
|
|
*) echo "unknown" ;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
# Check dependencies
|
|
check_dependencies() {
|
|
local missing=""
|
|
|
|
if ! command -v curl > /dev/null 2>&1 && ! command -v wget > /dev/null 2>&1; then
|
|
missing="${missing}curl or wget, "
|
|
fi
|
|
|
|
if ! command -v jq > /dev/null 2>&1; then
|
|
missing="${missing}jq, "
|
|
fi
|
|
|
|
if ! command -v bc > /dev/null 2>&1; then
|
|
missing="${missing}bc, "
|
|
fi
|
|
|
|
if [ -n "$missing" ]; then
|
|
echo_error "Missing dependencies: ${missing%, }"
|
|
echo ""
|
|
echo "Install them with:"
|
|
echo " Ubuntu/Debian: sudo apt-get install curl jq bc bash-completion"
|
|
echo " CentOS/RHEL: sudo yum install curl jq bc bash-completion"
|
|
echo " macOS: brew install jq bc bash-completion"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Download file
|
|
download_file() {
|
|
local url="$1"
|
|
local output="$2"
|
|
|
|
if command -v curl > /dev/null 2>&1; then
|
|
curl -fsSL "$url" -o "$output"
|
|
elif command -v wget > /dev/null 2>&1; then
|
|
wget -q -O "$output" "$url"
|
|
else
|
|
echo_error "Neither curl nor wget is available"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Main installation
|
|
main() {
|
|
echo_green "=========================================="
|
|
echo_green " finish.sh Installation"
|
|
echo_green " Version: $ACSH_VERSION"
|
|
echo_green "=========================================="
|
|
echo ""
|
|
|
|
# Detect shell
|
|
SHELL_TYPE=$(detect_shell)
|
|
case "$SHELL_TYPE" in
|
|
zsh)
|
|
RC_FILE="$HOME/.zshrc"
|
|
;;
|
|
bash)
|
|
RC_FILE="$HOME/.bashrc"
|
|
;;
|
|
*)
|
|
echo_error "Unsupported shell. Currently only bash and zsh are supported."
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "Detected shell: $SHELL_TYPE"
|
|
|
|
# Check Python and venv
|
|
echo "Checking Python installation..."
|
|
if ! command -v python3 > /dev/null 2>&1; then
|
|
echo_error "Python 3 is required but not found"
|
|
echo "Install it with:"
|
|
echo " Ubuntu/Debian: sudo apt-get install python3 python3-pip python3-venv"
|
|
echo " macOS: brew install python3"
|
|
exit 1
|
|
fi
|
|
echo_green "✓ Python 3 found: $(python3 --version)"
|
|
|
|
# Check if venv module is available
|
|
if ! python3 -m venv --help > /dev/null 2>&1; then
|
|
echo_error "python3-venv module is not installed"
|
|
echo "Install it with:"
|
|
echo " Ubuntu/Debian: sudo apt-get install python3-venv"
|
|
echo " CentOS/RHEL: sudo yum install python3-venv"
|
|
echo " macOS: (included with python3)"
|
|
exit 1
|
|
fi
|
|
echo_green "✓ python3-venv available"
|
|
echo ""
|
|
|
|
# Check dependencies
|
|
echo "Checking dependencies..."
|
|
if ! check_dependencies; then
|
|
exit 1
|
|
fi
|
|
echo_green "✓ All dependencies found"
|
|
echo ""
|
|
|
|
# Determine installation location
|
|
# Prefer local user install at ~/.local/bin, create it if missing
|
|
if [ ! -d "$HOME/.local/bin" ]; then
|
|
mkdir -p "$HOME/.local/bin"
|
|
fi
|
|
|
|
if [ -d "$HOME/.local/bin" ]; then
|
|
INSTALL_LOCATION="$HOME/.local/bin/finish"
|
|
# Add to PATH if not already there
|
|
if ! echo "$PATH" | grep -q "$HOME/.local/bin"; then
|
|
echo_warning "$HOME/.local/bin is not in PATH"
|
|
if [ ! -f "$RC_FILE" ] || ! grep -q ".local/bin" "$RC_FILE"; then
|
|
echo "Adding $HOME/.local/bin to PATH in $RC_FILE"
|
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$RC_FILE"
|
|
fi
|
|
fi
|
|
elif [ -w "/usr/local/bin" ]; then
|
|
INSTALL_LOCATION="/usr/local/bin/finish"
|
|
else
|
|
echo_error "Cannot determine installation location"
|
|
echo "Please ensure either $HOME/.local/bin exists and is writable, or run with sudo for /usr/local/bin"
|
|
exit 1
|
|
fi
|
|
|
|
# Create directories if needed
|
|
mkdir -p "$(dirname "$INSTALL_LOCATION")"
|
|
mkdir -p "$HOME/.venvs"
|
|
|
|
# Download Python script
|
|
echo "Downloading finish.py..."
|
|
URL="$REPO_URL/$BRANCH_OR_VERSION/src/finish.py"
|
|
if ! download_file "$URL" "$INSTALL_LOCATION"; then
|
|
echo_error "Failed to download from $URL"
|
|
exit 1
|
|
fi
|
|
|
|
# Download requirements.txt
|
|
echo "Downloading requirements.txt..."
|
|
TEMP_REQ="/tmp/finish_requirements.txt"
|
|
REQ_URL="$REPO_URL/$BRANCH_OR_VERSION/requirements.txt"
|
|
if ! download_file "$REQ_URL" "$TEMP_REQ"; then
|
|
echo_error "Failed to download requirements.txt from $REQ_URL"
|
|
exit 1
|
|
fi
|
|
|
|
# Create virtualenv and install dependencies
|
|
echo "Creating virtual environment..."
|
|
VENV_PATH="$HOME/.venvs/finish"
|
|
if [ -d "$VENV_PATH" ]; then
|
|
echo "Virtual environment already exists, removing old one..."
|
|
rm -rf "$VENV_PATH"
|
|
fi
|
|
|
|
if ! python3 -m venv "$VENV_PATH"; then
|
|
echo_error "Failed to create virtual environment"
|
|
echo "Make sure python3-venv is installed:"
|
|
echo " Ubuntu/Debian: sudo apt-get install python3-venv"
|
|
exit 1
|
|
fi
|
|
echo_green "✓ Virtual environment created at $VENV_PATH"
|
|
|
|
echo "Installing Python dependencies..."
|
|
if ! "$VENV_PATH/bin/pip" install --quiet --upgrade pip; then
|
|
echo_error "Failed to upgrade pip"
|
|
exit 1
|
|
fi
|
|
|
|
if ! "$VENV_PATH/bin/pip" install --quiet -r "$TEMP_REQ"; then
|
|
echo_error "Failed to install dependencies"
|
|
cat "$TEMP_REQ"
|
|
exit 1
|
|
fi
|
|
echo_green "✓ Dependencies installed"
|
|
rm -f "$TEMP_REQ"
|
|
|
|
# Update shebang to use venv python (compatible with macOS and Linux)
|
|
if sed --version >/dev/null 2>&1; then
|
|
# GNU sed (Linux)
|
|
sed -i "1s|.*|#!$VENV_PATH/bin/python3|" "$INSTALL_LOCATION"
|
|
else
|
|
# BSD sed (macOS)
|
|
sed -i '' "1s|.*|#!$VENV_PATH/bin/python3|" "$INSTALL_LOCATION"
|
|
fi
|
|
|
|
# Verify shebang was updated correctly
|
|
SHEBANG=$(head -n 1 "$INSTALL_LOCATION")
|
|
if [ "$SHEBANG" != "#!$VENV_PATH/bin/python3" ]; then
|
|
echo_error "Failed to update shebang. Got: $SHEBANG"
|
|
exit 1
|
|
fi
|
|
|
|
chmod +x "$INSTALL_LOCATION"
|
|
echo_green "✓ Installed to $INSTALL_LOCATION"
|
|
echo ""
|
|
|
|
# Ensure current shell PATH includes the install dir for immediate use
|
|
INSTALL_DIR="$(dirname "$INSTALL_LOCATION")"
|
|
case ":$PATH:" in
|
|
*":$INSTALL_DIR:"*) ;;
|
|
*) export PATH="$INSTALL_DIR:$PATH" ;;
|
|
esac
|
|
|
|
# Check bash-completion
|
|
if [ "$SHELL_TYPE" = "bash" ]; then
|
|
if ! command -v _init_completion > /dev/null 2>&1; then
|
|
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
|
echo_warning "bash-completion not loaded. Add to $RC_FILE:"
|
|
echo " source /usr/share/bash-completion/bash_completion"
|
|
elif [ -f /etc/bash_completion ]; then
|
|
echo_warning "bash-completion not loaded. Add to $RC_FILE:"
|
|
echo " source /etc/bash_completion"
|
|
else
|
|
echo_warning "bash-completion not found. Install it for best experience:"
|
|
echo " sudo apt-get install bash-completion # Ubuntu/Debian"
|
|
fi
|
|
echo ""
|
|
fi
|
|
fi
|
|
|
|
# Test that finish works
|
|
echo "Testing installation..."
|
|
if ! "$INSTALL_LOCATION" --version > /dev/null 2>&1; then
|
|
echo_error "finish command failed to execute"
|
|
echo "Testing with direct python call..."
|
|
"$VENV_PATH/bin/python3" "$INSTALL_LOCATION" --version
|
|
exit 1
|
|
fi
|
|
echo_green "✓ finish command works"
|
|
|
|
# Run finish install to set up keybinding
|
|
echo "Setting up shell keybinding..."
|
|
if "$INSTALL_LOCATION" install; then
|
|
echo ""
|
|
echo_green "=========================================="
|
|
echo_green " Installation Complete!"
|
|
echo_green "=========================================="
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Reload your shell configuration:"
|
|
echo " source $RC_FILE"
|
|
echo ""
|
|
echo " 2. Configure your LLM endpoint:"
|
|
echo " finish config"
|
|
echo ""
|
|
echo " 3. Edit config if needed:"
|
|
echo " nano ~/.finish/finish.json"
|
|
echo ""
|
|
echo " 4. Start using by pressing Alt+\\ after typing a command"
|
|
echo ""
|
|
echo "Example:"
|
|
echo " Type: show gpu status"
|
|
echo " Press: Alt+\\"
|
|
echo " Select completion with ↑↓ arrows, Enter to accept"
|
|
echo ""
|
|
echo "Documentation: https://git.appmodel.nl/tour/finish"
|
|
else
|
|
echo_error "Installation failed. Please check the output above."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main "$@"
|