敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註

曉查 乾明 發自 凹非寺

量子位 報道 | 公眾號 QbitAI

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

數學課上,全程鍵盤手打1700頁筆記。

速度緊追老師板書,公式、圖形一個不落。

效果?請看下圖:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


不僅排版媲美教科書,而且還能夠批註,檢索關鍵詞……

筆記被他Po到網上之後,便引來大量圍觀。

不到一天,相關推文就已經有2000多贊,Hacker News論壇上蓋了200多樓。

甚至有網友評論稱:“你就是我們需要的英雄!”

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

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


這位來自歐洲的小哥非常強烈安利Vim文本編輯器,他說:

用LaTeX寫數學公式,我選Vim編輯器。它強大、通用、可擴展性很強。只要是基於文本的任務我都用它,寫代碼、編輯LaTeX、寫markdown都是。

雖然入門階段的學習曲線超級陡峭,但只要掌握了基本的操作方式,就會欲罷不能。

下面就讓我們看一下他完成這一壯舉的具體流程,文中提到的工具下載地址,我們都附在了最後。

快速上手教程

我們先看看小哥的工作環境配置。

他用Vim編輯LaTeX的場景,就像下面這樣:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


左邊是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=0
set conceallevel=1
let g:tex_conceal='abdmg'

最後兩行控制的是“隱藏”功能。開啟了這個功能,除了你光標所在的那一行之外,文本里夾雜的LaTeX代碼就都會隱藏或者替換成其他符號。

比如說在下面動圖裡,隱藏了[,],$之後,沒有了它們的干擾,整個文檔就更易讀。這個功能還會用∩替代\bigcap,∈替代\in等等。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


設置完成,接下來就到了整個教程的精華所在:

用LaTeX記筆記,怎麼才能像老師寫板書一樣快?

這就是片段(snippets)發揮作用地方了。

片段

片段是什麼?

片段是一小段可複用的文本,由其他文本觸發。

例如,輸入sign,再按下Tab鍵,這個單詞就會自動擴展為一段簽名:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


片段也可以是動態的:輸入today並按下Tab鍵,它就會變成當前的日期。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


而輸入box按Tab,就會出現一個框,還會隨著輸入文字自動變大。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


片段,甚至可以嵌套在另一個片段裡用:

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


怎麼創建片段?使用UltiSnips

管理片段的插件UltiSnips,小哥是這樣配置的:

關於sign片段的代碼如下:

snippet sign "Signature"
Yours sincerely,
Gilles Castel
endsnippet

對於動態的片段,你可以將代碼放在``之間, 在片段擴展的時候,就會運行。下面的例子,就是用 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) + '┘'`
$0
endsnippet

這些 Python 代碼塊將被變量 snip.rv 的值替換。在這些代碼塊中,你可以訪問代碼段的當前狀態,例如t[1]包含第一個製表位,fn是當前文件名等等。

LaTex片段

使用片段編寫LaTeX,要比純手工編寫快得多。特別有些非常複雜的片段能幫你大大節約時間,有效防止抓狂。

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

環境

想插入一個環境,只需要在一行的開頭輸入beg。然後鍵入環境的名稱,這個名稱在\end{}命令中也是一樣。按下Tab鍵,就能夠將光標放置在新創建的環境中。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


這個片段的代碼如下:

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

其中,b表示這個片段只會在代碼行的開頭展開,A代表自動展開,也就是說不用按Tab鍵了。製表位(Tab stop)——也就是你可以通過按Tab 和Shift+Tab跳轉到的位置——用$1、 $2、......來表示,最後一個用$0。

行內和數學顯示

在記數學筆記的過程中,最常用的兩個片段是mk和dm。

它們負責啟動數學模式。第一個片段用於“行內數學”,第二個用於“顯示數學”。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


代碼行內的數學片段是“智能的”:它知道什麼時候在$符號後面直接輸入一個單詞,它會自動加個空格。但如果輸入一個非單詞的字符,它就不會添加空格了,比如在““$p$-value”情況下,是這樣的:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


這個片段的代碼如下:

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

第一行末尾的w,意味著這個片段會在單詞邊界處擴展,例如,hellomk不會擴展,但是hello mk會。

用於顯示數學的片段更簡單,也更加方便;有了它,你可能再也不會忘記用句號結束方程了。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


代碼:

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

小寫和上標

另一個很有用的片段就是下標。能夠把a1改為a1,把a_12改為a{12}。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


這個片段的觸發器是使用正則表達式。有兩種情況會擴展片段。一是你鍵入一個字符,後面跟著一個數字,比如[A-Za-z]\d;另一種是,一個字符後面有並跟著兩個數字,比如[A-Za-z]\d\d。

當你使用括號將正則表達式的一部分裝在一個組中時,例如(\d\d),你可以在 Python中通過match.group (i)來使用它們擴展片段。

至於上標,可以使用td,它就會變成^{}。然而,對於平方、立方和其他一些常見的片段,可以使用專門的代碼片段,如 sr、cb等等。

效果圖:

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


代碼:

snippet sr "^2" iA
^2
endsnippet
snippet cb "^3" iA
^3
endsnippet
snippet compl "complement" iA
^{c}
endsnippet
snippet td "superscript" iA
^{$1}$0
endsnippet

分數

分數是一個用起來最方便的一個片段,擴展的形式如下:

/ / → 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)}{
敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


第一個片段的代碼很簡單:

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

第二個和第三個示例,可以使用正則表達式來匹配3/、4ac/、6pi^2/、a2/等表達式。

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


看了上邊這些,你可能覺得正則表達式太難了。沒關係,下面有一個解釋得非常直觀的圖表:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


在第四和第五種示例下,要換一種方法。使用UltiSnips的正則表達式引擎解決不了的,Python可以:

這裡最後要分享的關於分數的片段,能根據你的選擇,來生成一個分數。

你可以先選擇一些文本,然後按Tab鍵,繼續輸入、然後再按Tab鍵。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


代碼中,使用${VISUAL}變量來表示所選的內容。

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

Sympy和Mathematica

還有一個很酷但用得不多的片段,是使用Sympy來計算數學表達式。例如,輸入sympy,然後按下Tab,可以擴展為sympy | sympy,輸入sympy 1 + 1 sympy,按下Tab,可以擴展為2。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


片段代碼:

nippet sympy "sympy block " w
sympy $1 sympy$0
endsnippet
priority 10000
snippet 'sympy(.*)sympy' "evaluate sympy" wr
`!p
from 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,也可以做類似的事情:


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


