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 next/previos math zone #1810

Closed
ghost opened this issue Sep 28, 2020 · 11 comments
Closed

Jump to next/previos math zone #1810

ghost opened this issue Sep 28, 2020 · 11 comments

Comments

@ghost
Copy link

ghost commented Sep 28, 2020

vimtex has mappings for jumping forward and backward to different elements like environments, comments etc. ([m [/ and family). Would it be possible to have a similar mapping to jump to next math element?

For example in the following text:

This is normal text, here comes some math $\alpha + \beta = \gamma$.
Here's some more math $$e^{i\pi} + 1  = 0,$$ and finally an equation
\begin{equation}
a^2 + b^2 = c^2
\end{equation}

]n (or any other keybinding) should go to $\alpha + \beta = \gamma$, then $$e^{i\pi} + 1 = 0,$$ and then finally to the equation environment.

@ghost ghost added the enhancement label Sep 28, 2020
@lervag
Copy link
Owner

lervag commented Sep 28, 2020

This sounds like a good idea. I think a simple solution is to search for $, $$, or \begin for forward motion and repeat until the syntax group of the following element is detected as a math group. I think this should be fast and robust (that is, as robust as the syntax scripts are at detecting math regions).

@ghost
Copy link
Author

ghost commented Sep 29, 2020

This sounds like a good idea. I think a simple solution is to search for $, $$, or \begin for forward motion and repeat until the syntax group of the following element is detected as a math group. I think this should be fast and robust (that is, as robust as the syntax scripts are at detecting math regions).

Glad you like it. If you can guide me, I can try to implement it and send a pull request. I have a little knowledge about vimscript.

@ghost
Copy link
Author

ghost commented Sep 29, 2020

Alright, I saw how vimtex#motion#environment is implemented and we need something like the following mixture (copied the environment implementation)

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

  " search either for $, $$, \[, \] or math environments like \begin{equation}\end{equation}
  " Have to also figure out if give $ or $$ is the beginning of the math environment or the end.
  let l:re = g:vimtex#re#not_comment . (a:begin ? '\$\{1,2}\|\\begin\s*\{' : '\$\{1,2}\|\\end\s*\{')
  let l:flags = 'W' . (a:backwards ? 'b' : '')

  for l:_ in range(l:count)
    in_math_region = false   
    while not in_math_region then
      in_math_region = check_math_region()
      " get current position and check we are in a math region, implement this.
      call search(l:re, l:flags)
    endwhile
  endfor
endfunction

Let me know what you think about it.

@Rmano
Copy link

Rmano commented Sep 29, 2020

" search either for $, $$, \[, \] or math environments like \begin{equation}\end{equation}

I know they're not loved a lot, but you should add \( and \) to the list...

Anyway, awesome idea, thanks!

@ghost ghost closed this as completed Sep 29, 2020
@ghost ghost reopened this Sep 29, 2020
@ghost
Copy link
Author

ghost commented Sep 29, 2020

Sorry, closed the issue by mistake.

" search either for $, $$, \[, \] or math environments like \begin{equation}\end{equation}

I know they're not loved a lot, but you should add \( and \) to the list...

Anyway, awesome idea, thanks!

Yes sure, I was not aware of it. Let @lervag have a look at it and then I will try to implement it.

@lervag
Copy link
Owner

lervag commented Sep 29, 2020

Some minor changes, still pseudocode:

function! vimtex#motion#math(begin, backwards, visual) abort " {{{1
  " Save cursor position first (and restore it on errors)
  let l:curpos_saved = vimtex#pos#get_cursor()

  let l:count = v:count1
  if a:visual
    normal! gv
  endif

  " Search for $, $$, \[, \(, \begin
  " Use syntax to determine if we are inside math region
  let l:re = g:vimtex#re#not_comment . '%(\${1,2}|\\\[|\\\(|\\begin\s*\{)'
  let l:flags = 'W' . (a:backwards ? 'b' : '')

  for l:_ in range(l:count)
    " Ensure we are not going into infinite loop
    let l:iter = 0
    while l:iter <= 5
      let l:iter += 1
      call search(l:re, l:flags)
      let l:pos = vimtex#pos#get_cursor()
      if vimtex#syntax#in_mathzone(l:pos)
        break
      endif
    endwhile
  endfor

  " Restore cursor position if fail
  call vimtex#pos#set_cursor(l:curpos_saved)
endfunction

Notes:

  • I suggest you first make a version that does not care about the begin option. Only move between beginning of math regions. When that works, you can add the other variant after.

  • Don't search for explicit math environments. Instead search for the \begin part and just check if the content of the environment is a math zone.

  • Save the cursor position originally and restore it if the search fails. You can use the vimtex#pos#... apis.

  • To check if a position is inside a math zone, use vimtex#syntax#in_mathzone. It might be necessary to check a displacement of the position, in which case you can use something like vimtex#pos#next(l:pos).

Let me know if you find the vimtex code/apis confusing, I'll be glad to help you make a PR for this!

@ghost
Copy link
Author

ghost commented Sep 30, 2020

@lervag Thanks for the feedback. I have started working on it, and I will let you know if I need help.

@ghost
Copy link
Author

ghost commented Oct 5, 2020

@lervag I have added the first version. Code here.

What works:

  • Can jump forward/backward with ]n and [n to the start of any math zones i.e. \begin{}, $, $$, \[, and \( with count.
  • Can jump to the end of math environments with [N and ]N i.e. the \begin{}\end{} family.
  • If there are no math environments to jump to, no motion happens.

What can be changed slightly:

  • Right now, if I give a jump count larger than the number of math zones available in the source file, the motion doesn't happen. This can be changed slightly, to jump to the last available math zone instead of not moving.

What does not work:

  • I can't think of an easy way to jump to the end of the math zones defined by $, $$, \[ and \(. While the syntax id attribute of both left and right $, or \[ and \] is Delimiter, only the left $ and \[ return true for math zone. The right $ or \] are considered outside of the math zone.

Let me know what you think if it.

Here's the tex source for testing purposes.

@ghost
Copy link
Author

ghost commented Oct 5, 2020

What does not work:

* I can't think of an easy way to jump to the end of the math zones defined by `$`, `$$`, `\[` and `\(`. While the syntax id attribute of both left and right `$`, or `\[` and `\]` is `Delimiter`, only the left `$` and `\[` return true for math zone. The right `$` or `\]` are considered outside of the math zone.

Let me know what you think if it.

Thanks to your notes, I have updated the code to take care of the $, \] and \] delimiters. Now we can also jump to end of these math zones as well.

@lervag
Copy link
Owner

lervag commented Oct 5, 2020

Let me know what you think if it.

Thanks! I very much appreciate the effort! It would be much easier for me to consider your code if you could open a pull request. Then we could 1) close this issue, 2) continue the discussions in the PR, and 3) do code review, suggestions and such "in the open".

@lervag
Copy link
Owner

lervag commented Oct 11, 2020

This issue is now solved from #1818.

@lervag lervag closed this as completed Oct 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants