Last active
April 4, 2021 14:41
-
-
Save be1/34dfa8f269f751e47c4903a01bee4c0e to your computer and use it in GitHub Desktop.
Quick (Rust version) LaTeX cd-cover generator from a brasero xml project.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use serde_derive::Deserialize; | |
use structopt::StructOpt; | |
use serde_xml_rs::from_str; | |
use percent_encoding::percent_decode_str; | |
use chrono::Local; | |
#[derive(StructOpt)] | |
struct Cli { | |
/// The path to the file to read | |
#[structopt(parse(from_os_str))] | |
path: std::path::PathBuf, | |
} | |
#[derive(Debug, Deserialize)] | |
struct Audio { | |
uri: String, | |
start: u64, | |
end: u64, | |
title: String, | |
artist: String | |
} | |
#[derive(Debug, Deserialize)] | |
struct Track { | |
audio: Vec<Audio> | |
} | |
#[derive(Debug, Deserialize)] | |
struct Braseroproject { | |
version: String, | |
label: String, | |
track: Track | |
} | |
fn escape(s: String) -> String { | |
let escape = vec![ | |
('\\', "\\textbackslash{}"), | |
('_', "\\_"), | |
('#', "\\#"), | |
('$', "\\$"), | |
('%', "\\%"), | |
('^', "\\^"), | |
('&', "\\&"), | |
('{', "\\{"), | |
('}', "\\}"), | |
('~', "\\~") | |
]; | |
let mut escaped = s; | |
for esc in escape { | |
escaped = escaped.replace(esc.0, esc.1); | |
} | |
return escaped; | |
} | |
fn main() { | |
let args = Cli::from_args(); | |
let content = std::fs::read_to_string(&args.path) | |
.expect("could not read file"); | |
let xml: Braseroproject = from_str(&content).unwrap(); | |
let mut tex_begin = r###"\documentclass{cd-cover}[a4paper,landscape] | |
\usepackage[french]{babel} | |
\usepackage[utf8]{inputenc} | |
\usepackage[T1]{fontenc} | |
\usepackage{sans} | |
"###.to_string(); | |
let label = escape(xml.label); | |
let com = format!("\\newcommand{{\\TITLE}}{{{}}}\n", label); | |
tex_begin += &com; | |
let com = format!("\\newcommand{{\\SUBTITLE}}{{{}}}\n", "Compilation"); | |
tex_begin += &com; | |
let date = Local::now().date().format("%d-%m-%Y"); | |
let com = format!("\\newcommand{{\\DATE}}{{{}}}\n", date); | |
tex_begin += &com; | |
let com = r###" | |
\begin{document} | |
\parindent=0pt\parskip=0pt | |
\begin{bookletsheets} | |
\begin{center} | |
\begin{framebox} | |
{\LARGE \textbf{\TITLE}} | |
\end{framebox} | |
\end{center} | |
\vfill | |
{\large{\textbf\SUBTITLE}}\hfill{\large\DATE} | |
\end{bookletsheets} | |
\begin{backsheet}{\hfil\TITLE\hfil\SUBTITLE\hfil\DATE} | |
\begin{center} | |
\textbf{\TITLE} | |
\end{center} | |
\begin{enumerate} | |
"###; | |
tex_begin += &com; | |
println!("{}", tex_begin); | |
for audio in xml.track.audio { | |
let title = escape(percent_decode_str(&audio.title).decode_utf8().unwrap().to_string()); | |
let artist = escape(percent_decode_str(&audio.artist).decode_utf8().unwrap().to_string()); | |
let duration = (audio.end - audio.start) / 1000000; | |
let sec = duration / 1000; | |
let m = (sec / 60).to_string(); | |
let sec = sec % 60; | |
println!("\\item {} ({}) \\dotfill {}'{:02}", title, artist, m, sec); | |
} | |
println!(r"\end{{enumerate}}"); | |
println!(); | |
println!(r"\end{{backsheet}}"); | |
println!(r"\end{{document}}"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment