Switch to configure and make based build

Also removed excessive use of std.regex in esvapi.d and
made it actually compile -_-
This commit is contained in:
Jeremy Baxter 2023-09-24 10:31:12 +13:00
parent 7ebc0d7b66
commit 6efe117545
5 changed files with 254 additions and 68 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
*.so
*.a
esv
Makefile

View file

@ -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

View file

@ -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.
<!--
By default the configure script looks for ldc and dmd in your PATH
and optimises the command-line arguments based on the compiler.
-->
## Documentation

187
configure vendored Executable file
View file

@ -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 <<EOF
configure: create an optimised makefile for the current environment
options:
-c: force use of a particular compiler (dmd or ldc2)
-d: build in debug mode, with debug symbols and statements enabled
-r: build in release mode with optimisation flags enabled (default)
-h: show this help message
EOF
exit 0
;;
?) exit 1 ;;
:) exit 1 ;;
esac
done
# creating the makefile
u_cflags="$cflags"
unset cflags
gen_DC
gen_CFLAGS
gen_LDFLAGS
rm -f "$mkf"
printf '# begin generated definitions' >>"$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"

View file

@ -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)