summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-05-20 03:01:36 +0000
committerNorbert Preining <norbert@preining.info>2024-05-20 03:01:36 +0000
commit225d674dde02e0571b74d1fc483d2d4d1084856a (patch)
tree3383b898fc205a5dfed8205c28cc6f337db30e9f /macros
parenta65977b7a0d9973e675e06e3b250663288afe988 (diff)
CTAN sync 202405200301
Diffstat (limited to 'macros')
-rw-r--r--macros/latex/contrib/catppuccinpalette/README.md28
-rw-r--r--macros/latex/contrib/catppuccinpalette/catppuccinpalette.dtx422
-rw-r--r--macros/latex/contrib/catppuccinpalette/catppuccinpalette.ins57
-rw-r--r--macros/latex/contrib/catppuccinpalette/catppuccinpalette.pdfbin0 -> 210724 bytes
-rw-r--r--macros/latex/contrib/spbmark/spbmark.pdfbin91761 -> 91750 bytes
-rw-r--r--macros/latex/contrib/spbmark/spbmark.sty64
-rw-r--r--macros/latex/contrib/spbmark/spbmark.tex41
-rw-r--r--macros/luatex/latex/semesterplannerlua/README.md43
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua.dtx885
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua.ins59
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua.pdfbin0 -> 144336 bytes
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua_calendar.lua132
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua_dmenu.lua156
-rw-r--r--macros/luatex/latex/semesterplannerlua/semesterplannerlua_timetable.lua233
14 files changed, 2087 insertions, 33 deletions
diff --git a/macros/latex/contrib/catppuccinpalette/README.md b/macros/latex/contrib/catppuccinpalette/README.md
new file mode 100644
index 0000000000..1cb1507f22
--- /dev/null
+++ b/macros/latex/contrib/catppuccinpalette/README.md
@@ -0,0 +1,28 @@
+# Readme for the package catppuccinPalette
+
+Author: Lukas Heindl (`oss.heindl+latex@protonmail.com`).
+
+CTAN page: not yet
+
+## License
+The LaTeX package `catppuccinPalette` is distributed under the LPPL 1.3 license.
+
+## Description
+
+The LaTeX package `catppuccinPalette` provides new colors for xcolor.
+
+## Installation
+
+For a manual installation:
+
+* put the files `catppuccinpalette.ins` and `catppuccinpalette.dtx` in the same directory;
+* run `latex catppuccinpalette.ins` in that directory.
+
+The file `catppuccinpalette.sty` will be generated.
+
+The file `catppuccinpalette.sty` is the only file necessary to use the latex package `catppuccinPalette`.
+You have to put it in the same directory as your document or (best) in a `texmf` tree.
+
+Simplified version:
+
+* run `l3build unpack` to generate the `.sty` in `build/unpacked/`
diff --git a/macros/latex/contrib/catppuccinpalette/catppuccinpalette.dtx b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.dtx
new file mode 100644
index 0000000000..d9cabfcd02
--- /dev/null
+++ b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.dtx
@@ -0,0 +1,422 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+% ---------------------------------------------------------------------------
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Lukas Heindl.
+%
+% This work consists of the files catppuccinpalette.dtx and catppuccinpalette.ins
+% and the derived filebase catppuccinpalette.sty.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{catppuccinpalette.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{catppuccinpalette}
+%<*package>
+ [2024/02/27 v1.0.1 catppuccin xcolor palette]
+%</package>
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{catppuccinpalette}[2024/02/27]
+\usepackage{multicol}
+\usepackage{pgffor}
+\usepackage{tabularx, booktabs}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{catppuccinpalette.dtx}
+ \PrintChanges
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{111}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \changes{v0.0.1}{2024/02/09}{Converted to DTX file}
+% \changes{v1.0.0}{2024/02/27}{First full release}
+% \changes{v1.0.1}{2024/05/19}{Make fit for CTAN}
+%
+% \DoNotIndex{\newcommand,\newenvironment,\color,\colorlet,\def,\fi,\RequirePackage,\ProvidesPackage,\ProcessPgfOptions,\preparecolorset,\pgfkeys,\pagecolor,\newif,\NeedsTeXFormat}
+%
+% \providecommand*{\url}{\texttt}
+% \GetFileInfo{catppuccinpalette.dtx}
+% \title{The \textsf{catppuccinPalette} package}
+% \author{Lukas Heindl \\ \url{oss.heindl+latex@protonmail.com} \\ \url{https://github.com/atticus-sullivan/catpuccinPalette}}
+% \date{\fileversion~from \filedate}
+%
+% \maketitle
+%
+% \begin{abstract}
+% The LaTeX package \pkg{catppuccinPalette} provides new colors for xcolor.
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% Catppuccin\footnote{\url{https://github.com/catppuccin/catppuccin}} is a nice
+% pastel theme in 4 flavours/styles (\emph{Latte}, \emph{Frapp\'e},
+% \emph{Macchiato}, \emph{Mocha}). This package defines these themes as xcolor
+% colors.
+%
+% \section{Usage}
+%
+% Load via |\usepackage{catppuccinpalette}|
+%
+% Just use the new colors (prefixed with \verb|Cat<Style>|) like normal xcolors.
+% In addition to the usual colors of the palette, this package defines some
+% colors according to the
+% style guide\footnote{\url{https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md}}
+% for ease of use.
+%
+% This package also allows you to set a specific style which sets the shortened
+% color names (prefixed only with \verb|Cat|) to the selected style (allows for
+% easy switching style) via the package option \verb|style|.
+%
+% This package loads xcolor (without options) so if you want to set some xcolor
+% options you should load xcolor before loading this package.
+%
+% \subsection{Package options}
+% \begin{tabularx}{\linewidth}{lX}
+% \emph{Option} & \emph{Description}
+% \\\toprule
+% \verb|style| &
+% set the style used by the shortened prefix (\verb|Cat|). Possible values:
+% \verb|Latte| (default+initial), \verb|latte|, \verb|Frappe|, \verb|frappe|,
+% \verb|Mocha|, \verb|mocha|
+% \\
+% \verb|textcolor| &
+% set the default textcolor of the document to \verb|CatText|. Possible values:
+% \verb|false| (default+initial), \verb|true|
+% \\
+% \verb|pagecolor| &
+% set the pagecolor of the document to \verb|CatBackground|. Possible values:
+% \verb|false| (default+initial), \verb|true|
+% \\\midrule
+% \verb|styleAll| &
+% shortcut for setting \verb|pagecolor| and \verb|textcolor|
+% \\\bottomrule
+% \end{tabularx}
+%
+% \subsection{Colors}
+% \newcommand{\showCol}[1]{\raisebox{0.5ex}{\fcolorbox{black}{#1}{\hspace{1em}}} #1}
+% \foreach \Style in {Latte,Frappe,Macchiato,Mocha}{
+% \subsubsection{Style \texttt{\Style}}
+% \begin{multicols}{2}
+% \def\Style{Latte}
+% \showCol{Cat\Style Blue}\par
+% \showCol{Cat\Style Rosewater}\par
+% \showCol{Cat\Style Flamingo}\par
+% \showCol{Cat\Style Pink}\par
+% \showCol{Cat\Style Mauve}\par
+% \showCol{Cat\Style Red}\par
+% \showCol{Cat\Style Maroon}\par
+% \showCol{Cat\Style Peach}\par
+% \showCol{Cat\Style Yellow}\par
+% \showCol{Cat\Style Green}\par
+% \showCol{Cat\Style Teal}\par
+% \showCol{Cat\Style Sky}\par
+% \showCol{Cat\Style Sapphire}\par
+% \showCol{Cat\Style Blue}\par
+% \showCol{Cat\Style Lavender}\par
+% \showCol{Cat\Style Text}\par
+% \showCol{Cat\Style Subtext1}\par
+% \showCol{Cat\Style Subtext0}\par
+% \showCol{Cat\Style Overlay2}\par
+% \showCol{Cat\Style Overlay1}\par
+% \showCol{Cat\Style Overlay0}\par
+% \showCol{Cat\Style Surface2}\par
+% \showCol{Cat\Style Surface1}\par
+% \showCol{Cat\Style Surface0}\par
+% \showCol{Cat\Style Base}\par
+% \showCol{Cat\Style Mantle}\par
+% \showCol{Cat\Style Crust}\par
+% \end{multicols}
+%
+% Some basic colors according to the style guide:
+%
+% \begin{multicols}{2}
+% \showCol{Cat\Style Background}\par
+% \showCol{Cat\Style Link}\par
+% \phantom{}\par
+% \columnbreak
+% \showCol{Cat\Style Success}\par
+% \showCol{Cat\Style Warning}\par
+% \showCol{Cat\Style Error}\par
+% \end{multicols}
+%
+% }
+%
+%
+% \StopEventually{}
+%
+% \section{Implementation}
+%
+% \iffalse
+%<*package>
+% \fi
+%
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[1994/06/01]
+\RequirePackage{pgfopts}
+\RequirePackage{xcolor}
+% \end{macrocode}
+% Define the conditionals used by package options
+% \begin{macrocode}
+\newif\ifcatppuccinpalette@pagecolor
+\newif\ifcatppuccinpalette@textcolor
+\pgfkeys{
+ /catppuccinPalette/.cd,
+% \end{macrocode}
+% Define the package option keys
+% \begin{macrocode}
+ style/.is choice,
+ style/.value required,
+ style/Latte/.code = {\def\catppuccinpalette@style{Latte}},
+ style/latte/.forward to = /catppuccinPalette/style/Latte,
+ style/Frappe/.code = {\def\catppuccinpalette@style{Frappe}},
+ style/frappe/.forward to = /catppuccinPalette/style/frappe,
+ style/Macchiato/.code = {\def\catppuccinpalette@style{Macchiato}},
+ style/macchiato/.forward to = /catppuccinPalette/style/Macchiato,
+ style/Mocha/.code = {\def\catppuccinpalette@style{Mocha}},
+ style/mocha/.forward to = /catppuccinPalette/style/Mocha,
+ textcolor/.is if = catppuccinpalette@textcolor,
+ textcolor/.default = true,
+ pagecolor/.is if = catppuccinpalette@pagecolor,
+ pagecolor/.default = true,
+ styleAll/.style = {pagecolor,textcolor},
+% \end{macrocode}
+% Set initial values for all options
+% \begin{macrocode}
+ textcolor = false,
+ pagecolor = false,
+ style = Latte,
+}
+\ProcessPgfOptions*
+% \end{macrocode}
+% Define the \emph{Latte} colorset
+% \begin{macrocode}
+\preparecolorset{RGB/HTML}{CatLatte}{}{%
+ Rosewater,220,138,120/DC8A78;%
+ Flamingo,221,120,120/DD7878;%
+ Pink,234,118,203/EA76CB;%
+ Mauve,136,57,239/8839EF;%
+ Red,210,15,57/D20F39;%
+ Maroon,230,69,83/E64553;%
+ Peach,254,100,11/FE640B;%
+ Yellow,223,142,29/DF8E1D;%
+ Green,64,160,43/40A02B;%
+ Teal,23,146,153/179299;%
+ Sky,4,165,229/04A5E5;%
+ Sapphire,32,159,181/209FB5;%
+ Blue,30,102,245/1E66F5;%
+ Lavender,114,135,253/7287FD;%
+ Text,76,79,105/4C4F69;%
+ Subtext1,92,95,119/5C5F77;%
+ Subtext0,108,111,133/6C6F85;%
+ Overlay2,124,127,147/7C7F93;%
+ Overlay1,140,143,161/8C8FA1;%
+ Overlay0,156,160,176/9CA0B0;%
+ Surface2,172,176,190/ACB0BE;%
+ Surface1,188,192,204/BCC0CC;%
+ Surface0,204,208,218/CCD0DA;%
+ Base,239,241,245/EFF1F5;%
+ Mantle,230,233,239/E6E9EF;%
+ Crust,220,224,232/DCE0E8%
+}
+% \end{macrocode}
+% Define colors according to the catppuccin style guide
+% \begin{macrocode}
+\colorlet{CatLatteBackground}{CatLatteBase}
+\colorlet{CatLatteLink}{CatLatteBlue}
+\colorlet{CatLatteSuccess}{CatLatteGreen}
+\colorlet{CatLatteWarning}{CatLatteYellow}
+\colorlet{CatLatteError}{CatLatteRed}
+% \end{macrocode}
+% Define the styles \emph{Frappe}, \emph{Macchiato} and \emph{Mocha} accordingly
+% \begin{macrocode}
+\preparecolorset{RGB/HTML}{CatFrappe}{}{%
+ Rosewater,242,213,207/F2D5CF;%
+ Flamingo,238,190,190/EEBEBE;%
+ Pink,244,184,228/F4B8E4;%
+ Mauve,202,158,230/CA9EE6;%
+ Red,231,130,132/E78284;%
+ Maroon,234,153,156/EA999C;%
+ Peach,239,159,118/EF9F76;%
+ Yellow,229,200,144/E5C890;%
+ Green,166,209,137/A6D189;%
+ Teal,129,200,190/81C8BE;%
+ Sky,153,209,219/99D1DB;%
+ Sapphire,133,193,220/85C1DC;%
+ Blue,140,170,238/8CAAEE;%
+ Lavender,186,187,241/BABBF1;%
+ Text,198,208,245/C6D0F5;%
+ Subtext1,181,191,226/B5BFE2;%
+ Subtext0,165,173,206/A5ADCE;%
+ Overlay2,148,156,187/949CBB;%
+ Overlay1,131,139,167/838BA7;%
+ Overlay0,115,121,148/737994;%
+ Surface2,98,104,128/626880;%
+ Surface1,81,87,109/51576D;%
+ Surface0,65,69,89/414559;%
+ Base,48,52,70/303446;%
+ Mantle,41,44,60/292C3C;%
+ Crust,35,38,52/232634%
+}
+\colorlet{CatFrappeBackground}{CatFrappeBase}
+\colorlet{CatFrappeLink}{CatFrappeBlue}
+\colorlet{CatFrappeSuccess}{CatFrappeGreen}
+\colorlet{CatFrappeWarning}{CatFrappeYellow}
+\colorlet{CatFrappeError}{CatFrappeRed}
+\preparecolorset{RGB/HTML}{CatMacchiato}{}{%
+ Rosewater,244,219,214/F4DBD6;%
+ Flamingo,240,198,198/F0C6C6;%
+ Pink,245,189,230/F5BDE6;%
+ Mauve,198,160,246/C6A0F6;%
+ Red,237,135,150/ED8796;%
+ Maroon,238,153,160/EE99A0;%
+ Peach,245,169,127/F5A97F;%
+ Yellow,238,212,159/EED49F;%
+ Green,166,218,149/A6DA95;%
+ Teal,139,213,202/8BD5CA;%
+ Sky,145,215,227/91D7E3;%
+ Sapphire,125,196,228/7DC4E4;%
+ Blue,138,173,244/8AADF4;%
+ Lavender,183,189,248/B7BDF8;%
+ Text,202,211,245/CAD3F5;%
+ Subtext1,184,192,224/B8C0E0;%
+ Subtext0,165,173,203/A5ADCB;%
+ Overlay2,147,154,183/939AB7;%
+ Overlay1,128,135,162/8087A2;%
+ Overlay0,110,115,141/6E738D;%
+ Surface2,91,96,120/5B6078;%
+ Surface1,73,77,100/494D64;%
+ Surface0,54,58,79/363A4F;%
+ Base,36,39,58/24273A;%
+ Mantle,30,32,48/1E2030;%
+ Crust,24,25,38/181926%
+}
+\colorlet{CatMacchiatoBackground}{CatMacchiatoBase}
+\colorlet{CatMacchiatoLink}{CatMacchiatoBlue}
+\colorlet{CatMacchiatoSuccess}{CatMacchiatoGreen}
+\colorlet{CatMacchiatoWarning}{CatMacchiatoYellow}
+\colorlet{CatMacchiatoError}{CatMacchiatoRed}
+\preparecolorset{RGB/HTML}{CatMocha}{}{%
+ Rosewater,245,224,220/F5E0DC;%
+ Flamingo,242,205,205/F2CDCD;%
+ Pink,245,194,231/F5C2E7;%
+ Mauve,203,166,247/CBA6F7;%
+ Red,243,139,168/F38BA8;%
+ Maroon,235,160,172/EBA0AC;%
+ Peach,250,179,135/FAB387;%
+ Yellow,249,226,175/F9E2AF;%
+ Green,166,227,161/A6E3A1;%
+ Teal,148,226,213/94E2D5;%
+ Sky,137,220,235/89DCEB;%
+ Sapphire,116,199,236/74C7EC;%
+ Blue,137,180,250/89B4FA;%
+ Lavender,180,190,254/B4BEFE;%
+ Text,205,214,244/CDD6F4;%
+ Subtext1,186,194,222/BAC2DE;%
+ Subtext0,166,173,200/A6ADC8;%
+ Overlay2,147,153,178/9399B2;%
+ Overlay1,127,132,156/7F849C;%
+ Overlay0,108,112,134/6C7086;%
+ Surface2,88,91,112/585B70;%
+ Surface1,69,71,90/45475A;%
+ Surface0,49,50,68/313244;%
+ Base,30,30,46/1E1E2E;%
+ Mantle,24,24,37/181825;%
+ Crust,17,17,27/11111B%
+}
+% \end{macrocode}
+% Define shortcuts for active style
+% \begin{macrocode}
+\colorlet{CatMochaBackground}{CatMochaBase}
+\colorlet{CatMochaLink}{CatMochaBlue}
+\colorlet{CatMochaSuccess}{CatMochaGreen}
+\colorlet{CatMochaWarning}{CatMochaYellow}
+\colorlet{CatMochaError}{CatMochaRed}
+\colorlet{CatRosewater}{Cat\catppuccinpalette@style Rosewater}
+\colorlet{CatFlamingo}{Cat\catppuccinpalette@style Flamingo}
+\colorlet{CatPink}{Cat\catppuccinpalette@style Pink}
+\colorlet{CatMauve}{Cat\catppuccinpalette@style Mauve}
+\colorlet{CatRed}{Cat\catppuccinpalette@style Red}
+\colorlet{CatMaroon}{Cat\catppuccinpalette@style Maroon}
+\colorlet{CatPeach}{Cat\catppuccinpalette@style Peach}
+\colorlet{CatYellow}{Cat\catppuccinpalette@style Yellow}
+\colorlet{CatGreen}{Cat\catppuccinpalette@style Green}
+\colorlet{CatTeal}{Cat\catppuccinpalette@style Teal}
+\colorlet{CatSky}{Cat\catppuccinpalette@style Sky}
+\colorlet{CatSapphire}{Cat\catppuccinpalette@style Sapphire}
+\colorlet{CatBlue}{Cat\catppuccinpalette@style Blue}
+\colorlet{CatLavender}{Cat\catppuccinpalette@style Lavender}
+\colorlet{CatText}{Cat\catppuccinpalette@style Text}
+\colorlet{CatSubtext1}{Cat\catppuccinpalette@style Subtext1}
+\colorlet{CatSubtext0}{Cat\catppuccinpalette@style Subtext0}
+\colorlet{CatOverlay2}{Cat\catppuccinpalette@style Overlay2}
+\colorlet{CatOverlay1}{Cat\catppuccinpalette@style Overlay1}
+\colorlet{CatOverlay0}{Cat\catppuccinpalette@style Overlay0}
+\colorlet{CatSurface2}{Cat\catppuccinpalette@style Surface2}
+\colorlet{CatSurface1}{Cat\catppuccinpalette@style Surface1}
+\colorlet{CatSurface0}{Cat\catppuccinpalette@style Surface0}
+\colorlet{CatBase}{Cat\catppuccinpalette@style Base}
+\colorlet{CatMantle}{Cat\catppuccinpalette@style Mantle}
+\colorlet{CatCrust}{Cat\catppuccinpalette@style Crust}
+\colorlet{CatBackground}{Cat\catppuccinpalette@style Base}
+\colorlet{CatLink}{Cat\catppuccinpalette@style Blue}
+\colorlet{CatSuccess}{Cat\catppuccinpalette@style Green}
+\colorlet{CatWarning}{Cat\catppuccinpalette@style Yellow}
+\colorlet{CatError}{Cat\catppuccinpalette@style Red}
+% \end{macrocode}
+% Set (only initial) pagecolor according to the style guide if the user wants this
+% \begin{macrocode}
+\ifcatppuccinpalette@pagecolor
+ \pagecolor{CatBackground}
+\fi
+% \end{macrocode}
+% Set textcolor according to the style guide if the user wants this
+% \begin{macrocode}
+\ifcatppuccinpalette@textcolor
+ \color{CatText}
+\fi
+% \end{macrocode}
+\endinput
+%
+% \iffalse
+%</package>
+% \fi
+%
+% \Finale
+\endinput
diff --git a/macros/latex/contrib/catppuccinpalette/catppuccinpalette.ins b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.ins
new file mode 100644
index 0000000000..c93b929dcd
--- /dev/null
+++ b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.ins
@@ -0,0 +1,57 @@
+%% Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+%% --------------------------------------------------------------------------
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Lukas Heindl.
+%%
+%% This work consists of the files catppuccinpalette.dtx and catppuccinpalette.ins
+%% and the derived filebase catppuccinpalette.sty.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/catppuccinpalette}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+--------------------------------------------------------------------------
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+\endpreamble
+
+\generate{\file{catppuccinpalette.sty}{\from{catppuccinpalette.dtx}{package}}}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* catppuccinpalette.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file catppuccinpalette.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
diff --git a/macros/latex/contrib/catppuccinpalette/catppuccinpalette.pdf b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.pdf
new file mode 100644
index 0000000000..aedd35c9bf
--- /dev/null
+++ b/macros/latex/contrib/catppuccinpalette/catppuccinpalette.pdf
Binary files differ
diff --git a/macros/latex/contrib/spbmark/spbmark.pdf b/macros/latex/contrib/spbmark/spbmark.pdf
index 5ad9b3e360..8242e5e3bf 100644
--- a/macros/latex/contrib/spbmark/spbmark.pdf
+++ b/macros/latex/contrib/spbmark/spbmark.pdf
Binary files differ
diff --git a/macros/latex/contrib/spbmark/spbmark.sty b/macros/latex/contrib/spbmark/spbmark.sty
index 9646dc1e00..c1ce4837a5 100644
--- a/macros/latex/contrib/spbmark/spbmark.sty
+++ b/macros/latex/contrib/spbmark/spbmark.sty
@@ -9,7 +9,7 @@
% https://creativecommons.org/licenses/by/4.0/legalcode
\NeedsTeXFormat{LaTeX2e}[2018/12/31]
\RequirePackage{xparse,l3keys2e}
-\ProvidesExplPackage{spbmark}{2024/05/13}{1.46i}
+\ProvidesExplPackage{spbmark}{2024/05/19}{1.46j}
{Customize superscripts and subscripts}
\cs_generate_variant:Nn \box_set_ht:Nn { cv }
@@ -22,6 +22,8 @@
\cs_generate_variant:Nn \tl_if_novalue:nF { V }
\cs_generate_variant:Nn \tl_if_blank:nF { v }
+\providecommand{\AfterPreamble}{\AtBeginDocument}
+\AtBeginDocument{\cs_set_eq:NN \AfterPreamble \use:n}
\cs_set_eq:NN \spb@textsuperscript@save \textsuperscript
\cs_set_eq:NN \spb@textsubscript@save \textsubscript
\cs_set_eq:NN \spb@math@super@save \sp
@@ -30,46 +32,78 @@
\cs_new_protected:Npn \spb_define:n { \keys_define:nn { ctex/tools } }
\cs_new_protected:Npn \spb_set:n { \keys_set:nn { ctex/tools } }
\cs_set_eq:NN \spbset \spb_set:n
+
\keys_define:nn { spbmark/option }
{
text .choice:,
- text/true .code:n =
+ text/true .code:n =
{
\cs_set:Npn \textsuperscript { \super[textsp] }
\cs_set:Npn \textsubscript { \sub[textsb] }
},
- text/false .code:n =
+ text/false .code:n =
{
\cs_set:Npn \textsuperscript { \spb@textsuperscript@save }
\cs_set:Npn \textsubscript { \spb@textsubscript@save }
},
- text .default:n = true,
+ text .default:n = true,
math .choice:,
- math/true .code:n =
+ math/true .code:n =
{
\cs_set:Npn \sp { \super[mathsp] }
\cs_set:Npn \sb { \sub[mathsb] }
},
- math/false .code:n =
+ math/false .code:n =
{
\cs_set:Npn \sp { \spb@math@super@save }
\cs_set:Npn \sb { \spb@math@sub@save }
},
- math .default:n = true,
+ math .default:n = true,
foot .choice:,
- foot/true .code:n =
+ foot/true .code:n =
{
\cs_set:Npn \@makefnmark
{ \hbox:n { \fnmarkfont{\super[fnmark]{\@thefnmark}} } }
},
- foot/false .code:n =
+ foot/false .code:n =
{ \cs_set:Npn \@makefnmark { \spb@@makefnmark@save } },
- foot .default:n = true,
- both .meta:n = { text = #1,math = #1 },
- both .default:n = true,
- all .meta:n = { text = #1,math = #1,foot = #1 },
- all .default:n = true
+ foot .default:n = true,
+ both .meta:n = { text = #1,math = #1 },
+ both .default:n = true,
+ all .meta:n = { text = #1,math = #1,foot = #1 },
+ all .default:n = true
+ }
+\char_set_catcode_active:N \~
+\keys_define:nn { spbmark/option }
+ {
+ math* .choice:,
+ math*/true .code:n =
+ {
+ \AfterPreamble
+ {
+ \group_begin:
+ \char_set_lccode:nn { `\~ } { `\^ }
+ \lowercase{\group_end:\cs_set:Npn ~} { \super[mathsp*] }
+ \group_begin:
+ \char_set_lccode:nn { `\~ } { `\_ }
+ \lowercase{\group_end:\cs_set:Npn ~} { \sub[mathsb*] }
+ \char_set_mathcode:nn { `\^ } { "8000 }
+ \char_set_catcode_other:N \^
+ \char_set_catcode_other:N \_
+ }
+ },
+ math*/false .code:n =
+ {
+ \AfterPreamble
+ {
+ \char_set_catcode_math_superscript:N \^
+ \char_set_catcode_math_subscript:N \_
+ \char_set_mathcode:nn { `\^ } { "005E }
+ }
+ },
+ math* .default:n = true
}
+\char_set_catcode_space:N \~
\tl_if_exist:NTF \ftntm@font
{ \tl_set_eq:NN \fnmarkfont \ftntm@font }
{ \tl_set_eq:NN \fnmarkfont \normalfont }
@@ -112,7 +146,7 @@
\cs_new_protected:Npn \spbshortkv #1#2
{ \spb_define:n { #1 .meta:n = {#2} } }
\clist_map_inline:nn
- { textsp,textsb,mathsp,mathsb,fnmark }
+ { textsp,textsb,mathsp,mathsb,mathsp*,mathsb*,fnmark }
{
\defspbstyle{#1}{}
\spbshortkv{#1}{style = #1}
diff --git a/macros/latex/contrib/spbmark/spbmark.tex b/macros/latex/contrib/spbmark/spbmark.tex
index e631b4c210..9d04ea07f9 100644
--- a/macros/latex/contrib/spbmark/spbmark.tex
+++ b/macros/latex/contrib/spbmark/spbmark.tex
@@ -8,8 +8,8 @@
{
package = spbmark,
title = the spbmark package,
- version = v1.46i,
- date = 2024/05/13,
+ version = v1.46j,
+ date = 2024/05/19,
authors = Qu Yi,
info = Customize superscript and subscript,
email = toquyi@163.com,
@@ -40,7 +40,7 @@
\newsplitarg{\splitoarg}{[}{]}
\newsplitarg{\splitmarg}{\{}{\}}
\newsplitarg{\splitdarg}{(}{)}
-\newnote{\newtag}[1][New]{\textcolor{red}{#1}}
+\newnote{\newtag}[1]{\textcolor{red}{#1}}
\renewcommand{\emph}[1]{\textcolor{red}{#1}}
\renewcommand{\cnltx@write@lastname}{}
\makeatother
@@ -49,12 +49,14 @@
\section{Macro package options}
The following macro package options will redefine the script commands of the \LaTeX{} kernel. If you do not specify the values of boolean options, they default to \code{true}. These options can also be changed in the preamble area and main body using the global control command \cs{spbset}.
\begin{options}
- \keychoice{text}{true,\fbox{false}}\newtag[Changed]%
- \cs{textsuperscript} and \cs{textsubscript} are equivalent to the \cs{super} and \cs{sub} commands. You can also use the \cs{defspbstyle} command to define the style \code{textsp} and \code{textsb} to change the format of the text superscript and subscript.
- \keychoice{math}{true,\fbox{false}}\newtag[Changed]%
- \cs{sp} and \cs{sb} are equivalent to the \cs{super} and \cs{sub} commands. You can also use the \cs{defspbstyle} command to define the style \code{mathsp} and \code{mathsb} to change the format of the math superscript and subscript.
- \keychoice{foot}{true,\fbox{false}}\newtag[Changed]%
- The format of the footnote mark match the superscript global move and format settings. You can also use the \cs{defspbstyle} command to define the superscript style \code{fnmark} to change the format of the footnote mark.
+ \keychoice{text}{true,\fbox{false}}
+ \cs{textsuperscript} and \cs{textsubscript} are equivalent to the \cs{super} and \cs{sub} commands. The command \cs{defspbstyle} can be used to define the style \code{textsp} and \code{textsb} to change the format of the text superscript and subscript.
+ \keychoice{math}{true,\fbox{false}}
+ \cs{sp} and \cs{sb} are equivalent to the \cs{super} and \cs{sub} commands. The command \cs{defspbstyle} can be used to define the style \code{mathsp} and \code{mathsb} to change the format of the math superscript and subscript.
+ \keychoice{math*}{true,\fbox{false}}\newtag{Exp\\v1.46j}%
+ The \code{\^{}} and \code{\_{}} tokens in the math mode are equivalent to the \cs{super} and \cs{sub} commands. The command \cs{defspbstyle} can be used to define the style \code{mathsp*} and \code{mathsb*} to change the format of the math superscript and subscript.
+ \keychoice{foot}{true,\fbox{false}}
+ The format of the footnote mark match the superscript global move and format settings. \cs{defspbstyle} can be used to define the superscript style \code{fnmark} to change the format of the footnote mark.
\begin{example}[code-only]
\defspbstyle{textsp}{vmove=-1pt,cmd=\bfseries}
\defspbstyle{mathsb}{hmove=0.5em}
@@ -152,7 +154,7 @@ The options common to \meta{kv list} of the three commands are as follows. They
Use the \meta{style name} defined by the \cs{defspbstyle} command to make it work global or local.
\keychoice{mode}{text,math,\fbox{match}}
The mode of superscript or subscript output can be \code{text} or \code{math} mode. The \code{match} option automatically matches output modes according to the current mode.
- \keychoice{thiswd}{auto,\fbox{keep}}\newtag%
+ \keychoice{thiswd}{auto,\fbox{keep}}
Sets how the length of the this marker is handled after this command is used. If it is \code{keep}, the width of the previous marker remains the same. If it is \code{auto}, if the next token is a marker command and the upper or lower position is the \textcolor{red}{opposite} of the this command, the width of the this marker is maintained, otherwise the width automatically returns to \textcolor{red}{zero}.
\begin{example}
\spbset{sbhmove=-\llastwd,sbthiswd=auto,sbcmd=\color{red}}
@@ -161,7 +163,7 @@ The options common to \meta{kv list} of the three commands are as follows. They
3A\sub{bcd}[thiswd=keep]\sub{e}Some texts\sub{e} \\
4A\sub{bcd}\sub{e}Some texts\sub{e}
\end{example}
- \keyval{regex}{regular expression}\newtag%
+ \keyval{regex}{regular expression}
After using the superscript or subscript command, this option is used to determine whether the \textcolor{red}{following} tokens match the \meta{regular expression}. If it does \textcolor{red}{not}, the width of the this marker returns to zero.
\begin{example}[code-only]
\newcommand{\mysp}[2][]{\super[regex=\c{mysb},#1]{#2}}
@@ -206,13 +208,13 @@ The following list of keys control the format both of superscript \emph{or} subs
The distance between the subscript baseline and the previous line.
\keyval{sbdepth}{fixed length}
The distance between the subscript baseline and the next line.
- \keychoice{spthiswd}{auto,\fbox{keep}}\newtag%
+ \keychoice{spthiswd}{auto,\fbox{keep}}
Width processing mode after using this superscript. See Section \ref{sec:user commands} for the meaning of this option.
- \keychoice{sbthiswd}{auto,\fbox{keep}}\newtag%
+ \keychoice{sbthiswd}{auto,\fbox{keep}}
Width processing mode after using this subscript. See Section \ref{sec:user commands} for the meaning of this option.
- \keyval{spregex}{regular expression}\newtag%
+ \keyval{spregex}{regular expression}
After the superscript command is used, the regular expression rules of the following tokens are matched. See Section \ref{sec:user commands} for the meaning of this option.
- \keyval{sbregex}{regular expression}\newtag%
+ \keyval{sbregex}{regular expression}
After the subscript command is used, the regular expression rules of the following tokens are matched. See Section \ref{sec:user commands} for the meaning of this option.
\end{options}
@@ -251,9 +253,12 @@ Here is a list of the three commands, please pay attention to the usage of optio
\subsection{siunitx}
It can also be used with the \pkg*{siunitx} package to output superscript and subscript in the unit:
\begin{example}
- \unit[mode=math]{kg.m/s\super[vmove=-1pt]{2}} \\
- \qty[mode=text]{30}{A\supersub[hmove=1pt,cmd=\color{red}]{b}{c}} \\
- \spbset{sbhmove=2pt}\unit[mode=text]{A\sub{b}}
+ \spbset{spcmd=\spbifmath{}{\color{purple}}}
+ \sisetup{text-superscript-command=\super}
+ 1-\qty[mode=text]{10}{A^2} \\
+ 2-\unit[mode=math]{kg.m/s\super[vmove=-1pt]{2}} \\
+ 3-\qty[mode=text]{30}{A\supersub[hmove=1pt,cmd=\color{blue}]{b}{c}} \\
+ 4-\spbset{sbhmove=2pt}\unit[mode=text]{A\sub{b}}
\end{example}
\subsection{realscripts}
diff --git a/macros/luatex/latex/semesterplannerlua/README.md b/macros/luatex/latex/semesterplannerlua/README.md
new file mode 100644
index 0000000000..d7049942cb
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/README.md
@@ -0,0 +1,43 @@
+# Readme for the package semesterplannerLua
+
+Author: Lukas Heindl (`oss.heindl+latex@protonmail.com`).
+
+CTAN page: not yet
+
+## License
+The LaTeX package `semesterplannerLua` is distributed under the LPPL 1.3 license.
+
+## Description
+
+The LaTeX package `semesterplannerLua` provides commands to print timetables, lists
+of appointments and exams. Also it is possible to draw calendars of specified
+ranges (and mark dates which were previously listed).
+
+## Installation
+
+For a manual installation:
+
+* put the files `semesterplannerlua.ins` and `semesterplannerlua.dtx` in the
+same directory;
+* run `latex semesterplannerlua.ins` in that directory.
+
+The file `semesterplannerlua.sty` will be generated.
+
+In addition to the `semesterplannerlua.sty` the files
+`semesterplannerLua_calendar.lua` and `semesterplannerLua_timetable.lua` are
+also required.
+You have to put them in the same directory as your document or (best) in a `texmf` tree.
+
+
+### Simplified version:
+
+* run `l3build unpack` to generate the `.sty` (and the `.lua` files) in
+`build/unpacked/`
+
+### Experimental: dmenu script
+There is also the `semesterplannerLua_dmenu.lua` script which will display the
+previous and next (and currently running) item from your timetable via dmenu,
+copying the url or the link to the TUM roomfinder(if set) to your clipboard if
+selected.
+
+You might want to adapt the roomfinder behaviour.
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua.dtx b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.dtx
new file mode 100644
index 0000000000..8341981afd
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.dtx
@@ -0,0 +1,885 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+% ---------------------------------------------------------------------------
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Lukas Heindl.
+%
+% This work consists of the files beamercolorthemeCatppuccin.dtx and beamercolorthemeCatppuccin.ins
+% and the derived filebase beamercolorthemeCatppuccin.sty.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{semesterplannerlua.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{semesterplannerlua}
+%<*package>
+ [2024/05/19 v1.1.1 Semesterplanner package in lua with tikz only]
+%</package>
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage[a4paper,margin=25mm,left=50mm,nohead]{geometry}
+\usepackage[numbered]{hypdoc}
+\usepackage{array}
+\usepackage{semesterplannerlua}[2024/02/27]
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{\jobname.dtx}
+ \PrintChanges
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{362}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \changes{v0.0.0}{2021/10/07}{First draft}
+% \changes{v0.0.1}{2022/04/28}{Added new options (providing day
+% representation in source code)}
+% \changes{v0.0.2}{2022/04/30}{Write out timetable data to be able to build
+% e.g. something with dmenu over it and provide an example dmenu lua
+% script}
+% \changes{v0.0.3}{2024/02/25}{Rename to semesterplannerLua and rewrite for
+% l3build}
+% \changes{v1.0.0}{2024/02/27}{First full release}
+% \changes{v1.1.0}{2024/05/19}{Make ready for CTAN}
+% \changes{v1.1.1}{2024/05/19}{Make ready for CTAN (2)}
+%
+%
+% \DoNotIndex{\newcommand,\newenvironment,\\,\begin,\end,\def,\definecolor,\directlua,\endinput,\faBullhorn,\faCamera,\faFlag,\faQuestion,\faTimesCircle,\faWarning,\faWindows,\faYoutubePlay,\node,\pgfkeys,\pgfkeysvalueof,\protected,\raggedright,\textbf,\textcolor,\textwidth,\unexpanded,\",\x,\y,\year,\week,\tiny,\tikz@lib@cal@xshift,\tikz@lib@cal@yshift,\tikz,\textit,\t,\section,\phantom,\pgftransformyshift,\pgftransformxshif,\pgfmathsetlength,\pgf@ya,\pgf@xa,\openout,\n,\newwrite,\month,\minuteToFrac,\matrix,\l,\jobname,\init,\immediate,\ignorespaces,\ifdate,\hfil,\href,\foreach,\faStickyNoteO,\faPencil,\faComment,\faClockO,\faCalendar,\faBold,\draw,\d,\day,\checkKeys,\%,\RequirePackage,\usepackage,\usetikzlibrary,\pgftransformxshift}
+%
+% \providecommand*{\url}{\texttt}
+% \GetFileInfo{semesterplannerlua.dtx}
+% \title{\textsf{semesterplannerLua} --- Semesterplanner package in lua
+% with tikz only
+% }
+% \author{Lukas Heindl \\ \url{oss.heindl+latex@protonmail.com} \\ \faGithub:
+% \url{https://github.com/atticus-sullivan/semesterplannerLua}}
+% \date{\fileversion~from \filedate}
+%
+% \maketitle
+%
+% \begin{abstract}
+% This package provides a mean to easily print a timetable e.g. for a
+% semesterplan. The reason for this package to exist is that I wanted to
+% reimplement \url{https://github.com/nlschn/semesterplanner/} with
+% printing the timetable with |tikz| only (which is more easily to be
+% modified) and with the ability of making entries spanning only a fraction
+% of the column (for showing simultanious events).
+%
+% Documents using this package need to be compiled with
+% LuaLaTeX. The package requires |xcolor|, |fontawesome|, |tikz| (and |pgfkeys|).
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \section{Usage}
+% Load with |\usepackage{semesterplannerlua}|
+% \subsection{timetable}
+%
+% \DescribeEnv{timetable} |\begin{timetable}[opts]...\end{timetable}|\\
+% This is the core environment of this package. Within it you can use
+% |\lecture|, |\seminar|, |\tutorial|, |\officehour| and |\meeting|. All
+% these commands are only defined inside the |timetable| environment, and
+% have the same structure. It typesets a timetable with the specified
+% entries. If you have a look at the |.sty| file you'll see that these
+% macros just take a general macro and set some default values before. Thus
+% it is easy to define new ones (keep in mind that you'll need
+% |\makeatletter|) to access the general macro.
+%
+% Writes out a file containing the data from the timetable (your events) to
+% be able to have just the |.tex| file containing the timetable, but do
+% some scriping on the data (e.g. show the last, current and next events).
+% For simplicity the data is stored in lua-syntax (|return|s a table of the
+% events). This way we don't need to worry about any string escaping (like
+% with csv) and no complicated parsers are needed. Be aware though that a
+% simple |events = dofile"path"| has risks since |"path"| might contain lua
+% code which is simply executed that way.
+%
+% |opts| are optional arguments (enclosed with |{}|) separated with |,|:
+% \begin{description}
+% \item[|days|] List of the names of the days that should be set as
+% column names. Note that if you specify only 4 names only these 4
+% columns will be printed (with the first day being identified as
+% Monday)
+% \textit{Default: |Mon,Thue,Wend,Thur,Fri|}
+% \item[|dayse|] List of strings used in the code to idenfity the day.
+% This list is kind of a mapping string $\to$ integer.
+% \item[|start time|] Explicit start-time of the timetable given in minutes
+% (|HH*60 + MM|). Can be set as |start time/.evaluated={HH*60 + MM}|.
+% If this is empty, the start time is derived from the given events.
+% \textit{Default: |""|}
+% \item[|end time|] Equivalent to |start-time|
+% \textit{Default: |""|}
+% \item[|width|] Give the width of the timetable. (can be given e.g. as
+% |\textwidth| as this is directly given to tikz).
+% \textit{Default:} |\textwidth|
+% \item[|length|] Give the length of the timetable (measured in |cm|)
+% (has to be a straight number since this is needed in calculation)
+% \textit{Default: 10}
+% \end{description}
+%
+% \DescribeMacro{\lecture} |\lecture [opts]|
+%
+% \DescribeMacro{\tutorial} |\tutorial [opts]|
+%
+% \DescribeMacro{\seminar} |\seminar [opts]|
+%
+% \DescribeMacro{\officehour} |\officehour[opts]|
+%
+% \DescribeMacro{\meeting} |\meeting [opts]|
+%
+% |opts| are optional arguments (enclosed with |{}|) separated with |,|:
+% \begin{description}
+% \item[|title|] Give the name of the lecture
+% \item[|speaker|] Give the name of the lecturer
+% \item[|location|] Give the place of the event (most probably the room or
+% an online plattform, see \ref{icons}). If you want to use
+% |\href{url}{string repr}|, keep in mind that you need to
+% |\unescaped{}| it, since all input to lua has to be text
+% \item[|day|] The weekday on which the event takes place. Has to be
+% one of those you specified in |dayse| (or by default: |M|,|T|,|W|,|Th|,|F|)
+% \item[|time|] The timespan of the event formatted as |HH:MM-HH:MM|
+% (24H clock)
+% \item[|prio|] The priority of the event (see \ref{icons})
+% \item[|scale width|] Specify the width of the entry in fractions
+% of column (use |0.5| to span half the column).
+% \item[|offset|] Shift the entry to the right. Specified in fractions
+% of column.
+% \item[|password|] Original purpose: Only included in the file written
+% out with the timetable data, to be able to make a script which
+% quickly copies url (from |location|) and |password| to the clipboard.
+% \item[|type|] Only included in the file written out with the
+% timetable data as well (Original purpose: To be able to exclude some
+% types)
+% \item[|tikz|] Free customizable event code. See the documentation
+% at the end for keys that can be used here (all keys in |/event|). To
+% simply pass arguments to the tikz-node that is being created for the
+% event use |tikz/.append={your arguments}| (be careful with |text width|,
+% |text height|, |text depth| as these keys are being used for
+% the dimensions of the node as well as with |anchor|)
+% \item[|content|] Is usually set automatically based on the other keys
+% (|title|for instance). This key can override this.
+% \item[|textcolor|] Usually set by the type of macro used
+% \item[|formatter|] internal stub for providing different formatting
+% options. Formatting functions need to be specified in the
+% |-timetable.lua| file
+% \end{description}
+% The entries |Day| and |Time| are mandatory since they are needed for the
+% positioning of the node. All others are merely necessary for the content
+% of the node and are therefore nor mandatory.
+%
+% \subsubsection{Special Notes}
+% Note that the |length| argument does specify the length of the timetable
+% without taking account of the column headers.
+%
+% Same goes for the |width| parameter regarding the labels containing the
+% time on the right. Since in this case any tex-lenght is allowed, you can
+% simply try to subtract the length of the clock label using something like
+% |\settowidth{\length}{12:30}| to set a length to the length of a clock
+% label and then subtract this from the length you want to specify.
+%
+% \hangindent=4.5em \hangafter=1 \textbf{Hint:} The content of the
+% environment isn't processed by this package. Only the event commands (so
+% to speak |\lecture|,|\tutorial|,|\seminar|,|\officehour|,|\meeting| are
+% relevant. All other contents are set immediately before the timetable.
+% Therefore, if you wan to add e.g. a |\hspace*{10cm}| to shift the
+% timetable to the left, the last line of the env would be the place to do
+% so (there musn't be an empty line below since otherwise a new paragraph
+% is started).
+%
+% \newpage
+% \subsubsection{Example}
+% |\begin{timetable}[|\\
+% | days={Mon,Thue,Wend,Thur,Fri},|\\
+% | start time/.evaluated={11*60}, end time/.evaluated={15*60}|\\
+% | ]|\\
+% | \lecture[title={TestingLectureLongOne},speaker={Doe},|\\
+% | location={RN1},day={W},time={12:30-13:30}]|\\
+% | \lecture[title={TestingLectureLongOne},speaker={John},|\\
+% | location={RN1},day={Th},time={12:30-13:30},offset=0.5,scale width=0.5]|\\
+% | \lecture[title={TestingLectureLongOne},speaker={Dr. Doe},|\\
+% | location={\zoom},day={T},time={12:30-13:30},prio={\phigh}]|\\
+% |\end{timetable}|\\
+%
+% \begin{timetable}[days={Mon,Thue,Wend,Thur,Fri}, start
+% time/.evaluated={11*60}, end time/.evaluated={15*60}]
+% \lecture[title={TestingLectureLongOne}, speaker={Heindl}, location={RN1}, day={W}, time={12:30-13:30}]
+% \lecture[title={TestingLectureLongOne}, speaker={Heindl}, location={RN1}, day={Th}, time={12:30-13:30}, offset=0.5, scale width=0.5]
+% \lecture[title={TestingLectureLongOne}, speaker={Heindl}, location={\zoom}, day={T}, time={12:30-13:30}, prio={\phigh}]
+% \hspace*{-.2\textwidth}
+% \end{timetable}
+%
+% \subsection{Calendar related things}
+% Now some environments and commands come which in generally are being used
+% to typeset a table with the detailed information, but which also store
+% the gathered data internally.\\
+% This saved data can be used to output a calendar where the events (from
+% the saved data) are highlighted with a mark (already passed days are
+% crossed and the current day is highlighted as well).
+%
+% The different environments described below are similar in general, but
+% differ in detail (mostly the list of argument that are passed and printed
+% in the table).
+%
+% \newpage
+% \paragraph{Example}\mbox{}\\
+% |\begin{appointments}{true}|\\
+% | \appointment[print=true,shift=false,tikz={fill=black,rectangle},|\\
+% | date={2022-04-15}, course={Appointment with my dog},|\\
+% | end={2022-04-18}, period={1}]|\\
+% | \appointment[date={2022-04-14}, course={Appointment with my dog},|\\
+% | room={at home}, time={12:00}, prio={\pmandatory}]|\\
+% |\end{appointments}|\\
+% |\begin{exams}{false}|\\
+% | \exam[tikz={fill=yellow}, date={2022-06-20}, time={arround midday},|\\
+% | course={Driving}, desc={Mid-Term}, prio={\phigh},|\\
+% | room={University}, type={\oral}]|\\
+% |\end{exams}|\\
+% |\begin{deadlines}{false}|\\
+% | \deadline[tikz={fill=blue}, date={2022-06-22},|\\
+% | course={Submitting Driver-license form}, prio={\phigh}]|\\
+% |\end{deadlines}|\\
+% ||\\
+% |\printSpCalendar[2]{2022-04-01}{2022-07-31}|
+
+% \begin{appointments}{true}
+% \appointment[print=true,shift=false,tikz={fill=black,rectangle}, date={2022-04-15}, course={Appointment with my dog}, end={2022-04-18}, period={1}]
+% \appointment[date={2022-04-14}, course={Appointment with my dog}, room={at home}, time={12:00}, prio={\pmandatory}]
+% \end{appointments}
+% \begin{exams}{false}
+% \exam[tikz={fill=yellow}, date={2022-06-20}, time={arround midday}, course={Driving}, desc={Mid-Term}, prio={\phigh}, room={University}, type={\oral}]
+% \end{exams}
+% \begin{deadlines}{false}
+% \deadline[tikz={fill=blue}, date={2022-06-22}, course={Submitting Driver-license form}, prio={\phigh}]
+% \end{deadlines}
+%
+% \printSpCalendar[2]{2022-04-01}{2022-07-31}
+%
+% \DescribeMacro{\printSpCalendar} |\printSpCalendar[cols]{start_date}{end_date}|\\
+% This is the macro to output such a calendar populated with the gathered
+% events.\\
+% Use the |cols| argument to specify the amount of columns being used
+% (months set side by side).\\
+% |start_date| and |end_date| both have to be specified in the |YYYY-MM-DD|
+% format.
+%
+% \subsubsection{Appointments}
+% \DescribeEnv{appointments} |\begin{appointments}[Room]{true/false}...\end{appointments}|\\
+% Environment to typeset a table of appointments. Stores the data
+% internally to be able to typeset a calendar (with |\printSpCalendar|)
+% with a mark for each event.\\
+% The optional argument is used as header for the |Room| column (maybe for
+% some appointments another title is more suitable).\\
+% The mandatory argument which is |true/false| decides if the internally
+% stored data used to typeset the calendar is being erased before this
+% environment.
+%
+% \DescribeMacro{\appointment} |\appointment[opts]|\\
+% |opts| are optional arguments (enclosed with |{}|) separated with |,|:
+% \begin{description}
+% \item[|date|] Date of the appointment formatted as |YYYY-MM-DD|
+% \item[|course|] Name of the course
+% \item[|room|] Room (only shown in the table)
+% \item[|time|] Time of the event (free text independant of any
+% formatting, only shown in the table)
+% \item[|prio|] priority of the event (shown in the table) (see
+% \ref{icons})
+% \item[|desc|] Description of the event (shown in the table)
+% \item[|end|] upper boundary when the event should stop to repeat (with
+% |period|). Has to be set to make event periodic/repeating.
+% \item[|period|] Set the period of the repeating event.
+% \item[|draw|] |true/false| wether to draw a mark in the calendar
+% \item[|print|] |true/false| wether to display te entry in the
+% appointments table.
+% \item[|shift|] |true/false| wether to shift the mark in the calendar if
+% there is already another event on that date (to be able to see both
+% marks)
+% \item[|tikz|] Free customizable tikz code used for drawing the mark
+% in the calendar. See the documentation at the end for keys that can
+% be used here (all keys in |/cal|). To simply pass arguments to the
+% tikz-node that is being created for the event use |tikz/.append={your arguments}|\\
+% Use e.g. to set the color of the mark via |tikz/.append={green}|
+% \end{description}
+% \subsubsection{Exams}
+% \DescribeEnv{exams} |\begin{exams}{true/false}...\end{exams}|\\
+% Environment to typeset a table of exams. Stores the data
+% internally to be able to typeset a calendar (with |\printSpCalendar|)
+% with a mark for each event.\\
+% The mandatory argument which is |true/false| decides if the internally
+% stored data used to typeset the calendar is being erased before this
+% environment.
+%
+% \DescribeMacro{\exam} |\exam[opts]|\\
+% |opts| are optional arguments (enclosed with |{}|) separated with |,|:
+% \begin{description}
+% \item[|date|] Date of the exam formatted as |YYYY-MM-DD|
+% \item[|course|] Name of the course
+% \item[|room|] Room (only shown in the table)
+% \item[|type|] Type of the exam (see \ref{icons}) (intended:
+% written/oral)
+% \item[|time|] Time of the event (free text independant of any
+% formatting, only shown in the table)
+% \item[|desc|] Description of the event (shown in the table)
+% \item[|draw|] |true/false| wether to draw a mark in the calendar
+% \item[|print|] |true/false| wether to display te entry in the
+% exams table.
+% \item[|shift|] |true/false| wether to shift the mark in the calendar if
+% there is already another event on that date (to be able to see both
+% marks)
+% \item[|tikz|] Free customizable tikz code used for drawing the mark
+% in the calendar. See the documentation at the end for keys that can
+% be used here (all keys in |/cal|). To simply pass arguments to the
+% tikz-node that is being created for the event use |tikz/.append={your arguments}|\\
+% Use e.g. to set the color of the mark via |tikz/.append={green}|
+% \end{description}
+%
+% \subsubsection{Deadlines}
+% \DescribeEnv{deadlines} |\begin{deadlines}{true/false}...\end{deadlines}|\\
+% Environment to typeset a table of deadlines. Stores the data
+% internally to be able to typeset a calendar (with |\printSpCalendar|)
+% with a mark for each event.\\
+% The mandatory argument which is |true/false| decides if the internally
+% stored data used to typeset the calendar is being erased before this
+% environment.
+%
+% \DescribeMacro{\deadline} |\deadline[opts]|\\
+% |opts| are optional arguments (enclosed with |{}|) separated with |,|:
+% \begin{description}
+% \item[|date|] Date of the deadline formatted as |YYYY-MM-DD|
+% \item[|course|] Name of the course
+% \item[|prio|] priority of the event (shown in the table) (see
+% \ref{icons})
+% \item[|desc|] Description of the event (shown in the table)
+% \item[|draw|] |true/false| wether to draw a mark in the calendar
+% \item[|print|] |true/false| wether to display te entry in the
+% deadlines table.
+% \item[|shift|] |true/false| wether to shift the mark in the calendar if
+% there is already another event on that date (to be able to see both
+% marks)
+% \item[|tikz|] Free customizable tikz code used for drawing the mark
+% in the calendar. See the documentation at the end for keys that can
+% be used here (all keys in |/cal|). To simply pass arguments to the
+% tikz-node that is being created for the event use |tikz/.append={your arguments}|\\
+% Use e.g. to set the color of the mark via |tikz/.append={green}|
+% \end{description}
+%
+% \subsection{Icons}\label{icons}
+% This package defines some modified fontawesome icons (they are being
+% encircled with a white circle for better readability).\\
+% \begin{tabular}{rl|rl}
+% |\zoom| & \textcolor{DodgerBlue}{\faCamera} &
+% |\teams| & \textcolor{DodgerBlue}{\faWindows}
+% \\
+% |\BBB| & \textcolor{DodgerBlue}{\faBold} &
+% |\youtube| & \textcolor{DodgerBlue}{\faYoutubePlay}
+% \\\hline
+% |\pmandatory| & \textcolor{red}{\faWarning} &
+% |\phigh| & \textcolor{red}{\faFlag}
+% \\
+% |\pmid| & \textcolor{yellow}{\faFlag} &
+% |\plow| & \textcolor{green}{\faFlag}
+% \\
+% |\pnone| & \textcolor{gray}{\faTimesCircle}
+% \\ \hline
+% |\tbd| & \faQuestion &
+% |\tba| & \faBullhorn
+% \end{tabular}
+%
+%
+%
+% \newpage
+% \section{Implementation}
+% This package uses |semesterplannerLua| as prefix/directory where
+% possible. Since this is not possible for latex macro names, in this
+% occasions |semesterplannerLua@| is used as prefix.
+% \subsection{semesterplannerlua.sty}
+% \subsubsection{Global Stuff}
+% \begin{macrocode}
+%<*package>
+\RequirePackage{tikz}
+\usetikzlibrary{calendar, positioning, shapes.misc, backgrounds}
+\RequirePackage{pgfkeys}
+\RequirePackage{xcolor}
+\RequirePackage{fontawesome}
+\RequirePackage{luapackageloader} % use the default lua path as well
+% \end{macrocode}
+% Define some colors for the course types (can be globally overwritten)
+% \begin{macrocode}
+\definecolor{seminar}{rgb}{1.0, 0.8, 0.0}
+\definecolor{lecture}{rgb}{0.2, 0.7, 1.0}
+\definecolor{tutorial}{rgb}{0.0, 0.8, 0.0}
+\definecolor{meeting}{rgb}{0.8, 0.0, 0.0}
+\definecolor{officehour}{rgb}{0.0, 0.4, 0.6}
+\definecolor{DodgerBlue}{HTML}{1E90FF}
+% \end{macrocode}
+% \begin{macro}{\semesterplannerLua@encircle}
+% This macro puts a circle arround its argument for better readability. In
+% this package this is used for the fontawesome symbols.
+% \begin{macrocode}
+ \newcommand*{\semesterplannerLua@encircle}[1]{
+ \begin{minipage}[b][1em][c]{1.5em}
+ \begin{tikzpicture}
+ \node[fill,circle,inner sep=1pt, color = white] {#1};
+ \end{tikzpicture}
+ \end{minipage}
+ }
+% \end{macrocode}
+% \end{macro}
+% Commands for exams
+% \begin{macro}{\oral}
+% \begin{macrocode}
+\protected\def\oral{\faComment}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\written}
+% \begin{macrocode}
+\protected\def\written{\faPencil}
+% \end{macrocode}
+% \end{macro}
+% Commands for symbols of priority
+% \begin{macro}{\pmandatory}
+% \begin{macrocode}
+ \protected\def\pmandatory{\semesterplannerLua@encircle{\textcolor{red}{\faWarning}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\phigh}
+% \begin{macrocode}
+ \protected\def\phigh{\semesterplannerLua@encircle{\textcolor{red}{\faFlag}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\pmid}
+% \begin{macrocode}
+ \protected\def\pmid{\semesterplannerLua@encircle{\textcolor{yellow}{\faFlag}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\plow}
+% \begin{macrocode}
+ \protected\def\plow{\semesterplannerLua@encircle{\textcolor{green}{\faFlag}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\pnone}
+% \begin{macrocode}
+ \protected\def\pnone{\semesterplannerLua@encircle{\textcolor{gray}{\faTimesCircle}}}
+% \end{macrocode}
+% \end{macro}
+
+% Commands for online platforms.
+% \begin{macro}{\teams}
+% \begin{macrocode}
+ \protected\def\teams{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faWindows}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\zoom}
+% \begin{macrocode}
+ \protected\def\zoom{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faCamera}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\youtube}
+% \begin{macrocode}
+ \protected\def\youtube{\semesterplannerLua@encircle{\textcolor{red}{\faYoutubePlay}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\BBB}
+% \begin{macrocode}
+ \protected\def\BBB{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faBold}}}
+% \end{macrocode}
+% \end{macro}
+
+% Command for "To be determined" and "To be Announced"
+% \begin{macro}{\tbd}
+% \begin{macrocode}
+ \protected\def\tbd{\faQuestion}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\tba}
+% \begin{macrocode}
+ \protected\def\tba{\faBullhorn}
+% \end{macrocode}
+% \end{macro}
+
+
+% Load the lua modules
+% \begin{macrocode}
+\directlua{sp = require("semesterplannerLua_timetable.lua")}
+\directlua{cal = require("semesterplannerLua_calendar.lua")}
+% \end{macrocode}
+% Set all the pgfkeys required for the arguments. To achieve that the
+% defaults are restored every time the environment is used, this is
+% inside the environment definition. This of course disables all
+% possibilities of setting a global default but enables setting local
+% defaults for the events
+% \begin{macrocode}
+ \pgfkeys{
+% \end{macrocode}
+% |/semesterplannerLua| will be the pgf-path used for this package. Here
+% all used keys are set (and initialized with defaults. |timetable/env/|:
+% \begin{description}
+% \item[|days|] is a list of
+% strings representing the header names for the day columns in the
+% timetable (adding Sat and Sun (additional entries) will result in
+% two more columns.
+% \item[|start time|] can be used to set a fixed time where the timetable
+% starts (otherwise this is calculated from the entries) to enable
+% this behaviour this key has to be set to |HH*60 + MM| (easy way
+% is by using |start time/.evaluated={HH*60+MM}|)
+% \item[|end time|] equivalent to |start time|
+% \item[|width|] is
+% the horizontal width of the timetable (not including the column
+% headers on the top) this can be a latex length string or
+% |\textwidth| as well.
+% \item[|length|] is the vertical length of the
+% timetable (not including the clock labels on the side)
+% measured in cm (in future versions this may become measured in
+% pts for better interaction with the LaTeX lengths.
+% \end{description}
+% \begin{macrocode}
+ /semesterplannerLua/timetable/env/.cd,
+ days/.initial={Mon,Thue,Wend,Thur,Fri}, days/.default={Mon,Thue,Wend,Thur,Fri},
+ dayse/.initial={M,T,W,Th,F}, dayse/.default={M,T,W,Th,F},
+ %
+ start time/.initial=, start time/.default=,
+ end time/.initial=, end time/.default=,
+ %
+ width/.initial=\textwidth, width/.default=\textwidth,
+ length/.initial=10, length/.default=10,
+ %
+% \end{macrocode}
+% |timetable/event/|:
+% \begin{description}
+% \item[|content|] is the content of the event (is passed on without any
+% formatting). Since this is passed to lua without modification
+% its value must be an unexpanded string (lua will simply print
+% it so the eventually the string will be evaluated)
+% \item[|time|] is a |HH:MM-HH:MM| string representing start- and
+% end-time of the event. Used in constructing the content as well
+% \item[|day|] is either |M|,|T|,|W|,|Th| or |F| specifying the day on
+% which the event takes place
+% \item[|tikz|] this key allows the user to manually pass options to the
+% node created for this event
+% \item[|scale width|] allows to scale the width of the event to be able
+% to draw overlapping events besides each other. Will usually be a
+% value between |0| and |1|.
+% \item[|offset|] same goal like |scale width| but shifts the event node
+% by the given value to the right. (Given as value between |0| and
+% |1| indicating how many columns the event should be shifted)
+% \item[|textcolor|] foreground color of the content text
+% \item[|title|] title (set in bold by default)
+% \item[|speaker|]
+% \item[|location|]
+% \item[|prio|]
+% \item[|formatter|] this is special
+% \end{description}
+% \begin{macrocode}
+ /semesterplannerLua/timetable/event/.cd,
+ % event arguments
+ content/.initial=, content/.default=,
+ %
+ time/.initial=, time/.default=,
+ day/.initial=, day/.default=,
+ %
+ tikz/.initial=, tikz/.default=,
+ scale width/.initial=1, scale width/.default=1,
+ offset/.initial=0, offset/.default=0,
+ %
+ textcolor/.initial=, textcolor/.default=,
+ title/.initial=, title/.default=,
+ speaker/.initial=, speaker/.default=,
+ location/.initial=, location/.default=,
+ password/.initial=, password/.default=,
+ prio/.initial=, prio/.default=,
+ type/.initial=, type/.default=,
+ formatter/.initial=timetableformatter, formatter/.default=timetableformatter,
+ %
+% \end{macrocode}
+% |calendar/|:
+% \begin{description}
+% \item[|draw|]
+% \item[|room|]
+% \item[|prio|]
+% \item[|course|]
+% \item[|desc|]
+% \item[|start|]
+% \item[|end|]
+% \item[|tikz|]
+% \item[|period|]
+% \item[|shift|]
+% \item[|print|] Only makes sence if the command is suffixed by a |%|
+% otherwise somehow a space gets inserted (eventhough the |%| is
+% inserted from lua as well
+% \end{description}
+% \begin{macrocode}
+ /semesterplannerLua/calendar/.cd,
+ draw/.initial={true}, draw/.default={true},
+ room/.initial={}, room/.default={},
+ time/.initial={}, time/.default={},
+ prio/.initial={}, prio/.default={},
+ course/.initial={}, course/.default={},
+ desc/.initial={}, desc/.default={},
+ type/.initial={}, type/.default={},
+ date/.initial={}, date/.default={},
+ end/.initial={}, end/.default={},
+ tikz/.initial={}, tikz/.default={},
+ period/.initial={nil}, period/.default={nil},
+ shift/.initial={true}, shift/.default={true},
+ print/.initial={true}, print/.default={true},
+ }
+% \end{macrocode}
+%
+% \subsection{Tikz Calendar add weekday labels}
+% \begin{macrocode}
+\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
+\tikzstyle{day heading}=[]
+\tikzstyle{day letter headings}=[
+ execute before day scope={ \ifdate{day of month=1}{%
+ \pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}%
+ \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
+ \pgftransformyshift{-\pgf@ya}
+ \foreach \d/\l in {0/M,1/T,2/W,3/T,4/F,5/S,6/S} {
+ \pgf@xa=\d\pgf@xa%
+ \pgftransformxshift{\pgf@xa}%
+ \pgftransformyshift{\pgf@ya}%
+ \node[every day,day heading]{\l};%
+ }
+ }{}%
+ }%
+]
+% \end{macrocode}
+%
+% \subsubsection{Local Stuff (timetable-env local)}
+% \begin{environment}{timetable}
+% This is the environment doing all the stuff. To gate the positions where
+% the corresponding macros can be used (and in terms of pgfkeys for reasons
+% of default values) all the macros used are put into the environment.
+% \begin{macrocode}
+\newenvironment{timetable}[1][]{
+ \section*{\faClockO~Timetable}
+% \end{macrocode}
+%
+% Read the argumens given by the user after restoring the defaults
+% (Restoring currently makes no sense, since they are created a few
+% lines above anyways, but creation might be moved outside the
+% environment some day.\\
+% Afterwards the lua module is beeing initialized (erase data from
+% possible previous runs.
+% \begin{macrocode}
+ \pgfkeys{/semesterplannerLua/timetable/env/.cd, days,dayse, start time,end time, width,length, #1}
+ \directlua{sp.init{
+ days=[[\pgfkeysvalueof{/semesterplannerLua/timetable/env/days}]],
+ min=[[\pgfkeysvalueof{/semesterplannerLua/timetable/env/start time}]],
+ max=[[\pgfkeysvalueof{/semesterplannerLua/timetable/env/end time}]],
+ dayse=[[\pgfkeysvalueof{/semesterplannerLua/timetable/env/dayse}]]}}
+% \end{macrocode}
+% \begin{macro}{\semesterplannerLua@event}
+% Is used to pass the event to the lua engine which in turn will collect
+% the event to draw it in the end. For that the arguments given are parsed
+% after restoring the pgf keys to their default values. The optional
+% argument herby is a sequence of pgf keys, the second argument is
+% a string representing the content (this MUST be unexpanded since
+% this is passed to lua which in turn will pass it unmodified back)
+% \begin{macrocode}
+ \newcommand{\semesterplannerLua@event}[1][]{
+ \pgfkeys{/semesterplannerLua/timetable/event/.cd,content,time,day,tikz,scale
+ width,offset,textcolor,title,speaker,type,location,password,prio,formatter, ##1}
+ \directlua{
+ sp.addEvent{
+ time="\pgfkeysvalueof{/semesterplannerLua/timetable/event/time}",
+ day="\pgfkeysvalueof{/semesterplannerLua/timetable/event/day}",
+ tikz=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/tikz}]],
+ offset=\pgfkeysvalueof{/semesterplannerLua/timetable/event/offset},
+ scale_width=\pgfkeysvalueof{/semesterplannerLua/timetable/event/scale width},
+ formatter=\pgfkeysvalueof{/semesterplannerLua/timetable/event/formatter},
+ textcolor=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/textcolor}]],
+ title=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/title}]],
+ speaker=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/speaker}]],
+ location=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/location}]],
+ password=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/password}]],
+ prio=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/prio}]],
+ type=[[\pgfkeysvalueof{/semesterplannerLua/timetable/event/type}]],
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% Short-hand macros for different events using the corresponding
+% background color
+%
+% \begin{macro}{\lecture}
+% \begin{macrocode}
+ \newcommand{\lecture}[1][]{
+ \semesterplannerLua@event[tikz={fill=lecture,}, textcolor=white, type=lect, ##1]
+ \ignorespaces
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\seminar}
+% \begin{macrocode}
+ \newcommand{\seminar}[1][]{
+ \semesterplannerLua@event[tikz={fill=seminar,}, textcolor=white, type=sem, ##1]
+ \ignorespaces
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\tutorial}
+% \begin{macrocode}
+ \newcommand{\tutorial}[1][]{
+ \semesterplannerLua@event[tikz={fill=tutorial,}, textcolor=white, type=tut, ##1]
+ \ignorespaces
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\meeting}
+% \begin{macrocode}
+ \newcommand{\meeting}[1][]{
+ \semesterplannerLua@event[tikz={fill=meeting,}, textcolor=white, type=meet, ##1]
+ \ignorespaces
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\officehour}
+% \begin{macrocode}
+ \newcommand{\officehour}[1][]{
+ \semesterplannerLua@event[tikz={fill=officehour,}, textcolor=white, type=office, ##1]
+ \ignorespaces
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+}{
+% \end{macrocode}
+% At the end of the environment after all events have been collected,
+% generate and output the tikz code needed to draw the timetable.
+% \begin{macrocode}
+ \directlua{sp.draw(
+ [[\pgfkeysvalueof{/semesterplannerLua/timetable/env/length}]],
+ [[\pgfkeysvalueof{/semesterplannerLua/timetable/env/width}]])}
+}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macrocode}
+
+% \end{macrocode}
+% \begin{macro}{printSpCalendar}
+% Print a calendar from startDate to endDate (encoded as YYYY-MM-DD) as
+% one calendar per month in a matrix with the given amount of columns
+% \begin{macrocode}
+\newcommand{\printSpCalendar}[3][3]{\directlua{cal.drawCalendar("#2", "#3", #1)}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+
+\newenvironment{appointments}[2][Room]{
+ \directlua{cal.init(#2)}
+ \newcommand{\appointment}[1][]{%
+ \pgfkeys{/semesterplannerLua/calendar/.cd,draw,room,time,prio,course,desc,date,end,tikz,period,type,shift,print, ##1}%
+ \directlua{
+ cal.addAppointment{draw=\pgfkeysvalueof{/semesterplannerLua/calendar/draw},
+ room=[[\pgfkeysvalueof{/semesterplannerLua/calendar/room}]],
+ time=[[\pgfkeysvalueof{/semesterplannerLua/calendar/time}]],
+ prio=[[\pgfkeysvalueof{/semesterplannerLua/calendar/prio}]],
+ course=[[\pgfkeysvalueof{/semesterplannerLua/calendar/course}]],
+ desc=[[\pgfkeysvalueof{/semesterplannerLua/calendar/desc}]],
+ date=[[\pgfkeysvalueof{/semesterplannerLua/calendar/date}]],
+ endDate=[[\pgfkeysvalueof{/semesterplannerLua/calendar/end}]],
+ tikz=[[\pgfkeysvalueof{/semesterplannerLua/calendar/tikz}]],
+ period=\pgfkeysvalueof{/semesterplannerLua/calendar/period},
+ shift=\pgfkeysvalueof{/semesterplannerLua/calendar/shift},
+ print=\pgfkeysvalueof{/semesterplannerLua/calendar/print}}}%
+ \ignorespaces
+ }
+ \section*{\faCalendar~Appointments}
+ \begin{tabular}{rlllll}
+ \textbf{Date}&\textbf{Time}&\textbf{Course}&\textbf{Description}&\textbf{#1}&\textbf{Prio.}\\
+}{
+ \end{tabular}
+}
+
+\newenvironment{exams}[1]{
+ \directlua{cal.init(#1)}
+ \newcommand{\exam}[1][]{%
+ \pgfkeys{/semesterplannerLua/calendar/.cd,draw,room,time,prio,course,desc,date,end,tikz,period,type,shift,print, ##1}%
+ \directlua{
+ cal.addExam{
+ draw=\pgfkeysvalueof{/semesterplannerLua/calendar/draw},
+ room=[[\pgfkeysvalueof{/semesterplannerLua/calendar/room}]],
+ time=[[\pgfkeysvalueof{/semesterplannerLua/calendar/time}]],
+ course=[[\pgfkeysvalueof{/semesterplannerLua/calendar/course}]],
+ desc=[[\pgfkeysvalueof{/semesterplannerLua/calendar/desc}]],
+ date=[[\pgfkeysvalueof{/semesterplannerLua/calendar/date}]],
+ tikz=[[\pgfkeysvalueof{/semesterplannerLua/calendar/tikz}]],
+ type=[[\pgfkeysvalueof{/semesterplannerLua/calendar/type}]],
+ shift=\pgfkeysvalueof{/semesterplannerLua/calendar/shift},
+ print=\pgfkeysvalueof{/semesterplannerLua/calendar/print}}}%
+ \ignorespaces
+ }
+ \section*{\faStickyNoteO~Exams}
+ \begin{tabular}{rllll}
+ \textbf{Date}&\textbf{Time}&\textbf{Course}&\textbf{Type}&\textbf{Note}\\
+}{
+ \end{tabular}
+}
+
+\newenvironment{deadlines}[1]{
+ \directlua{cal.init(#1)}
+ \newcommand{\deadline}[1][]{%
+ \pgfkeys{/semesterplannerLua/calendar/.cd,draw,room,time,prio,course,desc,date,end,tikz,period,type,shift,print, ##1}%
+ \directlua{
+ cal.addDeadline{
+ draw=\pgfkeysvalueof{/semesterplannerLua/calendar/draw},
+ course=[[\pgfkeysvalueof{/semesterplannerLua/calendar/course}]],
+ desc=[[\pgfkeysvalueof{/semesterplannerLua/calendar/desc}]],
+ date=[[\pgfkeysvalueof{/semesterplannerLua/calendar/date}]],
+ tikz=[[\pgfkeysvalueof{/semesterplannerLua/calendar/tikz}]],
+ prio=[[\pgfkeysvalueof{/semesterplannerLua/calendar/prio}]],
+ shift=\pgfkeysvalueof{/semesterplannerLua/calendar/shift},
+ print=\pgfkeysvalueof{/semesterplannerLua/calendar/print}}}%
+ \ignorespaces
+ }
+ \section*{\faStickyNoteO~Deadlines}
+ \begin{tabular}{rlll}
+ \textbf{Date}&\textbf{Course}&\textbf{Description}&\textbf{Prio}\\
+}{
+ \end{tabular}
+}
+% \end{macrocode}
+\endinput
+%
+% \iffalse
+%</package>
+% \fi
+%
+% \Finale
+\endinput
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua.ins b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.ins
new file mode 100644
index 0000000000..d6815fbc1b
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.ins
@@ -0,0 +1,59 @@
+%% Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+%% --------------------------------------------------------------------------
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Lukas Heindl.
+%%
+%% This work consists of the files semesterplannerlua.dtx and semesterplannerlua.ins
+%% and the derived filebase semesterplannerlua.sty.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/semesterplannerLua}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2024 by Lukas Heindl <oss.heindl+latex@protonmail.com>
+--------------------------------------------------------------------------
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+\endpreamble
+
+\generate{
+ \file{semesterplannerlua.sty}{\from{semesterplannerlua.dtx}{package}}
+}
+
+\obeyspaces
+\Msg{***********************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* semesterplannerlua.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file semesterplannerlua.dtx *}
+\Msg{* through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{***********************************************************************}
+
+\endbatchfile
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua.pdf b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.pdf
new file mode 100644
index 0000000000..40ee78f8a3
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua.pdf
Binary files differ
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua_calendar.lua b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_calendar.lua
new file mode 100644
index 0000000000..f2fa0e5e32
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_calendar.lua
@@ -0,0 +1,132 @@
+local dateLib = require "date"
+function init(clear)
+ -- clean up first
+ -- global variable
+ if clear then
+ EVENTS = {}
+ end
+end
+
+text = {
+ print = function(s)
+ -- print("\"" .. s .. "\"")
+ tex.print(s)
+ end
+}
+
+function genDot(opts)
+ dot = ""
+ if opts.draw then
+ dot = string.format([[\tikz[baseline=(X.base)]\node (X) [fill opacity=.5,fill=red,circle,inner sep=0mm, %s] {\phantom{D}};]], opts.tikz)
+ end
+ return dot
+end
+
+function addEvent(opts)
+ opts.inputlineno = tex.inputlineno
+ -- print(string.format("collecting from line %d", opts.inputlineno))
+ if opts.draw then
+ assert(opts.date ~= nil and opts.tikz ~= nil, "date and tikz has to be given")
+ if opts.endDate == nil or opts.endDate == '' then
+ table.insert(EVENTS, {shift=opts.shift,date=dateLib(opts.date), tikz=opts.tikz, period=opts.period, endDate=nil, inputlineno=opts.inputlineno})
+ else
+ table.insert(EVENTS, {shift=opts.shift,date=dateLib(opts.date), tikz=opts.tikz, period=opts.period, endDate=dateLib(opts.endDate), inputlineno=opts.inputlineno})
+ end
+ end
+end
+
+function addAppointment(opts)
+ addEvent(opts)
+ dot = genDot(opts)
+ if opts.print then
+ tex.sprint(string.format([[\textit{%s} & %s & %s%s & %s & %s & %s\\]], opts.date, opts.time, dot, opts.course, opts.desc, opts.room, opts.prio))
+ else
+ tex.sprint("%")
+ end
+end
+
+function addExam(opts)
+ addEvent(opts)
+ dot = genDot(opts)
+ if opts.print then
+ tex.sprint(string.format([[\textit{%s} & %s & %s%s & %s & %s \\]], opts.date, opts.time, dot, opts.course, opts.type, opts.desc))
+ else
+ tex.sprint("%")
+ end
+end
+
+function addDeadline(opts)
+ addEvent(opts)
+ dot = genDot(opts)
+ if opts.print then
+ tex.sprint(string.format([[\textit{%s} & %s%s & %s & %s \\]], opts.date, dot, opts.course, opts.desc, opts.prio))
+ else
+ tex.sprint("%")
+ end
+end
+
+function drawCalendar(minDate, maxDate, cols)
+ minDate = dateLib(minDate)
+ maxDate = dateLib(maxDate)
+ text.print([[\begin{tikzpicture}[every calendar/.style={day headings=red!50,day letter headings,inner sep=2pt, week list, month label above centered, month text={\textcolor{red}{\%mt} \%y-}, every month/.style={yshift=3ex}}] ]])
+ text.print([[\matrix[column sep=1em, row sep=1em]{]])
+ local i = 1
+ running = true
+ while running do
+ -- derive end from start, then check if maxDate is reached
+ endDate = minDate:copy():addmonths(1):setday(1):adddays(-1)
+ if endDate >= maxDate then
+ endDate = maxDate
+ running = false
+ end
+ text.print(string.format(
+ [[\calendar (%04d-%02d) [dates=%04d-%02d-%02d to %04d-%02d-%02d] if (Sunday) [red] if (Saturday) [red!50!white] if (equals=\year-\month-\day) [nodes={inner sep=.25em,rectangle,line width=1pt,draw}] if (at least=\year-\month-\day) {} else [nodes={strike out, draw}]; ]],
+ minDate:getyear(), minDate:getmonth(), minDate:getyear(), minDate:getmonth(), minDate:getday(), endDate:getyear(), endDate:getmonth(), endDate:getday()))
+
+ minDate:addmonths(1)
+ minDate:setday(1)
+
+ if i % cols == 0 or not running then
+ text.print([[\\]])
+ else
+ text.print([[&]])
+ end
+ i = i + 1
+ end
+ text.print([[ }; ]])
+
+ local usedDates = {}
+ text.print([[\begin{scope}[on background layer] ]])
+ for i,ele in ipairs(EVENTS) do
+ -- print(string.format("Drawing item from line %d", ele.inputlineno))
+ while ele.date <= maxDate and (ele.endDate == nil or ele.date <= ele.endDate) do
+ local xshift = 0
+ if ele.shift then
+ if usedDates[tostring(ele.date)] ~= nil then
+ xshift = math.ceil(usedDates[tostring(ele.date)] / 2)
+ if usedDates[tostring(ele.date)] % 2 == 0 then
+ xshift = -xshift
+ end
+ usedDates[tostring(ele.date)] = usedDates[tostring(ele.date)] + 1
+ else
+ usedDates[tostring(ele.date)] = 1
+ end
+ end
+ text.print(string.format([[\node[xshift=%d mm, fill opacity=.5,fill=red,circle,text width=0ex,inner sep=1.1ex, %s] at (%04d-%02d-%04d-%02d-%02d) {};]],
+ xshift, ele.tikz, ele.date:getyear(), ele.date:getmonth(), ele.date:getyear(), ele.date:getmonth(), ele.date:getday()))
+ if ele.period == nil then break end
+ ele.date:adddays(ele.period)
+ end
+ end
+ text.print([[\end{scope}]])
+ text.print([[\end{tikzpicture}]])
+end
+
+semesterplannerLuaCal = {
+ init = init,
+ addAppointment = addAppointment,
+ addDeadline = addDeadline,
+ addExam = addExam,
+ drawCalendar = drawCalendar,
+}
+return semesterplannerLuaCal
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua_dmenu.lua b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_dmenu.lua
new file mode 100644
index 0000000000..d267d68071
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_dmenu.lua
@@ -0,0 +1,156 @@
+#!/usr/bin/env texlua
+
+----------------------
+-- HELPER_FUNCTIONS --
+----------------------
+local function check_installed(prog)
+ local r = os.execute("which " .. prog .. "&> /dev/null")
+ return r
+end
+
+local function help()
+ print("Displays a dmenu prompt with the last, current and next events and copies location/url [+password] to the clipboard")
+ print()
+ print("USAGE:")
+ print(string.format("\t%s dataFile [ignoreType ...]", arg[0]))
+ print()
+ print("OPTIONS:")
+ print()
+ print("ARGS:")
+ print(string.format("\t%-12s\t%s", "<dataFile>", "path to the input csv file with 'start', 'end', 'title', 'location', 'password', 'type' headers (not written in the file)"))
+ print(string.format("\t%-12s\t%s", "", "location may contain '\\href{location}{url}' in which casethe two fields are extracted"))
+ print(string.format("\t%-12s\t%s", "<ignoreType>", "entries with that type are ignored"))
+end
+
+local function dur2str(dur)
+ return string.format("%02d:%02d", dur//60, dur%60)
+end
+
+local function contains(t, ele)
+ for _,v in pairs(t) do
+ if v == ele then return true end
+ end
+ return false
+end
+
+-------------------
+-- PREREQUISITES --
+-------------------
+if not check_installed("dmenu") then
+ print("Error: dmenu has to be installed (options -l, -i and -p required, but these are in the default anyway)")
+ os.exit(-1)
+end
+if not check_installed("xsel") then
+ print("Error: xsel has to be installed")
+ os.exit(-1)
+end
+
+if #arg < 1 then
+ print("Error: At least one argument has to be given")
+ print()
+ help()
+ os.exit(-1)
+end
+if arg[1] == "-h" or arg[1] == "--help" then
+ help()
+ os.exit(0)
+end
+
+local type_exclude = {}
+for i=1,#arg do
+ table.insert(type_exclude, arg[i])
+end
+
+-----------
+-- MAIN --
+----------
+
+local maxes = {title=0, location=0, type=0}
+
+local before = {diff=25*60*7}
+local after = {diff=25*60*7}
+
+local c = {}
+
+local current = os.date("*t")
+local today = tonumber(os.date("%u")) - 1
+current.minutes = current.min + (today*24 + current.hour)*60
+
+local inputs = loadfile(arg[1], "t", {})() -- easy loading comes with the disadvantage that arbitrary code which is in that file gets executed
+for _,ele in ipairs(inputs) do
+ if not contains(type_exclude, ele["type"]) then
+ ele.start, ele["end"] = tonumber(ele.start), tonumber(ele["end"])
+ ele.url = ele.location:match([[\href ?{(.*)}{.*}]])
+ ele.location = ele.location:match([[\href ?{.*}{(.*)}]]) or ele.location
+
+ if maxes.title < #ele.title then maxes.title = #ele.title end
+ if maxes.location < #ele.location then maxes.location = #ele.location end
+ if maxes.type < #ele.type then maxes.type = #ele.type end
+
+ if current.minutes > ele.start and current.minutes < ele["end"] then
+ ele.diff = current.minutes-ele["start"]
+ table.insert(c, ele)
+ elseif current.minutes < ele.start then
+ if ele.start - current.minutes < before.diff then
+ before = {diff=ele.start-current.minutes}
+ end
+ if ele.start - current.minutes <= before.diff then
+ ele.diff = before.diff
+ table.insert(before, ele)
+ end
+ elseif current.minutes > ele["end"] then
+ if current.minutes - ele["end"] < after.diff then
+ after = {diff=current.minutes-ele["end"]}
+ end
+ if current.minutes - ele["end"] <= after.diff then
+ ele.diff = after.diff
+ table.insert(after, ele)
+ end
+ end
+ end
+end
+
+maxes = {title=maxes.title < 100 and maxes.title or 99, location=maxes.location < 100 and maxes.location or 99, type=maxes.type < 100 and maxes.type or 99}
+
+local dmenu_in,map = {},{}
+for _,x in ipairs(after) do
+ local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # ended %s ago", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
+ table.insert(dmenu_in, s)
+ map[s] = x
+end
+
+for _,x in ipairs(c) do
+ local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # began %s ago", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
+ table.insert(dmenu_in, s)
+ map[s] = x
+end
+
+for _,x in ipairs(before) do
+ local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # begins in %s", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
+ table.insert(dmenu_in, s)
+ map[s] = x
+end
+
+local dmenu_ins = table.concat(dmenu_in, "\n")
+
+print(dmenu_ins)
+-- TODO check for forbidden strings in dmenu_in
+local proc = io.popen(string.format("echo '%s' | dmenu -i -l %d -p 'Select entry'", dmenu_ins, #dmenu_in), "r")
+local dmenu_out = proc:read("l")
+if not dmenu_out then
+ os.execute("notify-send 'Uni' 'Nothing selected'")
+ os.exit()
+end
+
+local sel = map[dmenu_out]
+assert(sel, "Error building/reading the lookup table")
+if sel.url and sel.url ~= "" then
+ os.execute(string.format("echo -n '%s' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied URL to clipboard'", sel.url))
+elseif sel.location and sel.location ~= "" then
+ os.execute(string.format("echo -n '%s' | xsel -b && notify-send -h -- string:x-canonical-private-synchronous:uni 'Uni' 'Copied URL to clipboard'", sel.location))
+ os.execute(string.format("echo -n 'https://portal.mytum.de/campus/roomfinder/search_room_results?searchstring=%s&building=Alle&search=Suche+starten' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied Roomfinder-url to clipboard'", sel.location))
+end
+
+if sel.password and sel.password ~= "" then
+ os.execute(string.format("sleep 3 && echo -n '%s' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied password to clipboard'", sel.password))
+end
diff --git a/macros/luatex/latex/semesterplannerlua/semesterplannerlua_timetable.lua b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_timetable.lua
new file mode 100644
index 0000000000..049644d291
--- /dev/null
+++ b/macros/luatex/latex/semesterplannerlua/semesterplannerlua_timetable.lua
@@ -0,0 +1,233 @@
+function init(opts)
+ tex.print([[\newwrite\timetableATdataOutput \immediate\openout\timetableATdataOutput=\jobname-data.dat]])
+ tex.print([[\immediate\write\timetableATdataOutput{return \iftrue\string{\else}\fi}]])
+ if(not checkKeys(opts, {"days", "min", "max", "dayse"})) then
+ error("missing argument")
+ end
+ -- clean up first
+ -- global variables
+ EVENTS={}
+ DAYS = prepareDays(opts.days) -- header with names of the days set from tex currently
+ DAYSE = prepareDays(opts.dayse) -- day representation in source code
+ MIN = 25*60 -- bigger than any allowed value could be
+ MAX = 0
+ MIN_BYPASS = false -- weather min is fixed by the user
+ MAX_BYPASS = false -- weather max is fixed by the user
+
+ if(opts.min == "") then
+ else
+ assert(opts.min:match("^%d+"), "start time has to be an integer representing the HH*60+MM of the desired start time")
+ MIN = tonumber(opts.min)
+ MIN_BYPASS = true
+ end
+
+ if(opts.max == "") then
+ else
+ assert(opts.max:match("^%d+"), "end time has to be an integer representing the HH*60+MM of the desired end time")
+ MAX = tonumber(opts.max)
+ MAX_BYPASS = true
+ end
+end
+
+function defaultFormatter(opts)
+ local ret = ""
+ for k,v in pairs(opts) do
+ if type(k) == "string" then k = k:gsub("[_^]", "") end
+ if type(v) == "string" then v = v:gsub("[_^]", "") end
+ ret = string.format("%s, %s: %s", ret, tostring(k), tostring(v))
+ end
+ -- print(ret)
+ return ret
+end
+
+function timetableformatter(opts)
+ return string.format(
+ [[\textcolor{%s}{\textbf{%s}\\[.2em]\raggedright{%s}\\[0.5em]\raggedright{%s}\hfil\raggedright{%s}\\[0.5em]\raggedright{%s}}]],
+ opts.textcolor, opts.title, opts.speaker, opts.prio, opts.location, opts.time)
+end
+-- result are the global variables EVENTS, MIN and MAX
+function addEvent(opts)
+ -- print("Reading event on line ", tex.inputlineno)
+ opts.inputlineno = tex.inputlineno
+ if(not checkKeys(opts, {"time", "day", "tikz"})) then
+ error("missing argument")
+ end
+
+ if opts.content == nil then
+ if opts.formatter == nil then
+ opts.content = defaultFormatter(opts)
+ else
+ opts.content = opts.formatter(opts)
+ end
+ end
+
+ opts.from,opts.to = dur2Int(opts.time)
+
+ tex.print(string.format(
+ [[\immediate\write\timetableATdataOutput{\unexpanded{{["start"]=%q, ["end"]=%q, ["title"]=%q, ["location"]=%q, ["password"]=%q, ["type"]=%q},}}]],
+ opts.from + 24*60*day2Int(opts.day),
+ opts.to + 24*60*day2Int(opts.day),
+ opts.title,
+ opts.location:match([[\href{(.*)}{.*}]]) or opts.location,
+ opts.password,
+ opts.type
+ ))
+
+ if(not MIN_BYPASS and opts.from < MIN) then MIN = opts.from end
+ if(not MAX_BYPASS and opts.to > MAX) then MAX = opts.to end
+ assert(opts.from < opts.to, "From has to be before to")
+
+ table.insert(EVENTS, opts)
+end
+-- parameters are all global variables
+function draw(length, width)
+ -- copy relevant variables for working on local copies
+ local events = copy_array(EVENTS)
+ local days = copy_array(DAYS)
+ local min, minH, max, maxH = prepareMinMax(MIN, MAX)
+
+ assert(length:match("%d*%.?%d*"), "Length must be a valid length measured in cm")
+ length = tonumber(length)
+
+ textwidth = width
+
+ tex.print([[\begin{tikzpicture}]])
+ tex.print([[\tikzset{defStyle/.style={font=\tiny,anchor=north west,fill=blue!50,draw=black,rectangle}}]])
+ -- print the tabular with the weekday headers
+ tex.print(string.format(
+ [[\foreach \week [count=\x from 0, evaluate=\x as \y using \x+0.5] in {%s}{ ]],
+ table.concat(days, ",")
+ )
+ )
+ tex.print(string.format(
+ [[\node[anchor=south] at (\y/%d* %s, 0) {\week};]], #days, textwidth))
+ tex.print(string.format(
+ [[\draw (\x/%d * %s, 0cm) -- (\x/%d * %s, %dcm);]],
+ #days,
+ textwidth,
+ #days,
+ textwidth, -length
+ )
+ )
+ tex.print("}")
+ tex.print(string.format(
+ [[\draw (%s, 0) -- (%s,%dcm);]],
+ textwidth,
+ textwidth,
+ -length
+ )
+ )
+
+ for i=minH,maxH do
+ tex.print(string.format(
+ [[\node[anchor=east] at (0,%fcm ) {%d:00};]],
+ minuteToFrac(i*60,min,max)*-length, i
+ )
+ )
+ tex.print(string.format(
+ [[\draw (0,%fcm ) -- (%s,%fcm );]],
+ minuteToFrac(i*60,min,max)*-length,
+ textwidth,
+ minuteToFrac(i*60,min,max)*-length
+ )
+ )
+ end
+
+ local d
+ local red = 0.3333 -- calculated in em from inner sep
+ local red_y = 0.25 -- calculated in em
+ for _,e in ipairs(events) do
+ if e.from < max and e.to > min then -- only draw if event is in scope (part of the comp is done in addEvent from < to
+ if e.to > max then e.to = max end
+ if e.from < min then e.from = min end
+ -- print("Drawing event on line ", e.inputlineno)
+ d = day2Int(e.day)
+ tex.print(string.format(
+ [[\node[defStyle,text width=-%fem+%f%s/%d, text depth=%fcm-%fem, text height=%fem, %s] at (%f*%s,%fcm) {%s};]],
+ 2*red, -- text width
+ e.scale_width, -- text width
+ textwidth,
+ #days, -- text width
+ length*(e.to-e.from)/(max-min), -- text depth
+ 2*red+red_y, -- text depth
+ red_y, -- text height
+ e.tikz, -- free tikz code
+ (d+e.offset)/#days, -- xcoord
+ textwidth,
+ minuteToFrac(e.from,min,max)*-length, -- ycoord
+ e.content -- content
+ )
+ )
+ end
+ end
+ tex.print([[\end{tikzpicture}]])
+ tex.print([[\immediate\write\timetableATdataOutput{\iffalse{\else\string}\fi}]])
+end
+function search_array(t, s)
+ for k,v in ipairs(t) do
+ if(v == s) then return k end
+ end
+ return nil
+end
+
+function minuteToFrac(minute, min, max)
+ return (minute-min)/(max-min)
+end
+function prepareMinMax(min, max)
+ local minH = math.floor(min/60)
+ local maxH = math.ceil(max/60)
+ local min = minH*60
+ local max = maxH*60
+ return min, minH, max, maxH
+end
+function checkKeys(t, k)
+ for _,x in ipairs(k) do
+ if(t[x] == nil) then
+ return false
+ end
+ end
+ return true
+end
+function dur2Int(clk)
+ local f1,f2, t1,t2 = clk:match("^(%d%d?):(%d%d)-(%d%d?):(%d%d)$")
+ if(f1 ~= nil and f2 ~= nil and t1 ~= nil and t2 ~= nil) then
+ f1 = tonumber(f1) f2 = tonumber(f2)
+ t1 = tonumber(t1) t2 = tonumber(t2)
+ assert(f1 >= 0 and f1 < 24, "Hours have to be >= 0 && < 24")
+ assert(f2 >= 0 and f2 < 60, "Mins have to be >= 0 && < 60")
+ assert(t1 >= 0 and t1 < 24, "Hours have to be >= 0 && < 24")
+ assert(t2 >= 0 and t2 < 60, "Mins have to be >= 0 && < 60")
+ return f1*60 + f2, t1*60 + t2
+ else
+ error("clk string \"" .. clk .. "\" was no valid clock string")
+ end
+end
+function prepareDays(days)
+ local ret = {}
+ for m in days:gmatch("[^,]+") do
+ table.insert(ret, m)
+ end
+ return ret
+end
+function day2Int(day)
+ return search_array(DAYSE, day) - 1
+end
+
+function copy_array(obj)
+ if type(obj) ~= 'table' then return obj end
+ local res = {}
+ for k, v in pairs(obj) do
+ local c = copy_array(v)
+ res[copy_array(k)] = c
+ end
+ return res
+end
+
+semesterplannerLua = {
+ init = init,
+ addEvent = addEvent,
+ draw = draw,
+ day2Int = day2Int,
+}
+return semesterplannerLua
+