Автоматическая дата в личном журнале

Автоматическая дата в личном журнале

Я веду личный журнал с помощью LaTeX. Я хотел бы создать среду, которая автоматически отслеживает дату каждой записи, без необходимости вручную вводить их. Вот код на данный момент

\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}

На самом деле newdayокружающая среда — это просто более запутанная версия гораздо более простой

\NewDocumentEnvironment{ newday }{ o }{
  \textbf{#1}
  \marginnote{ \datedayname,~\today } \\
}{
  \vspace{0.5cm}
}

Проблема, которую я хотел бы решить, заключается в следующем: предположим, я ввожу newdayсегодняшнюю дату, т. е. 25 февраля 2019 года. Как мне сделать так, чтобы код не изменил дату этой записи, когда день закончится?

Я начал писать код для первого варианта, думая, что он позволит мне хранить каждую дату в отдельном файле, но быстро понял, что файл .jrnперезаписывается каждый раз при компиляции, так что это бесполезно.

Есть идеи, как решить эту проблему?

РЕДАКТИРОВАТЬпроблемный код

\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}

решение1

Всякий раз, когда вы начинаете newday, вы должны проверить, установлена ​​ли уже дата во вспомогательном файле. Если есть, вы просто копируете ее в новый файл, в противном случае вы устанавливаете текущую дату:

\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}

Открывая файл для записи только в самом конце, мы гарантируем, что старый файл будет перезаписан только в том случае, если оставшийся документ был интерпретирован до конца, поэтому мы не очищаем файл и не теряем информацию в случае сбоя компиляции.

Вместо того, чтобы сначала читать файл в последовательность, мы могли бы читать одну строку вспомогательного файла при каждом вызове newday. Но тогда нам пришлось бы занимать один дескриптор файла для всего запуска. Читая файл одним блоком, мы можем освободить дескриптор файла как можно скорее. введите описание изображения здесь

Связанный контент