Vor einiger Zeit habe ich bei Quora die Frage beantwortet:
Wie kann ich
mit den Vorlesungsskripten in Mathematik auf LaTeX Schritt halten? Dort erklĂ€rte ich meinen Notizen-Workflow in LaTeX mit Vim und Inkscape (fĂŒr Zeichnungen). Aber seitdem hat sich viel geĂ€ndert, deshalb möchte ich mehrere Blog-BeitrĂ€ge mit einer Beschreibung des neuen Prozesses veröffentlichen. Dies ist der erste Artikel.
Ich habe im zweiten Semester eines Mathematikkurses angefangen, mit LaTeX Notizen zu machen, und seitdem habe ich ĂŒber 1700 Seiten geschrieben. Hier einige Beispiele, wie die Zusammenfassung aussieht:



Diese Notizen, einschlieĂlich Zeichnungen, werden direkt in der Vorlesung erstellt und anschlieĂend nicht bearbeitet. Um Abstracts effizient in LaTeX zu schreiben, mĂŒssen vier Regeln befolgt werden:
- Das Schreiben von Text und Formeln in LaTeX sollte so schnell sein wie das Schreiben eines Dozenten an die Tafel: Die Verzögerung ist nicht akzeptabel.
- Das Zeichnen von Illustrationen sollte fast so schnell sein wie das des Dozenten.
- Das Verwalten von Notizen, dh das HinzufĂŒgen von Notizen, das Anordnen aller Notizen, die letzten beiden Vorlesungen, das Suchen von Notizen usw. sollte schnell und einfach sein.
- Es sollte möglich sein, PDF-Dokumente mit LaTeX zu kommentieren, wenn ich eine Notiz mit einem PDF-Dokument schreiben möchte.
In diesem Artikel geht es um den ersten Punkt: Notizen zu LaTeX machen.
Vim und LaTeX
Um Text und mathematische Formeln auf LaTeX zu schreiben, verwende ich Vim. Dies ist ein leistungsstarker Allzweck-Texteditor, der in hohem MaĂe erweiterbar ist. Ich benutze es, um Code, LaTeX, Markdown-Text ... im Allgemeinen alle Texte zu schreiben. Er hat eine ziemlich steile Lernkurve, aber wenn Sie die Basis beherrschen, ist es bereits schwierig, ohne die ĂŒblichen Tastenkombinationen zum Editor zurĂŒckzukehren. So sieht mein Bildschirm aus, wenn ich ein LaTeX-Dokument bearbeite:

Auf der linken Seite befindet sich Vim und auf der rechten Seite der
Zathura PDF-Viewer, der auch TastaturkĂŒrzel im Vim-Stil unterstĂŒtzt. Ich arbeite in Ubuntu mit dem
bspwm Window Manager. Als Plugin hat LaTeX
vimtex installiert. Es bietet Syntaxhervorhebung, Inhaltsverzeichnis, Synctex usw. Mit dem
vim-plug habe ich es wie folgt konfiguriert:
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'
Die letzten beiden Zeilen passen die Verkleidung an. Dies ist eine Funktion, bei der der LaTeX-Code ersetzt wird oder unsichtbar wird, wenn sich der Cursor nicht in dieser Zeile befindet. Wenn Sie
\ [
,
\]
,
$
ausblenden, sind sie nicht so auffĂ€llig, wodurch Sie einen besseren Ăberblick ĂŒber das Dokument erhalten. Diese Funktion ersetzt auch
\bigcap
durch
â©
,
\in
durch
â
usw., wie in der Animation gezeigt:

Mit dieser Einstellung können Sie die Aufgabe erfĂŒllen: Schreiben Sie auf LaTeX so schnell, wie ein Dozent an die Tafel schreibt. Hier kommen Schnipsel ins Spiel.
Schnipsel
Was ist ein Ausschnitt?
Ein Snippet ist ein kurzes StĂŒck wiederverwendbaren Textes, das von einem anderen Text aufgerufen wird. Wenn Sie beispielsweise ein Zeichen eingeben und die Tabulatortaste drĂŒcken, wird das Wortzeichen zu einer Signatur:

Snippets können dynamisch sein: Wenn ich
today
tippe und die
Tab
drĂŒcke, wird das Wort
today
durch das aktuelle Datum ersetzt, und das
box
Tab
wird zu einem Feld, dessen GröĂe automatisch zunimmt.


Sie können sogar ein Snippet in einem anderen verwenden:

Erstellen von Snippets mit UltiSnips
Um Snippets zu steuern, verwende ich das
UltiSnips- Plugin. Hier ist seine Konfiguration:
Plug 'sirver/ultisnips' let g:UltiSnipsExpandTrigger = '<tab>' let g:UltiSnipsJumpForwardTrigger = '<tab>' let g:UltiSnipsJumpBackwardTrigger = '<s-tab>'
Code fĂŒr das Snippet-
sign
:
snippet sign "Signature" Yours sincerely, Gilles Castel endsnippet
Bei dynamischen Snippets können Sie den Code zwischen die AnfĂŒhrungszeichen setzen. Dieser Code wird ausgefĂŒhrt, wenn das Snippet erweitert wird. Hier habe ich bash verwendet, um das aktuelle Datum zu formatieren:
date + %F
snippet today "Date" `date +%F` endsnippet
Innerhalb des
`!p ... `
-Blocks können Sie in Python schreiben. Schauen Sie sich den Code fĂŒr das
box
Snippet an:
snippet box "Box" `!p snip.rv = 'â' + 'â' * (len(t[1]) + 2) + 'â'` â $1 â `!p snip.rv = 'â' + 'â' * (len(t[1]) + 2) + 'â'` $0 endsnippet
Anstelle dieses Codes wird der Wert der Variablen
snip.rv
in das Dokument eingefĂŒgt. Innerhalb der Blöcke haben Sie Zugriff auf den aktuellen Status des Snippets. Beispiel:
t[1]
entspricht der Position der ersten Registerkarte,
fn
aktuellen Dateinamen usw.
LaTeX-Snippets
Snippets beschleunigen die Arbeit erheblich, insbesondere einige der komplexeren Snippets. Beginnen wir mit dem einfachsten.
Die Umwelt
Um eine Umgebung einzufĂŒgen, geben Sie am Anfang der Zeile
beg
. Dann der Name der Umgebung, der sich im Befehl
\end{}
widerspiegelt. Durch DrĂŒcken der
Tab
der Cursor eingefĂŒgt.

Der Code lautet wie folgt:
snippet beg "begin{} / end{}" bA \begin{$1} $0 \end{$1} endsnippet
Das Symbol
b
bedeutet, dass ein solches Snippet nur am Anfang einer Zeile funktioniert.
A
bedeutet automatische Erweiterung, dh Sie mĂŒssen nicht die
Tab
drĂŒcken. Tabs, auf die Sie durch DrĂŒcken von
Tab
und
Shift
+
Tab
werden als
$1
,
$2
, ... und letzteres als
$0
.
Inline- und Anzeigeformeln
Die beiden am hÀufigsten verwendeten Snippets sind
mk
und
dm
, die den Mathematikmodus auslösen. Die erste fĂŒr Inline-Formeln, die zweite fĂŒr angezeigte.

Intelligentes Formel-Snippet: Er weiĂ, wann ein Leerzeichen nach dem Dollarzeichen eingefĂŒgt werden muss. Wenn ich unmittelbar nach dem SchlieĂen von $ mit der Eingabe eines Wortes beginne, wird ein Leerzeichen hinzugefĂŒgt. Wenn ich jedoch ein anderes Zeichen eingebe, wird kein Leerzeichen hinzugefĂŒgt, wie im Fall von '$ p $ -Wert'.

Der Code fĂŒr dieses Snippet lautet:
snippet mk "Math" wA $${1}$`!p if t[2] and t[2][0] not in [',', '.', '?', '-', ' ']: snip.rv = ' ' else: snip.rv = '' `$2 endsnippet
W
am Ende der ersten Zeile bedeutet, dass sich das Snippet nur an Wortgrenzen ausdehnt. Daher
hellomk
beispielsweise
hellomk
nicht und
hello mk
funktioniert nicht.
Das Snippet fĂŒr die angezeigten Formeln ist einfacher, aber auch sehr praktisch. Die Gleichungen enden immer mit einem Punkt.

<snippet dm "Math" wA \[ $1 .\] $0 endsnippet
Tiefgestellte und hochgestellte Zeichen
Ein weiteres nĂŒtzliches Snippet ist fĂŒr Indizes. Es Ă€ndert
a1
in
a_1
und
a_12
in
a_{12}
.

Der Code fĂŒr dieses Snippet verwendet einen regulĂ€ren Ausdruck als Auslöser. Es erweitert das Fragment, wenn Sie ein Zeichen gefolgt von einer als
[A-Za-z]\d
codierten Ziffer oder ein Zeichen gefolgt von
_
und zwei Ziffern eingeben:
[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
Wenn Sie Teile eines regulÀren Ausdrucks in Klammern zu einer Gruppe zusammenfassen, z. B.
(\d\d)
, können Sie sie in der Snippet-Erweiterung ĂŒber
match.group(i)
in Python verwenden.
FĂŒr hochgestellte Zeichen verwende ich
td
, das sich in
^{}
verwandelt. Obwohl fĂŒr die hĂ€ufigsten (Quadrat, WĂŒrfel und mehrere andere) separate Snippets vorgesehen sind, wie z. B.
sr
,
cb
und
comp
.

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
Bruchteil
Eines der bequemsten Snippets arbeitet mit BrĂŒchen. Er macht folgende Ersetzungen:
//
â
\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)}{}

Zum ersten ein einfacher Code:
snippet // "Fraction" iA \\frac{$1}{$2}$0 endsnippet
Die zweite und dritte Substitution erfolgen mit Hilfe von regulĂ€ren AusdrĂŒcken, die den AusdrĂŒcken
3/
,
4ac/
,
6\pi^2/
,
a_2/
usw. entsprechen.
snippet '((\d+)|(\d*)(\\)?([A-Za-z]+)((\^|_)(\{\d+\}|\d))*)/' "Fraction" wrA \\frac{`!p snip.rv = match.group(1)`}{$1}$0 endsnippet
Wie Sie sehen können, können regulĂ€re AusdrĂŒcke ziemlich lang werden, aber hier ist ein Diagramm, das alles erklĂ€ren sollte:

Im vierten und fĂŒnften Fall versucht das Snippet, die entsprechende Klammer zu finden. Da die Regex-Engine von UltiSnips nicht weiĂ, wie das geht, musste ich Python verwenden:
priority 1000 snippet '^.*\)/' "() Fraction" wrA `!p stripped = match.string[:-1] depth = 0 i = len(stripped) - 1 while True: if stripped[i] == ')': depth += 1 if stripped[i] == '(': depth -= 1 if depth == 0: break; i -= 1 snip.rv = stripped[0:i] + "\\frac{" + stripped[i+1:-1] + "}" `{$1}$0 endsnippet
SchlieĂlich möchte ich ein Snippet freigeben, das die aktuelle Auswahl in einen Bruchteil verwandelt. WĂ€hlen Sie den Text aus, drĂŒcken Sie die
Tab
, geben Sie
/
und erneut die
Tab
.

Der Code verwendet die Variable
${VISUAL}
, die Ihre Auswahl widerspiegelt.
snippet / "Fraction" iA \\frac{${VISUAL}}{$1}$0 endsnippet
Sympy und Mathematica
Ein anderes cooles, aber weniger verwendetes Snippet fĂŒhrt
Sympy aus , um mathematische AusdrĂŒcke auszuwerten. Beispiel:
sympy
Tab
zu
sympy | sympy
sympy | sympy
und
sympy 1 + 1 sympy
Tab
wird zu
2
.

