2

While writing software documentation, the need arose for a command that automatically hyphenates camelCase words at uppercase letters, e.g. camel-Case. Furthermore, these camelCase words are typeset to a certain color. @David Carlisle provided the solution here via a command \zzz{camelCase}.

However, some of the camelCase variables are documented for internal use only. To this end there is a flag defined as

\newboolean{\internal}
\setboolean{internal}{true}

in a config file. In another post @Steven B. Segletes introduced a new command \zzzconditional to make variables disappear if \internal is false.

Now for the grand finale =) A large number of paragraphs in my document contain \zzzconditional commands but are also for internal use only, e.g.

\ifthenelse{\boolean{internal}}{%
    Here is a paragraph for internal use which will only appear when the \textbackslash internal flag is set to TRUE. But I also refer to a camelCase variable \zzzconditional{InpShaftActTrqSpdRndVar} using the aforementioned command.%
}{}%

Unfortunately,~custom hyphenation defined in \zzzconditional does not work in this context. More precisely,~hyphenation breaks entirely which results in overfull lines (see MWE).

Is there any implementation that allows the use of \zzzconditional inside an \ifthenelse command?

The following MWE consists of a main file that loads another file codeInput.tex through the \input command. Here is the code for the MWE's main file:

\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{ifthen}
\def\zzcolor{\color{red}}

