1

I'm looking for a way to create a songbook out of individual song files.

Each song file is a self-contained block of text data consisting of:

  • Song name
  • Song author
  • Some details (optional)
  • Lyrics with chords (to be typeset within a LaTeX environment guitar)

If I was doing this manually I'd put something like this in file song1.tex:

    \section{Song Name}
    \paragraph{Song author}
    \textit{Some details}
    \begin{guitar}
        Lyrics with chrods
    \end{guitar}

And then use \include{song1} in the main.tex. (I have found a way to include all the files automatically using a Lua script)

However, I want the source files to be formatted as minimally as possible (they are meant to be added by non-TeX savvy people).

I was considering storing the songs in plain .txt files, where the line number specifies the fields:

Song Name
Song Author
Song details
Song lyrics...
....

But I'm not 100% how to easily parse this. Also, something like multiline Song details breaks this.

Other ideas included storing it in JSON:

{"name":"Name",
"author":"Author",
"details":"Details",
"lyrics":"Song \n Lyrics"
}

or YAML:

name: Name
author: Author
details: >
  Multi-line
  Details
lyrics: >
  Multiline
  Lyrics

And parse those?

What would be the most natural way to do this in LaTeX? How would you go about this?

4

2 Answers 2

1

Starting with a song file MHALL.txt (Mary Had A Little Lamb), according to the OP's desired format:

Mary Had a Little Lamb
Anonymous
Children's song
^{A}Mary had a little lamb,
^{E}Little lamb, ^{A}little lamb,
^{A}Mary had a little lamb,
Its ^{E}fleece was white as ^{A}snow.

^{A}Everywhere that Mary went,
^{E}Mary went, ^{A}Mary went,
^{A}Everywhere that Mary went
The ^{E}lamb was sure to ^{A}go
 
It ^{A$\sharp$}followed her to school one day
...

and the following short code using readarray, the output may be formatted as an annotated song lyric. I don't know anything about a guitar environment, so I created my own format for "formatting" chords, namely, to top-lap the chord name, using the input syntax ^{<chord name>} as an active input from the input file. Note that chord names like ^{A$\flat$} are perfectly suitable to this input style. Obviously, this part of the formatting can be tailored to the OP's desires.

