With the answer from autogobble for lstinputlistings
I've managed to create a command that gobbles \lstinputlisting
and makes firstnumber
to start by firstline
. I would like to rewrite it as a package, so it hooks into \lstinputlisting
, but as the code might reflect I have very little experience with programming in LaTeX.
My goal is to be able to write
\lstset{tabsize=3,numbers=left,frame=single,basicstyle=\footnotesize\ttfamilily,}
\lstinputlisting[levels=1,linerange={2-4},...]{hello.c}
where the dots are possible extra regular listings options.
or what could be even more nice:
\lstset{tabsize=3,numbers=left,frame=single,basicstyle=\footnotesize\ttfamilily,}
\lstinputlisting[autogobble,linerange={2-4},...]{hello.c}
where LaTeX automatically counted the number of tabs like in How to automatically skip leading white spaces in listings
MWE
\documentclass{article}
\usepackage{listings,xifthen}
\lstset{tabsize=3,numbers=left,frame=single,basicstyle=\Huge\ttfamily,columns=flexible}
\newlength{\gobble}
\newlength{\gobblea}
% The width of a single space. basicstyle from lstset should be used
\sbox0{\Huge\ttfamily \ }
\newcommand{\mylist}[5]{
%#1 is number of tabs, could be calculated like in listings-autogobble with autogobble=true or be an extra option
%#2 is tabsize, which is set in lstset
%#3 is firstline from lstset
%#4 is lastline from lstset
%#5 is the filename, the only thing which should be an argument and not an option.
% Remove a single space
\setlength{\gobble}{-\the\wd0}
% Reindent a bit by multiplying with 0.9, then multiply by tabsize and number of indentation levels
\setlength{\gobble}{0.9\gobble*#1*#2}
\setlength{\gobblea}{\gobble}
\addtolength{\gobblea}{10pt}
% Check if firstline is defined
\ifthenelse{\isempty{#3} \OR \equal{#3}{0}}{%
% Check if lastline is defined
\ifthenelse{\isempty{#4}}{%
\lstinputlisting[firstnumber=1,firstline=1,framexleftmargin=\gobble,xleftmargin=\gobble,numbersep=\gobblea]{#5}
}{
\lstinputlisting[firstnumber=1,firstline=1,lastline=#4,framexleftmargin=\gobble,xleftmargin=\gobble,numbersep=\gobblea]{#5}
}
}{
\ifthenelse{\isempty{#4}}{%
\lstinputlisting[firstnumber=#3,firstline=#3,framexleftmargin=\gobble,xleftmargin=\gobble,numbersep=\gobblea]{#5}
}{
\lstinputlisting[firstnumber=#3,firstline=#3,lastline=#4,framexleftmargin=\gobble,xleftmargin=\gobble,numbersep=\gobblea]{#5}
}
}
}
\begin{document}
%mylist{#tabs}{#tabsize}{firstline}{lastline}{filename}
\mylist{1}{3}{2}{4}{hello1.c}
\end{document}
edit:
I just modified the code from cyberSingularity a bit to use lst@basicstyle
and lst@tabsize
.
It should work with any:
- font size in document class
- font size in basicstyle
- tabsize
Limitations (Would be very pleased if someone could address these limitations):
columns=flexible
and basicstyle=\ttfamily
.tabsize
or basicstyle
is passed as options to \lstinputlisting
, they must be written before widthgobble
.\ttfamily
\documentclass[10pt]{article}
\usepackage{listings}
\usepackage{filecontents}
\begin{filecontents*}{hello1.c}
if (a<b){
if (b<a){
printf("hello")
}
}
\end{filecontents*}
\lstset{tabsize=3,numbers=left,frame=single,basicstyle=\Huge\ttfamily,columns=flexible}
\makeatletter
\newlength{\singlespace}
\newlength{\gobble}
\newlength{\numbersep}
% The width of a single space.
\settowidth{\singlespace}{\lst@basicstyle \ }
\setlength{\singlespace}{-\singlespace}
\lst@Key{firstlineandnumber}\relax{\def\lst@firstline{#1\relax}\def\lst@firstnumber{#1\relax}}
\lst@Key{widthgobble}{0}{%
\setlength{\gobble}{0.9\singlespace}% reindent a bit
\setlength{\gobble}{\lst@tabsize\gobble}% multiply by tabsize
\setlength{\gobble}{#1\gobble}% multiply by number of tabs
\def\lst@xleftmargin{\gobble}% move left margin left
\def\lst@framexleftmargin{\gobble}% move left frameborder left
\setlength{\numbersep}{\gobble}%
\addtolength{\numbersep}{10pt}%
\def\lst@numbersep{\numbersep}% distance between numbers and left frameborder
}
\makeatother
\begin{document}
%widthgobble=#tabs,firstlineandnumber sets firstline and firstnumber
\lstinputlisting[widthgobble=1,firstlineandnumber=2,lastline=4]{hello1.c}
\end{document}
Best Answer
Are you after something like this? I have provided new keys:
widthgobble
, which takes as an argument#tabs*#tabsize
firstlineandnumber
, which sets bothfirstline
andfirstnumber
Note that I had some trouble using the
*
syntax for setting the length of\gobble
so have implemented an ugly workaround (which currently means that the argument towidthgobble
should always have two numbers separated by an asterisk):