commit 78211e76872d631430015511c558f3bbf6588df4
parent 2452e2730d8fefaf1fc90842f894ef1efa39bf61
Author: Wilson Gheen <wilson@wilsonrgheen.com>
Date:   Sun, 31 Jul 2022 07:57:29 -0500
Refactor (gawk --lint) and partially standardize code and indentation
Diffstat:
| M | Makefile |  |  | 5 | +++-- | 
| M | bbl.awk |  |  | 21 | +++++++++------------ | 
| M | bbl.sh |  |  | 170 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ | 
3 files changed, 105 insertions(+), 91 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,8 +8,9 @@ bbl: bbl.sh bbl.awk *.tsv
 	tar cz bbl.awk *.tsv >> $@
 	chmod +x $@
 
-test: bbl.sh
-	shellcheck -s sh bbl.sh
+test: bbl.sh bbl.awk
+	shellcheck -s sh -S error bbl.sh
+	echo -n | gawk --lint=invalid -f bbl.awk
 
 clean:
 	rm -f bbl
diff --git a/bbl.awk b/bbl.awk
@@ -29,19 +29,17 @@ BEGIN {
 	}
 
 	if (cmd == "ref") {
-        switch(lang) {
-            case "he":
+        if (lang == "he") {
                 re["num"] = "[ק-ת]?([יכלמנסעפצ]?[א-ט]?|טו|טז)"
                 re["book"] = "([א-ת]+ )?[א-ת]+"
                 re["chsep"] = ":"
-                break
-            default:
+        }
+        else {
                 re["num"] = "[1-9]+[0-9]*"
                 re["book"] = "^[1-9]?[a-zA-Z ]+"
                 re["chsep"] = ":?"
-                break
         }
-		mode = parseref(ref, p, re)
+		mode = parseref(p)
 		p["book"] = cleanbook(p["book"])
 	}
 }
@@ -64,7 +62,7 @@ function num(str){
     return (lang == "he") ? str : int(str)
 }
 