片段代碼:

priority 1000
snippet math "mathematica block" w
math $1 math$0
endsnippet
priority 10000
snippet 'math(.*)math' "evaluate mathematica" wr
`!p
import subprocess
code = '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}。.和,的順序沒關係,所以可以同時按下它們兩個。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


這些片段真的可以節省時間,可以按照和老師寫板書一樣的順序來記。

注意,bar和hat前綴也依然可以用,只要以較低的優先級添加它們就行。

這些片段的代碼是:

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


priority 10
snippet "hat" "hat" riA
\hat{$1}$0
endsnippet
priority 100
snippet "([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等等。


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


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


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


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


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


特定課程的片段

除了一些常用的片段,也可以針對特定的課程設定片段。例如,在量子力學這門課中,可以設定一些關於bra/ket符號的片段。

|ψ>→\ket{\psi}

→\braket{a}{b}

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


代碼:

snippet "\\bra{`!p snip.rv = match.group(1).replace('q', f'\psi').replace('f', f'\phi')`}
endsnippet
snippet "\|(.*?)\>" "ket" riA
\ket{`!p snip.rv = match.group(1).replace('q', f'\psi').replace('f', f'\phi')`}
endsnippet
snippet "(.*)\\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 !p
texMathZones = ['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 False
endglobal

現在,你可以將context “math()”添加到只希望在數學上下文中展開的片段中。

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

請注意,“數學上下文”是一個微妙的東西。 有時你可以使用\text{…}在數學環境中添加一些文本。在這種情況下,你不需要擴展片段。但是,在以下情況下: \[ \text{$...$} \],它們可以擴展。 這就是為什麼math上下文的代碼有點複雜。下面的動圖說明了這些微妙之處。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


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

用筆還是用電腦?

純手打記下1700頁數學筆記,awesome都不夠形容了這位小哥了,堪稱理工科學生中的“英雄”。

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註


並非所有人都贊同小哥的做法,強大的高科技工具在傳統面前常常會被質疑。

有部分網友認為手寫比電腦打字印象深刻,而且要達到這位小哥的熟練程度,恐怕LaTeX和Vim得練習好幾年。

既然用筆更方便,為什麼還要用電腦來記筆記呢?原因很簡單:字太醜!

敲代碼寫下1700頁數學筆記,速度堪比板書還支持搜索批註

如果記下來的內容連自己看的慾望都沒有,怎麼複習課堂筆記呢?至少用電腦記下來的排版工整,讓人賞心悅目。

雖然國外網友爭論不休,但在國內只要一個條件就可以徹底否決這個方法:不讓帶電腦進課堂。

對此,你怎麼看?

工具傳送門:

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/


分享到:


相關文章: