Wie ich Mathe-Notizen zu LaTeX in Vim schreibe

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.

Source: https://habr.com/ru/post/de445066/


All Articles