lervag / vimtex

VimTeX: A modern Vim and neovim filetype plugin for LaTeX files.
MIT License
5.53k stars 391 forks source link

Enable conceal only for display environments (particularly for maths) #2396

Closed krishnakumarg1984 closed 2 years ago

krishnakumarg1984 commented 2 years ago

When a paragraph contains inline math, its navigation/editing becomes annoying when using vim's conceal feature due to the wobbly effect experienced when the cursor moves into/out of it. It would be nice to selectively disable conceal only in such inline environments.

My .vimrc has the following relevant settings:

set wrap
set conceallevel=2

Demonstration An animation perhaps explains the situation better than words. See https://asciinema.org/a/a0Y12DBYSSuyNZ8sVhjCRPyEf

minimal_example.tex

\documentclass{article}
\usepackage{mathtools}
\begin{document}

This is inline math, $(1 - \epsilon) \cdot (1 + \delta)$, whose navigation/editing becomes annoying when using vim's conceal feature due to the wobbles experienced \mbox{$e = \int_0^{2 \pi}  e^{-x}\, \text{dx}$} when the cursor moves into/out of it. It would be nice to selectively disable conceal only in such inline environments.

Below, we have some display math. It is absolutely desirable to have vim's conceal when editing display math. Display math environments are fairly important and are designed to standout, and hence it may help the author to employ the conceal feature. There is no other visual annoyance here.

$$\alpha + \beta$$

The rest of the document is meaningless gibberish placeholder text. Lorem ipsum
dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa
sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim
cupidatat excepteur officia. Culpa proident adipisicing id nulla nisi laboris
ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non
excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea
consectetur et est culpa et culpa duis.

\end{document}
lervag commented 2 years ago

I can see the motivation for this and can relate to the annoyance (among the reasons why I just generally keep the conceals off).

However, implementing the desired feature is a major undertaking, because it will require a change in the entire conceal implementation. The current idea has been to allow selectively specifying which types of conceals the user wants. And for the math kinds, I never thought of making it optional in which environment a user might want the conceals altogether.

So, to be more clear: This would require that we make two clusters for all math syntax elements. One for concealable regions and one for un-concealable regions. In short: It is a lot of work!

I'm sorry to say I am not motivated to do this work myself.

I will let the issue stay open for a while in case someone would be crazy enough to attempt this (perhaps you?). But if not, I will close the issue as "won't fix" in some time. Sorry!

krishnakumarg1984 commented 2 years ago

As a zeroth order brainstorming, is it worth thinking about iterating on the dumb thought-process below?

Provide a config key g:vimtex_disable_conceal_inline_math and set it to false by default to preserve existing behaviour.

At the first pass attempt, the disable-conceal-inline-math branch won't care about performance.

My point is, rather than hacking on vimtex's conceal implementation, we leverage vim's built-in (and battle-tested) conceal per paragraph looking for the first pair of \(, \) or $...$ anywhere in a region delimited by whitespace-only lines. Feel free to straightaway tell me if this is all gibberish (which most likely it is).

lervag commented 2 years ago

Well, no, it is not that easy. It is not how conceallevel works. However, your idea could be turned around. That is, one could dynamically change conceallevel when you move around the file. I don't want to build anything "official" around that in VimTeX, because it is way to "hacky", but something like this could work:

function! UpdateConcealLevel() abort
  " Either from environment names
  if vimtex#env#is_inside('equation')
    set conceallevel=2
  else
    set conceallevel=0
  endif

  " Or based on syntax
  if vimtex#syntax#in('texMathZoneEnv')
    set conceallevel=2
  else
    set conceallevel=0
  endif
endfunction

autocmd CursorMoved *.tex call UpdateConcealLevel()
krishnakumarg1984 commented 2 years ago

Thank you for putting together a function that can help.

Does vimtex#env#is_inside('equation') deal with only the equation environment? What about other amsmath display environments?

lervag commented 2 years ago

Yes. The argument to is_inside is a string that is used to match the environment name as a normal vim regex.

Another option is to use the syntax groups, but I don't think they are named consistently enough:

 $ ... $          ⇒  texMathZoneX
$$ ... $$         ⇒  texMathZoneXX
\( ... \)         ⇒  texMathZone
\[ ... \]         ⇒  texMathZone
\begin{equation}  ⇒  texMathZoneEnv
  ...
\end{equation}

The latter might actually be a feature request in itself - that is, to update the syntax regions to make the shorthand variants distinguishable.

krishnakumarg1984 commented 2 years ago

Yes. The argument to is_inside is a string that is used to match the environment name as a normal vim regex.

Another option is to use the syntax groups, but I don't think they are named consistently enough:

 $ ... $          ⇒  texMathZoneX
$$ ... $$         ⇒  texMathZoneXX
\( ... \)         ⇒  texMathZone
\[ ... \]         ⇒  texMathZone
\begin{equation}  ⇒  texMathZoneEnv
  ...
