2

I read a lot of questions and answers about this matter, each doing a little of what I was looking for, but when I tried to merge them together, the whole world collapsed...

My goal is to build a revision table at the beginnig of my document. I found Generate automatic revision's numbering tabular that do it pretty nicely. The thing is that my compagny requires the revision to be "last first" order. So using the example, when I use

\AddRevision{2017-04-28}{Initial Release}{Miraino Hikari}
\AddRevision{2017-05-02}{Modification for something}{Jo Someone}

I got this result

Revisions:
0   2017-04-28     Initial Release                     Miraino Hikari
1   2017-05-02     Modification after some revision        Jo Someone

but what I would like is

Revisions:
1   2017-05-02     Modification after some revision        Jo Someone
0   2017-04-28     Initial Release                     Miraino Hikari

So I found a way to revert a list here: How to invert list used for a tikz foreach loop which work again really great when you have a normal list, but not so fine when you try to build a tabular. Then I found How do I use the ampersand (&) inside a foreach or conditional (or other group/environment) when building tables? that work similarly to the Revision numbering tabular example, but again, I can't see how to revert my list.

To do some tests, I tried to use all these example to try to generate the "First-Top" and "Last-Top" example. (Names changed to keep the original working)

\let\revlist\empty
\let\revlistI\empty

