环境

  • 操作系统:Windows 10/11、Ubuntu 20.04 LTS
  • LaTeX\LaTeX 发行版:MiKTeX 21.12、TinyTeX
  • 编辑器:Visual Studio Code、RStudio、Neovim
  • PDF 阅读器:SumatraPDF、Zathura

通常情况下,LaTeX\LaTeX 初学者应当安装 TeX Live[1] 和 TeX Studio 之后就可以编写文档了[2],但是本人并不喜欢 TeX Live 的臃肿和 TeX Studio 的丑,极其影响生产力。

MiKTeX 由 @Christian Schenk 一人维护,让我们说:谢谢 Christian

MiKTeX 会在需要用到某个包时自动安装。另外 2022 年请抛弃已经十年没更新的 CTeX\mathrm{C}\TeX(MikTeX 的分支),国内期刊可能要求你用,但没关西。

# 安装

# Windows

  1. 下载并安装 MiKTeX
    北外源或者清华源主页面右下角可以看到获取下载链接按钮,
    fig:01
    点进去,选择 应用程序 ,再下拉选择 TeX排版系统
    fig:02
    TeXstudio(需要的话,安装 Qt5 版本,更稳定)和 LyX(偏向所见即所得)是两种代码编辑器,这里不用。因为臃肿舍弃 TeX Live,MacTeX 仅支持 MacOS 系统,我们选择 MikTeX 21.12 (Windows, x64) ,下载 basic-miktex-21.12-x64.exe (basic 也就是基础包)
    fig:03
    fig:04
    fig:05
    安装路径改成自己想要的,不要中文,可以有空格
    fig:06
    安装缺失包选 Yes
    fig:07
    fig:08

  2. 配置 VSCode(这里假定你装好了 VSCode)
    安装插件

fig:09

需要在 设置 里添加如下配置[3]

