From 817e8be51a21e1d0762d900503d0eb42de901851 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 19 May 2024 20:36:35 +0000 Subject: semesterplannerlua (19may24) git-svn-id: svn://tug.org/texlive/trunk@71305 c570f23f-e606-0410-a88d-b1316a301751 --- .../doc/lualatex/semesterplannerlua/README.md | 43 + .../semesterplannerlua/semesterplannerlua.pdf | Bin 0 -> 144336 bytes .../semesterplannerlua/semesterplannerlua.dtx | 885 +++++++++++++++++++++ .../semesterplannerlua/semesterplannerlua.ins | 59 ++ .../semesterplannerlua/semesterplannerlua.sty | 256 ++++++ .../semesterplannerlua_calendar.lua | 132 +++ .../semesterplannerlua_dmenu.lua | 156 ++++ .../semesterplannerlua_timetable.lua | 233 ++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/tlpsrc/collection-luatex.tlpsrc | 1 + Master/tlpkg/tlpsrc/semesterplannerlua.tlpsrc | 0 11 files changed, 1766 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/lualatex/semesterplannerlua/README.md create mode 100644 Master/texmf-dist/doc/lualatex/semesterplannerlua/semesterplannerlua.pdf create mode 100644 Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.dtx create mode 100644 Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.ins create mode 100644 Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua.sty create mode 100644 Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_calendar.lua create mode 100644 Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_dmenu.lua create mode 100644 Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_timetable.lua create mode 100644 Master/tlpkg/tlpsrc/semesterplannerlua.tlpsrc diff --git a/Master/texmf-dist/doc/lualatex/semesterplannerlua/README.md b/Master/texmf-dist/doc/lualatex/semesterplannerlua/README.md new file mode 100644 index 00000000000..d7049942cb8 --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/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/Master/texmf-dist/doc/lualatex/semesterplannerlua/semesterplannerlua.pdf b/Master/texmf-dist/doc/lualatex/semesterplannerlua/semesterplannerlua.pdf new file mode 100644 index 00000000000..40ee78f8a3d Binary files /dev/null and b/Master/texmf-dist/doc/lualatex/semesterplannerlua/semesterplannerlua.pdf differ diff --git a/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.dtx b/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.dtx new file mode 100644 index 00000000000..8341981afd2 --- /dev/null +++ b/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.dtx @@ -0,0 +1,885 @@ +% \iffalse meta-comment +% +% Copyright (C) 2024 by Lukas Heindl +% --------------------------------------------------------------------------- +% 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} +% +%\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%\ProvidesPackage{semesterplannerlua} +%<*package> + [2024/05/19 v1.1.1 Semesterplanner package in lua with tikz only] +% +% +%<*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} +% +% \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 +% +% \fi +% +% \Finale +\endinput diff --git a/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.ins b/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.ins new file mode 100644 index 00000000000..d6815fbc1bb --- /dev/null +++ b/Master/texmf-dist/source/lualatex/semesterplannerlua/semesterplannerlua.ins @@ -0,0 +1,59 @@ +%% Copyright (C) 2024 by Lukas Heindl +%% -------------------------------------------------------------------------- +%% 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 +-------------------------------------------------------------------------- +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/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua.sty b/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua.sty new file mode 100644 index 00000000000..deb287c5b07 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua.sty @@ -0,0 +1,256 @@ +%% +%% This is file `semesterplannerlua.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% semesterplannerlua.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright (C) 2024 by Lukas Heindl +%% -------------------------------------------------------------------------- +%% 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. +%% +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{semesterplannerlua} + [2024/05/19 v1.1.1 Semesterplanner package in lua with tikz only] + +\RequirePackage{tikz} +\usetikzlibrary{calendar, positioning, shapes.misc, backgrounds} +\RequirePackage{pgfkeys} +\RequirePackage{xcolor} +\RequirePackage{fontawesome} +\RequirePackage{luapackageloader} % use the default lua path as well +\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} + \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} + } +\protected\def\oral{\faComment} +\protected\def\written{\faPencil} + \protected\def\pmandatory{\semesterplannerLua@encircle{\textcolor{red}{\faWarning}}} + \protected\def\phigh{\semesterplannerLua@encircle{\textcolor{red}{\faFlag}}} + \protected\def\pmid{\semesterplannerLua@encircle{\textcolor{yellow}{\faFlag}}} + \protected\def\plow{\semesterplannerLua@encircle{\textcolor{green}{\faFlag}}} + \protected\def\pnone{\semesterplannerLua@encircle{\textcolor{gray}{\faTimesCircle}}} + + \protected\def\teams{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faWindows}}} + \protected\def\zoom{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faCamera}}} + \protected\def\youtube{\semesterplannerLua@encircle{\textcolor{red}{\faYoutubePlay}}} + \protected\def\BBB{\semesterplannerLua@encircle{\textcolor{DodgerBlue}{\faBold}}} + + \protected\def\tbd{\faQuestion} + \protected\def\tba{\faBullhorn} + +\directlua{sp = require("semesterplannerLua_timetable.lua")} +\directlua{cal = require("semesterplannerLua_calendar.lua")} + \pgfkeys{ + /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, + % + /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, + % + /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}, + } +\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};% + } + }{}% + }% +] +\newenvironment{timetable}[1][]{ + \section*{\faClockO~Timetable} + \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}]]}} + \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}]], + } + } + } + \newcommand{\lecture}[1][]{ + \semesterplannerLua@event[tikz={fill=lecture,}, textcolor=white, type=lect, ##1] + \ignorespaces + } + \newcommand{\seminar}[1][]{ + \semesterplannerLua@event[tikz={fill=seminar,}, textcolor=white, type=sem, ##1] + \ignorespaces + } + \newcommand{\tutorial}[1][]{ + \semesterplannerLua@event[tikz={fill=tutorial,}, textcolor=white, type=tut, ##1] + \ignorespaces + } + \newcommand{\meeting}[1][]{ + \semesterplannerLua@event[tikz={fill=meeting,}, textcolor=white, type=meet, ##1] + \ignorespaces + } + \newcommand{\officehour}[1][]{ + \semesterplannerLua@event[tikz={fill=officehour,}, textcolor=white, type=office, ##1] + \ignorespaces + } +}{ + \directlua{sp.draw( + [[\pgfkeysvalueof{/semesterplannerLua/timetable/env/length}]], + [[\pgfkeysvalueof{/semesterplannerLua/timetable/env/width}]])} +} + +\newcommand{\printSpCalendar}[3][3]{\directlua{cal.drawCalendar("#2", "#3", #1)}} + +\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} +} +\endinput +%% +%% End of file `semesterplannerlua.sty'. diff --git a/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_calendar.lua b/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_calendar.lua new file mode 100644 index 00000000000..f2fa0e5e32d --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/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/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_dmenu.lua b/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_dmenu.lua new file mode 100644 index 00000000000..d267d680715 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/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", "", "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", "", "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/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_timetable.lua b/Master/texmf-dist/tex/lualatex/semesterplannerlua/semesterplannerlua_timetable.lua new file mode 100644 index 00000000000..049644d2914 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/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 + diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 2d2445a6c1a..5df68729d83 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -757,7 +757,7 @@ my @TLP_working = qw( sdaps sdrt sduthesis se2thesis secdot secnum section sectionbox sectionbreak sectsty seealso selectp selinput selnolig semantex semantic semantic-markup semaphor - semesterplanner seminar semioneside semproc semtex + semesterplanner semesterplannerlua seminar semioneside semproc semtex sepfootnotes sepnum seqsplit serbian-apostrophe serbian-date-lat serbian-def-cyr serbian-lig sesamanuel sesstime setdeck setspace setspaceenhanced diff --git a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc index 11985b7be56..7cf9d21872f 100644 --- a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc @@ -98,6 +98,7 @@ depend plantuml depend pyluatex depend scikgtex depend selnolig +depend semesterplannerlua depend showhyphenation depend showkerning depend spacekern diff --git a/Master/tlpkg/tlpsrc/semesterplannerlua.tlpsrc b/Master/tlpkg/tlpsrc/semesterplannerlua.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3