LaTeX:Lstlisting自动识别代码段落

发布于 2024-09-26 19:19:37 字数 739 浏览 1 评论 0原文

我正在编写一个与 LaTeX 中的一些文档材料相关的程序(用 C 语言,但我认为这不是那么相关)。我希望文档材料包含我的原始代码中的代码片段。

为了包含源代码并使其保持最新,我在文档中执行以下操作:

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

这会自动加载 ../src/source.c 进入我的文档。

但是,如果我在第 200 行之前添加一些行,这意味着第 200 行“向下徘徊了一些行”,所以我必须对此进行调整才能获得原始功能。

所以这是我的问题:有人知道如何动态地告诉 lstinputlisting (或任何适当的替代品)来告诉要采取哪些行吗?

我想象如下:我向我的 C 源代码添加特殊注释,这些注释将被 lstinputlisting 识别,例如

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

然后,lstlisting 扫描文件并仅包含之间的行BEGINEND 事物。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

野の 2024-10-03 19:19:37

我在您发帖后几个月才回复您,但我在下面描述的 lstlistings 功能已经在该软件包中存在了好几年了。

要查找的关键字是选项 linerange,以及为方便起见的 rangeprefixrangesuffix

这是一个完整的例子。

\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}

然后将以下内容保存在 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----------------

这是一个很好的解决方案,因为人们不可避免地要编辑代码,然后更新整个 TeX 文件中的行号就变得很乏味。使用符号解决了这个问题,但它也在代码本身中留下了痕迹,即如果行数发生变化,或者宽度变化太大,则需要确认排版输出看起来仍然合理。

最后,编辑代码后,仅当您在标记的块中插入/删除时,才需要再次排版乳胶文件。

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.

香草可樂 2024-10-03 19:19:37

我能立即想到的唯一合理的方法是创建一个 makefile 并让它负责生成正确的输出。

假设 sourcefile.c 在 ./src 中,LaTeX 文件在 ./tex 中,那么 ./tex/Makefile 可能看起来像这样:

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>

然后 doc.tex 中的 lstlistings 将指向 ./src/sourcefile.grep

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

乖乖兔^ω^ 2024-10-03 19:19:37

在 C 中使用 #include 不是更容易吗?

这不是完美的,但足够好的解决方案。

这是一个示例(无法编译,我上次用 C 写的东西是 5 年前):

Main C 程序:

    #include <stdio.h>

    //function included from separate file -- will be included in LaTeX too
    #include "fun_x.c"         

    int main() 
    {
      int d = 0;
      printf("%d", fun_x(d));

    //code included from separate file -- will be included in LaTeX too
    #include "calc.c"

      return 0;
    }

fun_x.c 文件:

int fun_x(int c) 
{
  c++;
  return c;
}

calc.c 文件:

d = 99;
d = fun_x(d);

LaTeX 源:

\begin{document}
...

\lstinputlisting{../src/fun_x.c)

...

\lstinputlisting{../src/calc.c)

...

\end{document}

Would not be easier to use #include in C?

It is not perfect, but good enough, solution.

Here is an example (could not compile, I'd written last time something in C 5 years ago):

Main C program:

    #include <stdio.h>

    //function included from separate file -- will be included in LaTeX too
    #include "fun_x.c"         

    int main() 
    {
      int d = 0;
      printf("%d", fun_x(d));

    //code included from separate file -- will be included in LaTeX too
    #include "calc.c"

      return 0;
    }

fun_x.c file:

int fun_x(int c) 
{
  c++;
  return c;
}

calc.c file:

d = 99;
d = fun_x(d);

LaTeX source:

\begin{document}
...

\lstinputlisting{../src/fun_x.c)

...

\lstinputlisting{../src/calc.c)

...

\end{document}
梦年海沫深 2024-10-03 19:19:37

不久前在 TeX SE 上讨论过类似的事情,一个答案使用了一个包catchfile Betweentags。这并不能直接解决您的问题,但也许您可以使用它来将您想要的片段提供给 \lstlistings ,也许再次使用临时文件。

Something like this was discussed on the TeX SE a while back and one answer used a package catchfilebetweentags. This doesn't solve your problem directly, but perhaps you can use that to feed the fragment you want to \lstlistings, perhaps again with a temporary file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文