fix(ui): Fix color rendering and flush-right alignment

Addressed three critical UI issues identified by user:

1. Fixed Color Codes Showing Literally in Flag Browser
   - Changed colorize_syntax() to return raw string with \033 codes
   - Updated to use printf instead of echo -e for proper escaping
   - Changed printf format from %s to %b for syntax interpretation
   - Escape codes now render as colors, not literal text

2. Improved Right-Alignment to Be Flush to Edge
   - Reduced safety padding from 8 to 2 characters
   - Syntax now sits tighter to right edge
   - Looks cleaner and more professional
   - Calculates: NEEDED_SPACES = TERM_WIDTH - VISIBLE_WIDTH - 2

3. Added Colorized Syntax to Interactive Menu
   - Applied colorize_syntax() to menu display (was dim cyan)
   - [OPTIONS] now shows in yellow
   - FILE, PATTERN etc. now show in magenta
   - Command names in cyan + bold
   - Consistent with explain mode and flag browser
   - Updated fzf header to reflect color scheme

Technical Changes:
- colorize_syntax(): Returns raw \033 codes via printf %s
- Callers use printf %b to interpret escape sequences
- browse_flags_fuzzy(): Uses %b format for syntax line
- mode_explain(): Uses printf %b for colored output
- Interactive menu: Applies colorize_syntax() to SYNTAX_PART

Testing:
- ✓ Explain mode: Colors render correctly
- ✓ Interactive menu: Flush right, colorized syntax
- ✓ No literal \033 codes appear
- ✓ All three issues resolved

Before:
- Escape codes showing as literal text
- Too much gap before syntax
- Syntax all one color (dim cyan)

