0

Following my previous question, for this MWE,

\documentclass{article}
\usepackage[hidelinks,colorlinks=false]{hyperref}
\usepackage{lipsum}

\setlength\marginparwidth{0.8\dimexpr(\paperwidth - \textwidth)/2\relax}
\usepackage[textwidth=\marginparwidth]{todonotes}

\usepackage{etoolbox}

\makeatletter
\newcommand\@todonotes@owner{default}
\define@key{todonotes}%
    {owner}{\def\@todonotes@owner{#1}}

\newtoggle{ownerdefault}
\newtoggle{ownerB}


\newcommand\stR[2]{% 1st reviewer comment
    \todo[%
    owner=default,
    author=1st Reviewer,noline,caption={#1 Comment},color=blue!20%
    ]%
    {#1 Comment}{\color{blue}{\bfseries#2}}}

\newcommand\ndR[2]{% 2nd reviewer comment
    \todo[%
    owner=B,
    author=2nd Reviewer,noline,caption={#1 Comment},color=red!50!white%
    ]%
    {#1 Comment}{\color{red}{\bfseries#2}}}



\renewcommand{\@todonotes@addElementToListOfTodos}{%
    \if@todonotes@colorinlistoftodos%
     \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\protect\fcolorbox{\@todonotes@currentbordercolor}%
                {\@todonotes@currentbackgroundcolor}%
                {\protect\textcolor{\@todonotes@currentbackgroundcolor}{o}}%
            \ \@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \else%
      \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \fi}%

\makeatother
\begin{document}
\toggletrue{ownerdefault}
\section*{Reviewer \#1 Comments}
\InputIfFileExists{\jobname.tdo}{}

\toggletrue{ownerB}
\togglefalse{ownerdefault}
\section*{Reviewer \#2 Comments}
\InputIfFileExists{\jobname.tdo}{}

\togglefalse{ownerB}
\makeatletter \@starttoc{tdo}\makeatother % to trigger the creation of the list

\section{Section}

Text \stR{\#2}{2nd comment of the 1st reviewer} another text\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3b}{3rd comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Some text \stR{\#1}{1st comment of the 1st reviewer} continue text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3a}{1st comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\end{document}

enter image description here

I need to know how to alphanumerically sort the entries of listoftodos according to the first argument the custom todo commands?

For example, I need the first list entries to be sorted like:

#1 Comment

#2 Comment

and the second list entries to be sorted like:

#3a Comment

#3b Comment

3

Well you will need some tool that sorts the .tdo. You really don't want to do this in latex. E.g. if you would switch to lualatex you could do something like this (you could also activate --shell-excape and call some external script):

\documentclass{article}
\usepackage[hidelinks,colorlinks=false]{hyperref}
\usepackage{lipsum}

\setlength\marginparwidth{0.8\dimexpr(\paperwidth - \textwidth)/2\relax}
\usepackage[textwidth=\marginparwidth]{todonotes}

\usepackage{etoolbox}

\makeatletter
\newcommand\@todonotes@owner{default}
\define@key{todonotes}%
    {owner}{\def\@todonotes@owner{#1}}

\newtoggle{ownerdefault}
\newtoggle{ownerB}


\newcommand\stR[2]{% 1st reviewer comment
    \todo[%
    owner=default,
    author=1st Reviewer,noline,caption={#1 Comment},color=blue!20%
    ]%
    {#1 Comment}{\color{blue}{\bfseries#2}}}

\newcommand\ndR[2]{% 2nd reviewer comment
    \todo[%
    owner=B,
    author=2nd Reviewer,noline,caption={#1 Comment},color=red!50!white%
    ]%
    {#1 Comment}{\color{red}{\bfseries#2}}}



\renewcommand{\@todonotes@addElementToListOfTodos}{%
    \if@todonotes@colorinlistoftodos%
     \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\protect\fcolorbox{\@todonotes@currentbordercolor}%
                {\@todonotes@currentbackgroundcolor}%
                {\protect\textcolor{\@todonotes@currentbackgroundcolor}{o}}%
            \ \@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \else%
      \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \fi}%

\makeatother
\usepackage{luacode}

\begin{luacode*}
function sort_tdo (jobname)
     local lines = {}
    -- read the lines in table 'lines'
     for line in io.lines(jobname) do
      table.insert(lines, line)
    end
    -- sort
    table.sort(lines)
    -- write all the lines
   file=io.open(jobname.."sorted", "w") 
   io.output(file) 
   for i, l in ipairs(lines) do io.write(l, "\n") 
   end
   io.close(file)
   end 
\end{luacode*}

\IfFileExists{\jobname.tdo}{\directlua{sort_tdo("\jobname.tdo")}}{}

\begin{document}
\toggletrue{ownerdefault}
\section*{Reviewer \#1 Comments}
\InputIfFileExists{\jobname.tdosorted}{}

\toggletrue{ownerB}
\togglefalse{ownerdefault}
\section*{Reviewer \#2 Comments}
\InputIfFileExists{\jobname.tdosorted}{}

\togglefalse{ownerB}
\makeatletter \@starttoc{tdo}\makeatother % to trigger the creation of the list

\section{Section}

Text \stR{\#2}{2nd comment of the 1st reviewer} another text\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3b}{3rd comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Some text \stR{\#1}{1st comment of the 1st reviewer} continue text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3a}{1st comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\end{document}

enter image description here

0
2

The following is based on Ulrike's answer and also requires LuaTeX. It has three improvements: It does not read the file line by line but instead reads it in one go (That's often faster), it uses local instead of global variables if possible and uses non-generic names for it's only global variable (avoiding problems with other code which also uses such variables) and doesn't write the sorted lines to a file and instead keeps them in a Lua variable. This avoids messing up Lua's default output stream, doesn't leave another file in your working directory and is faster:

\documentclass{article}
\usepackage[hidelinks,colorlinks=false]{hyperref}
\usepackage{lipsum}

\setlength\marginparwidth{0.8\dimexpr(\paperwidth - \textwidth)/2\relax}
\usepackage[textwidth=\marginparwidth]{todonotes}

\usepackage{etoolbox}

\makeatletter
\newcommand\@todonotes@owner{default}
\define@key{todonotes}%
    {owner}{\def\@todonotes@owner{#1}}

\newtoggle{ownerdefault}
\newtoggle{ownerB}


\newcommand\stR[2]{% 1st reviewer comment
    \todo[%
    owner=default,
    author=1st Reviewer,noline,caption={#1 Comment},color=blue!20%
    ]%
    {#1 Comment}{\color{blue}{\bfseries#2}}}

\newcommand\ndR[2]{% 2nd reviewer comment
    \todo[%
    owner=B,
    author=2nd Reviewer,noline,caption={#1 Comment},color=red!50!white%
    ]%
    {#1 Comment}{\color{red}{\bfseries#2}}}



\renewcommand{\@todonotes@addElementToListOfTodos}{%
    \if@todonotes@colorinlistoftodos%
     \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\protect\fcolorbox{\@todonotes@currentbordercolor}%
                {\@todonotes@currentbackgroundcolor}%
                {\protect\textcolor{\@todonotes@currentbackgroundcolor}{o}}%
            \ \@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \else%
      \addtocontents{tdo}
      {%
       \protect\iftoggle{owner\@todonotes@owner}
         {%
          \protect\contentsline {todo}
            {\@todonotes@caption
            }{\thepage}{\@currentHref}%
          }{}%
       }%
    \fi}%

\makeatother
\usepackage{luacode}

\begin{luacode*}
  local split_lines = lpeg.Ct((lpeg.C((1-lpeg.P'\n')^0)*'\n')^0)*-1
  function sorted_lines_from_filename (jobname)
    local file = io.open(jobname)
    local lines = split_lines:match(file:read'a')
    file:close()
    assert(lines, 'Files should end with a newline')
    table.sort(lines)
    return lines
  end
\end{luacode*}

\IfFileExists{\jobname.tdo}{\directlua{sorted_tdo = sorted_lines_from_filename("\jobname.tdo")}}{}

\begin{document}
\toggletrue{ownerdefault}
\section*{Reviewer \#1 Comments}
\directlua{if sorted_tdo then tex.tprint(sorted_tdo) end}

\toggletrue{ownerB}
\togglefalse{ownerdefault}
\section*{Reviewer \#2 Comments}
\directlua{if sorted_tdo then tex.tprint(sorted_tdo) end}

\togglefalse{ownerB}

\directlua{sorted_tdo=nil} % We no longer need sorted_tdo, so clean up

\makeatletter \@starttoc{tdo}\makeatother % to trigger the creation of the list

\section{Section}

Text \stR{\#2}{2nd comment of the 1st reviewer} another text\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3b}{3rd comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Some text \stR{\#1}{1st comment of the 1st reviewer} continue text.\vspace{\baselineskip}

\lipsum[1-2]\vspace{\baselineskip}

Text \ndR{\#3a}{1st comment of the 2nd reviewer} another text.\vspace{\baselineskip}

\end{document}

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.