From 21b24b2c2ffa4c3ccf13c55c3ffd7ce24131f3b5 Mon Sep 17 00:00:00 2001 From: David Tomaschik Date: Thu, 12 Feb 2026 15:52:10 -0800 Subject: [PATCH] Start on "cloudy" --- bin/cloudy.sh | 148 +++++++++++++++++++++++++++++++++ dotfiles/gemini/settings.json | 5 +- dotfiles/local/lib/bash/tui.sh | 107 ++++++++++++++++++++++++ 3 files changed, 259 insertions(+), 1 deletion(-) create mode 100755 bin/cloudy.sh create mode 100644 dotfiles/local/lib/bash/tui.sh diff --git a/bin/cloudy.sh b/bin/cloudy.sh new file mode 100755 index 0000000..c9f2be4 --- /dev/null +++ b/bin/cloudy.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash + +set -ueo pipefail +shopt -s extglob + +# get libraries +. ${HOME}/.local/lib/bash/tui.sh + +COMMANDS=( + gctx + kctx +) + +_make_extglob() { + local IFS='|' + echo "@($*)" +} + +CMD_PATTERN=$(_make_extglob "${COMMANDS[@]}") + +usage() { + echo "Available Subcommands:" + printf " - %-10s\n" "${COMMANDS[@]}" + exit 1 +} + +_gctx_set() { + gcloud config configurations activate "${1}" maxnamelen ) ? ${#name} : maxnamelen )) + if [[ "$active" == "True" ]] ; then + default="${name}" + fi + lines+=("${name}" "${description}") + done < <(gcloud config configurations list \ + --format='value(is_active, name, format("{} (as {})", properties.core.project, properties.core.account))') + local choice + if choice=$(printf "%-${maxnamelen}s %s\n" "${lines[@]}" | select_entry "gcloud config" "$default") ; then + _gctx_set "${choice}" + else + echo "No option selected, leaving unchanged." + fi + return 0 +} + +_gctx_new() { + local cname="${1:-}" + if test -z "${cname}" ; then + echo "Usage: gctx new " >&2 + return 1 + fi + gcloud config configurations create "${cname}" +} + +_gctx_name() { + gcloud info --format='value(config.active_config_name)' +} + +_gctx_clone() { + # save old config + local oldconfig=() + local line + while IFS= read -r line ; do + old_config+=("$line") + done < <(gcloud config configurations describe "$(_gctx_name)" --format='multi(properties:format="flattened[separator=\" \"]")') + + # create new + _gctx_new "${1:-}" + + # set config + for line in "${oldconfig[@]}" ; do + local keyname="${line%% *}" + local keypath="${keyname//\.//}" + local value="${line#* }" + gcloud config set "${keypath}" "${value}" + done + return 0 +} + +gctx() { + local subcmd="${1:-}" + shift || true + case "${subcmd}" in + clone) + _gctx_clone "$@" + return + ;; + new) + _gctx_new "$@" + return + ;; + show) + gcloud config configurations list --filter="is_active=True" \ + --format='table(name, properties.core.account, properties.core.project, properties.compute.zone:label=COMPUTE_DEFAULT_ZONE, properties.compute.region:label=COMPUTE_DEFAULT_REGION)' \ + "$@" + ;; + list) + gcloud config configurations list "$@" + return + ;; + activate) + _gctx_set "$@" + return + ;; + ""|choose) + _gctx_choose + return + ;; + *) + if _gctx_set "${subcmd}" 2>/dev/null ; then + return 0 + fi + echo "Usage: gctx [show|list|new|choose|clone|]" >&2 + return 1 + ;; + esac +} + +kctx() { + return 0 +} + +INVOKED_AS=$(basename "$0") +# shellcheck disable=SC2053 +if [[ "$INVOKED_AS" == $CMD_PATTERN ]] ; then + CMD="${INVOKED_AS}" +else + CMD="${1:-}" + shift || usage +fi + + +# shellcheck disable=SC2254 +case "${CMD}" in + ${CMD_PATTERN}) + "${CMD}" "$@" + ;; + *) + usage + ;; +esac diff --git a/dotfiles/gemini/settings.json b/dotfiles/gemini/settings.json index e7828ce..cd3d629 100644 --- a/dotfiles/gemini/settings.json +++ b/dotfiles/gemini/settings.json @@ -10,5 +10,8 @@ "GEMINI.md" ] }, - "selectedAuthType": "gemini-api-key" + "selectedAuthType": "gemini-api-key", + "general": { + "vimMode": true + } } \ No newline at end of file diff --git a/dotfiles/local/lib/bash/tui.sh b/dotfiles/local/lib/bash/tui.sh new file mode 100644 index 0000000..e25ec33 --- /dev/null +++ b/dotfiles/local/lib/bash/tui.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash + +# verify array support +if eval '_t=(1)' 2>/dev/null; then + unset _t +else + echo "Error: This script requires a shell with array and local variable support (like Bash or Zsh)." >&2 + (return 0 2>/dev/null) && return 1 || exit 1 +fi + +select_entry() { + # interactive selection from a list + # usage: select_entry "$prompt" "$default" + local prompt="${1:-Select an entry}" + local default_choice="${2:-}" + local input_data + + if [[ -t 0 ]] ; then + echo "select_entry should be used with piped input" >&2 + return 1 + fi + + input_data=$(cat) + + if [[ -z "$input_data" ]]; then + return 1 + fi + + local display_prompt="$prompt" + if [[ -n "$default_choice" ]]; then + display_prompt="$prompt [$default_choice]" + fi + + if [[ -z "${NO_FZF:-}" ]] && command -v fzf >/dev/null 2>&1; then + local fzf_input="$input_data" + + # If a default is provided, move that line to the very top + # so fzf's cursor starts on it. + if [[ -n "$default_choice" ]]; then + local default_line + default_line=$(echo "$input_data" | grep "^$default_choice\([[:space:]]\|$\)") + if [[ -n "$default_line" ]]; then + # Remove the original line and prepend it to the top + fzf_input=$(printf "%s\n%s" "$default_line" "$(echo "$input_data" | grep -v "^$default_choice\([[:space:]]\|$\)")") + fi + fi + + local choice + choice=$(echo "$fzf_input" | \ + fzf --prompt="$prompt: " --accept-nth 1 --height '~100%' --reverse) + if [[ -z "$choice" ]]; then + [[ -n "$default_choice" ]] && echo "$default_choice" && return 0 + return 1 + fi + echo "${choice}" + return 0 + else + local i=1 + local lines=() + + printf "\n--- %s ---\n" "$prompt" >&2 + + # Load lines into an array + while IFS= read -r line; do + [[ -z "$line" ]] && continue + printf "%2d) %s\n" "$i" "$line" + lines[i]="$line" + ((i++)) + done <<< "$input_data" + + local count=$((i - 1)) + + printf "%s (1-%d or word): " "$display_prompt" "$count" >&2 + read -r choice + + if [[ -z "$choice" ]]; then + if [[ -n "$default_choice" ]]; then + echo "$default_choice" + return 0 + else + return 1 + fi + fi + + # Match logic + if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= count )); then + echo "${lines[$choice]}" | awk '{print $1}' + else + # Iterate to find word match + local found=0 + for (( j=1; j<=count; j++ )); do + local current_line="${lines[$j]}" + local first_word="${current_line%%[[:space:]]*}" + if [[ "$choice" == "$first_word" ]]; then + echo "$first_word" + found=1 + break + fi + done + + if [[ $found -eq 0 ]]; then + echo "Invalid selection: $choice" >&2 + return 1 + fi + fi + fi +}