\end{equation}

The latter might actually be a feature request in itself - that is, to update the syntax regions to make the shorthand variants distinguishable.

Then, this doesn't scale to every possible environment unless the user strings together an endless bunch of or conditions.

It may be the case that detection of display math zone might be an important condition for it to be treated/presented differently in the buffer. You mentioned different highlight groups for visual presentation, but there could be other. For example, for a centered preview of how the typeset equation might look like using virtual text/conceal etc.(my imagination is running wild, I know).

Do you envisage such future needs of separate treatment applied to visual math zones? The argument that you could just compile and see the output is probably specious since it assumes that compilations are fast (you've pointed out the philosophical incompatibilities of LaTeX with live previews in my other recent issue). Despite the existence of conditional compilations, I think it's super convenient for the writer to get AucTeX like experience whilst suppressing inline conceals.

lervag commented 2 years ago

Do you envisage such future needs of separate treatment applied to visual math zones?

I'm sorry, but you lost me there.

I believe the following is quite close to what you want, actually:

function! UpdateConcealLevel() abort
  if vimtex#syntax#in('texMathZoneEnv')
    set conceallevel=2
  else
    set conceallevel=0
  endif
endfunction

autocmd CursorMoved *.tex call UpdateConcealLevel()

It is not perfect, but it would disable conceals except when your cursor is inside any math environment. Did you test it?

krishnakumarg1984 commented 2 years ago
function! UpdateConcealLevel() abort
  if vimtex#syntax#in('texMathZoneEnv')
    set conceallevel=2
  else
    set conceallevel=0
  endif
endfunction

autocmd CursorMoved *.tex call UpdateConcealLevel()

This almost works. Now, the problem is that the inline environments also gets affected by the toggling of the conceallevel, which continues the same jarring effect seen initially.

See the terminal recording here: https://asciinema.org/a/EnuprKRLT7Hc5zMODWqRJdCJS

lervag commented 2 years ago

Yes, and for this there is no solution except rewriting stuff - the part I already mentioned is out of scope for me. Sorry!

krishnakumarg1984 commented 2 years ago

We need something analogous to context-commentsrings (i.e. wherein lines of a different ft syntax is embedded within a file of another filetype). Neovim is already able to recognize this embedded syntax notation and change various buffer settings locally (not just the commentstring).

Is there any concept of region-local conceallevel at the paragraph level? (Neo)vim already understands the concept of paragraphs, right? If not, I think @clason is an upstream developer, and do either of you think it is worth raising this request to dev folks upstream (at least for neovim)?

PS: I am not an Emacs user, but from the demos that colleagues showed me, it looks like AucTeX can do this. A lot of AucTeX's power is from conceal-like features to "render" things in the edit buffer.

lervag commented 2 years ago

I believe this context specific thing is made possible for treesitter stuff. And treesitter will never be part of VimTeX.

A region-local conceallevel sounds interesting, but it does feel wrong - the only reason you need it here is because the syntax script is written in a suboptimal manner.

clason commented 2 years ago

Yes, AucTeX is all about conceal -- which I am not at all a fan of.

And, no, Neovim does not understand the concept of paragraph (except "look for empty line", which is not a semantic marker). I don't see much interest in adding such a concept to Neovim -- the tools are there (tree-sitter, extmarks) or will be (extranges, anticonceal a.k.a. inline virtual text), so someone interested in this can build their own solution.

krishnakumarg1984 commented 2 years ago

Apologies upfront if the below comes across badly, but I am merely trying to see how best to achieve things. Absolutely no offences intended.

The documenation currently says that:

VimTeX implements a traditional syntax script for syntax highlighting of LaTeX documents (see |syntax.txt|). The implementation is quite complete and has support for a lot of packages. It should work well for most people.

which contradicts (imho) with the above statement:

the only reason you need it here is because the syntax script is written in a suboptimal manner.

Again, pointing out this discrepancy in wording does sounds impolite, but let me gently assure you that my intentions are merely to see how to take this forward. I'd like to have the cake and eat it too....i.e. conceal where I want, and no conceal where I don't want - all within the same file.

lervag commented 2 years ago

I understand that there are only good intentions, but I believe I already explained this in my very first comment. I tried to explain how the current version is not good enough for the desired feature, and I explained that I do not intend to fix this myself. You are very welcome to attempt it, and I will be happy to help. But it is not straightforward and it will require some work.

clason commented 2 years ago

I'd like to have the cake and eat it too....i.e. conceal where I want, and no conceal where I don't want - all within the same file.

You can -- but then you have to bake it yourself.

krishnakumarg1984 commented 2 years ago

Alright alright. I was always bad at baking (both with cakes and with vimscript). Let's rest this case. If anyone wants to provide a baking recipe, maybe I'll do it. Otherwise, maybe I'll disable conceal for now :(

lervag commented 2 years ago

Hehe, no problem. I don't think I can give a much better baking recipe than I already did. So let's leave it at that.