After:
- Colors render properly
- Minimal 2-char gap (flush right)
- [OPTIONS]=yellow, FILE=magenta, cmd=cyan
This commit is contained in:
2025-10-28 02:11:22 -07:00
parent c0af8c15ca
commit 3af2b2a6ff
+41 -31
View File
@@ -430,7 +430,8 @@ mode_explain() {
# Display colorized syntax # Display colorized syntax
if [ -n "$raw_syntax" ]; then if [ -n "$raw_syntax" ]; then
colorize_syntax "$raw_syntax" | sed 's/^/ /' local colored=$(colorize_syntax "$raw_syntax")
printf " %b\n" "$colored"
fi fi
echo "" echo ""
@@ -593,36 +594,38 @@ get_practical_example() {
} }
# Colorize syntax elements by type for instant recognition # Colorize syntax elements by type for instant recognition
# Returns raw string with ANSI codes (caller should use echo -e or printf %b)
colorize_syntax() { colorize_syntax() {
local syntax="$1" local syntax="$1"
local colored_syntax="$syntax" local colored_syntax="$syntax"
# Color scheme for syntax elements: # Color scheme for syntax elements:
# - Command name (first word): Bright cyan # - Command name (first word): Bright cyan + bold
# - [OPTIONS], [OPTION], etc.: Yellow # - [OPTIONS], [OPTION], etc.: Yellow
# - UPPERCASE args (FILE, STRING, SET1, etc.): Magenta # - UPPERCASE args (FILE, STRING, SET1, etc.): Magenta
# - Lowercase/optional args: Green # - Lowercase/optional args: Green
# - ... (ellipsis): Dim white # - ... (ellipsis): Dim white
# Extract command name (first word) # Extract command name (first word) - escape special chars for sed
local cmd_word=$(echo "$syntax" | awk '{print $1}') local cmd_word=$(echo "$syntax" | awk '{print $1}' | sed 's/[]\/$*.^[]/\\&/g')
# Start with command in bright cyan # Start with command in bright cyan + bold
colored_syntax=$(echo "$syntax" | sed "s/^$cmd_word/\\${CYAN}\\${BOLD}$cmd_word\\${NC}/") colored_syntax=$(echo "$syntax" | sed "s/^$cmd_word/\\\\033[0;36m\\\\033[1m$cmd_word\\\\033[0m/")
# Color [OPTIONS], [OPTION], [EXPRESSION], etc. in yellow # Color [OPTIONS], [OPTION], [EXPRESSION], etc. in yellow
colored_syntax=$(echo "$colored_syntax" | sed -E "s/\[([A-Z][A-Z_-]*)\]/[\\${YELLOW}\1\\${NC}]/g") colored_syntax=$(echo "$colored_syntax" | sed -E "s/\[([A-Z][A-Z_-]*)\]/[\\\\033[0;33m\1\\\\033[0m]/g")
# Color UPPERCASE arguments in magenta (FILE, STRING, PATH, SET1, etc.) # Color UPPERCASE arguments in magenta (FILE, STRING, PATH, SET1, etc.)
colored_syntax=$(echo "$colored_syntax" | sed -E "s/([[:space:]])([A-Z][A-Z0-9_-]*[A-Z])([[:space:][:punct:]$])/\1\\${MAGENTA}\2\\${NC}\3/g") colored_syntax=$(echo "$colored_syntax" | sed -E "s/([[:space:]])([A-Z][A-Z0-9_-]*[A-Z])([[:space:][:punct:]$])/\1\\\\033[0;35m\2\\\\033[0m\3/g")
# Color lowercase optional arguments in green # Color lowercase optional arguments in green
colored_syntax=$(echo "$colored_syntax" | sed -E "s/\[([a-z][a-z-]*)\]/[\\${GREEN}\1\\${NC}]/g") colored_syntax=$(echo "$colored_syntax" | sed -E "s/\[([a-z][a-z-]*)\]/[\\\\033[0;32m\1\\\\033[0m]/g")
# Color ellipsis (...) in dim white # Color ellipsis (...) in dim white
colored_syntax=$(echo "$colored_syntax" | sed "s/\.\.\./\\${DIM}...\\${NC}/g") colored_syntax=$(echo "$colored_syntax" | sed "s/\.\.\./\\\\033[2m...\\\\033[0m/g")
echo -e "$colored_syntax" # Return raw string (no echo -e, let caller handle interpretation)
printf "%s" "$colored_syntax"
} }
# Extract all flags from man page or help # Extract all flags from man page or help
@@ -663,15 +666,17 @@ browse_flags_fuzzy() {
local flag_count=$(echo "$all_flags" | wc -l) local flag_count=$(echo "$all_flags" | wc -l)
# Colorize the syntax for the header # Colorize the syntax for the header
# colorize_syntax now returns raw \033 codes that printf %b will interpret
local colored_syntax=$(colorize_syntax "$cmd_syntax") local colored_syntax=$(colorize_syntax "$cmd_syntax")
# Create multi-line header with command info # Create multi-line header with command info using printf %b for proper escape code interpretation
local header="╔═══════════════════════════════════════════════════════════════════════════════╗ # Use actual ANSI codes for command and description, use %b for colored syntax
║ Command: ${CYAN}${BOLD}$cmd_name${NC} local header
║ Syntax: $colored_syntax printf -v header "╔═══════════════════════════════════════════════════════════════════════════════╗\n║ Command: \033[0;36m\033[1m%s\033[0m\n║ Syntax: %b\n║ Desc: \033[0;32m%s\033[0m\n╚═══════════════════════════════════════════════════════════════════════════════╝\n🔍 Fuzzy search %d flags | Multi-select: Ctrl-A/D | Esc: Back to menu" \
║ Desc: ${GREEN}$cmd_desc${NC} "$cmd_name" \
╚═══════════════════════════════════════════════════════════════════════════════╝ "$colored_syntax" \
🔍 Fuzzy search $flag_count flags | Multi-select: Ctrl-A/D | Esc: Back to menu" "$cmd_desc" \
"$flag_count"
# Show in fzf with integrated command info # Show in fzf with integrated command info
echo "$all_flags" | fzf \ echo "$all_flags" | fzf \
@@ -993,29 +998,34 @@ if [ "$INTERACTIVE" = true ]; then
SYNTAX_PART="$CMD_NAME [options]" SYNTAX_PART="$CMD_NAME [options]"
fi fi
# Truncate if too long # Truncate description if too long
if [ ${#DESC_PART} -gt $DESC_WIDTH ]; then if [ ${#DESC_PART} -gt $DESC_WIDTH ]; then
DESC_PART="${DESC_PART:0:$((DESC_WIDTH-3))}..." DESC_PART="${DESC_PART:0:$((DESC_WIDTH-3))}..."
fi fi
# Truncate syntax if too long (before colorizing)
if [ ${#SYNTAX_PART} -gt $SYNTAX_WIDTH ]; then if [ ${#SYNTAX_PART} -gt $SYNTAX_WIDTH ]; then
SYNTAX_PART="${SYNTAX_PART:0:$((SYNTAX_WIDTH-3))}..." SYNTAX_PART="${SYNTAX_PART:0:$((SYNTAX_WIDTH-3))}..."
fi fi
# Colorize the syntax (command in cyan, [OPTIONS] in yellow, FILE in magenta, etc.)
# colorize_syntax returns raw string with \033 codes, need to preserve them
COLORIZED_SYNTAX=$(colorize_syntax "$SYNTAX_PART")
# Calculate exact padding needed for right-alignment # Calculate exact padding needed for right-alignment
# Account for visual width only (not ANSI codes) # Use UNCOLORIZED lengths for spacing calculation
CMD_LEN=${#CMD_NAME} CMD_LEN=${#CMD_NAME}
DESC_LEN=${#DESC_PART} DESC_LEN=${#DESC_PART}
SYNTAX_LEN=${#SYNTAX_PART} SYNTAX_LEN=${#SYNTAX_PART} # Use original length, not colorized
# Calculate spaces needed: terminal width - all visible characters - separator chars # Calculate spaces needed for flush right-alignment
# Visible: cmd + ": " + desc + syntax = CMD_LEN + 2 + DESC_LEN + SYNTAX_LEN # Account for: cmd + ": " + desc + spaces + syntax
# Reduce safety padding from 8 to 2 for tighter right-alignment
VISIBLE_WIDTH=$((CMD_LEN + 2 + DESC_LEN + SYNTAX_LEN)) VISIBLE_WIDTH=$((CMD_LEN + 2 + DESC_LEN + SYNTAX_LEN))
NEEDED_SPACES=$((TERM_WIDTH - VISIBLE_WIDTH - 8)) # Extra padding for safety NEEDED_SPACES=$((TERM_WIDTH - VISIBLE_WIDTH - 2)) # Minimal padding for flush right
# Minimum spacing # Ensure minimum spacing
[ $NEEDED_SPACES -lt 3 ] && NEEDED_SPACES=3 [ $NEEDED_SPACES -lt 2 ] && NEEDED_SPACES=2
# Maximum spacing to prevent excessive gaps
[ $NEEDED_SPACES -gt 20 ] && NEEDED_SPACES=20
# Create spacing string # Create spacing string
SPACES=$(printf '%*s' "$NEEDED_SPACES" '') SPACES=$(printf '%*s' "$NEEDED_SPACES" '')
@@ -1023,8 +1033,8 @@ if [ "$INTERACTIVE" = true ]; then
# Format with colors: # Format with colors:
# - Bright cyan for command name # - Bright cyan for command name
# - White for description # - White for description
# - Dim cyan for syntax (right-aligned) # - Colorized syntax (right-aligned with cyan cmd, yellow [OPTIONS], magenta FILE, etc.)
formatted_line="\033[0;36m${CMD_NAME}\033[0m: ${DESC_PART}${SPACES}\033[2;36m${SYNTAX_PART}\033[0m" formatted_line="\033[0;36m${CMD_NAME}\033[0m: ${DESC_PART}${SPACES}${COLORIZED_SYNTAX}"
FORMATTED_COMMANDS+=("$formatted_line") FORMATTED_COMMANDS+=("$formatted_line")
done done
@@ -1033,7 +1043,7 @@ if [ "$INTERACTIVE" = true ]; then
SELECTED=$(printf "%b\n" "${FORMATTED_COMMANDS[@]}" | fzf \ SELECTED=$(printf "%b\n" "${FORMATTED_COMMANDS[@]}" | fzf \
--height 60% \ --height 60% \
--border \ --border \
--header "Select a command (Esc to exit) | cyan: command | description | dim: syntax" \ --header "Select a command (Esc to exit) | Colorized: cmd=[cyan] [OPTIONS]=[yellow] FILE=[magenta]" \
--prompt "🔍 Search: " \ --prompt "🔍 Search: " \
--preview-window=hidden \ --preview-window=hidden \
--ansi) --ansi)