\newcommand\NewAddRevTable[1]{%
    \ifx\revlist\empty
        \xdef\revlist{#1}%
        \xdef\revlistI{#1}%
    \else
        \xdef\revlist{\revlist,{#1}}%
        \xdef\revlistI{{#1},\revlistI}%
    \fi
}

\newcommand*\MyRevisionTable{
    \begin{flushleft}
        \textbf{\iflanguage{french}{Révisions :}{Revisions:}}\\
    \end{flushleft}
    \begin{table}[H]
        \begin{tabularx}{\textwidth}{llXr}
            \foreach\rev in \revlist {
                \rev\\
            }
        \end{tabularx}
    \end{table}
}

\newcounter{MyRevCounter}
\newcommand{\NewRevision}[3]{ 
    \NewAddRevTable{\arabic{MyRevCounter} & #1 & #2 & #3} 
    \stepcounter{MyRevCounter}
}%

\NewRevision{2017-04-28}{Version initiale}{Miraino Hikari}
\NewRevision{2017-05-02}{Modification after some revision}{Jo Someone}

this code of course, doesn't work (except if I escape the & and that I remove the tabularx environment). But changing the revlist for revlistI do exactly what I was looking for (except it's not in a table)

and I suspect that the magic in the original revision code happen here

\newcommand\AddNewRevTableTokens[1]{\global\@myrevtabtoks\expandafter{\the\@myrevtabtoks#1}}
\newcommand\eAddNewRevTableTokens[1]{%
    \protected@edef\NewRevTkTable{#1}%
    \expandafter\AddNewRevTableTokens\expandafter{\NewRevTkTable}%  
}

but for this I tried

\newcommand\AddNewRevTableTokens[1]{\global\@myrevtabtoks\expandafter{\the\@myrevtabtoks#1}}
\newcommand\eAddNewRevTableTokens[1]{%
    \expandafter\AddNewRevTableTokens\expandafter{\NewRevTkTable}%  
    \protected@edef\NewRevTkTable{#1}%
}

which just don't care about any extra revision, and this

\newcommand\AddNewRevTableTokens[1]{\global\@myrevtabtoks\expandafter{#1\the\@myrevtabtoks}}
\newcommand\eAddNewRevTableTokens[1]{%
    \protected@edef\NewRevTkTable{#1}%
    \expandafter\AddNewRevTableTokens\expandafter{\NewRevTkTable}%  
}

That just don't compile with an error that says

TeX capacity exceeded, sorry [input stack size=5000]. \MyRevisionTable

So I need help. Thanks in advance.

  • Why don't you create the list in the correct order directly? You only need to add a new revision to the left instead of to the right. – Ulrike Fischer May 3 '17 at 15:26
  • The thing is that I don't want to bother about the revision number itself (which the original method do perfectly using the counter). Ultimatly, I would like to be able to toggle between the two method since some document are First-Top (use manual or analysis document for example) and other are Last-Top (ISO9001 documents for instance). I already have an option in my document class that allow me to toggle between the two methods, but I'm not able at the moment to do the magic trick of having the Last-First insertion and still compile. – Miraino Hikari May 3 '17 at 15:48
  • I also don't want to invert my whole \AddRevision commands each time I need to toggle the revision table order – Miraino Hikari May 3 '17 at 15:52
  • But you can decide about the order just before you build the list. Why first build it in the wrong order and then invert it? – Ulrike Fischer May 3 '17 at 15:57
  • Both numerotation and context of the document. I can have to build the same document (let's say once for ISO archives and once for my client) both want the revision number in a different order (it's a pain, I know) and I'm not the only one doing documentation. The rule is to add the revision in the "prog std order" which means, enter your inital release then the other. The counter will do it's job, numeroting them from 0 to N. But when I produce the PDF, these perfectly numbered dynamic items can be print in either 0 to N or N to 0 or not at all or only last (depending on the context) – Miraino Hikari May 3 '17 at 16:18
2

Here some code to get both orders:

\documentclass{article}   

\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N   \l_rev_tablecontents_first_tl
\tl_new:N   \l_rev_tablecontents_last_tl
\int_new:N  \l_rev_counter_int

\NewDocumentCommand\ClearRevision { }
 {
  \tl_clear:N \l_rev_tablecontents
  \int_zero:N \l_rev_counter_int
 }

\NewDocumentCommand\AddRevision { m m m}
{
  \int_incr:N  \l_rev_counter_int
  \tl_put_left:Nn \l_rev_tablecontents_last_tl   { #1 & #2 & #3 \\}
  \tl_put_left:Nx \l_rev_tablecontents_last_tl   { \int_to_arabic:n { \l_rev_counter_int }  & }
  \tl_put_left:Nn \l_rev_tablecontents_last_tl   {Revision \c_space_tl} 
  \tl_put_right:Nn \l_rev_tablecontents_first_tl {Revision \c_space_tl}
  \tl_put_right:Nx \l_rev_tablecontents_first_tl { \int_to_arabic:n { \l_rev_counter_int }  & }
  \tl_put_right:Nn \l_rev_tablecontents_first_tl { #1 & #2 & #3 \\}
}

\NewDocumentCommand\PrintRevisionFirst { }
  { 
   \begin{tabular}{lccl}
       \l_rev_tablecontents_first_tl
   \end{tabular} 
  }


\NewDocumentCommand\PrintRevisionLast { }
  {
   \begin{tabular}{lccl}
       \l_rev_tablecontents_last_tl
   \end{tabular}
  }


\ExplSyntaxOff

%-----------------------------------------------------------


\AddRevision{2017-04-28}{Initial Release}{Miraino Hikari}
\AddRevision{2017-05-02}{Modification for something}{Jo Someone}

\begin{document}

    \PrintRevisionFirst 

   \bigskip   
    \PrintRevisionLast
\end{document}

If you want to start with zero, move the \int_incr to the end.

enter image description here

  • That is quite a different code from what I had before, I already had difficulties understanding the token one, this one seems even more obscure, but still a bit more readable... – Miraino Hikari May 3 '17 at 16:35
  • 1
    It looks a bit odd at first sight, with all the underscores. But if you simply accept that with expl3/xparse command names can also contain underscores and colons then it is much more readable than the other code with its \expandafters. – Ulrike Fischer May 3 '17 at 16:40
  • definitly is. I'm still not familiar with LaTeX3 syntax (still using good old LaTeX2e) but definitly, I will take the time to check it out. I saw that the xparse allow me to have multiple optional argument and that I needed for another of my problem, so you kindof solve another problems with the question generated by your answer. Thanks a lot. I will replace my old things with this and keep studying this wonderfull new (at least for me) syntax – Miraino Hikari May 3 '17 at 16:44
2

If the revisions are entered in chronological order, it's quite easy to get them in reverse order when they are to be printed: just store them in reverse order! ;-)

\documentclass{article}
\usepackage{xparse,tabularx}

\ExplSyntaxOn

\NewDocumentCommand{\AddRevision}{mmm}
 {
  \hikari_revision_add:nnn { #1 } { #2 } { #3 }
 }
\NewDocumentCommand{\PrintRevisions}{}
 {
  \begin{center}
  \cs_set_eq:NN \__hikari_revision_do:nnnn \hikari_revision_print_entry:nnnn
  \begin{tabularx}{\textwidth}{llXr}
  \multicolumn{4}{l}{Revisions} \\
  \hline
  \hikari_revision_print:
  \\\hline
  \end{tabularx}
  \end{center}
 }

\seq_new:N \g_hikari_revision_list_seq
\int_new:N \g_hikari_revision_number_int

\cs_new_protected:Nn \hikari_revision_add:nnn
 {
  \seq_gput_left:Nx \g_hikari_revision_list_seq
   {
    \exp_not:N \__hikari_revision_do:nnnn
     { \int_eval:n { \g_hikari_revision_number_int } }
     \exp_not:n { { #1 } { #2 } { #3 } }
   }
  \int_incr:N \g_hikari_revision_number_int
 }

\cs_new_protected:Nn \hikari_revision_print:
 {
  \seq_use:Nn \g_hikari_revision_list_seq { \\ }
 }

\cs_new:Nn \hikari_revision_print_entry:nnnn
 {
  #1 & #2 & #3 & #4
 }

\ExplSyntaxOff

\begin{document}

\AddRevision{2017-04-28}{Initial Release}{Miraino Hikari}
\AddRevision{2017-05-02}{Modification for something}{Jo Someone}

\PrintRevisions

\end{document}

I use an indirect method for storing the entries, with a “dummy function” that we can make equal to some real function at call time. So the list of revisions can be used in different ways without changing the main code. Maybe you also want to print out the list of reviewers or the dates: just define a suitable function like I did for \hikari_revision_print_entry:nnnn.

enter image description here

A different version that allows \AddRevision to be in whatever order in the document. The items are sorted by (reverse) date as part of \PrintRevisions.

\documentclass{article}
\usepackage{xparse,tabularx}

\ExplSyntaxOn

\NewDocumentCommand{\AddRevision}{mmm}
 {
  \hikari_revision_add:nnn { #1 } { #2 } { #3 }
 }
\NewDocumentCommand{\PrintRevisions}{}
 {
  \begin{center}
  \cs_set_eq:NN \__hikari_revision_do:nnn \hikari_revision_date:nnn
  \seq_set_eq:NN \l__hikari_revision_temp_seq \g_hikari_revision_list_seq
  \seq_sort:Nn \l__hikari_revision_temp_seq
   {
    \int_compare:nNnTF
     { ##1 } > { ##2 }
     { \sort_return_same: }
     { \sort_return_swapped: }
   }
  \cs_set_eq:NN \__hikari_revision_do:nnn \hikari_revision_entry:nnn
  \int_gset:Nn \g__hikari_revision_entry_int { \seq_count:N \l__hikari_revision_temp_seq }
  \tl_clear:N \l__hikari_revision_tablebody_tl
  \seq_map_inline:Nn \l__hikari_revision_temp_seq
   {
    \int_gdecr:N \g__hikari_revision_entry_int
    \tl_put_right:Nf \l__hikari_revision_tablebody_tl
     { \int_to_arabic:n { \g__hikari_revision_entry_int } ##1 }
   }
  \begin{tabularx}{\textwidth}{llXr}
  \multicolumn{4}{l}{Revisions} \\
  \hline
  \tl_use:N \l__hikari_revision_tablebody_tl
  \hline
  \end{tabularx}
  \end{center}
 }

\seq_new:N \g_hikari_revision_list_seq
\seq_new:N \l__hikari_revision_temp_seq
\int_new:N \g__hikari_revision_entry_int
\tl_new:N \l__hikari_revision_tablebody_tl
\cs_generate_variant:Nn \tl_put_right:Nn { Nf }

\cs_new_protected:Nn \hikari_revision_add:nnn
 {
  \seq_gput_right:Nn \g_hikari_revision_list_seq
   {
    \__hikari_revision_do:nnn { #1 } { #2 } { #3 }
   }
 }

\cs_new:Nn \hikari_revision_entry:nnn
 {
   & #1 & #2 & #3 \\
 }

\cs_new:Nn \hikari_revision_date:nnn
 {
  \__hikari_revision_make_date:w #1 \q_stop
 }
\cs_new:Npn \__hikari_revision_make_date:w #1-#2-#3 \q_stop
 {
  #1#2#3
 }
\ExplSyntaxOff

\begin{document}

\AddRevision{2017-05-03}{Changed code for revisions}{egreg}

\AddRevision{2017-04-28}{Initial Release}{Miraino Hikari}
\AddRevision{2017-05-02}{Modification for something}{Jo Someone}

\PrintRevisions

\end{document}

enter image description here

  • That's pretty much what my case #2 was, but the other proposition allow me to do tehm all at one. I still upvote your answer since it do the trick for someone who don't need as me as many cases. – Miraino Hikari May 3 '17 at 19:20
  • @MirainoHikari I added a version that sorts the revisions by date, independent of the order they are written in the document. – egreg May 3 '17 at 21:13
  • @egreg This looks very nice. I am wondering whether it might be possible to use the date from \AddRevision{DATE}.. as label to refer to the revision number in the text? – LukasCB May 3 '17 at 21:35
  • @LukasCB That could be added, but I don't think it makes much sense. – egreg May 3 '17 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.