This commit is contained in:
Rushmore75 2025-03-25 13:32:44 -06:00
commit abda6bab95
8 changed files with 350 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "HebrewLexicon"]
path = HebrewLexicon
url = https://github.com/openscriptures/HebrewLexicon.git

89
Cargo.lock generated Normal file
View File

@ -0,0 +1,89 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bible"
version = "0.1.0"
dependencies = [
"inline_colorization",
"quick-xml",
"serde",
]
[[package]]
name = "inline_colorization"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1804bdb6a9784758b200007273a8b84e2b0b0b97a8f1e18e763eceb3e9f98a"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.37.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "bible"
version = "0.1.0"
edition = "2024"
[dependencies]
inline_colorization = "0.1.6"
quick-xml = { version="0.37.2", features=["serialize"] }
serde = { version = "1.0.219", features = ["derive"] }

1
HebrewLexicon Submodule

@ -0,0 +1 @@
Subproject commit 21c9add13bc727d3a951361778e97e3ff7afd1ce

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# cli bible
## Important Links
[Tanach.us](https://tanach.us)
[HewbrewLexicon](https://github.com/openscriptures/HebrewLexicon/tree/master)

39
src/main.rs Normal file
View File

@ -0,0 +1,39 @@
use inline_colorization::*;
use std::{env, io::{self, Write}};
mod strong;
fn main() {
let arg = env::args().collect::<Vec<String>>();
if let Some(query) = arg.get(1) {
if query.starts_with("H") | query.starts_with("h") {
if let Some(found) = strong::get(query) {
print!("{found}");
return;
}
}
}
// No input args, go into interactive mode
let stdin = io::stdin();
let mut stdout = io::stdout();
loop {
print!("{color_bright_white}{style_bold}Search>{style_reset} ");
let _ = stdout.flush();
let mut buf = String::new();
stdin.read_line(&mut buf).unwrap();
let search = buf.trim().to_string();
if search.starts_with("H") {
if let Some(entry) = strong::get(&search) {
println!("");
print!("{}", entry);
println!("");
}
} else {
println!("Not sure what you're looking for...");
}
}
}

200
src/strong.rs Normal file
View File

@ -0,0 +1,200 @@
use std::{fmt::Display, fs::read_to_string};
use inline_colorization::*;
use quick_xml::de::from_str;
use serde::Deserialize;
pub fn get(query: &str) -> Option<Entry> {
// TODO Put this in a singleton
let file = read_to_string("./HebrewLexicon/HebrewStrong.xml").unwrap();
let obj: HebrewStrong = from_str(&file).unwrap();
// Yes, dumb search is ok. Searching for the last element took 2ms
obj.entries.into_iter().find(|entry| entry.number.eq(&query))
}
#[derive(Deserialize)]
pub struct HebrewStrong {
#[serde(rename = "$value")]
pub entries: Vec<Entry>,
}
#[derive(Deserialize, Debug)]
pub struct Entry {
#[serde(rename = "@id")]
pub number: String,
w: Word,
// TODO find who has multiple notes
note: Option<Vec<Note>>,
source: Option<Source>,
meaning: Option<Meaning>,
usage: Option<Usage>,
}
impl Display for Entry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{color_red}Strong's ID{style_reset}: {}", self.number)?;
if let Some(notes) = &self.note {
write!(f, "Notes:")?;
for note in notes {
writeln!(f, "{}", note)?;
}
}
write!(f, "{}", self.w)?;
if let Some(i) = &self.source {
writeln!(f, "{}", i)?;
}
if let Some(i) = &self.meaning {
writeln!(f, "{}", i)?;
}
if let Some(i) = &self.usage {
writeln!(f, "{}", i)?;
}
Ok(())
}
}
#[derive(Deserialize, Debug)]
struct Word {
#[serde(rename = "@pos")]
// TODO this is actaully a link to PartsOfSpeech.xml
part_of_speech: Option<String>,
#[serde(rename = "@pron")]
pronunciation: Option<String>,
#[serde(rename = "@xlit")]
transliteration: Option<String>,
#[serde(rename = "@xlm:lang")]
lang: Option<String>,
#[serde(rename = "$value")]
inner: String,
#[serde(rename = "@src")]
links_to: Option<String>,
}
impl Display for Word {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(part_of_speech) = &self.part_of_speech {
writeln!(f, "{color_magenta}Part of speech{style_reset}: {}", part_of_speech)?;
}
if let Some(i) = &self.transliteration {
writeln!(f, "{color_green}Transliteration{style_reset}: {}", i)?;
}
if let Some(i) = &self.lang {
writeln!(f, "{color_red}Language{style_reset}: {}", i)?;
}
writeln!(f, "{color_bright_cyan}Writen{style_reset}: {}", self.inner)?;
if let Some(pron) = &self.pronunciation {
writeln!(f, "{color_yellow}Pronounciation{style_reset}: {}", pron)?;
}
if let Some(i) = &self.links_to {
writeln!(f, "{color_bright_green}Also see{style_reset}: {}", i)?;
}
Ok(())
}
}
#[derive(Deserialize, Debug)]
struct Note {
#[serde(rename = "$value")]
inner: String,
}
impl Display for Note {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner)
}
}
#[derive(Deserialize, Debug)]
struct Source {
#[serde(rename = "$value")]
// Text vs Words make this a vec
inner: Option<Vec<MixedText>>,
}
impl Display for Source {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(inner) = &self.inner {
// WE ARE LOOPING
// !! Don't use writeln
write!(f, "{color_bright_green}Source{style_reset}: ")?;
for i in inner {
match i {
MixedText::Word(word) => {
if let Some(i) = &word.links_to {
write!(f, "{style_bold} (See: {}){style_reset}", i)?;
}
write!(f, "{color_bright_white} {} {style_reset}", word.inner)?;
},
_ => write!(f, "{}", i)?,
}
}
}
Ok(())
}
}
#[derive(Deserialize, Debug)]
struct Meaning {
#[serde(rename = "$value")]
inner: Vec<MixedText>,
}
impl Display for Meaning {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{color_cyan}Meaning:{style_reset}")?;
for i in &self.inner {
write!(f, "{}", i)?;
}
Ok(())
}
}
#[derive(Deserialize, Debug)]
struct Usage {
#[serde(rename = "$value")]
inner: Vec<String>,
}
impl Display for Usage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let new = self.inner.join(" ");
write!(f, "{color_bright_magenta}Usage{style_reset}: {new}")
}
}
#[derive(Deserialize, Debug)]
enum MixedText {
#[serde(rename = "w")]
Word(Word),
#[serde(rename = "$text")]
Text(String),
#[serde(rename = "def")]
/// The actual definition, as opposed to the supporting `MixedText::Text`, which is just
/// supporting text elements.
Definition(String),
#[serde(rename = "note")]
Note(Note),
}
impl Display for MixedText {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MixedText::Word(word) => write!(f, "{}", word),
MixedText::Text(text) => write!(f, "{}", text),
MixedText::Definition(def) => write!(f, " {style_bold}{}{style_reset} ", def),
MixedText::Note(note) => write!(f, "{}", note),
}
}
}