7 425 р.
9 900 р.
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'
\ [
, \]
, $
, то они не так бросаются в глаза, что даёт лучший обзор документа. Эта функция также заменяет \bigcap
на ∩
, \in
на ∈
и т. д., как показано на анимации:today
и нажимаю Tab
, слово today
заменяется текущей датой, а box
-Tab
становится полем, которое автоматически увеличивается в размере.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
``
, этот код будет запущен при расширении сниппета. Здесь я использовал 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
текущему имени файла и т. д.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
, которые запускают математический режим. Первый для встроенных формул, второй для отображаемых.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
сработает.<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
snippet // "Fraction" iA
\\frac{$1}{$2}$0
endsnippet
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
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 | 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('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
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}
. Порядок точки и запятой не имеет значения, так что я могу нажимать их одновременно. Эти сниппеты реально экономят время, потому что вы вводите их с той же скоростью, с какой лектор пишет на доске.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
, куда я добавляю сниппеты курса. Например, для квантовой механики есть сниппеты для записи квантовых состояний бра и кет.\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
disregard
, sr
заменится на ^2
, и получится di^2egard
.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
не так прост. Следующая анимация иллюстрирует эти тонкости.Ctrl+L
, исправляется предыдущая орфографическая ошибка. Это выглядит так:setlocal spell
set spelllang=nl,en_gb
inoremap <C-l> <c-g>u<Esc>[s1z=`]a<c-g>u
[s
, затем выбор первого варианта 1z=
и возврат `]a
. Команды <c-g>u
в середине позволяют быстро отменить сделанное исправление.