- Set \parindent to 0pt for clean left-aligned text - Remove current book column from song page footer (keep only reference books: BuLiBu, CL gr., SwA, Barde, LiBock) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
283 lines
8.0 KiB
TeX
283 lines
8.0 KiB
TeX
\NeedsTeXFormat{LaTeX2e}
|
|
\ProvidesPackage{songbook-style}[2026/04/01 Pfadfinder Carmina Leonis Style]
|
|
|
|
% --- Core packages ---
|
|
\RequirePackage{fontspec}
|
|
\RequirePackage[ngerman]{babel}
|
|
\RequirePackage[
|
|
a5paper,
|
|
top=15mm,
|
|
bottom=20mm,
|
|
inner=20mm,
|
|
outer=12mm
|
|
]{geometry}
|
|
\RequirePackage[hidelinks]{hyperref}
|
|
\RequirePackage{fancyhdr}
|
|
\RequirePackage{xcolor}
|
|
\RequirePackage{longtable}
|
|
\RequirePackage{array}
|
|
\RequirePackage{colortbl}
|
|
\RequirePackage{rotating}
|
|
\RequirePackage{graphicx}
|
|
\RequirePackage{csquotes}
|
|
\RequirePackage[minimal]{leadsheets}
|
|
\ExplSyntaxOn
|
|
\cs_new:cpn {leadsheets-library-musicsymbols-loaded} {}
|
|
\ExplSyntaxOff
|
|
\useleadsheetslibraries{chordnames,chords,shorthands,properties,templates,translations,songs}
|
|
|
|
% --- Repeat markers (used by shorthands library for |: and :| ) ---
|
|
\providecommand{\leftrepeat}{|:\,}
|
|
\providecommand{\rightrepeat}{\,:|}
|
|
\providecommand{\leftrightrepeat}{|:\,:|}
|
|
|
|
|
|
% --- Font setup ---
|
|
\setmainfont{TeX Gyre Heros}
|
|
\newfontfamily\frakfont{UnifrakturMaguntia-Book}[Path=fonts/,Extension=.ttf]
|
|
|
|
% --- Colors ---
|
|
\definecolor{tocrowgray}{gray}{0.92}
|
|
\definecolor{tocheadgray}{gray}{0.75}
|
|
|
|
% --- Page style ---
|
|
\pagestyle{fancy}
|
|
\fancyhf{}
|
|
\fancyfoot[LE]{\large\bfseries\thepage}
|
|
\fancyfoot[RO]{\large\bfseries\thepage}
|
|
\renewcommand{\headrulewidth}{0pt}
|
|
\renewcommand{\footrulewidth}{0pt}
|
|
|
|
% --- Custom song properties ---
|
|
\definesongproperty{alias}
|
|
\definesongproperty{note}
|
|
\definesongproperty{mundorgel}
|
|
\definesongproperty{pfadfinderliederbuch}
|
|
\definesongproperty{bulibu}
|
|
\definesongproperty{bulibull}
|
|
\definesongproperty{cl}
|
|
\definesongproperty{swa}
|
|
\definesongproperty{barde}
|
|
\definesongproperty{libock}
|
|
|
|
% --- leadsheets settings ---
|
|
\setleadsheets{
|
|
title-template = songbook,
|
|
verse/numbered = false,
|
|
verse/named = false,
|
|
chorus/named = false,
|
|
chorus/numbered = false,
|
|
after-song = \songendsection,
|
|
bar-shortcuts = false,
|
|
}
|
|
|
|
% --- No paragraph indentation (matches reference style) ---
|
|
\setlength{\parindent}{0pt}
|
|
|
|
\setchords{
|
|
format = \small,
|
|
}
|
|
|
|
% ==========================================================================
|
|
% Song TOC matrix
|
|
% ==========================================================================
|
|
|
|
\newcounter{songnumber}
|
|
\newcounter{tocrowcount}
|
|
|
|
\ExplSyntaxOn
|
|
\iow_new:N \g__sb_toc_iow
|
|
\tl_new:N \l__sb_title_tl
|
|
\tl_new:N \l__sb_bulibu_tl
|
|
\tl_new:N \l__sb_cl_tl
|
|
\tl_new:N \l__sb_swa_tl
|
|
\tl_new:N \l__sb_barde_tl
|
|
\tl_new:N \l__sb_libock_tl
|
|
\tl_new:N \l__sb_num_tl
|
|
\tl_new:N \l__sb_songid_tl
|
|
\bool_new:N \g__sb_toc_opened_bool
|
|
\seq_new:N \g__sb_written_seq
|
|
|
|
% Lazy-open: only truncate the file when first song writes to it
|
|
% This ensures the TOC reads the PREVIOUS run's data before truncation
|
|
\cs_new_protected:Npn \__sb_ensure_toc_open:
|
|
{
|
|
\bool_if:NF \g__sb_toc_opened_bool
|
|
{
|
|
\iow_open:Nn \g__sb_toc_iow { \c_sys_jobname_str .songtoc }
|
|
\bool_gset_true:N \g__sb_toc_opened_bool
|
|
}
|
|
}
|
|
|
|
\AtEndDocument{
|
|
\bool_if:NT \g__sb_toc_opened_bool
|
|
{ \iow_close:N \g__sb_toc_iow }
|
|
}
|
|
|
|
\cs_new_protected:Npn \writesongtoc
|
|
{
|
|
% Use leadsheets song ID to skip duplicate calls (measurement pass)
|
|
\tl_set:NV \l__sb_songid_tl \l_leadsheets_current_song_id_tl
|
|
\seq_if_in:NVF \g__sb_written_seq \l__sb_songid_tl
|
|
{
|
|
\seq_gput_right:NV \g__sb_written_seq \l__sb_songid_tl
|
|
\__sb_ensure_toc_open:
|
|
\stepcounter{songnumber}
|
|
\tl_set:Nx \l__sb_num_tl { \int_use:N \c@songnumber }
|
|
\tl_set:Nx \l__sb_title_tl { \songproperty{title} }
|
|
\tl_set:Nx \l__sb_bulibu_tl { \songproperty{bulibu} }
|
|
\tl_set:Nx \l__sb_cl_tl { \songproperty{cl} }
|
|
\tl_set:Nx \l__sb_swa_tl { \songproperty{swa} }
|
|
\tl_set:Nx \l__sb_barde_tl { \songproperty{barde} }
|
|
\tl_set:Nx \l__sb_libock_tl { \songproperty{libock} }
|
|
\iow_now:Nx \g__sb_toc_iow
|
|
{
|
|
\exp_not:N \songtocrow
|
|
{ \l__sb_title_tl }
|
|
{ \l__sb_bulibu_tl }
|
|
{ \l__sb_cl_tl }
|
|
{ \l__sb_swa_tl }
|
|
{ \l__sb_barde_tl }
|
|
{ \l__sb_libock_tl }
|
|
{ \exp_not:N \pageref { song: \l__sb_num_tl } }
|
|
}
|
|
}
|
|
% Label MUST be outside guard: measurement pass label is discarded (inside vbox),
|
|
% but the real pass label survives and gets written to .aux
|
|
\tl_set:Nx \l__sb_num_tl { \int_use:N \c@songnumber }
|
|
\label{song:\tl_use:N \l__sb_num_tl}
|
|
}
|
|
\ExplSyntaxOff
|
|
|
|
% --- Render one TOC row ---
|
|
% #1=title #2=BuLiBu #3=CL #4=SwA #5=Barde #6=LiBock #7=page
|
|
\newcommand{\songtocrow}[7]{%
|
|
#1 & #2 & #3 & #4 & #5 & #6 & \cellcolor{tocheadgray}\textbf{#7} \\
|
|
\hline
|
|
}
|
|
|
|
% --- Rotated column header ---
|
|
\newcommand{\rotheader}[1]{%
|
|
\begin{turn}{70}\footnotesize\textbf{#1}\end{turn}%
|
|
}
|
|
|
|
% --- Print the song TOC table ---
|
|
\newcommand{\printsongtoc}{%
|
|
\thispagestyle{fancy}%
|
|
{\Large\bfseries Inhaltsverzeichnis\par}%
|
|
\vspace{5mm}%
|
|
\footnotesize
|
|
\rowcolors{2}{tocrowgray}{white}%
|
|
\begin{longtable}{%
|
|
>{\raggedright\arraybackslash}p{0.36\textwidth}|%
|
|
>{\centering\arraybackslash}p{0.07\textwidth}|%
|
|
>{\centering\arraybackslash}p{0.07\textwidth}|%
|
|
>{\centering\arraybackslash}p{0.07\textwidth}|%
|
|
>{\centering\arraybackslash}p{0.07\textwidth}|%
|
|
>{\centering\arraybackslash}p{0.07\textwidth}|%
|
|
>{\centering\arraybackslash\columncolor{tocheadgray}}p{0.09\textwidth}%
|
|
}
|
|
& \rotheader{BuLiBu}
|
|
& \rotheader{CL (gr.)}
|
|
& \rotheader{SwA}
|
|
& \rotheader{Barde}
|
|
& \rotheader{LiBock}
|
|
& \rotheader{\normalsize Carmina\newline\normalsize Leonis} \\
|
|
\hline
|
|
\endfirsthead
|
|
& \rotheader{BuLiBu}
|
|
& \rotheader{CL (gr.)}
|
|
& \rotheader{SwA}
|
|
& \rotheader{Barde}
|
|
& \rotheader{LiBock}
|
|
& \rotheader{\normalsize Carmina\newline\normalsize Leonis} \\
|
|
\hline
|
|
\endhead
|
|
\InputIfFileExists{\jobname.songtoc}{}{}%
|
|
\end{longtable}%
|
|
\rowcolors{1}{}{}%
|
|
}
|
|
|
|
% ==========================================================================
|
|
% Song end section
|
|
% ==========================================================================
|
|
|
|
\newcommand{\songendsection}{%
|
|
\vfill
|
|
\ifsongproperty{note}{%
|
|
{\footnotesize\songproperty{note}\par\smallskip}%
|
|
}{}%
|
|
\begingroup\footnotesize
|
|
\ifsongproperty{lyrics}{%
|
|
\ifsongproperty{composer}{%
|
|
Worte: \songproperty{lyrics}\par
|
|
Weise: \songproperty{composer}\par
|
|
}{%
|
|
Worte und Weise: \songproperty{lyrics}\par
|
|
}%
|
|
}{%
|
|
\ifsongproperty{composer}{%
|
|
Weise: \songproperty{composer}\par
|
|
}{}%
|
|
}%
|
|
\endgroup
|
|
\vspace{3mm}%
|
|
\begingroup\footnotesize\centering
|
|
\begin{tabular}{ccccc}
|
|
BuLiBu & CL (gr.) & SwA & Barde & LiBock \\
|
|
\ifsongproperty{bulibu}{\songproperty{bulibu}}{} &
|
|
\ifsongproperty{cl}{\songproperty{cl}}{} &
|
|
\ifsongproperty{swa}{\songproperty{swa}}{} &
|
|
\ifsongproperty{barde}{\songproperty{barde}}{} &
|
|
\ifsongproperty{libock}{\songproperty{libock}}{}
|
|
\end{tabular}\par
|
|
\endgroup
|
|
\newpage
|
|
}
|
|
|
|
% ==========================================================================
|
|
% Song title template
|
|
% ==========================================================================
|
|
|
|
\definesongtitletemplate{songbook}{%
|
|
{\LARGE\frakfont\songproperty{title}\par}%
|
|
\writesongtoc
|
|
\vspace{4mm}%
|
|
}
|
|
|
|
% ==========================================================================
|
|
% Image placement
|
|
% ==========================================================================
|
|
|
|
% Full-page filler image (centered, scaled to fit, own page)
|
|
% Usage: \fillerpage{images/drawing.png}
|
|
\newcommand{\fillerpage}[1]{%
|
|
\clearpage
|
|
\thispagestyle{empty}%
|
|
\vspace*{\fill}%
|
|
\begin{center}%
|
|
\includegraphics[width=0.85\textwidth,height=0.85\textheight,keepaspectratio]{#1}%
|
|
\end{center}%
|
|
\vspace*{\fill}%
|
|
\clearpage
|
|
}
|
|
|
|
% Inline image within a page (e.g., at end of a song with remaining space)
|
|
% Usage: \songimage{images/landscape.png}
|
|
\newcommand{\songimage}[1]{%
|
|
\begin{center}%
|
|
\includegraphics[width=0.8\textwidth,keepaspectratio]{#1}%
|
|
\end{center}%
|
|
}
|
|
|
|
% Full-page image with no margins (bleeds to edges)
|
|
% Usage: \fullpageimage{images/cover.png}
|
|
\newcommand{\fullpageimage}[1]{%
|
|
\clearpage
|
|
\thispagestyle{empty}%
|
|
\newgeometry{margin=0pt}%
|
|
\noindent\includegraphics[width=\paperwidth,height=\paperheight]{#1}%
|
|
\restoregeometry
|
|
\clearpage
|
|
}
|