当前位置:首页 > 每日看点

Vim有什么奇技巧?

卡卷网2年前 (2025-01-08)每日看点285

有人用vim纯手打1700页数学笔记。

速度紧追老师板书,公式、图形一个不落。效果?请看下图:

不仅排版媲美教科书,而且还能够批注,检索……

笔记被他Po到网上之后,便引来大量围观。

不到一天,相关推文就已经有2000多赞,HackerNews论坛上盖了200多楼。

甚至有网友评论称:“你就是我们需要的英雄!”

他是怎么做到的呢?秘密武器就是:<>LaTeX+<>Vim!

下面就让我们看一下他完成这一壮举的具体流程,文中提到的工具下载,我们都附在了最后。

<>快速上手教程

我们先看看小哥的工作环境配置。

他用Vim编辑LaTeX的场景,就像下面这样:

左边是Vim,右边是pdf阅读器Zatha,它也有类似Vim的快捷键。

小哥用的作是Uuntu,使用spwm作为窗口器。在Vim中,使用的LaTex插件是vimtex,它有语法高亮显示、目录视图、同步对象等功能。

然后,使用vim-plug做如下配置:

Plug'lervag/vimtex' letg:tex_flor='latex' letg:vimtex_view_method='zatha' letg:vimtex_quickfix_mode=0 setconceallevel=1 letg:tex_conceal='admg'

最后两行控制的是“隐”功能。开启了这个功能,除了你光标所在的那一行之外,文本里夹杂的LaTeX代码就都会隐或者替换成符号。

如说在下面动图里,隐了[,],$之后,没有了它们的干扰,整个文档就更易读。这个功能还会用∩替代\igcap,∈替代\in等等。

设置完成,接下来就到了整个教程的精华所在:

<>用LaTeX记笔记,怎么才能像老师写板书一样快?

这就是片段(snippets)发挥作用地方了。

<>片段

<>片段是什么?

片段是一小段可复用的文本,由文本触发。

例如,输入sign,再按下Ta键,这个单词就会自动扩展为一段签名:

片段也可以是动态的:输入today并按下Ta键,它就会变成当前的期。

而输入ox按Ta,就会出现一个框,还会随着输入文字自动变大。

片段,甚至可以嵌套在另一个片段里用:

<>怎么创建片段?使用UltiSnips

片段的插件UltiSnips,小哥是这样配置的:

Plug'sirver/ultisnips' letg:UltiSnipsExpandTrigger='<ta>' letg:UltiSnipsJumpForwardTrigger='<ta>' letg:UltiSnipsJumpackwardTrigger='<s-ta>'

关于sign片段的代码如下:

snippetsign"Signate" Yossincerely, GillesCas endsnippet

对于动态的片段,你可以将代码放在``之间,在片段扩展的时候,就会运行。下面的例子,就是用ash格式化当前期:date+%f。

snippettoday"Date" `date+%F` endsnippet

你也可以在!p...代码块里使用Python,如上面ox片段的代码就是这样的:

snippetox"ox" `!psnip.rv='┌'+'─'*(len(t[1])+2)+'┐'` │$1│ `!psnip.rv='└'+'─'*(len(t[1])+2)+'┘'` $0 endsnippet

这些Python代码块将被变量snip.rv的值替换。在这些代码块中,你可以访问代码段的当前状态,例如t[1]包含第一个制表位,fn是当前文件名等等。

<>LaTex片段

使用片段编写LaTeX,要纯手工编写快得多。特别有些非常复杂的片段能帮你大大节约时间,有效防止抓狂。

下面是一些非常有用且容易上手的片段:

<>环境

想一个环境,只需要在一行的开头输入eg。然后键入环境的名称,这个名称在\end{}命令中也是一样。按下Ta键,就能够将光标放置在新创建的环境中。

这个片段的代码如下:

snippeteg"egin{}/end{}"A \egin{$1} $0 \end{$1} endsnippet

其中,表示这个片段只会在代码行的开头展开,A代表自动展开,也就是说不用按Ta键了。制表位(Tastop)——也就是你可以通过按Ta和Shift+Ta跳转到的位置——用$1、$2、......来表示,最后一个用$0。

<>行内和数学显示

在记数学笔记的过程中,最常用的两个片段是mk和dm。

它们负责启动数学模式。第一个片段用于“行内数学”,第二个用于“显示数学”。

