LaTeX 相当于 R 的“help foo”吗?

LaTeX 相当于 R 的“help foo”吗?

从 R 命令行我可以执行help foo--foo某个 R 命令在哪里 -- 并返回.html帮助文件foo。即使foo它来自我刚刚加载的某个非标准库,这也适用。

问:LaTeX 中与此最接近的过程是什么?

这里我得到了帮助,发现mthelptexdoc在 TeXLive 系统上)可以返回包、文档类和命令的帮助文件。但缺少 LaTeX 宏(例如\section

\section问:获取标准 latex 命令(例如)或需要加载的包中的命令(例如\mathcal来自 amsfonts)的完整文档的最快/最佳方法是什么?

到目前为止,我要么(1)寻找科普卡和达利,(2)使用帮助->关键词搜索在 WinEdt 中(返回LaTeX2e 帮助,这只对非常标准的 LaTeX 宏有用(例如\section)。即便如此,文档也非常有限),(3)标准 Google 和论坛搜索,或(4)使用手册(有时很难mthelp找到包含感兴趣的宏的适当包的手册)

也许我被 R 宠坏了,但这个过程效率太低了。我肯定做错了什么……对吧?

答案1

TeX 不是一种面向对象的编程语言,它不能像 Python 或 R 那样将文档数据附加到类和对象。没有回溯来了解某个宏是在哪个文件/包/类中定义的,也没有它的输入规范是什么。

我的方法是(1)用 Google 搜索未知的宏,找出它们在包中定义的位置,(2)texdoc <package>+ 搜索该宏,如果这没有帮助(3)我查看包的源代码,通过(3a)打开源文件或通过(3b)使用 \show\macro关于所讨论的宏。恕我直言,这是你能得到的最接近的东西help macro。它显示了宏的定义,告诉高级用户他们需要知道的大部分内容。

对于带有可选参数的宏,这没有多大帮助,因为\show只显示特殊的内部宏,如\\macro\macro(注意空格宏名)。当然,我自己编写了一个 Perl+TeX 脚本,它从命令行向我显示这些定义(texdef -p <package> <macro>)。发布它在我的待办事项清单上。

但是,如果您只想要宏的用户描述,即它需要多少个参数以及需要哪些参数,那么最好使用具有命令完成功能的编辑器,例如 Kile。这当然只适用于编辑器知道的命令,这些命令仅限于标准和一些更常见的包。

答案2

这实际上不是一个答案,但是对于评论来说太长了:

查找宏的文档的问题\foo在于(几乎)不可能知道在哪里\foo定义。例如,\section很可能是由您使用的文档类定义的,因此如果它是 article,您需要说texdoc article(或 miktex 中的等效内容),如果它是 memoir,则使用texdoc memoir。但是,如果您正在使用扩展或更改功能的某个包\section,则文档中的信息article可能不足、不相关甚至具有误导性。

我能给出的最好建议是保持你的前言简洁,对你使用的每一个包写一个小注释,如果你不知道为什么\usepackage{foobar},那可能是因为你不使用它[1]。比如

% babel - hyphenation rules and other localization stuff
\usepackage[danish]{babel}

% The geometry package makes it easy to set the margins
\usepackage{geometry}

如果您在某个时候发现需要添加包mathrsfs才能获得某种脚本数学字体(\mathscr),请务必在附近记下\usepackage{mathrsfs}。这样,您就更有可能知道在哪里查找文档。

[1] 这不完全正确,但我相信了解每个包的作用是很重要的。

答案3

与 不同R,在 LaTeX 中,除了处理错误时,您几乎从不使用内置命令行,即使是错误通常也由 LaTeX IDE 和编辑器处理。几乎每次您需要某些 LaTeX 命令的帮助时,您都在文本编辑器中。也许这就是为什么 LaTeX 不提供您所说的那种帮助。如果有任何有关 LaTeX 命令的帮助,它通常会集成到您正在使用的编辑器中。例如在 vim 中,如果您安装了 LaTeX 支持,则所有标准 LaTeX 命令(使用 LaTeX 与标准类之一且不需要其他包时可用的命令)都可以直接从 vim 帮助系统中访问,就像任何 vim 命令一样。我只需输入即可:he \mbox获得有关 LaTeX\mbox命令的帮助。不同的编辑器具有不同的功能,以及访问帮助系统的不同方式。

正如其他答案所指出的,如果您正在使用其他类和包,通常很难知道您的命令在哪里定义。使用不同的类和包,您会得到不同的命令,有时类或包会以自己的方式重新定义标准命令之一(例如,exam类的使用\part方式与标准 LaTeX 类中的使用方式完全不同)。这意味着任何帮助系统都必须在您键入文件时监视文件,并跟踪您正在使用的包。同样,文本编辑器可能是最适合此目的的。支持 LaTeX 的 Vim 确实会以某种方式跟踪您的包,尽管它不提供有关它们的帮助,但它会创建一个菜单,其中包含它识别的每个包中最重要的命令。理论上,这可以扩展,以便编辑器在您向文件中添加更多包时加载帮助文件,并扩展其帮助系统以涵盖这些包。可能可以编写一个程序来解析文件.dtx并尝试提取有关每个文件中定义的命令的信息。这可能并不容易,而且我认为它有点不可靠。

答案4

您可以使用以下代码显示包含给定字符串(例如给定的宏)的源代码部分。

如果您已经加载了所需的包,则可以在其中进行搜索。代码(和 之间\makeatletter\makeatother修补了\input原语,以便每次读取文件时,还会对其进行解析以在文件中查找给定的字符串。如果找到此字符串,它将与您的给定行数的上下文一起显示在终端上。它根本不是完善的代码(特别是,每次运行只能搜索一个字符串)。

要在特定文件中搜索,请执行\FindStringInFile {1}{5}{gathered}{amsmath.sty}(如果文件不存在,则会崩溃)。要在之后加载的所有文件中搜索,请执行\FindStringInAnyLaterFile {1}{5}{math*}。第一个和第二个参数是要在字符串前后显示的上下文行数。

在大多数简单情况下,代码不应该破坏文档的编译,但我无法做出任何保证。

\documentclass{minimal}

\makeatletter
% Standard macros
\def\FSIF@firstoftwo#1#2{#1}
\def\FSIF@secondoftwo#1#2{#2}
\def\FSIF@ifempty@NTF #1{%
  \expandafter\ifx \expandafter a\detokenize\expandafter{#1}a%
  \expandafter\FSIF@firstoftwo
  \else
  \expandafter\FSIF@secondoftwo
  \fi
}

% Declare our variables
\newread\FSIF@read
\newcount\FSIF@line@int
\newcount\FSIF@pre@context@int
\newcount\FSIF@post@context@int
\newcount\FSIF@found@int
\gdef\FSIF@context{}
\def\FSIF@lines@found{}
\def\FSIF@line@part@i{}
\def\FSIF@line@part@ii{}
\def\FSIF@message@break{}

\def\FindStringInFile#1#2#3#4{%
  \FSIF@pre@context@int#1\relax
  \FSIF@post@context@int#2\relax
  \gdef\FSIF@context{}%
  \expandafter\FSIF@aux\expandafter{\detokenize{#3}}{#4}%
  \FSIF@show@context
}


\def\FSIF@show@context{%
  \begingroup
  \newlinechar\endlinechar
  \show\FSIF@context
  \endgroup
}

\def\FSIF@aux #1#2{% `#1` is now detokenized
    \begingroup
    % Setup for nice display
    \begingroup\lccode`\*\endlinechar
    \lowercase{\endgroup \def\FSIF@message@break{*--------------------%
        ---------- #2 ------------------------------*}}%
    % 
    % Define a macro delimited by `#1`
    \def\FSIF@line@split##1#1##2\FSIF@mark##3\FSIF@stop{%
        \def\FSIF@line@part@i{##1}%
        \def\FSIF@line@part@ii{##2}%
    }%
    %  
    % Prepare to read the file, line by line (detokenized)
    \FSIF@line@int 0\relax
    \immediate\openin\FSIF@read #2\relax
    \ifeof\FSIF@read\ERROR\fi
    \def\FSIF@lines@found{}%
    %
    % Save each line in a different control sequence, built with
    % `\FSIF@fileline{<file name>}{<line number>}`.
    % 
    % If the string was found, store the line number in 
    % `\FSIF@lines@found`
    \loop 
    \unless\ifeof\FSIF@read
    \readline\FSIF@read to \FSIF@line@buffer
    \advance\FSIF@line@int by 1\relax
    \expandafter\expandafter\expandafter\let
        \FSIF@fileline{#2}{\the\FSIF@line@int}\FSIF@line@buffer
    \expandafter \FSIF@line@split \FSIF@line@buffer 
        \FSIF@mark #1\FSIF@mark \FSIF@stop
    \FSIF@ifempty@NTF \FSIF@line@part@ii {}{% 
        \edef\FSIF@lines@found{\FSIF@lines@found\the\FSIF@line@int,}%
    }%
    \repeat
    % 
    \expandafter\edef\csname FSIF@#2@lineno\endcsname{\the\FSIF@line@int}%
    % 
    % Then add `\FSIF@context@int` context lines around each line.
    % There can be overlaps...
    \edef\FSIF@lines@found{\FSIF@lines@found
      \number\numexpr\the\FSIF@line@int+\the\FSIF@pre@context@int,}%
    %
    \FSIF@pop@lines@found
    \FSIF@line@int 0\relax
    \loop
    \advance\FSIF@line@int by 1\relax
    % If we've exhausted this found-line's context, see the next one.
    \ifnum\numexpr\the\FSIF@found@int+\the\FSIF@post@context@int
                  <\the\FSIF@line@int\relax
    \FSIF@pop@lines@found
    \fi
    % If we're not yet at a context, step to one.
    \ifnum\numexpr\the\FSIF@found@int-\the\FSIF@pre@context@int
                  >\the\FSIF@line@int\relax
    \FSIF@line@int\numexpr\the\FSIF@found@int-\the\FSIF@pre@context@int
    \xdef\FSIF@context{\FSIF@context\FSIF@message@break}%
    \fi
    % Now we're in a context, so store that line.
    \xdef\FSIF@context{\FSIF@context\FSIF@fileline{#2}{\the\FSIF@line@int}}%
    % If we've not reached the end, we're done.
    \ifnum\FSIF@line@int<\csname FSIF@#2@lineno\endcsname\relax
    \repeat
    \endgroup
}

\def\FSIF@fileline#1#2{\csname FSIF@#1@#2\endcsname}

\def\FSIF@pop@lines@found{%
  \expandafter\FSIF@pop@lines@found@aux \FSIF@lines@found\FSIF@stop}
\def\FSIF@pop@lines@found@aux #1,#2\FSIF@stop{%
  \FSIF@found@int#1\relax \def\FSIF@lines@found{#2}}


\def\FSIF@new@@@input{\expandafter\FSIF@new@@@input@aux\romannumeral-`\0}
\def\FSIF@new@@@input@aux#1 {%
  \expandafter\FSIF@aux\expandafter{\FSIF@string}{#1}%
  \FSIF@show@context
  \FSIF@old@@@input #1 }

\def\FindStringInAnyLaterFile#1#2#3{%
  \FSIF@pre@context@int#1\relax
  \FSIF@post@context@int#2\relax
  \edef\FSIF@string{\detokenize{#3}}%
  \gdef\FSIF@context{}%
  % patch `\@@input`.
  \let\FSIF@old@@@input\@@input
  \let\@@input\FSIF@new@@@input
}


\makeatother
%

\FindStringInFile {1}{5}{gathered}{amsmath.sty}

\FindStringInAnyLaterFile {1}{5}{math*}

\usepackage{amsmath}

\usepackage{breqn}

\begin{document}

An equation,
\begin{align*}
  x^2 + y^2 &= z^2 \\
  x^2 - y^2 &= t^2
\end{align*}

\end{document}

相关内容