小米的主页
大家好, 我是 B 站 UP 主金色飞贼小米. 这是我的个人主页.
我是一名科研工作者, 在业余时间制作了一些 Emacs 和 LaTeX 的教程, 希望能对大家有所帮助.
省时省力写 LaTeX 系列
本系列讲解 Emacs 中利用 AucTeX + CDLaTeX 等插件省时省力完成 LaTeX 写作, 轻松使用 LaTeX 做即时笔记.
Emacs 上搭建你的终生个人知识库
本系列讲解如何围绕 Org-roam 在 Emacs 上实现双链笔记与搭建个人知识库.
大家好, 我是 B 站 UP 主金色飞贼小米. 这是我的个人主页.
我是一名科研工作者, 在业余时间制作了一些 Emacs 和 LaTeX 的教程, 希望能对大家有所帮助.
本系列讲解 Emacs 中利用 AucTeX + CDLaTeX 等插件省时省力完成 LaTeX 写作, 轻松使用 LaTeX 做即时笔记.
本系列讲解如何围绕 Org-roam 在 Emacs 上实现双链笔记与搭建个人知识库.
笔记核心功能:
笔记类型举例
…
从笔记高效地提取信息很难
LaTeX, org, markdown 等原子化笔记 + 网状结构链接 串连笔记, 自下而上生成结构Roam Research, Obsidian, Logseq, Notion …org-roam 的知识管理系统org-roam… 而不是 Roam Research, Obsedian, Logseq, Notion, …
Zotero 整合Roam Research: 创建于 2020.1., 双链+图形界面, 订阅制 (基础版 180$/年)Obsidian: 创建于 2020.3. 基于 Markdown 文件, 有强大插件生态, 基础版免费, 全平台使用Logseq: 创建于 2020. 开源, 基于 Markdown 或 org 文件. 与 Obsedian 非常像org-mode + Emacs链接链接 体现org-roam 记录学习 org-roam 的笔记Zotero 文献管理整合 (org-ref, helm-bibtex, org-roam-bibtex)org-noter 整合org 笔记流程优化org-cdlatex, org-preview)company)pyim)org-ref)org 界面优化 (org-modern, org-face …)org-agenda)org-roam-daily)org-roam-ui)……
以 Emacs 28 为准
gcc 编译器: 用于编译 emacsql-sqlite (Emacs 29 后应该不再需要)Windows 下可通过 msys2 安装 (推荐), 并保证在系统可执行文件目录下 pacman -S mingw-w64-x86_64-gccLinux 或 MacOS 下大概率系统自带org-roam 插件package-el 安装: M-x package-install <return> org-roam <return>use-package 模块中 :ensure t (见后面示例)org-roam-ui 插件package-el 安装: M-x package-install <return> org-roam-ui <return>use-package 模块中 :ensure t (见后面示例)emacsql-sqliteorg-roam, Emacs 会提示正在编译 emacsql-sqlite, 请耐心等待..emacs.d/elpa/emacsql-sqlite-XXXXX/sqlite 的目录org-roam (use-package org-roam
:ensure t ;; 自动安装
:custom
(org-roam-directory "~/roam-notes/") ;; 默认笔记目录, 提前手动创建好
(org-roam-dailies-directory "daily/") ;; 默认日记目录, 上一目录的相对路径
(org-roam-db-gc-threshold most-positive-fixnum) ;; 提高性能
:bind (("C-c n f" . org-roam-node-find)
;; 如果你的中文输入法会拦截非 ctrl 开头的快捷键, 也可考虑类似如下的设置
;; ("C-c C-n C-f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
("C-c n l" . org-roam-buffer-toggle) ;; 显示后链窗口
("C-c n u" . org-roam-ui-mode)) ;; 浏览器中可视化
:bind-keymap
("C-c n d" . org-roam-dailies-map) ;; 日记菜单
:config
(require 'org-roam-dailies) ;; 启用日记功能
(org-roam-db-autosync-mode)) ;; 启动时自动同步数据库
(use-package org-roam-ui
:ensure t ;; 自动安装
:after org-roam
:custom
(org-roam-ui-sync-theme t) ;; 同步 Emacs 主题
(org-roam-ui-follow t) ;; 笔记节点跟随
(org-roam-ui-update-on-save t))创建链接是最基础也是最重要的功能!
org-roam-capture (快捷键 C-c n c)
创建一条新笔记. 未来可以预设不同主题的默认模板. 每一条笔记就是一个 org 文件
org-roam-find (快捷键 C-c n f) 通过关键词查找笔记并跳转
org-roam-insert (快捷键 C-c n i) 插入一条笔记的链接
删除笔记: 直接删除笔记文件即可, 如 M-x delete-file
org-mode 内链接跳转: 鼠标点击或 C-c C-o (org-open-at-point)
加入标签: 普通的标签可以看作一个特殊的笔记条目, 可以用 org-roam-insert 去插入一些以关键字为标题的笔记充当标签.
一个通用惯例是在笔记头部用 org 的列表格式罗列标签, 如
- tag :: <tag-1>, <tag-2>, <tag-3>以后我们也可以把这一行加入笔记模板
vertico + orderless
(use-package vertico ;; 补全界面优化
:ensure t
:config
(vertico-mode))
(use-package orderless ;; 无序搜索
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles partial-completion)))))org-roam 的笔记文件是纯文本文件, 用任意网盘同步即可org-roam-directory 变量 (或者直接放在网盘目录下)git 同步: 可控制文件类型, 版本控制org-roam.db../emacs.d/ 目录下org 文件自动生成的 ((org-roam-db-autosync-mode))Windows 下执行这一命令可能会出现 Error ....... Selecting deleted buffer 的错误信息. 只要 emacs-sqlite 已经正常安装, 无视这条错误信息并再次执行 org-roam-db-sync 即可..org 笔记文件作为书本页边空间的延展, 记录任何信息, 包括截图, 数学公式, 代码等pdf 窗口和 org 窗口双向同步pdf 文件时, 笔记窗口光标会跟随到相应位置pdf 文件会跟随滚动… 或者选择 org 文件的理由
Git)org-mode 的强大功能和生态org-mode 是 Emacs 中最强大的插件markdown, html, latex, odt 等多种格式org-mode: Emacs 自带, 可以通过 M-x package-list-package 更新到 Melpa 最新版pdf-tools: 阅读 pdf 必备, 参考往期视频:
【Emacs+LaTeX教程】Emacs最强内置pdf阅读功能pdf-tools简介org-noter: M-x package-list-package 安装 Melpa 最新版djvu, epub 文件支持use-package, 可将以下代码加入 init.el 自动安装 (use-package org-noter
:ensure t )org-noterorg-noter 打开需要执行 M-x org-noter 命令. 有两种方式
pdf 文件打开
需要指定 org 文件名及路径. 这时会自动生成一个 org 文件, 并在 org 文件中保存 pdf 文件的路径名org 文件打开
这里 org 文件里须包含 pdf 文件的路径名, 一般来说是由第一种方式生成的 org 文件.未来的计划: 结合 org-roam + org-roam-bibtex + Zotero, 我们可以生成一个包含 pdf 路径的 org-noter 读书笔记模板
org-noter 的笔记文件使用org-mode 基本操作在 pdf 界面, M-x org-noter-create-skeleton 可以导入 pdf 大纲
小技巧: 在 pdf-tools 中, o / q 可以显示/关闭大纲.
org-mode 常用快捷键:
org-noter 通过记录页码及位置保持笔记文件与 pdf 文件的同步. 根据定位的精度, 在 pdf 界面, 有 3 种插入笔记方式
在笔记中还可以使用 CDLaTeX 编辑数学公式, 以及用 org-download 插入截图. 请到教程的最后查看这些功能的基本设置.
pdf -> org: 自动org -> pdf: 手动pdf 界面中使用 (setq org-noter-notes-search-path '("your/path/to/note-directory/" "2nd-path" "3rd-path"))设置后, 从 pdf 文件中使用 org-noter 命令会自动在上述目录中寻找与文件名同名的 .org 笔记文件.
两种 org-noter 使用模式
.org 文件中.org 文件中: 将上述变量设置为一个文件名 (setq org-noter-notes-search-path '("your/path/to/notes.org")) (setq org-noter-auto-save-last-location t) (setq org-noter-highlight-selected-text t)这是全局设置. 如果想对某一条笔记临时启用或禁用, 可以使用 C-u 前缀.
例如: 当前高亮默认设置为 t, 但当前笔记不想高亮文字, 可以使用 C-u M-e 插入 precise note
Note for page XXX修改长/短文本标准:
(setq org-noter-max-short-selected-text-length 20) ;; 默认为 80修改短文本默认标题:
(setq org-noter-default-heading-title "第 $p$ 页的笔记") (global-set-key (kbd "C-c n n") 'org-noter) ;; 与 org-roam 配合
(define-key org-noter-doc-mode-map (kbd "e") 'org-noter-insert-note) ;; 加入左手键位
(define-key org-noter-doc-mode-map (kbd "M-e") 'org-noter-insert-precise-note) ;; 加入左手键位自定义设置的全部代码
(setq org-noter-notes-search-path '("your/path/to/note-directory/")) ;; 默认笔记路径
(setq org-noter-auto-save-last-location t) ;; 自动保存上次阅读位置
(setq org-noter-max-short-selected-text-length 20) ;; 默认为 80
(setq org-noter-default-heading-title "第 $p$ 页的笔记") ;; 默认短标题格式
(global-set-key (kbd "C-c n n") 'org-noter) ;; 与 org-roam 配合
(define-key org-noter-doc-mode-map (kbd "e") 'org-noter-insert-note) ;; 加入左手键位
(define-key org-noter-doc-mode-map (kbd "M-e") 'org-noter-insert-precise-note) ;; 加入左手键位将上述代码写在 use-package 代码块中:
(use-package org-noter
:ensure t
:custom
(org-noter-notes-search-path '("your/path/to/note-directory/")) ;; 默认笔记路径
(org-noter-auto-save-last-location t) ;; 自动保存上次阅读位置
(org-noter-max-short-selected-text-length 20) ;; 默认为 80
(org-noter-default-heading-title "第 $p$ 页的笔记") ;; 默认短标题格式
:bind
(("C-c n n" . org-noter) ;; 与 org-roam 配合
:map org-noter-doc-mode-map ;; 加入左手键位
("e" . org-noter-insert-note)
("M-e" . org-noter-insert-precise-note)))org-mode 中与 LaTex 有关的设置
(use-package org
:defer t ;; 延迟加载
:custom
(org-highlight-latex-and-related '(native latex entities)) ;; LaTeX 高亮设置
(org-pretty-entities t) ;; LaTeX 代码的 prettify
(org-pretty-entities-include-sub-superscripts nil) ;; 不隐藏 LaTeX 的上下标更容易编辑
(org-format-latex-options
'(:foreground default :background default :scale 1.8 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) ;; 增大公式预览的图片大小
:config
(add-hook 'org-mode-hook #'org-cdlatex-mode) ;; 打开 cdlatex
)CDLaTeX 的设置可以参考我的视频
我会在另一期教程中详细介绍 org-mode 中 LaTeX 编辑的设置.
需要借助 org-download 实现. 在这里只给出实现截图功能的设置代码, 以后的教程再详细讲解.
使用方法
Windows 下用 <Win>+<shift>+s) 将截图保存到剪贴板org 文件中.安装方法
Linux / MacOS (未测试)
用以下 use-package 代码安装及设置 (use-package org-download
:ensure t ;; 自动从 melpa 上安装
:defer t ;; 延迟加载
:bind
(:map org-mode-map
("C-M-y" . org-download-clipboard)) ;; 绑定从剪贴版粘贴截图的快捷键
:custom
(org-download-heading-lvl 1) ;; 用一级标题给截图文件命名
:config
(setq-default org-download-image-dir "./img")) ;; 用同级 ./img 目录放置截图文件WindowsImageMagick, 并保证 magick.exe 在 PATH 变量的路径中
用 msys2 安装 pacman -S mingw-w64-x86_64-imagemagickorg-download.el 文件, 置于你的 .emacs.d 文件夹合适的路径中 (如 ~/.emacs.d/lisp/)use-package 代码及设置 (use-package org-download
:ensure async ;; 因为不是从melpa安装, 需要手动保证async安装
:defer t ;; 延迟加载
:load-path "~/.emacs.d/lisp/"
:bind
(:map org-mode-map
("C-M-y" . org-download-clipboard)) ;; 绑定从剪贴版粘贴截图的快捷键
:custom
(org-download-heading-lvl 1) ;; 用一级标题给截图文件命名
:config
(setq-default org-download-image-dir "./img")) ;; 用同级 ./img 目录放置截图文件Emcas 中读取 Zotero 文献数据库并进行引用Zotero 文献建立一则 org-roam 笔记org-noter 笔记文件, 在 Emacs 中阅读 Zotero 文献的 pdf 附件ZoteroBetter BibTeX 导出文献数据至 bib 文件ZotFile 保存 PDF 文件 (一般是网盘文件夹)helm/ivy-bibtex:bib 文件的信息读入 Emacs, 并提取文献的标题, 作者, 引用键名等org-roam:
准备一个符合 org-noter 的笔记格式的 org-roam 模板org-roam-bibtex + org-roamorg-roam 笔记bibtex 条目等org-noter + pdf-tools
打开 org-roam 笔记中的 PDF 文件并阅读, 做读书笔记.org-roam 基本设置:【从零搭建Emacs个人知识库】什么是双链笔记与 org-roam 初体验
use-package 和插件管理方法:
【省时省力写LaTeX】新手Emacs快速配置与插件管理 ;; 第一步: 告诉 Emacs 从哪里读取 Zotero 的信息
(setq zot_bib '("~/Nutstore/1/Nutstore/Zotero-Library/Better BibTeX Export/My Library.bib"
"<另一个Zotero bib 文件>.bib") ; Zotero 用 Better BibTeX 导出的 .bib 文件. 可以是多个文件
zot_pdf "~/Nutstore/1/Nutstore/Zotero-Library" ; Zotero 的 ZotFile 同步文件夹
org_refs "~/repos/notes/ref/" ) ; 自定义的 org-roam 文献笔记目录. 我的 org-roam 根目录是 ~/repos/notes
;; 第二步: 让 helm-bibtex 读取 Zotero 的信息
(use-package helm-bibtex ; 这里也可以用 ivy-bibtex 替换 helm-bibtex
:ensure t
:custom
(bibtex-completion-notes-path org_refs)
(bibtex-completion-bibliography zot_bib)
(bibtex-completion-library-path zot_pdf))
;; 第三步: 让 org-roam-bibtex 使用 helm-bibtex 的信息, 并绑定 orb 的快捷键
(use-package org-roam-bibtex
:ensure t
:after org-roam
:hook (org-roam-mode . org-roam-bibtex-mode)
:bind (("C-c n k" . orb-insert-link)
("C-c n a" . orb-note-action))
:custom
(orb-insert-interface 'helm-bibtex) ; 与上面 helm-bibtex/ivy-bibtex 的选择保持一致
(orb-insert-link-description 'citekey) ; 默认是用标题, 但是论文的标题一般很长, 不适合作为笔记链接的名字
(orb-preformat-keywords
'("citekey" "title" "url" "author-or-editor" "keywords" "file"))
(orb-process-file-keyword t)
(orb-attached-file-extensions '("pdf")))第四步: 加入一个文献笔记的 org-roam 模板
(use-package org-roam
:ensure t ;; 自动安装
:custom
(org-roam-directory "~/repos/notes/") ;; 默认笔记目录, 提前手动创建好
(org-roam-dailies-directory "daily/") ;; 默认日记目录, 上一目录的相对路径
(org-roam-db-gc-threshold most-positive-fixnum) ;; 提高性能
:bind (("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
("C-c n l" . org-roam-buffer-toggle) ;; 显示后链窗口
("C-c n u" . org-roam-ui-mode)) ;; 浏览器中可视化
:bind-keymap
("C-c n d" . org-roam-dailies-map) ;; 日记菜单
:config
(require 'org-roam-dailies) ;; 启用日记功能
;;============= 新增内容 =================
;; 第四步: 用 org-roam 生成文献笔记, 放在 org-roam 的 use-package 代码块 :config 关键字之后
;; 下面的 (setq my/ref-template ...) 可以放到 use-package 代码块之外
(setq my/ref-template
(concat "#+FILETAGS: reading research \n"
"- tags :: %^{keywords} \n"
"* %^{title}\n"
":PROPERTIES:\n"
":Custom_ID: %^{citekey}\n"
":URL: %^{url}\n"
":AUTHOR: %^{author-or-editor}\n"
":NOTER_DOCUMENT: ~/Nutstore/1/Nutstore/Zotero-Library/%^{citekey}.pdf\n"
":NOTER_PAGE:\n"
":END:"))
(add-to-list 'org-roam-capture-templates
`("r" "Zotero 文献模板" plain ; 文献笔记模板
,my/ref-template
:target
(file+head "ref/${citekey}.org" "#+title: ${title}\n")))
;;============= 新增内容结束 =================
(org-roam-db-autosync-mode)) ;; 启动时自动同步数据库 (setq my/ref-template
(concat "#+FILETAGS: reading research \n"
"- tags :: %^{keywords} \n"
"* %^{title}\n"
":PROPERTIES:\n"
":Custom_ID: %^{citekey}\n"
":URL: %^{url}\n"
":AUTHOR: %^{author-or-editor}\n"
":NOTER_DOCUMENT: ~/Nutstore/1/Nutstore/Zotero-Library/%^{citekey}.pdf\n"
":NOTER_PAGE:\n"
":END:"))
(add-to-list 'org-roam-capture-templates
`("r" "Zotero 文献模板" plain ; 文献笔记模板
,my/ref-template
:target
(file+head "ref/${citekey}.org" "#+title: ${title}\n")))zot_pdf 一致org_refs 一致org-noter 识别的关键字, 不建议修改org-roam 笔记标签, 会显示在 C-c n f 搜索界面并可搜索. 以空格分隔. 可以根据自己需要设置在 Org-mode 中获得和 LaTeX 模式 一致 的 LaTeX 代码体验:
prettify\(...\), $...$\[...\], $$...$$, \begin{XXX}...\end{XXX}org-mode 的 LaTeX 编辑模式是采用 latex-mode) ;; 你自己的 LaTeX 模式设置
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(add-hook 'LaTeX-mode-hook 'my/latex-hook)
(add-hook 'latex-mode-hook 'my/latex-hook)Org-mode 有一个专属的 org-cdlatex-mode, 打开后可以使用 CDLaTeX 模式中定义的所有快捷键命令. 关于 CDLaTeX 可以参考
(add-hook 'org-mode-hook #'org-cdlatex-mode) ;; 在 org-mode 中使用 cdlatex主要区别:
org-mode 中的展开/折叠功能equ + Tab = \begin{equation}\end{equation}qq + Tab = \quad$, ( 等不再自动匹配. (setq org-highlight-latex-and-related '(native latex entities)) ;; LaTeX 语法高亮设置
(setq org-pretty-entities t) ;; LaTeX 代码的 prettify
(setq org-pretty-entities-include-sub-superscripts nil) ;; 不隐藏 LaTeX 的上下标更容易编辑org-pretty-entities 和 LaTeX 模式中 prettify-symbol-mode 共享变量 tex--prettify-symbols-alist 的设置tex--prettify-symbols-alist 可参考 【Emacs+LaTeX教程】如何优雅地预览数学公式$ 匹配问题其实也可以用 cdlatex-mode 替代 org-cdlatex-mode, 但是确实有一些副作用.
折衷的解决方法: 复写 cdlatex-mode 中的括号和 $ 匹配函数.
;; org-cdlatex-mode 中使用 cdlatex 的自动匹配括号, 并把 $...$ 换成 \( ... \)
(defun my/insert-inline-OCDL ()
(interactive)
(insert "\\(") ;; 把 "\\(" 和 "\\)" 替换成 "$" 就能实现输入成对 "$" 的功能.
(save-excursion (insert "\\)" )))
(defun my/insert-bra-OCDL ()
(interactive)
(insert "(")
(save-excursion (insert ")" )))
(defun my/insert-sq-bra-OCDL ()
(interactive)
(insert "[")
(save-excursion (insert "]" )))
(defun my/insert-curly-bra-OCDL ()
(interactive)
(insert "{")
(save-excursion (insert "}" )))
(define-key org-cdlatex-mode-map (kbd "$") 'my/insert-inline-OCDL)
(define-key org-cdlatex-mode-map (kbd "(") 'my/insert-bra-OCDL)
(define-key org-cdlatex-mode-map (kbd "[") 'my/insert-square-bra-OCDL)
(define-key org-cdlatex-mode-map (kbd "{") 'my/insert-curly-bra-OCDL)这里还做了一个优化: 把 $ 绑定成输入 \(?\), 原因有二:
$ 输入行内公式, 要求公式内紧临 $ 的字符不能是空格, 否则不能识别为数学环境. 识别失败又会导致语法高亮、 cdlatex-mode 不能触发等问题$ 输入行内公式, 后面必须是空格. 这和 LaTeX 模式下输入习惯不同.用 \(?\) 替代就没有以上所有问题.
基本命令
预览图片大小调整
(setq my/latex-preview-scale 2) ;; 一般来说这里的 scale 约等于 set-face-attribute 中的 :height /100
(setq org-format-latex-options
`(:foreground default :background default :scale ,my/latex-preview-scale :html-foreground "Black" :html-background "Transparent" :html-scale ,my/latex-preview-scale :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) ;; 增大公式预览的图片大小org-previeworg-preview 是一个非正式的包, 极大 提高 了数学公式预览速度 (异步编译, 有望加入未来版本的 Org).
;; 快速编译数学公式
(use-package org-preview
:load-path "lisp/" ; 需要手动从网盘或 https://github.com/karthink/org-preview/ 下载 org-preview.el 文件, 并置于 ~/.emacs.d/lisp/ 文件夹下
;; straight 用户用下一行取代上一行
;; :straight (:host github :repo "karthink/org-preview")
:hook (org-mode . org-preview-mode))org-fragtog (use-package org-fragtog
:hook (org-mode . org-fragtog-mode))Org-mode 如何用上自定义的 LaTeX 宏命令?
#+LATEX_HEADER: 关键字在 Org 文件开头加入 =
#+LATEX_HEADER: \newcommand{\R}{\mathbb{R}}
就可以在整个文件中使用 \mathbb{R}
#+SETUPFILE: 关键字可以创建一个叫 latex-preamble.org 放在 Org-roam 目录下, 然后给所有的笔记文件开头 (可以放在笔记模板里) 加上
#+SETUPFILE: ./latex-preamble.org
然后把所有要用的导言区命令每一行加上 #+LATEX_HEARDER: 放在 latex-preamble.org 文件中.
.sty 文件与 LaTeX 文件共享自定义命令~/texmf/tex/latex/ 目录下的 mysymbol.sty 文件中 ;; 在 ~/texmf/tex/latex/ 下的 .sty 文件
(setq org-latex-packages-alist '(("" "mysymbol" t)))原理:
~/texmf 是正常情况下 $TEXMF 的目录. 可以通过命令行 kpsewhich --var-value TEXMF 确认$TEXMF/tex/latex/ 目录下的 .sty 的文件可以被 \usepackage 引用.\usepackage{mysymbol} 命令; 而在 LaTeX 文件中也可以使用同样的命令.Org-mode 和 CDLaTeX 的强强联合
代码汇总
;; 你自己的 LaTeX 模式设置
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(add-hook 'LaTeX-mode-hook 'my/latex-hook)
(add-hook 'latex-mode-hook 'my/latex-hook)
(add-hook 'org-mode-hook #'org-cdlatex-mode) ;; 在 org-mode 中使用 cdlatex
(setq org-highlight-latex-and-related '(native latex entities)) ;; LaTeX 语法高亮设置
(setq org-pretty-entities t) ;; LaTeX 代码的 prettify
(setq org-pretty-entities-include-sub-superscripts nil) ;; 不隐藏 LaTeX 的上下标更容易编辑
;; org-cdlatex-mode 中使用 cdlatex 的自动匹配括号, 并把 $...$ 换成 \( ... \)
(defun my/insert-inline-OCDL ()
(interactive)
(insert "\\(") ;; 把 "\\(" 和 "\\)" 替换成 "$" 就能实现输入成对 "$" 的功能.
(save-excursion (insert "\\)" )))
(defun my/insert-bra-OCDL ()
(interactive)
(insert "(")
(save-excursion (insert ")" )))
(defun my/insert-sq-bra-OCDL ()
(interactive)
(insert "[")
(save-excursion (insert "]" )))
(defun my/insert-curly-bra-OCDL ()
(interactive)
(insert "{")
(save-excursion (insert "}" )))
(define-key org-cdlatex-mode-map (kbd "$") 'my/insert-inline-OCDL)
(define-key org-cdlatex-mode-map (kbd "(") 'my/insert-bra-OCDL)
(define-key org-cdlatex-mode-map (kbd "[") 'my/insert-square-bra-OCDL)
(define-key org-cdlatex-mode-map (kbd "{") 'my/insert-curly-bra-OCDL)
(setq my/latex-preview-scale 2) ;; 一般来说这里的 scale 约等于 set-face-attribute 中的 :height /100
(setq org-format-latex-options
`(:foreground default :background default :scale ,my/latex-preview-scale :html-foreground "Black" :html-background "Transparent" :html-scale ,my/latex-preview-scale :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) ;; 增大公式预览的图片大小
;; 快速编译数学公式
(use-package org-preview
:load-path "lisp/" ; 需要手动从网盘或 https://github.com/karthink/org-preview/ 下载 org-preview.el 文件, 并置于 ~/.emacs.d/lisp/ 文件夹下
;; straight 用户用下一行取代上一行
;; :straight (:host github :repo "karthink/org-preview")
:hook (org-mode . org-preview-mode))
(use-package org-fragtog
:hook (org-mode . org-fragtog-mode))
;; 在 ~/texmf/tex/latex/ 下的 .sty 文件
(setq org-latex-packages-alist '(("" "mysymbol" t)))Zotero 界面:
收藏夹 - 文献列表 - 文献信息.bib 或其它文件pdf 文件作为附件.Zotero 内置 pdf 阅读器打开 pdf 文件Zotero Connector 插件 (下载链接)Edge, Chrome, FireFox, Safaripdf 全文DOI, ISBN 或者 Arxiv ID 等pdf 文件创建. Zotero 会尝试获取文献信息为保证参考文献信息准确, 建议多使用前两种方法
手动添加 pdf 附件: 适用于非官方手段获取的 pdf 文件
合并文献信息: Duplicate Items
Zotero 核心功能
.bib 等多种格式引用文件pdf两个有用的插件
Better BibTeX:.bib 文件, 与 Org-roam, Obsidian, Roam Research 等笔记软件交互必备!Zotfile:pdf 文件pdf 文件至个人网盘同步.xpi 文件并下载Tools -> Add Ons 选择从文件进行安装ZoteroBetter BibTeX 设置设置界面在 Edit -> Preference -> Better BibTeX 下
bibtex 中的 alpha 风格; 单作者取姓的前 3 字母, 2 个以上取首字母keey citekey unique -> across all libraries.bib 文件自动导出与更新Automatic Export -> Automatic Export -> On changeZotFile 同步设置Zotero 登录后有 500M 的同步空间, 因此最好有第 3 方网盘同步 pdf 文件
Zotero 帐号负责同步文献信息ZotFlie 负责用网盘同步 pdf 文件Better BibTeX 的键名无法同步, 但是相同规则的键名是一样的.Better BibTeX, 再登录 Zotero 帐号进行同步.Zotfile 设置: Tools -> ZotFile Preference
General Settings -> Custom Locationspdf 文件重命名规则: Renaming Rulesbibtex 键名命名 pdfAdvance Settings -> Automatically rename new attachment -> always renameZotero 自动下载的 pdf 有效pdf, 右键点击并选择 rename and move 即可在 org-roam 笔记流程中整合 Zotero, 包括
Emcas 中读取 Zotero 文献数据库并进行引用Zotero 文献建立一则 org-roam 笔记org-noter 笔记文件, 在 Emacs 中阅读 Zotero 文献的 pdf 附件本小节将介绍如何快速配置一个用于 LaTeX 写作的 Emacs, 包括软件安装和插件管理, 以及 Emacs 的一些必要的入门知识. 最后将推荐两组非常实用的插件: 第一组插件 Which-key + Keycast + Helpful 将帮助我们快速熟悉 Emacs 的操作和概念, 第二组插件 Vertico + Marginalia + Orderless 将有效提升我们在小缓冲区的补全体验, 并附上 AucTeX 和 CDLaTeX 的基本设置.
Emacs 可以运行在 Windows, Linux, MacOS 上, 也可以通过 termux 运行在 Android 手机或平板上. 这里我们只介绍电脑系统上的 Emacs 安装.
在本文撰写时 (2023.4), Emacs 的最新正式版本为 28.2, 最近的测试版本为 29.090. 下面介绍的安装方法针对的是正式版. (更新: 2023.8 已经可以下载 Emacs 29 正式版.)
在多数平台上, 我们是利用合适的开源软件管理器来安装 Emacs. 在 Linux 中这是自带的, 在 Windows 和 MacOS 中大家需要自行安装. 我们下面详细说明.
Linux 系统中可以用自带的软件管理器安装 Emacs. 例如, 在 Ubuntu 中使用 apt 安装 Emacs, 只需要在命令行中输入
sudo apt install emacsMacOS 中需要先安装 Homebrew. 方法是在命令行中输入
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"当 Homebrew 安装成功后会有提示, 然后就可以使用 Homebrew 安装 Emacs 了: 在命令行中输入
brew install emacsWindows 下安装 Emacs 有两种常见方法. 第一种是安装 MSYS2 (下载链接). 安装后打开 C:/msys64/mingw64.exe (C:/msys64/ 是 MSYS2 的默认安装目录, 根据实际情况调整). 在命令行中输入
pacman -S mingw-w64-x86_64-emacs通过 MSYS2 安装的一个好处是我们可以通过 Pacman 管理 Emacs 的更新. 另一个好处是在上面还可以很方便安装其它开源软件, 例如 Git, Epdfinfo 等. Epdfinfo 是在 Windows 下使用 Emacs 的 PDF-tools 插件的必需软件 (BV1pg4y1s7Z9).
另一种安装方法是直接从官网上下载安装包. Emacs 28 的安装包已经优化了不少, 会自动把程序安装至 C:/Program Files/emacs 目录下, 并附带卸载程序. 通过安装包安装的 Emacs 需要我们手动更新.
安装完 Emacs 之后, 我 强烈建议 大家交换 Caps Lock 与 Left Ctrl. Emacs 常常使用以 Ctrl 开始的快捷键, 因此把 Ctrl 与不常用的大写锁定 Caps Lock 交换是每个 Emacs 使用者对电脑 做的第一件事. Ctrl 键的广泛使用是因为在 Emacs 诞生之初, 当时通用的键盘 Ctrl 确实在当今的 Caps Lock 位置上. 再啰嗦一句: 交换 Caps lock 与 Ctrl 绝不是一件可有可无的事情, 它在我们日常使用 Emacs 中真的非常重要! 大家千万不要怕麻烦.
交换 Ctrl 与 Caps Lock 的方法在不同系统上也不一样.
Windows 中更改键位可以通过注册表或者最新的 PowerToys 软件.
注册表方法 (适用于 Win 10 以前)
方法如下:
regedit 打开注册表[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]Scancode 文件, 把内容修改为 00 00 00 00 00 00 00 00
03 00 00 00 1d 00 3a 00
3a 00 1d 00 00 00 00 00Scancode 文件并重启电脑PowerToys (适用于 Win 10, Win 11)
PowerToys 并安装在 Ubuntu 下, 可以安装 Gnome-tweaks:
sudo apt install gnome-tweaks然后打开 Gnome-tweaks 的键盘设置, 在高级选项里有关于 Ctrl 键的设置. 你不仅仅可以交换它与 Caps Lock, 也可以进行许多别的设置.
又或者, 在很多 Linux 系统的命令行下输入
setxkbmap -option ctrl:swapcaps也可以交换 Ctrl 与 Caps Lock .
在 MacOS 中, 大家可以在 system -> keyboard -> functional keys 中调整所有功能键的键位.
剩下两个设置只有 Windows 用户需要进行.
第一是把 Emacs 的家目录, 即 Emacs 中通过 ~ 访问的目录, 改成 C:/Users/<用户名>/. 默认的家目录是 C:/Users/<用户名>/AppData/Roaming/. 从这个目录出发不方便我们访问像 “我的文档” 这种常用文件夹, 所以我们需要手动修改家目录为 C:/Users/<用户名>/, 与 Linux 和 MacOS 的使用习惯保持一致.
修改家目录的方法是在环境变量的设置中 (可以在 Windows 搜索栏中搜索 Edit system variables 打开), 增加一个用户的环境变量 HOME, 把它设置为 C:/Users/<用户名>/.
第二是保证你的 Emacs 安装目录在系统变量 PATH 上. 如果不在, 还是在同一个界面, 把包含你 emacs.exe 的文件夹路径手动添加到 PATH 变量中.
作为 Emacs 新手, 大家需要理解的一个核心概念就是命令. 在 Emacs 中所有的操作, 无论简单复杂都是命令. Emacs 这个单词就来自于 macro, 即宏命令. 比如说我们想执行打开一个文件的操作, 有 3 种方式等价的操作方式:
file -> visit new file, 然后和普通的软件一样选择你要打开的文件.open-file 命令. 方法是按下 M-x (M = Alt), 然后在最下面的小缓冲区输入 open-file, 然后输入文件名.Emacs 中有许多有用的命令. 你未来也可以自己通过 Elisp 语言编写自己命令. Emacs 把其中最常用的命令都绑定了快捷键, 用户自己也可以设置自己的快捷键. 当我们用熟了之后, 很多快捷键就会像打字一样形成肌肉记忆. 作为新手, 我们有很多键盘的快捷操作可以用鼠标代替, 因此你不必急于一下子掌握全部 Emacs 的快捷键.
但是, 仍有一些快捷键是大家最好尽快熟悉的. 下面这张表我给大家总结了新手必知的几个快捷键. 在表中, C 表示 Ctrl, M 表示 Alt. 这也是 Emacs 快捷键通用写法. 最右边一列是快捷键对应的命令名, 也就是第一列所有的快捷键都等价于 M-x 加上第三列.
| 快捷键 | 操作 | 命令名 |
|---|---|---|
| C-g | 中止当前一!切!命!令! | keyboard-quit |
| C-/ | 撤销命令 | undo |
| 文件操作 | ||
| C-x C-f | 打开文件 | find-file |
| C-x C-s | 保存文件 | save-buffer |
| C-x b | 切换文件 (缓冲区) | switch-to-buffer |
| C-x 1 | 关闭其它窗口 | delete-other-window |
| C-h f/v/k | 查询命令/变量/快捷键 | describe-function/variable/key |
| 文本处理 | ||
| M-x | 复制 | kill-ring-save |
| C-w | 剪切 | kill-region |
| C-y | 粘贴 | yank |
在 Emacs 中发生误操作时, 你需要知道如何中止与撤销命令. 当你的快捷键输入一半想反悔时 (是的, Emacs 的快捷键可以很长!), 可以使用 C-g 重新来输入, 又或者 Emacs 在执行命令时卡住了, 你可以通过 C-g 来让它恢复正常.
如果你需要撤回上一条命令, 则需要使用 C-/. 但值得注意的是, 撤回撤回命令的命令也是同一个键; 这偶尔会让人抓狂.
下面我们介绍 Emacs 中最基础的几个管理界面的快捷键.
首先是打开文件, C-x C-f, 命令名是 find-file. 这里的 find 隐含 Emacs 会根据不同情况执行不同操作: 若文件存在, 则是普通的打开文件; 若文件不存在, 则是打开一个新文件.
第二个是保存文件, C-x C-s, 对应 save-buffer, 即把当前缓冲区 (更新后) 的内容写进文件里.
大多数情况将缓冲区 (buffer) 等同于文件不会影响你的 Emacs 使用. 这里简单讲讲它们的不同. 文件存在于电脑硬盘上, 而 Emacs 的缓冲区只显示文件内容. 当你把文件内容读入缓冲区以后, 又在 Emacs 外修改了文件的内容, 缓冲区中的内容并不会改变, 除非你明确指示 Emacs 重新读取. 而在 Windows 中, 一个文件同时只能被一个 Windows 程序打开. Emacs 的缓冲区也不一定对应着文件, 在模式栏大家可以看到当前缓冲区的名字. 名字被两个 * 号包含的一般是非文件的缓冲区, 例如 *Message* 用于显示 Emacs 给用户的信息, 编译 LaTeX 时 *Output* 会存放编译输出结果等.
第三个命令是切换缓冲区/文件, C-x b, 对应 switch-to-buffer. 执行后在最下方的小缓冲区会提示输入你想要切换的缓冲区名字, 默认是上一个显示的缓冲区, 直接回车就行.
在 Emacs 中同时显示多个缓冲区的方法是打开多个窗口 (window), 然后在每个窗口中显示一个缓冲区. 有时 Emacs 自动创建新的窗口, 例如展示帮助信息时. 新手最常用的操作是保留当前光标所在窗口, 而关掉其它所有窗口. 这可以通过, C-x 1, 即 delete-other-window 实现. 我们可以用鼠标辅助我们在不同窗口间切换.
Emacs 中查询帮助信息的快捷键是 C-h <字母>. 常用的有 C-h f, 查询命令, C-h v, 查询变量, 以及 C-h k, 查询快捷键. 通常 C-h 命令会自动创建新的窗口显示帮助信息. 我们可以先把光标移到我们工作的缓冲区, 然后用 C-x 1 关闭掉帮助信息窗口. 注意此时帮助信息的缓冲区并没有关闭, 重新显示可以通过 C-x b 并查找以 *help* 命名的缓冲区.
Emacs 有自己一套复制/剪切/粘贴的快捷键: M-w / C-w / C-y. 这和一般程序的 C-c / C-x / C-v 不同, 需要大家习惯. 所有复制或剪切的内容都会进入一个叫 kill-ring 的地方, 它相当于一个剪粘版的历史记录. 粘贴快捷键 C-y 会粘贴最近一条记录, 如果你想访问之前的记录, 可以紧跟着 C-y 再按下一次或多次 M-y.
接下来我们介绍如何更好地管理 Emacs 插件. Emacs 插件也叫 Emacs 包 (package). 插件可以给我们带来更多的功能, 是 Emacs 使用中不可缺少的一环. 插件的安装和设置与其它的 Emacs 设置一样, 都放在 Emacs 的启动文件 ~/.emacs.d/init.el 中. 关于插件安装与设置, 我推荐大家使用现在常用的 use-package 语法, 它的语法更简洁, 还可以很方便地自动安装插件.
Emacs 中下载新的插件可以通过不同的方式 (这也是由某些插件提供的). 常用的有两种, 一种是用内置的 package.el, 这个插件名字就叫 package.el, .el 后缀来自于 Emacs 的编程语言 Elisp.
第二种是用 Straight. package.el 会从官方的插件库 (ELPA, MELPA) 或镜像网站上下载新插件, 而 Straight 用下载插件的源代码并编译, 一般是利用 Git 从 Github 上下载. 为了使用 Straight, 你需要系统上已经安装了 Git 程序, 并且能正常地访问 github.com. 以下我们介绍两种安装方式如何设置.
我们在 package.el 和 Straight 的设置示例中都手动检查并安装了 use-package. Emacs 29 后 use-package 已经是内置插件, 相关代码可以省去.
package.el 设置示例以下我们提供了 package.el 的一个设置示例. 大家需要把如下代码放入设置文件 ./.emacs.d/init.el 中.
;; -*- lexical-binding: t; -*-
;; 静态作用域声明必须放在首行
;; 把 Emacs 自动添加的代码放到 custom.el 中
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
;;========================================
;; 使用 package.el 设置 Emacs 插件管理
;;========================================
(require 'package) ; 加载 package.el
(setq package-check-signature nil) ; 如果检查签名有问题可以加入这一行
;; 添加仓库位置
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
;; 国内用户也可以使用清华的镜像网站. 用下面的代码代替上面两行
;; (setq package-archives
;; '(("gnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")
;; ("nongnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/nongnu/")
;; ("melpa-stable" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/stable-melpa/")
;; ("melpa" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")))
;; 刷新插件列表
(unless package-archive-contents
(package-refresh-contents))
;; 自动安装 use-package. 在Emacs 29中已内置故可省略
(unless (package-installed-p 'use-package)
(package-install 'use-package))
;; 自动安装所有使用 use-package 声明的插件
(require 'use-package-ensure)
(setq use-package-always-ensure t)
;;========================================
;; Emacs 插件管理设置完毕
;;========================================
;;========================================
;; 这段代码放在最后, 加载 Emacs 自动设置的变量
(if (file-exists-p custom-file) (load-file custom-file))
;;========================================这段代码的第一部分启用了 package.el, 然后通过 package-archives 变量设置了下载插件的网址. 在国内也可以使用清华的软件源. 接下来 package-refresh-contents 刷新了插件列表. 然后我们自动检测 use-package 是否安装, 如果没有安装则自动下载安装. 最后, 我们设置了 use-package-always-ensure 变量为 t, 这样以后我们所有用 use-package 声明的插件都会自动安装.
straight.el 设置示例straight 需要用 git 从 github 等网站上下载源码. 请再三确认 git 在系统路径上 (尤其是用 msys2 安装的 Windows 用户).
因为 straight.el 与 package.el 难以共存, 所以我们必须早早手动禁用内置的 package.el. 这必须修改一个我们平时很少用的文件 .emacs.d/early-init.el. 我们需要在 early-init.el 中加入
;; 在执行 init.el 前禁用 package.el
(setq package-enable-at-startup nil)接下来, 我们需要在 init.el 中加入以下代码:
;; -*- lexical-binding: t; -*-
;;========================================
;; 把 Emacs 自动添加的代码放到 custom.el 中
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
;; 使用 straight.el 设置 Emacs 插件管理
;;========================================
(defvar bootstrap-version)
;; 修复 Emacs 29 修改了 native-compile 相关变量导致的 bug
(unless (version<= emacs-version "28.2")
(setq straight-repository-branch "develop"))
;; 以下代码从 straight.el 主页 https://github.com/radian-software/straight.el 上复制
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package) ; 用 straight.el 安装 use-package 声明的插件
(setq straight-use-package-by-default t) ; 自动安装所有插件, 相当于加入 :straight t
;;========================================
;; Emacs 插件管理设置完毕
;;========================================
;;========================================
;; 这段代码放在最后, 加载 Emacs 自动设置的变量
(if (file-exists-p custom-file) (load-file custom-file))
;;========================================这里大部分的代码是 straight.el 的 Github主页上提供的下载与安装 straight 的代码, 然后再用 straight 安装 use-package. 最后我用把 straight-use-package-by-default 变量设为 t, 这是在使用 straight 时进行插件自动安装的设置.
下面我给大家推荐两组非常实用的插件. 在进行好 package.el 或者 straight.el 的设置后 (注意: 不能同时使用), 安装与设置插件只需要把相关的 use-package 代码块复制到 init.el 即可. 而且在两个体系下的代码块基本是通用的.
我们之前也都设置了自动安装插件. 当你第一次执行 init.el 时 (通常是第一次重启 Emacs 的时候), Emacs 会自动检测你在 init.el 中声明的插件是否已经安装, 若没有则通过指定的方法 (package.el 或 straight.el) 自动下载安装. 如果大家在一台新的机器上使用 Emacs, 把 init.el 文件复制到新机器上就可以直接获得一模一样的使用体验!
你也可以在修改完 init.el 后, 执行 M-x eval-buffer 命令手动加载新加的 use-package 代码块.
在复制代码块中最常见的问题是某个地方在复制的过程中漏了括号. 大家已经发现 elisp 语言中括号是必须配对的. 我们可以在修改 init.el 后手动的用 M-x match-paren 检查括号是否匹配. 如果有不匹配的括号, 那么光标就会跳过没有匹配成功的括号上, 否则这个命令不会用任何效果.
我们首先介绍 Which-key + Keycast + Helpful. 安装代码如下
(use-package which-key
:custom (which-key-idle-delay 0.5) ; 延迟时间, 以秒为单位
:config (which-key-mode)) ; 启用 which-key 模式
(use-package keycast
:config (keycast-header-line-mode 1)) ; 在标题显示
(use-package helpful
:bind
;; 重新定向 C-h 开始的命令
(([remap describe-function] . #'helpful-callable)
([remap describe-variable] . #'helpful-variable)
([remap describe-key] . #'helpful-key)
([remap describe-command] . #'helpful-command)
([remap describe-symbol] . #'helpful-symbol)
("C-h C-d" . #'helpful-at-point)
("C-h F" . #'helpful-function)))which-key 可以在按下快捷键的时候自动提示你接下来可能的快捷键. 比如按下 C-h, 就会提示接下来你按 v, f, k 等可以查看哪种类型的帮助. 如果把鼠标悬停在选项上也会在浮窗中显示对应命令的帮助.
keycast 则会显示当前你使用的快捷键及对应的命令名. 它有 4 种显示的位置. 代码中我们选择在 headrer-line , 也就是 Emacs 窗口的最上方显示. 如果大家想在别的地方显示, 比如模式栏, 可以把 (keycast-header-line-mode 1) 改成 (keycast-mode-line-mode 1).
这两个插件可以帮助新手快速熟悉 Emacs 的快捷键和命令. 对于老用户来说, 也可以帮你快速熟悉新安装的插件. 我自己平时也是常开的.
helpful 则优化了帮助界面的信息显示, 包括更多有用的信息和高亮.
在 Emacs 中输入命令或打开文件, 切换缓冲区等等都会用到小缓冲区补全. 第二组插件 Vertico + Marginalia + Orderless 是针对小缓冲区补全的. 代码如下
(use-package vertico ; 竖式展开小缓冲区
:custom (verticle-cycle t)
:config (vertico-mode))
(use-package marginalia ; 更多信息
:config (marginalia-mode))
(use-package orderless ; 乱序补全
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles partial-completion)))))vertico 把每个补全选项放在单独的一行, 配合 marginalia 会在每个选项的右边加入更多相关信息.
在小缓冲区中输入时, 我们可以按 Tab 补全当前的输入. 加入 vertico 之后, 我们可以用 C-n 和 C-p 或者上下移动键来选择不同的补全选项. C-n 和 C-p 也是 Emacs 中上下移动光标的快捷键.
最后的 orderless 允许我们在小缓冲区补全时忽略单词的顺序. 例如, 如果我们输入 M-x, 想要匹配 find-file 命令, 在默认情况下必须先输入 find, 再输入 file 才能找到 find-file. 如果你用了 orderless, 则可以通过 file find 找到, 或者部分的单词 fil fin + Tab= 找到.
CDLaTeX + AucTeX 设置最后我们提供一个简单可用的 CDLaTeX 和 AucTeX 设置. 大家只要把这段代码复制进 init.el 就可以实现视频五分钟说服你用Emacs写LaTeX中的大部分功能.
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(use-package cdlatex
:load-path "lisp/" ; 需要手动从网盘或 https://github.com/cdominik/cdlatex/blob/master/cdlatex.el 下载 cdlatex.el 文件, 并置于 ~/.emacs.d/lisp/ 文件夹下
;; 若使用 straight, 注释前一行, 并取消下一行注释:
;; :straight (:host github :repo "cdominik/cdlatex" )
)
(use-package tex
:ensure auctex
;; 若使用 straight, 注释前一行, 并取消下一行注释:
;; :straight auctex
:custom
(TeX-parse-self t) ; 自动解析 tex 文件
(TeX-PDF-mode t)
(TeX-DVI-via-PDFTeX t)
:config
(setq-default TeX-master t) ; 默认询问主文件
(add-hook 'LaTeX-mode-hook 'my-latex-hook)) ; 加载LaTeX模式设置这个基本设置不一定能实现 PDF 正向或反向搜索, 因为这取决于操作系统与 PDF 阅读器. 如果你想在不同平台上使用 Emacs 并获得统一的 PDF 体验, 可以考虑使用 PDF-tools (见视频 BV1pg4y1s7Z9).
关于 CDLaTeX 的安装, 要注意的是, 它并不在任何的软件源时. 如果使用 package.el, 你需要手动下载这个文件 (Github链接 或者我网盘里的备份), 并用 :load-path 关键字指定文件的目录. 如果是 Straight, 则需要我们指定 Github 仓库的地址 cdominik/cdlatex.
AucTeX 是通过 (use-package tex) 激活的. 因为包名不统一的问题, 我们要额外加入 :ensure auctex 或 :straight auctex. 其实 Emacs 已经内置了 AucTeX, 但不一定是最新版本, 我们这里的 use-package 则会把它更新到最新版.
大家好, 我是小米, 欢迎大家来到我的省时省力写 LaTeX 系列. 本期我们开始介绍 Emacs 的 CDLaTeX 插件. 这次讲解如何使用 CDLaTeX 快速插入数学字母, 符号和字体的功能, 以及如何自定义新的快捷键.
Emacs 中的 LaTeX 编辑主要是依赖 AucTeX 和 CDLaTeX 这两个插件. AucTeX 提供了编辑 LaTeX 的基本功能, 而 CDLaTeX 主要提供了大量简化和易设置的输入方式. 为了安装并在 LaTeX 编辑时启用这两个插件, 我们需要在 init.el 中加入代码:
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(use-package tex
:ensure auctex
;; 若使用 straight, 注释前一行, 并取消下一行注释:
;; :straight auctex
:custom
(TeX-parse-self t) ; 自动解析 tex 文件
(TeX-PDF-mode t)
(TeX-DVI-via-PDFTeX t)
:config
(setq-default TeX-master t) ; 默认询问主文件
(add-hook 'LaTeX-mode-hook 'my/latex-hook)) ; 加载LaTeX模式钩子
(use-package cdlatex
:after tex ; 保证 cdlatex 在 auctex 之后加载
:load-path "lisp/" ; 需要手动从网盘或 https://github.com/cdominik/cdlatex/blob/master/cdlatex.el 下载 cdlatex.el 文件, 并置于 ~/.emacs.d/lisp/ 文件夹下
;; 若使用 straight, 注释前一行, 并取消下一行注释:
;; :straight (:host github :repo "cdominik/cdlatex" )
)使用 straight.el 的用户需要根据注释内容适当调整. 在 (use-package cdlatex ...) 中我们指定了 :after tex, 是为了保证 cdlateX 在 auctex 之后加载. 把 cdlatex 的 use-package 代码块置于 auctex 之后也实现了相同效果; 而加了这一行后, 代码块次序可以随意调整.
LaTeX-mode-hook 是我们打开 LaTeX 文件时需要加载的设置, 这里我们定义了一个新的函数 my/latex-hook (名字可随意), 这样方便我们日后加入更多的功能. 函数的第一行 (turn-on-cdlatex) 就是打开 tex 文件时加载 cdlatex-mode 的命令.
成功设置后, 当我们打开 tex 文件时, 大家应当可以看到模式栏中的 LaTeX/P 和 CDL, 就表示加载了 aucteX 和 cdlatex. 通过 C-h m (m 表示 mode) 可以查看当前加载的所有主要模式和次要模式.
这里的数学符号也包括各种非拉丁字母如 \alpha, \aleph 等. 输入方法是用反引号 (Tab 上方) 加另一个键组成的快捷键输入.
希腊字母可以用 ` + 对应拉丁字母插入, 包括大小写. 例如
\alpha\beta\gamma\Gamma\Sigma如果你不熟悉希腊字母对应的拉丁字母, 没有关系, 只要在按下 ` 后稍稍停顿, 就会弹出一个提示界面. 大家刚开始使用时可以多查看这个提示界面.
大家在提示界面可以看到, 除了希腊字母以外, 我们还可以用同样的方法快速插入数学符号. CDLaTeX 预置了很多好记的默认设置. 例如, ` + 8 插入 \infty, 因为数字 8 放平就是无穷, 又如, ` + * 插入 \times 乘号, ` + + 插入 \cup (并集), ` + > 插入 \rightarrow (右箭头) 等.
CDLaTeX 中连续按下两次反引号 ` 可以打开第二层目录. 第二层通常用于希腊字母的变体, 如
\epsilon, ``e 插入 \varepsilon\rho, ``r 插入 \varrho又或者是一些类似的符号, 如
\rightarrow, ``> 插入 \longrightarrow或者是多个符号最直观的快捷键相同, 但是频率最高的放在第一层, 频率低的放在第二层, 如
\delta, ``d 插入 \partial (求偏导符号)这个目录还有第 3 层, 这里绑定的快捷键就更少了. 默认的是一些数学函数的符号, 如 \sin, \exp 等
``反引号在 LaTeX 中写作几乎不会用到, 除了用于左双引号 `` (laTeX 的右双引号是 '' ). 这很好解决: 在 AucTeX 默认设置下, 第一个输入的双引号 " 会自动转换成为 `` 插入, 第二个输入的双引号 " 会转换为 '' . 例如, “word” 将插入 ``word''.
当然, 你也可以把反引号修改成其它的键, 但是既然无须担心双引号输入的问题, 我觉得改的意义不大. 反引号已经是很好的选择.
Emacs 的最大优势就是我们可以自由地设置. 前面反引号 ` 触发的快捷输入, 我们也可以添加自己需要的符号或调整已有的设置.
这里的所有设置保存在一个叫 cdlatex-math-symbol-alist 的变量中. 我们接下来讲解在 Emacs 如何设置一个变量, 保存设置以及加载设置. 这对其它的变量也是一样.
虽然所有的变量设置都可以通过 init.el 里面的 (setq ...) 语句完成, 对于 cdlatex-math-symbol-alist 这种结构非常复杂的变量, 新手还是建议用 Emacs 自带的设置界面.
打开一个变量的设置界面主要有两种方式 (以 cdlatex-math-symbol-alist 为例)
customize-variable 命令:
M-x customize-variable RET M-x cdlatex-math-symbol-alistcdlatex-math-symbol-alist 并点击 customize我们想调换 `e 和 ``e 原本的快捷键设置, 即实现如下效果: `e 插入 \varepsilon, ``e 插入 \epsilon. (这么做的原因是 \varepsilon 更常用).
cdlatex-math-symbol-alist 的设置界面character 后输入 eRepeat 后按 INS, 新插入的一行输入 \varepsilonRepeat 后按 INS, 新插入的一行输入 \epsilon这就完成了基本设置. 如果大家想绑定 ```e 和 ````e 等, 只需要再加入新的行以及你需要的 LaTeX 宏命令即可.
这里因为 `e 已经在 CDLaTeX 的默认设置中, 所以我们是覆盖了原有设置. 你可以在一开始的按下 ` 的提示界面中看到默认设置, 或者通过查看变量 cdlatex-math-symbol-alist-default.
设置完毕我们会点击 Apply and Save.
Apply: 改变了当前 cdlatex-math-symbol-alist 的値, 重启 Emacs 后失效Save: 保存设置, 重启后仍生效.但是已经打开的 tex 文件是看不到更新的设置的. 想要重新加载 CDLaTeX 的设置. 这有 3 种方法:
tex 文件.tex 文件缓冲区, 按下 C-c C-n.第三种方法可以刷新 LaTeX 模式设置, 也适用于其它与 cdlatex 的设置. 此时, 大家按下反引号 ` 就可以看到更新后的列表了.
原则上这个机制可以插入任意的数学表达式, 如 \stackrel{\mathrm{a.s.}}{=}=, 但是建议只绑定原子化的数学符号. 复杂的表达式更适合用 CDLaTeX 的命令补全功能. (参考 Tab 补全快速插入LaTeX代码)
快捷键要易记, 直观, 凭你的第一感觉就能找到. 否则不能提高输入速度. 大家也可以查看默认的设置寻找灵感. 反例就是把左箭头 \leftarrow 绑到 `> 上.
如果一个键上绑定了多层快捷键, 要考虑不同命令使用的频率, 把最常用的放在第一层, 次常用的放在第二层, 依此类推. 像上面的 \epsilon 和 \varepsilon 的例子.
你也可以绑定自己定义的宏命令. 例如, 我的 `e 绑定的是 \eps, 而在我的 LaTeX 文档引言区中会定义 \newcommand{\eps}{\varepsilon}. 这样的好处可以提高代码的可读性, 方便交流. 毕竟你的导师, 你的合作者未必用 Emacs, 长长的 \varepsilon 会让人眼花. 但是我输入时想到的是希腊字母 epsilon 就应该用 `e 输入.
这里有很大的发挥空间, 因为第二层和第三层基本都是空的, 每个键还分大小写, 可以自由设置 100 多个快捷键. 所以尽情发挥吧.
CDLaTeX 还可以快速插入不同的数学字体, 像 \mathrm{}, \mathbf{} 等等.
例如, 我们常常用粗体 R 表示实数域, 也就是 \mathbf{R}. 我们可以按 3 个键完成输入: R + ' + b
\mathbf{}按单引号 ' 默认会改变前一个字母的字体, 也包括希腊字母, 但只是前面一个字母. 例:
\mathbf{\alpha}a\mathbf{b}.如果需要改变多个字母的字体可以先选择字体, 再输入文本. 这就是第二种方法. 但是输入单引号时前面要是空格或者 $, { 这种功能性字符. 例:
可以用于改变多个字符的字体.
这种插入方式也可以推广到一切 LaTeX 宏命令 + 一对花括号内一段文本的结构. 除了像 \mathbf{}, \mathrm{} 这种数学字体, 还可以输入
数学公式中对字母的其它修饰, 如
\vec{}\hat{}\bar{}这里默认的快捷捷非常直观, 大家也可以按下单引号 ' 稍等以查看提示界面.
非数学公式中的文本字体, 如
\textbf{}\textit{}这里同样的 'b, 用在数学公式内就是 \mathbf{}, 用在文本中就是 \textbf{}. CDLaTeX 会自动检测当前环境是否为数学环境.
触发字体修饰的第三种方法是选先高亮选中一段文本, 再选择修饰. 例如, 选中数学环境外的 blabla, 然后按 ‘b, 则 blabla 会变成 \textbf{blabla}. 如果 blabla 在数学环境内, 则变成 \mathbf{blabla}
第一种方法只能修饰一个字母, 所以嵌套修饰只能使用第二种或第三种方法. 例:
\bar{\mathbf{R}}.\mathbf{R}, 然后高亮选中按下 '-, 变成 \bar{\mathbf{R}}这里需要设置的变量是 cdlatex-math-modify-alist. 打开设置界面的方法和前面一样, 输入
M-x customize-variable RET cdlatex-math-modify-alist
现在我们举一个例子. 假设我们想用 't 在数学公式中插入空心粗体 \mathbb{}. 操作如下
cdlatex-math-modify-alist 设置界面character 输入 t\mathbb\text, 这是 CDLaTeX 的默认设置.Type 改成 command. 两种方式几乎等价但是 command 现在更常用.我们修改完之后, 按 Apply and Save 保存, 然后在 tex 文件缓冲区中用 C-c C-n 刷新设置, 这样我们在数学环境中按下 ' 就能插入空心粗体 \mathbb{} 了.
customize-variable 设置保存位置我们的 init.el 设置里面有这样两行:
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
;; .....
;; .....
(if (file-exists-p custom-file) (load-file custom-file))这样 Emacs 会把通过 customize-variable 设置的变量保存在我们自定义的 custom.el 的文件中. 内容大概像这样:
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(cdlatex-math-modify-alist '((116 "\\mathbb" "" t nil nil)))
'(cdlatex-math-symbol-alist '((101 ("\\varepsilon" "\\epsilon")))))
;; ......这里包含了我们前面对 cdlatex-math-modify-alist 和 cdlatex-math-symbol-alist 的设置.
如果没有特别的设置, customize-variable 设置的变量默认会由 Emacs 保存到 init.el 文件的最后. 我们的设置可以区分自己的设置和 Emacs 保存的设置.
当然, 你也可以手动把 custom-set-variables 中的内容用 (setq ...) 语句写在你的 init.el 当中, 尤其可以放在相应插件的 use-package 代码块中. 这样的好处是方便单独管理每个插件的设置, 并且利用 use-package 的延迟加载功能加快打开 Emacs 的时间. 当我们的 CDLaTeX 设置很长的时候, 这样做可以把 Emacs 的启动时间从 10 多秒减少到 1 秒以下. 大家可以在熟悉了 Emacs 的设置后再做尝试, 新手不推荐这么做.
Emacs 中的 CDLaTeX 插件利用反引号 ` 和单引号 ' 开始的快捷键可以快速插入数学字母, 符号和字体. 我们可以通过设置 cdlatex-math-symbol-alist 和 cdlatex-math-modify-alist 这两个变量修改和增加自己喜欢的快捷键.
在下期视频中我们将介绍 CDLaTeX 中 Tab 的命令/模板补全功能. 它可以帮助我们输入一些更复杂的宏命令, 或者插入环境模板等等.
大家好, 我是小米. 本期我们将介绍如何在 CDLaTeX 中用 Tab 补全命令快速地输入复杂的宏命令和环境模板.
补全原理很简单, 用几个字母组合加 Tab 生成一些复杂的命令. 例如, fr + Tab 就会生成 \frac{}{}, 这里光标会停留在第一个括号内; 在第一个括号内完成输入后, 按 Tab 光标就会跳到下一个括号中. 因此, 输入一个常见的分数 \frac{1}{2} 只需要输入 f + r + Tab + 1 + Tab + 2.
CDLaTeX 内置了一些可补全的命令, 可以在 cdlatex-command-alist-default 变量中查看 (C-h v). 我们举一些例子 (以下 ? 所在位置表示补全后光标停留的位置.)
fr + Tab = \frac{?}{}, 根号 sq + Tab = \sqrt{?}qq + Tab = \quad, 大空格 qqq + Tab = \qquadlr( + Tab = \left(?\right), lr[ = \left[?\right]sn + Tab = \section{?}, ss + Tab = \subsection{?}, sss + Tab = \subsubsubsection{?}te + Tab = \text{}se + Tab = \{ \} (set)st + Tab = \stackover{}{}hl + Tab = \hline, hhl + Tab = \\ \hline (表格中常用)big( + Tab = \big(?\big), Big( + Tab = \Big(?\Big), bigg( + Tab = \bigg(?\bigg) (\big, \Big, \bigg 等是 amsmath 中调整括号大小的命令)lr< + Tab = \langle?\rangle, 一对尖括号 \(\langle \rangle\).显然, 这里的关键字选择都是用命令中最开始的两到三个字母, 这样非常好记, 也很容易使用.
大家可以看到这里的 Tab 补全其实就是一个替换字符串的过程. 当然字符串中也可以包括换行, 因此同样的机制也可以输入形如 \begin{XXX} ... \end{XXX} 的环境.
equation 环境equ + Tab 插入如下模板:
其中, \label{eq:XXX} 是 CDLaTeX 调用 reftex 自动生成的数字标签.
类似的数学公式环境还有如
ali + Tab 插入 align 环境 (自动生成标签), ali* + Tab 插入 align* 环境 (无标签)gat + Tab 插入 gather 环境 (自动生成标签), gat* + Tab 插入 gather* 环境 (无标签)enu + Tab 插入
此时, 在 enumerate 环境中:
it + Tab = \item\item这里, enu + Tab 等同于用 cdlatex-environment (C-c { ) 插入 enumerate 环境
类似的还有
ite + Tab 插入 itemize 环境fg + Tab 插入 figure 环境现在我们介绍如何自定义你自己需要的补全命令. 默认的补全命令都在 cdlatex-command-alist-default 中, 而现有的所有命令, 包括内置的和自定义的, 都可以通过 C-c ? 查看.
在用 C-c ? 查看时, 我们会在最右一列看到 TEXT 和 MATH 关键字:
MATH 关键字表示补全可以在 数学环境 中触发TEXT 关键字表示补全可以在 文本环境 中触发加入自定义新的补全命令通过修改变量 cdlatex-command-alist. 方法是调用 M-x customize-variable =, 然后输入变量名 =cdlatex-command-alist.
例子: te + Tab 输入 \text{?} (光标停在括号内). 我们需要填入如下参数
teinsert \text{}\text{?} (? 表示光标停留的位置)cdlatex-position-cursor (如果需要指定光标则必填!)nil (这是上面 hook 的参数)nil, Math mode: t保存设置 (Apply and Save) 之后, 在已经打开的 tex 文件中用 C-c C-n 可以刷新设置, 就可以开始使用了.
例子: big{ + Tab 插入 \big\{? \big\}
big{insert \big\{? \big\}\big\{? \big\cdlatex-position-cursornilnil, Math mode: t这里有两个细节. 第一是我们在 ? 后面手动多加了一个空格, 这里因为在 LaTeX 编辑模式下, 按 Tab 会自动跳到一个空格位置, 因此我们尽量用空格把代码分隔开来, 便于以后的修改; 既然如此, 我们干脆在模板中加入这个空格.
第二个细节时我们的替换字符串最后少了一个 }. 这是因为 CDLaTeX 中默认会自动匹配输入一对括号 {}. 因此我们只需要补全除了右花括号 } 以外的部分就可以.
CDLaTeX 中自动匹配的括号可以通过 cdlatex-paired-parens 设置, 只针对 $([{<| 6 个字符. 我一般会自动匹配
$([{ . 这里大家只需要注意你在 cdlatex-command-alist 中的设置与 cdlatex-paired-parens 保持一致就可以了.
例子: case + Tab 插入
caseinsert \begin{cases} \end{cases}cdlatex-position-cursornilnil, Math mode: t插入环境除了直接在 cdlatex-command-alist 的 Replacement 中写入环境模板以外, 还可以通过调用函数 cdlatex-environment 的方式实现.
在 LaTeX 编辑模式中, 有两种用环境名插入环境的方法
LaTeX-environment (C-c C-e) + description: 这会调用 AucTeX 的环境模板cdlatex-environment (C-c { ) + description: 这会调用 CDLaTeX 的环境模板.两种模板略有不同. 这第二种插入环境的方法就是用 Tab 补全触发第二个命令.
例子: des + Tab 插入 description 环境
desinsert \begin{description} \end{description}nilcdlatex-environment("description")t, Math mode: nil这里需要注意的是我们用了一个不同的 hook! 所插入的模板是由 cdlatex-env-alist, cdlatex-env-alist-default 控制的.
使用这种方式插入环境的好处:
AUTOLABEL 关键字 (equ + Tab 生成带标签的环境的实现方式)item 模板 (C-<enter> 触发)不过, 在一般情况下, 第一种方法直接把环境模板写进 cdlatex-command-alist 也能实现大部分的功能了.
我的 cdlatex-command-alist 变量, 仅做抛砖引玉之用.
(setq cdlatex-command-alist
'(("eq" "insert pairs of \\[ \\]" "\\[ ? \\]" cdlatex-position-cursor nil t t)
("Big(" "insert Big ()" "\\Big( ? \\Big" cdlatex-position-cursor nil nil t)
("Big[" "insert Big[" "\\Big[ ? \\Big" cdlatex-position-cursor nil nil t)
("Big\\|" "insert Big \\|" "\\Big\\| ? \\Big\\|" cdlatex-position-cursor nil nil t)
("Big{" "insert Big{}" "\\Big\\{ ? \\Big\\" cdlatex-position-cursor nil nil t)
("Big|" "insert Big|" "\\Big| ? \\Big|" cdlatex-position-cursor nil nil t)
("aali" "insert equation" "\\left\\{\\begin{aligned}\n? \n\\end{aligned}\\right." cdlatex-position-cursor nil nil t)
("alb" "Insert beamer alert block with overlay" "\\begin{alertblock}<+->{ ? } \n\n\\end{alertblock}" cdlatex-position-cursor nil t nil)
("alb*" "Insert beamer alert block without overlay" "\\begin{alertblock}{ ? } \n\n\\end{alertblock}" cdlatex-position-cursor nil t nil)
("big(" "insert big ()" "\\big( ? \\big" cdlatex-position-cursor nil nil t)
("big[" "insert big []" "\\big[ ? \\big" cdlatex-position-cursor nil nil t)
("big\\|" "insert big \\|" "\\big\\| ? \\big\\|" cdlatex-position-cursor nil nil t)
("bigg(" "insert bigg()" "\\bigg( ? \\bigg" cdlatex-position-cursor nil nil t)
("bigg[" "insert bigg[" "\\bigg[ ? \\bigg" cdlatex-position-cursor nil nil t)
("bigg\\|" "insert bigg\\|" "\\bigg\\| ? \\bigg\\|" cdlatex-position-cursor nil nil t)
("bigg{" "insert bigg{}" "\\bigg\\{ ? \\bigg\\" cdlatex-position-cursor nil nil t)
("bigg|" "insert bigg|" "\\bigg| ? \\bigg|" cdlatex-position-cursor nil nil t)
("big{" "insert big {}" "\\big\\{ ? \\big\\" cdlatex-position-cursor nil nil t)
("big|" "insert big|" "\\big| ? \\big|" cdlatex-position-cursor nil nil t)
("blo" "Insert beamer block with overlay" "\\begin{block}<+->{ ? } \n\n\\end{block}" cdlatex-position-cursor nil t nil)
("blo*" "Insert beamer block WITHOUT overlay" "\\begin{block}{ ? } \n\n\\end{block}" cdlatex-position-cursor nil t nil)
("bn" "binomial" "\\binom{?}{}" cdlatex-position-cursor nil nil t)
("capl" "insert \\bigcap\\limits_{}^{}" "\\bigcap\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("case" "insert cases" "\\begin{cases}\n? & \\\\\n &\n\\end{cases}" cdlatex-position-cursor nil nil t)
("cd" "insert cdots" "\\cdots" nil nil t t)
("cupl" "insert \\bigcup\\limits_{}^{}" "\\bigcup\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("dd" "insert ddots" "\\ddots" nil nil t t)
("def" "insert definition env" "" cdlatex-environment ("definition") t nil)
("des" "insert description" "" cdlatex-environment ("description") t nil)
("enu*" "insert enu" "\\begin{enumerate}\n\\item ?\n\\end{enumerate}" cdlatex-position-cursor nil t nil)
("equ*" "insert unlabel equation" "" cdlatex-environment ("equation*") t nil)
("exb" "Insert beamer example block with overlay" "\\begin{exampleblock}<+->{ ? } \n\n\\end{exampleblock}" cdlatex-position-cursor nil t nil)
("exb*" "Insert beamer example block without overlay" "\\begin{exampleblock}{ ? } \n\n\\end{exampleblock}" cdlatex-position-cursor nil t nil)
("exe" "Insert exercise" "\\begin{exercise}\n? \n\\end{exercise}" cdlatex-position-cursor nil t nil)
("fra" "insert frame (for beamer)" "" cdlatex-environment ("frame") t nil)
("hhl" "insert \\ \\hline" "\\\\ \\hline" ignore nil t nil)
("hl" "insert \\hline" "\\hline" ignore nil t nil)
("ipenu" "insert in paragraph enumerate" "" cdlatex-environment ("inparaenum") t nil)
("ipite" "insert in paragraph itemize" "" cdlatex-environment ("inparaitem") t nil)
("it" "insert \\item" "\\item?" cdlatex-position-cursor nil t nil)
("ld" "insert ldots" "\\ldots" nil nil t t)
("lem" "insert lemma env" "" cdlatex-environment ("lemma") t nil)
("liml" "insert \\lim\\limits_{}" "\\lim\\limits_{?}" cdlatex-position-cursor nil nil t)
("lr<" "insert bra-ket" "\\langle ? \\rangle" cdlatex-position-cursor nil nil t)
("myenu" "insert in my enumerate for beamer" "" cdlatex-environment ("myenumerate") t nil)
("myite" "insert in my itemize for beamer" "" cdlatex-environment ("myitemize") t nil)
("ons" "" "\\onslide<?>{ }" cdlatex-position-cursor nil t t)
("pa" "insert pause" "\\pause" ignore nil t nil)
("pro" "insert proof env" "" cdlatex-environment ("proof") t nil)
("prodl" "insert \\prod\\limits_{}^{}" " \\prod\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("prop" "insert proposition" "" cdlatex-environment ("proposition") t nil)
("se" "insert \\{\\}" "\\{ ? \\}" cdlatex-position-cursor nil nil t)
("spl" "insert split" "" cdlatex-environment ("split") nil t)
("st" "stackrel" "\\stackrel{?}{}" cdlatex-position-cursor nil nil t)
("te" "insert text" "\\text{?}" cdlatex-position-cursor nil nil t)
("thm" "insert theorem env" "" cdlatex-environment ("theorem") t nil)
("vd" "insert vdots" "\\vdots" nil nil t t)))你是否遇到过以下困扰:
RefTeX 让你轻松创建、引用和管理标签,随心所欲,毫无压力。
用 M-x + reftex-label, 或者 lbl + Tab (CDLaTeX 的命令补全) 均可以生成形如 \label{type:XXXX} 的标签.
标签的内容根据标签的类型, 有以下的方式决定.
\label{eq:NNN} 或者列表环境 \label{it:NNN}, 这里 NNN 表示自动生成的数字. 它是 RefTeX 在当前文档中找到的可以使用的最小数字.\section{First Second Third} 自动生成 \label{sec:first-second-third}用 M-x + reftex-reference, C-c [ 或者 ref + Tab (CDLaTeX 命令补全) 均可以触发引用交叉标签.
\ref, \pageref 等e: 公式标签 (eq:), 包括 equation, 以及 align, gather 等 amsmath 定义的数学公式环境i: 列表标签 (it:), 列表环境 item 的标签s: 章节标签 (sec:), f: 图片标签 (fig:), 等等\ref{} 命令中包含在我们一开始的 AucTeX 配置代码中:
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(add-hook 'LaTeX-mode-hook 'my/latex-hook)默认使用 \ref{} 格式, ref + Tab 直接进入标签选择
(setq reftex-ref-macro-prompt nil)在标签选择界面, 可以用 v 和 V 去改变引用格式.
reftex-reference 会识别光标前的文字自动选择标签类型. 例如, equation 后插入标签会默认类型为 e
可以由变量 reftex-guess-label-type 控制
(setq reftex-guess-label-type t) ; 默认值可以通过 M-x customize-variable 界面修改 reftex-label-alist
t, 绑定 theorem 环境, 标签以 thm: 开头\macro: theoremtthm:Theorem, 定理当我们选择某个标签类型如 t 时
reftex-trust-label-prefix 为 nil, 只会用环境名 theorem 来决定标签类型reftex-trust-label-prefix 为 t, 也会用 thm: 来识别标签类型.(setq reftex-trust-label-prefix t)e 类型加入更多的 magic worde公式可以通过 M-x customize-variable 界面修改 reftex-insert-label-flag
t 加进去.如果一个类型没有在两个列表中出现, 则使用数字作为标签.
(setq reftex-label-menu-flags '(t t nil nil t nil t nil)) ; 在标签选择界面;; 为 LaTeX 模式加载 RefTeX
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex))
(add-hook 'LaTeX-mode-hook 'my/latex-hook)
(setq reftex-ref-macro-prompt nil)
(setq reftex-guess-label-type t) ; 默认值
(setq reftex-trust-label-prefix t)
(setq reftex-label-menu-flags '(t t nil nil t nil t nil)) ; 标签选择界面跟随界面
;; 以及通过 customize-variable 对 reftex-label-alist 和 reftex-insert-label-flag 的设置pdf-tools 的理由在用 Emacs 编写 LaTeX 文档的过程中, 你是否…
又或者, 你想用 Emacs 做读书笔记, 需要同时:
pdf-tools 可以完美实现这些目标.
pdf-tools 的优点与 DocView (Emacs 中内置的 pdf 阅读器) 比较
DocView: 不清晰, 阅读效果差, 读取速度慢pdf-tools:auctex 配合使用, 支持对编译后 pdf 进行正向/反向搜索latex 文档org-noter 在 pdf 上做读书笔记分为两部分
melpa-stable 在 Emacs 包的列表中
可以通过查看 package-archives 变量进行确认 (require 'package) ;; Emacs 包管理器
(setq package-check-signature nil) ;; 如果有签名验证问题, 可以设置不检查签名
(setq package-archives '(("elpa" . "http://tromey.com/elpa/")
("melpa-stable" . "https://stable.melpa.org/packages/") ;; 下载 pdf-tools 只需要这个
("melpa" . "https://melpa.org/packages/")
("gnu" . "http://elpa.gnu.org/packages/")))pdf-toolsmelpa-stable 版本 (2023.3: melpa 版本仍有 bug)epdfinfo.exe 的安装epdfinfo.exe 及其它一些依赖文件 (例如 libpopper-<version>.dll) 可以帮助 Emacs 读取 pdf 文件
两种方法
msys2msys2 安装 epdfinfomsys2?可以将许多开源程序本地化编译为 Windows 程序的平台
优点
Git, Emacs, texlive, gcc, python …msys2 官网上 https://www.msys2.org/ 下载安装程序 msys2-x86_x64-<date>.exe. 默认安装目录为 C:/msys64/.C:/msys64/ 下 mingw64.exe. 会弹出一个命令行终端 pacman -S mingw-w64-x86_64-emacs-pdf-tools-serverC:\msys64\mingw64\bin 中找到 epdfinfo.exe.C:\msys64\mingw64\bin 加入环境变量 PATHpdf-tools在 init.el 文件中加入
(pdf-tools-install)如果想延迟启动 (如打开 pdf 文件后再启动, 节省 Emacs 启动时间), 可以用下面的代码替换
(pdf-loader-install)AucTeX 使用的配置保持不变的设置
(setq TeX-PDF-mode t)
(setq TeX-source-correlate-mode t) ;; 编译后开启正反向搜索
(setq TeX-source-correlate-method 'synctex) ;; 正反向搜索的执行方式
(setq TeX-source-correlate-start-server t) ;; 不再询问是否开启服务器以执行反向搜索使用 Sumatra PDF 的配置
(setq TeX-view-program-list
'(("Sumatra PDF" ("\"C:/Program Files/SumatraPDF/SumatraPDF.exe\" -reuse-instance" (mode-io-correlate " -forward-search %b %n ") " %o"))))
(assq-delete-all (quote output-pdf) TeX-view-program-selection)
(add-to-list 'TeX-view-program-selection '(output-pdf "Sumatra PDF")pdf-tools 的配置
(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) ;; 用pdf-tools 打开 pdf
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ;; 在完成编译后刷新 pdf 文件我的设置: 尽量把移动绑定在左手 (awsd), 空出右手进行鼠标操作.
(define-key pdf-view-mode-map
"d" 'pdf-view-next-page-command) ;; 向后翻页
(define-key pdf-view-mode-map
"a" 'pdf-view-previous-page-command) ;; 向前翻页
(define-key pdf-view-mode-map
"s" 'pdf-view-scroll-up-or-next-page) ;; 向下滑动
(define-key pdf-view-mode-map
"w" 'pdf-view-scroll-down-or-previous-page) ;; 向上滑动我的设置:
(require 'pdf-annot)
(define-key pdf-annot-minor-mode-map (kbd "C-a a") 'pdf-annot-add-highlight-markup-annotation) ;; 高亮
(define-key pdf-annot-minor-mode-map (kbd "C-a s") 'pdf-annot-add-squiggly-markup-annotation) ;; 波浪线
(define-key pdf-annot-minor-mode-map (kbd "C-a u") 'pdf-annot-add-underline-markup-annotation) ;; 下划线
(define-key pdf-annot-minor-mode-map (kbd "C-a d") 'pdf-annot-delete) ;; 删除这里重新绑定常用的返回功能 (小知识: 在 Sumatra PDF 里对应 Alt-<right>)
(require 'pdf-history)
(define-key pdf-history-minor-mode-map "b" 'pdf-history-backward)打开 pdf 文件时自动放缩
(add-hook 'pdf-view-mode-hook 'pdf-view-fit-width-to-window) ;; 自动放大到页宽这可能是安装了 2023 年后 pdf-tools 的版本导致的. 可以从 M-x package-list-package 界面中确认是从 melpa-stable 中安装的
(invalid-function pdf-view-current-page) 的错误信息这是因为在 28.x 以后的 Emacs 版本中会开启本地化编译 (native compilation), 而 pdf-tools 中有一些语法过时了, 在本地化编译时会报错. 如果这个 bug 不解决的话, 不影响 pdf-tools 的使用, 但是会稍微降低 pdf 渲染的速度.
用 C-h v <enter> system-configuration-options <enter> 查询, 如果变量包含字段 --with-native-compilation, 则说明当前版本支持本地化编译
本地化编译后的文件会放在 .emacs.d/eln-cache/ 中, 以 .elc 结尾.
如果在上面的目录下已经产生了 pdf-*.elc 文件, 请先删除.
(setq no-native-compile t)pdf-tools 的本地化编译 (setq native-comp-deferred-compilation-deny-list '(".*pdf.*")) (pdf-tools-install)
(setq native-comp-deferred-compilation-deny-list '(".*pdf.*"))
(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) ;; 用pdf-tools 打开 pdf
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ;; 在完成编译后刷新 pdf 文件
(define-key pdf-view-mode-map "d" 'pdf-view-next-page-command) ;; 向后翻页
(define-key pdf-view-mode-map "a" 'pdf-view-previous-page-command) ;; 向前翻页
(define-key pdf-view-mode-map "s" 'pdf-view-scroll-up-or-next-page) ;; 向下滑动
(define-key pdf-view-mode-map "w" 'pdf-view-scroll-down-or-previous-page) ;; 向上滑动
(require 'pdf-annot)
(define-key pdf-annot-minor-mode-map (kbd "C-a a") 'pdf-annot-add-highlight-markup-annotation) ;; 高亮
(define-key pdf-annot-minor-mode-map (kbd "C-a s") 'pdf-annot-add-squiggly-markup-annotation) ;; 波浪线
(define-key pdf-annot-minor-mode-map (kbd "C-a u") 'pdf-annot-add-underline-markup-annotation) ;; 下划线
(define-key pdf-annot-minor-mode-map (kbd "C-a d") 'pdf-annot-delete) ;; 删除
(require 'pdf-history)
(define-key pdf-history-minor-mode-map "b" 'pdf-history-backward)
(add-hook 'pdf-view-mode-hook 'pdf-view-fit-width-to-window) ;; 自动放大到页宽pdf-tools 的 Github 仓库: https://github.com/vedang/pdf-toolsmsys2 官网 https://www.msys2.org/epdfinfo.exe 可用版本: https://www.jianguoyun.com/p/DTiBwxMQ856tCxiflP0EIAApdf-tools 的理由在用 Emacs 编写 LaTeX 文档的过程中, 你是否…
又或者, 你想用 Emacs 做读书笔记, 需要同时:
pdf-tools 可以完美实现这些目标.
pdf-tools 的优点与 DocView (Emacs 中内置的 pdf 阅读器) 比较
DocView: 不清晰, 阅读效果差, 读取速度慢pdf-tools:auctex 配合使用, 支持对编译后 pdf 进行正向/反向搜索latex 文档org-noter 在 pdf 上做读书笔记分为两部分
melpa-stable 在 Emacs 包的列表中
可以通过查看 package-archives 变量进行确认 (require 'package) ;; Emacs 包管理器
(setq package-check-signature nil) ;; 如果有签名验证问题, 可以设置不检查签名
(setq package-archives '(("elpa" . "http://tromey.com/elpa/")
("melpa-stable" . "https://stable.melpa.org/packages/") ;; 下载 pdf-tools 只需要这个
("melpa" . "https://melpa.org/packages/")
("gnu" . "http://elpa.gnu.org/packages/")))pdf-toolsmelpa-stable 版本 (2023.3: melpa 版本仍有 bug)epdfinfo.exe 的安装epdfinfo.exe 及其它一些依赖文件 (例如 libpopper-<version>.dll) 可以帮助 Emacs 读取 pdf 文件
两种方法
msys2msys2 安装 epdfinfomsys2?可以将许多开源程序本地化编译为 Windows 程序的平台
优点
Git, Emacs, texlive, gcc, python …msys2 官网上 https://www.msys2.org/ 下载安装程序 msys2-x86_x64-<date>.exe. 默认安装目录为 C:/msys64/.C:/msys64/ 下 mingw64.exe. 会弹出一个命令行终端 pacman -S mingw-w64-x86_64-emacs-pdf-tools-serverC:\msys64\mingw64\bin 中找到 epdfinfo.exe.C:\msys64\mingw64\bin 加入环境变量 PATHpdf-tools在 init.el 文件中加入
(pdf-tools-install)如果想延迟启动 (如打开 pdf 文件后再启动, 节省 Emacs 启动时间), 可以用下面的代码替换
(pdf-loader-install)AucTeX 使用的配置保持不变的设置
(setq TeX-PDF-mode t)
(setq TeX-source-correlate-mode t) ;; 编译后开启正反向搜索
(setq TeX-source-correlate-method 'synctex) ;; 正反向搜索的执行方式
(setq TeX-source-correlate-start-server t) ;; 不再询问是否开启服务器以执行反向搜索使用 Sumatra PDF 的配置
(setq TeX-view-program-list
'(("Sumatra PDF" ("\"C:/Program Files/SumatraPDF/SumatraPDF.exe\" -reuse-instance" (mode-io-correlate " -forward-search %b %n ") " %o"))))
(assq-delete-all (quote output-pdf) TeX-view-program-selection)
(add-to-list 'TeX-view-program-selection '(output-pdf "Sumatra PDF")pdf-tools 的配置
(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) ;; 用pdf-tools 打开 pdf
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ;; 在完成编译后刷新 pdf 文件我的设置: 尽量把移动绑定在左手 (awsd), 空出右手进行鼠标操作.
(define-key pdf-view-mode-map
"d" 'pdf-view-next-page-command) ;; 向后翻页
(define-key pdf-view-mode-map
"a" 'pdf-view-previous-page-command) ;; 向前翻页
(define-key pdf-view-mode-map
"s" 'pdf-view-scroll-up-or-next-page) ;; 向下滑动
(define-key pdf-view-mode-map
"w" 'pdf-view-scroll-down-or-previous-page) ;; 向上滑动我的设置:
(require 'pdf-annot)
(define-key pdf-annot-minor-mode-map (kbd "C-a a") 'pdf-annot-add-highlight-markup-annotation) ;; 高亮
(define-key pdf-annot-minor-mode-map (kbd "C-a s") 'pdf-annot-add-squiggly-markup-annotation) ;; 波浪线
(define-key pdf-annot-minor-mode-map (kbd "C-a u") 'pdf-annot-add-underline-markup-annotation) ;; 下划线
(define-key pdf-annot-minor-mode-map (kbd "C-a d") 'pdf-annot-delete) ;; 删除这里重新绑定常用的返回功能 (小知识: 在 Sumatra PDF 里对应 Alt-<right>)
(require 'pdf-history)
(define-key pdf-history-minor-mode-map "b" 'pdf-history-backward)打开 pdf 文件时自动放缩
(add-hook 'pdf-view-mode-hook 'pdf-view-fit-width-to-window) ;; 自动放大到页宽这可能是安装了 2023 年后 pdf-tools 的版本导致的. 可以从 M-x package-list-package 界面中确认是从 melpa-stable 中安装的
(invalid-function pdf-view-current-page) 的错误信息这是因为在 28.x 以后的 Emacs 版本中会开启本地化编译 (native compilation), 而 pdf-tools 中有一些语法过时了, 在本地化编译时会报错. 如果这个 bug 不解决的话, 不影响 pdf-tools 的使用, 但是会稍微降低 pdf 渲染的速度.
用 C-h v <enter> system-configuration-options <enter> 查询, 如果变量包含字段 --with-native-compilation, 则说明当前版本支持本地化编译
本地化编译后的文件会放在 .emacs.d/eln-cache/ 中, 以 .elc 结尾.
如果在上面的目录下已经产生了 pdf-*.elc 文件, 请先删除.
(setq no-native-compile t)pdf-tools 的本地化编译 (setq native-comp-deferred-compilation-deny-list '(".*pdf.*")) (pdf-tools-install)
(setq native-comp-deferred-compilation-deny-list '(".*pdf.*"))
(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) ;; 用pdf-tools 打开 pdf
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ;; 在完成编译后刷新 pdf 文件
(define-key pdf-view-mode-map "d" 'pdf-view-next-page-command) ;; 向后翻页
(define-key pdf-view-mode-map "a" 'pdf-view-previous-page-command) ;; 向前翻页
(define-key pdf-view-mode-map "s" 'pdf-view-scroll-up-or-next-page) ;; 向下滑动
(define-key pdf-view-mode-map "w" 'pdf-view-scroll-down-or-previous-page) ;; 向上滑动
(require 'pdf-annot)
(define-key pdf-annot-minor-mode-map (kbd "C-a a") 'pdf-annot-add-highlight-markup-annotation) ;; 高亮
(define-key pdf-annot-minor-mode-map (kbd "C-a s") 'pdf-annot-add-squiggly-markup-annotation) ;; 波浪线
(define-key pdf-annot-minor-mode-map (kbd "C-a u") 'pdf-annot-add-underline-markup-annotation) ;; 下划线
(define-key pdf-annot-minor-mode-map (kbd "C-a d") 'pdf-annot-delete) ;; 删除
(require 'pdf-history)
(define-key pdf-history-minor-mode-map "b" 'pdf-history-backward)
(add-hook 'pdf-view-mode-hook 'pdf-view-fit-width-to-window) ;; 自动放大到页宽pdf-tools 的 Github 仓库: https://github.com/vedang/pdf-toolsmsys2 官网 https://www.msys2.org/epdfinfo.exe 可用版本: https://www.jianguoyun.com/p/DTiBwxMQ856tCxiflP0EIAA文本编辑中的两个要素
【Emacs+LaTeX教程】Emacs最强内置pdf阅读功能pdf-tools简介 缺点
preview-latex【教程】LaTeX+Emacs从零开始2-6节:所见即所得之Preview-latex 缺点
prettify-symbols-mode优点
版本要求
auctex 查看)M-x prettify-symbols-mode
init.el 文件设置 (defun my-latex-hook ()
(prettify-symbols-mode t))
(add-hook 'LaTeX-mode-hook 'my-latex-hook)保证 Unicode 数学符号可以正确显示
(set-fontset-font "fontset-default" 'mathematical "Cambria Math")设置自动展开光标附近的宏命令.
(setq prettify-symbols-unprettify-at-point t)tips: 如果只想删除刚输入的一个宏命令, 最快的方法是用 C-/ 撤消, 而不是一个个字符删除.
(require 'tex-mode)
(defun my/more-prettified-symbols ()
(mapc (lambda (pair) (cl-pushnew pair tex--prettify-symbols-alist))
'(("\\Z" . 8484) ;; 大多数人在latex中会用 \Z, \Q, \N, \R 表示数域
("\\Q" . 8474)
("\\N" . 8469)
("\\R" . 8477)
("\\eps" . 949)
("\\ONE" . #x1D7D9)
("\\mathbb{S}" . #x1D54A)
("\\PP" . #x2119) ;; 个人需要, 经常要使用P和E的数学字体
("\\P" . #x1D5AF )
("\\Pp" . #x1D40F)
("\\E" . #x1D5A4)
("\\Ee" . #x1D404)
("\\EE" . #x1D53C )
("\\Fc" . #x2131)
("\\Nc" . #x1D4A9))))
(my/more-prettified-symbols)将 ("<latex 宏命令>" . <unicode 编码>) 加入列表中
\\” 开头, 表示一个普通的 “\”.#x” 表示是 16 进制数字, 否则就是 10 进制个人加入编码的原则
\N , \Z 等大多数人使用的宏命令, 这样可以减少与他人合作的障碍E, P. ;; 以下为LaTeX mode相关设置
(setq-default TeX-master nil) ;; 编译时问询主文件名称
(setq TeX-parse-selt t) ;; 对新文件自动解析(usepackage, bibliograph, newtheorem等信息)
;; PDF正向搜索相关设置
(setq TeX-PDF-mode t)
(setq TeX-source-correlate-mode t)
(setq TeX-source-correlate-method 'synctex)
(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) ;; 用pdf-tools 打开 pdf
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ;; 在完成编译后刷新 pdf 文件
;; 打开TeX文件时应该加载的mode/执行的命令
(defun my-latex-hook ()
(turn-on-cdlatex) ;; 加载cdlatex
(outline-minor-mode) ;; 加载outline mode
(prettify-symbols-mode t)
(turn-on-reftex) ;; 加载reftex
(outline-hide-body)) ;; 打开文件时只显示章节标题
(add-hook 'LaTeX-mode-hook 'my-latex-hook)
(setq prettify-symbols-unprettify-at-point t)
(set-fontset-font "fontset-default" 'mathematical "Cambria Math")
(require 'tex-mode)
(defun my/more-prettified-symbols ()
(mapc (lambda (pair) (cl-pushnew pair tex--prettify-symbols-alist))
'(("\\Z" . 8484) ;; 大多数人在latex中会用 \Z, \Q, \N, \R 表示数域
("\\Q" . 8474)
("\\N" . 8469)
("\\R" . 8477)
("\\eps" . 949)
("\\ONE" . #x1D7D9)
("\\mathbb{S}" . #x1D54A)
("\\PP" . #x2119) ;; 个人需要, 经常要使用P和E的数学字体
("\\P" . #x1D5AF )
("\\Pp" . #x1D40F)
("\\E" . #x1D5A4)
("\\Ee" . #x1D404)
("\\EE" . #x1D53C )
("\\Fc" . #x2131)
("\\Nc" . #x1D4A9))))
(my/more-prettified-symbols)