settings.json参考链接
{
    "editor.minimap.enabled": true,// 控制是否显示缩略图
    "editor.bracketPairColorization.enabled": true,// 彩色括号
    "latex-workshop.chktex.enabled": false,// 检查 LaTeX 编写错误
    "latex-workshop.chktex.path": "chktex",//ChkTeX 路径
    "latex-workshop.chktex.run": "onSave",// 保存时自动检查
    "latex-workshop.intellisense.package.enabled": true,// 从使用包中自动补全命令和环境
    "latex-workshop.message.error.show": false,// 编译出错时是否
    "latex-workshop.message.warning.show": false,// 弹出气泡设置
    "latex-workshop.showContextMenu": false,// 右键运行菜单 "
    "latex-workshop.synctex.afterBuild.enabled": true,// 编译完成后自动同步
    "latex-workshop.view.pdf.internal.synctex.keybinding": "double-click",// 用于反向同步的内部查看器的按键绑定
    "latex-workshop.view.pdf.external.viewer.command": "C:/Program Files/SumatraPDF/SumatraPDF.exe",
    "latex-workshop.view.pdf.external.viewer.args": ["%PDF%"],// 设置外部查看器的参数
    "latex-workshop.view.pdf.external.synctex.command": "C:/Program Files/SumatraPDF/SumatraPDF.exe",// 反向同步的外部查看器的命令
    "latex-workshop.view.pdf.external.synctex.args": [// 反向同步的外部查看器的参数
        "-forward-search",
        "%TEX%",
        "%LINE%",
        "-reuse-instance",
        "-inverse-search",
        "\"C:/Program Files/Microsoft VS Code/Code.exe\" \"C:/Program Files/Microsoft VS Code/resources/app/out/cli.js\" --ms-enable-electron-run-as-node -r -g \"%f:%l\"",
        "%PDF%",
    ],
    "latex-workshop.view.pdf.viewer": "tab",// 设置 PDF 查看器的类型
    "latex-workshop.view.pdf.ref.viewer": "auto",// 设置反向同步的 PDF 查看器的类型
    "latex-workshop.latex.autoBuild.run": "never",// 设置是否自动编译
    "latex-workshop.latex.outDir": "%DIR%/out/",// 输出目录
    "latex-workshop.latex.clean.subfolder.enabled": true,// 设置是否清除子目录
    "latex-workshop.latex.autoClean.run": "never",// 编译失败时自动清理
    "latex-workshop.latex.recipe.default": "lastUsed",// 设置默认的编译方案
    "latex-workshop.latex.tools": [// 编译工具和命令
        {
            "name": "xelatex",
            "command": "xelatex",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-shell-escape",
                "-output-directory=%OUTDIR%",
                "%DOC%"
            ]
        },
        {
            "name": "latexmk",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-xelatex",
                "-shell-escape",
                "-outdir=%OUTDIR%",
                "%DOC%"
            ],
            "env": {}
        },
        {
            "name": "latexmk (lualatex)",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-lualatex",
                "-shell-escape",
                "-outdir=%OUTDIR%",
                "%DOC%"
            ],
            "env": {}
        },
        {
            "name": "latexmk_rconly",
            "command": "latexmk",
            "args": [
                "%DOC%"
            ],
            "env": {}
        },
        {
            "name": "pdflatex",
            "command": "pdflatex",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-shell-escape",
                "-output-directory=%OUTDIR%",
                "%DOC%"
            ],
            "env": {}
        },
        {
            "name": "lualatex",
            "command": "lualatex",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-shell-escape",
                "-output-directory=%OUTDIR%",
                "%DOC%"
            ]
        },
        {
            "name": "bibtex",
            "command": "bibtex",
            "args": ["%DOCFILE%"],
            "env": {}
        },
        {
            "name": "biber",
            "command": "biber",
            "args": [
                "--output-directory=%OUTDIR%",
                "%DOCFILE%"
            ],
            "env": {}
        },
        {
            "name": "texify",
            "command": "texify",
            "args": [
              "--synctex",
              "--pdf",
              "--tex-option=\"-interaction=nonstopmode\"",
              "--tex-option=\"-file-line-error\"",
              "%DOC%"
            ],
            "env": {}
        },
        {
            "name": "rnw2tex",
            "command": "Rscript",
            "args": [
                "-e",
                "knitr::opts_knit$set(concordance = TRUE); knitr::knit('%DOCFILE_EXT%')"
            ],
            "env": {}
        },
        {
            "name": "jnw2tex",
            "command": "julia",
            "args": [
              "-e",
              "using Weave; weave(\"%DOC_EXT%\", doctype=\"tex\")"
            ],
            "env": {}
        },
        {
            "name": "jnw2texmintex",
            "command": "julia",
            "args": [
                "-e",
                "using Weave; weave(\"%DOC_EXT%\", doctype=\"texminted\")"
            ],
            "env": {}
        },
        {
            "name": "tectonic",
            "command": "tectonic",
            "args": [
                "--synctex",
                "--keep-logs",
                "%DOC%.tex"
            ],
            "env": {}
        }
    ],
    "latex-workshop.latex.recipes": [// 用于配置编译链
        {
            "name": "LaTeXMK",
            "tools": ["latexmk"]
        },
        {
            "name": "LaTeXMK (latexmkrc)",
            "tools": [
                "latexmk_rconly"
            ]
        },
        {
            "name": "LaTeXMK (lualatex)",
            "tools": [
                "lualatexmk"
            ]
        },
        {
            "name": "XeLaTeX ➞ Biber ➞ XeLaTeX × 2",
            "tools": [
                "xelatex",
                "biber",
                "xelatex",
                "xelatex"
            ]
        },
        {
            "name": "XeLaTeX ➞ BibTeX ➞ XeLaTeX × 2",
            "tools": [
                "xelatex",
                "bibtex",
                "xelatex",
                "xelatex"
            ]
        },
        {
            "name": "PDFLaTeX ➞ BibTeX ➞ PDFLaTeX × 2",
            "tools": [
                "pdflatex",
                "bibtex",
                "pdflatex",
                "pdflatex"
            ]
        },
        {
            "name": "XeLaTeX",
            "tools": ["xelatex"]
        },
        {
            "name": "LuaLaTeX",
            "tools": ["lualatex"]
        },
        {
            "name": "PDFLaTeX",
            "tools": ["pdflatex"]
        },
        {
            "name": "TeXify",
            "tools": ["texify"]
        },
        {
            "name": "BibTeX",
            "tools": ["bibtex"]
        },
        {
            "name": "Biber",
            "tools": ["biber"]
        },
        {
            "name": "Compile Rnw files",
            "tools": [
                "rnw2tex",
                "latexmk"
            ]
        },
        {
            "name": "Compile Jnw files",
            "tools": [
                "jnw2tex",
                "latexmk"
            ]
        },
        {
            "name": "tectonic",
            "tools": [
                "tectonic"
            ]
        }
    ],
    "latex-workshop.latex.clean.fileTypes": [// 文件清理
        "*.aux",
        "*.bbl",
        "*.bcf",
        "*.blg",
        "*.idx",
        "*.ind",
        "*.ilg",
        "*.lof",
        "*.lot",
        "*.out",
        "*.toc",
        "*.toe",
        "*.acn",
        "*.acr",
        "*.alg",
        "*.glg",
        "*.glo",
        "*.gls",
        "*.ist",
        "*.fls",
        "*.log",
        "*.fdb_latexmk",
        "*.snm",
        "*.synctex(busy)",
        "*.synctex.gz",
        "*.synctex.gz(busy)",
        "*.nav",
        "*.run.xml",
        "*.hd",
        "*.xdv",
        "*.swp",
        "*.un~"
    ],
    "texlab.server.autoDownload": true,
    "workbench.colorCustomizations": {// 自定义彩色括号颜色
        "editorBracketHighlight.foreground1": "#5caeef",
        "editorBracketHighlight.foreground2": "#dfb976",
        "editorBracketHighlight.foreground3": "#c172d9",
        "editorBracketHighlight.foreground4": "#4fb1bc",
        "editorBracketHighlight.foreground5": "#97c26c",
        "editorBracketHighlight.foreground6": "#abb2c0",
        "editorBracketHighlight.unexpectedBracket.foreground": "#db6165"
    },
    "[latex]": {
        "editor.formatOnPaste": false,
        "editor.suggestSelection": "recentlyUsedByPrefix",
        "editor.defaultFormatter": "efoerster.texlab"
    }
}

