diff options
author | Joris | 2023-12-27 18:21:37 +0100 |
---|---|---|
committer | Joris | 2023-12-27 18:21:37 +0100 |
commit | 98eca7d594960aa616786cbd491b937d50f55499 (patch) | |
tree | db63132d159d09bed2b0a6454c822c2ed95091c6 /main.py | |
parent | 57da196f828352b009ca86dca98e352cf09663f3 (diff) |
First version with 2 songs
Diffstat (limited to 'main.py')
-rw-r--r-- | main.py | 147 |
1 files changed, 147 insertions, 0 deletions
@@ -0,0 +1,147 @@ +import string + +atom_end = set('()"\'') | set(string.whitespace) + +def parse(sexp): + stack, i, length = [[]], 0, len(sexp) + while i < length: + c = sexp[i] + + reading = type(stack[-1]) + if reading == list: + match c: + case '(': + stack.append([]) + case ')': + stack[-2].append(stack.pop()) + if stack[-1][0] == ('quote',): stack[-2].append(stack.pop()) + case '"': + stack.append('') + case "'": + stack.append([('quote',)]) + case _: + if c in string.whitespace: + pass + else: + stack.append((c,)) + elif reading == str: + if c == '"': + stack[-2].append(stack.pop()) + if stack[-1][0] == ('quote',): stack[-2].append(stack.pop()) + elif c == '\\': + i += 1 + stack[-1] += sexp[i] + else: + stack[-1] += c + elif reading == tuple: + if c in atom_end: + atom = stack.pop() + if atom[0][0].isdigit(): + stack[-1].append(eval(atom[0])) + else: + stack[-1].append(atom) + if stack[-1][0] == ('quote',): + stack[-2].append(stack.pop()) + continue + else: + stack[-1] = ((stack[-1][0] + c),) + i += 1 + return stack.pop() + +def h(node, attributes, *children): + res_attrs = '' + if type(attributes) == dict: + for key in attributes: + res_attrs += f' {key}={attributes[key]}' + else: + children = [attributes] + list(children) + + res = f'<{node} {res_attrs}>' + if type(children) in [tuple, list]: + res += ''.join(children) + elif type(children) == str: + res += children + + res += f'</{node}>' + return res + +def lines(s: str): + return [h('div', x) for x in s.split('\n')] + +def chord_line(sexp): + res = '' + for x in sexp: + res += h('td', { 'class': 'g-Chord' }, x[0]) + return res + +def chords(sexp): + return h('section', + { 'class': 'g-Section' }, + h('h2', { 'class': 'g-Subtitle' }, 'Accords'), + h('table', { 'class': 'g-Chords' }, *[h('tr', {}, chord_line(x)) for x in sexp])) + +part_names = { + 'intro': 'Intro', + 'verse': 'Couplet', + 'chorus': 'Refrain', + 'interlude': 'Interlude' +} + +def lyrics(sexp): + ys = [] + for x in sexp: + match x: + case [(name)]: + ys.append(h('section', + { 'class': 'g-Section' }, + h('div', + { 'class': 'g-Lyrics__Part' }, + h('h3', part_names[name[0]])))) + case [(name), s]: + ys.append(h('section', + { 'class': 'g-Section' }, + h('div', + { 'class': 'g-Lyrics__Part' }, + h('h3', part_names[name[0]]), + h('div', { 'class': 'g-Lyrics__Paragraph' }, *lines(s))))) + return h('section', + { 'class': 'g-Section' }, + h('h2', { 'class': 'g-Subtitle' }, 'Paroles'), + h('div', { 'class': 'g-Lyrics' }, *ys)) + +def sexp_prop(sexp, name): + return [x[1:] for x in sexp if x[0][0] == name][0] + +# ----------------- + +with open('ben-e-king-stand-by-me.lisp', 'r') as f: + content = f.read() + +sexp = parse(content) + +title = sexp_prop(sexp, 'title')[0] +subtitle = sexp_prop(sexp, 'from')[0] + +html = f''' + <!doctype html> + <html lang="fr"> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width"> + <title>{title} – {subtitle}</title> + <link rel="stylesheet" href="main.css"> + <link rel="icon" href="/icon.png"> + <script src="/main.js"></script> +''' + +html += h('body', + h('section', + { 'class': 'g-Section' }, + h('h1', { 'class': 'g-Title' }, title), + h('div', { 'class': 'g-Author' }, subtitle)), + chords(sexp_prop(sexp, 'chords')), + lyrics(sexp_prop(sexp, 'lyrics'))) + +with open('ben-e-king-stand-by-me.html', 'w') as f: + f.write(html) + +print('OK') |