#----------------------------------*-sh-*-------------------------------------- # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | # \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License # This file is part of OpenFOAM, licensed under GNU General Public License # . # # File # etc/config.sh/bash_completion # # Description # Bash completion handler for OpenFOAM applications and automatic # generation of completion associations # # Provides # foamAddCompletion # _of_complete_ # # Uses # _of_complete_cache_ # # Requires # bash 4.2 or newer # #------------------------------------------------------------------------------ # Remove old completions (skip for tcsh wrapper), which look like: # "complete ... -F _of_complete_ APPNAME if [ -z "$_of_complete_tcsh" ] then # For economy, obtain list first foamOldDirs="$(complete 2>/dev/null | sed -ne 's/^.*-F _of_.* \(..*\)$/\1/p')" for cleaned in $foamOldDirs do complete -r $cleaned 2>/dev/null done fi # Add completion for commands, directories of commands # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ unset -f foamAddCompletion 2>/dev/null foamAddCompletion() { [ "$#" -gt 0 ] || \ echo "Usage: foamAddCompletion -clear | -list | dir(s) | app(s)" 1>&2 local appName choices for appName do if [ "$appName" = "-clear" ] then # Clear cached values echo "clear cached values" _of_complete_cache_=() elif [ "$appName" = "-list" ] then # List cached keys choices="${#_of_complete_cache_[@]}" echo "$choices cached values:" [ "$choices" = 0 ] || echo ${!_of_complete_cache_[@]} # keys elif [ -d "$appName" ] then # Process directory for applications choices="$(find $appName -maxdepth 1 -executable -type f 2>/dev/null)" for appName in $choices do complete -o filenames -F _of_complete_ "${appName##*/}" # echo "complete ${appName##*/}" 1>&2 done elif command -v "$appName" > /dev/null 2>&1 then complete -o filenames -F _of_complete_ "${appName##*/}" # echo "complete ${appName##*/}" 1>&2 else echo "No completion added for $appName" 1>&2 fi done } # Generic completion handler for OpenFOAM applications # # Dispatch via "complete ... -F _of_complete_ APPNAME # - arg1 = command-name # - arg2 = current word # - arg3 = previous word # # The respective options are generated on-the-fly from the application's # -help-full output and cached to the _of_complete_cache_ global associative # array with entries formatted as "argOpts.. | boolOpts ..". # The '|' character separates options with and without arguments. # unset -f _of_complete_ 2>/dev/null _of_complete_() { local appName=$1 local cur=$2 local prev=$3 local choices case ${prev} in -help|-help-full|-doc|-doc-source) # These options are usage - we can stop now. COMPREPLY=() return 0 ;; -case) COMPREPLY=($(compgen -d -- ${cur})) ;; -time) # Could use "foamListTimes -withZero", but still doesn't address ranges COMPREPLY=($(compgen -d -X '![-0-9]*' -- ${cur})) ;; -region) choices=$(\ls -d system/*/ 2>/dev/null | sed -e 's#/$##' -e 's#^.*/##') COMPREPLY=($(compgen -W "$choices" -- ${cur})) ;; -fileHandler) choices="collated uncollated masterUncollated" COMPREPLY=($(compgen -W "$choices" -- ${cur})) ;; *) # All options choices="${_of_complete_cache_[$appName]}" # Not in cache, obtain by parsing application -help-full if [ -z "$choices" ] then # Treat ',' like space so '-a, -all' parses like '-a | -all' # Options with '=' (Eg, -mode=ugo) are not handled very well. local helpText=$($appName -help-full 2>/dev/null | \ sed -n -e 's/,/ /g' -e 's/=.*$/=/' -e '/^ *-/p') if [ -n "$helpText" ] then # Array of options with args local argOpts=($(awk '/^ {0,4}-[a-z]/ && /&2 choices="false" # Mark failure to prevent repeating again fi _of_complete_cache_[$appName]="$choices" ## echo "generated $appName = $choices" 1>&2 # Debugging fi if [ "${choices:-false}" = false ] then COMPREPLY=($(compgen -f -- ${cur})) else # Everything before the '|' ==> options with args. local argOpts="${choices%|*}" if [ "${argOpts/${prev} /}" != "${argOpts}" ] then # Option with unknown type of arg - set to files. # Not always correct but can still navigate path if needed... COMPREPLY=($(compgen -f -- ${cur})) elif [ -n "$cur" -a "${cur#-}" = "${cur}" ] then # Already started a (non-empty) word that isn't an option, # in which case revert to filenames. COMPREPLY=($(compgen -f -- ${cur})) else # Catchall # - Present remaining options (not already seen in $COMP_LINE) choices=$( for o in ${choices} do [ "${COMP_LINE/$o/}" = "${COMP_LINE}" ] && echo "${o#|}" done ) COMPREPLY=($(compgen -W "$choices" -- ${cur})) fi fi ;; esac return 0 } #------------------------------------------------------------------------------ # Uses 'declare -gA' for the implementation # The '-A' requires bash >= 4.0 and the '-g' requires bash >= 4.2 if [ "${BASH_VERSINFO[0]:-0}${BASH_VERSINFO[1]:-0}" -ge 42 ] then # Global associative array (cached options for OpenFOAM applications) declare -gA _of_complete_cache_; # Clear existing cache and reassign bash completions. # But for tcsh wrapper make use of caching and avoid this overhead. if [ -z "$_of_complete_tcsh" ] then _of_complete_cache_=() # Generate completions for predefined directories foamAddCompletion $FOAM_APPBIN # And a few scripts from bin/ foamAddCompletion paraFoam fi else # Bash version is too old. ## echo "No bash completions - requires bash >= 4.2" 1>&2 unset -f foamAddCompletion 2>/dev/null foamAddCompletion() { echo "foamAddCompletion disabled - requires bash >= 4.2" 1>&2 } unset -f _of_complete_ 2>/dev/null fi #------------------------------------------------------------------------------ # Intermediate variables (do as last for a clean exit code) unset cleaned foamOldDirs #------------------------------------------------------------------------------