晓查 乾明 发自 凹非寺 
转自: 量子位 | 公众号 QbitAI

又出现一位“神仙”本科生!

数学课上,全程键盘手打1700页笔记。

速度紧追老师板书,公式、图形一个不落。

效果?请看下图:

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

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

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

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

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

这位来自欧洲的小哥非常强烈安利Vim文本编辑器,他说:

用LaTeX写数学公式,我选Vim编辑器。它强大、通用、可扩展性很强。只要是基于文本的任务我都用它,写代码、编辑LaTeX、写markdown都是。

虽然入门阶段的学习曲线超级陡峭,但只要掌握了基本的操作方式,就会欲罢不能。

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

快速上手教程

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

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

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

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

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

Plug 'lervag/vimtex'let g:tex_flavor='latex'let g:vimtex_view_method='zathura'let g:vimtex_quickfix_mode=0set conceallevel=1let g:tex_conceal='abdmg'

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

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

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

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

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

片段

片段是什么?

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

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

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

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

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

怎么创建片段?使用UltiSnips

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

Plug 'sirver/ultisnips'let g:UltiSnipsExpandTrigger = ''let g:UltiSnipsJumpForwardTrigger = ''let g:UltiSnipsJumpBackwardTrigger = ''

关于sign片段的代码如下:

snippet sign "Signature"Yours sincerely,

Gilles Castelendsnippet

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

snippet today "Date"`date +%F`endsnippet

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

snippet box "Box"`!p snip.rv = '┌' + '─' * (len(t[1]) + 2) + '┐'`│ $1 │`!p snip.rv = '└' + '─' * (len(t[1]) + 2) + '┘'`$0endsnippet

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

LaTex片段

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

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

环境

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

这个片段的代码如下:

snippet beg "begin{} / end{}" bA\begin{$1}    $0\end{$1}endsnippet

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

行内和数学显示

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

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

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

这个片段的代码如下:

snippet mk "Math" wA$${1}$`!pif t[2] and t[2][0] not in [',', '.', '?', '-', ' ']:    snip.rv = ' 'else:    snip.rv = ''`$2endsnippet

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

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

代码:

snippet dm "Math" wA\[$1.\] $0endsnippet

小写和上标

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

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

snippet '([A-Za-z])(\d)' "auto subscript" wrA`!p snip.rv = match.group(1)`_`!p snip.rv = match.group(2)`endsnippet

snippet '([A-Za-z])_(\d\d)' "auto subscript2" wrA`!p snip.rv = match.group(1)`_{`!p snip.rv = match.group(2)`}endsnippet

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

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

效果图:

代码:

snippet sr "^2" iA^2endsnippet

snippet cb "^3" iA^3endsnippet

snippet compl "complement" iA^{c}endsnippet

snippet td "superscript" iA^{$1}$0endsnippet

分数

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

/ / → frac {}{}
3 / → frac {3}{}
4 pi ^ 2 / → frac {4 pi ^ 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}$0endsnippet

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

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

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

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

priority 1000snippet '^.*\)/' "() Fraction" wrA`!pstripped = match.string[:-1]depth = 0i = len(stripped) - 1while True:    if stripped[i] == ')': depth += 1    if stripped[i] == '(': depth -= 1    if depth == 0: break;    i -= 1snip.rv = stripped[0:i] + "\\frac{" + stripped[i+1:-1] + "}"`{$1}$0endsnippet

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

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

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

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

Sympy和Mathematica

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

片段代码:

snippet sympy "sympy block " wsympy $1 sympy$0endsnippet

priority 10000snippet 'sympy(.*)sympy' "evaluate sympy" wr`!pfrom sympy import *x, y, z, t = symbols('x y z t')k, m, n = symbols('k m n', integer=True)f, g, h = symbols('f g h', cls=Function)init_printing()snip.rv = eval('latex(' + match.group(1).replace('\\', '') \    .replace('^', '**') \    .replace('{', '(') \    .replace('}', ')') + ')')`endsnippet

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

片段代码:

priority 1000snippet math "mathematica block" wmath $1 math$0endsnippet

priority 10000snippet 'math(.*)math' "evaluate mathematica" wr`!pimport subprocesscode = 'ToString[' + match.group(1) + ', TeXForm]'snip.rv = subprocess.check_output(['wolframscript', '-code', code])`endsnippet

