First import in 3 languages versions.

master
Benoît Rouits 2 years ago
parent 8ad4567e71
commit 9b8e91f02e
  1. 27
      README.md
  2. 129
      golang/brasero2tex.go
  3. 66
      python/brasero2tex.py
  4. 1
      rust/.gitignore
  5. 15
      rust/Cargo.toml
  6. 119
      rust/src/main.rs

@ -1,3 +1,28 @@
# brasero2tex
Programme de génération de pochette de CD LaTeX à partir d'un fichier XML de projet `brasero`.
Programme de génération de pochette de CD LaTeX à partir d'un fichier XML de projet `brasero`. La pochette générée se base sur le paquetage `cd-cover` de LaTeX. Ce programme a été écrit en plusieurs langages: `python`, `rust`, `golang`. Les trois versions sont équivalentes.
Pour utiliser la version python:
```
# rien à compiler
```
Pour utiliser la version rust:
```
cargo build --release
```
Pour utiliser la version golang:
```
go build brasero2tex.go
```
Utilisation du programme:
```
brasero2tex projet.brasero > pochette.tex
```
Génération du fichier PDF:
```
pdflatex pochette.tex
```

@ -0,0 +1,129 @@
package main
import (
"os"
"time"
"strings"
"fmt"
"io/ioutil"
"encoding/xml"
"net/url"
)
type Braseroaudio struct {
XMLName xml.Name `xml:"audio"`
Uri string `xml:"uri"`
Start uint64 `xml:"start"`
End uint64 `xml:"end"`
Title string `xml:"title"`
Artist string `xml:"artist"`
}
type Braserotrack struct {
XMLName xml.Name `xml:"track"`
Audio []Braseroaudio `xml:"audio"`
}
type Braseroproject struct {
XMLName xml.Name `xml:"braseroproject"`
Version string `xml:"version"`
Label string `xml:"label"`
Track Braserotrack `xml:"track"`
}
func escape(s string) string {
escape := map[string]string {
"_": "\\_",
"#": "\\#",
"$": "\\$",
"%": "\\%",
"^": "\\^",
"&": "\\&",
"{": "\\{",
"}": "\\}",
"~": "\\~",
}
var escaped = s
escaped = strings.Replace(escaped, "\\", "\\textbackslash", -1)
for k, v := range escape {
escaped = strings.Replace(escaped, k, v, -1)
}
return escaped
}
func main() {
var args = os.Args[1:]
if len(args) != 1 {
fmt.Println("missing brasero project file")
os.Exit(1)
}
content, err := ioutil.ReadFile(args[0])
if (err != nil) {
fmt.Println("error reading brasero project file")
os.Exit(1)
}
var x Braseroproject;
if err := xml.Unmarshal(content, &x); err != nil {
fmt.Println("xml error parsing brasero project")
os.Exit(1)
}
var tex_begin = `\documentclass{cd-cover}[a4paper,landscape]
\usepackage[french]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{sans}
`
var com = fmt.Sprintf("\\newcommand{\\TITLE}{%s}\n", x.Label)
tex_begin += com
com = fmt.Sprintf("\\newcommand{\\SUBTITLE}{%s}\n", "Compilation")
tex_begin += com
var date = time.Now()
com = fmt.Sprintf("\\newcommand{\\DATE}{%02d-%02d-%d}\n", date.Day(), date.Month(), date.Year());
tex_begin += com
com = `
\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
fmt.Println(tex_begin)
for i := 0; i < len(x.Track.Audio); i++ {
audio := x.Track.Audio[i]
title, _ := url.QueryUnescape(audio.Title)
artist, _ := url.QueryUnescape(audio.Artist)
duration := (audio.End - audio.Start) / 1000000
sec := duration / 1000
min := sec / 60
sec = sec % 60
fmt.Printf("\\item %s (%s) \\dotfill %d'%02d\n", escape(title), escape(artist), min, sec)
}
fmt.Println("\\end{enumerate}")
fmt.Println()
fmt.Println("\\end{backsheet}")
fmt.Println("\\end{document}")
}

@ -0,0 +1,66 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, re, datetime, urllib.parse, xml.etree.ElementTree as ET
if len(sys.argv) < 2:
sys.exit('Usage: %s brasero.project.file' % sys.argv[0])
tree = ET.ElementTree(file=sys.argv[1])
root = tree.getroot()
label = next(root.iter("label")).text.replace('&', '\\&')
sub = "Compil Benoît"
today = datetime.date.today()
print("""
\\documentclass{cd-cover}[a4paper,landscape]
\\usepackage[french]{babel}
\\usepackage[utf8]{inputenc}
\\usepackage[T1]{fontenc}
\\usepackage{sans}
\\newcommand{\\TITLE}{""" + label + """}
\\newcommand{\\SUBTITLE}{""" + sub + """}
\\newcommand{\\DATE}{""" + str(today) + """}
\\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}""")
for e in root.iter("audio"):
title = urllib.parse.unquote(next(e.iter("title")).text).replace('&','\\&')
artist = urllib.parse.unquote(next(e.iter("artist")).text).replace('&', '\\&')
duration = int (next(e.iter("end")).text) - int (next(e.iter("start")).text)
duration /= 1000000
sec = duration / 1000
m = str(int(sec / 60))
s = int(sec) % 60
if s < 10:
s = "0" + str(s)
else:
s = str(s)
print ("\\item {} ({}) \\dotfill {}'{}".format(title, artist, m, s))
print("""
\\end{enumerate}
\\end{backsheet}
\\end{document}
""")

1
rust/.gitignore vendored

@ -0,0 +1 @@
/target

@ -0,0 +1,15 @@
[package]
name = "brasero2tex"
version = "0.1.0"
authors = ["Benoît Rouits <brouits@free.fr>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
structopt = "*"
serde = "*"
serde_derive = "*"
serde-xml-rs = "*"
percent-encoding = "*"
chrono = "*"

@ -0,0 +1,119 @@
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}}");
}
Loading…
Cancel
Save