Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LaTeX: Lstlisting automatically recognizing code passage

Tags:

lines

latex

I am writing a program (in C, but I suppose that's not so relevant) in connection with a little documentary material in LaTeX. I want the documentary material to contain code snippets from my original code.

In order to include source code and keep it up to date, I do the following in my document:

\lstinputlisting[firstline=200, lastline=210]{../src/source.c)

This loads automatically the lines 200 to 210 (which contain e.g. a function) from ../src/source.c into my document.

However, if I add some lines before line 200, this means that line 200 "wanders down some lines", so I have to adjust this in order to get my original function.

So here's my question: Does anybody know about a possibility how to dynamically tell lstinputlisting (or any adequate substitute) to tell which lines to take?

I imagine something like the following: I add special comments to my C source code that will be recognized by lstinputlisting, e.g.

/// lstinputlisting "myfunc" BEGIN
int myFunction(int x){
  return x+2;
}
/// lstinputlisting "myfunc" END

Then, lstlisting scans the file and just includes the lines between the BEGIN and the END things.

like image 427
phimuemue Avatar asked Oct 12 '10 14:10

phimuemue


2 Answers

I am answering a few months after your post, but the feature of lstlistings I describe below has been in that package for several years.

The keyword to look for is the option linerange, as well as, for convenience, rangeprefix and rangesuffix.

Here is a complete example.

\documentclass{article}
\usepackage{fullpage,times,listings}
\lstloadlanguages{C++}

\lstset{language=C++,keywordstyle=\bfseries,commentstyle=\itshape,
  rangeprefix=//----------------,rangesuffix=----------------,
  includerangemarker=false,columns=spaceflexible}

\begin{document}
We first show the main function.
\lstinputlisting[linerange=main0-main1]{code.cpp}
Then we show the implementation.
\lstinputlisting[linerange=fact0-fact1]{code.cpp}
\end{document}

then save the following in code.cpp:

#include <cassert>

//----------------fact0----------------
// A recursive implementation of factorial
int factorial(int i)
{
    if(i)
        return i * factorial(i-1);
    else
        return 1;
}
//----------------fact1----------------

//----------------main0----------------
// Test the implementation.
int main()
{
    assert(factorial(5) == 120);
}
//----------------main1----------------

This is a good solution because one inevitably edits the code, and then it becomes tedious to update the line numbers throughout one's TeX files. Using symbols solves this problem, but it also leaves a trace in the code itself that if the number of lines changes, or if the width changes too much, one needs to confirm that the typeset output still looks reasonable.

Finally, after editing the code, you need to typeset the latex files again only if you inserted/deleted within the marked blocks.

like image 61
Calaf Avatar answered Sep 28 '22 07:09

Calaf


The only reasonable way of making this happen that I can think of off the top of my head, is to create a makefile and have that be responsible for producing the correct output.

Assuming sourcefile.c is in ./src and LaTeX files are in ./tex then ./tex/Makefile could look something like this:

doc.tex: sourcefile.grep
        <command to compile doc.tex>
sourcefile.grep: 
        <command to grep/whatever to dump from 
        ../src/sourcefile.c to ./tex/sourcefile.grep>

And the lstlistings in doc.tex would then point to ./src/sourcefile.grep

like image 39
kahen Avatar answered Sep 28 '22 08:09

kahen