0

I'm renewing the subsubsection command such that I can either place the following text on the same line (default), or leave some space, with an ! token passed. It appears that for combinations of subsubsection with [] and !, or * and !, it compiles but does not produce the desired result.

I've successfully created commands that accept multiple tokens (tested in this same MWE) with xparse, and am not sure that is the problem.

This is tested on TeX Live 2020 on Overleaf. I tried luaexec, directlua, and luadirect.

Question: Can anyone spot a flaw in my attempt/approach? My solution uses LuaLaTeX. It feels a bit hacky to reconstruct the command and print it from Lua--is there a canonical way to "augment" commands in a similar fashion (ie adding token args !, or say, other optional arguments). Does the subsubsection command need to be expandable?

\documentclass{scrartcl}

\usepackage{xparse}
\usepackage{luacode}

\RedeclareSectionCommand[afterskip=-4ex]{subsubsection}

\begin{luacode*}
    _xTrue = '\\BooleanTrue '
    _xFalse = '\\BooleanFalse '
    _xNoValue = '-NoValue-'

    function makesubsubsection(s, o, m)
        texio.write_nl('>>>>> Arguments are: '..s..', '..o..', '..m)
        local cmd = '\\oldsubsubsection'
        if s == _xTrue then
            cmd = cmd .. '*'
        end
        if o ~= _xNoValue then
            cmd = cmd..'['..o..']'
        end
        tex.print(cmd..'{'..m..'}')
    end
\end{luacode*}

\let\oldsubsubsection\subsubsection
\RenewExpandableDocumentCommand{\subsubsection}{ s t! o m }{% does this need to be expandable?
    \IfBooleanT{#2}{\RedeclareSectionCommand[afterskip=12pt]{subsubsection}}{}
    \directlua{makesubsubsection(\luastringN{#1},\luastringN{#3},\luastringN{#4})}
    \IfBooleanT{#2}{\RedeclareSectionCommand[afterskip=-4ex]{subsubsection}}{}%
}


% \NewDocumentCommand{\TestTokArg}{ s  t! }{%
%   Test:\IfBooleanT{#1}{Star}\IfBooleanT{#2}{Excl}% testing token arg
% }

\begin{document}

% \TestTokArg \TestTokArg* \TestTokArg! \TestTokArg*!  % testing token arg

\tableofcontents 

\subsubsection{in ToC, in Line} text  %% works

\subsubsection[short1]{in ToC, in Line} text  %% works

\subsubsection!{in ToC, not in Line} text   %% works

\subsubsection![short2]{in ToC, not in Line} text  %% does not work

\subsubsection*{no ToC, in Line} text   %% works

\subsubsection*!{no Toc, not in line} text  %% does not work

\end{document}

enter image description here

For troubleshooting, I print out the args my lua function recieves, but in the log, it only shows the first three calls to subsubsection:

>>>>> Arguments are: \BooleanFalse , -NoValue-, in ToC, in Line
>>>>> Arguments are: \BooleanFalse , short1, in ToC, in Line
>>>>> Arguments are: \BooleanFalse , -NoValue-, in ToC, not in Line
2
  • what do you hope to gain by excaping to lua here?? Aug 16, 2021 at 22:35
  • It's just easier (for me) to reconstruct the optional arguments. I can't simply write \oldsubsubsection#1[#3]{#4}. I did ask in the Q if there's a canonical way to achieve this, so I am happy to hear suggestions :) trying to learn. Aug 16, 2021 at 22:47

1 Answer 1

3

First let's rewrite this without Lua to avoid the interaction of the two languages distracting from the actual issue:

\documentclass{scrartcl}

\usepackage{xparse}

\RedeclareSectionCommand[afterskip=-4ex]{subsubsection}

\let\oldsubsubsection\subsubsection

\RenewDocumentCommand{\subsubsection}{ s t! o m }{%
    \IfBooleanT{#2}{\RedeclareSectionCommand[afterskip=12pt]{subsubsection}}%
    \expanded{% \expanded ensures that we get one pass of expansion first which we use to build the right command. We can put \noexpand and/or \unexpanded around everything that should be preserved.
        \noexpand \oldsubsubsection
            \IfBooleanT {#1}{*}%
            \IfValueT {#3} {\unexpanded{[#3]}}%
            \unexpanded{{#4}}%
    }%
    \IfBooleanT{#2}{\RedeclareSectionCommand[afterskip=-4ex]{subsubsection}}%
}

\begin{document}

\tableofcontents 

\subsubsection{in ToC, in Line} text  %% works

\subsubsection[short1]{in ToC, in Line} text  %% works

\subsubsection!{in ToC, not in Line} text   %% works

\subsubsection![short2]{in ToC, not in Line} text  %% does not work

\subsubsection*{no ToC, in Line} text   %% works

\subsubsection*!{no Toc, not in line} text  %% does not work

\end{document}

This still fails, so Lua can't have been the cause of the issue.

The issue occurs for every call to \subsubsection after ! has been used once. Whenever ! is used, your code invokes \RedeclareSectionCommand which overwrites the current definition of the section command you specify (in your case \subsubsection). Thereby it overwrites your redefinition of this command, leading to the problem since afterwards \subsubsection no longer knows your additional arguments.

To solve this, you can avoid \RedeclareSectionCommand and instead change the parameter controlling afterskip directly: The afterskip for subsubsection is stored in \scr@subsubsection@afterskip.

So you get

\documentclass{scrartcl}

\usepackage{xparse}

\let\oldsubsubsection\subsubsection

\makeatletter
\RenewDocumentCommand \subsubsection { s t! o m }{%
    \edef \scr@subsubsection@afterskip {%
        \IfBooleanTF {#2} {12pt} {-4pt}%
    }%
    \expanded{%
        \noexpand \oldsubsubsection
            \IfBooleanT {#1} {*}%
            \IfValueT {#3} {\unexpanded{[#3]}}% edit forgot {#3}
            \unexpanded{{#4}}%
    }%
}
\makeatother

\begin{document}

\tableofcontents 

\subsubsection{in ToC, in Line} text  %% works

\subsubsection[short1]{in ToC, in Line} text  %% works

\subsubsection!{in ToC, not in Line} text   %% works

\subsubsection![short2]{in ToC, not in Line} text  %% works

\subsubsection*{no ToC, in Line} text   %% works

\subsubsection*!{no Toc, not in line} text  %% works

\end{document}
1
  • Excellent answer, thank you kindly. To clarify, does the first expand only expand the arguments because noexpand or unexpanded protects the other command sequences? Why the difference between (un|no)expand? Aug 16, 2021 at 23:45

You must log in to answer this question.

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