代码行内的数学片段是“智能的”:它知道什么时候在$符号后面直接输入一个单词,它会自动加个空格。但如果输入一个非单词的字符,它就不会添加空格了,如在““$p$-value”情况下,是这样的:

这个片段的代码如下:

snippetmk"Math"wA $${1}$`!p ift[2]andt[2][0]notin[',','.','?','-','']: snip.rv='' else: snip.rv='' `$2 endsnippet

第一行末尾的w,意味着这个片段会在单词边界处扩展,例如,hellomk不会扩展,但是hellomk会。

用于显示数学的片段更简单,也更加方便;有了它,你可能再也不会忘记用句号结束方程了。

代码:

snippetdm"Math"wA \[ $1 .\]$0 endsnippet

<>小写和上标

另一个很有用的片段就是下标。能够把a1改为a1,把a_12改为a{12}。

这个片段的触发器是使用正则表达式。有两种情况会扩展片段。一是你键入一个字符,后面跟着一个数字,如[A-Za-z]\d;另一种是,一个字符后面有并跟着两个数字,如[A-Za-z]\d\d。

snippet'([A-Za-z])(\d)'"autosuscript"wrA `!psnip.rv=match.group(1)`_`!psnip.rv=match.group(2)` endsnippet snippet'([A-Za-z])_(\d\d)'"autosuscript2"wrA `!psnip.rv=match.group(1)`_{`!psnip.rv=match.group(2)`} endsnippet

当你使用括号将正则表达式的一部分装在一个组中时,例如(\d\d),你可以在Python中通过match.group(i)来使用它们扩展片段。

至于上标,可以使用td,它就会变成^{}。然而,对于平方、立方和一些常见的片段,可以使用专门的代码片段,如sr、c等等。

效果图:

代码:

snippetsr"^2"iA ^2 endsnippet snippetc"^3"iA ^3 endsnippet snippetcompl"complement"iA ^{c} endsnippet snippettd"superscript"iA ^{$1}$0 endsnippet

<>分数

分数是一个用起来最方便的一个片段,扩展的形式如下:

//→frac{}{}3/→frac{3}{}4pi^2/→frac{4pi^2}{}(1+2+3)/→frac{1+2+3}{}(1+(2+3)/)→(1+frac{2+3}{})(1+(2+3))/→frac{1+(2+3)}{

第一个片段的代码很简单:

snippet//"Fraction"iA \\frac{$1}{$2}$0 endsnippet

第二个和第三个示例,可以使用正则表达式来匹配3/、4ac/、6pi^2/、a2/等表达式。

snippet'((\d+)|(\d*)(\\)?([A-Za-z]+)((\^|_)(\{\d+\}|\d))*)/'"Fraction"wrA \\frac{`!psnip.rv=match.group(1)`}{$1}$0 endsnippet

看了上边这些,你可能觉得正则表达式太难了。没关系,下面有一个解释得非常直观的图表:

在第四和第五种示例下,要换一种方法。使用UltiSnips的正则表达式引擎解决不了的,Python可以:

priority1000 snippet'^.*\)/'"()Fraction"wrA `!p stripped=match.string[:-1] depth=0 i=len(stripped)-1 whileTrue: ifstripped[i]==')':depth+=1 ifstripped[i]=='(':depth-=1 ifdepth==0:reak; i-=1 snip.rv=stripped[0:i]+"\\frac{"+stripped[i+1:-1]+"}" `{$1}$0 endsnippet

这里最后要分享的关于分数的片段,能根据你的选择,来生成一个分数。

你可以先选择一些文本,然后按Ta键,继续输入、然后再按Ta键。

代码中,使用${VUAL}变量来表示所选的内容。

snippet/"Fraction"iA \\frac{${VUAL}}{$1}$0 endsnippet

<>Sympy和Mathematica

还有一个很酷但用得不多的片段,是使用Sympy来计算数学表达式。例如,输入sympy,然后按下Ta,可以扩展为sympy|sympy,输入sympy1+1sympy,按下Ta,可以扩展为2。

片段代码:

snippetsympy"sympylock"w sympy$1sympy$0 endsnippet priority10000 snippet'sympy(.*)sympy'"evaluatesympy"wr `!p fromsympyimport* x,y,z,t=symols('xyzt') k,m,n=symols('kmn',integer=True) f,g,h=symols('fgh',cls=Function) init_printing() snip.rv=eval('latex('+match.group(1).replace('\\','')\ .replace('^','**')\ .replace('{','(')\ .replace('}',')')+')') ` endsnippet

