# A new environment to decide dynamically which commands to run?

I am having some user defined commands defined and used in my latex document. I need a way to check whether any of the commands is used. I want to make decisions based on the argument used in the command. Can I do this by defining a user defined environment? Please let me know what should be done here.

Example code:

\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\title{Latex Document}
\author{Eddy}
\begin{document}
\maketitle
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.}


I want to find out programmatically if \deleteline command is used in the content. I also want to find out what's the first argument used.

Edit: I am going to add a detailed use case of my current requirement. My input code is as follows. Please note that \begin{analyze}{eddy} is the new environment that is to be defined yet.

\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\title{Latex Document}
\author{Eddy}
\begin{document}
\maketitle
\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\end{document}

If no argument is passed to the new environment,

\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}


Output: All changes done by all users are taken into consideration

If 'eddy' is given as an input,

\begin{analyze}{eddy}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}


Output: Only changes by done by Eddy is considered. Other users changes are ignored.

\begin{analyze}{Margret}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}


Output: Only changes done by Margret is considered. All other changes are ignored.

-
Welcome to TeX.sx! Please add a minimal working example (MWE) that illustrates your problem. It will be much easier for us to reproduce your situation and find out what the issue is when we see compilable code, starting with \documentclass{...} and ending with \end{document}. –  Paul Gaborit Feb 20 '13 at 6:58
A rather, simple yet direct way to see wether you are using a command or not is to search through your editor the command you wish to check. In many editors this is done usually, by ctrl + f... –  Thanos Feb 20 '13 at 7:23
@Thanos Make a simple document and try if you are using \@firstoftwo. You will find you are not. However, you are. As well, good typesetter splits his document into several files if it's long. –  yo' Feb 20 '13 at 7:41
@tohecz: You are right;I cannot find it because it is running from the class... In this very case, he is defining a command in his very own document, so he will be able to see wether he is using his command, isn't that right? –  Thanos Feb 20 '13 at 9:49
@Thanos as long as he doesn't split the document into pieces, like many people (correctly) do. –  yo' Feb 20 '13 at 9:51

The cmdtrack package is designed for this. To quote its summary:

The pack­age keeps track of whether a com­mand de­fined in a doc­u­ment pream­ble is ac­tu­ally used some­where in the doc­u­ment. After the pack­age is loaded in the pream­ble of a doc­u­ment, all \new­com­mand (and sim­i­lar com­mand def­i­ni­tions) be­tween that point and the be­gin­ning of the doc­u­ment will be marked for log­ging. At the end of the doc­u­ment a re­port of com­mand us­age will be printed in the TeX log, for ex­am­ple: – “mdash was used on line 25”; – “ndash was never used”.

It doesn't track every command, but does handle things like \newtheorem as well as \newcommand. See the documentation for full details.

-
(This was posted to answer an early version of the question where the emphasis seemed to be on tracking whether a user-defined command was used. The subsequent edit makes this not so relevant any more.) –  Loop Space Feb 21 '13 at 9:02

You can modify any command by saving the old defintion via \let and then using \renewcommand to add code to it. The analyze environment here redefines the \deleteline and \addline macros so that the redefinition is local to within the analyze environment. Hence, outside of this environment, these two macros behave as originally defined:

## References:

• As A.Ellett mentioned, using the \let macro won't work for all cases and you need to use \LetLtxMacro instead. See When to use \LetLtxMacro? for more details.

## Code:

\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}
\usepackage{xstring}

\newcommand{\deleteline}[2]{\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}}
\title{Latex Document}
\author{Eddy}
%

% Keep original defintion of "\deleteline" and "\addline" around
\let\OldDeleteline\deleteline%

\newenvironment{analyze}[1][]{%
\edef\AnalyzeUserName{#1}% set this to the given user name
% These redefinitions are only within this environment
\renewcommand{\deleteline}[2]{%
% We allow all users changes
\OldDeleteline{##1}{##2}%
}{%
% Since some non-empty name was specified only allow if name matches.
\OldDeleteline{##1}{##2}%
}{%
% Don't do anything here as the name did not match given name.
}%
}%
}%
% We allow all users changes
}{%
% Since some non-empty name was specified only allow if name matches.
}{%
% Don't do anything here as the name did not match given name.
}%
}%
}%
}%

\begin{document}
\maketitle
% -----------------
\textbf{No option}\par
\begin{analyze}
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}

\textbf{option=eddy}\par
\begin{analyze}[eddy]
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}

