Compare commits
10 commits
0fe81de6c2
...
1136fa01bb
Author | SHA1 | Date | |
---|---|---|---|
1136fa01bb | |||
0b2133bae2 | |||
5c366d64b0 | |||
bc342d0415 | |||
67171b71dc | |||
4564b88e42 | |||
3d483fd0f4 | |||
94a954d634 | |||
e8da3e35cf | |||
d7201d9f9a |
7 changed files with 92 additions and 61 deletions
2
README
2
README
|
@ -1,4 +1,4 @@
|
||||||
This is esv, a program that displays Bible passages on the terminal.
|
This is esv 0.3.0, a program that displays Bible passages on the terminal.
|
||||||
|
|
||||||
To build, first install the LDC compiler and libcurl.
|
To build, first install the LDC compiler and libcurl.
|
||||||
Configure the build environment, compile and optionally install:
|
Configure the build environment, compile and optionally install:
|
||||||
|
|
|
@ -2,7 +2,7 @@ module config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum esvVersion = "0.2.0-dev";
|
enum esvVersion = "0.3.0";
|
||||||
|
|
||||||
enum apiKey = "abfb7456fa52ec4292c79e435890cfa3df14dc2b";
|
enum apiKey = "abfb7456fa52ec4292c79e435890cfa3df14dc2b";
|
||||||
enum configPath = "~/.config/esv.conf";
|
enum configPath = "~/.config/esv.conf";
|
||||||
|
|
51
esv.1
51
esv.1
|
@ -1,4 +1,4 @@
|
||||||
.Dd $Mdocdate: June 26 2024 $
|
.Dd $Mdocdate: May 01 2025 $
|
||||||
.Dt ESV 1
|
.Dt ESV 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -15,8 +15,7 @@
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
displays Bible passages on your terminal.
|
displays Bible passages on your terminal.
|
||||||
It can also play recorded audio tracks of certain passages,
|
It can also play audio passages.
|
||||||
through integration with an MP3 player utility.
|
|
||||||
.Pp
|
.Pp
|
||||||
See the section
|
See the section
|
||||||
.Sx EXAMPLES
|
.Sx EXAMPLES
|
||||||
|
@ -27,29 +26,28 @@ Verses can be provided in the format of
|
||||||
.Em chapter:verse ,
|
.Em chapter:verse ,
|
||||||
and
|
and
|
||||||
.Em chapter:verse-verse .
|
.Em chapter:verse-verse .
|
||||||
If the name of your desired book has a space in it, e.g.
|
If the name of your desired book has spaces in it, e.g.
|
||||||
.Dq "1 Corinthians" ,
|
.Dq "1 Corinthians" ,
|
||||||
you can put a hyphen or underscore in the place of the space,
|
you can provide the book name with hyphens or underscores in place of
|
||||||
or you can just pass the full book name with the space in it
|
the spaces, or you can pass the original book name.
|
||||||
by surrounding the argument with quotes in your shell.
|
|
||||||
Thus, both
|
Thus, both
|
||||||
.Dq 1-Corinthians
|
.Dq 1-Corinthians
|
||||||
and
|
and
|
||||||
.Dq "1 Corinthians"
|
.Dq 1_Corinthians
|
||||||
are valid book names.
|
are also valid book names.
|
||||||
.Pp
|
.Pp
|
||||||
By default,
|
By default,
|
||||||
.Xr mpg123 1
|
.Xr mpg123 1
|
||||||
is used as the MP3 player.
|
is used as the player for audio passages.
|
||||||
However, this can be overridden;
|
This can be overridden however;
|
||||||
see the
|
see the
|
||||||
.Sx ENVIRONMENT
|
.Sx ENVIRONMENT
|
||||||
section for more information on this.
|
section for more information.
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width 123456
|
.Bl -tag -width 123456
|
||||||
.It Fl a
|
.It Fl a
|
||||||
Play a recorded audio track rather than showing a passage.
|
Play an audio passage instead of printing a text passage.
|
||||||
.It Fl c Ar config
|
.It Fl c Ar config
|
||||||
Read the configuration from the path
|
Read the configuration from the path
|
||||||
.Ar config .
|
.Ar config .
|
||||||
|
@ -114,7 +112,8 @@ Where to read the configuration file,
|
||||||
rather than using the default location (see section
|
rather than using the default location (see section
|
||||||
.Sx FILES ) .
|
.Sx FILES ) .
|
||||||
.It Ev ESV_PLAYER
|
.It Ev ESV_PLAYER
|
||||||
The name of the MP3 player to use for playing audio passages.
|
The name of the audio player to use when playing audio passages.
|
||||||
|
The program specified must support playing MP3 audio.
|
||||||
If this is not set,
|
If this is not set,
|
||||||
.Nm
|
.Nm
|
||||||
will look for
|
will look for
|
||||||
|
@ -133,22 +132,20 @@ Read John 1:29-31:
|
||||||
.Pp
|
.Pp
|
||||||
Listen to a recorded audio track of Psalm 128:
|
Listen to a recorded audio track of Psalm 128:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl esv -a Psalm 128
|
.Dl esv -a Psalm 139
|
||||||
.Pp
|
|
||||||
Search the Bible for the phrase
|
|
||||||
.Dq "in love" :
|
|
||||||
.Pp
|
|
||||||
.Dl esv -s 'in love'
|
|
||||||
.Pp
|
.Pp
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
.Xr esvsearch 1
|
||||||
.Xr esv.conf 5
|
.Xr esv.conf 5
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An Jeremy Baxter Aq Mt jeremy@baxters.nz
|
.An Jeremy Baxter Aq Mt jeremy@reformers.dev
|
||||||
|
.Pp
|
||||||
|
Part of the
|
||||||
|
.Sy esv
|
||||||
|
distribution found at
|
||||||
|
.Lk https://reformers.dev/esv
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
Currently there are no known bugs in
|
Currently there are no known bugs in
|
||||||
.Nm ;
|
.Nm .
|
||||||
but if you think you've found a potential bug,
|
If you think you've found a potential bug,
|
||||||
please report it to me using my email address above.
|
please report it to my email address above.
|
||||||
.Pp
|
|
||||||
Existing bugs and planned features can be found on the bug tracker:
|
|
||||||
.Lk https://todo.sr.ht/~jeremy/esv
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.Dd $Mdocdate: March 23 2023 $
|
.Dd $Mdocdate: May 01 2025 $
|
||||||
.Dt ESV.CONF 5
|
.Dt ESV.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -15,9 +15,12 @@ An example is listed below:
|
||||||
.Dl [section]
|
.Dl [section]
|
||||||
.Dl key = value
|
.Dl key = value
|
||||||
.Pp
|
.Pp
|
||||||
Comments can be used by putting a hashtag
|
A line beginning with a hashtag
|
||||||
.Dq #
|
.Dq #
|
||||||
symbol at the beginning of a line.
|
will be considered a
|
||||||
|
.Dq comment
|
||||||
|
and will be ignored by
|
||||||
|
.Xr esv 1 .
|
||||||
.Pp
|
.Pp
|
||||||
The available configuration options are as follows:
|
The available configuration options are as follows:
|
||||||
.Bl -tag -width keyword
|
.Bl -tag -width keyword
|
||||||
|
|
23
esvapi.d
23
esvapi.d
|
@ -114,7 +114,7 @@ immutable string[] bibleBooks = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/++ All allowed API parameters (for text passages). +/
|
/++ All allowed API parameters (for text passages). +/
|
||||||
immutable string[] ESVAPI_PARAMETERS = [
|
immutable string[] esvapiParameters = [
|
||||||
"include-passage-references",
|
"include-passage-references",
|
||||||
"include-verse-numbers",
|
"include-verse-numbers",
|
||||||
"include-first-verse-numbers",
|
"include-first-verse-numbers",
|
||||||
|
@ -178,6 +178,12 @@ verseValid(in char[] verse)
|
||||||
assert(verseValid("15:12-17"));
|
assert(verseValid("15:12-17"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
defaultSearchFmt(string reference, string content) pure
|
||||||
|
{
|
||||||
|
return format!"\033[1m%s\033[0m\n %s\n"(reference, content.wrap(80));
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
+ Structure containing the authentication key, API URL,
|
+ Structure containing the authentication key, API URL,
|
||||||
+ any parameters to use when making a request as well as the
|
+ any parameters to use when making a request as well as the
|
||||||
|
@ -319,11 +325,12 @@ struct ESVApi
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
+ Calls search() and formats the results nicely as plain text.
|
+ Calls search() and formats the results nicely as plain text,
|
||||||
|
+ unless a custom function is provided.
|
||||||
+/
|
+/
|
||||||
string
|
string
|
||||||
searchFormat(alias fmt = "\033[1m%s\033[0m\n %s\n")
|
searchFormat(in string query,
|
||||||
(in string query, int lineLength = 0) /* 0 means default */
|
string function(string, string) fmt = &defaultSearchFmt)
|
||||||
{
|
{
|
||||||
char[] layout;
|
char[] layout;
|
||||||
JSONValue resp;
|
JSONValue resp;
|
||||||
|
@ -334,15 +341,9 @@ struct ESVApi
|
||||||
enforce!ESVException(resp["total"].integer != 0,
|
enforce!ESVException(resp["total"].integer != 0,
|
||||||
"No results for search");
|
"No results for search");
|
||||||
|
|
||||||
lineLength = lineLength == 0 ? 80 : lineLength;
|
|
||||||
|
|
||||||
() @trusted {
|
() @trusted {
|
||||||
foreach (JSONValue item; resp["results"].array) {
|
foreach (JSONValue item; resp["results"].array) {
|
||||||
layout ~= format!fmt(
|
layout ~= fmt(item["reference"].str, item["content"].str);
|
||||||
item["reference"].str,
|
|
||||||
item["content"].str
|
|
||||||
.wrap(lineLength)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
37
esvsearch.1
37
esvsearch.1
|
@ -1,4 +1,4 @@
|
||||||
.Dd $Mdocdate: June 26 2024 $
|
.Dd $Mdocdate: May 01 2025 $
|
||||||
.Dt ESVSEARCH 1
|
.Dt ESVSEARCH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm esvsearch
|
.Nm esvsearch
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl V
|
.Op Fl emV
|
||||||
.Op Fl c Ar config
|
.Op Fl c Ar config
|
||||||
.Ar query
|
.Ar query
|
||||||
.Ek
|
.Ek
|
||||||
|
@ -41,7 +41,16 @@ See the documentation on
|
||||||
in
|
in
|
||||||
.Xr esv 1
|
.Xr esv 1
|
||||||
for more information.
|
for more information.
|
||||||
.Sx ENVIRONMENT ) .
|
.It Fl e
|
||||||
|
Instead of showing loose matches for
|
||||||
|
.Ar query ,
|
||||||
|
only show exact matches.
|
||||||
|
.It Fl m
|
||||||
|
Print matches in a machine-readable format,
|
||||||
|
where each result takes up just one line.
|
||||||
|
Any spaces in the book name are replaced with underscores
|
||||||
|
and a slash character separates the passage reference
|
||||||
|
from the passage content.
|
||||||
.It Fl V
|
.It Fl V
|
||||||
Print the version number and exit.
|
Print the version number and exit.
|
||||||
.El
|
.El
|
||||||
|
@ -55,18 +64,14 @@ Search the Bible for verses containing
|
||||||
.Xr esv 1 ,
|
.Xr esv 1 ,
|
||||||
.Xr esv.conf 5
|
.Xr esv.conf 5
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An Jeremy Baxter Aq Mt jeremy@baxters.nz
|
.An Jeremy Baxter Aq Mt jeremy@reformers.dev
|
||||||
|
.Pp
|
||||||
|
Part of the
|
||||||
|
.Sy esv
|
||||||
|
distribution found at
|
||||||
|
.Lk https://reformers.dev/esv
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
.Nm
|
Currently there are no known bugs in
|
||||||
outputs search results in a human-readable manner,
|
.Nm .
|
||||||
which makes it nice for humans to read but difficult
|
|
||||||
for machines to parse and store.
|
|
||||||
.Nm
|
|
||||||
should support outputting results in a shell-readable format
|
|
||||||
and the JSON format.
|
|
||||||
.Pp
|
|
||||||
If you think you've found a potential bug,
|
If you think you've found a potential bug,
|
||||||
please report it to me using my email address above.
|
please report it to my email address above.
|
||||||
.Pp
|
|
||||||
Existing bugs and planned features can be found on the bug tracker:
|
|
||||||
.Lk https://todo.sr.ht/~jeremy/esv
|
|
||||||
|
|
29
esvsearch.d
29
esvsearch.d
|
@ -24,7 +24,9 @@ import std.file : FileException;
|
||||||
import std.getopt : getopt, GetOptException;
|
import std.getopt : getopt, GetOptException;
|
||||||
import std.path : baseName, expandTilde;
|
import std.path : baseName, expandTilde;
|
||||||
import std.process : environment;
|
import std.process : environment;
|
||||||
|
import std.regex : regex, matchAll, replaceFirst;
|
||||||
import std.stdio : writeln, writefln;
|
import std.stdio : writeln, writefln;
|
||||||
|
import std.string : tr;
|
||||||
|
|
||||||
import esvapi;
|
import esvapi;
|
||||||
import initial;
|
import initial;
|
||||||
|
@ -36,8 +38,28 @@ import cf = config;
|
||||||
|
|
||||||
string cFlag; /* config path */
|
string cFlag; /* config path */
|
||||||
bool eFlag; /* exact matches */
|
bool eFlag; /* exact matches */
|
||||||
|
bool mFlag; /* machine readable */
|
||||||
bool VFlag; /* show version */
|
bool VFlag; /* show version */
|
||||||
|
|
||||||
|
string
|
||||||
|
machineReadableFmt(string reference, string content)
|
||||||
|
{
|
||||||
|
/* match the start of the reference against bibleBooks
|
||||||
|
* to identify what book it's from, so we can replace
|
||||||
|
* spaces in the book name with underscores :-) */
|
||||||
|
foreach (string book; bibleBooks) {
|
||||||
|
auto match = reference.matchAll(regex("^(" ~ book ~ ") \\d"));
|
||||||
|
if (!match.empty) {
|
||||||
|
assert(match.captures[1] == book
|
||||||
|
&& bookValid(match.captures[1]));
|
||||||
|
reference = reference.replaceFirst(
|
||||||
|
regex('^' ~ book), book.tr(" ", "_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reference ~ " / " ~ content ~ "\n";
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(string[] args)
|
main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -59,6 +81,7 @@ main(string[] args)
|
||||||
config.caseSensitive,
|
config.caseSensitive,
|
||||||
"c", &cFlag,
|
"c", &cFlag,
|
||||||
"e", &eFlag,
|
"e", &eFlag,
|
||||||
|
"m", &mFlag,
|
||||||
"V", &VFlag,
|
"V", &VFlag,
|
||||||
);
|
);
|
||||||
} catch (GetOptException e) {
|
} catch (GetOptException e) {
|
||||||
|
@ -71,7 +94,7 @@ main(string[] args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
stderr.writefln("usage: %s [-e] [-l length] query",
|
stderr.writefln("usage: %s [-emV] [-c config] query",
|
||||||
baseName(args[0]));
|
baseName(args[0]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +133,9 @@ main(string[] args)
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
writeln(esv.searchFormat(query));
|
writeln(mFlag
|
||||||
|
? esv.searchFormat(query, &machineReadableFmt)
|
||||||
|
: esv.searchFormat(query));
|
||||||
catch (ESVException)
|
catch (ESVException)
|
||||||
die("no results");
|
die("no results");
|
||||||
catch (CurlException e)
|
catch (CurlException e)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue