1700頁數學筆記火了!全程敲代碼,速度飛快,硬核小哥教你上手

2021-01-10 量子位

曉查 乾明 發自 凹非寺 量子位 報導 | 公眾號 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 = '<tab>'let g:UltiSnipsJumpForwardTrigger = '<tab>'let g:UltiSnipsJumpBackwardTrigger = '<s-tab>'

關於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)`endsnippetsnippet '([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^2endsnippetsnippet cb "^3" iA^3endsnippetsnippet compl "complement" iA^{c}endsnippetsnippet 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$0endsnippetpriority 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$0endsnippetpriority 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}$0endsnippetpriority 100snippet "([a-zA-Z])bar" "bar" riA\overline{`!p snip.rv=match.group(1)`}endsnippet

priority 10snippet "hat" "hat" riA\hat{$1}$0endsnippetpriority 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符號的片段。

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

代碼:

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/

相關焦點

  • 全程快捷鍵給1700頁數學筆記配圖!硬核小哥上手LaTeX+Inkscape
    之前,我們介紹了一位神奇的本科生,他在數學課上用Vim+LaTeX,全程手打出1700頁課堂筆記,速度直追老師的板書。現在,這位Gilles小哥又開課了,上次他只教了大家手打公式的方法,這次他展示了數學筆記裡的畫圖技巧。他用到的神器是Inkscape+LaTeX,再加上自定義的快捷鍵,一個Ctrl+F,直接完成原來的六個步驟。
  • 幾行Matlab代碼教你上手傅立葉變換
    直接開始,如果你不熟悉Matlab,可以將代碼直接複製到編輯區,然後回車看結果就可以了。
  • 為何敲代碼,學好數學很重要?
    數學允許你推理邏輯結構,而不受其他約束的影響。這也是編程所需要的:創建邏輯系統來解決問題。我們來看一下編程的基本模式:找出問題所在設計算法和數據結構來解決它實現和測試在實踐中,工作往往組織得不是那麼好,因為步驟之間存在相互作用。你可以編寫代碼來通知別人設計方面的問題。可即便如此,上面這個基本模式也一遍又一遍地在實踐中重現。
  • 學霸教你如何做筆記,省時又高效
    俗話說好記性不如爛筆頭,學習筆記相信每個人都做過。那麼,天天做筆記,你就真的會做筆記嗎?做筆記就是一字不漏地抄老師的板書?做筆記就是把所有知識都寫在筆記本上,厚厚的幾本,就像一類手寫體教科書?這些都是做筆記的誤區!筆記做好了,將是提升學習成績的一大利器。
  • 302頁吳恩達Deeplearning.ai課程筆記,詳記基礎知識與作業代碼
    原標題:302頁吳恩達Deeplearning.ai課程筆記,詳記基礎知識與作業代碼 機器之心整理 作者:Wan近日,來自重慶大學的 Wan Zhen 製作了一份深度學習專項課程筆記,該筆記從神經網絡與深度學習基礎、提升深度神經網絡性能和卷積神經網絡三門課程出發詳細解釋了關鍵概念與作業代碼。本文概括性地介紹了這三課的主要內容,並選擇每個課程主題比較有意思的知識點進行介紹。
  • 十個中文例程教會你輕鬆上手製作Arduino智能小車
    你可以自己自己動手製作,也可以購買成品套裝;Arduino所使用到的軟體都可以免費下載。硬體參考設計 (CAD 文件)也是遵循availableopen-source協議, 你可以非常自由地根據你自己的要求去修改他們。本文精選了Arduino教程、例程、設計案例,集結了國內外官方資料和資深工程師的經驗,是學習AArduino的必備寶典。
  • 全程教你操作,看一次就會!
    全程教你操作,看一次就會!製作一個圓球,並沒有什麼難度,但要製作出質量規格都符合標準的圓球,卻有點難度的,但對於老外們來說,這都不是什麼事,前一秒,有木匠拿木頭製作圓球,後一秒,又有老外用錫紙製作圓球。
  • 「1028」頁高考物理備考攻略+考綱解讀+糾錯筆記+真題演練!
    敲黑板~今天就給同學們整理了高中物理的備考攻略,其中包括基礎知識、考綱解讀、糾錯筆記、經典例題、歷年真題、各地區的考卷等等!同時給大家附上解析,詳細到每一步的解法!一共1028頁!包括但不限於高中三年重點,這三年的物理有它勝過任何的資料!由於篇幅限制,只能發出部分截圖,所以想要提高物理成績的同學就要抓緊了,無論是高一高二抓住物理基礎,還是高三複習衝刺,一定要它的幫助!
  • 高考數學丨「全國卷」壓軸解答題解題策略+58頁導數解題筆記
    全國卷對於導數應用的考查,其難點一直圍繞函數的單調性、極值和最值展開,以導數為工具探究函數的性質,藉此研究不等式、方程等問題,著重考查分類討論、數形結合、化歸與轉化的數學思想方法,意在考查學生的運算求解能力、推理論證能力,充分體現數學理性思維的特點,從思維的層次性、深刻性和創新性等方面進行考查
  • 資料| 1800頁33章數學方法精要筆記 —深入數學建模, 機器學習和...
    from=leiphonecolumn_res07091 書籍介紹  · · · · · ·在信息爆炸的當今,大到企業巨頭的經營方向, 小到和日常生活相關的人工駕駛等領域,數學建模和人工智慧都對信息數據的收集、處理、解釋以及做出決策將起到至關重要的作用。負責開發模型和算法的一線科學家和工程師, 都需要有堅實的數學基礎。
  • 《方舟生存進化》恐龍筆記方位代碼大全 包含孤島和焦土筆記
    導 讀 第1頁:恐龍名稱 展開 《方舟生存進化》中有很多恐龍,今天小編為大家帶來了「最終生命體」《方舟生存進化》恐龍筆記方位代碼大全 包含孤島和焦土筆記,想要快速找到恐龍的玩家
  • 康奈爾法、思維導圖法等做筆記,提高做筆記效率!看完還想再寫三頁
    還可以酌情增加一部分頁面來記錄反饋,如在《微習慣》中我預留出一頁空白用來記錄自己的實踐反饋效果。——文學院張藝線性代數作為一名線性代數的入門級學生,有些剛剛接觸的定義非常重要,這時就需要將定義全部抄下來。這個「抄」可有點不同,要找出整個句子或者段落的「主謂賓」,最後畫出一個小型框架,把內容填進去。
  • 中國第一代程式設計師裡的「四大天王」,30年前敲代碼,現狀如何?
    網際網路來中國的時間不長,平時接觸的程式設計師敲代碼超過十年以上的也是少數,在為自己擔心的時候,不妨看一下中國的第一代程式設計師們的現狀,他們從1988年開始敲代碼,如今也已經有了三十年的經驗當時的他們名震世界,如今卻差距太大,有的人身價千億、有的人財務自由瀟灑過生活、有的人卻被掃地出門黯然離場。
  • 500頁內容帶你上手最流行框架
    全書約 500 頁,包含 15 個章節,內容詳實,圖文並茂。這本書為使用 PyTorch 構建和訓練神經網絡提供了詳細且易於上手的教程,使用的程式語言為 Python。>學習的機制使用神經網絡擬合數據使用卷積執行泛化現實示例:構建用於癌症檢測的神經網絡部署到生產環境詳細目錄如下所示:書籍特點:圖文並茂,代碼豐富
  • word最後一頁空白頁怎麼刪除 手把手教你如何刪除Word最後一頁空白頁
    word最後一頁空白頁怎麼刪除 手把手教你如何刪除Word最後一頁空白頁時間:2017-06-14 13:53   來源:系統天堂   責任編輯:沫朵 川北在線核心提示:原標題:word最後一頁空白頁怎麼刪除 手把手教你如何刪除Word最後一頁空白頁 用過word的朋友都知道,word最後一頁常常出現空白頁。
  • 兩度破譯「白宮密碼」,卻稱自己是抱娃敲代碼的普通媽媽
    抱娃敲代碼最讓王小雲崩潰的是,研究生畢業前夕,在導師——著名數學家潘承洞院士、於秀源教授的建議下,她放棄了「解析數學」的成果,開始研究一個新興的「密碼學」。那十年,當別人在為了評職稱、拿獎勵,不斷想辦法發表「注水」論文的時候,王小雲在不斷敲代碼
  • WGCNA新手入門筆記(含代碼和數據)
    加權基因共表達網絡分析(WGCNA,Weighted gene co-expression network analysis)是一個很火的生信分析方法讓大家能夠入門WGCNA進行實操是我整理這一學習筆記的最終目的。筆記內容涉及到WGCNA的簡介,安裝運行,代碼解析和靈活變換,跑出的圖有什麼意義等,準備分3-4次說。WGCNA能夠從複雜數據中(N多分組)快速地提取出與樣本特徵相關的基因共表達模塊,以供後續分析。
  • 糖炒板慄不用買,教你個省事又好吃的方法,簡單易學好上手
    美食是生活美好的魔法料理,願你不被時間和社會束縛,幸福地填飽肚子,美味能夠最大程度的治癒一個人,新的一天從美食開始。歡迎來到魔法飼料。倒入清水道快沒過晚年,用勺子把彈藥講話,大火把水煮開後轉中火,蓋上鍋蓋煮15分鐘。時間差不多後可以看到板慄都煮開,可水也基本煮幹了。這時打開鍋蓋不停翻動,讓糖漿裹到板慄上,每顆板慄都金黃油亮就可以關火了,把地中間劃開一刀更方便,剝殼也熟得更快,白糖也可以用蜂蜜來代替。