用Mathematica,也可以做类似的事情:

片段代码:

priority1000 snippetmath"mathematicalock"w math$1math$0 endsnippet priority10000 snippet'math(.*)math'"evaluatemathematica"wr `!p importsuprocess code='ToString['+match.group(1)+',TeXForm]' snip.rv=suprocess.check_output(['wolframscript','-code',code]) ` endsnippet

<>后缀片段

除了上边这些之外,后缀片段也很值得分享。例如phat→hat{p}和zar→overline{z}。还有类似的后缀向量,例如v,.→vec{v}和v.,→vec{v}。.和,的顺序没关系,所以可以同时按下它们两个。

这些片段的可以节省时间,可以按照和老师写板书一样的顺序来记。

注意,ar和hat前缀也依然可以用,只要以较低的优先级添加它们就行。

这些片段的代码是:

priority10 snippet"ar""ar"riA \overline{$1}$0 endsnippet priority100 snippet"([a-zA-Z])ar""ar"riA \overline{`!psnip.rv=match.group(1)`} endsnippet

priority10 snippet"hat""hat"riA \hat{$1}$0 endsnippet priority100 snippet"([a-zA-Z])hat""hat"riA \hat{`!psnip.rv=match.group(1)`} endsnippet

snippet"(\\?\w+)(,\.|\.,)""Vectorpostfix"riA \vec{`!psnip.rv=match.group(1)`} endsnippet

<>片段

此外,小哥还有大约100个常用的片段(下载附于文末),大多数都很简单。如,输入!>变成\mapsto,输入->变成\to等等。

fun变成f:\R\to\R:,!>变成\mapsto,->变成\to,cc变成\suset。

lim变成\lim{n\to\infty},sum变成\sum{n=1}^{\infty},ooo变成\infty。

<>特定课程的片段

除了一些常用的片段,也可以针对特定的课程设定片段。例如,在量子力学这门课中,可以设定一些关于ra/ket符号的片段。

<a|→\ra{a}<ψ|→\ra{\psi}=""a="">→\ket{a}|ψ>→\ket{\psi}→\raket{a}{}

代码:

snippet"\<(.*?)\|""ra"riA \ra{`!psnip.rv=match.group(1).replace('q',f'\psi').replace('f',f'\phi')`} endsnippet snippet"\|(.*?)\>""ket"riA \ket{`!psnip.rv=match.group(1).replace('q',f'\psi').replace('f',f'\phi')`} endsnippet snippet"(.*)\\ra{(.*?)}([^\|]*?)\>""raket"riA `!psnip.rv=match.group(1)`\raket{`!psnip.rv=match.group(2)`}{`!psnip.rv=match.group(3).replace('q',f'\psi').replace('f',f'\phi')`} endsnippet

<>上下文

在编写这些片段时需要考虑的一件事是,“这些片段会与长与常用的文本冲突吗?”

例如,在英语中大约有72个单词包含sr,这意味着当输入disregard这个词时,sr会扩展到^2,出现一个di^2egard。

这个问题的解决方案是,为代码片段添加上下文。

通过使用Vim的语法突出显示,可以确定UltiSnips是否应该扩展片段,这取决于你使用的是数学还是文本。

gloal!p texMathZones=['texMathZone'+xforxin['A','AS','','S','C', '','D','DS','E','ES','F','FS','G','GS','H','HS','I','', 'J','JS','K','KS','L','LS','DS','V','W','X','Y','Z']] texIgnoreMathZones=['texMathText'] texMathZoneIds=vim.eval('map('+str(texMathZones)+",'hlID(v:val)')") texIgnoreMathZoneIds=vim.eval('map('+str(texIgnoreMathZones)+",'hlID(v:val)')") ignore=texIgnoreMathZoneIds[0] defmath(): synstackids=vim.eval("synstack(line('.'),col('.')-(col('.')>=2?1:0))") try: first=next( iforiinreversed(synstackids) ifiintexIgnoreMathZoneIdsoriintexMathZoneIds ) retnfirst!=ignore exceptStopIteration: retnFalse endgloal

现在,你可以将context“math()”添加到只希望在数学上下文中展开的片段中。

context"math()" snippetsr"^2"iA ^2 endsnippet

请注意,“数学上下文”是一个微妙的东西。有时你可以使用\text{…}在数学环境中添加一些文本。在这种情况下,你不需要扩展片段。但是,在以下情况下:\[\text{$...$}\],它们可以扩展。这就是为什么math上下文的代码有点复杂。下面的动图说明了这些微妙之处。

