diff options
Diffstat (limited to 'common/config/zsh')
| -rw-r--r-- | common/config/zsh/.zshenv | 6 | ||||
| -rw-r--r-- | common/config/zsh/user/completion.zsh | 1 | ||||
| -rw-r--r-- | common/config/zsh/user/functions.zsh | 348 | ||||
| -rw-r--r-- | common/config/zsh/user/options.zsh | 8 | ||||
| -rw-r--r-- | common/config/zsh/user/prompt.zsh | 88 |
5 files changed, 313 insertions, 138 deletions
diff --git a/common/config/zsh/.zshenv b/common/config/zsh/.zshenv index b7b4f56..03d8f28 100644 --- a/common/config/zsh/.zshenv +++ b/common/config/zsh/.zshenv @@ -1,3 +1,9 @@ +# Source .profile if not already sourced +if [ -z "$PROFILE_SOURCED" ]; then + [ -f "$HOME/.profile" ] && source "$HOME/.profile" + export PROFILE_SOURCED=1 +fi + ####################################### # XDG Base Directories ####################################### diff --git a/common/config/zsh/user/completion.zsh b/common/config/zsh/user/completion.zsh index 2445548..984f28f 100644 --- a/common/config/zsh/user/completion.zsh +++ b/common/config/zsh/user/completion.zsh @@ -20,7 +20,6 @@ unset _comp_path # Skip the not really helpful global compinit skip_global_compinit=0 -DISABLE_MAGIC_FUNCTIONS=true #zstyle ':completion:*' menu select=1 diff --git a/common/config/zsh/user/functions.zsh b/common/config/zsh/user/functions.zsh index 7c79ee5..d93cec8 100644 --- a/common/config/zsh/user/functions.zsh +++ b/common/config/zsh/user/functions.zsh @@ -13,72 +13,124 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then *) CFG_OS="other" ;; esac - # Map system path to repository path _repo_path() { local f="$1" - # If it's an absolute path that's not in HOME, handle it specially - if [[ "$f" == /* && "$f" != "$HOME/"* ]]; then - echo "$CFG_OS/${f#/}" - return + # Normalize absolute or relative + if [[ "$f" == "$HOME/"* ]]; then + f="${f#$HOME/}" + elif [[ "$f" == "./"* ]]; then + f="${f#./}" fi - # Check for paths that should go to the repository root + # Already tracked? Use that + local dirs=("common/" "$CFG_OS/home/" "$CFG_OS/Users/") + for d in "${dirs[@]}"; do + local match="$(_config ls-files --full-name | grep -F "/$f" | grep -F "$d" || true)" + if [[ -n "$match" ]]; then + echo "$match" + return + fi + done + + # Already a special repo path case "$f" in - common/*|linux/*|macos/*|windows/*|profile/*|README.md) + common/*|"$CFG_OS/home/"*|"$CFG_OS/Users/"*|profile/*|README.md) echo "$f" return ;; - "$HOME/"*) - f="${f#$HOME/}" - ;; esac - # Default: put under OS-specific home - echo "$CFG_OS/home/$f" + # Map everything else dynamically + case "$f" in + *) + case "$CFG_OS" in + linux) echo "linux/home/$f" ;; + macos) echo "macos/Users/$f" ;; + windows) echo "windows/Users/$f" ;; + *) echo "$CFG_OS/home/$f" ;; + esac + ;; + esac } _sys_path() { local repo_path="$1" - local os_path_pattern="$CFG_OS/" - # Handle OS-specific files that are not in the home subdirectory - if [[ "$repo_path" == "$os_path_pattern"* && "$repo_path" != */home/* ]]; then - echo "/${repo_path#$os_path_pattern}" - return - fi + # System HOME + local sys_home + case "$CFG_OS" in + linux|macos) sys_home="$HOME" ;; + windows) sys_home="$USERPROFILE" ;; + esac + + # Repo HOME roots + local repo_home + case "$CFG_OS" in + linux) repo_home="linux/home" ;; + macos) repo_home="macos/Users" ;; + windows) repo_home="windows/Users" ;; + esac case "$repo_path" in - common/scripts/*) - echo "$HOME/.scripts/${repo_path#common/scripts/}" - ;; - common/config/*) - case "$CFG_OS" in - linux) - local base="${XDG_CONFIG_HOME:-$HOME/.config}" - echo "$base/${repo_path#common/config/}" + # Common files → $HOME/… but normalize well-known dirs + common/*) + local rel="${repo_path#common/}" + + case "$rel" in + # XDG config + .config/*|config/*) + local sub="${rel#*.config/}" + sub="${sub#config/}" + echo "${XDG_CONFIG_HOME:-$sys_home/.config}/$sub" + ;; + + # XDG data (assets, wallpapers, icons, fonts…) + assets/*|.local/share/*) + local sub="${rel#assets/}" + sub="${sub#.local/share/}" + echo "${XDG_DATA_HOME:-$sys_home/.local/share}/$sub" ;; - macos) - echo "$HOME/Library/Application Support/${repo_path#common/config/}" + + # XDG cache (if you ever store cached scripts/config) + .cache/*) + local sub="${rel#.cache/}" + echo "${XDG_CACHE_HOME:-$sys_home/.cache}/$sub" ;; - windows) - # Windows Bash (Git Bash, MSYS, WSL) respects LOCALAPPDATA - echo "$LOCALAPPDATA\\${repo_path#common/config/}" + + # Scripts + .scripts/*|scripts/*) + local sub="${rel#*.scripts/}" + sub="${sub#scripts/}" + echo "$sys_home/.scripts/$sub" ;; + + # Default: dump directly under $HOME *) - echo "$HOME/.config/${repo_path#common/config/}" + echo "$sys_home/$rel" ;; esac ;; - common/assets/*|profile/*|README.md) - echo "$HOME/.cfg/$repo_path" + + # Profile files → $HOME/… + profile/*) + local rel="${repo_path#profile/}" + echo "$sys_home/$rel" ;; - common/*) - echo "$HOME/.cfg/$repo_path" + + # OS-specific home paths → $HOME or $USERPROFILE + "$repo_home"/*) + local rel="${repo_path#$repo_home/}" + echo "$sys_home/$rel" ;; - */home/*) - echo "$HOME/${repo_path#*/home/}" + + # OS-specific system paths outside home/Users → absolute + "$CFG_OS/"*) + local rel="${repo_path#$CFG_OS/}" + echo "/$rel" ;; + + # Fallback: treat as repo-only *) echo "$HOME/.cfg/$repo_path" ;; @@ -106,68 +158,150 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then # Main config command config() { local cmd="$1"; shift - local target_dir="" - - # Parse optional --target flag for add - if [[ "$cmd" == "add" ]]; then - while [[ "$1" == --* ]]; do - case "$1" in - --target|-t) - target_dir="$2" - shift 2 - ;; - *) - echo "Unknown option: $1" - return 1 - ;; - esac - done - fi case "$cmd" in add) local file_path local git_opts=() local files=() + local target_dir="" - # Parse arguments + # Parse optional --target flag before files while [[ $# -gt 0 ]]; do case "$1" in --target|-t) target_dir="$2" shift 2 ;; - -*) # Any other flags are git flags + -*) # any other git flags git_opts+=("$1") shift ;; - *) # Anything else is a file + *) # files files+=("$1") shift ;; esac done - # Process each file for file_path in "${files[@]}"; do + # Store original for rel_path calculation + local original_path="$file_path" + + # Make path absolute first + if [[ "$file_path" != /* && "$file_path" != "$HOME/"* ]]; then + file_path="$(pwd)/$file_path" + fi + + # Check if file exists + if [[ ! -e "$file_path" ]]; then + echo "Error: File not found: $file_path" + continue + fi + + # Calculate relative path from original input + local rel_path + if [[ "$original_path" == "$HOME/"* ]]; then + rel_path="${original_path#$HOME/}" + elif [[ "$original_path" == "./"* ]]; then + rel_path="${original_path#./}" + else + rel_path="$original_path" + fi + + # Check if file is already tracked + local existing_path="$(_config ls-files --full-name | grep -Fx "$(_repo_path "$file_path")" || true)" local repo_path - if [[ -n "$target_dir" ]]; then - local rel_path - if [[ "$file_path" == /* ]]; then - rel_path="$(basename "$file_path")" - else - rel_path="$file_path" - fi + if [[ -n "$existing_path" ]]; then + repo_path="$existing_path" + elif [[ -n "$target_dir" ]]; then repo_path="$target_dir/$rel_path" else repo_path="$(_repo_path "$file_path")" fi + # Copy file into bare repo local full_repo_path="$HOME/.cfg/$repo_path" mkdir -p "$(dirname "$full_repo_path")" cp -a "$file_path" "$full_repo_path" - # Only git flags + repo_path go to git + # Add to git + _config add "${git_opts[@]}" "$repo_path" + + echo "Added: $file_path -> $repo_path" + done + ;; + + add) + local file_path + local git_opts=() + local files=() + local target_dir="" + local flatten=false + + # Parse options + while [[ $# -gt 0 ]]; do + case "$1" in + --target|-t) + target_dir="$2" + shift 2 + ;; + --flatten) + flatten=true + shift + ;; + -*) + git_opts+=("$1") + shift + ;; + *) + files+=("$1") + shift + ;; + esac + done + + for file_path in "${files[@]}"; do + local original_path="$file_path" + + if [[ "$file_path" != /* && "$file_path" != "$HOME/"* ]]; then + file_path="$(pwd)/$file_path" + fi + + if [[ ! -e "$file_path" ]]; then + echo "Error: File not found: $file_path" + continue + fi + + # Calculate relative path + local rel_path + if [[ "$original_path" == "$HOME/"* ]]; then + rel_path="${original_path#$HOME/}" + elif [[ "$original_path" == "./"* ]]; then + rel_path="${original_path#./}" + else + rel_path="$original_path" + fi + + # Already tracked? + local existing_path="$(_config ls-files --full-name | grep -Fx "$(_repo_path "$file_path")" || true)" + local repo_path + if [[ -n "$existing_path" ]]; then + repo_path="$existing_path" + elif [[ -n "$target_dir" ]]; then + if $flatten; then + repo_path="$target_dir/$(basename "$file_path")" + else + repo_path="$target_dir/$rel_path" + fi + else + repo_path="$(_repo_path "$file_path")" + fi + + # Copy and add + local full_repo_path="$HOME/.cfg/$repo_path" + mkdir -p "$(dirname "$full_repo_path")" + cp -a "$file_path" "$full_repo_path" _config add "${git_opts[@]}" "$repo_path" echo "Added: $file_path -> $repo_path" @@ -177,17 +311,43 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then rm) local rm_opts="" local file_path_list=() + local target_dir="" - for arg in "$@"; do - if [[ "$arg" == "-"* ]]; then - rm_opts+=" $arg" - else - file_path_list+=("$arg") - fi + # Parse options + while [[ $# -gt 0 ]]; do + case "$1" in + --target|-t) + target_dir="$2" + shift 2 + ;; + -*) + rm_opts+=" $1" + shift + ;; + *) + file_path_list+=("$1") + shift + ;; + esac done for file_path in "${file_path_list[@]}"; do - local repo_path="$(_repo_path "$file_path")" + local repo_path + # Check if already a repo path (exists in git index) - exact match + if _config ls-files --full-name | grep -qFx "$file_path"; then + repo_path="$file_path" + elif [[ -n "$target_dir" ]]; then + # Use target directory if specified + local rel_path + if [[ "$file_path" == "$HOME/"* ]]; then + rel_path="${file_path#$HOME/}" + else + rel_path="${file_path#./}" + fi + repo_path="$target_dir/$rel_path" + else + repo_path="$(_repo_path "$file_path")" + fi if [[ "$rm_opts" == *"-r"* ]]; then _config rm --cached -r "$repo_path" @@ -195,8 +355,12 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then _config rm --cached "$repo_path" fi - eval "rm $rm_opts \"$file_path\"" - echo "Removed: $file_path" + # Compute system path for actual file removal + local sys_file="$(_sys_path "$repo_path")" + if [[ -e "$sys_file" ]]; then + eval "rm $rm_opts \"$sys_file\"" + fi + echo "Removed: $repo_path" done ;; @@ -228,10 +392,17 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then ;; status) - # Check for missing files and auto-sync existing ones - local auto_synced=() + local modified_files=() local missing_files=() + # Colors like git + local RED="\033[31m" + local GREEN="\033[32m" + local YELLOW="\033[33m" + local BLUE="\033[34m" + local BOLD="\033[1m" + local RESET="\033[0m" + while read -r repo_file; do local sys_file="$(_sys_path "$repo_file")" local full_repo_path="$HOME/.cfg/$repo_file" @@ -240,31 +411,31 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then missing_files+=("$repo_file") elif [[ -e "$sys_file" ]]; then if ! diff -q "$full_repo_path" "$sys_file" >/dev/null 2>&1; then - cp -fa "$sys_file" "$full_repo_path" - auto_synced+=("$repo_file") + modified_files+=("$repo_file") fi fi done < <(_config ls-files) # Report missing files if [[ ${#missing_files[@]} -gt 0 ]]; then - echo "=== Missing Files (consider removing from git) ===" + echo -e "${BOLD}${RED}=== Missing Files (consider removing from git) ===${RESET}" for repo_file in "${missing_files[@]}"; do - echo "missing: $repo_file" + echo -e " ${RED}deleted:${RESET} $(_sys_path "$repo_file") -> $repo_file" done echo fi - # Report auto-synced files - if [[ ${#auto_synced[@]} -gt 0 ]]; then - echo "=== Auto-synced Files ===" - for repo_file in "${auto_synced[@]}"; do - echo "synced: $(_sys_path "$repo_file") -> $repo_file" + # Report modified files + if [[ ${#modified_files[@]} -gt 0 ]]; then + echo -e "${BOLD}${YELLOW}=== Modified Files (different from system) ===${RESET}" + for repo_file in "${modified_files[@]}"; do + echo -e " ${YELLOW}modified:${RESET} $(_sys_path "$repo_file") -> $repo_file" done echo fi - _config status + # Finally, show underlying git status (with colors) + _config -c color.status=always status ;; deploy|checkout) @@ -315,7 +486,6 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then } fi - # Make SUDO_ASKPASS agnostic: pick the first available askpass binary. # You can predefine SUDO_ASKPASS env var to force a particular path. : "${SUDO_ASKPASS:=""}" diff --git a/common/config/zsh/user/options.zsh b/common/config/zsh/user/options.zsh index 99840d7..aaa7b83 100644 --- a/common/config/zsh/user/options.zsh +++ b/common/config/zsh/user/options.zsh @@ -1,8 +1,8 @@ # Recursion limits FUNCNEST=999 - +# DISABLE_MAGIC_FUNCTIONS=true - +# # Enable various options for Zsh behavior setopt interactive_comments # Allow comments to appear in interactive mode unsetopt BEEP # Disable the system beep (to prevent annoying beeps) @@ -19,6 +19,10 @@ setopt AUTO_PUSHD # Save more directory history, and use "cd -" w # Hide history of commands starting with a space setopt histignorespace # Do not save commands that start with a space in the history +setopt BANG_HIST EXTENDED_HISTORY INC_APPEND_HISTORY SHARE_HISTORY +setopt HIST_EXPIRE_DUPS_FIRST HIST_IGNORE_DUPS HIST_IGNORE_ALL_DUPS +setopt HIST_FIND_NO_DUPS HIST_IGNORE_SPACE HIST_SAVE_NO_DUPS +setopt HIST_REDUCE_BLANKS HIST_VERIFY HIST_BEEP # --- Detect terminal control characters and behavior --- diff --git a/common/config/zsh/user/prompt.zsh b/common/config/zsh/user/prompt.zsh index c55a835..4a52138 100644 --- a/common/config/zsh/user/prompt.zsh +++ b/common/config/zsh/user/prompt.zsh @@ -1,6 +1,20 @@ #!/bin/zsh -########## Prompt(s) ########## +########## Prompt(s) ########## + +# Check if Nerd Fonts are installed +typeset -g _has_nerd_fonts=0 +if fc-list | grep -qi nerd; then + _has_nerd_fonts=1 +fi + +# Set git branch icon based on font availability +typeset -g _git_branch_icon +if [[ $_has_nerd_fonts -eq 1 ]]; then + _git_branch_icon=$'\uE0A0' # Nerd Font git branch icon +else + _git_branch_icon="±" # Fallback: plus-minus symbol +fi # Autoload necessary functions for vcs_info and coloring autoload -Uz vcs_info @@ -28,8 +42,8 @@ typeset -g _spinner_idx=0 typeset -ga _spinner_frames=('⣾' '⣽' '⣻' '⢿' '⡿' '⣟' '⣯' '⣷') typeset -g _cmd_is_running=0 typeset -g _show_spinner=0 -typeset -g _SPINNER_DELAY=5 # Only show spinner after 5 seconds -typeset -g _FINISHED_DELAY=10 # Only show finished message after 10 seconds +typeset -g _SPINNER_DELAY=5 # Only show spinner after 5 seconds +typeset -g _FINISHED_DELAY=10 # Only show finished message after 10 seconds # Register the ZLE widget for spinner updates - do this early zle -N update_spinner @@ -37,7 +51,7 @@ zle -N update_spinner # Cache git information to avoid repeated expensive operations typeset -g _git_cached_info="" typeset -g _git_cache_timestamp=0 -typeset -g _git_cache_lifetime=2 # seconds before cache expires +typeset -g _git_cache_lifetime=2 # seconds before cache expires # Calculate how much space is available for the prompt components function available_space() { @@ -48,8 +62,8 @@ function available_space() { # Check if we need to abbreviate git info function need_to_abbreviate_git() { local available=$(available_space) - local vi_mode_len=13 # Length of "-- INSERT --" - local prompt_base_len=20 # Base prompt elements length + local vi_mode_len=13 # Length of "-- INSERT --" + local prompt_base_len=20 # Base prompt elements length local path_len=${#${PWD/#$HOME/\~}} local git_full_len=0 @@ -70,9 +84,9 @@ function need_to_abbreviate_git() { # Determine if we need to abbreviate if [[ $total_needed -gt $available ]]; then - return 0 # Need to abbreviate + return 0 # Need to abbreviate else - return 1 # Don't need to abbreviate + return 1 # Don't need to abbreviate fi } @@ -158,15 +172,14 @@ function configure_vcs_styles() { fi zstyle ':vcs_info:*' actionformats '%F{5}%F{2}%b%F{3}|%F{1}%a%F{5}%f ' - zstyle ':vcs_info:*' formats '%F{208} '$'\uE0A0'' %f$(git_branch_test_color)%f%F{76}%c%F{3}%u%f ' + zstyle ':vcs_info:*' formats "%F{208} ${_git_branch_icon} %f\$(git_branch_test_color)%f%F{76}%c%F{3}%u%f " zstyle ':vcs_info:git*+set-message:*' hooks git-untracked git-dynamic } # Show "untracked" status in git - with conditional abbreviation +vi-git-untracked() { if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]] && \ - git status --porcelain | grep '??' &> /dev/null ; then - + git status --porcelain | grep '??' &> /dev/null ; then if need_to_abbreviate_git; then hook_com[unstaged]+='%F{196} !%f%F{15}u%f' else @@ -184,7 +197,6 @@ function configure_vcs_styles() { ssh_name() { if [[ -n $SSH_CONNECTION ]]; then local ssh_info - if need_to_abbreviate_git; then # Abbreviated SSH info ssh_info="ssh:%F{green}%n$nc%f" @@ -217,7 +229,6 @@ function job_name() { job_name="${title_jobs}" job_length=$((${available}-70)) [ "${job_length}" -lt "0" ] && job_length=0 - if [ "${job_length}" -gt 0 ]; then job_name+="%F{green}$(jobs | grep + | tr -s " " | cut -d " " -f 4- | cut -b 1-${job_length} | sed "s/\(.*\)/\1/")%f" else @@ -226,7 +237,6 @@ function job_name() { fi fi fi - echo "${job_name}" } @@ -239,12 +249,12 @@ function should_show_spinner() { # Show spinner only after delay threshold if [[ $elapsed -ge $_SPINNER_DELAY ]]; then _show_spinner=1 - return 0 # Yes, show spinner + return 0 # Yes, show spinner fi fi _show_spinner=0 - return 1 # No, don't show spinner + return 1 # No, don't show spinner } # Update spinner animation - simplified version @@ -258,10 +268,10 @@ function update_spinner() { function start_spinner_timer() { _spinner_idx=0 _cmd_is_running=1 - _show_spinner=0 # Start with spinner hidden until delay passes + _show_spinner=0 # Start with spinner hidden until delay passes # Set up the TRAPALRM for periodic updates - CRITICAL FIX - TMOUT=0.5 # Update spinner every 0.5 seconds + TMOUT=0.5 # Update spinner every 0.5 seconds # Define TRAPALRM function - this is key to the spinner working TRAPALRM() { @@ -385,7 +395,6 @@ function exit_code_info() { if [[ $exit_code -ne 0 ]]; then local signal_name="" - # Check if it's a signal if [[ $exit_code -gt 128 && $exit_code -le 165 ]]; then local signal_num=$((exit_code - 128)) @@ -398,12 +407,12 @@ function exit_code_info() { # Return formatted error code echo "%F{red}✘ $exit_code$signal_name%f" else - echo "%F{green}✓%f" # Success indicator + echo "%F{green}✓%f" # Success indicator fi } abbreviated_path() { - local full_path="${PWD/#$HOME/~}" # Replace $HOME with ~ + local full_path="${PWD/#$HOME/~}" # Replace $HOME with ~ local available=$(available_space) # If path is root @@ -450,12 +459,11 @@ abbreviated_path() { for i in {1..$((last_index - 1))}; do [[ -n ${parts[i]} ]] && result+="/${parts[i]:0:1}" done - result+="/${parts[last_index]}" + echo "%F{4}${result}%f" } - # Prompt variables user="%n" at="%F{15}at%{$reset_color%}" @@ -482,14 +490,10 @@ v4="]" newline=$'\n' # Indicate INSERT mode for vi - NEVER truncate this -function insert-mode () { - echo "-- INSERT --" -} +function insert-mode () { echo "-- INSERT --" } # Indicate NORMAL mode for vi - NEVER truncate this -function normal-mode () { - echo "-- NORMAL --" -} +function normal-mode () { echo "-- NORMAL --" } # Vi mode indicator vi-mode-indicator () { @@ -505,15 +509,15 @@ vi-mode-indicator () { # Prompt function to ensure the prompt stays on one line, even in narrow terminals function set-prompt() { vi-mode-indicator - configure_vcs_styles # Dynamically set vcs styles based on available space - vcs_info # Refresh vcs info with new styles + configure_vcs_styles # Dynamically set vcs styles based on available space + vcs_info # Refresh vcs info with new styles local available=$(available_space) + if (( available < 14 )); then # Extremely narrow terminal — use minimal prompt PS1="${carriage_return}${dollar}${space}${empty_line_bottom}" RPROMPT='$(exit_code_info)' - else # Path display - always show something for path, but adapt based on space local path_display="$(abbreviated_path)" @@ -550,7 +554,7 @@ my_precmd() { _cmd_duration=0 fi - stop_spinner_timer # Make sure spinner is stopped + stop_spinner_timer # Make sure spinner is stopped vcs_info set-prompt vi-mode-indicator @@ -609,12 +613,8 @@ function zle-line-init() { zle reset-prompt vi-mode-indicator case "${KEYMAP}" in - vicmd) - echo -ne '\e[1 q' - ;; - main|viins|*) - echo -ne '\e[5 q' - ;; + vicmd) echo -ne '\e[1 q' ;; + main|viins|*) echo -ne '\e[5 q' ;; esac } @@ -625,12 +625,8 @@ function zle-keymap-select() { zle -R vi-mode-indicator case "${KEYMAP}" in - vicmd) - echo -ne '\e[1 q' - ;; - main|viins|*) - echo -ne '\e[5 q' - ;; + vicmd) echo -ne '\e[1 q' ;; + main|viins|*) echo -ne '\e[5 q' ;; esac } @@ -648,7 +644,7 @@ function preexec() { _last_executed_command=$1 _cmd_start_time=$(date +%s) _cmd_is_running=1 - _show_spinner=0 # Reset spinner flag + _show_spinner=0 # Reset spinner flag # Start the spinner timer immediately start_spinner_timer |
