Eu mantenho um diário pessoal usando LaTeX. Gostaria de criar um ambiente que monitore automaticamente a data de cada entrada, sem precisar inseri-las manualmente. Este é o código até agora
\documentclass{tufte-book}
\usepackage{datenumber, ifthen, xparse}
\usepackage{lipsum}
\setstartyear{2000}
\newcounter{day}
\setcounter{day}{0}
\newcounter{if_auxnewday_begun}
\setcounter{if_auxnewday_begun}{0}
\ExplSyntaxOn
\iow_new:N \g_journal_stream
\seq_new:N \g_journal_seq
\NewDocumentEnvironment{ newday }{ o }{
\addtocounter{day}{1}
\seq_gput_right:Nx \g_journal_seq {
{ \arabic{day} }
{ \datedayname,~\today }
{ \IfValueTF{ #1 }{ #1 }{} }
}
\file_if_exist_input:n {\c_sys_jobname_str.jrn}
}{
\int_compare:nNnT { \arabic{if_auxnewday_begun} } = { 1 }{
\end{ auxnewday}
\setcounter{if_auxnewday_begun}{0}
}
}
\NewDocumentCommand{ \saveday }{ mmm }{
\int_compare:nNnT { #1 } = { \arabic{day} }{
\begin{ auxnewday }{#2}{#3}
\setcounter{if_auxnewday_begun}{1}
}
}
\NewDocumentEnvironment{ auxnewday } { mm }{
\textbf{ #2 }
\marginnote{ #1} \\
}{
\vspace{0.5cm}
}
\AtEndDocument{
\iow_open:Nn \g_journal_stream { \c_sys_jobname_str.jrn }
\save_days:
\iow_close:N \g_journal_stream
}
\cs_new_protected:Nn \save_days: {
\seq_map_function:NN \g_journal_seq \__save_days:n
}
\cs_new_protected:Nn \__save_days:n {
\iow_now:Nn \g_journal_stream {
\saveday #1
}
}
\ExplSyntaxOff
\begin{document}
\begin{newday}[A day]
\lipsum[1-5]
\end{newday}
\begin{newday}[Another day]
\lipsum[6-9]
\end{newday}
\end{document}
Do jeito que está, o newday
ambiente é apenas uma versão mais complicada do muito mais simples
\NewDocumentEnvironment{ newday }{ o }{
\textbf{#1}
\marginnote{ \datedayname,~\today } \\
}{
\vspace{0.5cm}
}
O problema que gostaria de resolver é o seguinte: suponha que eu insira newday
hoje, ou seja, 25 de fevereiro de 2019. Como evito que o código altere a data dessa entrada quando o dia terminar?
Comecei a codificar a primeira opção pensando que isso me permitiria manter cada data em um arquivo separado, mas rapidamente percebi que o .jrn
arquivo é sobrescrito toda vez que eu compilo, então é inútil.
Alguma idéia de como resolver esse problema?
EDITARcódigo problemático
\documentclass[justified, symmetric]{tufte-book}
\usepackage{ifoddpage, ifthen, xparse}
\usepackage[calc, showdow, english]{datetime2}
\DTMnewdatestyle{mydateformat}{%
\renewcommand{\DTMdisplaydate}[4]{%
\DTMshortweekdayname{##4},\space% short weekday,
\DTMmonthname{##2}\nobreakspace% (full) Month
\number##3,\space% day,
\number##1% year
}%
\renewcommand{\DTMDisplaydate}{\DTMdisplaydate}%
}
\DTMsetdatestyle{mydateformat}
\usepackage{lipsum}
\newcounter{day}
\title{Title}
\author{Author}
\ExplSyntaxOn
% Declare variables
\seq_new:N \g_journal_seq
\seq_new:N \g_journal_out_seq
\iow_new:N \g_journal_stream
\tl_new:N \l_journal_date_tl
% At the beginning of the run, read the lines of the `.jrn` file into a sequence.
% These are the dates. If the file can not be opened, it probably does not exist and we treat it as empty.
\cs_new:Npn \readjournaldates {
\ior_open:NnT \g_journal_stream { \c_sys_jobname_str.jrn } {
\ior_map_inline:Nn \g_journal_stream {
\seq_gput_right:Nn \g_journal_seq { ##1 }
}
\ior_close:N \g_journal_stream
}
}
% The main environment:
\NewDocumentEnvironment{ newday }{ O{} }{
\stepcounter{day}
% If the sequence \g_journal_seq is not empty yet, then we already saved a date
% for the current day. Save this day in `\l_journal_date_tl` and delete it from
% the sequence. Otherwise we have not saved anything yet, so we choose the current date.
\seq_gpop_left:NNF \g_journal_seq \l_journal_date_tl {
\tl_set:Nx \l_journal_date_tl {\today}
}
% Now we have to save the chosen date for the next run. First, only store it in the
% sequence `\g_journal_out_seq`, we only write it to the file at the end to avoid
% overwriting the file if something fails:
\seq_gput_right:NV \g_journal_out_seq \l_journal_date_tl
\textbf{ #1 }
\marginnote{\checkoddpage\ifoddpage \l_journal_date_tl \else\raggedleft \l_journal_date_tl \fi} \\
}{
\vspace{0.5cm}
}
% At the end of the document, iterate over `\g_journal_out_seq` and write every entry into a line.
\AtEndDocument{
\iow_open:Nn \g_journal_stream { \c_sys_jobname_str.jrn }
\seq_map_inline:Nn \g_journal_out_seq {
\iow_now:Nn \g_journal_stream { #1 }
}
\iow_close:N \g_journal_stream
}
\ExplSyntaxOff
\readjournaldates
\begin{document}
\maketitle
\pagenumbering{arabic}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[2]
\end{newday}
\begin{newday}
\lipsum[3]
\end{newday}
\begin{newday}[Ciao]
\lipsum[4]
\end{newday}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[2]
\end{newday}
\begin{newday}
\lipsum[3]
\end{newday}
\begin{newday}[Ciao]
\lipsum[4]
\end{newday}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[2]
\end{newday}
\end{document}
Responder1
Sempre que você iniciar um newday
, deverá verificar se já existe uma data definida no arquivo auxiliar. Se houver. você simplesmente copia para o novo arquivo, caso contrário você define a data atual:
\documentclass{tufte-book}
\usepackage{datenumber, ifthen, xparse}
\usepackage{lipsum}
\setstartyear{2000}
\newcounter{day}
\ExplSyntaxOn
% Declare variables
\seq_new:N \g_journal_seq
\seq_new:N \g_journal_out_seq
\iow_new:N \g_journal_stream
\tl_new:N \l_journal_date_tl
% At the beginning of the run, read the lines of the `.jrn` file into a sequence.
% These are the dates. If the file can not be opened, it probably does not exists
% and we treat it as empty.
\cs_new:Npn \readjournaldates {
\ior_open:NnT \g_journal_stream { \c_sys_jobname_str.jrn } {
\ior_map_inline:Nn \g_journal_stream {
\seq_gput_right:Nn \g_journal_seq { ##1 }
}
\ior_close:N \g_journal_stream
}
}
% The main environment:
\NewDocumentEnvironment{ newday }{ O{} }{
\stepcounter{day}
% If the sequence \g_journal_seq is not empty yet, then we already saved a date
% for the current day. Save this day in `\l_journal_date_tl` and delete it from
% the sequence. Otherwise we have not saved anything yet, so we choose the current
% date.
\seq_gpop_left:NNF \g_journal_seq \l_journal_date_tl {
\tl_set:Nx \l_journal_date_tl {\datedayname,~\today}
}
% Now we have to save the choosen date for the next run. First, only store it in the
% sequence `\g_journal_out_seq`, we only write it to the file at the end to avoid
% overwriting the file if something fails:
\seq_gput_right:NV \g_journal_out_seq \l_journal_date_tl
\textbf{ #1 }
\marginnote{ \l_journal_date_tl } \\
}{
\vspace{0.5cm}
}
% At the end of the document, iterate over `\g_journal_out_seq` and write every entry
% into a line
\AtEndDocument{
\iow_open:Nn \g_journal_stream { \c_sys_jobname_str.jrn }
\seq_map_inline:Nn \g_journal_out_seq {
\iow_now:Nn \g_journal_stream { #1 }
}
\iow_close:N \g_journal_stream
}
\ExplSyntaxOff
\makeatletter
\readjournaldates
\makeatother
\begin{document}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[2]
\end{newday}
\begin{newday}
\lipsum[3]
\end{newday}
\end{document}
Ao abrir o arquivo para escrita apenas no final, garantimos que o arquivo antigo só será sobrescrito se o documento restante tiver sido interpretado até o final, portanto não limpamos o arquivo e perdemos informações se a compilação falhar.
Em vez de ler primeiro o arquivo em uma sequência, poderíamos ler uma linha do arquivo auxiliar em cada invocação de newday
. Mas então teríamos que ocupar um identificador de arquivo durante toda a execução. Ao ler o arquivo em um bloco, podemos liberar o identificador do arquivo o mais rápido possível.