Skip to content

Instantly share code, notes, and snippets.

@be1
Last active April 4, 2021 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save be1/34dfa8f269f751e47c4903a01bee4c0e to your computer and use it in GitHub Desktop.
Save be1/34dfa8f269f751e47c4903a01bee4c0e to your computer and use it in GitHub Desktop.
Quick (Rust version) LaTeX cd-cover generator from a brasero xml project.
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