From ec8be68b49f0676f9e19e981e99c6807cd8451af Mon Sep 17 00:00:00 2001 From: Jeremy Baxter Date: Wed, 26 Jun 2024 12:55:41 +1200 Subject: [PATCH] esvsearch: split esv search code into separate program Requires rewiring the build system to accommodate for two executables. Fixes: https://todo.sr.ht/~jeremy/esv/4 --- .gitignore | 1 + Makefile | 13 ++++--- configure | 4 +- esv.1 | 5 --- esv.d | 21 +--------- esvsearch.d | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 esvsearch.d diff --git a/.gitignore b/.gitignore index 2564793..a2666f7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.so *.a esv +esvsearch result config.mk \ No newline at end of file diff --git a/Makefile b/Makefile index 25e82a6..009925f 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,14 @@ DC = ${_DC} CFLAGS = ${_CFLAGS} OBJS = ${_OBJS} -all: esv +all: esv esvsearch include config.mk -esv: ${OBJS} - ${DC} ${_LDFLAGS} -of=$@ ${OBJS} +esv: esv.o ${OBJS} + ${DC} ${_LDFLAGS} -of=$@ esv.o ${OBJS} +esvsearch: esvsearch.o ${OBJS} + ${DC} ${_LDFLAGS} -of=$@ esvsearch.o ${OBJS} .SUFFIXES: .d .o @@ -19,10 +21,11 @@ esv: ${OBJS} ${DC} ${CFLAGS} -c $< clean: - rm -f esv ${OBJS} ${INIOBJS} + rm -f esv esvsearch esv.o esvsearch.o ${OBJS} -install: esv +install: esv esvsearch install -Dm755 esv ${DESTDIR}${PREFIX}/bin/esv + install -Dm755 esvsearch ${DESTDIR}${PREFIX}/bin/esvsearch install -Dm644 esv.1 ${DESTDIR}${MANPREFIX}/man1/esv.1 install -Dm644 esv.conf.5 ${DESTDIR}${MANPREFIX}/man5/esv.conf.5 diff --git a/configure b/configure index 38055a6..9eb816c 100755 --- a/configure +++ b/configure @@ -5,8 +5,8 @@ set -e mkf=config.mk -objs='esv.o esvapi.o util.o initial.o' -srcs='esv.d esvapi.d util.d initial.d' +objs='esvapi.o util.o initial.o' +srcs='esvapi.d util.d initial.d' # utility functions diff --git a/esv.1 b/esv.1 index 84b5b02..35257e8 100644 --- a/esv.1 +++ b/esv.1 @@ -10,7 +10,6 @@ .Op Fl aFfHhNnRrV .Op Fl c Ar config .Op Fl l Ar length -.Op Fl s Ar query .Ar book verses .Ek .Sh DESCRIPTION @@ -96,10 +95,6 @@ Include verse numbers (the default). Exclude passage references. .It Fl r Include passage references (the default). -.It Fl s Ar query -Rather than displaying a passage or playing an audio track, -search the Bible for instances of -.Ar query . .It Fl V Print the version number and exit. .El diff --git a/esv.d b/esv.d index dc2e7f6..c173feb 100644 --- a/esv.d +++ b/esv.d @@ -45,7 +45,6 @@ int lFlag; /* line length */ bool lFlagSpecified; bool nFlag, NFlag; /* verse numbers */ bool rFlag, RFlag; /* passage references */ -string sFlag; /* search passages */ bool VFlag; /* show version */ int @@ -73,7 +72,6 @@ main(string[] args) "l", &onLineLength, "N", &NFlag, "n", &nFlag, "R", &RFlag, "r", &rFlag, - "s", &sFlag, "V", &VFlag, ); } catch (GetOptException e) { @@ -85,14 +83,9 @@ main(string[] args) return 0; } - if (sFlag != "") { - /* skip argument validation */ - goto config; - } - if (args.length < 3) { stderr.writefln( - "usage: %s [-aFfHhNnRrV] [-c config] [-l length] [-s query] book verses", + "usage: %s [-aFfHhNnRrV] [-c config] [-l length] book verses", baseName(args[0])); return 1; } @@ -134,8 +127,6 @@ key = %s die(e.msg); } - enforceDie(!(aFlag && sFlag), "cannot specify both -a and -s flags"); - apiKey = ini["api"].key("key"); enforceDie(apiKey != null, "API key not present in configuration file; cannot proceed"); @@ -168,16 +159,6 @@ key = %s return 0; } - if (sFlag) { - try - writeln(esv.searchFormat(sFlag)); - catch (ESVException) - die("no results for search"); - catch (CurlException e) - die(e.msg); - return 0; - } - esv.extraParameters = ini["api"].key("parameters", ""); /* Get [passage] keys */ diff --git a/esvsearch.d b/esvsearch.d new file mode 100644 index 0000000..72ffba0 --- /dev/null +++ b/esvsearch.d @@ -0,0 +1,110 @@ +/* + * esvsearch: search the Bible from your terminal + * + * The GPLv2 License (GPLv2) + * Copyright (c) 2023-2024 Jeremy Baxter + * + * esv is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * esv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with esv. If not, see . + */ + +module esvsearch; + +import std.file : FileException; +import std.getopt : getopt, GetOptException; +import std.path : baseName, expandTilde; +import std.process : environment; +import std.stdio : writeln, writefln; + +import esvapi; +import initial; +import util; + +import cf = config; + +@safe: + +string cFlag; /* config path */ +bool VFlag; /* show version */ + +int +main(string[] args) +{ + string apiKey; + string configPath; + INIUnit ini; + ESVApi esv; + + sharedInit(args); + + cFlag = null; + + /* Parse command-line options */ + try { + import std.getopt : config; + getopt(args, + config.bundling, + config.caseSensitive, + "c", &cFlag, + "V", &VFlag, + ); + } catch (GetOptException e) { + handleOptError(e.msg); + } + + if (VFlag) { + writeln("esvsearch " ~ cf.esvVersion); + return 0; + } + + if (args.length < 2) { + stderr.writefln("usage: %s [-l length] query", + baseName(args[0])); + return 1; + } + + /* determine configuration file: options take first priority, + * then environment variables, and then the default path */ + configPath = environment.get(cf.configEnv, cf.configPath) + .expandTilde(); + try { + if (cFlag) + configPath = cFlag.expandTilde(); + + readINIFile(ini, configPath); + } catch (FileException e) { + /* filesystem syscall errors */ + import core.stdc.errno : ENOENT; + + if (e.errno != ENOENT) + die(e.msg); + + warn(configPath ~ ": no such file or directory"); + warn("Invoke esv to create an initial configuration file."); + } + + apiKey = ini["api"].key("key"); + enforceDie(apiKey != null, + "API key not present in configuration file; cannot proceed"); + + esv = new ESVApi(apiKey); + + try + writeln(esv.searchFormat(args[1])); + catch (ESVException) + die("no results"); + catch (CurlException e) + die(e.msg); + + return 0; +}