本文基本上是对 How I'm able to take notes in mathematics lectures using LaTeX and Vim一文的实践操作。感谢原作者的分享。
本文基础
平台
Windows 11
软件
- gvim
- SumatraPDF
- miktex
Vim 插件
- vimtex
- utilsnip
正文
下载安装上述软件,包括 gvim, SumatraPDF, miktex, Strawberry perl.
- SumatraPDF就是一个支持 rpc的PDF浏览器,其它平台的推荐浏览器可以在 vimtex上的文档中寻找,比如上述 Castel小哥在文章中在 linux上用的 Zathura。
- MiKTeX是 Windows平台上的一个 LaTeX实现,在本文中它作为用于编译 LaTex文件的后端存在。
- Strawberry perl是 MiKTeX的依赖项,用于安装管理丰富的数学符号包
在vim上安装上述的 vim插件。我使用的是 vim plug, 所以我在我的 _vimrc中加入了:
call plug#begin() ... Plug 'lervag/vimtex',{'tag':'v2.15'} Plug 'godlygeek/tabular' Plug 'sirver/ultisnips' ''Plug 'your/vim-snippets' ... call plug#end()
注意最后一行有个被注释的插件,我建议你在gayhub上创建一个自己的vim-snippets仓库,用来管理自己的snippets。ultisnips的 github页上推荐的是 honza/vim-snippets, 你可以fork一份作为自己的snippets库的开始。
vim配置
- vimtex的配置
" Noting {{{ let g:tex_flavor='latex' let g:vimtex_quickfix_mode=0 set conceallevel=1 let g:vimtex_view_general_viewer = 'SumatraPDF.exe' let g:vimtex_view_general_options \ = '-reuse-instance -forward-search @tex @line @pdf' let g:tex_conceal='abdmg' " PDF reader " let g:Tex_ViewRule_pdf = 'SumatraPDF " -reuse-instance -inverse-search "gvim -c \":RemoteOpen +\%l \%f\""' let g:vimtex_view_general_viewer = 'SumatraPDF' "这里放置你的sumatrapdf 安装路径 let g:vimtex_view_general_options \ = ' -reuse-instance -forward-search @tex @line @pdf' \ . ' -inverse-search "' . ' wt -w 0 \"\" ' . 'gvim' \ . ' -v --not-a-term -T dumb -c \"VimtexInverseSearch %l ''%f''\""' "for vim/gvim " 编译过程中忽略警告信息 let g:vimtex_quickfix_open_on_warning=0 " 这里是LaTeX编译引擎的设置,这里默认LaTeX编译方式为-pdf(pdfLaTeX), " vimtex提供了magic comments来为文件设置编译方式 " 例如,我在tex文件开头输入 % !TEX program = xelatex 即指定-xelatex "(xelatex)编译文件 let g:vimtex_compiler_latexmk_engines = { \ '_' : '-pdf', \ 'pdflatex' : '-pdf', \ 'dvipdfex' : '-pdfdvi', \ 'lualatex' : '-lualatex', \ 'xelatex' : '-xelatex', \ 'context (pdftex)' : '-pdf -pdflatex=texexec', \ 'context (luatex)' : '-pdf -pdflatex=context', \ 'context (xetex)' : '-pdf -pdflatex=''texexec --xtx''', \} " 这里是设置latexmk工具的可选参数 let g:vimtex_compiler_latexmk = { \ 'build_dir' : '', \ 'callback' : 1, \ 'continuous' : 1, \ 'executable' :'latexmk', \ 'hooks' : [], \ 'options' : [ \'-verbose', \'-file-line-error', \'-shell-escape', \'-synctex=1', \'-interaction=nonstopmode', \], \} " }}}
要注意的主要是latex客户端和pdf浏览器的名称、路径。
在配置完后,可以新建一个 .tex文件,随便写点啥,比如:\documentclass{article} \begin{document} \title{Hello world} \author{BugCatcher} \endP{document}
保存然后在普通模式下输入
<localleader>ll
开始编译,编译完成后会自动打开 pdf浏览器,查看编译后的结果。- ultisnips的配置
" UltiSnips {{{ let g:tex_flavor = "latex" let g:UltiSnipsSnippetDirectories=["UltiSnips",'$HOME/vimfiles/plugged/vim-snippets/UltiSnips'] let g:UltiSnipsExpandOrJumpTrigger="<TAB>" let g:UltiSnipsExpandTrigger="<TAB>" let g:UltiSnipsJumpForwardTrigger="<TAB>" let g:UltiSnipsJumpBackwardTrigger="<S-TAB>" " }}}
要注意的主要是,在使用 ultisnip的同时我也使用了 coc,coc默认的补全触发键也是 <tab>,所以我把 coc的补全触发键改为了<c-k>。
在选择 snippets插件的时候我一度犹豫过使用 coc-snippets,它的优点是它本身就是 coc的一个模块,和 coc其它部分兼容,不会存在像 ultisnips和 coc的触发键冲突这样的问题。但是缺点是它是基于nodejs开发的,有些 ultisnips的强大功能它无法支持,详情可以参考 coc-snippets的 github页面。
其中一个强大的功能正是 pre_expand, post_expand等 snippet actions。比如说,我正要学习的数学知识涉及大量的矩阵,没有 snippets得写到手抽筋;但是面对不同尺寸的矩阵,难道说我要一个个写 snippets来展开吗?这时候,我扒到了一个 snippets:global !p ... def create_matrix(snip): matrix_str = (snip.buffer[snip.line].split('mat')[0]+'matrix').strip() rows = 'x'.join(snip.buffer[snip.line].split("x", 2)[:-1]) cols = 'x'.join(snip.buffer[snip.line].split("x", 2)[-1:]) int_val = lambda string: int(''.join(s for s in string if s.isdigit())) rows = int_val(rows) cols = int_val(cols) offset = cols + 1 old_spacing = snip.buffer[snip.line][:snip.buffer[snip.line].rfind('\t') + 1] snip.buffer[snip.line] = '' final_str = old_spacing + "\\begin{"+matrix_str+"}\n" for i in range(rows): final_str += old_spacing + '\t' final_str += " & ".join(['$' + str(i * cols + j + offset) for j in range(cols)]) final_str += " \\\\\\\n" final_str += old_spacing + "\\end{"+matrix_str+"}\n$0" snip.expand_anon(final_str) endglobal ... pre_expand "create_matrix(snip)" snippet "(small|[bBpvV])?mat(rix)?(\d+)x(\d+)" "Generate (small|[bBpvV])?matrix of *rows* by *columns*" br endsnippet
上面的 snippet,它首先在snippet文件的开头的全局 python脚本中写了一个根据输入返回对应矩阵snippet的函数,然后加了一个使用正则表达式的snippet,自动匹配矩阵的格式,比如 bmat3x3。在实际使用时你输入 bmat3x3,触发补全,然后它就会调用
create_matrix
函数生成对应的snippet填充到文件中,这时你只用一下下tab来遍历输入 3x3 矩阵的 9个元素。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。