منذ بعض الوقت في Quora أجبت على السؤال:
كيفية مواكبة ملاحظات المحاضرة في الرياضيات على LaTeX . شرحت هناك سير عمل تدوين الملاحظات في LaTeX باستخدام Vim و Inkscape (للرسومات). لكن منذ ذلك الحين ، تغير الكثير ، لذلك أريد نشر العديد من منشورات المدونة مع وصف للعملية الجديدة. هذا هو أول المقالات.
لقد بدأت باستخدام LaTeX لتدوين الملاحظات في الفصل الدراسي الثاني من دورة الرياضيات ، ومنذ ذلك الحين كتبت أكثر من 1700 صفحة. فيما يلي بعض الأمثلة على شكل الملخص:



يتم عمل هذه الملاحظات ، بما في ذلك الرسومات ، مباشرة في المحاضرة ولا يتم تحريرها لاحقًا. لكتابة الملخصات بكفاءة في LaTeX ، يجب اتباع أربع قواعد:
- يجب أن تكون كتابة النص والصيغ في LaTeX بنفس سرعة كتابة المحاضر على السبورة: التأخير غير مقبول.
- يجب أن تكون الرسوم التوضيحية الرسم بنفس سرعة المحاضر.
- يجب أن تكون إدارة الملاحظات ، أي إضافة ملاحظات ، وترتيب جميع الملاحظات ، آخر محاضرتين ، وملاحظات البحث ، وما إلى ذلك ، سريعة وسهلة.
- يجب أن يكون من الممكن تعليق مستندات pdf باستخدام LaTeX إذا أردت كتابة ملاحظة مع مستند pdf.
هذه المقالة حول النقطة الأولى: تدوين الملاحظات على LaTeX.
فيم و لاتكس
لكتابة النص والصيغ الرياضية على LaTeX ، يمكنني استخدام Vim. هذا هو محرر نصوص قوي للأغراض العامة ، قابل للتوسيع بدرجة كبيرة. أنا استخدامها لكتابة التعليمات البرمجية ، والنص اللاتكس ، تخفيض السعر ... بشكل عام ، أي النصوص. لديه منحنى تعليمي حاد ، لكن إذا كنت تتقن القاعدة ، فمن الصعب بالفعل العودة إلى المحرر دون استخدام المفاتيح الساخنة المعتادة. هذا ما تبدو عليه شاشتي عندما أقوم بتحرير مستند LaTeX:

على اليسار هو Vim ، وعلى اليمين هو عارض
Zathura PDF ، والذي يدعم أيضًا اختصارات لوحة المفاتيح على غرار Vim. أنا أعمل في أوبونتو مع مدير نافذة
bspwm . كما المساعد تثبيت اللثي
vimtex . يوفر تسليط الضوء على بناء الجملة ، وجدول المحتويات ، synctex ، إلخ. باستخدام
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
بـ
∈
، إلخ ، كما هو موضح في الرسوم المتحركة:

باستخدام هذا الإعداد ، يمكنك تحقيق المهمة: الكتابة على LaTeX بأسرع ما يكتبه المحاضر على السبورة. القصاصات تدخل حيز اللعب هنا.
قصاصات
ما هو المقتطف؟
المقتطف عبارة عن جزء قصير من النص القابل لإعادة الاستخدام والذي يسمى بنص آخر. على سبيل المثال ، عند كتابة علامة وضغط Tab ، تتحول علامة الكلمة إلى توقيع:

يمكن أن تكون المقتطفات ديناميكية: عندما أكتب
today
واضغط على
Tab
، يتم استبدال الكلمة
today
بالتاريخ الحالي ، ويصبح
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 Castel endsnippet
بالنسبة إلى المقتطفات الديناميكية ، يمكنك وضع الكود بين backquotes ، ، وسيتم تشغيل هذا الكود عند تمديد المقتطف. أنا هنا استخدم bash لتنسيق التاريخ الحالي:
date + %F
snippet today "Date" `date +%F` endsnippet
داخل كتلة
`!p ... `
، يمكنك الكتابة في بيثون. انظر إلى رمز مقتطف
box
:
snippet box "Box" `!p snip.rv = '┌' + '─' * (len(t[1]) + 2) + '┐'` │ $1 │ `!p snip.rv = '└' + '─' * (len(t[1]) + 2) + '┘'` $0 endsnippet
بدلاً من هذا الرمز ، سيتم إدراج قيمة المتغير
snip.rv
في المستند. داخل الكتل ، يمكنك الوصول إلى الحالة الحالية للقصاص ، على سبيل المثال ،
t[1]
يتوافق مع مكان علامة التبويب الأولى ،
fn
اسم الملف الحالي ، إلخ.
قصاصات LaTeX
المقتطفات تسريع العمل بشكل كبير ، وخاصة بعض المقتطفات الأكثر تعقيدًا. لنبدأ مع أبسط.
البيئة
لإدخال بيئة ، فقط أدخل
beg
في بداية السطر. ثم اسم البيئة ، والتي تنعكس في الأمر
\end{}
. الضغط على
Tab
يضع المؤشر في الداخل.

