关于 latex-writing
latex-writing 是用于编写和审阅结构清晰的 LaTeX 文档的技能,重点涵盖语义标记、列表选择、交叉引用、引文、引号及文学编程中的代码规范。
主要功能
- 01选择语义恰当的列表环境
- 02避免孤立的单项列表
- 03指导使用 cleveref 交叉引用
- 04涵盖引文与引号规范
- 05在 .nw 文件中使用 noweb 表记
适用场景
- 01组织定义和 API 参数
- 02审阅 LaTeX 列表与引用用法
- 03在 .nw 文档中编写代码示例
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dbosk/ claude-skills --skill latex-writing安装后在 Claude Code 中输入/latex-writing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CLAUDE.mdLICENSE.mdreferences/cleveref-type-names.mddual-beamer-article.mdminted-v3-and-floats.mdunicode-and-fonts.md详细介绍
LaTeX 写作最佳实践
本指南介绍如何按照既定最佳实践,创建结构良好、语义正确的 LaTeX 文档。
核心原则:语义标记
使用与内容语义相符的 LaTeX 环境,而不只是关注视觉效果。
列表环境:如何选择
为术语-定义配对使用 description
如果内容包含标签及其后面的解释、定义或描述,请使用 description 环境:
\begin{description}
\item[Term] Definition or explanation of the term
\item[Label] Content associated with the label
\item[Property] Description of the property
\end{description}
绝对不要这样做:
\begin{itemize}
\item \textbf{Term:} Definition or explanation
\item \textbf{Label:} Content associated with label
\end{itemize}
description 的常见用例
- API 参数:
\item[username] The user's login name - 配置选项:
\item[timeout] Maximum wait time in seconds - 术语表条目:
\item[LaTeX] A document preparation system - 通过/失败示例:
\item[Passes] Correct implementation... - 功能描述:
\item[Auto-save] Automatically saves every 5 minutes
例外:教学元评注
不要使用可见的 description 列表来呈现面向教师的教学性
注释,例如 \enquote{哪些内容会变化}、\enquote{哪些内容保持不变},
或教学材料中的顺序说明。这些内容应通过 didactic-notes 技能放入
\ltnote{...} 中。只有当带标签的内容属于面向学生的文档本身时,
才使用 description。
为简单列表使用 itemize
当列表项性质相同且不带标签时,请使用 itemize:
\begin{itemize}
\item First uniform item
\item Second uniform item
\item Third uniform item
\end{itemize}
为编号步骤或排名使用 enumerate
当顺序很重要时,请使用 enumerate:
\begin{enumerate}
\item First step in the process
\item Second step in the process
\item Third step in the process
\end{enumerate}
只有一个项目的列表应写成正文,而不是列表
只有一个 \item 的列表绝不正确:它会显示成一个孤立的项目符号,
没有同级项目可供枚举。在 exercise、definition、remark、
example、block 等语义环境中,这种情况十分常见:单个问题或
一行陈述被不必要地包装在 itemize 中。
% BAD — one bullet, nothing to list
\begin{exercise}
\begin{itemize}
\item Describe your algorithm for sorting laundry.
\end{itemize}
\end{exercise}
% GOOD — prose
\begin{exercise}
Describe your algorithm for sorting laundry.
\end{exercise}
两个简短句子分别写成两个项目符号,通常也不如直接写成正文。只有在
确实存在多个并列、可枚举的项目时,才使用 itemize/enumerate。
在同时包含 beamer/article 的幻灯片中,这一点尤为重要:孤立的项目
符号在幻灯片上显得难看,也会打断讲义的正文流畅度(参见
didactic-notes 技能)。
环境开头绝不要使用列表或代码块——先写引导文字
即使列表中确实有多个项目,也不能让它成为语义环境
(example、exercise、remark、definition、block)中的
第一项内容。如果一开始就是 \begin{enumerate}、\begin{itemize}、
\inputminted 或 \begin{minted},就会与环境的行内标签冲突:第一个
列表项(或第一行代码)会和 \enquote{示例 1.} 显示在同一行,彼此覆盖。
务必先写至少一句简短的引导语,再放入列表或代码。
% BAD — enumerate/minted butts against the "Exempel 1." label
\begin{example}[Att göra pannkakssmet]
\begin{enumerate}
\item Knäck tre ägg i en bunke.
...
\end{enumerate}
\end{example}
\begin{example}[Hela programmet]
\inputminted{python}{examples/pannkakor.py}
\end{example}
% GOOD — a lead-in sentence puts the list/code on its own line
\begin{example}[Att göra pannkakssmet]
Följ stegen:
\begin{enumerate}
\item Knäck tre ägg i en bunke.
...
\end{enumerate}
\end{example}
\begin{example}[Hela programmet]
Det ser ut så här:
\inputminted{python}{examples/pannkakor.py}
\end{example}
因此,规则并非 \enquote{禁止使用项目符号}——先用正文句子引出后, 就可以使用项目符号和代码。禁止的是让列表或代码块成为环境的开头。
在编号项目之间穿插评注(enumitem resume)
如果编号项目(调查/测验问题、要求、考试任务)需要附带解释性评注,
请让 \item 文本保持简洁,并将评注写成各个单项环境之间的正文;
使用 enumitem 恢复编号:
\begin{enumerate}
\item \enquote{Have you programmed before this course?}
\end{enumerate}
Commentary motivating the question, referencing what it serves.
\begin{enumerate}[resume]
\item \enquote{How do you plan to study in this course?}
\end{enumerate}
More commentary...
- 共享同一段评注的项目应放在同一个环境中。
- 需要
\usepackage{enumitem};在 beamer/article 双模式构建中,只在 article 驱动文件中加载该包(enumitem 与 beamer 的列表内部机制 冲突),并将此类列表放在 article 模式的正文中,幻灯片构建任务会 跳过这些内容(\mode*)。 - 反模式:在问题文本后将评注直接附加到
\item中——这样问题和其 理由就会混在一起。
识别模式
审阅或编写 LaTeX 时,请留意以下模式,这些模式表明应使用 description:
\item \textbf{SomeLabel:}→ 应使用\item[SomeLabel]\item \emph{SomeLabel:}→ 应使用\item[SomeLabel]\item SomeLabel ---→ 应使用\item[SomeLabel]- 每个条目都以粗体或强调文本开头的列表
修正常见反模式
反模式:在 Itemize 中使用粗体标签
% INCORRECT
\begin{itemize}
\item \textbf{Passes:} \verb|\documentclass{article}|
\item \textbf{Fails:} No documentclass declaration
\end{itemize}
正确:Description 环境
% CORRECT
\begin{description}
\item[Passes] \verb|\documentclass{article}|
\item[Fails] No documentclass declaration
\end{description}
反模式:使用手动格式,而非语义结构
% INCORRECT
\noindent\textbf{Configuration:} Set timeout to 30 seconds.\\
\textbf{Performance:} Optimized for large datasets.
正确:语义化的 Description
% CORRECT
\begin{description}
\item[Configuration] Set timeout to 30 seconds
\item[Performance] Optimized for large datasets
\end{description}
Literate Programming(.nw 文件)
重要:在 literate programming 文件(.nw)中编写 LaTeX 时,使用 noweb 的 [[code]] 表示法引用代码,而不是使用 \texttt 手动转义。
使用 [[code]] 表示法,而非 \texttt{...\_...}
noweb literate programming 系统提供了用于代码引用的特殊表示法,可自动处理下划线等特殊字符。
反模式:使用 \texttt 手动转义下划线
% INCORRECT - in .nw files
The \texttt{get\_submission()} method calls \texttt{\_\_getattribute\_\_}.
We store \texttt{\_original\_get\_submission} in the closure.
The \texttt{NOREFRESH\_GRADES} constant defines final grades.
正确:使用 [[code]] 表示法
% CORRECT - in .nw files
The [[get_submission()]] method calls [[__getattribute__]].
We store [[_original_get_submission]] in the closure.
The [[NOREFRESH_GRADES]] constant defines final grades.
原因:
- 自动转义特殊字符(下划线、反斜杠等)
- 提高源代码的可读性(无需手动转义)
- 遵循 literate programming 约定
- 避免因忘记转义而导致 LaTeX 错误
- 清晰地区分代码和正文
何时使用 [[code]],何时使用 \texttt
在 .nw 文件中使用 [[code]],适用于:
- 函数和方法名:
[[get_submissions()]]、[[__init__]] - 变量名:
[[_includes]]、[[user_id]] - 类名:
[[LazySubmission]]、[[Assignment]] - 常量:
[[NOREFRESH_GRADES]]、[[MAX_RETRIES]] - 模块名:
[[pickle]]、[[Canvas]] - 含有下划线或特殊字符的任何标识符
在 .nw 文件中使用 \texttt,适用于:
- 不含特殊字符的简短非代码技术术语
- 文件扩展名:
\texttt{.py}、\texttt{.nw} - 不含下划线的简单命令
在常规 .tex 文件中(非 literate programming 文件):
- 使用
\texttt并正确转义,因为这里无法使用[[...]] - 或使用
minted或listings等包来处理代码
审阅时的识别模式
审阅 .nw 文件时,请留意以下反模式:
\texttt{..._...}→ 应使用[[...]]\texttt{...__...}→ 应使用[[...]]\item[SOME\_CONSTANT behavior]→ 可以改写标签,并在正文中放入[[SOME_CONSTANT]];也可以在标签中将常量包在[[...]]内——\item[ [[SOME_CONSTANT]] behavior]。如果选择 第二种方式,请在]]和结尾的]之间至少隔一个字符(通常是一个空格),以免连续出现三个方括号, 从而触发 runaway-argument 错误。
真实代码示例
记录方法:
% INCORRECT
The \texttt{\_\_getstate\_\_} method excludes \texttt{\_original\_get\_submission}.
% CORRECT
The [[__getstate__]] method excludes [[_original_get_submission]].
记录常量:
% INCORRECT
\item[NOREFRESH\_GRADES behavior] Submissions with final grades...
% CORRECT
\item[Final grade policy] Submissions with final grades (A, P, P+, complete)
are never refreshed, maintaining the [[NOREFRESH_GRADES]] policy.
记录属性:
% INCORRECT
The decorator adds a \texttt{\_\_cache} dictionary and \texttt{\_\_all\_fetched} flag.
% CORRECT
The decorator adds a [[__cache]] dictionary and [[__all_fetched]] flag.
其他最佳实践
交叉引用
- 始终对所有交叉引用使用
\cref{...}(cleveref 包) - 绝不要使用
\S\ref{...}或手动输入章节/图表前缀 - 使用描述性标签:
\label{sec:introduction},而非\label{s1} - 示例:
- 章节:
\cref{sec:background}→ “第 2.1 节” - 图:
\cref{fig:diagram}→ “图 3” - 表:
\cref{tab:results}→ “表 1” - 多个:
\cref{sec:intro,sec:conclusion}→ “第 1 节和第 4 节”
- 章节:
反面示例:手动添加前缀
% INCORRECT
Section~\ref{sec:intro} shows...
\S\ref{sec:background} discusses...
Figure~\ref{fig:plot} demonstrates...
% CORRECT
\cref{sec:intro} shows...
\cref{sec:background} discusses...
\cref{fig:plot} demonstrates...
原因:cleveref 包会自动添加正确的前缀(章节、图等),并处理复数形式、范围和特定语言的格式。
引用类型名称:\cref 输出的名称必须与正文实际使用的词语一致,无论使用何种语言——如果文档说的是“步骤”,就不能渲染成“项目 5”(使用 \AtBeginDocument 钩子中的 \crefname 覆盖,并确保该钩子在 cleveref 之后注册,以免语言选项自身的钩子悄然覆盖它)。对于非英语文档,cleveref 还会从自身的包选项或全局类选项获取语言设置,而非从 babel 获取。一个文档中有多种类型时,可以按标签(\label[type]{...})或按环境处理(enumitem 的 \newlist,每个列表使用一个计数器——beamer 中除外)。完整指南见 references/cleveref-type-names.md(搜索:crefname、terminology、AtBeginDocument、label[type]、newlist、swedish、enumi、appendix)。
引文
- 使用正确的引文命令(
\cite、\citep、\citet),不要手动引用 - 绝不要手动写
[1]或(Smith 2020)
引语(csquotes 包)
- 始终使用
\enquote{...}表示引语,绝不要手动输入引号 - 自动处理嵌套引语:
\enquote{outer \enquote{inner} quote} - 根据语言调整:瑞典语使用 »...« 或 "...",英语使用 "..." 或 '...'
- 对于块引用,使用
\begin{displayquote}...\end{displayquote}
反面示例:手动输入引号
% INCORRECT
"This is a quote"
``This is a quote''
'single quotes'
正确:使用 csquotes
% CORRECT
\enquote{This is a quote}
\enquote{outer \enquote{inner} quote}
原因:手动输入的引号不会根据语言设置调整,还可能导致排版不一致。csquotes 包会根据文档语言正确处理所有引号样式。
引用原文与注明来源的转述
使用哪种命令取决于文本是否为源文中的逐字引用:
- 逐字转载源文 → 使用带引文的整合式引用命令,让引语自带出处;不要写
\enquote{...}再附上一个独立的\cite/\autocite:\textcquote[⟨prenote⟩][⟨postnote⟩]{key}{text}— 行内\blockcquote[⟨postnote⟩]{key}{text}— 块引用(长引语)
- 转述、重构的对话或转述的示例 → 这不是引语。使用
\textcite/\autocite将来源整合到正文中,并将任何转述的话语放在普通的\enquote中。 - 普通的
\enquote{...}仅用于其他情况:表示存疑的引号、提及词语本身,以及回指已引用的引语。
% INCORRECT — verbatim source text as \enquote + detached citation
The study reports \enquote{much higher (63\%)} results \autocite[p.~167]{NCOL}.
% CORRECT — verbatim quotation carries its own citation
The study reports \textcquote[p.~167]{NCOL}{much higher (63\%)} results.
% CORRECT — a paraphrased/recounted example is attributed, NOT \textcquote'd
\Textcite[pp.~24--25]{NCOL} reports a study in which a child answers
\enquote{five} for one hand and \enquote{ten} for the other.
重要注意事项:\textcquote/\blockcquote 表示花括号中的文本是源文中的逐字原文。使用前请确认这些文字确实出现在源文中;不要将这些命令用于转述、重构的对话或提及词语本身——此类内容应改用 \textcite/\autocite 标明来源。(参见 backing-claims 技能——引用前请阅读并核实来源。)
强调
- 在正文中,绝不要使用全大写来强调
- 使用
\emph{...}来强调词语或短语 - 强调程度较强时,使用
\textbf{...}或嵌套的\emph{\emph{...}} - 让 LaTeX 处理排版样式
反例:使用全大写来强调
% INCORRECT
This is VERY important to understand.
We must do this NOW before moving forward.
The BENEFITS of classes are clear.
正确:使用语义强调
% CORRECT
This is \emph{very} important to understand.
We must do this \emph{now} before moving forward.
The \emph{benefits} of classes are clear.
原因:在正文中使用全大写会被视为大喊大叫,排版效果也不好。它更难阅读,显得不专业。请使用 \emph{...} 进行语义强调,由 LaTeX 以适当的方式呈现(通常为斜体,但可根据上下文和文档样式进行配置)。
例外:按照惯例使用大写字母书写的缩写和专有名称(例如 NASA、USA、PDF)可以保留大写,也无需强调。
浮动体:图和表格
核心原则:图像不是图,但图可以包含图像。请使用规范的图和表格环境,并添加标题和标签。
每个表格和图都必须有标题——没有例外。 无论多小,都不要在 center 环境或正文中直接放置裸露的 tabular 或 \includegraphics:请将其放入带有标题和标签的 table/figure 浮动体中,并使用 \cref 引用。标题应说明读者应从表格或图中理解什么(它所体现的规则或所展示的要点),而不只是说明主题。从其他地方移植文本时请注意这一点——源文档中的无标题表格不能作为先例。
错误——裸露的 tabular,没有标题,按位置引用:
The slot length follows from the title:
\begin{center}
\begin{tabular}{lr}
Title & Minutes \\ \hline
Redovisning & 15 \\
Redovisning spec & 30 \\
\end{tabular}
\end{center}
The table above is the specification.
正确——带标题的浮动体,使用 \cref 引用:
The slot length follows from the title, see \cref{tab:slot-durations}.
\begin{table}
\begin{sidecaption}{%
The slot length that a title gives: 30 minutes for
\enquote{Redovisning spec}, 15 for any other title.
}[tab:slot-durations]
\begin{tabular}{lr}
\toprule
\textbf{Title} & \textbf{Minutes} \\
\midrule
Redovisning & 15 \\
Redovisning spec & 30 \\
\bottomrule
\end{tabular}
\end{sidecaption}
\end{table}
\Cref{tab:slot-durations} is the specification.
浮动体会移动,因此绝不要用 \enquote{上方}、\enquote{下方}或\enquote{下表}来指代它;请使用 \cref。
使用 sidecaption(memoir 类)
使用 memoir 文档类时,优先使用 sidecaption,而不是传统的 \caption,以获得更好的版式和可访问性:
用于插图:
\begin{figure}
\begin{sidecaption}{Clear description of image content}[fig:label]
\includegraphics[width=0.7\textwidth]{path/to/image}
\end{sidecaption}
\end{figure}
用于表格:
\begin{table}
\begin{sidecaption}{Description of table content}[tab:label]
\begin{tabular}{lcc}
\toprule
Header1 & Header2 & Header3 \\
\midrule
Data1 & Data2 & Data3 \\
\bottomrule
\end{tabular}
\end{sidecaption}
\end{table}
sidecaption 的主要特点:
- 标题位置:标题显示在内容(插图/表格)旁边,而非上方或下方
- 节省空间:更充分地利用页面宽度,尤其适用于较窄的图片/表格
- 提高可读性:标题与内容在视觉上紧密相连
- 可访问性:标题文本与内容之间有清晰的语义区分
- 标签一致:标签放在可选的第二个参数
[fig:label]中
将内容推向其侧边标题所在的一侧。 较窄的插图或表格必须贴着放置标题的页边距——标题在右侧页边距时靠右,在左侧页边距时靠左;绝不能靠左而让标题远在右侧,也不能居中。memoir 不会自动这样排版:它会在一个全宽、左对齐的盒子中排版正文。
- 使用 didactic ≥ 2.9(选项
sidecapalign=caption,默认值)时,这一过程会自动完成:正文中不要写\centering、\raggedleft或\flushscap。注意:可伸缩空白会折叠(A\hfill B最终会并排;可用\makebox[\linewidth]{A\hfill B}拉开),而正文中的脚注可能导致 varwidth 放弃处理(日志中会出现 \enquote{Failed to reprocess entire contents}),使正文保留在 memoir 原本放置的位置。 - 使用
sidecapalign=off或较旧版本的 didactic 时,在 sidecaption 正文开头放置\flushscap。在 2.9 之前,它读取的是前一个浮动体的侧边,因此在外侧/内侧标题的双面文档中,可能会向错误方向对齐。 - 不使用 didactic 时,只有当标题始终位于右侧页边距(单面文档或
\sidecapmargin{right})时,正文中的\raggedleft才有效。
检查生成的 PDF,确认浮动体与标题之间是否存在空隙。如果仍有空隙,请检查日志加载的是哪个 didactic.sty(grep -n 'didactic.sty' *.log):项目通常会将 didactic 作为 git 子模块打包(例如 doc/didactic,并链接为 doc/didactic.sty),且锁定在较旧版本,从而遮蔽 ~/texmf 中的版本。请更新子模块。
何时使用 sidecaption:
- 无需占满正文宽度的中等大小插图/表格
- 标题与内容相邻有助于理解的教学材料
- 使用 memoir 类的文档(具有 memoir 特性的 Beamer 演示文稿)
传统标题的替代方案:
\begin{figure}
\centering
\includegraphics[width=0.7\textwidth]{path/to/image}
\caption{Description of image content}
\label{fig:label}
\end{figure}
在以下情况下,使用传统的 \caption + \label:
- 不使用 memoir 类
- 插图/表格占满正文宽度
- 标题自然地放在内容下方(例如宽表格)
引用插图和表格
引用插图和表格时,始终使用 \cref{fig:label}(cleveref 宏包):
As shown in \cref{fig:memory-hierarchy}, secondary memory is slower but non-volatile.
The results in \cref{tab:benchmark} demonstrate...
绝不要硬编码引用,如 “Figure 1”“Table 3.2”,也不要使用 Figure~\ref{fig:label} 之类的手动前缀——让 cleveref 自动处理编号和前缀。
原样文本与代码
- 代码块使用
minted(首选,支持语法高亮;需要-shell-escape)或listings - 行内代码片段使用
\verb或\mintinline - 绝不要将代码作为普通文本粘贴
- minted v3(TeX Live 2024+)注意事项——参见
references/minted-v3-and-floats.md(搜索:outputdir、Pygments lexer):[outputdir=...]宏包选项已移除(现在会报错;应加载普通的\usepackage{minted});此外,minted/\mintinline的语言参数若跨行 会导致Pygments lexer " python" is unknown错误。每次 minted 调用的参数都应放在同一行;只在多个\mintinline{...}{...}调用之间换行,切勿在调用内部换行。
调试 ! LaTeX Error: Float(s) lost.
在 beamer/article 双模式教学内容 + memoir 构建中,这种致命且不显示位置的错误(在 \end{document} 处报告)通常由仅幻灯片的 \begin{frame}<presentation> frame 中的引用或脚注引起(它会抑制输出,但仍会执行主体内容,因此边注脚注会变成孤立内容),而不是普通 frame 中的引用;后者没有问题。运行一次精简的 pdflatex -halt-on-error,越过 latexmk/biber 的噪声,查看真正的错误,并通过最小复现进行诊断。修复方法:用 \mode<presentation>{...} 包住仅幻灯片的 frame(或用 \only<presentation>{...} 过滤引用)。**注意:**不能将 \mode<presentation>{...} 包装用于 [fragile] frame——组的结束 } 会落在 verbatim .vrb 扫描范围之外,导致 slides 构建失败,并报错 ! Extra }, or forgotten \endgroup。对于仅幻灯片的 fragile frame,如果实际上不需要 [fragile](其中没有 verbatim/minted/listings),就移除它;否则保留 \begin{frame}<presentation>[fragile],并用 \only<presentation>{\autocite{...}} 保护每个引用。完整诊断参见:
references/minted-v3-and-floats.md 和 didactic-notes 技能中的
references/footnotes-and-citations.md。
beamer/article 双模式构建(一个源文件,两种输出)
对于从相同内容文件编译两次的论文(memoir +
beamerarticle 文章和 beamer 幻灯片,内容文件以 \mode* 开头),请遵循 references/dual-beamer-article.md(搜索:pyblock frame、ProvideSemanticEnv、restatable、biber root)。简要来说,有四条规则:
- 每个 PythonTeX
pyblock都必须放在一个\begin{frame}[fragile]中,并且该 frame 必须在两种模式下都能渲染——幻灯片构建任务会跳过 frame 外的 pyblock,导致共享的 PythonTeX 会话数据不同步(症状:输出互换、?? PythonTeX ??)。 - 研究问题和假设应放在语义化且带有 cleveref 标签的环境中(didactic 的
question;在\DeclareTranslation后通过\ProvideSemanticEnv声明例如hypothesis),并写在\begin{restatable}{question}{tag}(thm-restate)中,再用\tag*重述——共享导言区中需提供 beamer 兼容层;通过\cref{rq:*}引用,绝不要直接写“RQ1”/“H2”。 - 仅幻灯片的 frame:用
\mode<presentation>{...}包装(注意上文关于 fragile 的限制);仅用于文章的正文应放在 frame 之外;不要让幻灯片项目符号列表与相邻的文章正文重复。 - **出处应与引文一同出现,并放在 frame 内。**幻灯片上展示的逐字引文必须在幻灯片上标注来源(在引文本身加脚注/
\footcite):如果出处放在 frame 后的仅文章正文中,幻灯片上的引文就会没有出处。将出处附在引文上后,它会在 beamer 幻灯片页脚处显示,并在文章中显示为边注/脚注——一个源文件即可满足两种构建任务。 - Biber 重跑应从项目根目录执行(
biber ltxobj/<jobname>),绝不要从输出目录内部执行。
编码和字体(取决于引擎)
Unicode/字体构建失败在 pdfLaTeX 与 XeLaTeX/LuaLaTeX 上的修复方法正好相反,因此请先确认引擎(grep 'This is' file.log)。
完整指南见 references/unicode-and-fonts.md(搜索:
DeclareUnicodeCharacter、iftex、newunicodechar、fontenc、pdffonts):
- pdfLaTeX —
! LaTeX Error: Unicode character … (U+XXXX) not set up— 某个非 ASCII 字节没有映射(反向引号、各种破折号、≈、方框绘图字符)。请在导言区使用\usepackage[utf8]{inputenc}然后使用\DeclareUnicodeCharacter{XXXX}{...}修复,不要编辑源文件。 (inputenc用于定义可移植的\DeclareUnicodeCharacter;没有它可能会出现Undefined control sequence。) - XeLaTeX/LuaLaTeX — 不会出现“not set up”错误(原生支持 UTF-8),而且此处的
\DeclareUnicodeCharacter未定义(inputenc会被忽略)。请使用\ifpdftex … \fi(iftex 包)将仅适用于 pdfLaTeX 的映射括起来;使用\newunicodechar重新映射字形。 - pdfLaTeX — 代码呈现为比例衬线字体(下划线提取为
˙,引号变成弯引号)——没有\usepackage[T1]{fontenc},就无法选择仅支持 T1 编码的等宽字体(例如 Bera Mono)。请加载该包(放在\ifpdftex分支中)。 - 构建系统可能会切换引擎。
latexmk -pdf与-xelatex不同,Makefile 规则也可能由.nw文件生成,因此make/子模块更新可能会切换引擎——请重新检查.log横幅,不要想当然。 - 诊断问题,不要猜测:
pdffonts -f N -l N file.pdf可显示某个页面嵌入了哪些字体;pdftotext -f N -l N可通过字形→Unicode 映射揭示编码。
路径
- 路径中始终使用正斜杠:
figures/diagram.pdf,而非figures\diagram.pdf - 使用与平台无关的路径规范
LaTeX 编写工作流
编写或编辑 LaTeX 内容时:
- 检查文件类型:你是否在
.nw文学编程文件中?如果是,请使用[[code]]表示法,而非\texttt{...\_...} - 识别内容结构:这是由统一条目组成的列表,还是术语—定义对?
- 选择语义环境:让环境与内容含义相匹配
- 使用恰当的命令:使用 LaTeX 的语义命令,而非手动格式化
- 核对交叉引用:确保标签和引用描述清晰且正确
- 检查反模式:检查 itemize 中的
\textbf{Label:},以及 .nw 文件中的\texttt{..._...}
审查 LaTeX 代码时
检查以下常见问题:
- 使用
\textbf{Label:}的列表,而非description环境 - 使用硬编码数字,而非
\ref - 手动添加交叉引用前缀(
\S\ref、Section~\ref、Figure~\ref),而非使用\cref - 手动设置引用格式,而非使用
\cite命令 - 使用手动引号(
"..."、'...'、`...`),而非使用\enquote{...} - 逐字引用 的源文本使用
\enquote{...}+ 独立的\cite/\autocite,而非使用\textcquote/\blockcquote(反之,若\textcquote/\blockcquote包裹的是改写内容而非逐字引用,也有问题) - 图片未使用
figure环境 - 代码格式不正确(未使用 listings/verbatim)
- 路径中使用 Windows 风格的反斜杠
- 未使用
iftex保护引擎专用的 Unicode/字体设置——例如,无条件使用\DeclareUnicodeCharacter(仅适用于 pdfLaTeX),这会导致 XeLaTeX/LuaLaTeX 报错(参见references/unicode-and-fonts.md) - pdfLaTeX:非 ASCII 字符没有对应的
\DeclareUnicodeCharacter映射,或使用了\DeclareUnicodeCharacter,却没有\usepackage[utf8]{inputenc} - pdfLaTeX:等宽字体/代码被渲染为比例衬线字体——缺少适用于仅支持 T1 编码字体(如 Bera Mono)的
\usepackage[T1]{fontenc} - Beamer/article 双模式构建:
pyblock位于不同时用于两种模式的\begin{frame}[fragile]外部(这会导致 PythonTeX 会话不同步),或在正文中使用字面文本 "RQ1"/"H2",而非通过\cref引用语义化的问题/假设环境(参见references/dual-beamer-article.md)
对 .nw 文学编程文件的额外检查:
-
\texttt{..._...}或\texttt{...__...}→ 应使用[[...]]表示法 - 描述标签中含有下划线,例如
\item[FOO\_BAR behavior]→ 使用更合适的标签,并在文本中使用[[FOO_BAR]] - 代码引用中任何手动转义的下划线 → 改用
[[...]]
Beamer:演示模式与文章模式
创建同时生成文章版本的 Beamer 演示文稿时,使用 \mode<presentation> 和 \mode<article>,为每种格式提供合适的内容。
何时拆分内容
冗长的文本环境:定义、备注、示例、区块等语义环境中的正文超过 2-3 行时,对于幻灯片而言过于冗长。
解决方案:为演示文稿提供简洁版本,为文章提供完整说明:
\begin{frame}
\mode<presentation>{%
\begin{remark}[Key Point]
\begin{itemize}
\item Concise point 1
\item Concise point 2
\item Concise point 3
\end{itemize}
\end{remark}
}
\mode<article>{%
\begin{remark}[Key Point]
Full explanatory paragraph with detailed reasoning and context
that would overwhelm a slide but provides value in written form.
Additional paragraphs can elaborate on nuances and implications.
\end{remark}
}
\end{frame}
视觉元素
使用 \textbytext 的并排布局:
- 演示文稿:
\textbytext(无星号,列宽,适用于 beamer 帧) - 文章:
\textbytext*(带星号,全宽,更适合印刷文档)
\begin{frame}
\mode<presentation>{%
\textbytext{Left content}{Right content}
}
\mode<article>{%
\textbytext*{Left content}{Right content}
}
\end{frame}
原则
幻灯片需要清晰的视觉效果和简洁性(项目符号、短语)。文章则可以提供深度和解释(完整句子、段落)。应针对不同媒介设计合适的内容。
使用 Mentipy 的互动问题
对于需要嵌入实时投票的幻灯片或教学文章,可在 PythonTeX 区块或其他 Python 区块中使用
mentipy.latex。面向学生的问题优先使用
mc、open_text、scale 和 word_cloud,然后运行
mentipy serve 发布投票;URL 更改后重新编译,以嵌入更新后的二维码。讲义使用
layout="article" 或 layout="article+qr";Beamer 幻灯片使用 layout="slide"。
标准导言区
对于新的 LaTeX 文档,请使用 references/preamble.tex 中的标准导言区。将其原样复制到项目的 doc/preamble.tex,并在 \documentclass 后使用 \input{preamble} 引入。
文档结构:
\documentclass[a4paper,oneside]{memoir}
\input{preamble}
\title{Document Title}
\author{Author Name}
\date{\today}
\begin{document}
\frontmatter
\maketitle
\tableofcontents
\mainmatter
% Content here
\backmatter
\end{document}
标准导言区提供:
- 语言支持、参考文献、数学和引文功能
- 代码高亮和 noweb 支持
- 交叉引用和表格
enumitem、acro和siunitx等常用实用工具
这可确保所有文档和项目的格式保持一致。
请记住
LaTeX 是一种基于语义标记的文档准备系统,而不是文字处理器。目标是描述内容是什么,而不是它应该是什么样子。让 LaTeX 根据你提供的语义结构处理格式。