后缀片段

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

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

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

这些片段的代码是:

priority 10snippet "bar" "bar" riA\overline{$1}$0endsnippet

priority 100snippet "([a-zA-Z])bar" "bar" riA\overline{`!p snip.rv=match.group(1)`}endsnippet
priority 10snippet "hat" "hat" riA\hat{$1}$0endsnippet

priority 100snippet "([a-zA-Z])hat" "hat" riA\hat{`!p snip.rv=match.group(1)`}endsnippet
snippet "(\\?\w+)(,\.|\.,)" "Vector postfix" riA\vec{`!p snip.rv=match.group(1)`}endsnippet 

其他片段

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

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

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

特定课程的片段

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

→\ket{a}
|ψ>→\ket{\psi}
→\braket{a}{b}

代码:

snippet "\ "bra" riA\bra{`!p snip.rv = match.group(1).replace('q', f'\psi').replace('f', f'\phi')`}endsnippetsnippet "\|(.*?)\>" "ket" riA\ket{`!p snip.rv = match.group(1).replace('q', f'\psi').replace('f', f'\phi')`}endsnippetsnippet "(.*)\\bra{(.*?)}([^\|]*?)\>" "braket" riA`!p snip.rv = match.group(1)`\braket{`!p snip.rv = match.group(2)`}{`!p snip.rv = match.group(3).replace('q', f'\psi').replace('f', f'\phi')`}endsnippet

上下文

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

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

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

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

