Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"cSpell.words": [
"Bashmatic",
"rubygems"
"rubygems",
"RUSTUP"
]
}
3 changes: 1 addition & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Bashmatic® — Project Guide for Claude
# Bashmatic® — Project Guide for Claudens (“a BASH DSL for humans”), focused on

> A BASH framework of ~900 helper functions (“a BASH DSL for humans”), focused on
> beautiful terminal output, consistent command execution, and self-documenting
> scripts. Loads in under 200ms. MIT licensed.

Expand Down
89 changes: 89 additions & 0 deletions bin/rust-install
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
# vim: ft=bash
#
set +e

# Re-exec under modern bash if we landed in bash 3 (macOS /bin/bash).
# Without this, sourcing parts of bashmatic from bash 3 misbehaves and
# leaves the user in odd states. Done before anything else.
if [[ -n ${BASH_VERSION} && ${BASH_VERSION:0:1} -lt 4 ]]; then
for __new_bash in /opt/homebrew/bin/bash /usr/local/bin/bash; do
if [[ -x ${__new_bash} ]]; then
exec "${__new_bash}" "$0" "$@"
fi
done
fi

[[ -z ${BASHMATIC_HOME} ]] && export BASHMATIC_HOME="$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1; pwd -P)")"

if [[ $(uname -s) == Darwin ]] ; then
command -v brew >/dev/null && {
brew update
[[ ${BASH_VERSION:0:1} -lt 4 ]] && brew install bash
export PATH="$(brew --prefix)/bin:$PATH"
}
fi

[[ -z ${BASHMATIC_HOME} ]] && export BASHMATIC_HOME="${HOME}/.bashmatic"
[[ -d ${BASHMATIC_HOME} ]] || bash -c "$(curl -fsSL https://bashmatic.re1.re); bashmatic-install"
[[ -d ${BASHMATIC_HOME} ]] || {
echo "Can't find Bashmatic, even after attempting an installation."
echo "Please install Bashmatic with the following command line:"
echo 'bash -c "$(curl -fsSL https://bashmatic.re1.re); bashmatic-install"'
exit 1
}

# shellcheck source=/dev/null
source "${BASHMATIC_HOME}/lib/color.sh"
source "${BASHMATIC_HOME}/lib/output.sh"
source "${BASHMATIC_HOME}/lib/output-boxes.sh"
source "${BASHMATIC_HOME}/lib/output-admonitions.sh"
source "${BASHMATIC_HOME}/lib/output-utils.sh"
source "${BASHMATIC_HOME}/lib/runtime.sh"
source "${BASHMATIC_HOME}/lib/time.sh"
source "${BASHMATIC_HOME}/lib/util.sh"

command -v rustc >/dev/null && command -v cargo >/dev/null && {
printf "${txtgrn}Rust is already installed.${clr}\n" 2>/dev/null
exit 0
}

readonly __rust_rustup_home=/opt/rust/rustup
readonly __rust_cargo_home=/opt/rust/cargo

run "sudo mkdir -p \"${__rust_rustup_home}\" \"${__rust_cargo_home}\""
run "sudo chown -R \"$(id -un)\":\"$(id -gn)\" /opt/rust"

export RUSTUP_HOME="${__rust_rustup_home}"
export CARGO_HOME="${__rust_cargo_home}"

run "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path"

declare -a local_shells_done=()

