[Tex/LaTex] How to resolve clashing definitions of \comment in comment.sty and changes.sty without affecting either’s interface

changescommentsenvironmentsmacrospackage-writing

I'm writing a package that uses both changes (v3.1.2) and comment (v3.8), and I'd like to expose their functionality to consumers of my package without having to modify either one's interface.

The problem is that both changes.sty and comment.sty define \comment. Hence

\documentclass{article}
\usepackage{comment}
\usepackage{changes}
\begin{document}\end{document}

throws the error

Command \comment already defined.

I understand this can be fixed using savesym by (essentially) modifying changes.sty's interface, e.g.

\documentclass{article}
\usepackage{savesym}

\usepackage{changes}
\savesymbol{comment} % rename \comment -> \origcomment
\usepackage{comment}

\begin{document}
\origcomment{pdf comment using 'changes.sty'}
\begin{comment}
code comment using 'comment.sty'
\end{comment}
\end{document}

Alternatively, comment.sty provides \excludecomment for defining custom comment environments, e.g.

\documentclass{article}
\usepackage{savesym}

\usepackage{comment}
\savesymbol{comment}
\excludecomment{mycomment}
\usepackage{changes}

\begin{document}
\comment{pdf comment using 'changes.sty'}
\begin{mycomment}
code comment using 'comment.sty'
\end{mycomment}
\end{document}

but changes.sty breaks the default comment environment.

Is it possible to build a layer in my package which mediates between changes.sty's \comment command and comment.sty's comment environment? The aim is to expose the original interface of each to a consumer of my package.


The two clashing definitions are as follows:

% changes.sty line 791
\newcommand{\comment}[2][\@empty]{%
\setkeys{Changes@comment}{#1}%
\Changes@output%
{comment}%
{\Changes@comment@id}%
{}%
{}%
{#2}%
{\changescommentname}%
{#2}%
}
% comment.sty line 241
\def\excludecomment
 #1{\message{Excluding comment '#1'}%
    \csarg\def{#1}{\endgroup \message{Excluding '#1' comment.}%
        \begingroup
           \DefaultCutFileName \def\ProcessCutFile{}%
           \def\ThisComment####1{}\ProcessComment{#1}}%
    \csarg\def{After#1Comment}{\CloseAndInputCutFile \endgroup}
    \CommentEndDef{#1}}
% ...
% line 292
\excludecomment{comment}

Best Answer

You can via \let save both the \comment-macro which underlies the comment-environment of the comment package and the \comment-macro which comes with the changes-package.

Then you can define your own \comment-macro which "looks" at the definition of \@currenvir.

If \@currenvir = comment, then executing \comment imples calling the macro which underlies the comment-environment.
Otherwise executing \comment implies calling the macro which comes from the changes-package.

Be aware that with the following example I said \includecomment{comment} so that the content of comment-environments results in visual output.

\documentclass{article}

\makeatletter
\newcommand*\UD@CommentName{comment}%
\newcommand\UDsavedcommentenvironment{}%
\newcommand\UDsavedcommentmacro{}%
\usepackage{changes}[2019/01/26 v3.1.2]
\let\UDsavedcommentmacro=\comment
\let\comment=\relax
\usepackage{comment}%[2016/07/16 v3.8]
\includecomment{comment}%
%\excludecomment{comment}%
\let\UDsavedcommentenvironment=\comment
\let\comment=\relax
\newcommand\comment{%
  \ifx\@currenvir\UD@CommentName
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\UDsavedcommentenvironment}{\UDsavedcommentmacro}%
}%
\makeatother

\begin{document}
\null
\comment{A pdf comment using `changes.sty'.}%
\begin{comment}
A code comment using `comment.sty'.
\end{comment}
\comment{Another pdf comment using `changes.sty'.}%
\begin{comment}
Another code comment using `comment.sty'.
\end{comment}
Some text.
\end{document}

enter image description here

Related Question