2

My goal:

\begin{equation}[singular=<sing_flag>,plural=<plur_flag>]\label{eq:1}
    a < b
\end{equation}
\cref{eq:1}

yields <sing_flag> (1) for any input for singular and plural (I'd like to avoid specifying a \crefname for every equation type manually).

Basic Idea: When singular and/or plural are passed create new counter (within equation) as anker for cleveref and pass singular/plural to \crefname.

Problems:

  • Just setting \crefname doesn't work, for some reason I have to set \crefformat etc, which is cumbersome and doesn't automate well with babel
  • Even \crefformat doesn't quite work. It just uses the default settings for singular and plural.

MWE:

\documentclass[]{article}

%% Packages
\usepackage{xkeyval}
\usepackage{xparse}
\usepackage{ifthen}
\usepackage{aliascnt}
\usepackage{cleveref}


\makeatletter

%% New Counter for counting new types of equations
\newcounter{misitex@formulatypes}

%% Set up for options
\define@cmdkey[misitex]{equation}{singular}{}
\define@cmdkey[misitex]{equation}{plural}{}
\setkeys[misitex]{equation}{singular=none,plural=none} % initialize

%% Save old equation env
\let\oldequation\equation
\let\endoldequation\endequation

%% Set Crefformat
\newcommand{\misitex@setcrefformat}[3]{
    SetCrefFormat gets: \noexpand{#2} \noexpand{#3}

    %% Shouldn't this suffice?
    \crefname{#1}{#2}{#3}
    \Crefname{#1}{#2}{#3}

    %% Why do I need this?
    \crefformat{#1}{##2#2~\upshape{(##1)}##3}
    \crefrangeformat{#1}{
        ##3#3~\upshape{(##1)}##4 to~##5\upshape{(##2)}##6
    }
    \crefmultiformat{#1}{##2#3~\upshape{(##1)}##3}%
        { and~##2\upshape{(##1)}##3}%
        {, ##2\upshape{(##1)})}%
        { and~##2\upshape{(##1)}##3}
}

%% Set options only if passed
\NewDocumentCommand{\misitex@equation@parse}{m m}{
    \IfValueTF{#1}{\setkeys[misitex]{equation}{#1}}{}
    \IfValueTF{#2}{\setkeys[misitex]{equation}{#2}}{}
}

%% Create new type of equation
\newcommand{\misitex@eqaution@setnew}[2]{
    % Add new equation counter
    \stepcounter{misitex@formulatypes}
    \newaliascnt{misitex@formulatype@\themisitex@formulatypes}{equation}

    % Set cref format
    \misitex@setcrefformat{misitex@formulatype@\themisitex@formulatypes}{#1}{#2}

    % Refstep for cref
    \refstepcounter{misitex@formulatype@\themisitex@formulatypes}

    % Set Equation Numbering
    \def\eqNumber{\eqno{\hbox{\upshape{
                    (\csname themisitex@formulatype@\themisitex@formulatypes \endcsname)
        }}}\@ignoretrue}
}

%% Renew Equation env
%% If singular/plural is passed: cerate new counter and apply cref names
%% Else just use old equation env
\RenewDocumentEnvironment{equation}{>{\SplitArgument{1}{,}}o}{
    % Parse Arguments
    \IfValueT{#1}{\misitex@equation@parse #1}%

    \ifthenelse{\equal{\cmdmisitex@equation@singular}{none}}%
    {%
        \ifthenelse{\equal{\cmdmisitex@equation@plural}{none}}%
            {%
                \oldequation%
            }{%
                \misitex@eqaution@setnew%
                    {\cref@equation@name}{\cmdmisitex@equation@plural}%
                $$
            }%
    }{%
        \ifthenelse{\equal{\cmdmisitex@equation@plural}{none}}%
            {%
                \misitex@eqaution@setnew%
                    {\cmdmisitex@equation@singular}{\cref@equation@name@plural}%
                $$%
            }{%
                \misitex@eqaution@setnew%
                    {\cmdmisitex@equation@singular}
                    {\cmdmisitex@equation@plural}%
                $$%
            }%
    }%
}{
    \ifthenelse{\equal{\cmdmisitex@equation@singular}{none}}%
    {%
        \ifthenelse{\equal{\cmdmisitex@equation@plural}{none}}%
            {
                \endoldequation
            }%
            {\eqNumber $$}%
    }{
        \eqNumber $$
    }
}

\makeatother

\begin{document}

    \begin{equation}[singular=Ineq.,plural=Ineqs.]\label{test}
     a = b
    \end{equation}

    \cref{test}

    \begin{equation}\label{test2}
    a = b
    \end{equation}

    \cref{test,test2}
\end{document}

Outputs:

enter image description here

So while it seems that singular and plural are passed to \crefformat correctly, \cref uses the default none.


While I'm aware, that this is quite a specific problem, I'm glad for any advise :)

  • The user guide of the cleveref package has a section about dynamic renaming of item types, say, to create a different call-out for inequalities. Did you give that method a try? – Mico May 4 at 13:24
  • I'm not quite shure, which section you mean. Can you give a number? cleveref – Hirsch May 4 at 14:12
  • Section 6, "Overriding the Cross-Reference Type". – Mico May 4 at 14:15
  • Mh, that's actually what I'm doing/want to do in \misitex@setcrefformat. In your linked question, only one other equation type is needed. However, I want to be able to set singular and plural dynamically without adding a \crefname to the preamble each time. – Hirsch May 4 at 14:33
  • 1
    I'm afraid I don't understand your 'without adding a \crefname to the preamble each time' concern. Your draft code contains 101[!] lines; the added, ineq-related instructions occupy all of 3 lines. – Mico May 4 at 14:40
1

The problem seems to be, that \crefname doesn't define global commands. A workaround is to use the capability of cleveref to read a file cleveref.cfg befor compilation. By writing the \crefname directives to that file, the desired solution is achieved.

MWE:

Note that the command hanling has been altered, which however is not the actual point of the question.

\documentclass{scrartcl}

\usepackage{hyperref}
\usepackage{mathtools}
\usepackage{aliascnt}
\usepackage{cleveref}
\usepackage{xparse}

\makeatletter

\newcounter{misitex@formulatypes}

\let\oldequation\equation
\let\endoldequation\endequation

%% Open file
\newwrite\cleverefcfg
\immediate\openout\cleverefcfg=cleveref.cfg

%% Some shortcuts to write special characters to file
\begingroup\lccode`?=`# \lowercase{\endgroup
    \newcommand{\hashsymb}{?}
}
\begingroup\lccode`?=`{ \lowercase{\endgroup
    \newcommand{\bracksymbo}{?}
}
\begingroup\lccode`?=`} \lowercase{\endgroup
    \newcommand{\bracksymbc}{?}
}
\begingroup\lccode`?=`\% \lowercase{\endgroup
    \newcommand{\commentsymb}{?}
}

%% write cleveref directives to file
\newcommand{\creflabelformat@tofile}[1]{
    \if@cref@nameinlink
        \protected@write\cleverefcfg{}{
            \string\creflabelformat{#1}\bracksymbo\hashsymb\commentsymb%
        }
        \protected@write\cleverefcfg{}{
            2\string\textup\bracksymbo(\hashsymb\commentsymb
        }
        \protected@write\cleverefcfg{}{
            1)\bracksymbc\hashsymb\commentsymb
        }
        \protected@write\cleverefcfg{}{
            3\bracksymbc\commentsymb
        }
    \else
        \protected@write\cleverefcfg{}{
            \string\creflabelformat{#1}\bracksymbo\string\textup\bracksymbo(\hashsymb\commentsymb%
        }
        \protected@write\cleverefcfg{}{
            2\hashsymb\commentsymb
        }
        \protected@write\cleverefcfg{}{
            1\hashsymb\commentsymb
        }
        \protected@write\cleverefcfg{}{
            3)\bracksymbc\bracksymbc\commentsymb
        }
    \fi
}

%% Renew equation env
%% Input may be [<cstm number>], [<sing>][<plur>], or [<cstm number>][<sing>][<plur>]
\RenewDocumentEnvironment{equation}{o o o}{
    \IfNoValueTF{#3}{
        \IfNoValueTF{#2}{
            \oldequation
            \IfValueT{#1}{\tag{#1}}
        }{
            \IfValueT{#1}{
                \stepcounter{misitex@formulatypes}
                \newaliascnt{misitex@formulatype@\themisitex@formulatypes}{equation}

                %% Write \crefname instruction to config file
                \protected@write\cleverefcfg{}{
                    \string\crefname{misitex@formulatype@\themisitex@formulatypes}{#1}{#2}
                    \string\Crefname{misitex@formulatype@\themisitex@formulatypes}{#1}{#2}
                }
                \creflabelformat@tofile{misitex@formulatype@\themisitex@formulatypes}
            }
            \oldequation
            \IfValueT{#1}{
                \addtocounter{equation}{-1}
                \refstepcounter{misitex@formulatype@\themisitex@formulatypes}
            }
        }
    }{
        \IfValueT{#2}{
            \stepcounter{misitex@formulatypes}
            \newaliascnt{misitex@formulatype@\themisitex@formulatypes}{equation}

            %% Write \crefname instruction to config file
            \protected@write\cleverefcfg{}{
                \string\crefname{misitex@formulatype@\themisitex@formulatypes}{#2}{#3}
                \string\Crefname{misitex@formulatype@\themisitex@formulatypes}{#2}{#3}
            }
            \creflabelformat@tofile{misitex@formulatype@\themisitex@formulatypes}
        }
        \oldequation
        \IfNoValueTF{#1}{}{
            \IfValueT{#2}{
                \expandafter\def\csname themisitex@formulatype@\themisitex@formulatypes\endcsname{#1}
                \addtocounter{equation}{-1}
            }
            \renewcommand{\theequation}{#1}
        }
        \IfValueT{#2}{
            \addtocounter{equation}{-1}
            \refstepcounter{misitex@formulatype@\themisitex@formulatypes}
        }
    }
}{
    \endoldequation
}

\makeatother

\begin{document}

    \begin{equation}[a]\label{test}
     a = b
    \end{equation}

    \begin{equation}[Ineq][Ineqs]\label{test2}
    a = b
    \end{equation}

    \begin{equation}[c]\label{test3}
    a = b
    \end{equation}

    \begin{equation}[Formula][Formulae]\label{test4}
    a = b
    \end{equation}

    \begin{equation}[Formula][Formulae]\label{test45}
    a = b
    \end{equation}

    \begin{equation}\label{test5}
    a = b
    \end{equation}


    \cref{test,test2,test3,test4,test5,test45}

\end{document}

Output: enter image description here

Note

As shown, equations (2) and (3) are not grouped as Formulae (2) and (3). This however is a general problem an can be reproduced in a much simpler setting. A workaround is to explicitly set \crefformat in addition to \crefname.

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.