[Tex/LaTex] How to automatically adjust font size for listings, so it fits gives amount of textwidth

fontsformattinglistings

For code listings, I often change the listings parameter basicstyle to adjust the font size so that listing fit within the container it is in.

I mainly use a cell in a table to display small listing in. But the container could be a minipage or the whole page, or anything else.

So in a table cell, I use \linewidth or it could be some percentage of the textwidth.

I also know the number of characters of the widest (longest) line of the listing. I wrote a small lua function which finds this value.

I just do not know how to use the above 2 pieces of information, in order to map it to the correct font size to tell listing to use such that it fits.

Assuming for now that 11pt class is used. But it will be nice if this would work for arbitrary value and also any font family that happens to be used.

Here is a MWE showing an example listing, which I want to show in a table. I know the space needed, which is \linewidth, and I calculate that the longest line is 56 characters for this example, and I know I am using 11 pt.

What should the font size be then so that the listing would fit in? For example, when using \small it does not fit

Mathematica graphics

Code for the above is (MWE)

\documentclass[11pt]{scrbook}
\IfFileExists{luatex85.sty}{\usepackage{luatex85}}{}

\usepackage[T1]{fontenc}
\usepackage{color}
\usepackage{listings}
\definecolor{bg}{RGB}{240,240,240}
\usepackage{moreverb}
\usepackage{luacode}
\begin{luacode*}
function getMaxLineWidth()
local maxLineLength = 0;

   local r    
   for line in io.lines("code.m") do
       r = string.len(line)
       print(line,r)
       if r>maxLineLength then
          maxLineLength=r
       end
   end     
   tex.print(maxLineLength)
end
\end{luacode*}
\newcommand{\getMaxLineWidth}{\directlua{ getMaxLineWidth() }}

\begin{document}

\begin{verbatimwrite}{code.m} 
clear all; 
syms s t
f = (s^4+5*s^3+6*s^2+9*s+30)/(s^4+6*s^3+21*s^2+46*s+30);
pretty(f)
\end{verbatimwrite}

\begin{tabular}{|p{0.7\textwidth}|}\hline    
space available for the listing is     \the\linewidth and the 
The maximum line width is \getMaxLineWidth \ then
what should be the font size below so it will fit?

\lstinputlisting[language=Matlab,backgroundcolor=\color{bg},
    basicstyle=\ttfamily\small]{code.m}
\\\hline
\end{tabular}

\end{document}

By trial and error scriptsize is found to work:

Mathematica graphics

And this manual adjustment is what I am trying to avoid. I think knowing the space available in pt and knowing the number of characters, and also the font size used for the document, it should be possible to calculate what font size is needed to pass to the listing command so this is all automated?

I am also not sure if one can specify an arbitrary font size value, or is one limited to the values given by \normalsize,\small, etc… ?

Can this be automated?

For reference, thanks for answer what-point-pt-font-size-are-large-etc

Mathematica graphics

Best Answer

The idea for this comes from David Carlisle in chat. Basically, you put the listing in a box that will be scaled down if wider than some width. The adjustbox package provides an easy interface for doing just this.

Note however, as Ulrike Fischer mentions in chat, that this may well end up looking horrible (such as my example below), but if looks are irrelevant, then by all means.

\documentclass{article}
\usepackage{matlab-prettifier}
\lstset{style=Matlab-editor,breaklines=false}
\usepackage{adjustbox}

\begin{document}
\begin{adjustbox}{max width=\textwidth}
\begin{lstlisting}
x = a + b + c + d + e + f + g + h + i + j + k + l + m +n + o + p + q + r + s + t + u + v + x + y
\end{lstlisting}
\end{adjustbox}

\begin{adjustbox}{max width=\textwidth}
\begin{lstlisting}
x = a + b + c + d + e + f
\end{lstlisting}
\end{adjustbox}
\end{document}
Related Question