Microsoft VS CodeSumatraPDF 的路径改成自己的。

接口可能会变更,一切以官方 Wiki 为主。

配置 SumatraPDF 反向同步,右键管理员身份运行 SumatraPDF ,点击 设置 -> 高级选项 ,查找 EnableTeXEnhancements ,改为

SumatraPDF-settings.txt
InverseSearchCmdLine = "C:\Program Files\Microsoft VS Code\Code.exe" "C:\Program Files\Microsoft VS Code\resources\app\out\cli.js" --ms-enable-electron-run-as-node -r -g "%f:%l"
EnableTeXEnhancements = true

注意使用自己的路径

编译最小工作实例(MWE),下面代码复制到新创建的 main.tex

main.tex
\documentclass{article}
\begin{document}
Hello \LaTeX !
\end{document}

fig:10
如果成功编译出 PDF 文件,且编辑器左下角任务栏有个✓而不是就是配置成功。

相关插件配置及使用:

  • Citation Picker for Zotero :从 Zotero 插入引文,快捷键 Alt + Shift + Z
  • HyperSnips for Math : 就是提供一些自动补全的快捷项(有点像代码片段),比如输入分数时不用输 \frac{1}{2} ,直接输 1/2 就会自动补全。需要到 OrangeX4's HyperSnips(或这里)下载补全的模板,放在 %APPDATA%/Code/User 新建的 hsnips 文件夹下。用 git 可以直接:
    git clone https://github.com/OrangeX4/OrangeX4-HyperSnips.git %APPDATA%/Code/User/hsnips
  • Latex Sympy Calculator [可选项]: 借助 sympylatex2sympy2 自动符号运算,稍显鸡肋,需要系统安装 Python ,且运行过 pip install sympy latex2sympy2 Flask