snippet 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('xyz t') k, m, n = symbols('km n', integer=True) f, g, h = symbols('fg h', cls=Function) init_printing() snip.rv = eval('latex(' + match.group(1).replace('\\', '') \ .replace('^', '**') \ .replace('{', '(') \ .replace('}', ')') + ')') ` endsnippet
FĂŒr Mathematica ist auch etwas Ăhnliches möglich:

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
Postfix-Snippets
Es scheint mir erwĂ€hnenswert, auch Postfix-Snippets zu erwĂ€hnen, die nach Eingabe bestimmter Zeichen den entsprechenden Text einfĂŒgen. Zum Beispiel
phat
â
\hat{p}
und
zbar
â
\overline{z}
. Ein Ă€hnliches Snippet fĂŒgt einen Vektor ein, zum Beispiel
v,.
â
\vec{v}
und
v.,
â
\vec{v}
. Die Reihenfolge von Punkt und Semikolon spielt keine Rolle, so dass ich sie gleichzeitig anklicken kann. Diese Schnipsel sparen wirklich Zeit, da Sie sie mit der gleichen Geschwindigkeit eingeben, mit der ein Dozent an die Tafel schreibt.

Beachten Sie, dass die
bar
und HutprĂ€fixe weiterhin funktionieren, nur mit einer niedrigeren PrioritĂ€t. Der Code fĂŒr diese Snippets lautet:
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
Andere Schnipsel
Ich habe immer noch ungefÀhr hundert hÀufig verwendete Schnipsel. Alle von ihnen sind
hier verfĂŒgbar. Die meisten von ihnen sind ziemlich einfach. Zum Beispiel
!>
Wird zu
\mapsto
,
->
wird zu
\to
usw.

fun
verwandelt sich in
f: \R \to \R :
,
!>
â
\mapsto
,
cc
â
\subset
.

lim
wird zu
\lim_{n \to \infty}
,
sum
â
\sum_{n = 1}^{\infty}
,
ooo
â
\infty
.


Kursspezifische Schnipsel
Neben hÀufig verwendeten habe ich auch spezielle Schnipsel. Sie werden als einzelne Zeile in
.vimrc
:
set rtp+=~/current_course
Hier ist
current_course
ein
symbolischer Link zum aktuellen Kurs (mehr dazu in einem anderen Artikel). In diesem Ordner befindet sich die Datei
~/current_course/UltiSnips/tex.snippets
, in der ich
~/current_course/UltiSnips/tex.snippets
hinzufĂŒge. FĂŒr die Quantenmechanik gibt es beispielsweise Ausschnitte zum Aufzeichnen der QuantenzustĂ€nde von Wandlampen und Ketos.
<a|
â
\bra{a}
<q|
â
\bra{\psi}
|a>
â
\ket{a}
|q>
â
\ket{\psi}
\braket{a}{b}
â
\braket{a}{b}
Da die Quantenmechanik hÀufig
\psi
, habe ich automatisch alle
q
in Klammern durch
\psi
.

snippet "\<(.*?)\|" "bra" riA \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
Kontext
Wenn Sie diese Schnipsel schreiben, sollten Sie berĂŒcksichtigen, ob sie im Klartext zu finden sind. Zum Beispiel gibt es laut meinem Wörterbuch ungefĂ€hr 72 Wörter auf Englisch und 2.000 Wörter auf NiederlĂ€ndisch mit sr. Wenn ich also
disregard
di^2egard
, Àndert sich
sr
zu
^2
und wir erhalten
di^2egard
.
Die Lösung fĂŒr dieses Problem besteht darin, Snippets Kontext hinzuzufĂŒgen. Die Syntaxhervorhebung von Vim bestimmt, ob UltiSnips ein Snippet verwenden soll, je nachdem, ob Sie sich im Formel- oder Textmodus befinden. Ich habe mir diese Option ausgedacht:
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
Jetzt können Sie den Snippets, die Sie nur in einem mathematischen Kontext anwenden möchten, den
context "math()"
hinzufĂŒgen.
context "math()" snippet sr "^2" iA ^2 endsnippet
Beachten Sie, dass der mathematische Kontext eine subtile Sache ist. Manchmal schreiben wir im Formelmodus auch Text mit
\text{...}
. In diesem Fall möchten wir keine Snippets verwenden. Im folgenden Fall:
\[ \text{$...$} \]
mĂŒssen sie jedoch angewendet werden. Aus diesem Grund ist der Code fĂŒr den
math
Kontext nicht so einfach. Die folgende Animation veranschaulicht diese Feinheiten.

Rechtschreibkorrektur im laufenden Betrieb
Obwohl Formeln ein wichtiger Bestandteil des Abstracts sind, drucke ich die meiste Zeit auf Englisch. UngefĂ€hr 80 Wörter pro Minute, meine SchreibfĂ€higkeiten sind ziemlich gut, aber ich mache viele Tippfehler. Aus diesem Grund habe ich Vim eine Bindung hinzugefĂŒgt, die Rechtschreibfehler korrigiert, ohne die Arbeit zu beeintrĂ€chtigen. Wenn ich wĂ€hrend der Eingabe
Ctrl+L
, wird der vorherige Rechtschreibfehler korrigiert. Es sieht so aus:

Meine Einstellungen fĂŒr die RechtschreibprĂŒfung:
setlocal spell set spelllang=nl,en_gb inoremap <Cl> <cg>u<Esc>[s1z=`]a<cg>u
Gehen Sie hier zu den vorherigen Rechtschreibfehlern, wÀhlen Sie dann die erste Option
1z=
und geben Sie
`]a
. Mit den Befehlen
<cg>u
in der Mitte können Sie die Korrektur schnell rĂŒckgĂ€ngig machen.
AbschlieĂend
Dank Vim-Snippets ist das Schreiben von LaTeX-Code nicht mehr Ă€rgerlich, sondern ein VergnĂŒgen. In Kombination mit der Rechtschreibung im laufenden Betrieb können Sie so Vorlesungen ĂŒber Mathematik bequem und schnell skizzieren. Im
nÀchsten Artikel werde ich auf andere Themen eingehen, z. B. das digitale Zeichnen von Illustrationen und das Einbetten in ein LaTeX-Dokument.