From c653422734bf511ab0d0f91eef542c21d33d813f Mon Sep 17 00:00:00 2001 From: Robert Perce Date: Wed, 25 Mar 2026 10:50:18 -0500 Subject: [PATCH] tmux, bash, mgmt fiddling --- .chezmoiignore | 9 +++++ private_bin/private_executable_mgmt | 2 +- private_dot_bashrc.tmpl | 2 - .../private_mgmt/fns/bin_from.bash | 35 ++++++++++++++++ .../private_mgmt/fns/current.bash | 40 +++++++++++++++++++ .../private_mgmt/fns/github_latest.bash | 18 +++++++++ .../private_mgmt/fns/install_bin.bash | 17 ++++++++ .../private_mgmt/fns/is_latest.bash | 17 ++++++++ .../private_mod/unmanaged_packages.bash | 17 ++++++++ .../private_mgmt/private_packages | 2 +- .../private_tmux/private_tmux.conf.tmpl | 12 +++--- 11 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 private_dot_config/private_mgmt/fns/bin_from.bash create mode 100644 private_dot_config/private_mgmt/fns/current.bash create mode 100644 private_dot_config/private_mgmt/fns/github_latest.bash create mode 100644 private_dot_config/private_mgmt/fns/install_bin.bash create mode 100644 private_dot_config/private_mgmt/fns/is_latest.bash create mode 100644 private_dot_config/private_mgmt/private_mod/unmanaged_packages.bash diff --git a/.chezmoiignore b/.chezmoiignore index 0f69dda..7ad9e2d 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -16,3 +16,12 @@ README.md {{- if eq .chezmoi.osRelease.id "arch" | not }} bin/quickaur {{- end }} + +{{- if eq .chezmoi.osRelease.id "ubuntu" | not }} +.config/mgmt/mod/unmanaged_packages.bash +.config/mgmt/fns/bin_from.bash +.config/mgmt/fns/current.bash +.config/mgmt/fns/github_latest.bash +.config/mgmt/fns/install_bin.bash +.config/mgmt/fns/is_latest.bash +{{- end }} diff --git a/private_bin/private_executable_mgmt b/private_bin/private_executable_mgmt index fda0dd0..190ab37 100644 --- a/private_bin/private_executable_mgmt +++ b/private_bin/private_executable_mgmt @@ -8,7 +8,7 @@ positional=(); parse_args "$@" if [ -d "$mgmt_dir/fns" ]; then while IFS= read -rd '' fnfile; do source "$fnfile" - done < <(find "$functions" -type f -print0) + done < <(find "$mgmt_dir/fns" -type f -print0) fi PREFIX="" diff --git a/private_dot_bashrc.tmpl b/private_dot_bashrc.tmpl index 0a2762f..0c57883 100755 --- a/private_dot_bashrc.tmpl +++ b/private_dot_bashrc.tmpl @@ -23,8 +23,6 @@ if [[ "$PATH" != *"$HOME/bin"* ]]; then PATH=$PATH:"$HOME/bin" fi -bind 'set mark-symlinked-directories on' - export EDITOR='/usr/bin/env nvim' export VISUAL='/usr/bin/env nvim' diff --git a/private_dot_config/private_mgmt/fns/bin_from.bash b/private_dot_config/private_mgmt/fns/bin_from.bash new file mode 100644 index 0000000..4f9931f --- /dev/null +++ b/private_dot_config/private_mgmt/fns/bin_from.bash @@ -0,0 +1,35 @@ +# shellcheck shell=bash +bin_from() { + name="$1" + url="$2" + flag="$3" + + if [[ -z "$name" || -z "$url" ]]; then + diag "$(red "error: missing name ($name) or url ($url)!")" + exit 1 + fi + + if [[ "$url" == *.tar.gz || "$url" == *.tgz ]]; then + dir=$(mktemp -d) + if curl -sSL "$url" | tar -C "$dir" -xz 2>&1 | grep -q 'not in gzip format'; then + diag "$(red "error: file from $url not in gzip format")" + exit 1 + fi + file=$(find "$dir" -type f -name "$name") + elif [[ "$url" == *.tar.xz ]]; then + dir=$(mktemp -d) + curl -sSL "$url" | tar -C "$dir" -xJ + file=$(find "$dir" -type f -name "$name") + elif [[ "$url" == *.zip ]]; then + zip=$(mktemp --suffix=.zip) + dir=$(mktemp -d) + curl -sSL "$url" > "$zip" + unzip -qq "$zip" -d "$dir" + file=$(find "$dir" -type f -name "$name") + else + file="$(mktemp)" + curl -sSLo "$file" "$url" || diag "$(red "error from url [$url]")" + fi + + install_bin "$name" "$file" "$url" "$flag" +} diff --git a/private_dot_config/private_mgmt/fns/current.bash b/private_dot_config/private_mgmt/fns/current.bash new file mode 100644 index 0000000..de62c79 --- /dev/null +++ b/private_dot_config/private_mgmt/fns/current.bash @@ -0,0 +1,40 @@ +# shellcheck shell=bash +#================================================================ +#% SYNOPSIS +#+ current [-f ] [-r ] +#% +#% OPTIONS +#% -f set command-line args to pass to ; single string. +#% Default: [--version] +#% -r set regex used to extract version string from cmd output +#% Default: [v?(\d+\.\d+\.\d+)] +#================================================================ +current() { + flag="--version" + regex='v?(\d+\.\d+\.\d+)' + declare -a args + OPTIND=1 + while [ $OPTIND -le "$#" ]; do + if getopts :f:r: opt; then + case "$opt" in + \?) + diag "$(red "error: called 'current' badly")" + ;; + f) flag="$OPTARG" ;; + r) regex="$OPTARG" ;; + esac + else + args+=("${!OPTIND}") + (( OPTIND++ )) + fi + done + set -- "${args[@]}" + + cmd="$1" + + if command -v "$cmd" >/dev/null; then + bash -c "$cmd $flag" | perl -ne 'm/'"$regex"'/ && print "$1\n"' || true + else + true + fi +} diff --git a/private_dot_config/private_mgmt/fns/github_latest.bash b/private_dot_config/private_mgmt/fns/github_latest.bash new file mode 100644 index 0000000..f6906aa --- /dev/null +++ b/private_dot_config/private_mgmt/fns/github_latest.bash @@ -0,0 +1,18 @@ +# shellcheck shell=bash + +github_latest() { + repo="$1" + tag="${2:-latest}" + if [ "$tag" = "--no-latest-tag" ]; then + curl -sfSL "https://github.com/$repo/tags" \ + | perl -ne 'm,a href="/'"$repo"'/releases/tag/v(\d\.\d(?:.\d)?)", && print "$1\n"' \ + | sort -V \ + | tail -n1 || echo "[github error]" + else + curl -sfSI "https://github.com/$repo/releases/$tag" \ + | grep '^location' \ + | awk -F/ '{print $NF}' \ + | sed 's/\s\+$//' || echo "[github error]" + fi +} + diff --git a/private_dot_config/private_mgmt/fns/install_bin.bash b/private_dot_config/private_mgmt/fns/install_bin.bash new file mode 100644 index 0000000..4b3daa2 --- /dev/null +++ b/private_dot_config/private_mgmt/fns/install_bin.bash @@ -0,0 +1,17 @@ +# shellcheck shell=bash +install_bin() { + name="$1" + file="$2" + source="$3" + flag="$4" + + if file "$file" | grep -Eqv 'ELF|executable'; then + diag "$(red "error: file from $source not an executable")" + exit 1 + fi + + if [ "$flag" != "--no-backup" ] && [ -f "/usr/local/bin/$name" ]; then + sudo cp "/usr/local/bin/$name" "/usr/local/bin/$name.old" + fi + sudo install -m 755 "$file" "/usr/local/bin/$name" +} diff --git a/private_dot_config/private_mgmt/fns/is_latest.bash b/private_dot_config/private_mgmt/fns/is_latest.bash new file mode 100644 index 0000000..798a76f --- /dev/null +++ b/private_dot_config/private_mgmt/fns/is_latest.bash @@ -0,0 +1,17 @@ +is_latest() { + exe="$1" + latest="$2" + installed="$3" + silent="$4" + if ! command -v "$exe" > /dev/null; then + diag "$exe not installed; $latest available" + return 1 + elif [ "$latest" = "$installed" ]; then + test "$silent" = "silent" || diag "$exe already up to date" + elif [ "$latest" = "" ]; then + diag "[warn] 'latest' $exe is empty string" + else + diag "$exe $installed installed, but $latest available" + return 1 + fi +} diff --git a/private_dot_config/private_mgmt/private_mod/unmanaged_packages.bash b/private_dot_config/private_mgmt/private_mod/unmanaged_packages.bash new file mode 100644 index 0000000..f569699 --- /dev/null +++ b/private_dot_config/private_mgmt/private_mod/unmanaged_packages.bash @@ -0,0 +1,17 @@ +# shellcheck shell=bash +export DEPENDS=( mod/packages.bash ) + +_i_fzf() { + latest=$(github_latest junegunn/fzf) + diag "latest fzf $latest" + if ! is_latest fzf "$latest" $(current fzf); then + bin_from fzf "https://github.com/junegunn/fzf/releases/download/${latest}/fzf-${latest#v}-linux_amd64.tar.gz" + fi +} +apply() { + for fn in $(declare -F | awk '$3 ~ /^_i_/ { print $3 }'); do + $fn + done + + diag "all manual packages up to date" +} diff --git a/private_dot_config/private_mgmt/private_packages b/private_dot_config/private_mgmt/private_packages index c3e947a..6e7ef13 100644 --- a/private_dot_config/private_mgmt/private_packages +++ b/private_dot_config/private_mgmt/private_packages @@ -7,5 +7,5 @@ mosh nvim; termux:neovim arch:neovim ubuntu: rg; termux:ripgrep sqlite3; termux:sqlite -tailscale; termux: +tailscale; termux: ubuntu: tmux diff --git a/private_dot_config/private_tmux/private_tmux.conf.tmpl b/private_dot_config/private_tmux/private_tmux.conf.tmpl index 4212108..c381e0f 100644 --- a/private_dot_config/private_tmux/private_tmux.conf.tmpl +++ b/private_dot_config/private_tmux/private_tmux.conf.tmpl @@ -28,19 +28,17 @@ set -g status on set -g status-style bg=colour235,fg=brightblack set -g status-left-length 50 set -g status-right-length 50 +set -g status-justify centre +set -g status-left "#[fg=colour32] [#S] p#D ⧽ " {{- if has "phone" .class }} set -g status-position top -set -g status-justify left -set -g status-interval 15 -set -g status-left "#[fg=blue,bold]#S#[fg=brightblack,bg=colour235] ⧽ " -set -g status-right "#[fg=brightblack,bg=colour235]⧼ %Y-%m-%d" +set -g status-interval 60 +set -g status-right "#[fg=colour136]⧼ %m-%d" {{- else }} set -g status-position bottom -set -g status-justify centre set -g status-interval 1 -set -g status-left "#[fg=colour33,bg=colour235] #h ⧽ " -set -g status-right "#[bg=colour235,fg=colour136] ⧼ %a ⧼ %H:%M:%S ⧼ %Y-%m-%d " +set -g status-right "#[fg=colour136]⧼ %a ⧼ %H:%M:%S ⧼ %Y-%m-%d " set -g default-command fish {{- end }}