Сортировка новых команд по одной переменной

Сортировка новых команд по одной переменной

Два рецензента сделали несколько комментариев по моей статье, и я пишу ответное письмо. Я определил новую команду следующим образом:

\newcommand{\response}[3]{Comment by Reviewer #1 \\ Comment: #2 \\ Response: #3}

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

КОММЕНТАРИИ РЕЦЕНЗЕНТА 1

Комментарий: Это комментарий.

Ответ: Это ответ.

...

КОММЕНТАРИИ РЕЦЕНЗЕНТА 2

Комментарий: Это комментарий.

Ответ: Это ответ.

...

Как отсортировать команды по первой переменной команды?

Поскольку я еще не начал писать свой документ, альтернативные решения также приветствуются.

решение1

Вот подход, при котором

  • Возможные имена рецензентов — «Джон Доу» и «Джон Смит»,
    а ответы и записи ответов отправляются во внешние файлы \jobname.rvallи \jobname.rvdoe/ \jobname.rvsmith.
  • второй и третий аргументы \response(комментарий и ответ) будут прочитаны в соответствии с verbatim-category-code-regime.
    Вместо того, чтобы вкладывать эти аргументы в фигурные скобки, вы можете использовать verbatim-разделители, например, с \verb-command, если вам это нравится или необходимо.

    В основном тексте эти аргументы будут переданы в eTeX \scantokens.

    Эти аргументы также будут дословно скопированы/записаны в .aux-файл и в файлы \jobname.rvallи \jobname.rvdoeсоответствующие \jobname.rvsmith.

Вы можете импортировать файлы \jobname.rvallи \jobname.rvdoe/ \jobname.rvsmithв другие документы TeX через \input.
Все, что вам нужно сделать, это убедиться, что в этих других документах TeX макросы \responselinewithreviewer/ \responselinewithoutreviewerопределены для обработки трех аргументов.
Если вы используете \UDcollectverbargfrom below для их определения таким образом, чтобы они считывали второй и третий аргументы под verbatim-category-code-régime с \verb-syntax, вы можете заставить их содержать такие вещи, как \verbи несбалансированные фигурные скобки.

Суть такова:

Это своего рода повторная реализация / -механизма ядра LaTeX 2e. (Этот механизм также лежит в основе / , , , и т. д.)@starttoc{⟨tocfile⟩}\addtocontents{⟨tocfile⟩}{...}\tableofcontents\addcontentsline\listoffigures\listoftables

Повторная реализация считывает и обрабатывает аргументы в режиме verbatim-category-code-régime.

\listofallresponsesдоставляет все комментарии и ответы.

\dummylistofallresponsesприводит .rvallк записи файла без добавления данных в документ.

\listofreviewersresponses{⟨reviewer⟩}доставляет все комментарии и ответы, которые принадлежат⟨рецензент⟩.

\dummylistofreviewersresponses{⟨reviewer⟩}вызывает.rv⟨reviewer⟩-файл, который будет записан без передачи его содержимого в документ.

Файл test.tex:

% Due to usage of \detokenize and \scantokens compiling this file
% requires LaTeX with eTeX-extensions.
\makeatletter
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
%%=============================================================================
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstofone{\expandafter} %
  \@secondoftwo}{\@firstofone{\expandafter} \@firstoftwo}%
}%
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%
%% \UD@ExtractKthArg{<integer K>}{<list of undelimited args>} 
%% 
%% In case there is no K-th argument in <list of indelimited args> : 
%%   Does not deliver any token.
%% In case there is a K-th argument in <list of indelimited args> : 
%%   Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%%   \UD@ExtractKthArg{0}{ABCDE} yields: <nothing>
%%
%%   \UD@ExtractKthArg{3}{ABCDE} yields:  C
%%
%%   \UD@ExtractKthArg{3}{AB{CD}E} yields:  CD
%%
%%   \UD@ExtractKthArg{4}{{001}{002}{003}{004}{005}} yields: 004
%%
%%   \UD@ExtractKthArg{6}{{001}{002}{003}} yields: <nothing> 
%% 
%%=============================================================================
\newcommand\UD@ExtractKthArg[1]{%
  \romannumeral0%
  % #1: <integer number K>
  \expandafter\UD@ExtractKthArgCheck
  \expandafter{\romannumeral\number\number#1 000}%
}%
\newcommand\UD@ExtractKthArgCheck[2]{%
  \UD@CheckWhetherNull{#1}{ }{%
    \expandafter\UD@ExtractKthArgLoop\expandafter{\@firstoftwo{}#1}{#2}%
  }%
}%
\newcommand\UD@ExtractKthArgLoop[2]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo#2{}.}{ }{%
    \UD@CheckWhetherNull{#1}{%
      \UD@ExtractFirstArgLoop{#2\UD@SelDOm}%
    }{%
      \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#2}%
      {\expandafter\UD@ExtractKthArgLoop\expandafter{\@firstoftwo{}#1}}%
    }%
  }%
}%
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\@firstoftwo\expandafter{} \@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% Check whether argument contains no exclamation mark which is not nested in 
%% braces:
%%.............................................................................
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains no exclamation mark>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains exclamation mark>}%
%%=============================================================================
\newcommand\UD@GobbleToExclam{}\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%=============================================================================
%% Act depending on whether argument is "John Doe" or "John Smith":
%% \reviewerfork{<Argument>}{%
%%   {<tokens in case <Argument> is John Doe>}%
%%   {<tokens in case <Argument> is John Smith>}%
%%   {<tokens in case <Argument> is something else>}%
%% }
%%=============================================================================
\newcommand\reviewerfork[1]{%
  \romannumeral0%
  \UD@CheckWhetherNoExclam{#1}{%
    \@reviewerfork
    !#1!John Smith!{\@firstoftwo{\expandafter\expandafter\expandafter}{} \UD@ExtractKthArg{1}}%
    !John Doe!#1!{\@firstoftwo{\expandafter\expandafter\expandafter}{} \UD@ExtractKthArg{2}}%
    !John Doe!John Smith!{\@firstoftwo{\expandafter\expandafter\expandafter}{} \UD@ExtractKthArg{3}}%
    !!!!%
  }{%
   \@firstoftwo{\expandafter\expandafter\expandafter}{} \UD@ExtractKthArg{3}%
  }%
}%
\newcommand\@reviewerfork{}%
\long\def\@reviewerfork#1!John Doe!John Smith!#2#3!!!!{#2}%
%%=============================================================================
%% Act depending on whether is known/unknown:
%% \CheckWhetherReviewerknown{<Argument>}
%%                           {<tokens in case <Argument> is a known reviewer>}%
%%                           {<tokens in case <Argument> is not a known reviewer>}%
%%=============================================================================
\newcommand\CheckWhetherReviewerknown[1]{%
  \romannumeral0%
  \reviewerfork{#1}{%
     {\@firstofone{\expandafter} \@firstoftwo}%
     {\@firstofone{\expandafter} \@firstoftwo}%
     {\@firstofone{\expandafter} \@secondoftwo}%
  }%
}%
%%=============================================================================
%% Error-message in case the reviewer is unknown:
%% \unknownreviewererror{<reviewer>}%
%%                      {<name of macro that called \unknownreviewererror>}
%%=============================================================================
\newcommand\unknownreviewererror[2]{%
  \GenericError{%
    \space\space\space\@spaces\@spaces\@spaces
  }{%
   \@backslashchar#2-error\on@line: Reviewer `\detokenize{#1}' unknown%
  }{%
    See the comments of this file for explanation.%
  }{%
    Known reviewers in this demo are `John Doe' and `John Smith'.%
    \MessageBreak(The reviewer-argument is case sensitive.)%
  }%
}%
%%======================Code for \UDcollectverbarg=============================
%% \UDcollectverbarg{^^M-replacement}{<mandatory 1>}{<mandatory 2>}|<verbatim arg>|
%% 
%% reads <verbatim arg> under verbatim-catcode-regime and delivers:
%%
%%    <mandatory 1>{<mandatory 2>{<verbatim arg>}{|<verbatim arg>|}}
%%
%% Instead of verbatim-delimiter | the <verbatim arg> can be nested in braces.
%% You cannot use percent or spaces or horizontal tab as verbatim-delimiter.
%%
%% You can use <mandatory 1> for nesting calls to \UDcollectverbarg.
%% <mandatory 2> gets the <verbatim arg> twice: Once without verbatim-delimiters/braces,
%% once surrounded by verbatim-delimiters/braces.
%% Reason: When you feed it to \scantokens you don't need the verbatim-delimiters.
%%         When you use it for writing to temporary files and reading back,
%%         you need them.
%%=============================================================================
\begingroup
\catcode`\^^M=12 %
\@firstofone{%
  \endgroup%
  \newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
  \@ifdefinable\@UDEndlreplace{%
    \long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
      \UD@CheckWhetherNull{#3}%
      { #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
    }%
  }%
}%
\newcommand\UDcollectverbarg[3]{%
  \begingroup
  \let\do\@makeother % <- this and the next line switch to
  \dospecials        %    verbatim-category-code-régime.
  \catcode`\{=1      % <- give opening curly brace the usual catcode so a 
                     %    curly-brace-balanced argument can be gathered in
                     %    case of the first thing of the verbatimized-argument 
                     %    being a curly opening brace.
  \catcode`\ =10     % <- give space and horizontal tab the usual catcode so \UD@collectverbarg
  \catcode`\^^I=10   %    cannot catch a space or a horizontal tab as its 4th undelimited argument.
                     %    (Its 4th undelimited argument denotes the verbatim-
                     %     syntax-delimiter in case of not gathering a
                     %     curly-brace-nested argument.)
  \catcode`\%=14     % <- make percent comment.
  \kernel@ifnextchar\bgroup
  {% seems a curly-brace-nested argument is to be caught:
    \catcode`\}=2    % <- give closing curly brace the usual catcode also.
    \UD@collectverbarg{#1}{#2}{#3}{}%
  }{% seems an argument with verbatim-syntax-delimiter is to be caught:
    \do\{% <- give opening curly brace the verbatim-catcode again.
    \UD@collectverbarg{#1}{#2}{#3}%
  }%
}%
\newcommand\UD@collectverbarg[4]{%
  \do\ %   <- Now that \UD@collectverbarg has the delimiter or
  \do\^^I%    emptiness in its 4th arg, give space and horizontal tab
         %    the verbatim-catcode again.
  \do\^^M% <- Give the carriage-return-character the verbatim-catcode.
  \do\%%   <- Give the percent-character the verbatim-catcode.
  \long\def\@tempb##1#4{%
    \def\@tempb{##1}%
    \UD@CheckWhetherNull{#4}{%
      \def\@tempc{{##1}}%
    }{%
      \def\@tempc{#4##1#4}%
    }%
    \@onelevel@sanitize\@tempb % <- Turn characters into their "12/other"-pendants.
                               %    This may be important with things like the 
                               %    inputenc-package which may make characters 
                               %    active/which give them catcode 13(active).
    \expandafter\UDEndlreplace\expandafter{\@tempb}{#1}{\def\@tempb}% <- this starts 
                               %    the loop for replacing endline-characters.
    \@onelevel@sanitize\@tempc
    \expandafter\UDEndlreplace\expandafter{\@tempc}{#1}{\def\@tempc}%
    \expandafter\expandafter\expandafter\UD@@collectverbarg% <- this "spits out the result.
    \expandafter\expandafter\expandafter{%
    \expandafter\@tempb\expandafter}%
    \expandafter{\@tempc}{#2}{#3}%
  }%
  \@tempb
}%
\newcommand\UD@@collectverbarg[4]{%
  \endgroup
  #3{#4{#1}{#2}}%
}%
%%================= End of code for \UDcollectverbarg =========================
%%=============================================================================
%% \response{<reviewer>}{<comment>}{<response>}
%%    adds entries to toc-like-files \jobname.rvdoe or \jobname.rvsmith
%%    and \jobname.rvall
%%=============================================================================
\@ifdefinable\response{%
  \outer\long\def\response#1{%
    \UDcollectverbarg{^^J}{%
      \UDcollectverbarg{^^J}{\@firstofone}%
    }{\innerresponse{#1}}%
  }%
}%
\begingroup
% Now ^^A is used instead of %:
\catcode`\^^A=\the\catcode`\%\relax
\catcode`\%=12\relax
\@firstofone{^^A
  \endgroup
  \newcommand\innerresponse[5]{^^A
    ^^A #1 = <reviewer>
    ^^A #2 = <verbatimized comment without surrounding verbatim-delimiters>
    ^^A #3 = <verbatimized comment with surrounding verbatim-delimiters>
    ^^A #4 = <verbatimized response without surrounding verbatim-delimiters>
    ^^A #5 = <verbatimized response with surrounding verbatim-delimiters>
    \CheckWhetherReviewerknown{#1}{^^A
      \par\bigskip\noindent Comment by reviewer #1\\Comment: \scantokens{#2%}\\Response: \scantokens{#4%}^^A
      \responseentries{#1}{#3}{#5}^^A
    }{^^A
      \unknownreviewererror{#1}{response}^^A
    }^^A
  }^^A
  \newcommand\@innerresponsewritefile[1]{^^A
    \renewcommand\@innerresponsewritefile[6]{^^A
      ^^A #1 = space token
      ^^A ##1 = rv<reviewer>  (filename-extension)
      ^^A ##2 = <reviewer>
      ^^A ##3 = <verbatimized comment without surrounding verbatim-delimiters>
      ^^A ##4 = <verbatimized comment with surrounding verbatim-delimiters>
      ^^A ##5 = <verbatimized response without surrounding verbatim-delimiters>
      ^^A ##6 = <verbatimized response with surrounding verbatim-delimiters>
      \expandafter\UD@PassFirstToSecond\expandafter{^^A
                             \string\responselinewithreviewer^^J#1#1{##2}%^^J#1#1##4%^^J#1#1##6%^^A
                           }^^A
                           {\@writefile{rvall}}^^A
      \expandafter\UD@PassFirstToSecond\expandafter{^^A
                             \string\responselinewithoutreviewer^^J#1#1{##2}%^^J#1#1##4%^^J#1#1##6%^^A
                           }^^A
                           {\@writefile{##1}}^^A
    }^^A
  }^^A
  \@innerresponsewritefile{ }^^A
  \newcommand\innerresponselinewithreviewer[5]{^^A
    ^^A #1 = <reviewer>
    ^^A #2 = <verbatimized comment without surrounding verbatim-delimiters>
    ^^A #3 = <verbatimized comment with surrounding verbatim-delimiters>
    ^^A #4 = <verbatimized response without surrounding verbatim-delimiters>
    ^^A #5 = <verbatimized response with surrounding verbatim-delimiters>
    \par\bigskip\noindent Comment by reviewer #1\\Comment: \scantokens{#2%}\\Response: \scantokens{#4%}^^A
  }^^A
  \newcommand\innerresponselinewithoutreviewer[5]{^^A
    ^^A #1 = <reviewer>
    ^^A #2 = <verbatimized comment without surrounding verbatim-delimiters>
    ^^A #3 = <verbatimized comment with surrounding verbatim-delimiters>
    ^^A #4 = <verbatimized response without surrounding verbatim-delimiters>
    ^^A #5 = <verbatimized response with surrounding verbatim-delimiters>
    \par\bigskip\noindent Comment: \scantokens{#2%}\\Response: \scantokens{#4%}^^A
  }^^A
}% <- \@firstofone with changed catcodes done.
\newcommand\responseentries[3]{%
  % #1 = <reviewer>
  % #2 = <verbatimized comment with surrounding verbatim-delimiters>
  % #3 = <verbatimized response with surrounding verbatim-delimiters>
  \protected@write\@mainaux{}{%
     \string\@responsewritefile{\reviewerfork{#1}{{rvdoe}{rvsmith}{}}}\@percentchar^^J\space\space
     {#1}\@percentchar^^J\space\space
     #2\@percentchar^^J\space\space
     #3\@percentchar
  }%
}%
\newcommand\@responsewritefile[2]{%
  % #1 = rv<reviewer>  (filename-extension)
  % #2 = <reviewer>
  \UDcollectverbarg{^^J}{%
    \UDcollectverbarg{^^J}{\@firstofone}%
  }{\@innerresponsewritefile{#1}{#2}}%
}%
\newcommand\responselinewithreviewer[1]{%
  % #1 = <reviewer>
  \UDcollectverbarg{^^J}{%
    \UDcollectverbarg{^^J}{\@firstofone}%
  }{\innerresponselinewithreviewer{#1}}%
}%
\newcommand\responselinewithoutreviewer[1]{%
  % #1 = <reviewer>
  \UDcollectverbarg{^^J}{%
    \UDcollectverbarg{^^J}{\@firstofone}%
  }{\innerresponselinewithoutreviewer{#1}}%
}%
%%=============================================================================
%% \listofallresponses
%%   delivers all comments and responses.
%%
%% \dummylistofallresponses
%%   causes the .rvall-file to be written without delivering things into
%%   the document.
%%=============================================================================
\newcommand\listofallresponses{%
  \par\noindent ALL COMMENTS\par
  \@starttoc{rvall}%
}%
\newcommand\dummylistofallresponses{%
  \@dummystarttoc{rvall}%
}%
%%=============================================================================
%% \listofreviewersresponses{<reviewer>}%
%%   delivers all comments and responses that belong tp <reviewer>.
%%
%% \dummylistofreviewersresponses{<reviewer>}%
%%   causes the .rv<reviewer>-file to be written without delivering its 
%%   content into the document.
%%=============================================================================
\newcommand\listofreviewersresponses[1]{%
   \reviewerfork{#1}{%
     {\par\noindent COMMENTS BY REVIEWER JOHN DOE\par\@starttoc{rvdoe}}%
     {\par\noindent COMMENTS BY REVIEWER JOHN SMITH\par\@starttoc{rvsmith}}%
     {\unknownreviewererror{#1}{listofreviewersresponses}}%
   }%
}%
\newcommand\dummylistofreviewersresponses[1]{%
   \reviewerfork{#1}{%
     {\@dummystarttoc{rvdoe}}%
     {\@dummystarttoc{rvsmith}}%
     {\unknownreviewererror{#1}{dummylistofreviewersresponses}}%
   }%
}%
\newcommand\@dummystarttoc[1]{%
  \begingroup
  \makeatletter
  \if@filesw
    \expandafter\newwrite\csname tf@#1\endcsname
    \immediate\openout\csname tf@#1\endcsname\jobname.#1\relax
  \fi
  \@nobreakfalse
  \endgroup 
}%
\makeatother

\documentclass{article}
\usepackage{verbatim}% <- used only for \verbatiminput

\begin{document}
\enlargethispage{3cm}%
\vspace*{-3cm}%
\par\bigskip\noindent\textbf{\jobname.rvall looks like this:}

\verbatiminput{\jobname.rvall}%

\par\bigskip\noindent\textbf{\jobname.rvdoe looks like this:}

\verbatiminput{\jobname.rvdoe}%

\par\bigskip\noindent\textbf{\jobname.rvsmith looks like this:}

\verbatiminput{\jobname.rvsmith}%

\newpage

\InputIfFileExists{\jobname.rvall}{\par\bigskip\noindent\textbf{Inputting \jobname.rvall yields:}}{}

\InputIfFileExists{\jobname.rvdoe}{\par\bigskip\noindent\textbf{Inputting \jobname.rvdoe yields:}}{}%

\InputIfFileExists{\jobname.rvsmith}{\par\bigskip\noindent\textbf{Inputting \jobname.rvsmith yields:}}{}%

\newpage

% now let's cause the .rvall-file and the .rvdoe-file and the .rvsmith-file
% to be created_
%
% This will also import the files:
%
%\listofreviewersresponses{John Smith}%
%\bigskip
%\listofallresponses
%\bigskip
%\listofreviewersresponses{John Doe}%
%
% This will cause creation of these files only.
%
\dummylistofallresponses
\dummylistofreviewersresponses{John Smith}%
\dummylistofreviewersresponses{John Doe}%

\par\bigskip\noindent\textbf{The text of the main document is:}

\bigskip\noindent Some text.

\response{John Doe}{John Doe's first comment.}{Response to John Doe's first comment.}
\response{John Smith}%
         {John Smith's first comment.}%
         {Response to John Smith's first comment.}
\response{John Doe}{John Doe's second comment. It has verbatim
material: \verb|\TeX is funny|.
}{Response to John Doe's second comment.}
\response{John Smith}%
         {John Smith's second comment.}%
         |Response to John Smith's second comment. 
It has verbatim material 
with unbalanced braces:
\verb+\TeX}}} is funny!+|

\end{document}

введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

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