global !ptexMathZones = ['texMathZone'+x for x in ['A', 'AS', 'B', 'BS', 'C','CS', 'D', 'DS', 'E', 'ES', 'F', 'FS', 'G', 'GS', 'H', 'HS', 'I', 'IS','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]

def math():    synstackids = vim.eval("synstack(line('.'), col('.') - (col('.')>=2 ? 1 : 0))")    try:        first = next(            i for i in reversed(synstackids)            if i in texIgnoreMathZoneIds or i in texMathZoneIds        )        return first != ignore    except StopIteration:        return Falseendglobal

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

context "math()"snippet sr "^2" iA^2endsnippet

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

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

用笔还是用电脑?

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

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

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

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

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

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

对此,你怎么看?

工具传送门:

Linux和Mac系统自带Vim。

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

Vim插件管理:
https://github.com/junegunn/vim-plug

Vim上的LaTeX插件:
https://github.com/lervag/vimtex

窗口平铺管理器:
https://github.com/baskerville/bspwm

管理Vim片段工具:
https://github.com/SirVer/ultisnips

如果你用不惯Vim,还有Emacs、Atom、VS Code、Sublime,它们都有LaTeX插件,总有一款文本编辑器适合你。

LaTeX常见数学符号输入方法:
https://en.wikibooks.org/wiki/LaTeX/Mathematics

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

博文链接:

https://castel.dev/post/lecture-notes-1/

专注于数据科学领域的知识分享

欢迎在文章下方留言与交流

Python数据科学【读者福利】

【知识星球】:Python数据科学学习社区

推荐阅读

使用K-Means算法将图像压缩6倍!

备战春招 | 数据科学&机器学习面试题,来挑战吧~

备战春招 | 120 道机器学习面试题!

下载 | 风控大牛手把手教你搭建企业级信用评分模型

数据科学家需要掌握的几大命令行骚操作

带领拼多多超越京东后,黄峥依旧不想“搭理”五环内人群

latex 上标_1700页数学笔记火了!全程敲代码,速度飞快易搜索,硬核小哥教你上手LaTeX+Vim...相关推荐

  1. 1700 页数学笔记火了!全程敲代码,速度飞快易搜索,硬核小哥教你上手 LaTeX+Vim...

    点击"小詹学Python",选择"星标"公众号 重磅干货,第一时间送达 本文转载自量子位,禁二次转载 又出现一位"神仙"本科生! 数学课上, ...

  2. 全程快捷键!硬核小哥超快配图1700页数学笔记,教你上手LaTeX+Inkscape

    边策 乾明 发自 凹非寺  量子位 报道 | 公众号 QbitAI 之前,我们介绍了一位神奇的本科生,他在数学课上用Vim+LaTeX,全程手打出1700页课堂笔记,速度直追老师的板书. 现在,这位G ...

  3. LaTeX+Vim 数学笔记

    又出现一位"神仙"本科生! 数学课上,全程键盘手打1700页笔记. 速度紧追老师板书,公式.图形一个不落. 效果?请看下图: 不仅排版媲美教科书,而且还能够批注,检索关键词-- 笔 ...

  4. 如何搭建最舒适的PC数学笔记环境

    如何搭建最舒适的PC数学笔记环境 很多时候我们需要输入大量的公式的时候,latex可以说是首选,习惯latex后,全程键盘敲入的快感和效率是mathtype等公式编辑器不能比拟的,特别是最近两年各种论 ...

  5. 外卖小哥用计算机,阿里公布全球数学大赛答案一题可帮上千万外卖小哥提效30%...

    9月28日,阿里巴巴在全球数学比赛官网公布了大赛的官方参考答案. 这次数学大赛引发社会强烈关注.截至9月20日上午9点,组委会已经收到近4万全球参赛者的报名,共吸引了来自哈佛大学.麻省理工学院.清华大 ...

  6. 700 页的机器学习笔记火了!完整版开放下载

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 作者       梁劲(Jim Liang),来自SAP(全球第一大商业软件公司). 书籍特点       条理清晰 ...

  7. 700 页的机器学习笔记火啦,图文生动形象

    为了方便大家学习,我们已经准备好了完整版的机器学习笔记PDF,感兴趣的同学可以直接下载 链接: 百度网盘 请输入提取码 提取码: ie8i 作者介绍了常用的算法,包括:   线性回归 逻辑回归 神经网 ...

  8. 520 页机器学习笔记!图文并茂可能更适合你

    点击上方"小詹学Python","星标"公众号 重磅干货,第一时间送达 本文经机器之心授权转载,禁二次转载 前段时间,来自SAP(全球第一大商业软件公司)的梁劲 ...

  9. 超给力的 520 页机器学习笔记!图文并茂可能更适合你,文末附下载方法

    点击"开发者技术前线",选择"星标????" 在看|星标|留言,  真爱 来自:AI派 前段时间,来自SAP(全球第一大商业软件公司)的梁劲(Jim Liang ...

最新文章

  1. 在mysql中创建表的命令行_如何在命令行创建一个MySQL数据库
  2. java date sql和_Java.util.date 与 java.sql.date区别和转换
  3. python函数与函数式编程
  4. 饥荒海难创建显示专用服务器,饥荒创建世界时一直显示启动服务器 | 手游网游页游攻略大全...
  5. c语言中aver是什么意思_Linux系统top命令中的io使用率,到底是什么意思?
  6. Zookeeper的内存数据和持久化
  7. 写入word_E016 如何把Word文字信息批量写入文本文件
  8. torch nn.MaxPool2d
  9. 用Emmet写前端代码
  10. 头条搜索已经全面上线,会不会成为下一个流量风口
  11. Linux Device Tree
  12. mysql将一个表的字段更新到另一个表中
  13. 微软ios服务器,iOS 客户端入门
  14. font color=red[置顶]/font
  15. windows安装OHS(weblogic管理)
  16. 智变·人工智能革新客服行业
  17. 如何提高项目估算精准度?关键看5大影响因子
  18. 密码学——RSA加密算法
  19. Linux系统下nohup日志文件按日期分割展示
  20. Java基础项目实战--大学生求职招聘信息网站系统

热门文章

  1. 使用第三方平台短信接口实现发送验证码
  2. 一个蛮好的测试软件,测试你是否具有超级预测力
  3. 外卖与打车派单逻辑谁更复杂
  4. InnoDB中的索引
  5. 石家庄:市环保局长解析持续雾霾天气原因 2013-02-05 来源:搜狐网
  6. Hdoj 2717.Catch That Cow 题解
  7. 蒸汽机器人布里茨天赋_lol蒸汽机器人布里茨出装_布里茨符文天赋加点_布里茨攻略视频图片-红瀚达电竞网...
  8. 最全面的Android热修复技术
  9. 看浙商老板的27条创业思维,终于明白马云为什么能这么成功
  10. 设计模式之略见一斑(外观模式Facade)