#!/bin/bash #------------------------------------------------------------------------------ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | Website: https://openfoam.org # \\ / A nd | Copyright (C) 2020-2023 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License # This file is part of OpenFOAM. # # OpenFOAM is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # OpenFOAM is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with OpenFOAM. If not, see . # # Script # foamGenerateBashCompletion # # Description # Generate the bash_completion file # #------------------------------------------------------------------------------ usage() { cat<. # # File # etc/config.sh/bash_completion # # Description # Bash [TAB] completion file from OpenFOAM # Sourced from /etc/bashrc # #------------------------------------------------------------------------------ # shellcheck disable=SC2155,SC2207,SC2086 EOF } optionFunctions () { cat<,' '\n' | \\ sort -u | \\ xargs } EOF } declareLocals () { cat < "$file" optionFunctions >> "$file" for app in $apps do appName="${app##*/}" echo "Configuring $appName" # If a special configurations is defined for this app, use it and continue echo "$specialApps" | \ grep -qsw "$appName" && "_$appName" >> "$file" && continue # Get arguments. Anything on the usage line in <> or [] brackets. argList=$($app -help | \ grep ^Usage | \ awk -F '[]>]' '{for(i=1;i<=NF;++i) print $i}' | \ awk -F ' [<[]' '{print $2}') # Categorise arguments ... # File arguments. Entries without "output", ending in "file". inputFileArgs=$(echo "$argList" | while read -r line do echo "$line" | grep -v output | grep -E "file$" done) nInputFileArgs=$(echo "$inputFileArgs" | sed '/^$/d' | wc -l) # Directory arguments. Entries without "output", including "case" or "dir*". inputDirArgs=$(echo "$argList" | while read -r line do echo "$line" | grep -v output | grep -Ei "(case|dir).*" done) nInputDirArgs=$(echo "$inputDirArgs" | sed '/^$/d' | wc -l) # Options. Anything in the between "options" and the next empty line. optList=$($app -help | \ sed -n '/^options/,/^$/p' | \ grep -E "^[\t ]*-" | \ tr -s " ") [ -z "$optList" ] && continue # Categorise options ... arglessOpts="" # options without arguments dirOpts="" # options with directory arguments fileOpts="" # options with file arguments handlerOpts="" # file handler options -fileHandler rangesOpts="" # ranges options -time argOpts="" # options with unspecified arguments specialOpts="" # -solver, -table, -func while read -r line do # Clear the variable unset next # Get the option opt=$(echo "$line" | cut -d " " -f1 | tr -d " ") # Ignore "-solver" if app is a script [ "$opt" = "-solver" ] && isScript "$appName" && continue # Deal with quoted option arguments for -libs [ "$opt" = "-libs" ] && next=libList case "$opt" in -solver|-table|-func) specialOpts="$specialOpts $opt" continue ;; esac # Get the adjacent string in <> brackets [ "$next" ] || \ next=$(echo "$line" | \ sed 's/ \<.*\>.*//g' | \ awk -F '>' '{print $1}' | \ awk -F ' <' '{print $2}' | tr -d \) | \ tr -d \() # Categorise by the the last word in the string case "${next##* }" in "") arglessOpts="$arglessOpts $opt" ;; dir) dirOpts="$dirOpts $opt" ;; file) fileOpts="$fileOpts $opt";; handler) handlerOpts="$handlerOpts $opt";; ranges) rangesOpts="$rangesOpts $opt";; *) argOpts="$argOpts $opt";; esac done<<< "$optList" # Combine options into a single list # shellcheck disable=SC2086 allOpts=$(printf '%s\n' \ $arglessOpts $dirOpts $fileOpts $handlerOpts $rangesOpts $argOpts $specialOpts | \ sort) # Write the completion function ... # shellcheck disable=SC2086 { echo "_${appName}_ ()" echo "{" declareLocals echo "" # shellcheck disable=SC2027,SC2086 echo " opts=\""$allOpts"\"" echo " for o in \$used ; do opts=\"\${opts/\$o/}\" ; done" if [ ! "$nInputFileArgs" = 0 ] then echo " extra=\"-d -f\"" elif [ ! "$nInputDirArgs" = 0 ] then echo " extra=\"-d\"" else echo " extra=\"\"" fi echo "" caseStart if [ -n "$dirOpts" ] then printf " %s)\n" "$(echo $dirOpts | tr " " "|")" echo " opts=\"\" ; extra=\"-d\" ;;" fi if [ -n "$fileOpts" ] then printf " %s)\n" "$(echo $fileOpts | tr " " "|")" echo " opts=\"\" ; extra=\"-d -f\" ;;" fi if [ -n "$handlerOpts" ] then printf " %s)\n" "$(echo $handlerOpts | tr " " "|")" echo " opts=\"uncollated collated masterUncollated\" ; extra=\"\" ;;" fi if [ -n "$rangesOpts" ] then printf " %s)\n" "$(echo $rangesOpts | tr " " "|")" echo " opts=\"\$(foamListTimes -withZero 2> /dev/null)\" ; extra=\"\" ;;" fi if [ -n "$argOpts" ] then printf " %s)\n" "$(echo $argOpts | tr " " "|")" echo " opts=\"\" ; extra=\"\" ;;" fi for sopt in $specialOpts do printf " %s) opts=\"\$(_%s \${cur})\" ;;\n" "$sopt" "${sopt#-}" done # Set argOpts to all options with arguments argOpts="$argOpts $dirOpts $fileOpts $handlerOpts $rangesOpts" # Get the max of nInputFileArgs and nInputDirArgs nMaxFileDirArgs=$nInputFileArgs [ "$nInputDirArgs" -gt "$nMaxFileDirArgs" ] && \ nMaxFileDirArgs=$nInputDirArgs # Stop optional arguments once mandatory arguments are entered case "$nMaxFileDirArgs" in 0) echo " *) ;;" ;; 1) echo " -*) ;;" echo " *)" if [ -z "${argOpts// }" ] then echo " opts=\"\"; extra=\"\"" else echo " case \"\${COMP_WORDS[COMP_CWORD-2]}\" in" printf " %s) ;;\n" \ "$(echo $argOpts | tr " " "|")" echo " *) opts=\"\"; extra=\"\" ;;" echo " esac" fi echo " ;;" ;; *) echo " -*) ;;" echo " *) opts=\"\";;" ;; esac caseEnd echo "}" echo "complete -o filenames -o nospace -F _${appName}_ ${appName}" echo "" } >> "$file" done cat<<\EOF >> "$file" #------------------------------------------------------------------------------ EOF #------------------------------------------------------------------------------