الكود كما يلي:
snippet beg "begin{} / end{}" bA \begin{$1} $0 \end{$1} endsnippet
يعني الرمز
b
أن مثل هذا المقتطف يعمل فقط في بداية السطر ، يعني
A
التوسع التلقائي ، أي أنك لست بحاجة إلى الضغط على
Tab
. تتم الإشارة إلى علامات التبويب التي تذهب إليها عن طريق الضغط على
Tab
و
Shift
+
Tab
على أنها
$1
،
$2
، ... والرمز الأخير هو
$0
.
مضمنة وعرض الصيغ
القصاصات الأكثر استخدامًا هما
mk
و
dm
، مما يؤدي إلى تشغيل وضع الرياضيات. الأول للصيغ المضمّنة ، والثاني للصيغ المعروضة.

مقتطف الصيغة الذكية: يعرف متى يتم إدخال مسافة بعد علامة الدولار. عندما أبدأ بكتابة كلمة مباشرة بعد إغلاق $ ، فإنها تضيف مسافة. لكن إذا كتبت حرفًا آخر ، فلن تضيف مسافة ، كما في حالة "قيمة $ p $-value".

الكود الخاص بهذه المقتطف هو:
snippet mk "Math" wA $${1}$`!p if t[2] and t[2][0] not in [',', '.', '?', '-', ' ']: snip.rv = ' ' else: snip.rv = '' `$2 endsnippet
W
في نهاية السطر الأول أن المقتطف يتسع فقط عند حدود الكلمات. لذلك ، على سبيل المثال ، لن تعمل
hellomk
،
hellomk
hello mk
.
مقتطف الصيغ المعروضة أبسط ، ولكنه مريح للغاية أيضًا. يجعل دائمًا المعادلات تنتهي بنقطة.

<snippet dm "Math" wA \[ $1 .\] $0 endsnippet
أحرف منخفضة ومرتقبة
مقتطف مفيد آخر هو للفهارس. يغير
a1
إلى
a_1
و
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)
، يمكنك استخدامها في ملحق المقتطف عبر
match.group(i)
في Python.
بالنسبة للأحرف الفائقة ، يمكنني استخدام
td
، والذي يتحول إلى
^{}
. على الرغم من أنه الأكثر شيوعًا (المربعة ، المكعب ، وعدة أخرى) ، فإن القصاصات المنفصلة مخصصة ، مثل
sr
و
cb
و
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
الكسور
واحدة من أكثر المقتطفات ملاءمة تعمل مع الكسور. يقوم بالبدائل التالية:
//
→
\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}$0 endsnippet
يحدث
4ac/
الثاني والثالث بمساعدة التعبيرات العادية المقابلة للتعبيرات
3/
،
4ac/
،
6\pi^2/
،
a_2/
، إلخ.
snippet '((\d+)|(\d*)(\\)?([A-Za-z]+)((\^|_)(\{\d+\}|\d))*)/' "Fraction" wrA \\frac{`!p snip.rv = match.group(1)`}{$1}$0 endsnippet
كما ترون ، يمكن أن تصبح التعبيرات العادية طويلة جدًا ، ولكن فيما يلي رسم بياني يوضح كل شيء:

في الحالتين الرابعة والخامسة ، يحاول القصاص العثور على القوس المقابل. نظرًا لأن محرك UltiSnips regex لا يعرف كيفية القيام بذلك ، كان علي استخدام Python:
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
أخيرًا ، أريد مشاركة قصاصة تحول التحديد الحالي إلى كسر. حدد النص ، واضغط على
Tab
، واكتب
/
ثم اضغط على
Tab
مرة أخرى.