-function parseref(ref, arr, re) {
+function parseref(arr) {
     # NOTE: For Hebrew, the colon between book and chapter is required
 	# 1. <book>
 	# 2. <book>:?<chapter>
@@ -259,8 +257,7 @@ function bookmatches(book, bookabbr, query) {
 function roughpattern(regex) {
     # TODO Can mess with search pattern if regex is used on command line
     regex = tolower(regex)
-    switch(lang) {
-        case "el":
+    if (lang == "el") {
             polytonic["α"] = "[αάἀ-ἆὰᾀ-ᾆᾳ-ᾷ]"
             polytonic["ε"] = "[εέἐ-ἕὲ]"
             polytonic["η"] = "[ηήἠ-ἧὴᾐ-ᾗῃ-ῇ]"
@@ -271,10 +268,9 @@ function roughpattern(regex) {
             for (letter in polytonic) {
                 gsub(letter, polytonic[letter], regex)
             }
-            break
-        case "la":
+    }
+    else if (lang =="la" ) {
             gsub("e", "[eë]", regex)
-            break
     }
     return regex
 }
@@ -388,6 +384,7 @@ END {
 	if (cmd == "ref") {
         if (outputted_records == 0) {
 		    print "Unknown reference: " ref
+		    exit 1
         } else if (mode == "random") {
             printf("~~~RANDOMS: %d\n", p["numberOfVerses"])
         }
diff --git a/bbl.sh b/bbl.sh
@@ -6,101 +6,114 @@ SELF="$0"
 BIBLE=""
 
 data_exists() {
-    sed '1,/^#EOF$/d' < "$SELF" | tar tz "$1.tsv" > /dev/null 2>&1
+    sed '1,/^#EOF$/d' < "$SELF" | tar tz "$1.tsv" >/dev/null 2>&1
 }
 get_data() {
-	sed '1,/^#EOF$/d' < "$SELF" | tar xz -O "$1"
+    sed '1,/^#EOF$/d' < "$SELF" | tar xz -O "$1"
+}
+get_ref() {
+    # Thank you, StackExchange. This will cause $PAGER to give the same exit code
+    # that bbl would have given, so that a nonzero exit code can be used in scripts
+    # to know that the reference returned no results.
+    { { { { get_data "$1" | awk -v cmd=ref -v ref="$2" -v cross_ref="$3" -v lang="$lang" "$(get_data bbl.awk)"; echo $? >&3; } | ${PAGER} >&4; } 3>&1; } | { read xs; exit $xs; } } 4>&1
+}
+list_books() {
+    reading="$(echo "${BIBLE}" | cut -d " " -f 1)"
+    get_data "$reading" 2>/dev/null | awk -v cmd=list "$(get_data bbl.awk)" | ${PAGER}
+    exit
 }
 list_readings() {
     sed '1,/^#EOF$/d' < "$SELF" | tar tz --wildcards "*.tsv" | sed 's/\.tsv$//'
-    exit 0
+    exit
 }
 
 if [ ! -t 1 ]; then
     # If output is not a terminal, prevent the default behavior of opening the data in the pager only to send it down the pipeline
     PAGER="cat"
 elif [ -z "$PAGER" ]; then
-	if command -v less >/dev/null; then
-		PAGER="less"
-	else
-		PAGER="cat"
-	fi
+    if command -v less >/dev/null; then
+        PAGER="less"
+    else
+        PAGER="cat"
+    fi
 fi
 
 show_help() {
-	exec >&2
-	echo "usage: $(basename "$0") [flags] [reference...]"
-	echo
+    exec >&2
+    echo "usage: $(basename "$0") [flags] [reference...]"
+    echo
     echo "  Flags:"
     echo "  -l, --list-books        list book names (for the reading chosen)"
     echo "  -L, --list              list options for readings (Vulgate, KJV, Latin poems, etc.)"
     echo "  -o                      choose a reading by name (i.e. by the name of the corresponding TSV file, sans file extension)"
-	echo "  -W, --no-line-wrap      no line wrap"
-	echo "  -V, --no-verse-numbers  no verse numbers are printed--just the book title at the top and a number for each chapter"
+    echo "  -W, --no-line-wrap      no line wrap"
+    echo "  -V, --no-verse-numbers  no verse numbers are printed--just the book title at the top and a number for each chapter"
     echo "  -C, --no-ch-numbers     no chapter headings either (implies -V)"
     echo "  -T, --no-title          book title is not printed"
     echo "  -B, --no-verse-break    No linebreaks at the end of each verse--each chapter runs like a continuous paragraph. Currently implies -V (I am working on changing that)"
-	echo "  -N, --no-format         Equivalent to -WCTB"
+    echo "  -N, --no-format         Equivalent to -WCTB"
         echo "  -c, --cat               echo text to STDOUT"
-	echo "  -h, --help              show help"
+    echo "  -h, --help              show help"
         echo "  Bibles:"
-	echo "  -d, --douay             Douay-Rheims Bible"
+    echo "  -d, --douay             Douay-Rheims Bible"
     echo "  -g, --greek             Greek Bible (Septuagint + SBL NT)"
     echo "  -H, --hebrew            The Bible in Hebrew (with cantillation marks and niqqudim)"
-	echo "  -i, --ivrit             The Bible in Hebrew without cantillation marks and niqqudim"
-	echo "  -j, --jerusalem         New Jerusalem Bible"
-	echo "  -k, --kjv               King James Bible"
-	echo "  -n, --knox              Knox Bible"
+    echo "  -i, --ivrit             The Bible in Hebrew without cantillation marks and niqqudim"
+    echo "  -j, --jerusalem         New Jerusalem Bible"
+    echo "  -k, --kjv               King James Bible"
+    echo "  -n, --knox              Knox Bible"
         echo "  -r, --rsv               Revised Standard Version: Catholic Edition"
-	echo "  -v, --vulgate           Clementine Vulgate"
+    echo "  -v, --vulgate           Clementine Vulgate"
     echo
     echo "Specify multiple versions to cross-reference (view them in multi-column fashion)."
     echo "This feature is not yet available for languages that are read right-to-left."
     echo "Specifying -i or -H will currently override all other translations and output only the Hebrew Bible."
-	echo
-	echo "  Reference types:"
+    echo
+    echo "  Reference types:"
     echo "  NOTE: The colon between book and chapter is required for Hebrew, optional for everything else."
     echo " References for Hebrew must be in Hebrew; for all else, must be in English."
-	echo "      <Book>"
-	echo "          Individual book"
-	echo "      <Book>:<Chapter>"
-	echo "          Individual chapter of a book"
-	echo "      <Book>:<Chapter>:<Verse>[,<Verse>]..."
-	echo "          Individual verse(s) of a specific chapter of a book"
-	echo "      <Book>:<Chapter>:<Verse>[,<Chapter>:<Verse>]..."
-	echo "          Individual verses of different chapters of a book"
-	echo "      <Book>:<Chapter>-<Chapter>"
-	echo "          Range of chapters in a book"
-	echo "      <Book>:<Chapter>:<Verse>-<Verse>"
-	echo "          Range of verses in a book chapter"
-	echo "      <Book>:<Chapter>:<Verse>-<Chapter>:<Verse>"
-	echo "          Range of chapters and verses in a book"
-	echo
-	echo "      /~?<Search>"
-	echo "          All verses that match a pattern"
-	echo "      <Book>/~?<Search>"
-	echo "          All verses in a book that match a pattern"
-	echo "      <Book>:<Chapter>/~?<Search>"
-	echo "          All verses in a chapter of a book that match a pattern"
-	echo "      In searches, the optional ~ indicates that the search should be approximate:"
-	echo "      Case and accent marks will be disregarded. Note that this will often take"
-	echo "      much longer than an exact search"
+    echo "      <Book>"
+    echo "          Individual book"
+    echo "      <Book>:<Chapter>"
+    echo "          Individual chapter of a book"
+    echo "      <Book>:<Chapter>:<Verse>[,<Verse>]..."
+    echo "          Individual verse(s) of a specific chapter of a book"
+    echo "      <Book>:<Chapter>:<Verse>[,<Chapter>:<Verse>]..."
+    echo "          Individual verses of different chapters of a book"
+    echo "      <Book>:<Chapter>-<Chapter>"
+    echo "          Range of chapters in a book"
+    echo "      <Book>:<Chapter>:<Verse>-<Verse>"
+    echo "          Range of verses in a book chapter"
+    echo "      <Book>:<Chapter>:<Verse>-<Chapter>:<Verse>"
+    echo "          Range of chapters and verses in a book"
+    echo
+    echo "      /~?<Search>"
+    echo "          All verses that match a pattern"
+    echo "      <Book>/~?<Search>"
+    echo "          All verses in a book that match a pattern"
+    echo "      <Book>:<Chapter>/~?<Search>"
+    echo "          All verses in a chapter of a book that match a pattern"
+    echo "      In searches, the optional ~ indicates that the search should be approximate:"
+    echo "      Case and accent marks will be disregarded. Note that this will often take"
+    echo "      much longer than an exact search"
     echo
-	echo "      @ <Number-of-Verses>?"
-	echo "          Random verse or assortment of verses from any book/chapter"
-	echo "      <Book> @ <Number-of-Verses>?"
-	echo "          Random verse or assortment of verses from any chapter in a given book"
-	echo "      <Book>:<Chapter> @ <Number-of-Verses>?"
-	echo "          Random verse or assortment of verses from the given book:chapter"
-	exit 2
+    echo "      @ <Number-of-Verses>?"
+    echo "          Random verse or assortment of verses from any book/chapter"
+    echo "      <Book> @ <Number-of-Verses>?"
+    echo "          Random verse or assortment of verses from any chapter in a given book"
+    echo "      <Book>:<Chapter> @ <Number-of-Verses>?"
+    echo "          Random verse or assortment of verses from the given book:chapter"
+    echo
+    echo " Exit code is 0 if no problems; 1 if cross-referencing and one or more references"
+    echo " returned nothing; 2 if no references returned anything."
 }
 
 set_bible() {
-    if [ -z "${BIBLE}" ] || [ "$nocrossref" ]; then
+    if [ -z "$BIBLE" ] || [ "$nocrossref" ]; then
         BIBLE=$1
     else
         #For cross-referencing
-        BIBLE=${BIBLE}" "$1
+        BIBLE="$BIBLE $1"
     fi
 }
 default_bible() {
@@ -153,7 +166,8 @@ while [ $# -gt 0 ]; do
                 PAGER="cat"
                 shift ;;
         -h|--help)
-                show_help ;;
+                show_help
+                exit 0 ;;
         -d|--douay)
                 set_bible drb
                 shift ;;
@@ -194,10 +208,8 @@ done
 
 [ -z "$BIBLE" ] && default_bible
 
-if [ "$list" ]; then
-    get_data "$(echo "${BIBLE}" | cut -d " " -f 1).tsv" | awk -v cmd=list "$(get_data bbl.awk)" | ${PAGER}
-    exit
-fi
+[ "$list" ] && list_books
+
 
 if cols=$(tput cols 2>/dev/null); then
         versions=0
@@ -209,35 +221,39 @@ if cols=$(tput cols 2>/dev/null); then
 fi
 
 if [ $# -eq 0 ]; then
-	if [ ! -t 0 ]; then
-		show_help
-	fi
+    if [ ! -t 0 ]; then
+        echo "Interactive mode cannot be used unless in a terminal"
+        exit 2
+    fi
 
-	# Interactive mode
+    # Interactive mode
     b="$(echo "$BIBLE" | cut -d ' ' -f 1)"
-	while true; do
-		printf '%s> ' "$b"
-		if ! read -r ref; then
-			break
-		fi
-		get_data "$b.tsv" | awk -v cmd=ref -v ref="$ref" -v lang="$lang" "$(get_data bbl.awk)" | ${PAGER}
-	done
-	exit 0
+    while true; do
+        printf '%s> ' "$b"
+        if ! read -r ref; then
+            break
+        fi
+        get_ref "$b" "$ref"
+    done
+    exit 0
 fi
 
 i=0
 tempDirPattern="${TMPDIR:-/tmp/}$(basename "$0")."
 myTempDir=$(mktemp -d "${tempDirPattern}XXXXXXXXXXXX")
 exitCode=0
+atLeastOneSuccess=''
 for version in $BIBLE; do
     filename="${myTempDir}/${i}-${version}.txt"
-    get_data "${version}".tsv 2>/dev/null | awk -v cmd=ref -v ref="$*" -v cross_ref="${i}" -v lang="$lang" "$(get_data bbl.awk)" 2>/dev/null > "$filename"
+    get_ref "$version.tsv" "$*" "$i" > "$filename"
+    [ $? -ne 0 ] && exitCode=1 || atLeastOneSuccess='y'
     i=$((i + 1))
 done
+[ -z "$atLeastOneSuccess" ] && exitCode=2
 
 if [ ${i} -gt 1 ]; then
     filename="${myTempDir}/crossref.txt"
-    paste -d '@' $(ls -d "${myTempDir}/"*) | column -t -s "@" -o "	" | sed '/^[a-zA-Z]/s/^/\t/;1s/^ *//;' > "$filename"
+    paste -d '@' $(ls -d "${myTempDir}/"*) | column -t -s "@" -o "    " | sed '/^[a-zA-Z]/s/^/\t/;1s/^ *//;' > "$filename"
     # Remove all files in the tmpdir with a hyphen in the name, i.e. everything except the file we just created
     rm "$myTempDir"/*-*
 else
@@ -260,7 +276,7 @@ if [ "$noTerm" ]; then
         echo "$0: Text may not be terminal-compatible and BROWSER environment variable is not set or cannot be invoked."
         echo "To suppress this error and try to display on the terminal no matter what, set the environment"
         echo "variable 'UNICODE_TERM' to a non-empty string"
-        exitCode=1
+        exitCode=2
     fi
 elif [ "$r2l" ]; then
     rev "${filename}" | $PAGER
@@ -268,6 +284,6 @@ else
     $PAGER "$filename"
 fi
 
-rm -rf "$tempDirPattern"??*
+rm -r "$tempDirPattern"??*
 mv "${tempDirPattern}K" "$myTempDir" 2>/dev/null # Preserves browser-viewable files for only one invocation
 exit "$exitCode"