Yet another, better, version. This one seems to fix all formatting issues.
#======================================================================
# Format a file (or standard input) and display it or page it if
# necessary
# pg [-n] [file]
# -n add line numbers to output
#======================================================================
pg () {
local -r ncols=8 # number of columns used for line numbers
local -r promptLines=$(echo -e "$PS1" | wc -l) # number of lines taken by PS1 prompt
# capture standard input
# huge files can, of course, fill all available memory
while IFS='' read -r -t 0.1 line; do
if ! [[ -v pipeFile ]]; then
local -a pipeFile
local inc
local lineCount
fi
pipeFile=( "${pipeFile[@]}" "$line" )
inc=$(fmt -s -w $(( COLUMNS - ncols )) <<< $line | wc -l)
lineCount=$(( lineCount + inc ))
done
# set up line numbering
if [[ "$1" = '-n' ]]; then
local -A num
num[cat]='-n' # parameter for turning on line numbering in cat
num[less]='-N' # parameter for turning on line numbering in less
shift
fi
# if taking input from a file
if [[ $# -gt 0 ]]; then
if [[ -f "$1" ]]; then
# format file only if necessary and feed it to either less or cat
fmt -s -w $(( COLUMNS - ncols )) "$1" |
if [[ $(fmt -s -w $(( COLUMNS - ncols )) "$1" | wc -l) \
-gt $(( LINES - promptLines )) ]]; then
less -R ${num[less]}
else
cat ${num[cat]}
fi
elif [[ -d "$1" ]]; then
printf '%s: %s: Is a directory\n' 'pg' "$1" >&2
else
printf '%s: %s: No such file or directory\n' 'pg' "$1" >&2
fi
elif [[ -v pipeFile ]]; then # taking input from standard input
for line in "${pipeFile[@]}"; do
echo "$line"
done |
fmt -s -w $(( COLUMNS - ncols )) |
if [[ lineCount -gt $(( LINES - promptLines )) ]]; then
less -R ${num[less]}
elif [[ lineCount -gt 0 ]]; then
cat ${num[cat]}
else
:
fi
fi
}