diff --git a/.gitignore b/.gitignore index 65381ba..32112d3 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,7 @@ profiles/* # Jupyter jupyter/workspace/* -!jupyter/workspace/000-sample.ipynb \ No newline at end of file +!jupyter/workspace/000-sample.ipynb + +# History +.history \ No newline at end of file diff --git a/compose.gum.yml b/compose.gum.yml new file mode 100644 index 0000000..a08bddc --- /dev/null +++ b/compose.gum.yml @@ -0,0 +1,5 @@ +services: + gum: + build: + context: ./gum + dockerfile: Dockerfile \ No newline at end of file diff --git a/gum/Dockerfile b/gum/Dockerfile new file mode 100644 index 0000000..c5b4df1 --- /dev/null +++ b/gum/Dockerfile @@ -0,0 +1,4 @@ +FROM busybox:1.35.0-uclibc as busybox +COPY --from=ghcr.io/charmbracelet/gum /usr/local/bin/gum /usr/local/bin/gum + +ENTRYPOINT [ "/usr/local/bin/gum" ] \ No newline at end of file diff --git a/harbor.sh b/harbor.sh index bc16e7d..6298d89 100755 --- a/harbor.sh +++ b/harbor.sh @@ -95,6 +95,12 @@ show_help() { echo " profile add|save - Add current config as a profile" echo " profile set|use|load - Use a profile" echo + echo " history|h [ls|rm|add] - Harbor command history." + echo " When run without arguments, launches interactive selector." + echo " history clear - Clear the history" + echo " history size - Get/set the history size" + echo " history list|ls - List recored history" + echo echo " defaults [ls|rm|add] - List default services" echo " defaults rm - Remove, also accepts handle or index" echo " defaults add - Add" @@ -796,9 +802,11 @@ execute_and_process() { } swap_and_retry() { + local command=$1 shift local args=("$@") + record_history_entry "$default_history_file" "$default_history_size" "${args[*]}" # Try original order if "$command" "${args[@]}"; then @@ -1737,12 +1745,86 @@ establish_tunnel() { log_info "Tunnel URL: $tunnel_url" print_qr "$tunnel_url" || { log_error "Failed to print QR code"; exit 1; } } + +record_history_entry() { + local file="$1" + local max_entries="$2" + local input="harbor $3" + + # Check if the input already exists in the file + if ! grep -Fxq -- "$input" "$file" 2>/dev/null; then + log_debug "Recording history entry: '$file', '$max_entries', '$input'" + + printf '%s\n' "$input" >> "$file" + + # If we've exceeded max entries, remove oldest entries + if [ "$(wc -l < "$file")" -gt "$max_entries" ]; then + tail -n "$max_entries" "$file" > "$file.tmp" && mv "$file.tmp" "$file" + fi + fi +} + +run_harbor_history() { + case "$1" in + ls|list) + shift + cat "$default_history_file" + ;; + size) + shift + env_manager_alias history.size "$@" + ;; + clear) + log_info "Clearing history" + echo "" > "$default_history_file" + ;; + --help|-h) + echo "Harbor history management" + echo + echo "Usage: harbor history {ls|size|clear}" + echo + echo "Commands:" + echo " ls|list - List all history entries" + echo " size - Get or set the maximum number of history entries" + echo " clear - Clear all history entries" + return 0 + ;; + *) + local max_entries=10 + local history_file="$default_history_file" + local tmp_dir=$(mktemp -d) + local services=$(get_active_services) + + local output_file="$tmp_dir/selected_command.txt" + local entrypoint="/bin/sh -c \"/usr/local/bin/gum filter < ${history_file} > /tmp/gum_test/selected_command.txt\"" + + $(compose_with_options $services "gum") run \ + --rm \ + -it \ + -e "TERM=xterm-256color" \ + -v "$harbor_home:$harbor_home" \ + -v "$tmp_dir:/tmp/gum_test" \ + --workdir "$harbor_home" \ + --entrypoint "$entrypoint" \ + gum + + if [ -s "$output_file" ]; then + log_debug "Selected command: $(cat "$output_file")" + eval "$(cat "$output_file")" + else + log_info "No command selected" + fi + + rm -rf "$tmp_dir" + ;; + esac +} + # shellcheck disable=SC2034 __anchor_service_clis=true run_gum() { - local gum_image=ghcr.io/charmbracelet/gum - docker run --rm -it -e "TERM=xterm-256color" $gum_image "$@" + docker run --rm -it -e "TERM=xterm-256color" $default_gum_image "$@" } run_dive() { @@ -2924,15 +3006,22 @@ run_jupyter_command() { # ======================================================================== # Globals -version="0.1.22" +version="0.1.23" harbor_repo_url="https://github.com/av/harbor.git" delimiter="|" scramble_exit_code=42 harbor_home=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")") -original_dir=$PWD -cd "$harbor_home" || exit profiles_dir="$harbor_home/profiles" default_profile="$profiles_dir/default.env" +default_gum_image="ghcr.io/charmbracelet/gum" + +original_dir=$PWD +cd "$harbor_home" || exit + +# Set color variables +set_colors +# Initialize the log levels +set_default_log_levels # Config ensure_env_file @@ -2942,12 +3031,8 @@ default_open=$(env_manager get ui.main) default_autoopen=$(env_manager get ui.autoopen) default_container_prefix=$(env_manager get container.prefix) default_log_level=$(env_manager get log.level) - -# Set color variables -set_colors - -# Initialize the log levels -set_default_log_levels +default_history_file=$(env_manager get history.file) +default_history_size=$(env_manager get history.size) main_entrypoint() { case "$1" in @@ -3230,6 +3315,10 @@ main_entrypoint() { shift run_bench_command "$@" ;; + history|h) + shift + run_harbor_history "$@" + ;; *) return $scramble_exit_code ;; diff --git a/package.json b/package.json index a172d4d..415bfc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@av/harbor", - "version": "0.1.22", + "version": "0.1.23", "bin": { "harbor": "./bin/harbor" } diff --git a/profiles/default.env b/profiles/default.env index fc9c654..d4098f0 100644 --- a/profiles/default.env +++ b/profiles/default.env @@ -57,6 +57,8 @@ HARBOR_CLI_NAME="harbor" HARBOR_CLI_SHORT="h" HARBOR_CLI_PATH="~/.local/bin" HARBOR_LOG_LEVEL="INFO" +HARBOR_HISTORY_SIZE=10 +HARBOR_HISTORY_FILE="./.history" # OpenAI # ---------------------