Last active
May 14, 2025 13:29
-
-
Save marijnbent/02af375463dae03ceb0bf02a4b3d29a0 to your computer and use it in GitHub Desktop.
Brew Interactive Install
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# brew-interactive: Interactive Homebrew Package Management | |
# | |
# Install it as a brew package here: https://github.com/marijnbent/homebrew-interactive-install | |
# | |
# Description: | |
# This script provides an enhanced, interactive command-line interface for | |
# managing Homebrew packages (formulae and casks). It streamlines the common | |
# workflow of searching for a package, viewing its information, and then | |
# installing it. Instead of typing multiple `brew` commands, you can: | |
# | |
# 1. Search for packages using a fuzzy finder (`fzf`). | |
# 2. Instantly preview `brew info` for the highlighted package within `fzf`. | |
# 3. Select a package (press Enter) to directly install it. | |
# 4. After an install attempt, you are immediately presented with options to: | |
# - Re-run the same search (refresh results). | |
# - Start a new search for a different package. | |
# - Quit the interactive session. | |
# | |
# This tool is ideal for users who frequently explore and install new | |
# Homebrew packages and prefer a more dynamic, keyboard-driven experience. | |
# It leverages `fzf` for its powerful fuzzy searching and preview capabilities. | |
# | |
# Keywords for search: | |
# brew, homebrew, fzf, interactive, search, install, package manager, | |
# formula, cask, tui, cli, fuzzy finder, brew search, brew info, brew install | |
# | |
# ------------------------------------------------------------------------------ | |
# Installation and Setup: | |
# ------------------------------------------------------------------------------ | |
# | |
# 1. Prerequisites: | |
# - Homebrew: Must be installed on your macOS or Linux system. | |
# (See: https://brew.sh/) | |
# - fzf (Fuzzy Finder): This script relies heavily on `fzf`. | |
# Install it via Homebrew: | |
# `brew install fzf` | |
# | |
# 2. Save the Script: | |
# Copy the entire content of this script and save it to a file on your | |
# system. For example, you could name it `brew-interactive.sh` or simply `brewi`. | |
# A common location for personal scripts is `~/bin` or `~/.local/bin`. | |
# | |
# Example: | |
# `mkdir -p ~/bin` (if it doesn't exist) | |
# `curl -o ~/bin/brewi https://gist.github.com/YOUR_GIST_URL/raw/brewi.sh` | |
# (Replace `YOUR_GIST_URL` if you host it on a Gist) | |
# OR | |
# `nano ~/bin/brewi` (and paste the script content) | |
# | |
# 3. Make it Executable: | |
# Navigate to the directory where you saved the script and make it executable: | |
# `chmod +x ~/bin/brewi` | |
# | |
# 4. Add to PATH (Recommended): | |
# If you saved the script to a directory like `~/bin` or `~/.local/bin`, | |
# ensure this directory is in your system's `PATH` environment variable. | |
# This allows you to run the script by simply typing its name from any | |
# directory. | |
# | |
# To check if `~/bin` is in your PATH: | |
# `echo $PATH` | |
# | |
# If it's not, add one of the following lines to your shell's configuration | |
# file (e.g., `~/.bashrc`, `~/.zshrc`): | |
# | |
# For bash: | |
# `export PATH="$HOME/bin:$PATH"` | |
# For zsh: | |
# `export PATH="$HOME/bin:$PATH"` (or `path=($HOME/bin $path)`) | |
# | |
# After editing the file, source it or open a new terminal window: | |
# `source ~/.bashrc` or `source ~/.zshrc` | |
# | |
# 5. Create an Alias (Optional): | |
# If you prefer a different command name or if the script is not in your | |
# PATH, you can create an alias in your shell's configuration file. | |
# | |
# Example alias in `~/.bashrc` or `~/.zshrc`: | |
# `alias brewi='/path/to/your/script/brew-interactive.sh'` | |
# (Replace `/path/to/your/script/` with the actual path) | |
# | |
# Remember to source your shell config file after adding an alias. | |
# | |
# ------------------------------------------------------------------------------ | |
# Usage: | |
# ------------------------------------------------------------------------------ | |
# | |
# Once installed and (optionally) in your PATH or aliased: | |
# | |
# - To start and be prompted for a search term: | |
# `brewi` | |
# | |
# - To start with an initial search term: | |
# `brewi <search_term>` | |
# Example: `brewi httpie` | |
# | |
# Inside the script: | |
# - Use arrow keys (↑↓) to navigate the search results in `fzf`. | |
# - The right pane will show `brew info` for the highlighted package. | |
# - Press `Enter` on a package in the list to *directly install it*. | |
# - Press `Esc` in the `fzf` list to go back to the main options menu | |
# (search again, new search, quit). | |
# | |
# ------------------------------------------------------------------------------ | |
set -euo pipefail | |
if ! command -v fzf &> /dev/null; then | |
echo "Error: fzf could not be found." >&2 | |
echo "Please install it first: brew install fzf" >&2 | |
exit 1 | |
fi | |
if ! command -v brew &> /dev/null; then | |
echo "Error: brew command could not be found." >&2 | |
echo "Please ensure Homebrew is installed and in your PATH." >&2 | |
exit 1 | |
fi | |
main_interactive_loop() { | |
local current_search_term="$1" | |
local packages="" | |
local selected_package="" | |
while true; do | |
if [ -z "$current_search_term" ]; then | |
local new_search_input | |
echo | |
read -r -p "Enter Brew search term (or press Enter to quit): " new_search_input | |
if [ -z "$new_search_input" ]; then | |
echo "No search term provided. Quitting." | |
return 0 | |
fi | |
current_search_term="$new_search_input" | |
fi | |
echo | |
echo "Searching for '$current_search_term'..." | |
packages=$( (brew search --formulae "$current_search_term" 2>/dev/null; brew search --casks "$current_search_term" 2>/dev/null) | | |
grep -v '^==>' | | |
grep . | | |
sort -u ) | |
if [ -z "$packages" ]; then | |
echo "No packages found matching '$current_search_term'." | |
# No packages found. Proceed directly to the main options menu. | |
else | |
# Packages found. Enter the fzf loop for selection. | |
# This loop runs once per selection (install) or if Esc is pressed in fzf. | |
# After one selection/install, it breaks to the main menu. | |
while true; do | |
selected_package=$(echo "$packages" | fzf \ | |
--prompt="Select ('$current_search_term' results | Enter: INSTALL | Esc: main menu): " \ | |
--height="70%" \ | |
--layout=reverse \ | |
--border \ | |
--preview-window='right:60%:wrap' \ | |
--header "Search: '$current_search_term'. ↑↓ to navigate. Enter to INSTALL. Preview: 'brew info'." \ | |
--preview="echo 'Loading info for {}...' && brew info {} 2>/dev/null || echo 'No detailed info or cask not tapped.'" \ | |
--exit-0) | |
if [ -z "$selected_package" ]; then | |
break | |
fi | |
echo | |
echo "-----------------------------------------------------" | |
echo "Attempting to install: $selected_package (from search '$current_search_term')" | |
echo "-----------------------------------------------------" | |
if brew install "$selected_package"; then | |
echo -e "\n'$selected_package' installed successfully!" | |
else | |
echo -e "\nFailed to install '$selected_package'. It might already be installed or another issue occurred." >&2 | |
fi | |
echo | |
break | |
done | |
fi | |
echo | |
echo "What would you like to do next?" | |
echo "1. Search again for '$current_search_term' (refresh results)" | |
echo "2. Search for a new app" | |
echo "3. Quit" | |
local choice | |
while true; do | |
read -r -p "Enter your choice (1-3): " choice | |
case "$choice" in | |
1) | |
echo "Preparing to search again for '$current_search_term'..." | |
break | |
;; | |
2) | |
current_search_term="" | |
echo "Preparing to search for a new app..." | |
break | |
;; | |
3) | |
echo "Quitting." | |
return 0 | |
;; | |
*) echo "Invalid choice. Please enter 1, 2, or 3." >&2 ;; | |
esac | |
done | |
done | |
} | |
initial_search_term="${1-}" | |
main_interactive_loop "$initial_search_term" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can install it as a brew package here: https://github.com/marijnbent/homebrew-interactive-install