File size: 6,065 Bytes
5670bcb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
#
# Caption Tool installer
#
# One-command install (host this file, then):
#   curl -fsSL https://oohfixer.com/caption-tool/install.sh | bash
#
# Local install (run from this folder):
#   bash install.sh
#
# Environment overrides:
#   CAPTION_TOOL_BASE -> base URL the files are served from (download mode)
#   CAPTION_TOOL_DIR  -> install location (default ~/.local/share/caption_tool)

set -euo pipefail

BASE_URL="${CAPTION_TOOL_BASE:-https://oohfixer.com/caption-tool}"
INSTALL_DIR="${CAPTION_TOOL_DIR:-$HOME/.local/share/caption_tool}"
BIN_DIR="$HOME/.local/bin"
VENV="$INSTALL_DIR/.venv"

info()  { printf '%s\n' "$1"; }
err()   { printf 'Error: %s\n' "$1" >&2; }

# Ask a yes/no question on the terminal so it works even when this script is
# piped in via curl (where stdin is the script itself, not the keyboard).
prompt_yes_no() {
  local ans
  if [ -r /dev/tty ]; then
    read -r -p "$1 [y/N] " ans < /dev/tty || ans=""
  else
    read -r -p "$1 [y/N] " ans || ans=""
  fi
  case "$ans" in
    y|Y|yes|YES|Yes) return 0 ;;
    *) return 1 ;;
  esac
}

# Best-effort install of Python 3.13 via the system package manager.
install_python() {
  local os_id=""
  if [ -f /etc/os-release ]; then
    # shellcheck disable=SC1091
    os_id="$(. /etc/os-release && echo "$ID")"
  fi

  case "$os_id" in
    ubuntu|debian|linuxmint|pop|raspbian|kali)
      sudo apt-get update
      if ! sudo apt-get install -y python3.13 python3.13-venv; then
        sudo apt-get install -y software-properties-common
        sudo add-apt-repository -y ppa:deadsnakes/ppa
        sudo apt-get update
        sudo apt-get install -y python3.13 python3.13-venv
      fi
      ;;
    fedora|rhel|centos|rocky|almalinux)
      sudo dnf install -y python3.13
      ;;
    arch|manjaro)
      err "Arch-based systems do not provide older Python easily."
      info "Install python-3.13 from the AUR, then re-run this installer."
      return 1
      ;;
    *)
      if command -v brew >/dev/null 2>&1; then
        brew install python@3.13
      else
        err "Could not detect your OS package manager."
        info "Install Python 3.13 manually (https://www.python.org/downloads/), then re-run."
        return 1
      fi
      ;;
  esac
}

# --- 1. Locate or install a suitable Python --------------------------------
PYBIN=""
if command -v python3 >/dev/null 2>&1; then
  PYVER="$(python3 --version 2>&1 | sed 's/Python //')"
  PYMAJ="$(printf '%s' "$PYVER" | cut -d. -f1)"
  PYMIN="$(printf '%s' "$PYVER" | cut -d. -f2)"
  if [ "$PYMAJ" -gt 3 ] || { [ "$PYMAJ" -eq 3 ] && [ "$PYMIN" -ge 14 ]; }; then
    if prompt_yes_no "Python $PYVER is installed, but Caption Tool needs 3.13 or older. Install Python 3.13 now?"; then
      install_python || true
      PYBIN="$(command -v python3.13 || true)"
    fi
  else
    PYBIN="$(command -v python3)"
  fi
else
  if prompt_yes_no "Python 3 was not found. Install Python 3.13 now?"; then
    install_python || true
    PYBIN="$(command -v python3.13 || command -v python3 || true)"
  fi
fi

if [ -z "$PYBIN" ]; then
  err "A Python 3.13 (or older) interpreter is required."
  info "Install it, then re-run:  bash install.sh"
  exit 1
fi

# Re-verify the chosen interpreter is acceptable.
PYVER="$("$PYBIN" --version 2>&1 | sed 's/Python //')"
PYMAJ="$(printf '%s' "$PYVER" | cut -d. -f1)"
PYMIN="$(printf '%s' "$PYVER" | cut -d. -f2)"
if [ "$PYMAJ" -gt 3 ] || { [ "$PYMAJ" -eq 3 ] && [ "$PYMIN" -ge 14 ]; }; then
  err "Python $PYVER is still too new. Caption Tool requires 3.13 or older."
  exit 6
fi

# --- 2. Locate the source files (local copy or download) --------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-.}")" && pwd)"
if [ -f "$SCRIPT_DIR/caption.py" ]; then
  SRC_MODE="local"
  SRC="$SCRIPT_DIR"
else
  SRC_MODE="download"
  SRC="$BASE_URL"
fi

# --- 3. Create install dir + virtual environment ----------------------------
info "Installing Caption Tool"
info "  Location: $INSTALL_DIR"
info ""

info "Step 1/5  Preparing the isolated Python environment..."
mkdir -p "$INSTALL_DIR"
if [ ! -d "$VENV" ]; then
  "$PYBIN" -m venv "$VENV"
fi

# --- 4. Fetch the tool files -------------------------------------------------
info "Step 2/5  Getting the tool files..."
if [ "$SRC_MODE" = "local" ]; then
  cp "$SRC/caption.py"         "$INSTALL_DIR/"
  cp "$SRC/caption_config.json" "$INSTALL_DIR/"
  cp "$SRC/requirements.txt"   "$INSTALL_DIR/"
else
  curl -fsSL "$SRC/caption.py"          -o "$INSTALL_DIR/caption.py"
  curl -fsSL "$SRC/caption_config.json" -o "$INSTALL_DIR/caption_config.json"
  curl -fsSL "$SRC/requirements.txt"    -o "$INSTALL_DIR/requirements.txt"
fi

# --- 5. Install dependencies -------------------------------------------------
info "Step 3/5  Installing dependencies (this can take a few minutes)..."
"$VENV/bin/pip" install --quiet --upgrade pip
"$VENV/bin/pip" install --quiet -r "$INSTALL_DIR/requirements.txt"

# --- 6. Create the global 'captions' command ---------------------------------
info "Step 4/5  Creating the 'captions' command..."
mkdir -p "$BIN_DIR"
cat > "$BIN_DIR/captions" <<EOF
#!/usr/bin/env bash
exec "$VENV/bin/python" "$INSTALL_DIR/caption.py" "\$@"
EOF
chmod +x "$BIN_DIR/captions"

# --- 7. Make sure ~/.local/bin is on PATH ------------------------------------
NEED_RESTART=0
if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then
  RC="$HOME/.bashrc"
  case "${SHELL:-}" in
    *zsh) RC="$HOME/.zshrc" ;;
  esac
  if [ -f "$RC" ] && ! grep -q 'caption_tool_path' "$RC"; then
    printf '\nexport PATH="%s:$PATH"  # caption_tool_path\n' "$BIN_DIR" >> "$RC"
  fi
  NEED_RESTART=1
fi

# --- 8. Done -----------------------------------------------------------------
info "Step 5/5  Done."
info ""
info "Caption Tool is installed."
if [ "$NEED_RESTART" = "1" ]; then
  info "Run the next line (or open a new terminal) to use 'captions' anywhere:"
  info "    source $RC"
else
  info "The command 'captions' is ready to use now."
fi
info ""
info "Start captioning:        captions"
info "Or point at a folder:    captions --path \"/path/to/images\""