除了上述一些片段,你也可以根据自己的需要,来自己添加一些插件或者片段,来提高自己的效率。

<>用笔还是用电脑?

纯手打记下1700页数学笔记,awesome都不够形容了这位小哥了,堪称理工科学生中的“英雄”。

并非所有人都赞同小哥的做法,强大的高科技工具在传面前常常会被质疑。

有部分网友认为手写电脑打字印象深刻,而且要达到这位小哥的熟练程度,恐怕LaTeX和Vim得练习好几年。

既然用笔更方便,为什么还要用电脑来记笔记呢?原因很简单:字太丑!

如果记下来的内容连自己看的都没有,怎么复习课堂笔记呢?至少用电脑记下来的排版工整,让人赏心悦目。

虽然国外网友争论不休,但在国内只要一个条件就可以彻底否决这个方法:不让带电脑进课堂。

对此,你怎么看?

<>工具传送门:

Linux和Mac自带Vim。

Windows用户安装Vim:s://ftp.nluug.nl/pu/vim/pc/gvim81.exe

Vim插件:s://githu/junegunn/vim-plug

Vim上的LaTeX插件:s://githu/lervag/vimtex

窗口平铺器:s://githu/askerville/spwm

Vim片段工具:s://githu/SirVer/ultisnips

LaTeX常见数学符号输入方法:s://en.wikiooks.org/wiki/LaTeX/Mathemati

想要熟悉更多的LaTeX使用方法,就需要地学习,平时多加练习也必不可少。

博文链接:

s://cas.dev/post/lecte-notes-1/

—<>完—

量子位·QitAIվ'ᴗ'ի追踪AI技术和产品新动态

量子位

欢迎大家关注我们,以及订阅我们的知乎专栏

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/01/7259.html

分享给朋友:

相关文章

NAS那么好,为什么还是没能成为大多数家庭必备的存储设备?

NAS那么好,为什么还是没能成为大多数家庭必备的存储设备?

最主要原因是因为——贵! 看看我家里搭建的这一套吧。 目前我家中有5台常用的NAS,分别为群晖DS1522+、威联通TS-464C2、绿联DX4600 Pro 、极空间Z4S、威联通TS-AI642。个人认为,这其中的每台NAS都是时代…

用红米手机会很丢人吗?

前些日子遇到了一位快递小哥,京东的,签收 小哥年纪不算大,目测二十多岁 他的手机上全是一道道极严重的划痕,有点卡, 他开热点了,热点名就是手机型号,红米9a,我父母的同款 现在他那边操作了一会,然后又是我这边操作了一会 小哥看着我手机刷刷的…

有没有高手指点一下Google做SEO现在的技巧啊?心好累。

有没有高手指点一下Google做SEO现在的技巧啊?心好累。

搜索引擎优化 (SEO) 的目标是让 Google 在用户输入相关搜索查询时提供您的网页链接。 虽然没有固定的蓝图可以保证您获得最高排名,但有几种 SEO 最佳实践(您可以将其视为 SEO 规则)可以增加您在非付费结果中获得良好排名的机会。…

如何评价小米14pro顶配可以选配卫星通话,小米15全系都无法选配?

如何评价小米14pro顶配可以选配卫星通话,小米15全系都无法选配?

雷总不是说了吗,我可以不用,但你不能没有。市面上OPPO Find X8 Pro和vivo X200 Pro的卫星通信版分别加价300,而荣耀Magic7和Magic7 Pro有卫星通信版且不加价,荣耀更显诚意。 我觉得有是更好的,虽然使用…

为什么小公司留不住人?

为什么小公司留不住人?

我估计,整个知乎,可能没有比我公司再小得了,。。 正对面就是我唯一的一个员工的工位。 为啥留不住人。因为那些留不住人的老板,太拿自己当回事。 大公司靠制度。小公司靠人情。 我这儿的业务,因为全都是线上,所以员工来不来坐班都不重要。 天太…

抖音有3,4万粉丝能挣多少钱?

抖音有3,4万粉丝能挣多少钱?

如果在抖音有100万粉丝,一个月能赚多少钱你知道吗?直接说答案: 抖音有100万粉丝,可能1分钱也赚不到...那视频有100万点赞,能赚多少钱?可能也是1分钱都赚不到... 新手需要通过抖音变现 [文章: 做为新手玩抖音要注意什么?怎样才能…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。