[bash] pg() a simple paging function

Here is a greatly improved version of the same function:

#======================================================================
# Format a file (or standard input) and display it or page it if
# necessary
#     pg [-n] [file]
#        -n add line numbers to output
#======================================================================
pg () {

    # capture standard input
    # huge files can, of course, fill all available memory
    while read -t 0.1 line; do
        if ! [[ -v pipeFile ]]; then
            local -a pipeFile
            local inc
            local lineCount
        fi
        if [[ "$1" = '-n' ]]; then
            local numColumns=8  # number of columns devoted to line numbers
        fi
        pipeFile=( "${pipeFile[@]}" "$line" )
        inc=$(fmt -s -w $(( COLUMNS - ${numColumns:-0} )) <<< $line | wc -l)
        lineCount=$(( lineCount + inc ))
    done

    # set up line numbering
    if [[ "$1" = '-n' ]]; then
        [[ -v numColumns ]] || local numColumns=8
        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

    # number of lines taken by PS1 prompt
    local promptLines=$(echo -e "$PS1" | wc -l)

    # if taking input from a file
    if [[ $# -gt 0 ]]; then
        if [[ -f "$1" ]]; then
            # format file and feed it to either less or cat
            fmt -s -w $(( COLUMNS - ${numColumns:-0} )) "$1" |
            if [[ $(fmt -s -w $(( COLUMNS - ${numColumns:-0} )) "$1" | wc -l) \
                -gt $(( LINES - promptLines )) ]]; then
                less ${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 - ${numColumns:-0} )) |
        if [[ lineCount -gt $(( LINES - promptLines )) ]]; then
            less ${num[less]}
        elif [[ lineCount -gt 0 ]]; then
            cat ${num[cat]}
        else
            :
        fi
    fi
}

This will take input from standard input as well as from a file and does basic error checking. One problem with this function is that it reads all of standard input into an array before processing it. Very large files can thus fill all of memory and crash.

/r/ScriptSwap Thread