\textbf{option=Margret}\par
\begin{analyze}[Margret]
As part of this project, we intend to study the complex structures of Latex. \deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is to be added.}
\end{analyze}
\end{document}

-
Thanks for your reply. I will be more clear with my requirement. Here it is. 1. I want to pass on an argument (for example, 'eddy') to my user defined environment. 2. The environment will check if \deleteline command is used. If it's used with the argument 'eddy', I need to to remove that line. 3. Any \deleteline command with any other argument (i.e, not 'eddy' should be ignored. Please let me know if I am clear. –  eddyrokr Feb 20 '13 at 18:30
@user1515489: Not sure I fully understand. Instead of describing it, I think you should mock up a real example of how you want this to be (as far as the input), and what the desired output is. That will also serve as a test case. For the part you are not sure about, just add pseudo code as comments. This way those trying to help can just focus on exactly what you require and have a test case to test to see that it satisfies your needs. Basically build the test case you will need to be sure that any proposed solution works as you desire. –  Peter Grill Feb 20 '13 at 18:36
I have edited my question with an use case example. –  eddyrokr Feb 20 '13 at 19:02
@eddyrokr: But you have not defined how the decision is to be made in terms of when do you want the text deleted. In what case would the text not be deleted? A proper test case should check all the possible cases to ensure that it works for the cases you want it to. I supposed you want the text deleted if its parameter matches the anyalze environment's parameter. Do you want to allow for the parameter to be a list such as \begin{analyze}{eddy,fred,mike} or will it always only be one name? –  Peter Grill Feb 20 '13 at 21:56
Making the parameter a list is not of the priority now. The only priority is to bring out this functionality with the help of an environment. Using just an argument is fine for now. –  eddyrokr Feb 20 '13 at 22:37

I don't see the need for a environment here. If you just set a master variable which is taken for comparison it's easier.

\documentclass{report}
\usepackage{ulem}