يستخدم الكود المتغير
${VISUAL}
، والذي يعكس اختيارك.
snippet / "Fraction" iA \\frac{${VISUAL}}{$1}$0 endsnippet
سيمبي ورياضيات
يعمل مقتطف رائع آخر أقل استخدامًا على تشغيل
sympy لتقييم تعبيرات الرياضيات. على سبيل المثال:
Tab
sympy
Tab
تتوسع إلى
sympy | sympy
sympy | sympy
، و
sympy 1 + 1 sympy
Tab
يتحول إلى
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
بالنسبة إلى Mathematica ، هناك شيء مماثل ممكن أيضًا:

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
يبدو لي أن أذكر أيضًا قصاصات postfix التي تدرج النص المناسب بعد إدخال أحرف معينة. على سبيل المثال ،
phat
→
\hat{p}
و
zbar
→
\overline{z}
. إدراج مقتطف مشابه متجهًا ، على سبيل المثال ،
v,.
→
\vec{v}
و
v.,
→
\vec{v}
. لا يهم ترتيب الفترة والفاصلة المنقوطة ، لذلك يمكنني النقر عليها في نفس الوقت. هذه المقتطفات توفر الوقت حقًا ، لأنك تدخلها بنفس السرعة التي يكتبها المحاضر على السبورة.

لاحظ أن بادئات
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
قصاصات أخرى
لا يزال لدي حوالي مائة قصاصة شائعة الاستخدام. كل منهم متاح
هنا . معظمهم بسيط جدا. على سبيل المثال ،
!>
يتحول إلى
\mapsto
،
->
يصبح
\to
، إلخ.

تتحول
fun
إلى
f: \R \to \R :
،
!>
→
\mapsto
،
cc
→
\subset
.

يصبح
lim
\lim_{n \to \infty}
،
sum
→
\sum_{n = 1}^{\infty}
،
ooo
→
\infty
.


قصاصات الدورة التدريبية المحددة
بالإضافة إلى تلك المستخدمة بشكل متكرر ، لدي أيضًا قصاصات محددة. يتم تحميلها كسطر واحد في
.vimrc
:
set rtp+=~/current_course
تعد
current_course
هنا
رابطًا رمزيًا للدورة التدريبية الحالية (المزيد حول هذا الموضوع في مقال آخر). في هذا المجلد ، يوجد الملف
~/current_course/UltiSnips/tex.snippets
، حيث أضيف قصاصات الدورة التدريبية. على سبيل المثال ، بالنسبة لميكانيكا الكم ، هناك قصاصات لتسجيل حالات الكم من الشمعدانات والكيتو.
<a|
→
\bra{a}
<q|
→
\bra{\psi}
|a>
→
\ket{a}
|q>
→
\ket{\psi}
\braket{a}{b}
→
\braket{a}{b}
نظرًا لأن ميكانيكا الكم تستخدم غالبًا
\psi
، استبدلت تلقائيًا كل
q
في braket بـ
\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
السياق
عند كتابة هذه المقتطفات ، يجب أن تفكر فيما إذا كان يمكن العثور عليها في نص عادي. على سبيل المثال ، وفقًا لقاموسي ، هناك حوالي 72 كلمة باللغة الإنجليزية ، و 2000 كلمة باللغة الهولندية مع 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
ليس بهذه البساطة. الرسوم المتحركة التالية توضح هذه التفاصيل الدقيقة.

تصحيح الإملاء على الطاير
على الرغم من أن الصيغ جزء مهم من الملخص ، إلا أنني أطبع معظم الوقت باللغة الإنجليزية. حوالي 80 كلمة في الدقيقة ، مهاراتي في الكتابة جيدة ، لكنني أصنع الكثير من الأخطاء المطبعية. لهذا السبب أضفت ارتباطًا إلى Vim يصحح الأخطاء الإملائية دون التدخل في العمل. عندما أقوم
Ctrl+L
أثناء الإدخال ، يتم تصحيح خطأ الإملاء السابق. يبدو مثل هذا:

الإعدادات الخاصة بي للتدقيق الإملائي:
setlocal spell set spelllang=nl,en_gb inoremap <Cl> <cg>u<Esc>[s1z=`]a<cg>u
هنا ، انتقل إلى الخطأ
[s
الأخطاء) الإملائي السابق ، ثم حدد الخيار الأول
1z=
ثم ارجع. تتيح لك أوامر
<cg>u
في الوسط التراجع عن التصحيح بسرعة.
في الختام
بفضل مقتطفات Vim ، لم تعد كتابة رمز LaTeX مزعجًا ، بل هي متعة. في تركيبة مع الإملاء أثناء الطيران ، يتيح لك ذلك تحديد محاضرات الرياضيات بشكل مريح وسريع. في
المقالة التالية ، سأتحدث عن مواضيع أخرى ، مثل رسم الرسوم التوضيحية رقميًا وإدراجها في مستند LaTeX.