From ed59c036124c231c3d8514367d54d3f5901c0aca Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 24 Jan 2021 11:16:12 -0500 Subject: completions/bash: Some improvements --- completions/bfs.bash | 533 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 342 insertions(+), 191 deletions(-) (limited to 'completions') diff --git a/completions/bfs.bash b/completions/bfs.bash index a890c5f..0896bef 100644 --- a/completions/bfs.bash +++ b/completions/bfs.bash @@ -1,194 +1,345 @@ -# bash completion script - -_bfs () -{ - local cword=$COMP_CWORD - local cur="${COMP_WORDS[$cword]}" - local prev prev1 - if (($cword > 0)); then - prev="${COMP_WORDS[$(($cword-1))]}" - fi - if (($cword > 1)); then - prev1="${COMP_WORDS[$(($cword-2))]}" - fi - - # arguments with a special completion procedure - local options_special='-exec -execdir -ok -okdir -fprintf -D -S -regextype -fstype -gid -uid -group -user -perm -type -xtype' - - # arguments whose values should not be completed - # (e.g. because they are numeric, glob, regexp, time, etc.) - local options_nocomp='-maxdepth -mindepth -amin -Bmin -cmin -mmin -asince -Bsince -csince -msince -atime -Btime -ctime -mtime -ilname -iname -ipath -iregex -iwholename -inum -links -lname -name -path -wholename -regex -since -size -used -printf -newerat -newerBt -newerct -newermt -xattrname' - - # arguments whose value is a filename - local options_filecomp='-anewer -Bnewer -cnewer -mnewer -newer -samefile -fls -fprint -fprint0 -neweraa -neweraB -newerac -neweram -newerBa -newerBB -newerBc -newerBm -newerca -newercB -newercc -newercm -newerma -newermB -newermc -newermm -f' - - # arguments whose value is a dirname - local options_dircomp='' - - # options with no value - local flags='-H -L -P -E -X -d -s -x -O1 -O2 -O3 -not -and -or -exclude -color -nocolor -daystart -depth -follow -ignore_readdir_race -noignore_readdir_race -mount -nohidden -status -unique -warn -nowarn -xdev -acl -capable -empty -executable -readable -writable -false -true -hidden -nogroup -nouser -sparse -xattr -delete -rm -exit -ls -print -print0 -printx -prune -quit -version -help' - - local all_options="${flags} ${options_special} ${options_nocomp} ${options_filecomp} ${options_dircomp}" - - # completions which require parsing the whole command string - case "${COMP_WORDS[*]}" in - (*\ -exec\ *|*\ -execdir\ *|*\ -ok\ *|*\ -okdir\ *) - case "$prev" in - (-exec|-execdir|-ok|-okdir) - # complete commands for first word after exec-type option - COMPREPLY=($(compgen -c -- "$cur")) - return - ;; - esac - # default completion only after exec-type option - #TODO: complete whatever command was provided after -exec - #TODO: detect end of -exec string and continue completing as normal - COMPREPLY=($(compgen -o default -o bashdefault -- "$cur")) - return - ;; - esac - - # completions with 2-word lookbehind - case "$prev1" in - (-fprintf) - # -fprintf FORMAT FILE - # Like -ls/-print/-print0/-printf, but write to FILE instead of standard - # output - # when -fprintf is prev1, current word is FILE; perform file completion - COMPREPLY=($(compgen -f -- "$cur")) - return - ;; - esac - - # completions with 1-word lookbehind - case "$prev" in - (-maxdepth|-mindepth|-[aBcm]min|-[aBcm]since|-[aBcm]time|-ilname|-iname|-ipath|-iregex|-iwholename|-inum|-links|-lname|-name|-path|-wholename|-regex|-since|-size|-used|-printf|-newer[aBcm]t|-xattrname) - # arguments whose values should not be completed - # (e.g. because they are numeric, glob, regexp, time, etc.) - COMPREPLY=() - return - ;; - (-[aBcm]newer|-newer|-samefile|-fls|-fprint|-fprint0|-newer[aBcm][aBcm]|-f) - # arguments whose value is a filename - #FIXME: -o filenames should suppress spaces and add trailing / to dirnames - COMPREPLY=($(compgen -o filenames -f -- "$cur")) - return - ;; - # (-f) - # # arguments whose value is a dirname - # COMPREPLY=($(compgen -d -- "$cur")) - # return - # ;; - (-type|-xtype) - # -type [bcdlpfswD] - # Find files of the given type - # -xtype [bcdlpfswD] - # Find files of the given type, following links when -type would not, and - # vice versa - if [[ -n $cur ]] && ! [[ $cur =~ ,$ ]]; then - cur+=, - fi - COMPREPLY=("${cur}"{b,c,d,l,p,f,s,w,D}) - return - ;; - (-gid|-uid) - # -gid [-+]N - # -uid [-+]N - # Find files owned by group/user ID N - #TODO: list numeric uids/gids - COMPREPLY=() - return - ;; - (-group) - # -group NAME - # Find files owned by the group NAME - COMPREPLY=($(compgen -g -- "$cur")) - return - ;; - (-user) - # -user NAME - # Find files owned by the user NAME - COMPREPLY=($(compgen -u -- "$cur")) - return - ;; - (-S) - # -S bfs|dfs|ids|eds - # Use breadth-first/depth-first/iterative/exponential deepening search - # (default: -S bfs) - COMPREPLY=($(compgen -W 'bfs dfs ids eds' -- "$cur")) - return - ;; - (-D) - # -D FLAG - # Turn on a debugging flag (see -D help) - COMPREPLY=($(compgen -W 'help cost exec opt rates search stat tree all' -- "$cur")) - return - ;; - (-regextype) - # -regextype TYPE - # Use TYPE-flavored regexes (default: posix-basic; see -regextype help) - COMPREPLY=($(compgen -W 'help posix-basic posix-extended' -- "$cur")) - return - ;; - (-fstype) - # -fstype TYPE - # Find files on file systems with the given TYPE - #TODO: parse the mount table for a list of mounted filesystem types - COMPREPLY=() - return - ;; - (-perm) - # -perm [-]MODE - # Find files with a matching mode - # sample syntax: - # -perm 777 - # -perm 507 - # -perm u+rw - # -perm og-rx - if [[ -z "$cur" ]]; then - # initial completion - COMPREPLY=(0 1 2 3 4 5 6 7 u g o) - return - elif [[ "$cur" =~ [rwx][rwx][rwx]$ ]] || [[ "$cur" =~ [0-7][0-7][0-7]$ ]]; then - # final completion (filled in all possible mode bits) - COMPREPLY=("$cur") +#!/bin/bash + +############################################################################ +# bfs # +# Copyright (C) 2020 Benjamin Mundt # +# Copyright (C) 2020 Tavian Barnes # +# # +# Permission to use, copy, modify, and/or distribute this software for any # +# purpose with or without fee is hereby granted. # +# # +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # +############################################################################ + +# bash completion script for bfs + +_bfs() { + local cword="$COMP_CWORD" + local cur="${COMP_WORDS[cword]}" + local prev prev2 + if ((cword > 0)); then + prev="${COMP_WORDS[cword-1]}" + fi + if ((cword > 1)); then + prev2="${COMP_WORDS[cword-2]}" + fi + + # Options with a special completion procedure + local special=( + -D + -S + -exec + -execdir + -fprintf + -fstype + -gid + -group + -ok + -okdir + -perm + -regextype + -type + -uid + -user + -xtype + ) + + # Options whose values should not be completed + # (e.g. because they are numeric, glob, regexp, time, etc.) + local nocomp=( + -{a,B,c,m}{min,since,time} + -ilname + -iname + -inum + -ipath + -iregex + -iwholename + -links + -lname + -maxdepth + -mindepth + -name + -newer{a,B,c,m}t + -path + -printf + -regex + -since + -size + -used + -wholename + -xattrname + ) + + # Options whose value is a filename + local filecomp=( + -{a,B,c,m}newer + -f + -fls + -fprint + -fprint0 + -newer + -newer{a,B,c,m}{a,B,c,m} + -samefile + ) + + local operators=( + -a + -and + -exclude + -not + -o + -or + ) + + # Flags that take no arguments + local nullary_flags=( + -E + -H + -L + -O{0,1,2,3,4,fast} + -P + -X + -d + -x + ) + + # Options that take no arguments + local nullary_options=( + -color + -daystart + -depth + -follow + -ignore_readdir_race + -maxdepth + -mindepth + -mount + -nocolor + -noignore_readdir_race + -noleaf + -nowarn + -status + -unique + -warn + -xdev + ) + + # Tests that take no arguments + local nullary_tests=( + -capable + -empty + -executable + -false + -hidden + -nogroup + -nohidden + -nouser + -readable + -sparse + -true + -writable + -xattr + -xattrname + ) + + # Actions that take no arguments + local nullary_actions=( + --help + --version + -delete + -exit + -help + -ls + -print + -print0 + -printx + -prune + -quit + -rm + -version + ) + + local everything=( + "${special[@]}" + "${nocomp[@]}" + "${filecomp[@]}" + "${operators[@]}" + "${nullary_flags[@]}" + "${nullary_options[@]}" + "${nullary_tests[@]}" + "${nullary_actions[@]}" + ) + + # Completing -exec requires matching the whole command line + local iscmd isarg word + for word in "${COMP_WORDS[@]::cword}"; do + case "$word" in + -exec|-execdir|-ok|-okdir) + iscmd=y + ;; + \\\;|+) + if [[ -n "$iscmd" ]] || [[ -n "$isarg" ]]; then + iscmd= + isarg= + fi + ;; + *) + if [[ -n "$iscmd" ]]; then + iscmd= + isarg=y + fi + ;; + esac + done + + if [[ -n "$iscmd" ]]; then + COMPREPLY=($(compgen -c -- "$cur")) return - elif [[ "$cur" =~ [0-7]$ ]]; then - # intermediate completion, octal mode specifier - COMPREPLY=("$cur"{0,1,2,3,4,5,6,7}) + elif [[ -n "$isarg" ]]; then + COMPREPLY=($(compgen -o default -o bashdefault -W "{} + \\\\;" -- "$cur")) return - elif [[ "$cur" =~ ^[ugo]*[+-][rwx]*$ ]]; then - # intermediate completion, symbolic mode specifier + fi + + # Completions with 2-word lookbehind + case "$prev2" in + -fprintf) + # -fprintf FORMAT FILE + # Like -ls/-print/-print0/-printf, but write to FILE instead of standard + # output + # when -fprintf is prev2, current word is FILE; perform file completion + COMPREPLY=($(compgen -f -- "$cur")) + return + ;; + esac + + # No completion for numbers, globs, regexes, times, etc. + if [[ " ${nocomp[@]} " =~ " $prev " ]]; then COMPREPLY=() - [[ "$cur" =~ [rwx]$ ]] && COMPREPLY+=("${cur}") - [[ "$cur" =~ [+-][wx]*r ]] || COMPREPLY+=("${cur}r") - [[ "$cur" =~ [+-][rx]*w ]] || COMPREPLY+=("${cur}w") - [[ "$cur" =~ [+-][rw]*x ]] || COMPREPLY+=("${cur}x") - return 0 - elif [[ "$cur" =~ ^[ugo] ]]; then - # intermediate completion, symbolic group specifier - COMPREPLY=(+ -) - [[ "$cur" =~ ^[go]*u ]] || COMPREPLY+=("${cur}u") - [[ "$cur" =~ ^[uo]*g ]] || COMPREPLY+=("${cur}g") - [[ "$cur" =~ ^[ug]*o ]] || COMPREPLY+=("${cur}o") - return 0 - fi - COMPREPLY=() - return - ;; - esac - - # completions with no lookbehind - case "$cur" in - (-*) - # complete all options - COMPREPLY=($(compgen -o default -o bashdefault -W "${all_options}" -- "$cur")) - return - ;; - esac - - # default completion - COMPREPLY=($(compgen -o default -o bashdefault -- "$cur")) - return -} && - complete -F _bfs bfs + return + fi + + # Complete filenames + if [[ " ${filecomp[@]} " =~ " $prev " ]]; then + COMPREPLY=($(compgen -o filenames -f -- "$cur")) + return + fi + + # Other completions with 1-word lookbehind + case "$prev" in + -type|-xtype) + # -type [bcdlpfswD] + # Find files of the given type + # -xtype [bcdlpfswD] + # Find files of the given type, following links when -type would not, and + # vice versa + COMPREPLY=() + if [[ -n $cur ]] && ! [[ $cur =~ ,$ ]]; then + COMPREPLY+=("$cur") + cur+=, + fi + COMPREPLY+=("$cur"{b,c,d,l,p,f,s,w,D}) + return + ;; + -gid|-uid) + # -gid [-+]N + # -uid [-+]N + # Find files owned by group/user ID N + # TODO: list numeric uids/gids + COMPREPLY=() + return + ;; + -group) + # -group NAME + # Find files owned by the group NAME + COMPREPLY=($(compgen -g -- "$cur")) + return + ;; + -user) + # -user NAME + # Find files owned by the user NAME + COMPREPLY=($(compgen -u -- "$cur")) + return + ;; + -S) + # -S bfs|dfs|ids|eds + # Use breadth-first/depth-first/iterative/exponential deepening search + # (default: -S bfs) + COMPREPLY=($(compgen -W 'bfs dfs ids eds' -- "$cur")) + return + ;; + -D) + # -D FLAG + # Turn on a debugging flag (see -D help) + COMPREPLY=($(compgen -W 'help cost exec opt rates search stat tree all' -- "$cur")) + return + ;; + -regextype) + # -regextype TYPE + # Use TYPE-flavored regexes (default: posix-basic; see -regextype help) + COMPREPLY=($(compgen -W 'help posix-basic posix-extended' -- "$cur")) + return + ;; + -fstype) + # -fstype TYPE + # Find files on file systems with the given TYPE + #TODO: parse the mount table for a list of mounted filesystem types + COMPREPLY=() + return + ;; + (-perm) + # -perm [-]MODE + # Find files with a matching mode + # sample syntax: + # -perm 777 + # -perm 507 + # -perm u+rw + # -perm og-rx + if [[ -z "$cur" ]]; then + # initial completion + COMPREPLY=(0 1 2 3 4 5 6 7 u g o) + return + elif [[ "$cur" =~ [rwx][rwx][rwx]$ ]] || [[ "$cur" =~ [0-7][0-7][0-7]$ ]]; then + # final completion (filled in all possible mode bits) + COMPREPLY=("$cur") + return + elif [[ "$cur" =~ [0-7]$ ]]; then + # intermediate completion, octal mode specifier + COMPREPLY=("$cur"{0,1,2,3,4,5,6,7}) + return + elif [[ "$cur" =~ ^[ugo]*[+-][rwx]*$ ]]; then + # intermediate completion, symbolic mode specifier + COMPREPLY=() + [[ "$cur" =~ [rwx]$ ]] && COMPREPLY+=("${cur}") + [[ "$cur" =~ [+-][wx]*r ]] || COMPREPLY+=("${cur}r") + [[ "$cur" =~ [+-][rx]*w ]] || COMPREPLY+=("${cur}w") + [[ "$cur" =~ [+-][rw]*x ]] || COMPREPLY+=("${cur}x") + return 0 + elif [[ "$cur" =~ ^[ugo] ]]; then + # intermediate completion, symbolic group specifier + COMPREPLY=(+ -) + [[ "$cur" =~ ^[go]*u ]] || COMPREPLY+=("${cur}u") + [[ "$cur" =~ ^[uo]*g ]] || COMPREPLY+=("${cur}g") + [[ "$cur" =~ ^[ug]*o ]] || COMPREPLY+=("${cur}o") + return 0 + fi + COMPREPLY=() + return + ;; + esac + + # Completions with no lookbehind + if [[ "$cur" == -* ]]; then + # complete all options + COMPREPLY=($(compgen -o default -o bashdefault -W "${everything[*]}" -- "$cur")) + return + fi + + # default completion + COMPREPLY=($(compgen -o default -o bashdefault -f -W "${everything[*]} ! ," -- "$cur")) + return +} && complete -F _bfs bfs -- cgit v1.2.3