From 6efe117545cbceef4368866678f1c9e049e2b301 Mon Sep 17 00:00:00 2001 From: Jeremy Baxter Date: Sun, 24 Sep 2023 10:31:12 +1300 Subject: [PATCH] Switch to configure and make based build Also removed excessive use of std.regex in esvapi.d and made it actually compile -_- --- .gitignore | 1 + Makefile | 32 --------- README.md | 35 ++++++---- configure | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++ esvapi.d | 67 ++++++++++++------- 5 files changed, 254 insertions(+), 68 deletions(-) delete mode 100644 Makefile create mode 100755 configure diff --git a/.gitignore b/.gitignore index c4d9507..ad9dd2d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.so *.a esv +Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 6bd438e..0000000 --- a/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -IMPORT = import -PREFIX = /usr/local -MANPREFIX = /usr/share/man - -DC = ldc2 -CFLAGS = -O -I${IMPORT} -release -w -OBJS = main.o esvapi.o ini.o - -all: esv - -esv: ${OBJS} - ${DC} ${CFLAGS} -of$@ ${OBJS} - -# main executable -main.o: main.d esvapi.o - ${DC} ${CFLAGS} -of$@ -c main.d - -esvapi.o: esvapi.d - ${DC} ${CFLAGS} -of$@ -c esvapi.d - -ini.o: ${IMPORT}/dini/*.d - ${DC} ${CFLAGS} -of$@ -c ${IMPORT}/dini/*.d - -clean: - rm -f esv ${OBJS} - -install: esv - install -m755 esv ${DESTDIR}${PREFIX}/bin/esv - cp -f esv.1 ${DESTDIR}${MANPREFIX}/man1 - cp -f esv.conf.5 ${DESTDIR}${MANPREFIX}/man5 - -.PHONY: all clean install diff --git a/README.md b/README.md index 5bfc305..d69a187 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ *Read the Bible from your terminal* -`esv` is a utility that displays passages of the English Standard Bible on your terminal. -It connects to the ESV web API to retrieve the passages, +`esv` is a utility that displays passages of the English Standard Bible +on your terminal. It connects to the ESV web API to retrieve the passages, and allows configuration through command-line options and the configuration file. Example usage: @@ -20,18 +20,20 @@ A Psalm of David. He makes me lie down in green pastures.... ``` -If the requested passage is over 32 lines long, `esv` will pipe it through a pager -(default less). The pager being used can be changed through the `ESV_PAGER` -environment variable or just disabled altogether by passing the -P option. +If the requested passage is over 32 lines long, `esv` will pipe it through +a pager (default less). The pager being used can be changed through the +`ESV_PAGER` environment variable or just disabled altogether by passing the +-P option. -The names of Bible books are not case sensitive, so John, john, JOHN and jOhN +The names of Bible books are not case sensitive, so John, john, and JOHN are all accepted. ## Audio `esv` supports playing audio passages through the -a option. -The `mpg123` audio/video player is utilised here and so it is therefore required -if you want to use audio mode. +The `mpg123` audio/video player is utilised here and so it required if you +want to play audio passages. If you prefer, you can use a different player +(such as mpv) by editing config.di. Audio usage is the same as normal text usage. `esv -a Matthew 5-7` will play an audio passage of Matthew 5-7. @@ -40,10 +42,13 @@ an audio passage of Matthew 5-7. To install `esv`, first make sure you have the [LLVM D compiler (ldc)](https://github.com/ldc-developers/ldc#installation) -installed on your system. You should also have Phobos (the D standard library, comes included with LDC) -installed as a dynamic library in order to run the executable. +installed on your system. -First clone the source code repository: +Commands prefixed with a dollar sign ($) are intended to be run as +a standard user, and commands prefixed with a hash sign (#) are intended +to be run as the root user. + +First, get the source code: ``` $ git clone https://codeberg.org/jtbx/esv @@ -53,13 +58,15 @@ $ cd esv Now, compile and install: ``` +$ ./configure $ make # make install ``` -By default the Makefile guesses that the ldc executable is named `ldc2`. If it is installed -under a different name, or if you wish to use a different compiler, use `make DC=compiler` -(where `compiler` is your compiler) instead. + ## Documentation diff --git a/configure b/configure new file mode 100755 index 0000000..8d03e11 --- /dev/null +++ b/configure @@ -0,0 +1,187 @@ +#!/usr/bin/env sh +# simple and flexible configure script for people who don't like to waste time +# licensed to the public domain + +set -e + +IMPORT=import + +mkf=Makefile +cflags=-I"$IMPORT" +objs='esv.o esvapi.o' +srcs='esv.d esvapi.d' +makefile=' +IMPORT = '"$IMPORT"' +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/man + +DC = ${_DC} +CFLAGS = ${_CFLAGS} +OBJS = ${_OBJS} ini.o + +all: esv + +esv: ${OBJS} + ${DC} ${_LDFLAGS} -of=$@ ${OBJS} + +.SUFFIXES: .d .o + +.d.o: + ${DC} ${CFLAGS} -c $< + +ini.o: ${IMPORT}/dini/*.d + ${DC} ${CFLAGS} -of=ini.o -c ${IMPORT}/dini/*.d + +clean: + rm -f esv ${OBJS} + +install: esv + install -m755 esv ${DESTDIR}${PREFIX}/bin/esv + cp -f esv.1 ${DESTDIR}${MANPREFIX}/man1 + cp -f esv.conf.5 ${DESTDIR}${MANPREFIX}/man5 + +.PHONY: all clean install +' + +# utility functions + +present () { + command -v "$1" 1>/dev/null 2>/dev/null +} +using () { + >&2 printf "using $1\n" +} +error () { + >&2 printf "$(basename $0): $1\n" + exit 1 +} + +# generators + +## D compiler +gen_DC () { + if ! [ -z "$dc" ]; then + using "$dc" + return 0 + fi + if present ldc2; then + dc=ldc2 + using ldc2 + elif present dmd; then + dc=dmd + using dmd + else + error "D compiler not found; install ldc or dmd" + fi +} + +## flags used in the compilation step +gen_CFLAGS () { + if [ -z "$debug" ]; then + case "$dc" in + ldc2) cflags="-Oz";; + dmd) cflags="-O";; + esac + using "$cflags" + else + fdebugsymbols="-g" + using "$fdebugsymbols" + case "$dc" in + ldc2) + fdebug="-d-debug" + using "$fdebug" + foptimisation="-O0" + using "$foptimisation" + ;; + dmd) fdebug="-debug";; + esac + cflags="$fdebugsymbols $fdebug" + unset fdebug + unset fdebugsymbols + unset foptimisation + fi +} + +## flags used in the linking step +gen_LDFLAGS () { + if [ "$dc" = ldc2 ]; then + if present ld.lld; then + ldflags="-linker=lld" + using "$ldflags" + elif present ld.gold; then + ldflags="-linker=gold" + using "$ldflags" + fi + fi +} + +# command line interface + +while getopts c:dhr ch; do + case "$ch" in + c) + case "$OPTARG" in + ldc2) dc="ldc2" ;; + dmd) dc="dmd" ;; + *) error "unknown D compiler '$OPTARG' specified (valid options: ldc2, dmd)" ;; + esac + ;; + d) debug=1 ;; + r) unset debug ;; + h) + cat <>"$mkf" +printf ' +_DC = %s +_CFLAGS = %s +_LDFLAGS = %s +' \ + "$dc" \ + "$cflags $u_cflags" \ + "$ldflags" \ + >>"$mkf" +## generate obj list +printf '_OBJS =' >>"$mkf" +for obj in $objs; do + printf " $obj" >>"$mkf" +done +printf '\n' >>"$mkf" +printf '# end generated definitions\n' >>"$mkf" + +printf "$makefile" >>"$mkf" + +## generate dependency list +>&2 printf "generating dependency list\n" +printf '\n# begin generated dependencies\n' >>"$mkf" +i=1 +for obj in $objs; do + "$dc" $u_cflags -O0 -o- -makedeps \ + "$(printf "$srcs" | awk '{print $'"$i"'}')" >>"$mkf" + i="$(($i + 1))" +done +printf '# end generated dependencies\n' >>"$mkf" diff --git a/esvapi.d b/esvapi.d index 84d17a7..f0cac7d 100644 --- a/esvapi.d +++ b/esvapi.d @@ -25,9 +25,9 @@ import std.exception : basicExceptionCtors, enforce; import std.file : tempDir, write; import std.format : format; import std.json : JSONValue, parseJSON; -import std.regex : regex, matchAll, replaceAll; +import std.regex : regex, matchAll; import std.stdio : File; -import std.string : capitalize; +import std.string : capitalize, tr; import std.net.curl : HTTP; enum ESVIndent @@ -162,8 +162,6 @@ bool verseValid(in char[] verse) @safe return false; } -} - class ESVApi { protected { @@ -234,32 +232,51 @@ class ESVApi params = []; { - (char[])[] parambuf; + void *o; + string[] parambuf; foreach (string opt; ESVAPI_PARAMETERS) { - bool bo; - int io; - switch (opt) { case "indent-using": - o = opts.indent_using; + o = cast(void *)opts.indent_using; break; case "indent-poetry": + case "include-passage-references": + case "include-verse-numbers": + case "include-first-verse-numbers": + case "include-footnotes": + case "include-footnote-body": + case "include-headings": + case "include-short-copyright": + case "include-copyright": + case "include-passage-horizontal-lines": + case "include-heading-horizontal-lines": + case "include-selahs": + o = cast(void *)opts.b[opt]; + break; + case "line-length": + case "horizontal-line-length": + case "indent-paragraphs": + case "indent-poetry-lines": + case "indent-declares": + case "indent-psalm-doxology": + o = cast(void *)opts.i[opt]; + break; + default: break; } - !opt.matchAll("^include-").empty) { - o = opts.b[opt]; - } else if (opt == "line-length" || - opt == "horizontal-line-length" || - !opt.matchAll("^indent-").empty) { - o = opts.i[opt]; - } - params = format!"%s&%s=%s"(params, opt, o.to!string()); + parambuf[parambuf.length] = format!"&%s=%s"( + opt, + opt == "indent-using" ? + opts.indent_using == ESVIndent.TAB ? "tab" : "space" + : o.to!string() + ); } } - request = HTTP( - format!"%s/text/?q=%s+%s%s%s"(_url, book + request = HTTP(format!"%s/text/?q=%s+%s%s%s"( + _url, + book .capitalize() - .replaceAll(regex(" "), "+"), + .tr(" ", "+"), verse, params, extraParameters) ); request.onProgress = onProgress; @@ -290,7 +307,12 @@ class ESVApi File tmpFile; auto request = HTTP(format!"%s/audio/?q=%s+%s"( - _url, book.capitalize().replaceAll(regex(" "), "+"), verse)); + _url, + book + .capitalize() + .tr(" ", "+"), + verse) + ); request.onProgress = onProgress; request.onReceive = (ubyte[] data) @@ -320,7 +342,8 @@ class ESVApi JSONValue json; request = HTTP(format!"%s/search/?q=%s"( - _url, query.replaceAll(regex(" "), "+"))); + _url, query.tr(" ", "+")) + ); request.onProgress = onProgress; request.onReceive = (ubyte[] data)