代码片段:latex.json(放到 %APPDATA%/Code/User/snippets

这部分适用于 R 语言用户
通常 R 语言用户会使用 RStudio 作为主力编辑器,就不用介绍安装步骤了(也仅是执行若干个下一步就搞定了)。这里用到的 TinyTeX[4],是 R 语言大神 @谢益辉 根据 TeX Live 的在线下载机制精简化的版本,本质上就是迷你 TeX Live,包含三个子版本:

  • TinyTeX-0.* :包含 TeX Live 的 infraonly 方案,不含任何 LaTeX 包。如果安装此版本,则可以通过 tlmgr 安装任何其他软件包,例如 tlmgr install latex-bin framed
  • TinyTeX-1.* :包含大约 90 个 LaTeX 包,足以编译常见的 RMarkdown 文档(这是 TinyTeX 项目的最初动机)。
  • TinyTeX.* :包含社区要求的更多 LaTeX 包。随着时间的推移,包的列表可能会增加,这种变化的大小也会相应增加。

其中 zip 适配 Windows, tgz 适配 MacOS, tar.gz 适配 Linux

但是由于 TeX Live 本身并不包含自动安装缺失包的功能,益辉老哥自己也没有太多精力实现这个逻辑(仅适配了 R 语言),让 TinyTeX 稍显鸡肋,通常只能利用 tlmgr 手动安装缺失的宏包,这在引用很少宏包情况下不太麻烦。

Windows Terminal
r
R version 4.1.2 (2021-11-01) -- "Bird Hippie"
Copyright (C) 2021 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
install.packages('tinytex')
??tinytex
starting httpd help server ... done
tinytex::is_tinytex()
[1] FALSE
tinytex::install_tinytex()
trying URL 'https://yihui.org/tinytex/TinyTeX-1.zip'
Content type 'application/octet-stream' length 104619761 bytes (99.8 MB)
downloaded 99.8 MB
3 File(s) copied
1 File(s) copied
Running fc-cache -v -r
tlmgr.pl: setting texmf max_print_line to 10000 (in C:/Users/i/AppData/Roaming/TinyTeX/texmf.cnf)
tinytex::is_tinytex()
[1] TRUE
tinytex::tinytex_root()
[1] "C:\\Users\\i\\AppData\\Roaming\\TinyTeX"
tinytex::xelatex("main.tex")
[1] "main.pdf"
tinytex::latexmk("main.tex")
[1] "main.pdf"
tinytex::tlmgr_repo(url = "https://mirrors.bfsu.edu.cn/CTAN/systems/texlive/tlnet")
tlmgr option repository "https://mirrors.bfsu.edu.cn/CTAN/systems/texlive/tlnet"
tlmgr.pl: setting default package repository to https://mirrors.bfsu.edu.cn/CTAN/systems/texlive/tlnet
tlmgr.pl: updating C:/Users/i/AppData/Roaming/TinyTeX/tlpkg/texlive.tlpdb
tinytex::tlmgr_update()
tlmgr update --all --self
q()
Save workspace image? [y/n/c]: n


24 步还可以直接到 Releases・yihui/tinytex-releases 下载解压压缩包,直接放到 %APPDATA%/TinyTeX ,再把路径加入环境变量中。

R Console
tinytex::tl_pkgs() # 查看宏包列表
tinytex::tlmgr_remove("ctex") # 删除单个宏包
tinytex::tlmgr_remove(c("xecjk", "ctex")) # 删除多个宏包
R Console
tinytex::uninstall_tinytex() # 卸载
tinytex::reinstall_tinytex() # 重装

# Linux

这里使用的是 Ubuntu 20.04 LTS (同样适用于 WSL2 ),在 Linux 下 TeX Live 和 MiKTeX 都是兼容的(两者现在都支持跨平台),由于我不经常有在 Linux 下编写 LaTeX\LaTeX 的场景,所以我选择了 TinyTeX 发行版。使用 Neovim 搭配 VimTeX 插件,PDF 阅读器使用 Zathura[5]

完全卸载 Vim [6]

sudo apt-get autoremove vim vim-runtime vim-tiny vim-common vim-scripts vim-doc

并安装 Neovim [7]

sudo apt-add-repository ppa:neovim-ppa/stable
sudo apt-get update
sudo apt-get install neovim

下载 vim-plug

sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'

配置 Neovim

~/.config/nvim/init.vimExample
call plug#begin()
" VimTeX 插件
Plug 'lervag/vimtex'
" coc.nvim 代码自动补全
Plug 'neoclide/coc.nvim', {'branch': 'release'}
" 代码片段
Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets'
call plug#end()
"" VimTeX
" 语法风格设为 LaTeX
let g:tex_flavor = 'latex'
" 不自动弹出编译错误窗口
let g:vimtex_quickfix_mode = 0
" 设置 PDF 阅读器
let g:vimtex_view_general_viewer = 'zathura'
let g:vimtex_view_method = 'zathura'
" 指定 VimTeX 编译程序
let g:vimtex_compiler_progname = 'nvr'
" VimTeX 目录 TOC 配置
let g:vimtex_toc_config = {
\ 'name' : 'TOC',
\ 'layers' : ['content', 'todo', 'include'],
\ 'split_width' : 25,
\ 'todo_sorted' : 0,
\ 'show_help' : 1,
\ 'show_numbers' : 1,
\}
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<c-b>"
let g:UltiSnipsJumpBackwardTrigger="<c-z>"
let g:UltiSnipsEditSplit="vertical"

安装插件 :PlugInstall

系统 Python 安装 neovim-remote(即 nvr ):

sudo python3 -m pip install neovim-remote

配置 Zathura

~/.config/zathura/zathurarc文档
set synctex true
set synctex-editor-command "nvr --remote-silent %f -c %l"

Neovim 的一些插件[8]

  1. VimTeX
    调出文章目录 :VimtexTocToggle

    快捷键:

    • \ll :使用默认编译器(latexmk)开始监听 .tex 文件的变化,编译 LaTeX 项目并打开 PDF 预览界面
    • \lk 或第二次 \ll :停止编译器监听文件变动,停止编译
    • \lv :正向从 Neovim 光标位置同步 PDF 显示区域
    • \lc :清理编译生成的中间文件
  2. coc.nvim: 依赖 node
    coc-vimtex:安装 :CocInstall coc-vimtex

  3. UltiSnips
    vim-snippets

# LaTeXMK

依赖 perl

perl -version

详细文档:

texdoc latexmk

配置文件:

.latexmkrc参考链接
## 工作路径 latexmk 配置文件
## 文件名:latexmkrc 或 .latexmkrc
## 文件目录:~
# 设置时区
$ENV{"TZ"}="Asia/Shanghai";
# 设置 pdflatex,xelatex,bibtex,biber 选项执行的命令
# % O, % S 是占位符;
# % O 代表选项,% S 代表对应命令的源文件
$pdflatex = "pdflatex -halt-on-error -file-line-error -synctex=1 -interaction=nonstopmode %O %S";
$lualatex = "lualatex -halt-on-error -file-line-error -synctex=1 -interaction=nonstopmode %O %S";
$xelatex = "xelatex -halt-on-error -file-line-error -synctex=1 -interaction=nonstopmode %O %S";
$xdvipdfmx = "xdvipdfmx -q -E -o %D %O %S";
$bibtex = "bibtex %O %S";
$biber = "biber %O %S";
# 生成后缀 fls 的文件,该文件包含程序读写时的文件列表,1 代表开启
$recorder = 1;
# 设置 pdf 预览器,需要把下面的程序路径更换为自己电脑 pdf 阅读器的路径
# Windows 使用 SumatraPDF
# Linux 使用 Zathura/Okular
# MacOS 使用 Skim
if($^O eq "MSWin32" or $^O eq "msys"){
    $pdf_previewer = 'start "D:\\Program Files\\SumatraPDF\\SumatraPDF.exe" %O %S';
}elsif($^O eq "linux"){
    $pdf_previewer = "start zathura %O %S";
    #$pdf_previewer = "start okular --unique %O %S";
}elsif($^O eq "darwin"){
    $pvc_view_file_via_temporary = 0;
    $pdf_previewer = "open -a Skim %O %S";
}
# 执行 latexmk -c 或 latexmk -C 时会清空 latex 程序生成的文件(-C 更强,会清空 pdf)
# 除此之外,可以设置额外的文件拓展,以进行清空
$clean_ext = "aux bbl blg idx ind ilg lof lot out toc toe acn acr alg glg glo gls ist fls log fdb_latexmk snm synctex(busy) synctex.gz synctex.gz(busy) nav run.xml hd xdv swp un~";
# 设置 pdf 生成模式,有 0 1 2 3 4 5
# 0 代表不生成 pdf
# 1 代表使用 $pdfltex 选项的命令,在系统 RC 文件已经设置
# 2 代表使用 $ps2pdf
# 3 代表使用 $dvipdf
# 4 代表使用 $lualatex;
# 5 代表使用 $xelatex,在系统 RC 文件已经设置
$pdf_mode = 5;
# 设置 bibtex 或 biber 的使用规则,有 0 1 1.5 2
# 0: 不使用 bibtex 或 biber; 清空的时候不会清空 .bbl 文件
# 1: 只有 bib 文件存在才使用 bibtex 或 biber;清空的时候不会清空 .bbl 文件
# 1.5: 只有 bib 文件存在才使用 bibtex 或 biber;当 bib 文件存在时会清空 bbl,否则不会清空
# 2: 有必要更新 bbl 文件时,运行 bibtex 或 biber,无需测试 bib 文件存在与否;清空删除 bbl
$bibtex_use = 1.5;
# 设置 latex 文件输出的目录
$out_dir = "out";
# 设置预览模式,相当于 -pv 选项,在编译结束会开启预览
# $view 设置预览的文件格式
$preview_mode = 1;
$view = "pdf";
# 设置 latexmk 编译的文件,和不需要编译的文件,可以时多个
@default_files = ("main.tex", "thesis.tex");
@default_excluded_files = ();
# 强制继续处理过去的错误,相当于 -f 选项
$force_mode = 1;
# 处理文件,不管时间戳如何,相当于 -g 选项
$go_mode = 1;
# 处理时更改为源文件的目录,相当于 -cd 选项
$do_cd = 1;
add_cus_dep("glo", "gls", 0, "glo2gls");
sub glo2gls {
    system("makeindex -s gglo.ist -o \"$_[0].gls\" \"$_[0].glo\"");
}
push @generated_exts, "glo", "gls";
add_cus_dep("nlo", "nls", 0, "nlo2nls");
sub nlo2nls {
    system("makeindex -s nomencl.ist -o \"$_[0].nls\" \"$_[0].nlo\"");
}
push @generated_exts, "nlo", "nls";

# 参考资料


  1. texlive-zh-cn ↩︎

  2. 一份简短的关于 LaTeX\LaTeX 安装的介绍 ↩︎

  3. LaTeX\LaTeX:用 VSCode 作为编辑器 ↩︎

  4. TinyTeX 中文文档 ↩︎

  5. 使用 Neovim 和 vimtex 高效撰写 LaTeX\LaTeX 学术论文 ↩︎

  6. ubuntu 下彻底卸载 vim 并重新安装 ↩︎

  7. 在 Ubuntu 上安装 Neovim (nvim) ↩︎

  8. VIM-Plug 安装插件时,频繁更新失败,或报端口 443 被拒绝等 ↩︎