\makeatletter
\def\@mytemp{}
\newcommand\setmaster[1]{
\def\@mytemp{#1}
}

\newcommand\del[2]{%
\def\@mytempa{#1}%%
\ifx\@mytempa\@mytemp%
\sout{#2}%
\fi%
}
\makeatother

\setmaster{eddy}

\begin{document}

Some text \del{eddy}{See me striked out.}\del{andy}{See me not at all}

\end{document}


As you see here everything which is not written by the master will not appear. The check for 'eddy' is done by the macro itself and on every call. This means that the 'master' must be set via \setmaster. Note that this uses very low level comparisons. If you have the need for more complex comparisons one could involve etoolbox or l3.

## Update (after edit)

Now first take a look at the output:

I used a optional argument because it is optional. You may add style and color as you please. You also may control the spaces a bit more carefully than i probably did.

\documentclass{report}
\usepackage{ulem}

\makeatletter

\newenvironment{analyse}[1][]{\bgroup%
\def\@myarga{#1}%
%
\ifx\@myarga\empty% if #1 is nothing we simply whant everything
\def\del##1##2{\textsuperscript{##1} \sout{##2}}%
\else% if name given:
\def\del##1##2{%
\def\@master{##1}%
\ifx\@myarga\@master% if name in local macro is = name in envir arg
\textsuperscript{##1}\sout{##2}%
\fi%
%
}
\def\add##1##2{% Just another command, same logic
\def\@master{##1}%
\ifx\@myarga\@master%
\textsuperscript{##1}##2%
\fi%
}
%
\fi%
}%
{\egroup\par}

\makeatother

\begin{document}
\begin{analyse}[eddy]
Argument \texttt{[eddy]}: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}[andy]
Argument \texttt{[andy]}: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}[]
Argument \texttt{[]} (empty): \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\begin{analyse}
No Argument: \del{eddy}{See me striked out.}\add{andy}{See me not at all}
\end{analyse}
\end{document}


As i said before a environment makes no much sense here. A simple macro to switch the name (or to nothing) would be sufficient. This btw. does not decide whether to run the \add or \del command dynamically, it just gobbles (does nothing with) the arguments given, if the conditions aren't met.

-
Why \bgroup at the start of analyse? And why redefining \del and \add each time? –  egreg Feb 21 '13 at 14:43
bgroup it's just an artefact and should make no difference... and for the redefining: i wanted those commands not to survive the group. And so far as i understand my code they are def'ed excatly one time per environment and so ther should be no great influence to the performance. Nevertheless i do not think that this is the most elegant way and i appreciate any hints. The solution for @CharlesSteward i posted the in chat chat.stackexchange.com/transcript/message/8203592#8203592 is significantly smaller (if one would strip it of the \csname stuff ;-) ) –  bloodworks Feb 21 '13 at 14:56

It's probably better to change the definitions of \deleteline and \addline to do a check on their first argument; if the check is passed, the real work is performed, otherwise nothing is done.

\documentclass[12pt]{article}
\usepackage{xparse}
\usepackage{ulem}
\usepackage{color}
\newcommand{\deleteline}[2]{%
\checkeditor{#1}{%
\textsuperscript{\textcolor{black}{ #1}} \textcolor{red}{\sout{#2}}%
}%
}
\checkeditor{#1}{%
\textsuperscript{\textcolor{black}{ #1}} \textcolor{green}{#2}%
}%
}

\ExplSyntaxOn
\seq_new:N \l_eddy_editors_seq
\bool_new:N \l_eddy_alleditors_bool

% analyze has one optional argument
\NewDocumentEnvironment{analyze}{o}
{
\IfNoValueTF{#1}
{% no argument expressed, all editors are good
\bool_set_true:N \l_eddy_alleditors_bool
}
{% only the mentioned editors are accepted
\bool_set_false:N \l_eddy_alleditors_bool
% store the names in a sequence
\seq_set_split:Nnn \l_eddy_editors_seq { , } { #1 }
}
}
{ }
\NewDocumentCommand{\checkeditor}{mm}
{
\bool_if:NTF \l_eddy_alleditors_bool
{% all editors are good
#2
}
{% check if #1 is in the accepted names
\seq_if_in:NnT \l_eddy_editors_seq { #1 } { #2 }
}
}
\ExplSyntaxOff
\begin{document}

\title{Latex Document}
\author{Eddy}

\maketitle

\begin{analyze}
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is
\end{analyze}

\begin{analyze}[eddy]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is
\end{analyze}

\begin{analyze}[Margret]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is
\end{analyze}

\begin{analyze}[eddy,Margret]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line will be stroked through.} \addline{Margret}{This line is
\end{analyze}

\end{document}


If you don't want to show the deleted parts when an editor is expressed, then the following should do:

\documentclass[12pt]{article}
\usepackage{xparse}
\usepackage{ulem}
\usepackage{color}
\ExplSyntaxOn

\seq_new:N \l_eddy_editors_seq
\bool_new:N \l_eddy_alleditors_bool

\NewDocumentCommand{\deleteline}{mm}
{
\bool_if:NTF \l_eddy_alleditors_bool
{\textsuperscript{\textcolor{black}{~#1}}~\textcolor{red}{\sout{#2}}}
{\seq_if_in:NnF \l_eddy_editors_seq { #1 } { #2 }}
}
{
\bool_if:NTF \l_eddy_alleditors_bool
{\textsuperscript{\textcolor{black}{~#1}}~\textcolor{green}{#2}}
{\seq_if_in:NnT \l_eddy_editors_seq { #1 } { #2 }\ignorespaces}
}

% analyze has one optional argument
\NewDocumentEnvironment{analyze}{o}
{
\IfNoValueTF{#1}
{% no argument expressed, all editors are good
\bool_set_true:N \l_eddy_alleditors_bool
}
{% only the mentioned editors are accepted
\bool_set_false:N \l_eddy_alleditors_bool
% store the names in a sequence
\seq_set_split:Nnn \l_eddy_editors_seq { , } { #1 }
}
}
{ }

\ExplSyntaxOff
\begin{document}

\title{Latex Document}
\author{Eddy}

\maketitle

\begin{analyze}
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line has been stroked through by eddy.}
\end{analyze}

\begin{analyze}[eddy]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line has been stroked through by eddy.}
\end{analyze}

\begin{analyze}[Margret]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line has been stroked through by eddy.}
\end{analyze}

\begin{analyze}[eddy,Margret]
As part of this project, we intend to study the complex structures of Latex.
\deleteline{eddy}{This line has been stroked through by eddy.}
\end{analyze}

\end{document}


The code is almost straightforward. The analyze environment checks for the presence of an optional argument. If there's not, the boolean variable \l_eddy_alleditors_bool is set to true (it's by default false), otherwise it stores in a sequence all the editor names, splitting the comma separated list of them.

The \deleteline and \addline commands work differently when the boolean is true or false. If it's true, \deleteline will print the editor's name and the text in red and struck out; instead \addline will print the editor's name and the text in green.

If the boolean is false, \deleteline will print the text only if the editor didn't appear in the list (with \seq_if_in:NnF) and \addline will print the text only if the editor appears in the list (with \seq_if_in:NnT).

-
Your method works awesome if I have to pass on a list. Thanks!! –  eddyrokr Mar 14 '13 at 20:06
Can you briefly explain what is the role of /ExplSyntaxOn and /ExplSyntaxOff here? And does these belong to the xparse package? –  eddyrokr Mar 14 '13 at 20:17
@eddyrokr They are the "LaTeX3 experimental" analogs of \makeatletter and \makeatother, for accessing to the programming environment and the macros with _ and : in their names. –  egreg Mar 14 '13 at 20:40
Can you please help me to modify your code so that the output is the logical versions of the stroked-out versions? That is, If "eddy" is given as an input, how can I reflect the changes done by "eddy" in the actual document. All stroked-out lines should be deleted and the added lines should be added as a normal text. –  eddyrokr Mar 14 '13 at 20:50
@eddyrokr I'm not sure I understand what you're asking. –  egreg Mar 14 '13 at 20:53

This does the job in 12 lines of code, giving a nestable environment and allowing edit racking to be switched on/off independently of the environment using \on{eddy}/\off{eddy

\documentclass[12pt]{article}
\usepackage{ulem}
\usepackage{color}

\def\on  #1{\csname #1true\endcsname  \relax}
\def\off #1{\csname #1false\endcsname \relax}
\def\analyze   #1{\def\analyzename{#1}\on\analyzename}
\def\endanalyze  {\off\analyzename}
\def\editor #1{\expandafter\newif\csname if#1\endcsname \off{#1}}
\newcommand{\deleteline}[2]{%
\expandafter{\let\ifbyeditor=}\csname if#1\endcsname
\ifbyeditor
\textsuperscript{\textcolor{black}{ #1}}%
\textcolor{red}{\sout{#2}}
\off{#1}  %Now it won't match the name again
\fi}

\title{Latex Document}
\author{Eddy}
\editor{eddy} \editor{amy}

\begin{document}
\maketitle

\def\line{\texttt{\analyzename} : One
\deleteline{eddy}{Eddy del}
Two
\deleteline{amy}{Amy del}
Three.}

\section{eddy}
\begin{analyze}{eddy}
\line
\end{analyze}

\section{amy}
\begin{analyze}{amy}
\line
\end{analyze}

\section{nested eddy/amy}
\begin{analyze}{eddy}
\begin{analyze}{amy}
\line
\end{analyze}
\end{analyze}

% The following code will fail, with a csname \jontrue undefined error
%   \begin{analyze}{jon}
%     \line
%   \end{analyze}
% Likewise, with csname \ifjon undefined:
%   \deleteline{jon}{Jon del}
% All editor names need to be declared with \editor or \newif

\end{document}


Edit Third version of the code, with thanks to bloodworks, David Carlisle, and especially egreg in chat for pointing out the issues in earlier iterations of the code.

-
why the \beingroup/\endgroup ? The latex environment implies a group anyway. Use of \edef makes it rather fragile, try repplacing eddy by mbox to see what I mean. –  David Carlisle Feb 21 '13 at 11:17

Here's a LaTeX3 solution which uses keywords to control the production of the text.

\documentclass{article}
\usepackage{ulem}
\usepackage{xcolor}
\usepackage{xparse}
\ExplSyntaxOn
%%
\tl_new:N    \g__ace_current_editor_tl
\prop_new:N  \g__ace_editors_plist
\clist_new:N \g__ace_active_editors_clist
%%
\bool_new:N        \g__ace_analysis_bool
\bool_gset_false:N \g__ace_analysis_bool
%%--------------------------------------------------------------------------------
\cs_new:Npn \__ace_check_whether_new_editor:n #1 {
\prop_gput_if_new:Nnn \g__ace_editors_plist { #1 } { #1 }
\bool_if_exist:cF { g__ace_editor_#1_bool }
{
\bool_new:c       { g__ace_editor_ #1 _bool }
\bool_gset_true:c { g__ace_editor_#1_bool}
}
\tl_gset:Nn \g__ace_current_editor_tl { #1 }
}
%%--------------------------------------------------------------------------------
%% There are only two keys.  The syntax is either "add=<name>" or "del=<name>"
%% where "add" means something is being "added" to the text and "del" means
%% is being "deleted" from the text.
\keys_define:nn { editing }
{
\__ace_check_whether_new_editor:n {#1}
\bool_gset_false:N \g__ace_delete_bool
},

del .code:n = {
\__ace_check_whether_new_editor:n {#1}
\bool_gset_true:N \g__ace_delete_bool
}
}

%%--------------------------------------------------------------------------------
%% commands to control the "analyze" environment
%%--------------------------------------------------------------------------------
%% this command is called from within the "analyze" environment.  The names
%% passed to that environment are the individuals whose editing will be reflected
%% in the outputted text.  First set the boolean for each defined editor to "false".
%% Then, only those editors listed in the environment are switch to "true".
\cs_new:Nn \__activate_current_editors: {
\prop_map_inline:Nn \g__ace_editors_plist
{
\prop_if_in:NnF \g__ace_editors_plist { ##1 } { \__ace_check_whether_new_editor:n {##1} }
\bool_gset_false:c { g__ace_editor_##1_bool }
\clist_map_inline:Nn \g__ace_active_editors_clist
{
\str_if_eq:nnT { ##1 } { ####1 }
{
\bool_gset_true:c { g__ace_editor_##1_bool }
}
}
%%            I'm not sure why this following code doesn't accomplish
%%            what the above \clist_map_inline:Nn does.
%%            \clist_if_in:NnT \g__ace_active_editors_clist { ##1 }
%%                {
%%                    \msg_term:x { [IN]who ~ = ~ ##1 }
%%                    \bool_gset_true:c { g__ace_editor_##1_bool }
%%                }
}
}
%% after leaving the "analyze" environment, switch all the editors booleans
%% to "true".
\cs_new:Nn \__activate_all_editors: {
\prop_map_inline:Nn \g__ace_editors_plist
{
\bool_gset_true:c { g__ace_editor_##1_bool }
}
}

%%--------------------------------------------------------------------------------
%% commands to control the "edit" command
%%--------------------------------------------------------------------------------
%% Note that mark up should not appear within the "analyze" environment.
\cs_new_protected:Npn \__ace_delete_content:n #1 {
\bool_if:NF \g__ace_analysis_bool
{    \textcolor{red}{\sout{#1}} }
}
\cs_new_protected:Npn \__ace_insert_content:n #1 {
\bool_if:NTF \g__ace_analysis_bool
{ #1 }
{ \textcolor{blue}{#1} }
}

%%--------------------------------------------------------------------------------
%% USER INTERFACE
%%--------------------------------------------------------------------------------
%% This environment takes a mandatory argument which specifies the edits of
%% which editors will be shown.
\DeclareDocumentEnvironment{analyze}{ m }
{
\bool_gset_true:N \g__ace_analysis_bool
\clist_gset:Nn \g__ace_active_editors_clist {#1}
\__activate_current_editors:
}
{
\bool_gset_false:N \g__ace_analysis_bool
\__activate_all_editors:
}
\NewDocumentCommand{\edit}{ O{del=master} m }
{
\keys_set:nn { editing } { #1 }
\bool_if:NF \g__ace_analysis_bool
{
{}\textsuperscript{\tl_use:N \g__ace_current_editor_tl}
}
\bool_if:cT { g__ace_editor_ \g__ace_current_editor_tl _bool }
{
\bool_if:NTF \g__ace_delete_bool
{ \__ace_delete_content:n  }
{ \__ace_insert_content:n  }
{#2}
}
}
\ExplSyntaxOff
\pagestyle{empty}
\setlength{\parindent}{0pt}
\newcommand{\testcontent}{%
This is all as to be expected. \edit[del=Jack]{Martians rule!}
}

\begin{document}

\textbf{Shows all editors:}\par
\testcontent
\vspace{1cm}

\textbf{Shows only Betty and David:}\par
\begin{analyze}{Betty,David}
\testcontent
\end{analyze}
\vspace{1cm}

\textbf{Shows only Jack:}\par
\begin{analyze}{Jack}
\testcontent
\end{analyze}
\vspace{1cm}

\textbf{Shows all editors:}\par
\testcontent

Hello
\end{document}


The result of this document is:

-
There are some issues with spacing that could definitely use cleaning up. I'm not sure yet how to handle that aspect (regarding extra space creeping in). But it's late. I'll have to think about it later. –  A.Ellett Feb 21 '13 at 7:36
Also, there's a chunk of code in there, regarding clists that doesn't work as I expected it to. It's been commented out and a hack has been written in. But if anyone could tell me what's wrong with the commented out portion, I'd be much appreciative. –  A.Ellett Feb 21 '13 at 7:37
Can you please explain the code please? –  eddyrokr Mar 14 '13 at 16:11