TeX - LaTeX Asked by BadAtLaTeXProgramming on September 29, 2021
I am planning to take some notes in a ‘laboratory book’-ish latex document (compare these templates 1,2). The protocol will span a large time and entries might vary from a few items to several sides.
In order to keep better track of what I did when, I would like to have a calendar (e.g. this or this) that shows section titles (and maybe the page number). These should link to the sections (like done with pictures here).
Obviously one can use hyperref and simply do it by hand. However an TOC in such manner that is generated automatically was preferable.
How can I create a TOC that looks like a calendar?
(or: a calendar that acts like a TOC)
Neither looking particularly nice nor quick to create (even if I used a custom command for the entries):
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Monthly Calendar
% LaTeX Template
%
% This template has been downloaded from:
% http://www.latextemplates.com
%
% Original calendar style author:
% Evan Sultanik (http://www.sultanik.com/LaTeX_calendar_style)
%
% Important note:
% This template requires the calendar.sty file to be in the same directory as the
% .tex file. The calendar.sty file provides the necessary structure to create the
% calendar.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Modified in order to represent the MWE for tex.stackexchange question:
% https://tex.stackexchange.com/q/356889/74942
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%----------------------------------------------------------------------------------------
% PACKAGES AND OTHER DOCUMENT CONFIGURATIONS
%----------------------------------------------------------------------------------------
documentclass[a4paper]{article}
%
usepackage{filecontents}
begin{filecontents}{calendar.sty}
NeedsTeXFormat{LaTeX2e}
defCalendarVersion{3.1}
defCalendarVersionDate{2009/04/24}
ProvidesClass{calendar}[CalendarVersionDate
LaTeX2e class file `calendar' vCalendarVersion]
typeout{'calendar' style CalendarVersion CalendarVersionDate.}
typeout{Created by Evan Sultanik}
typeout{****** Bugs/comments/suggestions/technicalities to Evan Sultanik -- [email protected] ******}
RequirePackage{tabularx}
def@CALtrue{1}
newcount@currentdaynum
newcounter{calendardate}
newcountStartingDayNumber
defdayheader#1#2{
noindent
begin{minipage}[t]{0.87hsize}
noindent
raggedright
textit{#1}
end{minipage}
begin{minipage}[t]{0.1hsize}
noindent
raggedleft
textit{#2}
end{minipage}
}
defactivities#1{
parbox{hsize}{vspace*{5pt}raggedrightscriptsize #1}smallskip
}
let@colbreak=&
defprintdayname#1{hfiltextsc{#1}hfil}
newcommand{dayname}[1]{
ifnum#1=1 Sundayelse
ifnum#1=2 Mondayelse
ifnum#1=3 Tuesdayelse
ifnum#1=4 Wednesdayelse
ifnum#1=5 Thursdayelse
ifnum#1=6 Fridayelse
ifnum#1=7 Saturdayelse
PackageError{calendar}{Unrecognized day number: #1!}
fififififififi
}
StartingDayNumber=1
newenvironment{calendar}[1]{
newdimen@calendarwidth
@calendarwidth=#1
begingroup
def@calendarmode{@CALtrue}
defday##1##2{
if@calendarmode@CALtrueelsePackageWarning{calendar}{The 'day' macro is expected to be used in the 'calendar' environment!}fi
ifnum@currentdaynum>7global@currentdaynum=1fi
globaladvance@currentdaynum by 1
dayheader{##1}{thecalendardate}defdaysep{vskip1pthrulevskip1pt}
activities{##2}
addtocounter{calendardate}{1}
ifnum@currentdaynum>7@arraycrhlineelse&fi
}
deffinishCalendar{
ifnum@currentdaynum=6 &hlineelse
ifnum@currentdaynum=5 &&hlineelse
ifnum@currentdaynum=4 &&&hlineelse
ifnum@currentdaynum=3 &&&&hlineelse
ifnum@currentdaynum=2 &&&&&hlineelse
ifnum@currentdaynum=1 &&&&&&hline
fifififififi
}
defBlankDay{
if@calendarmode@CALtrueelsePackageWarning{calendar}{The 'calendarday' macro is expected to be used in the 'calendar' environment!}fi
ifnum@currentdaynum>7global@currentdaynum=1fi
globaladvance@currentdaynum by 1
addtocounter{calendardate}{1}
ifnum@currentdaynum>7@arraycrhlineelse&fi
}
setcounter{calendardate}{1}
newcount@currday
@currday=StartingDayNumber
newcount@numdays
@numdays=7
let@cbreak=&
tabularx{@calendarwidth}{|X|X|X|X|X|X|X|} hline
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 &
ifnum@currday>@numdays@currday=1fiprintdayname{dayname{@currday}} globaladvance@currday by 1 hline hline
@currentdaynum=1
let@firstline=@CALtrue
}{
endtabularx
endgroup
}
end{filecontents}
%
usepackage{calendar} % Use the calendar.sty style
usepackage[colorlinks=false,linkcolor=black,bookmarks=false]{hyperref}
usepackage[margin=0.5in]{geometry}
begin{document}
pagestyle{empty} % Removes the page number from the bottom of the page
noindent
StartingDayNumber=1 % Calendar starting day, default of 1 means Sunday, 2 for Monday, etc
%----------------------------------------------------------------------------------------
% MONTH AND YEAR SECTION
%----------------------------------------------------------------------------------------
setcounter{section}{-1}
section{Table of Contents}
begin{center}
textsc{LARGE january} % Month
textsc{large 2017} % Year
end{center}
%----------------------------------------------------------------------------------------
begin{calendar}{hsize}
%----------------------------------------------------------------------------------------
% BLANK DAYS BEFORE THE BEGINNING OF THE CALENDAR
%----------------------------------------------------------------------------------------
% This part is very finicky. It defines the number of blank days at the beginning of the calendar before the first of the month starts. If you need this to be more than 4 (i.e. the first starts on a Friday or Saturday in a 31 day month), then you have two options:
% 1) You can uncomment another one or two BlankDay's below which will make a new week (6 total) which makes the calendar too big for one page, remedy this by decreasing the size of each day by replacing 2.5cm below with a smaller number.
% 2) Make the spill-over days start at the top left of the calendar (i.e. the calendar starts with 31 then a few days blank then 1, 2, 3, etc). The second option can be configured by uncommenting the below:
%setcounter{calendardate}{31} % Begin the count with 31 so the top left day is 31; this can be changed to 29 or 30 as required
%day{}{vspace{2.5cm}} % 31 - add another line identical to this if starting at 30 or earlier
% You will need to comment out the 31 in the NUMBERED DAYS AND CALENDAR CONTENT section below for this as well as commenting out one of the BlankDay's below. Play around with it and you will get it.
%BlankDay
%BlankDay
%BlankDay
%BlankDay
%BlankDay
%BlankDay
%----------------------------------------------------------------------------------------
% NUMBERED DAYS AND CALENDAR CONTENT
%----------------------------------------------------------------------------------------
% These are the numbered days in the template - if there are less than 31 days simply comment out the bottom lines.
% vspace{2.5cm} is only there to provide an even look to the calendar where each day is 2.5cm tall, it can be changed or removed to automatically adjust to the day in the week with the most content
setcounter{calendardate}{1} % Start the date counter at 1
day{}{
hyperref[01012017]{nameref{01012017}} hfill pageref{01012017}
hyperref[01012017_h]{nameref{01012017_h}} hfill pageref{01012017_h}
hyperref[01012017_s]{nameref{01012017_s}} hfill pageref{01012017_s}
} % 1 - Example of content
day{}{
hyperref[02012017]{nameref{02012017}} hfill pageref{02012017}
hyperref[02012017_a]{nameref{02012017_a}} hfill pageref{02012017_a}
hyperref[02012017_b]{nameref{02012017_b}} hfill pageref{02012017_b}
} % 2
day{}{vspace{2.5cm}} % 3
day{}{vspace{2.5cm}} % 4
day{}{vspace{2.5cm}} % 5
day{}{vspace{2.5cm}} % 6
day{}{vspace{2.5cm}} % 7
day{}{vspace{2.5cm}} % 8
day{}{
hyperref[09012017]{nameref{09012017}} hfill pageref{09012017}
} % 9
day{}{vspace{2.5cm}} % 10
day{}{vspace{2.5cm}} % 11
day{}{vspace{2.5cm}} % 12
day{}{vspace{2.5cm}} % 13
day{}{vspace{2.5cm}} % 14
day{}{vspace{2.5cm}} % 15
day{}{vspace{2.5cm}} % 16
day{}{vspace{2.5cm}} % 17
day{}{vspace{2.5cm}} % 18
day{}{vspace{2.5cm}} % 19
day{}{vspace{2.5cm}} % 20
day{}{vspace{2.5cm}} % 21
day{}{vspace{2.5cm}} % 22
day{}{vspace{2.5cm}} % 23
day{}{vspace{2.5cm}} % 24
day{}{vspace{2.5cm}} % 25
day{}{vspace{2.5cm}} % 26
day{}{vspace{2.5cm}} % 27
day{}{vspace{2.5cm}} % 28
day{}{vspace{2.5cm}} % 29
day{}{vspace{2.5cm}} % 30
day{}{vspace{2.5cm}} % 31
% Un-comment the BlankDay below if the bottom line of the calendar is missing
%BlankDay
% Un-comment to start counting again after 31
%setcounter{calendardate}{1}
%day{}{vspace{2.5cm}} % 1
%day{}{vspace{2.5cm}} % 2
%day{}{vspace{2.5cm}} % 3
%----------------------------------------------------------------------------------------
finishCalendar
end{calendar}
newpage
section{day1 - 01.01.2017}label{01012017}
begin{itemize}
item did some setup things
item $dots$
end{itemize}
subsection{hardware}label{01012017_h}
My tedious written composition of annoying hardware setup.
newpage
~
newpage
subsection{software}label{01012017_s}
The fun part: software!
newpage
section{day2 - 02.01.2017}label{02012017}
section{first test project}label{02012017_a}
some text
newpage
section{video shoot}label{02012017_b}
notes on my video log recording
newpage
~
newpage
section{something important}label{09012017}
end{document}
(I did not want to remove too much information so no-one would confuse this with not being from latextemplates.com. Moreover I am not aware what is actually minimally required)
first outsourced question:
Bake 'today' into source file (or custom aux-file)
I am still investigating on this issue, hence …
Helpful information, e.g. on generation of ToCs, deeper TeX(-programming) necessary for this project or anything else would be much appreciated also!
I think this may be able to achieve what you want.
Before spamming my code, please be advised that following requirements need to be met:
mycode.lua
into source folder.-- for debugging
-- https://github.com/kikito/inspect.lua
-- inspect = require("inspect")
-- https://github.com/kikito/md5.lua/blob/master/md5.lua
md5 = require("md5")
function strip(str)
return string.gsub(str, "^%s*(.-)%s*$", "%1")
end
function split_strip(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
local stripped = strip(str)
table.insert(t, stripped)
end
return t
end
function parse_time(time_str)
local tab = split_strip(time_str, "%-")
assert(#tab == 2, "invalid section format")
local day_str = string.gsub(tab[1], "day%s+", "")
local day_ind = tonumber(day_str)
assert(day_ind ~= nil, "invalid day index")
-- day/month/year format
local tab_mdy = split_strip(tab[2], "%.")
assert(#tab_mdy == 3, "invalid date format")
local month = tab_mdy[2]
local day = tab_mdy[1]
local year = tab_mdy[3]
local tp = os.time{year=year, month=month, day=day, hour=0, sec=1}
local date = os.date("*t", tp)
return {
day_ind=day_ind,
date=date
}
end
function label_section(storage, section_str)
return md5.sumhexa(section_str)
end
function label_subsection(storage, subsection_str)
local offset = storage["offset"]
local subsec_size = 0
if storage["subsection"][offset] ~= nil then
subsec_size = #storage["subsection"][offset]
end
local full_str = storage["section"][offset][1] .. subsection_str .. tostring(subsec_size)
return md5.sumhexa(full_str)
end
-- no integrity check for section headings
-- avoid duplicated dates
-- must have day 1
function register_section(storage, date_str)
local parse_res = parse_time(date_str)
local offset = parse_res["day_ind"]
if offset == 1 then
storage["num_blanks"] = parse_res["date"]["wday"] - 1
end
storage["offset"] = offset
local label = label_section(storage, date_str)
local t_in = {date_str, label}
storage["section"][offset] = t_in
storage["subsection"][offset] = {}
return t_in
end
function register_subsection(storage, subsection_str)
local offset = storage["offset"]
local label = label_subsection(storage, subsection_str)
local t_in = {subsection_str, label}
table.insert(storage["subsection"][offset], t_in)
return t_in
end
function new_storage()
local t = {}
t["section"] = {}
t["subsection"] = {}
t["num_days"] = 31
t["empty_fill"] = [[vspace{2.5cm}]]
return t
end
function create_toc(storage)
local t = {}
table.insert(t, [[begin{calendar}{hsize}]])
local j = storage["num_blanks"]
for i=1,j do
table.insert(t, [[BlankDay]])
end
table.insert(t, [[setcounter{calendardate}{1}]])
j = storage["num_days"]
for i=1,j do
local tt = {}
if storage["section"][i] ~= nil then
local sec_label = storage["section"][i][2]
table.insert(tt, string.format([[hyperref[%s]{nameref{%s} hfill pageref{%s}}newline]],
sec_label, sec_label, sec_label))
if storage["subsection"][i] ~= nil then
local subsec = storage["subsection"][i]
for _, val in pairs(subsec) do
local subsec_label = val[2]
table.insert(tt, string.format([[hyperref[%s]{nameref{%s} hfill pageref{%s}}newline]],
subsec_label, subsec_label, subsec_label))
end
end
end
local str = ""
if #tt == 0 then
str = storage["empty_fill"]
else
str = table.concat(tt, "n")
end
local day_str = string.format([[day{}{%s}]], str)
table.insert(t, day_str)
end
table.insert(t, [[finishCalendar]])
table.insert(t, [[end{calendar}]])
return table.concat(t, "n")
end
documentclass[a4paper]{article}
usepackage{calendar} % Use the calendar.sty style
usepackage[colorlinks=false,linkcolor=black,bookmarks=false]{hyperref}
usepackage[margin=0.5in]{geometry}
usepackage{luacode}
begin{document}
pagestyle{empty} % Removes the page number from the bottom of the page
noindent
setcounter{section}{-1}
section{Table of Contents}
begin{center}
textsc{LARGE january} % Month
textsc{large 2020} % Year
end{center}
directlua{
require("mycode")
% declare new global storage
storage = new_storage()
}
letoldsectionsection
letoldsubsectionsubsection
renewcommand{section}[1]{
directlua{
cur_sec = register_section(storage, "luaescapestring{#1}")
}
oldsection{#1}label{directlua{tex.print(cur_sec[2])}}
}
renewcommand{subsection}[1]{
directlua{
cur_subsec = register_subsection(storage, "luaescapestring{#1}")
}
oldsubsection{#1}label{directlua{tex.print(cur_subsec[2])}}
}
% update calendar source file
AtEndDocument{
directlua{
local out = create_toc(storage)
local file = io.open("jobname.calendar", "w")
file:write(out)
file:close()
}
}
% read the calendar from file
InputIfFileExists{jobname.calendar}
newpage
section{day 1 - 01.01.2020}
begin{itemize}
item did some setup things
item $dots$
end{itemize}
subsection{hardware}
My tedious written composition of annoying hardware setup.
newpage
~
newpage
subsection{software}
The fun part: software!
newpage
section{day 2 - 02.01.2020}
section{day 5 - 05.01.2020}
some text
newpage
section{day 10 - 10.01.2020}
subsection{notes on my video log recording}
newpage
% test identical section heading
subsection{notes on my video log recording}
newpage
~
newpage
section{day 20 - 20.01.2020}
end{document}
The core processing is completely done in Lua. I overrode default section
and subsection
commands to achieve automatically labeling. With Lua's date function, the number of BlankDay
's can be computed automatically. By the end of each compilation, the generated calendar source will be stored in jobname.calendar
and used in next run.
begin{calendar}{hsize}
BlankDay
BlankDay
BlankDay
setcounter{calendardate}{1}
day{}{hyperref[457625da265eeceb803943ba0808c2aa]{nameref{457625da265eeceb803943ba0808c2aa} hfill pageref{457625da265eeceb803943ba0808c2aa}}newline
hyperref[de221fb236d079c07b5af80cf9ecef34]{nameref{de221fb236d079c07b5af80cf9ecef34} hfill pageref{de221fb236d079c07b5af80cf9ecef34}}newline
hyperref[17592e2d9eafe348603ebdcc29dcb4ad]{nameref{17592e2d9eafe348603ebdcc29dcb4ad} hfill pageref{17592e2d9eafe348603ebdcc29dcb4ad}}newline}
day{}{hyperref[96f35bbca7ba14a54c2730705f376746]{nameref{96f35bbca7ba14a54c2730705f376746} hfill pageref{96f35bbca7ba14a54c2730705f376746}}newline}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{hyperref[69cc2168ce348de7a0d82d6f597cd274]{nameref{69cc2168ce348de7a0d82d6f597cd274} hfill pageref{69cc2168ce348de7a0d82d6f597cd274}}newline}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{hyperref[a402e6830c5d12dbda9ca2fb80398cd4]{nameref{a402e6830c5d12dbda9ca2fb80398cd4} hfill pageref{a402e6830c5d12dbda9ca2fb80398cd4}}newline
hyperref[831be6085cb90cfa125282e6b78ac8d5]{nameref{831be6085cb90cfa125282e6b78ac8d5} hfill pageref{831be6085cb90cfa125282e6b78ac8d5}}newline
hyperref[2df3994fff21c52f583af09d414f5d2e]{nameref{2df3994fff21c52f583af09d414f5d2e} hfill pageref{2df3994fff21c52f583af09d414f5d2e}}newline}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{hyperref[4c03bdd9c0e81f64cf961a4c48199e97]{nameref{4c03bdd9c0e81f64cf961a4c48199e97} hfill pageref{4c03bdd9c0e81f64cf961a4c48199e97}}newline}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
day{}{vspace{2.5cm}}
finishCalendar
end{calendar}
Miscellaneous reminders
Answered by Alan Xiang on September 29, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP