working song translation from lisp

This commit is contained in:
Chris Cochrun 2024-12-05 22:27:37 -06:00
parent f69d465596
commit 8c29e7900a
5 changed files with 123 additions and 47 deletions

4
Cargo.lock generated
View file

@ -1250,8 +1250,8 @@ dependencies = [
[[package]] [[package]]
name = "crisp" name = "crisp"
version = "0.1.0" version = "0.1.1"
source = "git+https://git.tfcconnection.org/chris/crisp#c3abe2fe48dc891322548d4fa900062772486bd3" source = "git+https://git.tfcconnection.org/chris/crisp#fa078e8d3fa9c0916f5da950eee896d4fa67a4eb"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"miette", "miette",

View file

@ -23,5 +23,5 @@ ron = "0.8.1"
sqlx = { version = "0.8.2", features = ["sqlite"] } sqlx = { version = "0.8.2", features = ["sqlite"] }
dirs = "5.0.1" dirs = "5.0.1"
tokio = "1.41.1" tokio = "1.41.1"
crisp = { git = "https://git.tfcconnection.org/chris/crisp" } crisp = { git = "https://git.tfcconnection.org/chris/crisp", version = "0.1.1" }

View file

@ -53,25 +53,31 @@ impl TryFrom<String> for Background {
impl TryFrom<PathBuf> for Background { impl TryFrom<PathBuf> for Background {
type Error = ParseError; type Error = ParseError;
fn try_from(value: PathBuf) -> Result<Self, Self::Error> { fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
if let Ok(value) = value.canonicalize() { match value.canonicalize() {
let extension = value Ok(value) => {
.extension() let extension = value
.unwrap_or_default() .extension()
.to_str() .unwrap_or_default()
.unwrap_or_default(); .to_str()
match extension { .unwrap_or_default();
"jpg" | "png" | "webp" | "html" => Ok(Self { match extension {
path: value, "jpeg" | "jpg" | "png" | "webp" | "html" => {
kind: BackgroundKind::Image, Ok(Self {
}), path: value,
"mp4" | "mkv" | "webm" => Ok(Self { kind: BackgroundKind::Image,
path: value, })
kind: BackgroundKind::Video, }
}), "mp4" | "mkv" | "webm" => Ok(Self {
_ => Err(ParseError::NonBackgroundFile), path: value,
kind: BackgroundKind::Video,
}),
_ => Err(ParseError::NonBackgroundFile),
}
}
Err(e) => {
error!("Couldn't canonicalize: {e}");
Err(ParseError::CannotCanonicalize)
} }
} else {
Err(ParseError::CannotCanonicalize)
} }
} }
} }
@ -80,7 +86,7 @@ impl TryFrom<&str> for Background {
type Error = ParseError; type Error = ParseError;
fn try_from(value: &str) -> Result<Self, Self::Error> { fn try_from(value: &str) -> Result<Self, Self::Error> {
let value = value.trim_start_matches("file://"); let value = value.trim_start_matches("file://");
if value.contains("~") { if value.starts_with("~") {
if let Some(home) = dirs::home_dir() { if let Some(home) = dirs::home_dir() {
if let Some(home) = home.to_str() { if let Some(home) = home.to_str() {
let value = value.replace("~", home); let value = value.replace("~", home);
@ -91,6 +97,8 @@ impl TryFrom<&str> for Background {
} else { } else {
Self::try_from(PathBuf::from(value)) Self::try_from(PathBuf::from(value))
} }
} else if value.starts_with("./") {
Err(ParseError::CannotCanonicalize)
} else { } else {
Self::try_from(PathBuf::from(value)) Self::try_from(PathBuf::from(value))
} }
@ -290,22 +298,49 @@ fn lisp_to_text(lisp: &Value) -> impl Into<String> {
} }
} }
// Need to return a Result here so that we can propogate
// errors and then handle them appropriately
pub fn lisp_to_background(lisp: &Value) -> Background { pub fn lisp_to_background(lisp: &Value) -> Background {
match lisp { match lisp {
Value::List(list) => { Value::List(list) => {
let kind = list[0].clone();
if let Some(source) = list.iter().position(|v| { if let Some(source) = list.iter().position(|v| {
v == &Value::Keyword(Keyword::from("source")) v == &Value::Keyword(Keyword::from("source"))
}) { }) {
let source = &list[source + 1]; let source = &list[source + 1];
match source { match source {
Value::String(s) => { Value::String(s) => {
match Background::try_from(s.as_str()) { if s.starts_with("./") {
Ok(background) => background, let Some(home) = dirs::home_dir() else {
Err(e) => { panic!("Should always be there");
error!( };
"Couldn't load background: {e}" let Some(home) = home.to_str() else {
); panic!("Should always be there");
Background::default() };
let mut home = home.to_string();
home.push_str("/");
let s = s.replace("./", &home);
dbg!(&s);
match Background::try_from(s.as_str()) {
Ok(background) => background,
Err(e) => {
dbg!(&e);
error!(
"Couldn't load background: {e}"
);
Background::default()
}
}
} else {
match Background::try_from(s.as_str()) {
Ok(background) => background,
Err(e) => {
error!(
"Couldn't load background: {e}"
);
Background::default()
}
} }
} }
} }

View file

@ -124,6 +124,7 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
let background = let background =
if let Some(background) = list.get(background_position) { if let Some(background) = list.get(background_position) {
dbg!(&background);
Some(slide::lisp_to_background(background)) Some(slide::lisp_to_background(background))
} else { } else {
None None
@ -156,7 +157,7 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
}; };
let ccli = if let Some(ccli) = list.get(ccli_position) { let ccli = if let Some(ccli) = list.get(ccli_position) {
Some(i32::from(ccli)) Some(i32::from(ccli).to_string())
} else { } else {
None None
}; };
@ -236,14 +237,19 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
let first_text_postiion = if let Some(pos) = let first_text_postiion = if let Some(pos) =
list.iter().position(|v| match v { list.iter().position(|v| match v {
Value::List(inner) => match &inner[0] { Value::List(inner) => {
Value::Symbol(Symbol(text)) => { (match &inner[0] {
text.contains("v1") Value::Symbol(Symbol(text)) => {
|| text.contains("text") text.contains("v1")
|| text.contains("c1") || text.contains("text")
} || text.contains("c1")
_ => false, }
}, _ => false,
} && match &inner[1] {
Value::String(_) => true,
_ => false,
})
}
_ => false, _ => false,
}) { }) {
pos pos
@ -253,11 +259,7 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
let lyric_elements = &list[first_text_postiion..]; let lyric_elements = &list[first_text_postiion..];
let mut lyric_list = if let Some(ref verse_order) = verse_order { let mut lyrics = vec![];
Vec::with_capacity(verse_order.capacity())
} else {
vec![]
};
for element in lyric_elements { for element in lyric_elements {
let Value::List(lyric) = element else { let Value::List(lyric) = element else {
@ -267,9 +269,9 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
continue; continue;
}; };
let lyric = String::from(&lyric[1]); let lyric = format!("{}{}", String::from(&lyric[1]), "\n");
let Some(ref verse_order) = verse_order else { let Some(ref verse_order) = verse_order else {
lyric_list.push(lyric); lyrics.push(lyric);
continue; continue;
}; };
@ -280,10 +282,23 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
continue; continue;
}; };
lyric_list.insert(verse_pos, lyric); lyrics.insert(verse_pos, lyric);
} }
todo!() let lyrics = lyrics.iter().flat_map(|s| s.chars()).collect();
Song {
id: 0,
title,
lyrics: Some(lyrics),
author,
ccli,
verse_order,
background,
font,
font_size,
..Default::default()
}
} }
pub async fn get_song_from_db( pub async fn get_song_from_db(
@ -399,6 +414,8 @@ impl Song {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::fs::read_to_string;
use super::*; use super::*;
use pretty_assertions::{assert_eq, assert_ne}; use pretty_assertions::{assert_eq, assert_ne};
@ -560,4 +577,20 @@ You saved my soul"
font_size: Some(60) font_size: Some(60)
} }
} }
fn test_lisp_song() -> Value {
let lisp = read_to_string("./test_song.lisp").expect("oops");
let lisp_value = crisp::reader::read(&lisp);
match lisp_value {
Value::List(v) => v.get(0).unwrap().clone(),
_ => Value::Nil,
}
}
#[test]
pub fn test_lisp_conversion() {
let value = test_lisp_song();
let song = Song::from(value);
assert!(false, "{:?}", song);
}
} }

8
test_song.lisp Normal file
View file

@ -0,0 +1,8 @@
(song :author "Jordan Feliz" :ccli 97987
:font "Quicksand" :font-size 80
:title "The River"
:background (image :source "~/pics/wallpapers/nixorange.jpeg" :fit cover)
:verse-order (v1 c1 v2 c1)
(v1 "I'm going down to the river")
(c1 "Down to the river")
(v2 "Down to the river to pray ay ay!"))