Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jump to previous/next math zone #1818

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -106,6 +106,7 @@ disabled if desired.
- Motions
- Move between section boundaries with `[[`, `[]`, `][`, and `]]`
- Move between environment boundaries with `[m`, `[M`, `]m`, and `]M`
- Move between math environment boundaries with `[n`, `[N`, `]n`, and `]N`
- Move between comment boundaries with `[*` and `]*`
- Move between matching delimiters with `%`
- Text objects
Expand Down
13 changes: 13 additions & 0 deletions autoload/vimtex.vim
Expand Up @@ -180,6 +180,19 @@ function! s:init_default_mappings() abort " {{{1
call s:map(1, 'o', '[]', '<plug>(vimtex-[])')
call s:map(1, 'o', '[[', '<plug>(vimtex-[[)')

call s:map(1, 'n', ']N', '<plug>(vimtex-]N)')
call s:map(1, 'n', ']n', '<plug>(vimtex-]n)')
call s:map(1, 'n', '[N', '<plug>(vimtex-[N)')
call s:map(1, 'n', '[n', '<plug>(vimtex-[n)')
call s:map(1, 'x', ']N', '<plug>(vimtex-]N)')
call s:map(1, 'x', ']n', '<plug>(vimtex-]n)')
call s:map(1, 'x', '[N', '<plug>(vimtex-[N)')
call s:map(1, 'x', '[n', '<plug>(vimtex-[n)')
call s:map(1, 'o', ']N', '<plug>(vimtex-]N)')
call s:map(1, 'o', ']n', '<plug>(vimtex-]n)')
call s:map(1, 'o', '[N', '<plug>(vimtex-[N)')
call s:map(1, 'o', '[n', '<plug>(vimtex-[n)')

call s:map(1, 'n', ']M', '<plug>(vimtex-]M)')
call s:map(1, 'n', ']m', '<plug>(vimtex-]m)')
call s:map(1, 'n', '[M', '<plug>(vimtex-[M)')
Expand Down
109 changes: 109 additions & 0 deletions autoload/vimtex/motion.vim
Expand Up @@ -39,6 +39,28 @@ function! vimtex#motion#init_buffer() abort " {{{1
onoremap <silent><buffer> <plug>(vimtex-[[)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[[)"<cr>

" Math
nnoremap <silent><buffer> <plug>(vimtex-]n) :<c-u>call vimtex#motion#math(1,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-]N) :<c-u>call vimtex#motion#math(0,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[n) :<c-u>call vimtex#motion#math(1,1,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[N) :<c-u>call vimtex#motion#math(0,1,0)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]n) :<c-u>call vimtex#motion#math(1,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]N) :<c-u>call vimtex#motion#math(0,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[n) :<c-u>call vimtex#motion#math(1,1,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[N) :<c-u>call vimtex#motion#math(0,1,1)<cr>
xmap <silent><buffer> <plug>(vimtex-]n) <sid>(vimtex-]n)
xmap <silent><buffer> <plug>(vimtex-]N) <sid>(vimtex-]N)
xmap <silent><buffer> <plug>(vimtex-[n) <sid>(vimtex-]n)
xmap <silent><buffer> <plug>(vimtex-[N) <sid>(vimtex-]N)
lervag marked this conversation as resolved.
Show resolved Hide resolved
onoremap <silent><buffer> <plug>(vimtex-]n)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]n)"<cr>
onoremap <silent><buffer> <plug>(vimtex-]N)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]N)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[n)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[n)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[N)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[N)"<cr>

" Environments
nnoremap <silent><buffer> <plug>(vimtex-]m) :<c-u>call vimtex#motion#environment(1,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-]M) :<c-u>call vimtex#motion#environment(0,0,0)<cr>
Expand Down Expand Up @@ -194,6 +216,93 @@ function! vimtex#motion#comment(begin, backwards, visual) abort " {{{1
endfunction

