diff --git a/bash-helper.sh b/bash-helper.sh index fde9c00..205d517 100755 --- a/bash-helper.sh +++ b/bash-helper.sh @@ -17,13 +17,12 @@ NC='\033[0m' # No Color # ASCII Banner show_banner() { - echo -e "${CYAN}" - echo " ____ __ ____ __ __" - echo " / __ )____ ______/ /_ / __ )__ ______/ /___/ /_ __" - echo " / __ / __ \`/ ___/ __ \\ / __ / / / / __ / __ / / / /" - echo " / /_/ / /_/ (__ ) / / / / /_/ / /_/ / /_/ / /_/ / /_/ /" - echo "/_____/\\__,_/____/_/ /_/ /_____/\\__,_/\\__,_/\\__,_/\\__, /" - echo " /____/" + echo -e "${CYAN} ____ __ ____ __ __" + echo -e " / __ )____ ______/ /_ / __ )__ ______/ /___/ /_ __" + echo -e " / __ / __ \`/ ___/ __ \\ / __ / / / / __ / __ / / / /" + echo -e " / /_/ / /_/ (__ ) / / / / /_/ / /_/ / /_/ / /_/ / /_/ /" + echo -e "/_____/\\__,_/____/_/ /_/ /_____/\\__,_/\\__,_/\\__,_/\\__, /" + echo -e " /____/${NC}" echo -e "${YELLOW} Your Intelligent CLI Assistant for Bash${NC}" echo "" } @@ -477,25 +476,83 @@ mode_explain() { echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" } +# Get quick syntax for a command +get_quick_syntax() { + local cmd="$1" + local syntax="" + + if type "$cmd" 2>/dev/null | grep -q "shell builtin"; then + syntax=$(help "$cmd" 2>/dev/null | head -1 | sed 's/^[[:space:]]*//' | cut -c1-60) + else + # Try to get first line from man page SYNOPSIS + syntax=$(man "$cmd" 2>/dev/null | col -b | sed -n '/^SYNOPSIS/,/^DESCRIPTION/p' | sed -n '2p' | sed 's/^[[:space:]]*//' | cut -c1-60) + + if [ -z "$syntax" ]; then + # Fallback to --help + syntax=$("$cmd" --help 2>&1 | grep -i "usage" | head -1 | sed 's/^[Uu]sage: //' | cut -c1-60) + fi + + if [ -z "$syntax" ]; then + syntax="$cmd [options]" + fi + fi + + echo "$syntax" +} + show_flags() { CMD_NAME=$1 FILTER=$2 echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - echo -e "${YELLOW}Flags for: ${GREEN}$CMD_NAME${NC}" + echo -e "${YELLOW}Command Details: ${GREEN}$CMD_NAME${NC}" if [ -n "$FILTER" ]; then echo -e "${YELLOW}Filter: ${GREEN}$FILTER${NC}" fi echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" + # Display SYNTAX section + if command -v "$CMD_NAME" &> /dev/null || type "$CMD_NAME" 2>/dev/null | grep -q "shell builtin"; then + echo -e "${CYAN}${BOLD}SYNTAX:${NC}" + + if type "$CMD_NAME" 2>/dev/null | grep -q "shell builtin"; then + # For builtins, get the first line of help + local syntax=$(help "$CMD_NAME" 2>/dev/null | head -1 | sed 's/^[[:space:]]*//') + if [ -n "$syntax" ]; then + echo -e " ${GREEN}$syntax${NC}" + else + echo -e " ${GREEN}$CMD_NAME [options]${NC}" + fi + else + # For regular commands, extract SYNOPSIS section from man page + local synopsis=$(man "$CMD_NAME" 2>/dev/null | col -b | sed -n '/^SYNOPSIS/,/^DESCRIPTION/p' | head -15 | tail -n +2 | head -n -1 | sed 's/^[[:space:]]*/ /') + if [ -n "$synopsis" ]; then + echo -e "${GREEN}$synopsis${NC}" + else + # Fallback: try to get usage from command itself + local usage=$("$CMD_NAME" --help 2>&1 | grep -i "usage" | head -1 | sed 's/^[Uu]sage: / /') + if [ -n "$usage" ]; then + echo -e " ${GREEN}$usage${NC}" + else + echo -e " ${GREEN}$CMD_NAME [options]${NC}" + fi + fi + fi + echo "" + fi + + # Display FLAGS/OPTIONS section + echo -e "${YELLOW}${BOLD}FLAGS/OPTIONS:${NC}" + echo "" + # Try to get flags from man page if type "$CMD_NAME" 2>/dev/null | grep -q "shell builtin"; then # Shell builtin - use help command if [ -n "$FILTER" ]; then - help "$CMD_NAME" 2>/dev/null | grep -E '^\s*-' | grep -i "$FILTER" + help "$CMD_NAME" 2>/dev/null | grep -iE "(^|\s)-.*$FILTER" | head -30 else - help "$CMD_NAME" 2>/dev/null | grep -E '^\s*-' + help "$CMD_NAME" 2>/dev/null | grep -E '^\s*-' | head -30 fi elif command -v "$CMD_NAME" &> /dev/null; then # External command - use man page @@ -516,9 +573,10 @@ show_flags() { fi if [ -n "$FILTER" ]; then - echo "$options_section" | grep -i "$FILTER" | head -30 + # Improved filter logic: match flag name or description + echo "$options_section" | grep -iE "(^|\s)-.*$FILTER|$FILTER.*-" | head -40 else - echo "$options_section" | head -30 + echo "$options_section" | head -40 fi else echo -e "${RED}Could not find help for: $CMD_NAME${NC}" @@ -527,6 +585,8 @@ show_flags() { return 1 fi + echo "" + echo -e "${DIM}Tip: Use the filter to search for specific flags or keywords${NC}" echo "" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" } @@ -536,8 +596,16 @@ list_commands() { echo "" for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} - DESC=${cmd#*:} - printf " %-10s - %s\n" "$CMD_NAME" "$DESC" + REST=${cmd#*:} + + # Extract description (before pipe) and syntax (after pipe) + if [[ "$REST" =~ (.+)\ \|\ (.+) ]]; then + DESC="${BASH_REMATCH[1]}" + SYNTAX="${BASH_REMATCH[2]}" + printf " %-10s - %-40s | %s\n" "$CMD_NAME" "$DESC" "$SYNTAX" + else + printf " %-10s - %s\n" "$CMD_NAME" "$REST" + fi done } @@ -545,122 +613,127 @@ get_command_description() { local search_cmd=$1 for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} - DESC=${cmd#*:} + REST=${cmd#*:} if [ "$CMD_NAME" = "$search_cmd" ]; then - echo "$DESC" + # Extract just the description part (before the pipe) + if [[ "$REST" =~ (.+)\ \|\ (.+) ]]; then + echo "${BASH_REMATCH[1]}" + else + echo "$REST" + fi return 0 fi done echo "Command help" } -# Command definitions for interactive mode +# Command definitions for interactive mode (format: "cmd:Description | Syntax") COMMANDS=( # File Operations - "ls:List directory contents" - "cd:Change the current directory" - "pwd:Print the name of the current working directory" - "cp:Copy files and directories" - "mv:Move or rename files and directories" - "rm:Remove files or directories" - "mkdir:Create a new directory" - "rmdir:Remove an empty directory" - "touch:Create empty file or update timestamp" - "cat:Concatenate and display files" - "less:View file contents with pagination" - "head:Display first lines of a file" - "tail:Display last lines of a file" - "chmod:Change file permissions" - "chown:Change file owner" - "ln:Create links between files" - "file:Determine file type" - "stat:Display file status" + "ls:List directory contents | ls [OPTION]... [FILE]..." + "cd:Change the current directory | cd [DIRECTORY]" + "pwd:Print the name of the current working directory | pwd [OPTION]" + "cp:Copy files and directories | cp [OPTION]... SOURCE DEST" + "mv:Move or rename files and directories | mv [OPTION]... SOURCE DEST" + "rm:Remove files or directories | rm [OPTION]... FILE..." + "mkdir:Create a new directory | mkdir [OPTION]... DIRECTORY..." + "rmdir:Remove an empty directory | rmdir [OPTION]... DIRECTORY..." + "touch:Create empty file or update timestamp | touch [OPTION]... FILE..." + "cat:Concatenate and display files | cat [OPTION]... [FILE]..." + "less:View file contents with pagination | less [OPTION]... [FILE]..." + "head:Display first lines of a file | head [OPTION]... [FILE]..." + "tail:Display last lines of a file | tail [OPTION]... [FILE]..." + "chmod:Change file permissions | chmod [OPTION] MODE FILE..." + "chown:Change file owner | chown [OPTION]... OWNER[:GROUP] FILE..." + "ln:Create links between files | ln [OPTION]... TARGET LINK_NAME" + "file:Determine file type | file [OPTION]... FILE..." + "stat:Display file status | stat [OPTION]... FILE..." # Text Processing - "grep:Search for patterns in files" - "sed:Stream editor for text manipulation" - "awk:Pattern scanning and text processing" - "cut:Remove sections from lines of files" - "sort:Sort lines of text" - "uniq:Report or filter out repeated lines" - "tr:Translate or delete characters" - "wc:Count lines, words, and characters" - "diff:Compare files line by line" + "grep:Search for patterns in files | grep [OPTION]... PATTERN [FILE]..." + "sed:Stream editor for text manipulation | sed [OPTION]... SCRIPT [FILE]..." + "awk:Pattern scanning and text processing | awk [OPTION]... PROGRAM [FILE]..." + "cut:Remove sections from lines of files | cut [OPTION]... [FILE]..." + "sort:Sort lines of text | sort [OPTION]... [FILE]..." + "uniq:Report or filter out repeated lines | uniq [OPTION]... [FILE]..." + "tr:Translate or delete characters | tr [OPTION]... SET1 [SET2]" + "wc:Count lines, words, and characters | wc [OPTION]... [FILE]..." + "diff:Compare files line by line | diff [OPTION]... FILE1 FILE2" # File Search - "find:Search for files in directory hierarchy" - "locate:Find files by name quickly" - "which:Show full path of commands" - "whereis:Locate binary, source, and manual pages" + "find:Search for files in directory hierarchy | find [PATH] [OPTIONS] [EXPRESSION]" + "locate:Find files by name quickly | locate [OPTION]... PATTERN..." + "which:Show full path of commands | which [OPTION]... COMMAND..." + "whereis:Locate binary, source, and manual pages | whereis [OPTION]... COMMAND..." # Compression - "tar:Archive files" - "gzip:Compress files" - "gunzip:Decompress gzip files" - "zip:Package and compress files" - "unzip:Extract compressed zip files" + "tar:Archive files | tar [OPTION]... [FILE]..." + "gzip:Compress files | gzip [OPTION]... [FILE]..." + "gunzip:Decompress gzip files | gunzip [OPTION]... [FILE]..." + "zip:Package and compress files | zip [OPTION]... ZIPFILE FILES..." + "unzip:Extract compressed zip files | unzip [OPTION]... FILE..." # Network - "ping:Test network connectivity" - "curl:Transfer data from URLs" - "wget:Download files from the web" - "ssh:Secure shell remote login" - "scp:Secure copy files between hosts" - "netstat:Network statistics" - "ss:Socket statistics" - "ip:Show/manipulate routing and devices" - "ifconfig:Configure network interfaces" + "ping:Test network connectivity | ping [OPTION]... HOST" + "curl:Transfer data from URLs | curl [OPTION]... URL..." + "wget:Download files from the web | wget [OPTION]... URL..." + "ssh:Secure shell remote login | ssh [OPTION]... USER@HOST [COMMAND]" + "scp:Secure copy files between hosts | scp [OPTION]... SOURCE DEST" + "netstat:Network statistics | netstat [OPTION]..." + "ss:Socket statistics | ss [OPTION]..." + "ip:Show/manipulate routing and devices | ip [OPTION]... OBJECT {COMMAND}" + "ifconfig:Configure network interfaces | ifconfig [INTERFACE] [OPTIONS]" # System Info - "top:Display system processes" - "htop:Interactive process viewer" - "ps:Report process status" - "df:Show disk space usage" - "du:Estimate file space usage" - "free:Display memory usage" - "uname:Print system information" - "uptime:Show how long system has been running" + "top:Display system processes | top [OPTION]..." + "htop:Interactive process viewer | htop [OPTION]..." + "ps:Report process status | ps [OPTION]..." + "df:Show disk space usage | df [OPTION]... [FILE]..." + "du:Estimate file space usage | du [OPTION]... [FILE]..." + "free:Display memory usage | free [OPTION]..." + "uname:Print system information | uname [OPTION]..." + "uptime:Show how long system has been running | uptime [OPTION]..." # Process Management - "kill:Send signal to a process" - "pkill:Kill processes by name" - "killall:Kill processes by name" - "bg:Put job in background" - "fg:Bring job to foreground" - "jobs:List active jobs" + "kill:Send signal to a process | kill [OPTION]... PID..." + "pkill:Kill processes by name | pkill [OPTION]... PATTERN" + "killall:Kill processes by name | killall [OPTION]... NAME..." + "bg:Put job in background | bg [JOB_SPEC]" + "fg:Bring job to foreground | fg [JOB_SPEC]" + "jobs:List active jobs | jobs [OPTION]..." # System Control - "sudo:Execute command as another user" - "systemctl:Control systemd services" - "service:Control system services" - "reboot:Reboot the system" - "shutdown:Shut down the system" + "sudo:Execute command as another user | sudo [OPTION]... COMMAND" + "systemctl:Control systemd services | systemctl [OPTION]... COMMAND" + "service:Control system services | service COMMAND [OPTIONS]" + "reboot:Reboot the system | reboot [OPTION]..." + "shutdown:Shut down the system | shutdown [OPTION]... [TIME]" # Package Management - "apt:Package manager (Debian/Ubuntu)" - "apt-get:APT package handling utility" - "dpkg:Debian package manager" - "snap:Snap package manager" + "apt:Package manager (Debian/Ubuntu) | apt [OPTION]... COMMAND" + "apt-get:APT package handling utility | apt-get [OPTION]... COMMAND" + "dpkg:Debian package manager | dpkg [OPTION]... ACTION" + "snap:Snap package manager | snap [OPTION]... COMMAND" # User Management - "useradd:Create new user" - "userdel:Delete user account" - "passwd:Change user password" - "su:Switch user" - "whoami:Print current username" - "w:Show who is logged in" - "who:Show who is logged in" + "useradd:Create new user | useradd [OPTION]... LOGIN" + "userdel:Delete user account | userdel [OPTION]... LOGIN" + "passwd:Change user password | passwd [OPTION]... [USER]" + "su:Switch user | su [OPTION]... [USER]" + "whoami:Print current username | whoami" + "w:Show who is logged in | w [OPTION]... [USER]" + "who:Show who is logged in | who [OPTION]..." # Misc Utilities - "echo:Display a line of text" - "date:Display or set system date and time" - "cal:Display calendar" - "history:Show command history" - "alias:Create command aliases" - "export:Set environment variables" - "env:Display environment variables" - "man:Display manual pages" - "watch:Execute command periodically" + "echo:Display a line of text | echo [OPTION]... [STRING]..." + "date:Display or set system date and time | date [OPTION]... [+FORMAT]" + "cal:Display calendar | cal [OPTION]... [[MONTH] YEAR]" + "history:Show command history | history [n]" + "alias:Create command aliases | alias [NAME[=VALUE]...]" + "export:Set environment variables | export [NAME[=VALUE]...]" + "env:Display environment variables | env [OPTION]... [NAME=VALUE]... [COMMAND]" + "man:Display manual pages | man [OPTION]... [SECTION] PAGE" + "watch:Execute command periodically | watch [OPTION]... COMMAND" ) # Parse arguments @@ -750,16 +823,38 @@ if [ "$INTERACTIVE" = true ]; then exit 1 fi - FZF_COMMAND=$(printf "%s\n" "${COMMANDS[@]}" | fzf --height 40% --border --preview 'echo {}' --preview-window=up:1:wrap) + # Enhanced preview showing command, description, and syntax + FZF_COMMAND=$(printf "%s\n" "${COMMANDS[@]}" | fzf --height 60% --border \ + --preview 'echo -e "\033[0;36mCommand:\033[0m {1}\n\033[0;36mDescription:\033[0m {2}\n\033[0;36mSyntax:\033[0m {3}"' \ + --preview-window=up:3:wrap \ + --delimiter ':|\|' \ + --with-nth 1,2,3) if [ -n "$FZF_COMMAND" ]; then + # Parse the selected command: "cmd:description | syntax" CMD=${FZF_COMMAND%%:*} - DESC=${FZF_COMMAND#*:} + REST=${FZF_COMMAND#*:} + + # Extract description and syntax + if [[ "$REST" =~ (.+)\ \|\ (.+) ]]; then + DESC="${BASH_REMATCH[1]}" + SYNTAX="${BASH_REMATCH[2]}" + else + DESC="$REST" + SYNTAX="$CMD [options]" + fi + echo "" - echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" - echo -e "\033[0;32mCommand:\033[0m $CMD" - echo -e "\033[0;32mDescription:\033[0m $DESC" - echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo -e "${YELLOW}Command:${NC} ${MAGENTA}$CMD${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo "" + echo -e "${CYAN}${BOLD}SYNTAX:${NC}" + echo -e " ${GREEN}$SYNTAX${NC}" + echo "" + echo -e "${GREEN}Description:${NC} $DESC" + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" read -p "Filter flags (optional, press Enter to skip): " FILTER echo "" @@ -772,11 +867,23 @@ if [ "$INTERACTIVE" = true ]; then elif [ -n "$COMMAND" ]; then # Validate command exists in our list FOUND=false + DESC_PART="" + SYNTAX_PART="" + for cmd in "${COMMANDS[@]}"; do CMD_NAME=${cmd%%:*} if [ "$CMD_NAME" = "$COMMAND" ]; then FOUND=true - DESC=${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="$COMMAND [options]" + fi break fi done @@ -788,15 +895,22 @@ elif [ -n "$COMMAND" ]; then echo "" echo "Attempting to show flags anyway..." echo "" + DESC_PART=$(get_command_description "$COMMAND") + SYNTAX_PART="$COMMAND [options]" fi - # Show command info - DESC=$(get_command_description "$COMMAND") + # Show command info in enhanced format echo "" - echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" - echo -e "\033[0;32mCommand:\033[0m $COMMAND" - echo -e "\033[0;32mDescription:\033[0m $DESC" - echo -e "\033[0;34m═══════════════════════════════════════════════════════════\033[0m" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo -e "${YELLOW}Command:${NC} ${MAGENTA}$COMMAND${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo "" + echo -e "${CYAN}${BOLD}SYNTAX:${NC}" + echo -e " ${GREEN}$SYNTAX_PART${NC}" + echo "" + echo -e "${GREEN}Description:${NC} $DESC_PART" + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" echo "" show_flags "$COMMAND" "$FILTER"