diff options
Diffstat (limited to 'linux/home/.config/zsh/user/prompt.zsh')
| -rw-r--r-- | linux/home/.config/zsh/user/prompt.zsh | 678 |
1 files changed, 0 insertions, 678 deletions
diff --git a/linux/home/.config/zsh/user/prompt.zsh b/linux/home/.config/zsh/user/prompt.zsh deleted file mode 100644 index b8b1b97..0000000 --- a/linux/home/.config/zsh/user/prompt.zsh +++ /dev/null @@ -1,678 +0,0 @@ -#!/bin/zsh - -########## Prompt(s) ########## - -# Autoload necessary functions for vcs_info and coloring -autoload -Uz vcs_info -autoload -Uz add-zsh-hook -autoload -U colors && colors - -# Enable prompt substitution -setopt prompt_subst - -# Display git branch status and color -precmd_vcs_info() { vcs_info } - -# Add vcs_info to precmd functions -precmd_functions+=( precmd_vcs_info ) - -# Manipulates cursor position: moves down by 2 lines, saves position, and restores cursor after an operation. -terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1] - -# Track last executed command for exit code display -typeset -g _last_executed_command="" -typeset -g _cmd_start_time=0 -typeset -g _cmd_end_time=0 -typeset -g _cmd_duration=0 -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 - -# Register the ZLE widget for spinner updates - do this early -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 - -# Calculate how much space is available for the prompt components -function available_space() { - local width=${COLUMNS:-80} - echo $width -} - -# 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 path_len=${#${PWD/#$HOME/\~}} - local git_full_len=0 - - # Try to estimate git info length if available - if git rev-parse --is-inside-work-tree &>/dev/null; then - local branch=$(git symbolic-ref --short HEAD 2>/dev/null) - git_full_len=${#branch} - - # Add length for status indicators - if [[ -n "$(git status --porcelain)" ]]; then - # Rough estimate for status text - git_full_len=$((git_full_len + 20)) - fi - fi - - # Calculate total space needed - local total_needed=$((vi_mode_len + prompt_base_len + path_len + git_full_len)) - - # Determine if we need to abbreviate - if [[ $total_needed -gt $available ]]; then - return 0 # Need to abbreviate - else - return 1 # Don't need to abbreviate - fi -} - -# Custom git branch coloring based on status -git_branch_test_color() { - local now=$(date +%s) - local cache_age=$((now - _git_cache_timestamp)) - - # Use cached value if available and not expired - if [[ -n "$_git_cached_info" && $cache_age -lt $_git_cache_lifetime ]]; then - echo "$_git_cached_info" - return - fi - - local ref=$(git symbolic-ref --short HEAD 2> /dev/null) - if [ -n "${ref}" ]; then - if [ -n "$(git status --porcelain)" ]; then - local gitstatuscolor='%F{green}' - else - local gitstatuscolor='%F{82}' - fi - _git_cached_info="${gitstatuscolor}${ref}" - _git_cache_timestamp=$now - echo "$_git_cached_info" - else - _git_cached_info="" - _git_cache_timestamp=$now - echo "" - fi -} - -# Git branch with dynamic abbreviation -git_branch_dynamic() { - local now=$(date +%s) - local cache_age=$((now - _git_cache_timestamp)) - - # Only query git if cache is expired - if [[ $cache_age -ge $_git_cache_lifetime ]]; then - local ref=$(git symbolic-ref --short HEAD 2> /dev/null) - if [ -n "${ref}" ]; then - if need_to_abbreviate_git; then - # Abbreviated version for small terminals - case "${ref}" in - "main") _git_cached_info="m" ;; - "master") _git_cached_info="m" ;; - "development") _git_cached_info="d" ;; - "develop") _git_cached_info="d" ;; - "feature/"*) _git_cached_info="f/${ref#feature/}" | cut -c 1-4 ;; - "release/"*) _git_cached_info="r/${ref#release/}" | cut -c 1-4 ;; - "hotfix/"*) _git_cached_info="h/${ref#hotfix/}" | cut -c 1-4 ;; - *) _git_cached_info="${ref}" | cut -c 1-5 ;; # Truncate to first 5 chars for other branches - esac - else - # Full branch name when there's room - _git_cached_info="${ref}" - fi - _git_cache_timestamp=$now - echo "$_git_cached_info" - else - _git_cached_info="" - _git_cache_timestamp=$now - echo "" - fi - else - echo "$_git_cached_info" - fi -} - -# VCS info styles (e.g., git) -zstyle ':vcs_info:*' check-for-changes true -zstyle ':vcs_info:*' enable git - -# Dynamically configure vcs_info formats based on available space -function configure_vcs_styles() { - if need_to_abbreviate_git; then - # Abbreviated versions - zstyle ':vcs_info:*' stagedstr ' +%F{15}s%f' - zstyle ':vcs_info:*' unstagedstr ' -%F{15}u%f' - else - # Full versions - zstyle ':vcs_info:*' stagedstr ' +%F{15}staged%f' - zstyle ':vcs_info:*' unstagedstr ' -%F{15}unstaged%f' - 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: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 - - if need_to_abbreviate_git; then - hook_com[unstaged]+='%F{196} !%f%F{15}u%f' - else - hook_com[unstaged]+='%F{196} !%f%F{15}untracked%f' - fi - fi -} - -# Dynamic git branch hook -+vi-git-dynamic() { - hook_com[branch]=$(git_branch_dynamic) -} - -# SSH info with conditional abbreviation -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" - else - ssh_info="ssh:%F{green}%n$nc%f" - if [[ -n $SSH_CONNECTION ]]; then - local ip_address - ip_address=$(echo $SSH_CONNECTION | awk '{print $3}') - ssh_info="$ssh_info@%F{green}$ip_address%f" - fi - fi - echo " ${ssh_info}" - fi -} - -# Job names (for job control) with conditional abbreviation -function job_name() { - job_name="" - job_length=0 - local available=$(available_space) - - # Only show jobs if we have reasonable space - if [ "${available}" -gt 60 ]; then - local job_count=$(jobs | wc -l) - if [ "${job_count}" -gt 0 ]; then - if need_to_abbreviate_git; then - job_name+="%F{green}j:${job_count}%f" - else - local title_jobs="jobs:" - 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 - job_name+="%F{green}${job_count}%f" - fi - fi - fi - fi - - echo "${job_name}" -} - -# Check if we should show the spinner based on elapsed time -function should_show_spinner() { - if [[ $_cmd_is_running -eq 1 ]]; then - local current_time=$(date +%s) - local elapsed=$((current_time - _cmd_start_time)) - - # Show spinner only after delay threshold - if [[ $elapsed -ge $_SPINNER_DELAY ]]; then - _show_spinner=1 - return 0 # Yes, show spinner - fi - fi - - _show_spinner=0 - return 1 # No, don't show spinner -} - -# Update spinner animation - simplified version -function update_spinner() { - # This function is now just a ZLE widget placeholder - # The actual spinner updates happen in the TRAPALRM handler - : -} - -# Start spinner timer when command runs longer than threshold -function start_spinner_timer() { - _spinner_idx=0 - _cmd_is_running=1 - _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 - - # Define TRAPALRM function - this is key to the spinner working - TRAPALRM() { - if [[ $_cmd_is_running -eq 1 ]]; then - local current_time=$(date +%s) - local elapsed=$((current_time - _cmd_start_time)) - - # Show spinner only after delay threshold - if [[ $elapsed -ge $_SPINNER_DELAY ]]; then - _show_spinner=1 - _spinner_idx=$(( (_spinner_idx + 1) % ${#_spinner_frames[@]} )) - - # Force prompt refresh - critical for updating the spinner - if [[ -o zle ]]; then - zle reset-prompt 2>/dev/null || true - zle -R - fi - fi - fi - } -} - -# Stop spinner when command finishes -function stop_spinner_timer() { - _cmd_is_running=0 - _show_spinner=0 - - # Disable the alarm trap and timer - TRAPALRM() { : } - TMOUT=0 - - # Force prompt refresh to clear spinner - if [[ -o zle ]]; then - zle reset-prompt 2>/dev/null || true - zle -R - fi -} - -# Format time in a human-readable way -function format_time() { - local seconds=$1 - local result="" - - # Format time as hours:minutes:seconds for long durations - if [[ $seconds -ge 3600 ]]; then - local hours=$((seconds / 3600)) - local minutes=$(( (seconds % 3600) / 60 )) - local secs=$((seconds % 60)) - result="${hours}h${minutes}m${secs}s" - elif [[ $seconds -ge 60 ]]; then - local minutes=$((seconds / 60)) - local secs=$((seconds % 60)) - result="${minutes}m${secs}s" - else - result="${seconds}s" - fi - - echo "$result" -} - -# Error code display for RPROMPT with spinner - fixed version -function exit_code_info() { - local exit_code=$? - - # If a command is running and we should show spinner - if [[ $_cmd_is_running -eq 1 && $_show_spinner -eq 1 ]]; then - local spinner=${_spinner_frames[$_spinner_idx]} - local current_time=$(date +%s) - local elapsed=$((current_time - _cmd_start_time)) - echo "%F{yellow}${spinner} ${elapsed}s%f" - return - fi - - # Don't show error code when line editor is active (user is typing) - if [[ -o zle ]]; then - echo "" - return - fi - - # Show command finished message for completed commands that took longer than threshold - if [[ -n "$_last_executed_command" && $_cmd_duration -ge $_FINISHED_DELAY ]]; then - local duration_formatted=$(format_time $_cmd_duration) - - # Show error code along with finished message if there was an error - if [[ $exit_code -ne 0 ]]; then - # Show TSTP (148) as a suspension indicator instead of error - if [[ $exit_code -eq 148 ]]; then - echo "%F{cyan}finished ${duration_formatted}%f %F{yellow}⏸ TSTP%f" - return - fi - - 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)) - signal_name=$(kill -l $signal_num 2>/dev/null) - if [[ -n "$signal_name" ]]; then - signal_name=" ($signal_name)" - fi - fi - - # Return formatted error code with finished message - echo "%F{cyan}finished ${duration_formatted}%f %F{red}✘ $exit_code$signal_name%f" - else - echo "%F{cyan}finished ${duration_formatted}%f %F{green}✓%f" - fi - return - fi - - # Don't show anything for exit code 0 (success) if this is first command - if [[ -z "$_last_executed_command" && $exit_code -eq 0 ]]; then - echo "" - return - fi - - # Show TSTP (148) as a suspension indicator instead of error - if [[ $exit_code -eq 148 ]]; then - echo "%F{yellow}⏸ TSTP%f" - return - fi - - 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)) - signal_name=$(kill -l $signal_num 2>/dev/null) - if [[ -n "$signal_name" ]]; then - signal_name=" ($signal_name)" - fi - fi - - # Return formatted error code - echo "%F{red}✘ $exit_code$signal_name%f" - else - echo "%F{green}✓%f" # Success indicator - fi -} - -abbreviated_path() { - local full_path="${PWD/#$HOME/~}" # Replace $HOME with ~ - local available=$(available_space) - - # If path is root - if [[ "$full_path" == "/" ]]; then - echo "%F{4}/%f" - return - fi - - # If path is just ~ - if [[ "$full_path" == "~" ]]; then - echo "%F{4}~%f" - return - fi - - # If extremely small terminal, show nothing to avoid breaking prompt - if (( available < 20 )); then - echo "" - return - fi - - # For very narrow terminals, just show the current dir - if (( available < 30 )); then - echo "%F{4}%1~%f" - return - fi - - # For moderately narrow terminals, show last two components - if (( available < 40 )); then - echo "%F{4}%2~%f" - return - fi - - # For wide terminals, show full path - if (( available > 70 )); then - echo "%F{4}${full_path}%f" - return - fi - - # Otherwise, show abbreviated path (e.g. ~/d/p/n) - local parts=("${(s:/:)full_path}") - local result="" - local last_index=${#parts[@]} - - 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%}" -machine="%F{4}%m%{$reset_color%}" -relative_home="%F{4}%~%{$reset_color%}" -carriage_return=""$'\n'"" -empty_line_bottom="" -chevron_right="" -color_reset="%{$(tput sgr0)%}" -color_yellow="%{$(tput setaf 226)%}" -color_blink="%{$(tput blink)%}" -prompt_symbol="$" -dollar_sign="${color_yellow}${color_blink}${prompt_symbol}${color_reset}" -dollar="%(?:%F{2}${dollar_sign}:%F{1}${dollar_sign})" -space=" " -#thin_space=$'\u2009' -thin_space=$'\u202F' -cmd_prompt="%(?:%F{2}${chevron_right} :%F{1}${chevron_right} )" -git_info="\$vcs_info_msg_0_" -v1="%{┌─[%}" -v2="%{]%}" -v3="└─[" -v4="]" -newline=$'\n' - -# Indicate INSERT mode for vi - NEVER truncate this -function insert-mode () { - echo "-- INSERT --" -} - -# Indicate NORMAL mode for vi - NEVER truncate this -function normal-mode () { - echo "-- NORMAL --" -} - -# Vi mode indicator -vi-mode-indicator () { - if [[ ${KEYMAP} == vicmd || ${KEYMAP} == vi-cmd-mode ]]; then - echo -ne '\e[1 q' - vi_mode=$(normal-mode) - elif [[ ${KEYMAP} == main || ${KEYMAP} == viins || ${KEYMAP} == '' ]]; then - echo -ne '\e[5 q' - vi_mode=$(insert-mode) - fi -} - -# 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 - - 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)" - - # Git info - omit entirely if not enough space - local gitinfo="" - if [[ $available -gt 40 ]]; then - gitinfo="${vcs_info_msg_0_}" - fi - - # Jobs info - local jobs=" $(job_name)" - - # SSH info - local sshinfo="$(ssh_name)" - - # Vi mode is priority 1 - ALWAYS show it - mode="%F{145}%{$terminfo_down_sc$vi_mode$terminfo[rc]%f%}" - - # Right prompt for error codes or spinner - #RPROMPT='$(exit_code_info)' - - PS1="${newline}${v1}${user}${v2} ${path_display}${gitinfo}${jobs}${sshinfo}${carriage_return}${mode}${v3}${dollar}${v4}${empty_line_bottom}" - fi -} - -# Pre-command hook to set prompt -my_precmd() { - # Calculate command duration if a command was run - if [[ -n "$_last_executed_command" && $_cmd_start_time -gt 0 ]]; then - _cmd_end_time=$(date +%s) - _cmd_duration=$((_cmd_end_time - _cmd_start_time)) - else - _cmd_duration=0 - fi - - stop_spinner_timer # Make sure spinner is stopped - vcs_info - set-prompt - vi-mode-indicator -} -add-zsh-hook precmd my_precmd - -# Update mode file based on current mode -update-mode-file() { - set-prompt - local current_mode=$(cat ~/.vi-mode 2>/dev/null || echo "") - local new_mode="$vi_mode" - - if [[ "$new_mode" != "$current_mode" ]]; then - echo "$new_mode" >| ~/.vi-mode - fi - - # Ensure we're in an interactive shell and ZLE is active - if [[ -o zle ]] && zle -l &>/dev/null; then - zle reset-prompt 2>/dev/null || true - else - # If ZLE is not active, fallback and print the prompt manually - set-prompt - print -Pn "$PS1" - fi - - # Refresh tmux client if tmux is running - if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then - tmux refresh-client -S - fi -} - -# Check if nvim is running and update mode -function check-nvim-running() { - if pgrep -x "nvim" > /dev/null; then - vi_mode="" - update-mode-file - if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then - tmux refresh-client -S - fi - else - if [[ ${KEYMAP} == vicmd || ${KEYMAP} == vi-cmd-mode ]]; then - vi_mode=$(normal-mode) - elif [[ ${KEYMAP} == main || ${KEYMAP} == viins || ${KEYMAP} == '' ]]; then - vi_mode=$(insert-mode) - fi - update-mode-file - if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then - tmux refresh-client -S - fi - fi -} - -# ZLE line initialization hook -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' - ;; - esac -} - -# ZLE keymap select hook -function zle-keymap-select() { - update-mode-file - zle reset-prompt - zle -R - vi-mode-indicator - case "${KEYMAP}" in - vicmd) - echo -ne '\e[1 q' - ;; - main|viins|*) - echo -ne '\e[5 q' - ;; - esac -} - -# Safer version of zle reset-prompt -function safe_reset_prompt() { - # Only reset if ZLE is active - if [[ -o zle ]] && zle -l &>/dev/null; then - zle reset-prompt 2>/dev/null || true - fi -} - -# Preexec hook for command execution - NO BACKGROUND JOBS VERSION -function preexec() { - # Store the command being executed - _last_executed_command=$1 - _cmd_start_time=$(date +%s) - _cmd_is_running=1 - _show_spinner=0 # Reset spinner flag - - # Start the spinner timer immediately - start_spinner_timer - - print -rn -- $terminfo[el] - echo -ne '\e[5 q' - vi-mode-indicator -} - -# Terminal resizing: resets the prompt if ZLE is active, updates the mode file. -TRAPWINCH() { - if [[ -o zle ]] && zle -l &>/dev/null; then - zle -R - zle reset-prompt 2>/dev/null || true - fi - update-mode-file 2>/dev/null -} - -# Register ZLE hooks -zle -N zle-line-init -zle -N zle-keymap-select -zle -N update_spinner - -# Register hooks -add-zsh-hook preexec preexec -add-zsh-hook precmd my_precmd - -set-prompt |
