简历/CV 大概是极少数会让读者在读内容之前先用外观下判断的文档之一。可是用 LaTeX 写简历的理由并不是「排出来好看」,而是:去年的简历今年还能原样编译,为每家公司所做的改动都以 git 的差异保留下来。这也是 LaTeX 中网上建议最容易过时的一角——好几个被反复称作「首选」的类,在 TeX Live 2024 里根本不存在;而确实存在的那个,第一次编译就会报错。本页只列出在 TeX Live 2024 上真正能用的东西,全部用 kpsewhich 和实际编译核对过。后半部分讲 信函:标准的 letter 类、KOMA-Script 的 scrlttr2,以及日文书信。
TeX Live 2024 里有哪些 CV 类,又缺了哪些
先说结论:moderncv、europecv、europasscv、currvita、komacv、limecv 都在 TeX Live 2024 里,而博客文章和 Overleaf 模板介绍里出现频率最高的 altacv 与 awesome-cv 并不在。在本地写 \documentclass{altacv},编译会停在 ! LaTeX Error: File 'altacv.cls' not found.(awesome-cv 的报错措辞相同)。这两者是通过 GitHub 和 Overleaf 模板库分发的,而非 CTAN;要用就得把仓库整个取下来,把 .cls 放到自己文档所在的目录。想把 Overleaf 上做好的简历搬回本地重排的人,第一个踩的多半就是这个坑。先敲一下 kpsewhich altacv.cls,什么都不输出就说明本地没有。
| 类 / 宏包 | TeX Live 2024 | 它能给你什么 |
|---|---|---|
moderncv | 有(v2.3.1) | 五种样式、七种配色,简历与求职信共用一个类 |
europecv | 有(需绕过一个错误) | 欧盟 Europass 版式;自带 29 种语言的标签定义 |
europasscv | 有 | Europass 的 2013 年修订版;其 README 明说未实现 2020 年版式 |
currvita | 有 | 是宏包而非类:在 article 之上加入 cv 与 cvlist 环境 |
komacv | 有(v1.1.2) | 在 KOMA-Script 之上重建的 moderncv 风格外观 |
limecv | 有(v0.1.12) | 带侧栏的现代版式——发行版内最接近 altacv 的选择 |
altacv | 无 | 经 GitHub / Overleaf 分发;kpsewhich altacv.cls 无任何输出 |
awesome-cv | 无 | 同上;会得到 ! LaTeX Error: File 'awesome-cv.cls' not found. |
moderncv 使用方法——\moderncvstyle 与 \cventry
moderncv 的设计思路只有一句:用两行决定外观,其余只写结构。\moderncvstyle{...} 从五种版式中选一种(casual〔默认〕、classic、banking、oldstyle、fancy),\moderncvcolor{...} 从七种配色中选一种(blue、black、burgundy、green、grey、orange、purple、red)。用 TeX Live 2024 附带的 v2.3.1 以 pdfLaTeX 逐一编译这五种样式,全部无错误通过。主力命令是 \cventry{years}{title}{institution}{location}{grade}{description},共六个参数,留空的 {} 会让该列自动收起。一行就够的条目用 \cvitem{header}{text},并排两项用 \cvdoubleitem,项目符号用 \cvlistitem。结构才是文档本身,样式只是套在外面的一层皮——所以为不同雇主把 casual 改成 banking 时,正文一个字符都不必动。
\documentclass[11pt,a4paper,sans]{moderncv}
\moderncvstyle{casual} % casual | classic | banking | oldstyle | fancy
\moderncvcolor{blue}
\usepackage[scale=0.75]{geometry}
\name{Taro}{Yamada}
\title{Software Engineer}
\address{1-1 Chiyoda}{Tokyo}{Japan}
\phone[mobile]{+81~90~0000~0000}
\email{[email protected]}
\begin{document}
\makecvtitle
\section{Experience}
% {years}{title}{institution}{location}{grade}{description}
\cventry{2020--2024}{Engineer}{ABC Inc.}{Tokyo}{}{Web development.}
\cvitem{Skills}{LaTeX, C, Python}
\end{document}moderncv 是不是已经没人维护了——它自己的 README 给了答案
「已经没人维护」只对了一半,而 TeX Live 2024 里附带的 README.md 说清了是哪一半:这份发行物是一个分支,目的是让 moderncv 在 CTAN 中继续活下去,因为上游自 2016 年起就已死亡。原作者是 Xavier Danaux;CHANGELOG 中 v2.1.0(2021 年 1 月 21 日)一条记着「maintainer change: now team maintained」,志愿者的接手就从那里开始。TeX Live 2024 收录的是 v2.3.1,日期为 2022 年 2 月 21 日。所以准确的说法不是「死了」,而是「2016 年被遗弃、2021 年被接手」——而且它在 TeX Live 2024 上确实能无错误编译。新增的 \social 服务项和迁移到 fontawesome5 也都是这个团队做的。
不过,被接手的宏包常见的毛病它也一并留着。moderncv 没有手册:README.md 老实写着「在写出像样的手册之前」请看 template.tex(随附的 moderncv_userguide.pdf 日期仍停在 2021 年 1 月)。而且文档目录里原样放着一个叫 KNOWN_BUGS 的文件,列出了诸如 fancy 样式下参考文献前后多余空白、配合 bibentry 时出现的 lonely \item--perhaps a missing list environment、以及 CJK 与 fancyhdr 的相互影响等已知问题。如果简历里要放论文列表,在决定用这个类之前先读一遍这一个文件,是最划算的调研。texdoc -l moderncv 会告诉你它在哪儿。
如何修掉 europecv 的 Sorting rule for 'begindocument' hook applied too late.
修法只有一行:自己在导言区写上 \usepackage{hyperref}(或 bookmark),错误就消失了。原因在类里。europecv.cls 是通过 \AtBeginDocument{...\RequirePackage{hyperref}...} 载入 hyperref 的——也就是说,在 \begin{document} 已经开始执行的时候才载入。hyperref 带来的 nameref.sty 会执行 \DeclareHookRule{begindocument}{showkeys}{before}{nameref},可此时 begindocument 钩子早已启动,于是 LaTeX 内核抛出 ! LaTeX hooks Error: Sorting rule for 'begindocument' hook applied too late.。自己提前载入 hyperref,nameref 就会在钩子规则仍然有效的时刻到场。
% europecv on TeX Live 2024: the class loads hyperref inside \AtBeginDocument,
% so nameref's hook rule arrives too late. Load hyperref yourself first.
\documentclass[a4paper,helvetica]{europecv}
\usepackage{graphicx} % europecv calls \includegraphics but does not load it
\usepackage{hyperref} % <- this line removes the "hook applied too late" error
\ecvname{Yamada, Taro}
\ecvemail{[email protected]}
\begin{document}
\begin{europecv}
\ecvpersonalinfo
\ecvsection{Work experience}
\ecvitem{2020--2024}{Engineer, ABC Inc., Tokyo}
\end{europecv}
\end{document}这不是新手失误而是类本身的缺陷,可以用 europecv 自带的例子验证:把 doc/latex/europecv/examples/minimal.tex——官方的最小示例——原样交给 pdfLaTeX,会得到同样的错误。相比之下 templates/cv_template_en.tex 能顺利通过,唯一相关的差别是它写了 \usepackage{bookmark},而 bookmark 会先把 hyperref 拉进来。另外 europecv.cls 调用了 \includegraphics 却不自己载入 graphicx,所以在保留徽标和旗帜的设置下还会附带出现 ! Undefined control sequence. \draweuropasslogo。加上 \usepackage{graphicx},或给类加上 nologo 选项。
关于 Europass 格式本身,别把两个名字相近的类搞混。europecv 实现的是 2002 年推出的欧洲通用格式一脉,并自带从 ecvbg.def 到 ecvsv.def 的 29 种语言标签定义文件。europasscv 实现的则是 2013 年改版后的版式,其 README 至今仍留着警告:「目前本类未实现 2020 年推出的最新 europass 版式」。欧盟的模板会改版,所以当招聘要求写着「请用 Europass 格式」时,务实的第一步是先弄清对方要的是哪一版。
标准 letter 类——一份文件寄给多个收件人
letter 类真正的卖点是:写几个 letter 环境,就得到几封信。发件人(\address)和签名(\signature)在导言区写一次,然后把 \begin{letter}{收件人} 一个个排下去,同一个发件人写给不同收件人的信就会逐封逐页输出——给十个人写推荐信、把同一份通知发给三十家公司,一个文件就能搞定。信体只有三部分:\opening{称呼}、正文、\closing{落款}。日期由 \today 自动填入;\encl{...} 印作 encl:,\cc{...} 印作 cc:,\ps{...} 把附言放在签名下方。写两封信就出两页,这一点实际编译就能验证。
\documentclass[11pt]{letter}
\address{Taro Yamada\\1-1 Chiyoda\\Tokyo 100-0001}
\signature{Taro Yamada}
\begin{document}
\begin{letter}{Hiring Manager\\ABC Inc.\\Osaka}
\opening{Dear Hiring Manager,}
I am writing to apply for the position.
\closing{Sincerely,}
\encl{CV, transcript} % prints as "encl:"
\cc{Personnel} % prints as "cc:"
\ps{P.S. Available from April.}
\end{letter}
% a second letter, same sender, second page
\begin{letter}{Second Recipient\\XYZ Ltd.}
\opening{Dear Sir or Madam,}
A second letter from the same source file.
\closing{Yours faithfully,}
\end{letter}
\end{document}scrlttr2 与 scrletter——折痕与开窗信封
scrlttr2 相对标准 letter 类的决定性差别在于:它连折纸装信封这一步都替你想到了。它会在折叠处印上浅浅的折痕线(foldmarks),并把收件人地址摆到开窗的位置。所有这些调整都被抽出到 .lco(letter class option)文件里,用 \LoadLetterOption{DIN} 载入。KOMA-Script 自带的 .lco 包括 DIN、DIN5008A、DIN5008B、DINmtext、NF(法国)、SN / SNleft(瑞士)、UScommercial9 / UScommercial9DW,以及把版面几何可视化印出来的 visualize。所有设置都通过 \setkomavar{fromname}{...} 形式的变量完成,内容与体例彻底分离。要按另一种信封规格重印同一封信,只需改 \LoadLetterOption 这一行。
另一个值得知道的是 scrletter。它不是类而是宏包,因此可以把 letter 环境直接嵌进 scrartcl 或 scrbook 文档中间。给报告附上一封送函、在合同末尾插入一页附函,都不必再拆成两份文档。实际上,在 \documentclass{scrartcl} 上加 \usepackage{scrletter},把 \begin{letter}{...} 放在 \section{...} 之后,文档就能照常编译。scrlttr2 与 scrletter 使用同一套变量和同样的 .lco,无需重新学习。
\documentclass[fontsize=11pt,foldmarks=true,parskip=half]{scrlttr2}
\LoadLetterOption{DIN} % or NipponEL, KakuLL, UScommercial9, SN, NF ...
\setkomavar{fromname}{Taro Yamada}
\setkomavar{fromaddress}{1-1 Chiyoda\\Tokyo 100-0001}
\setkomavar{signature}{Taro Yamada}
\setkomavar{subject}{Application for the advertised position}
\setkomavar{place}{Tokyo}
\begin{document}
\begin{letter}{Hiring Manager\\ABC Inc.\\Osaka}
\opening{Dear Hiring Manager,}
I am writing to apply for the position.
\closing{Sincerely,}
\encl{CV\\Transcript}
\end{letter}
\end{document}日文书信有专用的类吗——\挨拶 与长形信封的 .lco
TeX Live 2024 里没有日文书信的专用类。搜索 *letter*.cls 只能找到 scrlttr2、g-brief、dinbrief、akletter 等面向西文的类,没有和文书信类。不过实务上有两个答案。第一个在信封这一侧:KOMA-Script 自带按日本信封裁定的 .lco——NipponEL、NipponEH、NipponLL、NipponLH、NipponRL 对应长形与洋形 3 号/4 号,KakuLL 对应角形 A4(开窗尺寸为 90×45 mm 或 90×55 mm)。这项支持自 KOMA-Script 2.97e 起就有,手册的一个附录章节由 Gernot Hassenpflug 撰写,连 JIS A 系与 B 系纸张的差别都讲到了。
| .lco 文件 | 对应信封 | 开窗尺寸 |
|---|---|---|
DIN | 欧洲 DIN 规格信封(通常的起点) | — |
NipponEL | 长形/洋形 3 号、4 号 | 90 × 45 mm |
NipponEH | 同上,开窗更高的一类 | 90 × 55 mm |
NipponRL | 开窗偏右的长形/洋形 | 90 × 45 mm |
KakuLL | 角形 A4 | 90 × 45 mm |
visualize | 不是信封规格,而是把版面尺寸印出来以便核对 | — |
另一个答案在正文的开头。TeX Live 中随 jsclasses 分发的 okumacro.sty(奥村晴彦的宏集)定义了一个名字用日文写成的命令 \挨拶(问候),只要写下它,就会得到「拝啓」加上与当前月份相称的时令问候语。实现方式是朴素的十二分支 \ifcase\month:从一月起依次是 厳寒、春寒、早春、陽春、新緑、向暑、猛暑、残暑、初秋、仲秋、晩秋、初冬,末尾接上「の候,ますますご清栄のこととお喜び申し上げます。」。在八月用 upLaTeX 编译,确实会印出「拝啓 残暑の候,ますますご清栄のこととお喜び申し上げます。」。控制序列的名字能用日文书写本身就是 pTeX 一系的特点,也说明日文在这里被当作语言而非单纯的字符数据来处理。
% Japanese letter opening: okumacro defines a Japanese-named command that
% emits the salutation plus the seasonal formula for the current \month.
% Build with: uplatex jl.tex && dvipdfmx jl.dvi
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{okumacro}
\begin{document}
\挨拶
このたびは大変お世話になりました。
\hfill 敬具
\end{document}实务——该选哪一个,git 里该放什么
怎么选,多半由投递要求替你定了。若对方指定 Europass,就用 europecv 或 europasscv(先确认要哪一版)。若要写带 JIS 式表格框的日文履历书,用 tabular 自己排框比套 CV 类更快——所有 CV 类都以西文的「条目式」简历为前提,和带姓名栏、照片栏、印章栏的表格样式并不搭。其余一般英文 CV 用 moderncv;想要更现代的双栏外观就用 limecv;已经习惯 KOMA-Script 的用 komacv。无论选哪个,都别忘了用同一个类写求职信。moderncv 提供 \recipient、\opening、\makelettertitle、\makeletterclosing、\enclosure,能让简历与信函的标题、字体、配色保持一致。用两套模板做出来的两页纸,并排放在一起时通常一眼就能看出来。
- 按雇主区分的差异要放在不同文件里,而不是不同分支:共用一个
cv-body.tex,各个cv-company-a.tex只负责\input,更新就只有一处。 - 把类和模板一并放进仓库。凡是不在发行版里的东西——比如
altacv——正是三年后的你最会栽跟头的地方。 - 使用明确的输出文件名,而不是随手的
\jobname。名为main.pdf的附件会在对方的下载文件夹里彻底消失。 - 检查 PDF 元数据。
pdfinfo能看到的作者名和标题会随文件一起送到招聘方手上。 - 日文书信要一路测试到打印和折叠。若要装进开窗信封,
scrlttr2的visualize选项能把位置印出来供你核对。
最后,说说 LaTeX 在这一领域真正的强项。简历是设计文档,单论外观,它赢不了 InDesign,也赢不了 Canva 的模板。LaTeX 的长处在别处:五年前的 .tex 今天仍能产出同样的 PDF,为每家公司所做的改写能以 git diff 读出来,论文列表可以从 .bib 自动生成。也就是说,它让你把简历当作需要维护的资产,而不是一次性完成的作品。正因如此,选类时首先该确认的不是外观,而是这个类三年后还能不能编译——先用 kpsewhich 确认存在,再用实际编译确认健康,顺序就是这样。