% --------------------------------------------
% Definition of \zzz for text formatting and hyphenation
% --------------------------------------------
\makeatletter
\def\zzz{\leavevmode\begingroup
    \def\zzelt##1{%
        \catcode`##1\active\uccode`\~`##1\uppercase{%
            \def~{\egroup\egroup\-\hbox\bgroup\bgroup\zzcolor\string##1}}}%
    \zz@Alph{}%
    \@zzz}

\def\zz@Alph#1{%
    \zzelt A\zzelt B\zzelt C\zzelt D\zzelt E\zzelt F\zzelt G\zzelt H\zzelt I\zzelt J\zzelt
    K\zzelt L\zzelt M\zzelt N\zzelt O\zzelt P\zzelt Q\zzelt R\zzelt S\zzelt T\zzelt U\zzelt V\zzelt W\zzelt X\zzelt
    Y\zzelt Z}

\def\@zzz#1{\textbf{\texttt{\hbox\bgroup\bgroup\zzcolor#1\egroup\egroup}}\endgroup}
\makeatother

% --------------------------------------------
% Flag to set internal version of document
% --------------------------------------------
\newboolean{internal}
\setboolean{internal}{true}

% --------------------------------------------
% Definition of \zzzconditional which should work like \zzz, but only print to document if interal flag is TRUE
% --------------------------------------------
% helper command
\newcommand\removetheargument[1]{\leavevmode\unskip}
% command
\newcommand{\zzzconditional}{%
    \ifthenelse{\boolean{internal}}{%
        \zzz%
    }{
        \removetheargument%
    }%
}

\begin{document}
    \section{Test}

    Here is an example of how \textbackslash zzz\{\} hyphenates camelCase words. A variable \zzz{InpShaftActTrqSpdRndVar} is hyphenated at capital letters thanks to the amazing support here on StackExchange.

    Now here is an example of \textbackslash zzzconditional\{\}'s hyphenation. A variable \zzzconditional{InpShaftActTrqSpdRndVar} is hyphenated at capital letters. %
    % +++++ internal flag set to false +++++
    \setboolean{internal}{false}%
    % ++++++++++++++++++++++++++++++++++++++
    Having set the \textbackslash internal flag to false, the variable \zzzconditional{InpShaftActTrqSpdRndVar} will disappear. Look at the tex code of this example to see that \textbackslash zzzconditional\{InpShaftActTrqSpdRndVar\} was used in the previous sentence.

    % +++++ internal flag set to true +++++
    \setboolean{internal}{true}%
    % +++++++++++++++++++++++++++++++++++++
    \ifthenelse{\boolean{internal}}{%
        Here is a paragraph which appears only when the \textbackslash internal flag is true. However, inside this \textbackslash ifthenelse\{\}\{\}\{\} construct the hypenation in \textbackslash zzzconditional\{\} is broken. Instead it will result in an overfull line. This is shown in the following example \zzzconditional{InpShaftActTrqSpdRndVar}.%
    }{}%

    \ifthenelse{\boolean{internal}}{%
        The issue issue also persists if I use the command \textbackslash zzz\{\}, for example \zzz{InpShaftActTrqSpdRndVar}. So the core issue does not seem to be with \textbackslash zzzconditional\{\}.%
    }{}%

    \ifthenelse{\boolean{internal}}{%
        \input{codeInput}%
    }{}%

\end{document}

And here is the code for the external file codeInput.tex:

However,~if I use \textbackslash ifthenelse in the main document to \textbackslash input the text from an external file codeInput.tex,~\textbackslash zzzconditional will work. Look at this variable \zzzconditional{InpShaftActTrqSpdRndVar} for example. Unfortunately this workaround is not feasible in the scope of my document\footnote{Large software documentation with so many internal paragraphs that is not practical to create an individual file for loading each one.}.

This is the MWE after compilation: enter image description here

3
  • 2
    I would never use ifthen and \ifthenelse for complicated stuff. It is not powerful enough and catcode changes inside the text are difficult. I would use expl3 instead. May 16, 2018 at 11:07
  • 1
    Imho, plain if constructs are better than \ifthenelse, those are at least predictable in their limitations.
    – Skillmon
    May 16, 2018 at 11:18
  • Thank you both for the input. @Skillmon using your suggestion initial tests in my document seem successful. I used self-defined conditionals as described in this link. If you want the reputation for an accepted answer, you could post a blank answer and I will edit it and add an MWE. May 17, 2018 at 7:11

2 Answers 2

1

If you're looking just for conditionally inputting stuff, I'd use one of the following:

Plain style Booleans:

\newif\ifFoo% initializing
\Footrue% set it true
\Foofalse% set it false
\ifFoo
  <True case>
\else
  <False case>
\fi

%% Usage with a primitive wrapper (no catcode changes in arguments possible)
\makeatletter
\newcommand\myif[1]
  {%
    \csname if#1\endcsname
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
\makeatother
\myif{Foo}{<True case>}{<False case>}

etoolbox Booleans (this is basically the same as the above using a wrapper):

\usepackage{etoolbox}
\newbool{Foo}
\booltrue{Foo}
\boolfalse{Foo}
\ifbool{Foo}{<True case>}{<False case>}

etoolbox toogles:

\usepackage{etoolbox}
\newtoggle{Foo}
\toggletrue{Foo}
\togglefalse{Foo}
\iftoggle{Foo}{<True case>}{<False case>}

There is a slight difference between \newtoggle and \newbool. The latter uses \newif internally and effectively needs three macros per bool: \ifFoo, \Footrue, and \Foofalse. The toggle approach is different internally. I don't know if there is a clear advantage of one approach over the other.

If you need really advanced stuff you could as well use expl3. It has a nice Boolean interface allowing && and || constructs. This is overkill for your usage, imho.

If any input requires catcode changes (like verbatim read content) you can effectively only use the first approach using plain style, because the arguments are read and therefore any category changes don't apply to the already tokenized input. There could be a possible solution using \scantokens, but this again is over complicating, imho.

2
  • I used your first suggestion (plain style booleans) without the wrapper. As soon as I get the time (probably not today), I will post an answer below that incorporates your suggestion into the MWE. Thanks a lot, you saved my day! ...but I do have to replace loooaaaads of \ifthenelse constructs, been at it several hours already and only half way there =) Thanks for your help, much appreciated! May 17, 2018 at 11:05
  • @Jay_At_Play If the contents don't have to be catcode change aware, then you could as well use a search and replace with a wrapper (be it etoolbox's \ifbool or the \myifwrapper, they are the same except that \ifbool checks whether the macro is defined beforehand).
    – Skillmon
    May 17, 2018 at 12:06
0

As promised in the comment below the accepted answer, here is the implementation of the solution in my MWE. I basically introduced a self defined conditional as described by this link. Then I replaced the \ifthenelse constructs in the document body with \ifflagInternal constructs.

I also tried replacing \ifthenelse in the definition of \zzzconditional but for some reason it will not work with \ifflagInternal. This is just FYI, no solution required. Everything works as intended now =)

MWE code with implementation of solution posted by @Skillmon:

\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{ifthen}
\def\zzcolor{\color{red}}

% --------------------------------------------
% Definition of \zzz for text formatting and hyphenation
% --------------------------------------------
\makeatletter
\def\zzz{\leavevmode\begingroup
    \def\zzelt##1{%
        \catcode`##1\active\uccode`\~`##1\uppercase{%
            \def~{\egroup\egroup\-\hbox\bgroup\bgroup\zzcolor\string##1}}}%
    \zz@Alph{}%
    \@zzz}

\def\zz@Alph#1{%
    \zzelt A\zzelt B\zzelt C\zzelt D\zzelt E\zzelt F\zzelt G\zzelt H\zzelt I\zzelt J\zzelt
    K\zzelt L\zzelt M\zzelt N\zzelt O\zzelt P\zzelt Q\zzelt R\zzelt S\zzelt T\zzelt U\zzelt V\zzelt W\zzelt X\zzelt
    Y\zzelt Z}