\documentclass{article}
\usepackage{readarray,forloop,stackengine}
\setstackgap{L}{.9\baselineskip}% VERTICAL CHORD POSITION
\newcounter{songlines}
{\catcode`\^=\active 
  \gdef^#1{\trlap{\fbox{\tiny\sffamily\bfseries#1}}}}% CHORD FORMAT
\newcommand\formatsong[1]{%
  \bgroup
  \catcode`\^=\active 
  \readrecordarray{#1}\songdata
  \section{\songdata[1]}%
  \paragraph{\songdata[2]}%
  \textit{\songdata[3]}%
  \begin{quote}
  \forloop{songlines}{4}{\value{songlines}<\nrecords}{%
    \songdata[\thesonglines]\\
  }%
  \end{quote}
  \egroup
}
\fboxsep=2pt
\begin{document}
\formatsong{MHALL.txt}
\end{document}

enter image description here


SUPPLEMENT

Just to show how the chord format can be adjusted to suit, I grab some routines from my answer at Typesetting guitar chord diagrams in a songbook and to my prior code, I merely enlarge the VERTICAL CHORD POSITION (to allow room for the chord typesetting) and simplify the CHORD FORMAT (removing all extraneous formatting).

Then, using the pulled-in routines to define for the user guitar chords like \Cm (C-minor) and \GM (G-major), I can allow the user to specify these as the chords in the input file:

Mary Had a Little Lamb
Anonymous
Children's song
^{\Cm}Mary had a little lamb,
^{\GM}Little lamb, ^{\Cm}little lamb,
...

Then, with this augmented code,

\documentclass{article}
\usepackage{readarray,forloop,stackengine}
\setstackgap{L}{2.7\baselineskip}% VERTICAL CHORD POSITION
\newcounter{songlines}
{\catcode`\^=\active 
  \gdef^#1{\trlap{#1}}}% CHORD FORMAT
\newcommand\formatsong[1]{%
  \bgroup
  \catcode`\^=\active 
  \readrecordarray{#1}\songdata
  \section{\songdata[1]}%
  \paragraph{\songdata[2]}%
  \textit{\songdata[3]}%
  \begin{quote}
  \forloop{songlines}{4}{\value{songlines}<\nrecords}{%
    \songdata[\thesonglines]\\
  }%
  \end{quote}
  \egroup
}
\fboxsep=2pt
% FOLLOWING PULLED FROM ANSWER AT
% https://tex.stackexchange.com/questions/324828/typesetting-guitar-chord-diagrams-in-a-songbook/324924#324924
\usepackage{musixguit}
\def\chordalign{\dimexpr2.2ex}% 2.2ex sets alignment of chord
\def\chordminwidth{\dimexpr6.5ex}% 6.5ex provides min. hskip for optional argument
\newcommand\guitarchord[2]{%
  \savestack#1{\kern\chordalign\NOtes\guitar #2\en}
}
\newcommand\showchord[2][\relax]{%
  \ifx\relax#1\relax\def\tmpuaw{T}\else\def\tmpuaw{F}\fi%
  \stackengine{\Lstackgap}{#1}{%
    \makebox[0ex][l]{#2}\kern\chordminwidth}{O}{l}{F}{\tmpuaw}{L}%
}
\newcommand\chordline[2]{\setbox0=\hbox{#2}%
  \ifdim\wd0>\chordminwidth\showchord{#1}#2\else\showchord[#2]{#1}\fi%
}
\raiseguitar {0}

\guitarchord\Cm{{Cm $^7$}{2}x-----\gbarre1\gdot33\gdot52}
\guitarchord\GM{G{}o-----\gbarre3\gdot25\gdot35\gdot44}
%
\begin{document}
\formatsong{MHALL.txt}
\end{document}

the result may be more what the OP had in mind:

enter image description here

0

As the basic conceptual idea I'd use 1) simple sources, as you mention, and b) generate those .tex files e.g. by some scripting language (which is a no- or low-brainer for the experienced scripter).

Examples for simple sources

  • pure ASCII, e.g. with a suitable and simple directory structure
  • a database, like MS Access (or mysql or whatever)
  • a web-formular etc.

Scripting e.g. by

  • Perl
  • php (command line)
  • Javascript
  • concatenation by dedicated query in MS Access (or mysql or whatever)

Let me know your preference and I'll try to work out some basic code for you (if I can).

Structures

One file only approach

Use dedicated (own) markup, which your script can easily identify. Example, easy to do in Perl:

#N Blowin' in the wind
#A Bob Dylon
#D This song was ... bla bla
(many lines later
and this is all you should know about it
#I Guitar
#L How man roads
must a man walk down
...

Directory coded

Let's say there are more songs than authors. So a structure could be like this

\Bob Dylan
\Bob Dylan\Blowin in the wind
\Bob Dylan\Blowin in the wind\details.txt
\Bob Dylan\Blowin in the wind\lyrics.txt
\Bob Dylan\Blowin in the wind\instruments.txt

Splitting the PATH at "\" gives you all the nitty gritty details and access.

Database approach

You may want to define fields in a DB, or columns in a spreadsheet like Excel, like so:

author song details instrument lyrics year ...

where details and lyrics allow for long texts, while the others may be shorter. E.g. in MS Access you can alway turn the the table into a form, like so:

TABLE-STRUCTURE

How the data sets could look like: How the data sets could look like

When you start filling it: When you start filling it

FORM

What your people might use for entry What your people might use for entry

BTW ... you'll have the same ingredients and representation when doing this via a web-interface (form) with an underlying database (like mysql).

P.S.: Let me add from a different post here, that using datatool would open up this opportunity for you from a system design point of view:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.