feat(interactive): Add intuitive loop to go back to command search
Added seamless loop functionality for interactive mode:
Features:
1. Main Interactive Loop:
- Wrapped entire interactive mode in while true loop
- After viewing flags, prompts to search another command
- Press Enter to return to command menu
- Clear screen for clean UX
2. Multiple Exit Options:
- Esc in command menu: Clean exit with goodbye message
- Ctrl+C at prompt: Immediate exit
- Clear, intuitive navigation
3. User Flow:
Step 1: Select command from fuzzy search
Step 2: View command details and syntax
Step 3: Browse flags with fuzzy search
Step 4: Press Enter → Back to Step 1
OR Ctrl+C → Exit
4. Visual Feedback:
- Clear prompt: 'Press Enter to search another command'
- Separator lines for clarity
- Screen clear between iterations
- Goodbye message on exit
Benefits:
- No need to restart script for each command
- Intuitive navigation (Enter = continue, Esc/Ctrl+C = exit)
- Seamless command exploration workflow
- Better for learning/comparing multiple commands
- Professional UX with clear feedback
Example Session:
1. User selects 'ls' → views flags
2. Press Enter
3. Back to command menu, selects 'grep' → views flags
4. Press Enter
5. Back to command menu, selects 'tar' → views flags
6. Ctrl+C to exit
User Request: 'we also want a means to easily go back intuitively from after pulling up the fuzzy search for flags for a command back to the command fuzzy search'
This commit is contained in:
+86
-71
@@ -918,7 +918,7 @@ if [ -n "$MODE" ]; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Interactive mode with fzf
|
||||
# Interactive mode with fzf (loopable)
|
||||
if [ "$INTERACTIVE" = true ]; then
|
||||
# Check if fzf is available
|
||||
if ! command -v fzf &> /dev/null; then
|
||||
@@ -929,78 +929,86 @@ if [ "$INTERACTIVE" = true ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Format commands for display: description on left, syntax on right
|
||||
# Get terminal width for proper alignment
|
||||
TERM_WIDTH=$(tput cols 2>/dev/null || echo 120)
|
||||
# Main interactive loop
|
||||
while true; do
|
||||
# Format commands for display: description on left, syntax on right
|
||||
# Get terminal width for proper alignment
|
||||
TERM_WIDTH=$(tput cols 2>/dev/null || echo 120)
|
||||
|
||||
# Calculate widths (leave room for colors and spacing)
|
||||
MAX_CMD_WIDTH=15
|
||||
SYNTAX_WIDTH=45
|
||||
DESC_WIDTH=$((TERM_WIDTH - MAX_CMD_WIDTH - SYNTAX_WIDTH - 10))
|
||||
# Calculate widths (leave room for colors and spacing)
|
||||
MAX_CMD_WIDTH=15
|
||||
SYNTAX_WIDTH=45
|
||||
DESC_WIDTH=$((TERM_WIDTH - MAX_CMD_WIDTH - SYNTAX_WIDTH - 10))
|
||||
|
||||
# Ensure minimum widths
|
||||
if [ $DESC_WIDTH -lt 30 ]; then
|
||||
DESC_WIDTH=30
|
||||
SYNTAX_WIDTH=$((TERM_WIDTH - MAX_CMD_WIDTH - DESC_WIDTH - 10))
|
||||
fi
|
||||
|
||||
# Format each command with colors and right-aligned syntax
|
||||
FORMATTED_COMMANDS=()
|
||||
for cmd in "${COMMANDS[@]}"; do
|
||||
CMD_NAME=${cmd%%:*}
|
||||
REST=${cmd#*:}
|
||||
|
||||
# Extract description and syntax
|
||||
if [[ "$REST" =~ (.+)\ \|\ (.+) ]]; then
|
||||
DESC_PART="${BASH_REMATCH[1]}"
|
||||
SYNTAX_PART="${BASH_REMATCH[2]}"
|
||||
else
|
||||
DESC_PART="$REST"
|
||||
SYNTAX_PART="$CMD_NAME [options]"
|
||||
# Ensure minimum widths
|
||||
if [ $DESC_WIDTH -lt 30 ]; then
|
||||
DESC_WIDTH=30
|
||||
SYNTAX_WIDTH=$((TERM_WIDTH - MAX_CMD_WIDTH - DESC_WIDTH - 10))
|
||||
fi
|
||||
|
||||
# Truncate if too long (accounting for actual content, not color codes)
|
||||
if [ ${#DESC_PART} -gt $DESC_WIDTH ]; then
|
||||
DESC_PART="${DESC_PART:0:$((DESC_WIDTH-3))}..."
|
||||
fi
|
||||
if [ ${#SYNTAX_PART} -gt $SYNTAX_WIDTH ]; then
|
||||
SYNTAX_PART="${SYNTAX_PART:0:$((SYNTAX_WIDTH-3))}..."
|
||||
# Format each command with colors and right-aligned syntax
|
||||
FORMATTED_COMMANDS=()
|
||||
for cmd in "${COMMANDS[@]}"; do
|
||||
CMD_NAME=${cmd%%:*}
|
||||
REST=${cmd#*:}
|
||||
|
||||
# Extract description and syntax
|
||||
if [[ "$REST" =~ (.+)\ \|\ (.+) ]]; then
|
||||
DESC_PART="${BASH_REMATCH[1]}"
|
||||
SYNTAX_PART="${BASH_REMATCH[2]}"
|
||||
else
|
||||
DESC_PART="$REST"
|
||||
SYNTAX_PART="$CMD_NAME [options]"
|
||||
fi
|
||||
|
||||
# Truncate if too long (accounting for actual content, not color codes)
|
||||
if [ ${#DESC_PART} -gt $DESC_WIDTH ]; then
|
||||
DESC_PART="${DESC_PART:0:$((DESC_WIDTH-3))}..."
|
||||
fi
|
||||
if [ ${#SYNTAX_PART} -gt $SYNTAX_WIDTH ]; then
|
||||
SYNTAX_PART="${SYNTAX_PART:0:$((SYNTAX_WIDTH-3))}..."
|
||||
fi
|
||||
|
||||
# Calculate padding for right-alignment of syntax
|
||||
# Total visible length = cmd_name + ": " + desc + spaces + syntax
|
||||
CMD_LEN=${#CMD_NAME}
|
||||
DESC_LEN=${#DESC_PART}
|
||||
SYNTAX_LEN=${#SYNTAX_PART}
|
||||
NEEDED_SPACES=$((TERM_WIDTH - CMD_LEN - 2 - DESC_LEN - SYNTAX_LEN - 5))
|
||||
|
||||
# Ensure at least 2 spaces
|
||||
if [ $NEEDED_SPACES -lt 2 ]; then
|
||||
NEEDED_SPACES=2
|
||||
fi
|
||||
|
||||
# Create spacing string
|
||||
SPACES=$(printf '%*s' "$NEEDED_SPACES" '')
|
||||
|
||||
# Format with colors:
|
||||
# - Cyan for command name
|
||||
# - White for description
|
||||
# - Dim cyan for syntax
|
||||
formatted_line="\033[0;36m${CMD_NAME}\033[0m: ${DESC_PART}${SPACES}\033[2;36m${SYNTAX_PART}\033[0m"
|
||||
|
||||
FORMATTED_COMMANDS+=("$formatted_line")
|
||||
done
|
||||
|
||||
# Show in fzf with formatted display
|
||||
SELECTED=$(printf "%b\n" "${FORMATTED_COMMANDS[@]}" | fzf \
|
||||
--height 60% \
|
||||
--border \
|
||||
--header "Select a command (Esc to exit) | cyan: command | description | dim: syntax" \
|
||||
--prompt "🔍 Search: " \
|
||||
--preview-window=hidden \
|
||||
--ansi)
|
||||
|
||||
if [ -z "$SELECTED" ]; then
|
||||
# User pressed Esc or cancelled
|
||||
echo ""
|
||||
echo -e "${YELLOW}Exiting Bash Buddy. Happy coding! 👋${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Calculate padding for right-alignment of syntax
|
||||
# Total visible length = cmd_name + ": " + desc + spaces + syntax
|
||||
CMD_LEN=${#CMD_NAME}
|
||||
DESC_LEN=${#DESC_PART}
|
||||
SYNTAX_LEN=${#SYNTAX_PART}
|
||||
NEEDED_SPACES=$((TERM_WIDTH - CMD_LEN - 2 - DESC_LEN - SYNTAX_LEN - 5))
|
||||
|
||||
# Ensure at least 2 spaces
|
||||
if [ $NEEDED_SPACES -lt 2 ]; then
|
||||
NEEDED_SPACES=2
|
||||
fi
|
||||
|
||||
# Create spacing string
|
||||
SPACES=$(printf '%*s' "$NEEDED_SPACES" '')
|
||||
|
||||
# Format with colors:
|
||||
# - Cyan for command name
|
||||
# - White for description
|
||||
# - Dim cyan for syntax
|
||||
formatted_line="\033[0;36m${CMD_NAME}\033[0m: ${DESC_PART}${SPACES}\033[2;36m${SYNTAX_PART}\033[0m"
|
||||
|
||||
FORMATTED_COMMANDS+=("$formatted_line")
|
||||
done
|
||||
|
||||
# Show in fzf with formatted display
|
||||
SELECTED=$(printf "%b\n" "${FORMATTED_COMMANDS[@]}" | fzf \
|
||||
--height 60% \
|
||||
--border \
|
||||
--header "Select a command (cyan: command | description | dim: syntax)" \
|
||||
--prompt "🔍 Search: " \
|
||||
--preview-window=hidden \
|
||||
--ansi)
|
||||
|
||||
if [ -n "$SELECTED" ]; then
|
||||
# Extract command name from selection (strip color codes)
|
||||
CMD=$(echo "$SELECTED" | sed 's/\x1b\[[0-9;]*m//g' | awk -F: '{print $1}' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
|
||||
|
||||
@@ -1036,10 +1044,17 @@ if [ "$INTERACTIVE" = true ]; then
|
||||
|
||||
# Directly show fuzzy flag browser (no filter prompt)
|
||||
show_flags "$CMD"
|
||||
else
|
||||
echo "No command selected"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# After viewing flags, ask if user wants to search another command
|
||||
echo ""
|
||||
echo -e "${YELLOW}───────────────────────────────────────────────────────────${NC}"
|
||||
echo -e "${CYAN}Press Enter to search another command, or Ctrl+C to exit${NC}"
|
||||
echo -e "${YELLOW}───────────────────────────────────────────────────────────${NC}"
|
||||
read -r
|
||||
|
||||
# Clear screen for better UX
|
||||
clear
|
||||
done
|
||||
# Direct mode
|
||||
elif [ -n "$COMMAND" ]; then
|
||||
# Validate command exists in our list
|
||||
|
||||
Reference in New Issue
Block a user