while IFS= read -r shell_path || [[ -n ${shell_path} ]]; do
[[ -z ${shell_path// } ]] && continue
[[ ${shell_path} =~ ^[[:space:]]*# ]] && continue
shell="$(basename "${shell_path}")"
# shellcheck disable=SC2076
if [[ " ${local_shells_done[*]} " =~ " ${shell} " ]]; then
continue
fi
info "Installing hooks into ${SHELL_RC} for ${shell}..."
local_shells_done+=( "${shell}" )

SHELL_RC="${HOME}/.${shell}rc"
if [[ ! -s ${SHELL_RC} ]] ; then
touch "${SHELL_RC}"
fi
echo "Installing hooks into ${SHELL_RC} for ${shell}..."
if [[ -f ${SHELL_RC} ]] && ! grep -q 'RUSTUP_HOME=/opt/rust/rustup' "${SHELL_RC}" 2>/dev/null; then
echo "Appending Rust Initialization for ${shell} → ${SHELL_RC}"
{
echo "export RUSTUP_HOME=${__rust_rustup_home}"
echo "export CARGO_HOME=${__rust_cargo_home}"
echo "export PATH=\"${__rust_rustup_home}/bin:${__rust_cargo_home}/bin:\${PATH}\""
} >> "${SHELL_RC}"
fi
done < /etc/shells

258 changes: 258 additions & 0 deletions bin/rust-install-tools
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#!/usr/bin/env bash
#
# rust-install-tools — opinionated installer for modern Rust CLI/TUI tools.
# Skips anything already installed; for the rest, prints a colorful h2bg
# banner describing the tool, then installs it via cargo-binstall.
#
# USAGE:
# # We need BASH version 4+
# brew install bash # MacOS only
#
# # Then we can just run this script or do it from the Public Gist.
# curl -fsSL https://bit.ly/install-rust-tools | /opt/homebrew/bin/bash

set +e

# Re-exec under modern bash if we landed in bash 3 (macOS /bin/bash).
if [[ -n ${BASH_VERSION} && ${BASH_VERSION:0:1} -lt 4 ]]; then
for __new_bash in /opt/homebrew/bin/bash /usr/local/bin/bash; do
if [[ -x ${__new_bash} ]]; then
exec "${__new_bash}" "$0" "$@"
fi
done
fi

export OLD_IFS="${IFS}"

# Parent of bin/ when this script lives in the bashmatic checkout.
_rust_tools_bashmatic_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
[[ -z "${BASHMATIC_HOME:-}" ]] && export BASHMATIC_HOME="${_rust_tools_bashmatic_root}"

if [[ ! -d "${HOME}/.bashmatic" ]]; then
echo "→ Installing bashmatic..."
if [[ -x "${_rust_tools_bashmatic_root}/bin/bashmatic-install" ]]; then
"${_rust_tools_bashmatic_root}/bin/bashmatic-install" -q -l
elses
bash -c "$(curl -fsSL https://bashmatic.re1.re)" _ -q -l || \
bash -c "$(curl -fsSL https://raw.githubusercontent.com/kigster/bashmatic/master/bin/bashmatic-install)" _ -q -l
fi
fi
export BASHMATIC_HOME="${HOME}/.bashmatic"

# shellcheck source=/dev/null
source "${BASHMATIC_HOME}/init"

# --- Bootstrap cargo-binstall (so we don't compile everything from source) ---
if ! command -v cargo-binstall >/dev/null 2>&1; then
h3bg "cargo-binstall — fetches prebuilt Cargo binaries instead of compiling"
cargo install cargo-binstall
fi

# --- Tool catalog: binary | crate | one-line description ---
# ============================================================================
# Rust CLI tools, grouped by category. Format: binary|crate|description
# ============================================================================

TOOLS=(
# --- Shell & Prompt ---
"atuin |atuin |Synced shell history with searchable TUI"
"nu |nu |Nushell: structured-data shell"
"starship|starship|Minimal, blazing-fast cross-shell prompt"
"zoxide |zoxide |Smarter cd that learns your habits (frecency)"

# --- File Management ---
"bat |bat |Cat clone with syntax highlighting and paging"
"broot|broot |Tree-style file navigator"
"dua |dua-cli|Interactive TUI disk-usage explorer"
"dust |du-dust|Sorted disk-usage tree, drop-in du replacement"
"erd |erdtree|Modern tree with file-size and gitignore support"
"eza |eza |Modern ls with tree view, git status, and icons"
"fd |fd-find|Find replacement: gitignore-aware, parallel, sane defaults"
"xplr |xplr |Hackable, minimal, fast TUI file explorer"
"yazi |yazi-fm|Async TUI file manager with image previews"

# --- System Monitoring ---
"bandwhich|bandwhich|Per-process and per-connection bandwidth monitor"
"btm |bottom |Ratatui system monitor: top/htop replacement"
"kmon |kmon |Linux kernel module manager TUI"
"pgtop |pgtop |Postgres activity monitor, top-like"
"procs |procs |Modern ps: tree mode, search, color"

# --- Cargo / Rust dev ---
"bacon |bacon |Background cargo check/clippy/test TUI"
"cargo-audit |cargo-audit |Audit Cargo.lock for known security advisories"
"cargo-binstall|cargo-binstall|Install Rust binaries from prebuilt artifacts"
"cargo-deb |cargo-deb |Build .deb packages from Cargo metadata"
"cargo-deny |cargo-deny |Lint dependencies for licenses, bans, advisories"
"cargo-generate|cargo-generate|Scaffold new projects from git templates"
"cargo-liner |cargo-liner |Declarative cargo install via liner.toml"
"cargo-machete |cargo-machete |Find and remove unused Cargo dependencies"
"cargo-nextest |cargo-nextest |Next-gen test runner: parallel, retry, faster"

# --- Git & VCS ---
"delta |git-delta |Beautiful syntax-highlighted git diff pager"
"difft |difftastic|Syntax-aware structural diff, not line diff"
"git-cliff|git-cliff |Generate changelog from conventional commits"
"gitui |gitui |Full-featured git TUI: stage, commit, branch, blame"
"jj |jj-cli |Jujutsu: git-compatible VCS, rethought UX"
"mergiraf |mergiraf |AST-aware git merge driver, resolves false conflicts"
"serie |serie |Git log graph viewer (ratatui)"

# --- Data Inspection ---
"csvlens|csvlens |Interactive CSV pager with column-aware scrolling"
"gobang |gobang |Cross-database SQL client TUI"
"hexyl |hexyl |Colored, structured hex viewer"
"jless |jless |Interactive JSON/YAML viewer"
"qsv |qsv |CSV/data swiss-army knife, 50+ subcommands"
"rg |ripgrep |Lightning-fast recursive grep"
"rga |ripgrep_all|ripgrep for PDFs, ebooks, archives, SQLite"
"tokei |tokei |Count lines of code by language, blazing fast"

# --- Networking ---
"gping |gping |Ping with a live latency graph"
"monolith|monolith|Save complete web pages as single HTML files"
"oha |oha |HTTP load tester with a live TUI"
"slumber |slumber |YAML-driven HTTP API client TUI"
"trip |trippy |Network diagnostics: traceroute + ping + MTR in one"
"xh |xh |HTTPie-style HTTP client, fast and ergonomic"

# --- Productivity & TUI ---
"fzf-make |fzf-make |Interactive Makefile/justfile target picker"
"gpg-tui |gpg-tui |TUI for managing GPG keys"
"kdash |kdash |Kubernetes dashboard TUI"
"mprocs |mprocs |Run multiple commands in parallel in a TUI"
"or |octorus |GitHub PR review TUI built for Helix users"
"oxker |oxker |Docker container TUI: logs, exec, stats"
"presenterm |presenterm |Markdown slide presentations in the terminal"
"sk |skim |Rust fuzzy finder, fzf alternative"
"taskwarrior-tui|taskwarrior-tui|TUI front-end for Taskwarrior"
"tickrs |tickrs |Stock ticker dashboard in the terminal"
"tldr |tealdeer |tldr-pages client: cheatsheets for commands"
"topgrade |topgrade |Update everything: brew, cargo, npm, pip, apt..."
"tv |television |Channel-based fuzzy finder, scales past fzf"
"zellij |zellij |Modern terminal multiplexer, tmux alternative"

# --- Editors ---
"hx|helix-term|Post-modern modal editor with built-in LSP"

# --- Workflow & Automation ---
"just |just |Project-scoped command runner, not a build system"
"mise |mise |Polyglot runtime + env vars + tasks (replaces asdf, nvm, direnv)"
"ouch |ouch |One verb works for every archive format"
"pueue|pueue|Persistent task queue daemon, survives SSH disconnects"

# --- AI / LLM ---
"aichat|aichat|Multi-provider LLM CLI with RAG, agents, shell assist"

# --- Terminal Recording & Sharing ---
"agg |agg |asciinema cast to animated GIF (crate is stale; see note above)"
"asciinema|asciinema|Terminal session recorder, now in Rust (v3+)"

# --- Build, Benchmark & Test ---
"hyperfine|hyperfine|Statistical CLI benchmarking tool"

# --- Text Processing ---
"choose|choose |Human-friendly column selector, cut/awk subset"
"sd |sd |Saner regex find-and-replace, simpler than sed"
"sg |ast-grep|Tree-sitter structural search/rewrite, pattern-as-code"
"srgn |srgn |Surgical search-replace via tree-sitter queries"
)


installed=0
skipped=0
failed=()

_cargo_install_root="${CARGO_INSTALL_ROOT:-${CARGO_HOME:-${HOME}/.cargo}}"
_cargo_bin_path="${_cargo_install_root}/bin"
[[ -d "${_cargo_bin_path}" ]] && export PATH="$PATH:${_cargo_bin_path}"

cargo_install_list="$(cargo install --list 2>/dev/null || true)"

function print-status() {
local status="$1"; shift
local desc="$*"; shift

printf "%-60s |${clr} %-60s " "${status}" "${desc}"
}

function print-bin-crate() {
local bin="$1"
local crate="$2"
printf "%-16s → %-16s" "${bin}" "${crate}"
}

for entry in "${TOOLS[@]}"; do
bin=
crate=
desc=

IFS='|' read -r bin crate desc <<<"${entry}"

bin="$(echo "${bin}" | tr -d ' ')"
crate="$(echo "${crate}" | tr -d ' ')"

if command -v ${bin} >/dev/null 2>&1; then
h.green "$(print-status "✓ $(print-bin-crate "${bin}" "${crate}") is pre-installed" "${desc}")"
skipped=$((skipped + 1))
continue
fi

if [[ -x "${_cargo_install_root}/bin/${bin}" ]]; then
h.green "$(print-status "✓ $(print-bin-crate "${bin}" "${crate}") exists, but not in \$PATH" "${desc}")"
skipped=$((skipped + 1))
continue
fi

if [[ -n "${cargo_install_list}" ]] && printf '%s\n' "${cargo_install_list}" | grep -q "^${crate} v"; then
h.green "$(print-status "✓ $(print-bin-crate "${bin}" "${crate}") was installed by cargo" "${desc}")"
skipped=$((skipped + 1))
continue
fi

h.yellow "$(print-status "✓ $(print-bin-crate "${bin}" "${crate}") is installing" "${desc}")"
if cargo binstall -y ${crate} >/dev/null 2>&1; then
installed=$((installed + 1))
else
warn "binstall of ${crate} failed, attempting to build from sources..."
if cargo install ${crate} >/dev/null 2>&1; then
installed=$((installed + 1))
else
warning "failed to install ${bin} (${crate})"
failed+=("${bin} (${crate})")
continue
fi
fi
done

hr
info "Installation completed. All the tools with their descriptions will be shown below."
sleep 3
hr

h1bg "Summary" "installed: ${installed}" "skipped: ${skipped}" "failed: ${#failed[@]}"

if (( ${#failed[@]} > 0 )); then
warn "The following did not install cleanly:"
for f in "${failed[@]}"; do
echo " • ${f}"
done
echo
echo "Tip: try \`cargo install <crate>\` directly — binstall sometimes can't find a"
echo "prebuilt for your platform, but a from-source build will still work."
fi

tool_col_width=15

catalog_lines=(
"$(printf '%-*s %s' "${tool_col_width}" 'Tool' 'Description')"
)

for entry in "${TOOLS[@]}"; do
IFS='|' read -r bin crate desc <<<"${entry}"
catalog_lines+=("$(printf '%-*s %s' "${tool_col_width}" "${bin}" "${desc}")")
done

h4bg "${catalog_lines[@]}"

export IFS="${OLD_IFS}"
2 changes: 2 additions & 0 deletions init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ function os.yaml() {
# Main Flow
#———————————————————————————————————————————————————————————————————————————

unalias find 2>/dev/null
unalias ls 2>/dev/null

# resolve BASHMATIC_HOME if necessary
__bashmatic.prerequisites
Expand Down
Loading
Loading