\def\@zzz#1{\textbf{\texttt{\hbox\bgroup\bgroup\zzcolor#1\egroup\egroup}}\endgroup}
\makeatother

% --------------------------------------------
% Flags to set internal version of document
% --------------------------------------------
% flag for \zzzconditional
\newboolean{internal}
\setboolean{internal}{true}
% flag for use in document
\newif\ifflagInternal
\flagInternaltrue

% --------------------------------------------
% Definition of \zzzconditional which should work like \zzz, but only print to document if interal flag is TRUE
% --------------------------------------------
% helper command
\newcommand\removetheargument[1]{\leavevmode\unskip}
% command
\newcommand{\zzzconditional}{%
    \ifthenelse{\boolean{internal}}{%
        \zzz%
    }{
        \removetheargument%
    }%
}

\begin{document}
    \section{Test}

    Here is an example of how \textbackslash zzz\{\} hyphenates camelCase words. A variable \zzz{InpShaftActTrqSpdRndVar} is hyphenated at capital letters thanks to the amazing support here on StackExchange.

    Now here is an example of \textbackslash zzzconditional\{\}'s hyphenation. A variable \zzzconditional{InpShaftActTrqSpdRndVar} is hyphenated at capital letters. %
    % +++++ internal flag set to false +++++
    \setboolean{internal}{false}%
    % ++++++++++++++++++++++++++++++++++++++
    Having set the \textbackslash internal flag to false, the variable \zzzconditional{InpShaftActTrqSpdRndVar} will disappear. Look at the tex code of this example to see that \textbackslash zzzconditional\{InpShaftActTrqSpdRndVar\} was used in the previous sentence.

    % +++++ internal flag set to true +++++
    \setboolean{internal}{true}%
    % +++++++++++++++++++++++++++++++++++++
    \ifflagInternal%
        Here is a paragraph which appears only when the \textbackslash internal flag is true. However, inside this \textbackslash ifthenelse\{\}\{\}\{\} construct the hypenation in \textbackslash zzzconditional\{\} is broken. Instead it will result in an overfull line. This is shown in the following example \zzzconditional{InpShaftActTrqSpdRndVar}.%
    \fi%

    \ifflagInternal%
        The issue issue also persists if I use the command \textbackslash zzz\{\}, for example \zzz{InpShaftActTrqSpdRndVar}. So the core issue does not seem to be with \textbackslash zzzconditional\{\}.%
    \fi%

    \ifflagInternal%
        \input{codeInput}%
    \fi%

\end{document}

MWE after compilation:

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .