預先通告:我非常努力地寻找这个问题的答案,并使用各种不同的术语进行搜索。但我仍然有一种微妙的感觉,有人之前问过这个问题,因为这是一个非常普遍和有效的问题。所以如果之前有人问过,请将我引导到相关主题并接受我的道歉 :)
这个问题很容易陈述,但很难解决(至少对于像我这样的 TeX 新手来说):我想了解有关我的 tex 文档的某些信息,例如章节和部分的字体类型和大小。
有没有办法提取这些信息,比如,使用一个以结构化格式显示样式信息的包?如果我没记错的话,有一个用于显示页边距的包,但我没找到一个用于显示样式的包。
我知道有些样式是用户定义的,可以从文档前言中解析。我对此有两个问题。如果我拥有(创建)tex 文档,我可能想轻松地检查一切是否已准备就绪并按计划进行。如果我不拥有 tex 文档并想在该文档中使用某种样式,我可能最终会进行大量猜测。显然,有些样式默认为某些包或文档样式,我需要深入研究它们的来源。如果我能用更巧妙的方法解决问题,我宁愿不这样做 :)
最后,让我用一种“亵渎”的方式重新表述我的问题。在 MS Word 中,当我单击某些文本时,我可以看到它是 Calibri 还是 Arial、字体大小、是否粗体和斜体、确切的颜色,甚至段落参数和其他内容。我需要 TeX 文档有类似的东西。
编辑:我还有一个类比:我想要 TeX 的 Inspect Element 对于 HTML 和 CSS 元素的作用。
答案1
简短的回答是,这是不可能的。
甚至不可能自动找到章节标题的定义,而不必担心如何解析该定义来确定正在使用的字体。
以标准article
班为例。在那里你会发现
\newcommand\section{\@startsection {section}{1}{\z@}%
{-3.5ex \@plus -1ex \@minus -.2ex}%
{2.3ex \@plus.2ex}%
{\normalfont\Large\bfseries}}
因此,如果您知道参数的含义,\@startsection
那么您就知道间距和字体选择的一些细节。具体是什么字体\normalfont
取决于正在使用的字体包和声明。
但是我尝试的第一门课不在核心 Latex 分布中,即 komascrartcl
课。
我花了一段时间才找到(我真的不知道这个类的细节)的定义,\section
没有明显的定义,\section
而是你会发现
\DeclareSectionCommand[%
style=section,%
level=1,%
indent=\z@,%
beforeskip=-3.5ex \@plus -1ex \@minus -.2ex,%
afterskip=2.3ex \@plus.2ex,%
tocindent=0pt,%
tocnumwidth=1.5em%
]{section}
请注意,缺少\
。与乳胶格式中定义的{section}
不同,它被定义\@startsection
\DeclareSectionCommand
在这个文件中因此,建议的解析器能够识别出这个声明实际上是定义的唯一方法\section
是解析它的定义,即
\newcommand*{\DeclareSectionCommand}[2][]{%
\edef\reserved@a{%
\noexpand\FamilyStringKey[.dsc]{KOMAarg}{style}{%
\expandafter\noexpand\csname scr@#2@style\endcsname
}%
}\reserved@a
\scr@ifundefinedorrelax{scr@local@levelincrease}{%
\RelaxFamilyKey[.dsc]{KOMAarg}{increaselevel}%
}{%
\FamilyCounterMacroKey[.dsc]{KOMAarg}{increaselevel}[1]%
{\scr@local@levelincrease}%
}%
\scr@ifundefinedorrelax{scr@local@leveloffset}{%
\edef\reserved@a{%
\noexpand\FamilyCounterMacroKey[.dsc]{KOMAarg}{level}{%
\expandafter\noexpand\csname #2numdepth\endcsname}%
}\reserved@a
}{%
\edef\reserved@a{%
\noexpand\DefineFamilyKey[.dsc]{KOMAarg}{level}{%
\noexpand\FamilySetCounterMacro{KOMAarg}{level}{%
\expandafter\noexpand\csname #2numdepth\endcsname
}%
\unexpanded{%
{\numexpr ##1+\scr@local@leveloffset\relax}%
\edef\scr@local@leveloffset{%
\the\numexpr\scr@local@leveloffset+\scr@local@levelincrease\relax
}%
}%
}%
}\reserved@a
}%
\edef\reserved@a{%
\noexpand\FamilyLengthMacroKey[.dsc]{KOMAarg}{indent}{%
\expandafter\noexpand\csname scr@#2@sectionindent\endcsname}%
}\reserved@a
\edef\reserved@a{%
\noexpand\FamilyLengthMacroKey[.dsc]{KOMAarg}{beforeskip}{%
\expandafter\noexpand\csname scr@#2@sectionbeforeskip\endcsname}%
}\reserved@a
\edef\reserved@a{%
\noexpand\FamilyLengthMacroKey[.dsc]{KOMAarg}{afterskip}{%
\expandafter\noexpand\csname scr@#2@sectionafterskip\endcsname}%
}\reserved@a
\edef\reserved@a{%
\noexpand\DefineFamilyKey[.dsc]{KOMAarg}{font}{%
\noexpand\IfExistskomafont{#2}{%
\noexpand\setkomafont
}{%
\noexpand\newkomafont
}{#2}{####1}%
\noexpand\FamilyKeyStateProcessed
}%
}\reserved@a
\FamilyStringKey[.dsc]{KOMAarg}{counterwithin}{\scr@local@counterwithin}%
\let\scr@local@counterwithin\relax
\scr@ifundefinedorrelax{scr@local@tocleveloffset}{%
\edef\reserved@a{%
\noexpand\FamilyCounterMacroKey[.dsc]{KOMAarg}{toclevel}{%
\expandafter\noexpand\csname #2tocdepth\endcsname}%
}\reserved@a
}{%
\edef\reserved@a{%
\noexpand\DefineFamilyKey[.dsc]{KOMAarg}{toclevel}{%
\noexpand\FamilySetCounterMacro{KOMAarg}{toclevel}{%
\expandafter\noexpand\csname #2tocdepth\endcsname
}%
\unexpanded{%
{\numexpr ##1+\scr@local@tocleveloffset\relax}%
\edef\scr@local@tocleveloffset{%
\the\numexpr\scr@local@tocleveloffset+\scr@local@levelincrease\relax
}%
}%
}%
}\reserved@a
}%
\edef\reserved@a{%
\noexpand\FamilyLengthMacroKey[.dsc]{KOMAarg}{tocindent}{%
\expandafter\noexpand\csname scr@#2@tocindent\endcsname}%
}\reserved@a
\edef\reserved@a{%
\noexpand\FamilyLengthMacroKey[.dsc]{KOMAarg}{tocnumwidth}{%
\expandafter\noexpand\csname scr@#2@tocnumwidth\endcsname}%
}\reserved@a
\FamilyExecuteOptions[.dsc]{KOMAarg}{#1}%
\begingroup
\scr@ifundefinedorrelax{#2numdepth}{%
\scr@declaresectioncommanderror{#2}{section level}{level}%
}{}%
\scr@ifundefinedorrelax{scr@#2@sectionindent}{%
\scr@declaresectioncommanderror{#2}{section indent}{indent}%
}{}%
\scr@ifundefinedorrelax{scr@#2@sectionbeforeskip}{%
\scr@declaresectioncommanderror{#2}{before section skip}{beforeskip}%
}{}%
\scr@ifundefinedorrelax{scr@#2@sectionafterskip}{%
\scr@declaresectioncommanderror{#2}{after section skip}{afterskip}%
}{}%
\IfExistskomafont{#2}{}{%
\scr@declaresectioncommanderror{#2}{font}{font}%
}{}%
\scr@ifundefinedorrelax{scr@#2@tocindent}{%
\scr@declaresectioncommanderror{#2}{toc entry indent}{tocindent}%
}{}%
\scr@ifundefinedorrelax{scr@#2@tocnumwidth}{%
\scr@declaresectioncommanderror{#2}{toc entry number
width}{tocnumwidth}%
}{}%
\endgroup
\@firstofone{%
\@ifundefined{c@#2}{\newcounter{#2}}{}%
\ifx\scr@local@counterwithin\relax
\else\ifx\scr@local@counterwithin\@empty
\@namedef{the#2}{\arabic{#2}}%
\else
\@removefromreset{#2}{\scr@local@counterwithin}%
\@addtoreset{#2}{\scr@local@counterwithin}%
\expandafter\def\csname the#2\expandafter\endcsname{%
\csname the\scr@local@counterwithin\endcsname.\arabic{#2}}%
\fi
\fi
\@ifundefined{#2format}{%
\@namedef{#2format}{\csname the#2\endcsname\autodot\enskip}%
}{}%
\ifstr{\csname scr@#2@style\endcsname}{}{%
\ClassInfo{\KOMAClassName}{%
not defining `\expandafter\string\csname #2\endcsname' due
to\MessageBreak
empty section style%
}%
}{%
\scr@ifundefinedorrelax{scr@#2@style}{%
\ClassWarning{\KOMAClassName}{using default section style}%
\@namedef{scr@#2@style}{section}%
}{}%
\expandafter\edef\csname #2\endcsname{%
\noexpand\scr@ifundefinedorrelax{%
scr@start\csname scr@#2@style\endcsname}{%
\noexpand\ClassError{\noexpand\KOMAClassName}{%
section style `\csname scr@#2@style\endcsname' not defined}{%
A not yet defined section style `\csname scr@#2@style\endcsname'
has been setup for\MessageBreak
`\expandafter\string\csname #2\endcsname'. You should either setup
another style\MessageBreak
or define the style.\MessageBreak
If you'll continue, style `section' will be used as an emergency
fallback.%
}%
\noexpand\def\expandafter\noexpand\csname scr@#2@style\endcsname
{section}%
}{}%
\expandafter\noexpand
\csname scr@start\csname scr@#2@style\endcsname\endcsname
{#2}%
\expandafter\noexpand\csname #2numdepth\endcsname
\expandafter\noexpand\csname scr@#2@sectionindent\endcsname
\expandafter\noexpand\csname scr@#2@sectionbeforeskip\endcsname
\expandafter\noexpand\csname scr@#2@sectionafterskip\endcsname{%
\noexpand\ifdim\noexpand\glueexpr
\expandafter\noexpand\csname scr@#2@sectionbeforeskip\endcsname
<\noexpand\z@
\unexpanded{%
\ifnum \scr@compatibility>\@nameuse{scr@[email protected]}\relax
\setlength{\parfillskip}{\z@ plus 1fil}%
\fi
}%
\noexpand\fi
\unexpanded{%
\raggedsection\normalfont\sectfont\nobreak\usekomafont{#2}%
}%
}%
}%
}%
\@ifundefined{DeclareSectionNumberDepth}{%
\@ifundefined{#2markformat}{%
\@namedef{#2markformat}{\csname the#2\endcsname\autodot\enskip}%
}{}%
\@ifundefined{#2mark}{%
\expandafter\let\csname #2mark\endcsname\@gobble
}{}%
}{%
\DeclareSectionNumberDepth{#2}{\csname #2numdepth\endcsname}%
}%
\scr@ifundefinedorrelax{#2tocdepth}{%
\expandafter\let\csname #2tocdepth\expandafter\endcsname
\csname #2numdepth\endcsname
}{}%
\expandafter\providecommand\expandafter*%
\csname add#2tocentry\endcsname[2]{%
\addtocentrydefault{#2}{##1}{##2}%
}%
\scr@ifundefinedorrelax{l@#2}{%
\expandafter\edef\csname l@#2\endcsname{%
\noexpand\bprot@dottedtocline
\expandafter\noexpand\csname #2tocdepth\endcsname
\expandafter\noexpand\csname scr@#2@tocindent\endcsname
\expandafter\noexpand\csname scr@#2@tocnumwidth\endcsname
}%
}{}%
}%
}
并注意其中的行\expandafter\edef\csname #2\endcsname{
意味着第二个参数导致{section}
被\section
定义。
从那里到锻炼任何事物关于使用哪种字体似乎很棘手。人类读者可能会从诸如键名之类的键名中猜出一些东西,afterskip=2.3ex \@plus.2ex,
但是键名只是任意名称,所以任何猜测都只是猜测,除非您已经跟踪代码以查看它们的作用。
以上仅考虑\section
两个类中的一个命令article
和scratcl
。
答案2
这只是涉及‘亵渎’的部分。
您可以在 Word 中轻松恢复特定文档元素的精确格式信息的一个原因恰恰是 Word 不使用语义标记。
事实上,Word 甚至没有 LaTeX 那样的样式。从文档作者的角度来看,Word 的样式是衍生物- 格式是基础。从文档作者的角度来看,LaTeX 的样式是基本的- 它是衍生的格式。
因此,当您查看 Word 文档的“源代码”时,即使存在这样的源代码,它也不一定会告诉您每个文档元素的功能作用。标题可能如果作者组织严密、纪律严明,则可以使用样式。或者可能不会。但要使文档元素的格式与样式保持一致是一项艰巨的工作。您必须阻止自己做自然的事情,即直接更改您面前的元素的格式。
相比之下,在 LaTeX 文档中使用样式很容易,因为样式就在那里。具体格式并不就在你面前。就像文档元素并不就在你面前一样,解析器的文档元素也不就在你面前。当你在源代码中查看文档元素时,你看到的是它的功能作用,而你在编写文档内容时操纵的正是这个语义层。
这是一件好事!
当然,如果您不关心这些优点,您可以直接标记文档元素。在这种情况下,基本格式就在那里,解析器将能够相当轻松地确定它。当然,它无法轻易分辨出元素是标题还是其他,但它能够分辨出它是大号、粗体等等。如果您更进一步,您可以直接选择特定的字体和大小,然后解析器可以为您提供更多信息。您越避免语义标记,解析器就越能告诉您。这不是巧合,也不是避免此类标记的(好)理由!