" }}}1
function! vimtex#motion#math(begin, backwards, visual) abort " {{{1
let l:curpos_saved = vimtex#pos#get_cursor()
let l:count = v:count1
if a:visual
normal! gv
endif
normal! m`

lervag marked this conversation as resolved.
Show resolved Hide resolved
" Search for $, $$, \[, \(, \begin
" Use syntax to determine if we are inside math region.
let l:re = g:vimtex#re#not_comment . (a:begin
\ ? '%((\\\[)|(\\\()|(\\begin\s*\{)|(\$\$)|(\$))'
\ : '%((\\\])|(\\\))|(\\end\s*\{)|(\$\$)|(\$))')

let l:flags = 'Wp' . (a:backwards ? 'b' : '')

for l:_ in range(l:count)
let l:success = 0

" Ensure we are not going into an infinite loop, the choice to iterate
" not more than 6 times is arbitrary but good enough to find the math
" zone in the text currently visible in the window.
let l:iter = 0
while l:iter <= 5
let l:iter += 1
let l:submatch = search(l:re, l:flags)
let l:pos = vimtex#pos#get_cursor()
if l:submatch == 0
break

" Jump directly to \[, \], \(, \)
elseif l:submatch < 4
let l:success = 1
break

" Check if the environment is a math environment
elseif l:submatch == 4
if vimtex#syntax#in_mathzone(l:pos[1], l:pos[2])
let l:success = 1
break
endif

" Handle $, $$
else

" Look for beginning of mathzone
if a:begin
if vimtex#syntax#in_mathzone(l:pos[1], l:pos[2])
let l:success = 1
break
endif

" Look for end of mathzone
else

" If searching for end, first check that the current search position
" is atleast 2 columns left from the initial position and not in mathzone
" already. The check works because only opening $ and $$ are in mathzone, not
" the closing ones.
if vimtex#syntax#in_mathzone(l:pos[1], l:pos[2])
\ || (abs(l:curpos_saved[2] - l:pos[2]) == 1
\ && l:curpos_saved[1] - l:pos[1] == 0)
continue
endif

" Now check if previous position is inside a mathzone or not
let l:pos = vimtex#pos#prev(vimtex#pos#prev(l:pos))
if vimtex#syntax#in_mathzone(l:pos[1], l:pos[2])
let l:success = 1
break
endif
endif
endif
endwhile

" Update saved cursor position after successfully finding next math zone.
if l:success
let l:curpos_saved = vimtex#pos#get_cursor()

" If not able to find the first math zone, quit. Otherwize, the jumps with
" a count can lead to unexpected behavior.
else
call vimtex#pos#set_cursor(l:curpos_saved)
break
endif
endfor
endfunction


" Patterns to match section/chapter/...
Expand Down
21 changes: 21 additions & 0 deletions doc/vimtex.txt
Expand Up @@ -171,6 +171,7 @@ FEATURE OVERVIEW *vimtex-features*
- Motions
- Move between section boundaries with `[[`, `[]`, `][`, and `]]`
- Move between environment boundaries with `[m`, `[M`, `]m`, and `]M`
- Move between math environment boundaries with `[n`, `[N`, `]n`, and `]N`
- Move between comment boundaries with `[*` and `]*`
- Move between matching delimiters with `%`
- Text objects
Expand Down Expand Up @@ -780,6 +781,10 @@ This feature is explained in more detail later, see |vimtex-imaps|.
]M |<plug>(vimtex-]M)| `nxo`
[m |<plug>(vimtex-[m)| `nxo`
[M |<plug>(vimtex-[M)| `nxo`
]n |<plug>(vimtex-]n)| `nxo`
]N |<plug>(vimtex-]N)| `nxo`
[n |<plug>(vimtex-[n)| `nxo`
[N |<plug>(vimtex-[N)| `nxo`
]/ |<plug>(vimtex-]/| `nxo`
]* |<plug>(vimtex-]star| `nxo`
[/ |<plug>(vimtex-[/| `nxo`
Expand Down Expand Up @@ -2910,6 +2915,22 @@ object, see |text-objects|.
go to [count] previous end of an environment `\end`.
|exlusive| motion.

*<plug>(vimtex-]n)*
go to [count] next start of a math zone.
|exlusive| motion.

*<plug>(vimtex-]N)*
go to [count] next end of a math zone.
|exlusive| motion.

*<plug>(vimtex-[n)*
go to [count] previous start of a math zone.
|exlusive| motion.

*<plug>(vimtex-[N)*
go to [count] previous end of a math zone.
|exlusive| motion.

*<plug>(vimtex-]/)*
go to [count] next start of a LaTeX comment "%".
|exlusive| motion.
Expand Down
31 changes: 31 additions & 0 deletions test/tests/test-motions/test-math-motions.tex
@@ -0,0 +1,31 @@
\documentclass[]{article}

\begin{document}

Test file for math motion.

\begin{equation} % [n[n or 2[n
1 + 1 = 2
\end{equation} % [N[N or 2[N

\( 1 + 1 = 2 \) % Opening: [n, Closing: [N

\begin{enumerate}
\item 1
\item 2
\item 3
\item 4
\end{enumerate}
% CURSOR
\[ % ]n
1 + 1 = 2
\] % ]N

\begin{itemize}
\item $1 + 1 = 2$. % Opening: ]n]n or 2]n, Closing: ]N]N or 2]N
\end{itemize}

$1 + 1 = 2$ % Opening: ]n]n]n or 3]n, Closing: ]N]N]N or 3]N
$$1 + 1 = 2$$ % Opening: ]n]n]n]n or 4]n, Closing: ]N]N]N]N or 4]N

\end{document}
26 changes: 26 additions & 0 deletions test/tests/test-motions/test-math-motions.vim
@@ -0,0 +1,26 @@
set nocompatible
let &rtp = '../../..,' . &rtp
filetype plugin on
syntax on

nnoremap q :qall!<cr>

silent edit test-math-motions.tex

if empty($INMAKE) | finish | endif

" vint: -ProhibitCommandRelyOnUser

normal 19G2]n
call vimtex#test#assert_equal(line('.'), 25)

normal 19G]N
call vimtex#test#assert_equal(line('.'), 22)

normal 19G2[n
call vimtex#test#assert_equal(line('.'), 7)

normal 19G[N
call vimtex#test#assert_equal(line('.'), 11)

quit!