# How to have a dynamic \cft numwidth, i.e., accordingly to the number size?

For example, when this listing example, reaches up to 10000 items (listings) on the table, the number is hidden behind the hyphen, i.e.:

You can do this by either creating 10000 listings in the bellow example, or editing main.lol file and putting 10000 and 20000 as the listing numbers.

\PassOptionsToPackage{french}{babel}
\documentclass[english,12pt,a4paper,twoside]{abntex2}
\usepackage{caption,xpatch,listings}
\makeatletter
\tracingpatches

% https://tex.stackexchange.com/questions/269491/mixing-minted-with
\AtBeginEnvironment{listing}{\setcounter{listing}{\value{lstlisting}}}
\AtEndEnvironment{listing}{\stepcounter{lstlisting}}
\newlength\mylen

\begingroup
\let\newcounter\@gobble\let\setcounter\@gobbletwo
\globaldefs\@ne \let\c@loldepth\@ne
\newlistof{listings}{lol}{\lstlistlistingname}
\newlistof{lstlistoflistings}{lol}{\lstlistlistingname}
\newlistentry{lstlisting}{lol}{0}
\endgroup

% Why the empty space size is increasing each call to my calculate
% https://tex.stackexchange.com/questions/388411/why-the-empty-space
\newlength\cftlstlistingoldnumwidth
\setlength\cftlstlistingoldnumwidth{\cftlstlistingnumwidth}

% Calculate the size of the header
% What is the use of percent signs (%) at the end of lines?
% https://tex.stackexchange.com/questions/7453/what-is-the-use-of-percent
{%
\renewcommand\cftlstlistingpresnum{\lstlistingname~}%
\settowidth\mylen{\cftlstlistingpresnum\cftlstlistingaftersnum}%
\setlength\cftlstlistingnumwidth{\dimexpr\cftlstlistingoldnumwidth+\mylen}%
\renewcommand\cftlstlistingaftersnum{\hfill\textendash\hfill}%
}

\makeatother

\begin{document}

{
\lstlistoflistings*
}
% \newpage

\begin{lstlisting}[caption={Listing}]
# If the body of the namespace is longer than this
# number, it won't be indented. Requires
\end{lstlisting}
% \newpage

\begin{lstlisting}[caption={Listing}]
# If the body of the namespace is longer than this
# number, it won't be indented. Requires
\end{lstlisting}
% \newpage

\end{document}


References:

This seems to work, though I'm not quite sure what the aftersnum part is suppose to to

It will require a few passes to get settled.

\PassOptionsToPackage{french}{babel}
\documentclass[english,12pt,a4paper,twoside]{abntex2}
\usepackage[T1]{fontenc}
\usepackage{caption,listings}
\makeatletter

% get rid of the one listings may have provided
\let\lstlistoflistings\relax

% whatever this does, it seems to work
\begingroup
\let\newcounter\@gobble\let\setcounter\@gobbletwo
\globaldefs\@ne \let\c@loldepth\@ne
\newlistof{listings}{lol}{\lstlistlistingname}
\newlistof{lstlistoflistings}{lol}{\lstlistlistingname}
\newlistentry{lstlisting}{lol}{0}
\endgroup

\newlength\widestlistings

% use the hook in numberline to gather the width of the widest number
\renewcommand*\numberlinehook[1]{%
\expandafter\nametest\expandafter{\cftwhatismyname}{lstlisting}%
\ifsamename%
\settowidth\@tempdimc{\@nameuse{cft\cftwhatismyname font}#1}%
\ifdim\@tempdimc>\widestlistings\relax
\global\widestlistings=\@tempdimc
\fi
\fi
}

% widest number in the aux to be used on the next pass
\renewcommand\cftlolafterlisthook{
\typeout{w: \the\widestlistings}
\immediate\write\@mainaux{\string\gdef\string\savedlolwidth{\the\widestlistings}}
}

% prefix listing entries
\renewcommand\cftlstlistingname{\lstlistingname~}%
% autoadjust the width of the numwidth box, delayed so we can access
% the saved number
\AtBeginDocument{
\setlength\cftlstlistingnumwidth{%
\dimexpr\@ifundefined{savedlolwidth}{1em}{\@nameuse{savedlolwidth}}
+2em
}%
}
\renewcommand\cftlstlistingaftersnum{\hfill\textendash\hfill}%

\makeatother

\begin{document}

\lstlistoflistings*

% \newpage

\begin{lstlisting}[caption={Listing A}]
# If the body of the namespace is longer than this
# number, it won't be indented. Requires
\end{lstlisting}
% \newpage

\setcounter{lstlisting}{1000}

\begin{lstlisting}[caption={Listing B}]
# If the body of the namespace is longer than this
# number, it won't be indented. Requires
\end{lstlisting}
% \newpage

\end{document}

• You are amazing! – Peter Wilson Nov 5 '19 at 17:56
• @daleif, it is throwing this error Argument of \user@active@arg~ has an extra }. when I use \usepackage{hyphenat}\useshorthands{~}\defineshorthand{~=}{\hyp{}} – user Nov 6 '19 at 13:36
• @user you really should not redefine ~, look at the \renewcommand\cftlstlistingname{\lstlistingname~} line, there ~ is being used under the assumption that it is non-breaking space. And thus your messing with it makes that fail. – daleif Nov 6 '19 at 14:23