Files
OpenFOAM-12/bin/foamFind
Chris Greenshields f9ac53aab4 bin/foamFind: added '-edit' option to open file in a text editor
The editor must be specified by configuring the EDITOR environment
variable. For example to use the 'gedit' editor, the following entry
could be added to the user's .bashrc file:

export EDITOR=gedit
2024-04-19 20:53:00 +01:00

419 lines
12 KiB
Bash
Executable File

#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration | Website: https://openfoam.org
# \\ / A nd | Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
#
# Script
# foamFind
#
# Description
# Finds one or more files in OpenFOAM and optionally processes the contents
# by printing the file or lines matching a search string
#
#------------------------------------------------------------------------------
usage () {
cat <<USAGE
Usage: ${0##*/} [OPTIONS] <filename>
options:
-a | -applications search for the file from the \$FOAM_APP directory
-d | -dir <dir> specify search directory
-e | -edit open the file in a file editor, see below for info
-f | -files find wmake 'files' file associated with searched file
-h | -help help
-i | -isearch <string> searches files for a <string>, case insensitive
-m | -modules search for the file from the \$FOAM_MODULES directory
-n | -numbers print line numbers with file output
-o | -options find wmake 'options' file associated with searched file
-p | -print print the file(s)
-s | -search <string> searches files for a <string>, case sensitive
-t | -tutorials search for the file from the \$FOAM_TUTORIALS directory
Finds one or more files in OpenFOAM and optionally processes the contents by:
+ printing the file(s) ('-print' option);
+ printing lines within the file matching a search string ('-search' option);
+ opening a single (only) file in a text editor ('-edit' option).
The '-edit' option required the user to specify their choice of text editor by
setting the EDITOR environment variable. For example, to set the 'gedit' editor,
they could add to their \$HOME/.bashrc file, the line:
export EDITOR=gedit
With source code files, can locate the 'files' and 'options' files associated
with their compilation using 'wmake'.
By default, files are searched from the src (\$FOAM_SRC) directory.
Alternatively the '-dir' option allows the user to specify the search directory
The '-applications', '-modules' and '-tutorials' options specifically set the
search path to the \$FOAM_APP, \$FOAM_MODULES and \$FOAM_TUTORIALS directories,
respectively.
Examples:
foamFind -print wallHeatFlux.C | less
+ click space bar to scroll down
+ enter line number (after ":") to jump to line
+ enter "/text" to search for "text" (or any other string)
foamFind -applications -isearch "momentumtransport" -options fluid.C
foamFind -numbers -search laminar BirdCarreau.C
USAGE
}
error() {
exec 1>&2
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
usage
exit 1
}
findWmakeFiles () {
_file="$1" ; shift
_wmakeFiles="$*"
# Check if file is source code
! file -b "$_file" | grep -Eq "C.*source" && \
"'-$_filename' invalid, file is not source code" >&2 && \
return 1
_files=""
while true
do
_oldFile="$_file"
_file="${_file%/*}"
# cannot contract the path further
[ "$_oldFile" = "$_file" ] && break
# search for 'files' and/or 'options'
[ -d "$_file" ] && \
for _w in $_wmakeFiles
do
_files="$(echo "$_files" \
"$(find "$_file" -name "$_w" -type f)" | xargs)"
done
[ "$_files" ] && break
done
! [ "$_files" ] && \
error "no '$_filename' file found for '-files' or '-options'" >&2 && \
return 1
echo "$_files"
return 0
}
nParams () {
[ "$1" ] || return 1
echo "$1" | xargs | awk -F' ' '{print NF}'
return 0
}
selectFile () {
_filename="$1"; shift
_files="$*"
_nFiles="$(nParams "$_files")"
# Return file if only one
[ "$_nFiles" -eq 1 ] && echo "$_files" && exit 0
printf "Multiple files" >&2
[ "$_filename" ] && printf " with name '%s'" "$_filename" >&2
printf " found:\n" >&2
_i=1
for _f in $_files
do
printf "%i) %s\n" "$_i" "$_f" >&2
_i=$((_i + 1))
done
printf "Type ENTER to select all, or " >&2
printf "enter file number (1-%s) for specific file: " \
"$_nFiles" >&2
read -r _nFile
# Enter nothing
[ -z "$_nFile" ] && echo "$_files" && return 0
# Check incorrect number
! [ "$_nFile" -eq "$_nFile" ] 2>/dev/null && \
echo "\"$_nFile\" is not a number" >&2 && \
return 1
{ [ "$_nFile" -lt 1 ] || [ "$_nFile" -gt "$_nFiles" ] ; } && \
echo "\"$_nFile\" is not a number between 1 and $_nFiles" >&2 && \
return 1
# Enter number corresponding to file
# shellcheck disable=SC2086
echo $_files | awk -v n="$_nFile" '{print $n}'
return 0
}
setFile () {
_files="$1"
_n="$2"
echo "$_files" | xargs -n 1 | awk -v n="${_n}" 'NR==n'
}
isSrcDir () {
echo "$1" | grep -wqE "^($FOAM_SRC|$FOAM_APP)"
}
listFiles () {
_dir="$1"
_filename="$2"
_search="$3"
_ins=""
[ "$4" = "on" ] && _ins="i"
# Specify code files if _dir is in $FOAM_SRC or $FOAM_APP
_name="*"
isSrcDir "$dir" && _name="*.[CHL]"
[ "$_filename" ] && _name="$_filename"
[ "$_search" ] && \
find "$_dir" -name "$_name" -type f -print0 | \
xargs -0 grep -l$_ins "$search" && \
return 0
# Remove "\n"
find "$dir" -name "$filename" -type f -print0 | xargs -0
}
grepFile () {
_string="$1"
_file="$2"
_ins=""
[ "$3" = "on" ] && _ins="i"
_arg="$4"
# use $_arg for different cases: test, and with and without line numbers
case "$_arg" in
test)
grep -q"$_ins" "$_string" "$_file"
;;
numbers)
grep -hn"$_ins" "$_string" "$_file" | \
awk '{
split($0,f,":");
sub(/^([^:]+:)/,"",$0);
printf "%6i %s\n", f[1], $0
}'
;;
*)
grep -h"$_ins" "$_string" "$_file"
;;
esac
}
dirError () {
cat<<EOF
Search directory specified with more than one option from '-applications',
'-dir', '-modules' and '-tutorials'. Please specify only one of these options.
EOF
}
editConfigError () {
cat<<EOF
The '-edit' option requires the user to specify their chosen text editor using
the EDITOR environment variable. For example, to set the 'gedit' editor, they
could add to their \$HOME/.bashrc file, the line:
export EDITOR=gedit
EOF
}
searchError () {
cat<<EOF
The '-search' and '-isearch' options are both specified.
Please specify only one of these options, either '-isearch' for a
case-insensitive search or '-search' for case-sensitive.
EOF
}
optionsError () {
cat<<EOF
Two or more of the '-search/-isearch', '-print' and '-edit' options are
specified. Please specify only one of these options, either '-search/-isearch'
to print lines of files(s) matching an expression, or '-print' or '-edit' to
view the entire file(s).
EOF
}
dir=""
print=""
edit=""
wmakeFiles=""
search=""
insensitive=""
numbers=""
filename=""
while [ "$#" -gt 0 ]
do
case "$1" in
-a | -applications)
[ "$dir" ] && error "$(dirError)"
dir="$FOAM_APP"
shift
;;
-d | -dir)
[ "$dir" ] && error "$(dirError)"
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
[ -d "$2" ] || error "'$2' argument to '-dir' option is not a directory"
# shellcheck disable=SC2164
dir="$(cd "$2"; pwd)"
# Check $dir is in OpenFOAM
! echo "$dir" | grep -wq "^$WM_PROJECT_DIR" && \
error "Specified directory '$dir' is not in OpenFOAM installation"
shift 2
;;
-e | -edit)
{ [ "$insensitive" ] || [ "$print" ]; } && error "$(optionsError)"
[ "$EDITOR" ] || error "$(editConfigError)"
edit="$(which "$EDITOR")"
shift
;;
-f | -files)
wmakeFiles="$wmakeFiles files"
shift
;;
-h | -help)
usage
;;
-i | -isearch)
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
[ "$insensitive" ] && error "$(searchError)"
{ [ "$print" ] || [ "$edit" ]; } && error "$(optionsError)"
search="$2"
insensitive=on
shift 2
;;
-m | -modules)
[ "$dir" ] && error "$(dirError)"
dir="$FOAM_MODULES"
shift
;;
-n | -numbers)
numbers="numbers" # flag for line numbers in cat or grep
shift
;;
-o | -options)
wmakeFiles="$wmakeFiles options"
shift
;;
-p | -print)
{ [ "$insensitive" ] || [ "$edit" ]; } && error "$(optionsError)"
print="yes"
shift
;;
-s | -search)
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
[ "$insensitive" ] && error "$(searchError)"
{ [ "$print" ] || [ "$edit" ]; } && error "$(optionsError)"
search="$2"
insensitive=off
shift 2
;;
-t | -tutorials)
[ "$dir" ] && error "$(dirError)"
dir="$FOAM_TUTORIALS"
shift
;;
-*)
error "Invalid option '$1'"
;;
*)
# If filename is already set, then exit
[ "$filename" ] && error "Arguments specified ($#) =/= 1"
filename="$1"
shift
;;
esac
done
# Default search directory if not specified
[ "$dir" ] || dir="$FOAM_SRC"
# Disallow '-files' and '-options' if search directory does not include source code
[ "$wmakeFiles" ] && ! isSrcDir "$dir" && \
error "With search directory '$dir' (not source code)," \
"cannot use '-files' or '-options'"
# Check number of arguments
[ "$#" -eq 0 ] || error "Arguments specified =/= 1 (optional)"
# If filename is not set, check search string is specified
! [ "$filename" ] && ! [ "$search" ] && \
error "<filename> can only be omitted if a search string is specified" \
"with the '-search' option"
# If '-files' or '-options' is selected, ensure <filename> is set
! [ "$filename" ] && [ "$wmakeFiles" ] && \
error "With '-files' or '-options', <filename> must be specified"
# Find files
files="$(listFiles "$dir" "$filename" "$search" "$insensitive")"
# Ensure there is at least one file
nParams "$files" > /dev/null || error "No file '$filename' found in '$dir'"
# Select files when more than one is found
files="$(selectFile "$filename" "$files")" || error
# With '-files' and/or '-options', reuse file variable as the file
{ [ "$wmakeFiles" ] || [ "$edit" ] ; } && \
[ "$(nParams "$files")" -ne 1 ] && \
error "With '-files', '-options' or '-edit', a single file must be selected"
[ "$wmakeFiles" ] &&
! files="$(findWmakeFiles "$files" "$wmakeFiles")" && error
# Output
for f in $files
do
printf "\nFile: %s\n" "$f"
# Printing entire files
[ "$print" ] && \
printf ">>>\n" && \
{ [ "$numbers" ] && cat -n "$f" || cat "$f" ; } && \
printf "<<<\n"
# Opening files in a editor
[ "$edit" ] && "$edit" "$f"
# Printing lines matching strings
[ "$search" ] || continue
! grepFile "$search" "$f" "$insensitive" test && \
echo "Search: no match" && continue
printf ">>>\n"
grepFile "$search" "$f" "$insensitive" "$numbers"
printf "<<<\n"
done