0

I want to define a new list of things using \newlistof in the tocloft package. I included tocloft in the usual way for packages (\RequirePackage{tocloft}; full minimal code below). However, when I run it through pdflatex, I get:

Package tocloft Warning: I don't recognize any sectional divisions so I'll do nothing on input line ##.

...

! Undefined control sequence.

<recently read> \newlistof

l.## \newlistof

I found that someone else had the same problem but for \cftdot rather than \newlistof. That user asked what was going on rather than how to actually include the tocloft package, so now I know it's because tocloft is implemented to fail if it doesn't find any chapters, sections, etc. But I'm still none the wiser about how to include tocloft. I could find nothing else of relevance on the internet or in the documentation.

(Using \RequirePackage[titles]{tocloft}, which is how I want to use it, gives ! LaTeX Error: Unknown option 'titles' for package 'tocloft'., which is presumably for the same sort of reason.)

Instead of \RequirePackage{tocloft}, I tried:

\AtBeginDocument{\usepackage{tocloft}}
...
\newlistof{things}{tng}{\listthingsname}

so that it would load at the start of the document, but I get the same Undefined control sequence error (presumably because there are still no sectional divisions at that point). Commenting \newlistof out gives:

Package tocloft Warning: \@starttoc has already been redefined; tocloft bailing out. on input line 1156.

My question is how can I include tocloft in a *.dtx file? (I'm using the etoolbox package, if that helps.)


MWE (or rather minimum example that shows my initial attempt ):

% \iffalse meta-comment
%<*internal>
\iffalse
%</internal>
%<*internal>
\fi
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
  \expandafter\begingroup
\fi
%</internal>
%<*install>
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\nopreamble\nopostamble
\usedir{tex/latex/things}
\generate{
  \file{\jobname.sty}{\from{\jobname.dtx}{package}}
}
%</install>
%<install>\endbatchfile
%<*internal>
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</internal>
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{things}
\RequirePackage{etoolbox}
\RequirePackage{tocloft}
% \AtBeginDocument{\usepackage{tocloft}}
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{things}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
%\GetFileInfo{\jobname.sty}
%
% \title{Title}
% \author{Author}
% \date{\today}
%
% \maketitle
% ^^A\listofthings
%
%    \begin{macrocode}
%<*package>
%
\ newcommand{\listthingsname}{List of Things}
\newlistof{things}{tng}{\listthingsname}
%
% \newcommand{\thing}[1]{%
%   \refstepcounter{things}\textsuperscript{\thethings}#1%
%   \addcontentsline{tng}{things}{\protect{\thethings}#1}%
% }
%
%</package>
%    \end{macrocode}
pandammonium
  • 85
  • 1
  • 6
  • 2
    your dtx structure is rather weird, you sue \jobname but it only works if the file is called things.dtx as you include that package by name, the error is because you need the driver code earlier (or the package code guarded by % \iffalse so that when you do pdflatex things.dtx it only sees the <driver> section, as it is you are processing the <package> section before the documentclass has been loaded – David Carlisle Sep 22 '20 at 11:18
  • 1
    @DavidCarlisle I based my .dtx file on A model .dtx file – it was all I could find that explained how to write a .dtx package. I confess it's all a little over my head. The file is indeed called things.dtx – should I change \usepackage{things} to \usepackage{\jobname}? If I move the <driver> section to before the <package> section, it seems to work – is that a more standard dtx structure? – pandammonium Sep 22 '20 at 12:38
  • 1
    yes moving the driver up would be a good solution, you could post a self answer if you have a working version – David Carlisle Sep 22 '20 at 14:25
  • Thanks @DavidCarlisle – pandammonium Sep 22 '20 at 20:36

1 Answers1

1

David Carlisle pointed out that my dtx structure wasn't quite right. The <driver> section, which includes \begindocument, needs to be processed before the <package> section that includes the \RequirePackage commands. Therefore, moving the <driver> section to before that <package> section fixes the problem: \begindocument is called before any packages are required.

I also reverted \usepackage{things} to \usepackage{\jobname} because of David's comment. I'm not sure why I changed it in the first place :)


MWE (fixed)

% \iffalse meta-comment
%<*internal>
\iffalse
%</internal>
%<*internal>
\fi
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
  \expandafter\begingroup
\fi
%</internal>
%<*install>
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\nopreamble\nopostamble
\usedir{tex/latex/things}
\generate{
  \file{\jobname.sty}{\from{\jobname.dtx}{package}}
}
%</install>
%<install>\endbatchfile
%<*internal>
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</internal>
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{\jobname}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
%<*package>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{things}
\RequirePackage{etoolbox}
\RequirePackage[titles]{tocloft}
% \AtBeginDocument{\usepackage{tocloft}}
% \AtEndDocument{\usepackage{tocloft}}
%</package>
% \fi
%
%\GetFileInfo{\jobname.sty}
%
% \title{Title}
% \author{Author}
% \date{\today}
%
% \maketitle
% \listofthings
%
% \thing{A thing}
%
%    \begin{macrocode}
%<*package>
%
\newrobustcmd{\listthingsname}{List of Things}
\newlistof{things}{tng}{\listthingsname}
%
\newrobustcmd{\thing}[1]{%
  \refstepcounter{things}\textsuperscript{\thethings}#1%
  \addcontentsline{tng}{things}{\protect\numberline{\thethings}#1}%
}
%
%</package>
%    \end{macrocode}
pandammonium
  • 85
  • 1
  • 6