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

[conceal] \cite, \citep, \citet to key list or just a simple marker #1965

Closed
whisperity opened this issue Feb 20, 2021 · 36 comments
Closed

[conceal] \cite, \citep, \citet to key list or just a simple marker #1965

whisperity opened this issue Feb 20, 2021 · 36 comments
Labels
enhancement ready-to-implement Discussions are over, implementation should start

Comments

@whisperity
Copy link

This is a suggestion request to extend Vimtex's conceal feature with handling \cite, \citep, and \citet. If possible, it should be concealed out with either a (...) (where ... is the bib key for the cited work), or with [X] where X is a literal X to show there is a citation there, instead of the lengthy sequence a bib key could take.

Unfortunately, I'm not sure if conceal can handle "parsing" such elaborate sequences.

@lervag
Copy link
Owner

lervag commented Feb 22, 2021

I don't think Vim can do this type of "advanced" conceals, that is, we can only do relatively simple replacements.

To be able to answer/consider this request more clearly, perhaps you could show some examples of specifically how you would like this to work? I think the following shows approximately what I think can be achieved:

% Raw tex
See e.g. \cite{myref} for more info.
\citet{myref} show that ...

% Concealed
See e.g. [myref] for more info.
[myref] show that ...

A "perfect" solution would of course parse the reference key, but I think that is impossible (or at least too hard for me to consider). Further, a perfect solution would differentiate \citet and \citep and similar, but I would propose to simplify this to concealing boundaries, i.e. \cite…{ -> [ and } -> ]. But is this sufficient for this to be an interesting feature?

@whisperity
Copy link
Author

No need for it to be perfect. And yes, I know the conceal is iffy... e.g. for C++ I couldn't even manage to get it to conceal else if and else and if differently, even... 😦

Parsing the reference key is definitely impossible in the general case, and not worth the effort.
The purpose of conceal is to remove the bloat. The \cite(t|p)? here is bloat, similarly how \emph is bloat if your terminal supports italic letters in the first place.

Is it hard to "throw away" the insides of the concealed boundaries?

@lervag
Copy link
Owner

lervag commented Feb 25, 2021

Parsing the reference key is definitely impossible in the general case, and not worth the effort.

Good to hear we agree on that.

The purpose of conceal is to remove the bloat. The \cite(t|p)? here is bloat, similarly how \emph is bloat if your terminal supports italic letters in the first place.

Well, if we concealed \cite{xxx} so it looks like [xxx], then it could be hard to realize that this is really a citation and not just the actual text [xxx]. But I guess if you were to use this feature it would probably be what you want.

Is it hard to "throw away" the insides of the concealed boundaries?

I'm not sure what you mean, please try to show by example (raw vs "concealed variant").

So far, it seems my listing in the previous comment seems like an acceptable proposal for the feature.

@whisperity
Copy link
Author

Is it hard to "throw away" the insides of the concealed boundaries?

I'm not sure what you mean, please try to show by example (raw vs "concealed variant").

\cite{John2012Measurement,Anne2017Bifurcation} becomes [X], rather than [John2012Measurement,Anne2017Bifurcation]. "Always" X to simulate the citation becoming some number-in-brackets when you "print" the document.

I know in reality the citstion depends on style factor, but when it comes to reading the source text of the document, [X] is a good enough approximation.
Given concealmode set to only conceal when not editing but reading, this makes you go "Oh yeah there's some cites there." and that's useful.

(In many cases, the bib keys for stuff doesn't even make sense, sites generare either an auto increment ID (like IEEE) or the DOI (like ACM or Springer) as the bibkey.)

@lervag
Copy link
Owner

lervag commented Mar 1, 2021

I would propose an option: let g:vimtex_syntax_conceal = {'cites': n} where n is 0 to disable (default value, perhaps?) and with two variants:

% Raw TeX
Bla bla bla, see Ref.~\cite{John2012Measurement,Anne2017Bifurcation}. For more info, see also \cite{Bob2025Mystery}.

% Concealed with g:vimtex_syntax_conceal = {'cites': 1}
Bla bla bla, see Ref.~[X]. For more info, see also [X].

% Concealed with g:vimtex_syntax_conceal = {'cites': 2}
Bla bla bla, see Ref.~[John2012Measurement,Anne2017Bifurcation]. For more info, see also [Bob2025Mystery].

If you think this looks like a sufficient summary, then I'll look into if it is doable (without too much "hacking").

@whisperity
Copy link
Author

I like the idea. Maybe instead of a numbers 1 and 2, the configuration option could be a "word" like Xs or keys.

@mawkler
Copy link

mawkler commented Mar 4, 2021

Perhaps this is too difficult to implement, but it would be awesome if VimTeX showed the citation that would be generated in the PDF. For instance the number that \bibliographystyle{IEEEtranS} would generate.

For example, given Bla bla bla, see Ref.~\cite{John2012Measurement,Anne2017Bifurcation}. For more info, see also \cite{Bob2025Mystery}., when generating a PDF it would with \bibliographystyle{IEEEtranS} look something like this:

Bla bla bla, see Ref. [1]. For more info, see also [2].

It would be awesome if the concealed text looked something like above. The VimTeX feature doesn't necessarily have to look at the value of \bibliographystyle{IEEEtranS}, but it would be nice if it were easy to tell each concealed citation apart, while still being nice and short to remove the bloat.

Again, this may be way too difficult to implement, but I just want to throw the idea out.

@lervag
Copy link
Owner

lervag commented Mar 4, 2021

Perhaps this is too difficult to implement, but it would be awesome if VimTeX showed the citation that would be generated in the PDF.

Ah, yes, I'm sorry. This is too hard. The syntax conceal feature in Vim/neovim is quite limited (see :help syn-conceal for the details), and one such limitation (as far as I know) is that we can't dynamically replace text. In fact, we can only replace a syntax element with a single specified character (see :help syn-cchar).

So, to achieve [x], we actually need to use a hack where the initial part is concealed with [, the ending } is concealed with ], and the content is concealed with x. I'm not sure I will even be able to do this in a sufficiently robust manner, but I will try.

@whisperity
Copy link
Author

Perhaps this is too difficult to implement, but it would be awesome if VimTeX showed the citation that would be generated in the PDF.

Bla bla bla, see Ref. [1]. For more info, see also [2].

Again, this may be way too difficult to implement, but I just want to throw the idea out.

Definitely impossible to implement, and not just because of Vim's limited functionality, but to do this, you'd need to either: reimplement a significant part of the compilers, or use an integration that jacks into the actual compilers (like clangd for C/C++) and retrieves this data. This is an overexaggeration and I didn't look into it scientifically, but LaTeX is at least Turing-complete, but there is a high chance that the grammar is so deeply context-sensitive that it's undecidable in the general case. (C++ has similar issues in many case.) And, come on, to build a LaTeX document with cites, you have to run the compiler at least three times(!!!), plus bibtex somewhere down that road, and what latexmk is doing under the hood is running the compiler iteratively until the previous and the current output document stays the same. I.e. latexmk is prepared to do multiple rounds of iteration, which is pretty funny when you have a nondeterministic package somewhere down the road.

And this gets even worse when you got bib styles which are some sort of author-year combination, and the author names contain escape sequences or are generated by macros, etc... I am not saying this is completely impossible, but it would require both more than the conceal feature, and some true compiler integration...


Personal suggestion about bloats and whatnot: first, set concealcursor=nc, so in insert mode you're getting unconcealed text. Second, create a keybind that toggles concealment:

  function! ToggleConcealLevel()
      if &conceallevel == 0
          setlocal conceallevel=2
      else
          setlocal conceallevel=0
      endif
  endfunction
  nnoremap <silent> <C-c><C-y> :call ToggleConcealLevel()<CR>

@whisperity
Copy link
Author

So, to achieve [x], we actually need to use a hack where the initial part is concealed with [, the ending } is concealed with ], and the content is concealed with x. I'm not sure I will even be able to do this in a sufficiently robust manner, but I will try.

There is one issue with conceal that I found is that it seems the same location in the buffer can't have multiple concealments apply. I could never manage to differently conceal else if from else and if in C/C++. But I have to admit I'm lacking knowledge about Vimscripts and configuration in detail. However, [x] seems much more doable at face value than [1] and then [2].

@lervag
Copy link
Owner

lervag commented Mar 5, 2021

There is one issue with conceal that I found is that it seems the same location in the buffer can't have multiple concealments apply. I could never manage to differently conceal else if from else and if in C/C++.

Sorry, but I don't quite understand how you would want that C/C++ conceal. Reg. multiple concealments: it doesn't really make sense to apply multiple conceals at the same position. Conceal is basically used to hide text, but it does allow to replace with a single character. If something is hidden, you can't hide it more.

@whisperity
Copy link
Author

Sorry, but I don't quite understand how you would want that C/C++ conceal. Reg. multiple concealments: it doesn't really make sense to apply multiple conceals at the same position. Conceal is basically used to hide text, but it does allow to replace with a single character. If something is hidden, you can't hide it more.

Mind, I do not want it from you! But basically what I was is to have one character conceal for if, a different one for else if and a third one for else. So I'd want the following code snippet:

if (foo) {
  return 1;
} else if (bar) {
  return 2;
} else {
  return 3;
}

in concealment to look like this:

▸ (foo) {
  ⏎ 0;
} ▹ (bar) {
  ⏎ 1;
} ▪ {
  ⏎ 2;
}

But instead, it looks like this (note that else if instead of concealed as a "token" together, becomes two concealed tokens, else and if with their conceal chars, respectively):

▸ (foo) {
  ⏎ 0;
} ▪ ▸ (bar) {
  ⏎ 1;
} ▪ {
  ⏎ 2;
}

@mawkler
Copy link

mawkler commented Mar 5, 2021

An alternative to replacing citations with [X] that I would like to suggest and that might be easier to implement is to show a unicode symbol instead, like this:

% Raw TeX
Bla bla bla, see Ref.~\cite{John2012Measurement,Anne2017Bifurcation}. For more info, see also \cite{Bob2025Mystery}.

% Concealing with unicode symbol
Bla bla bla, see Ref.~🕮. For more info, see also 🕮.

Perhaps the exact symbol used could be customizable by the user so that they could use a nerd font glyph if they wanted.

@lervag
Copy link
Owner

lervag commented Mar 5, 2021

Mind, I do not want it from you! But basically what I was is to have one character conceal for if, a different one for else if and a third one for else. So I'd want the following code snippet:

This should be possible. You need to understand the order of syntax statements. The last one is checked first. So, you need to add the else if after. Feel free to contact me by mail if you want more input on this - if so, show me the code you use that fails.

@Melkster I actually like that suggestion a lot. It is much easier to implement than [x], since it relies on a single substitution character. One question: Would you want the same feature for both \citet and \citep (and similar)?

@whisperity What do you think?

@whisperity
Copy link
Author

% Concealing with unicode symbol
Bla bla bla, see Ref.~🕮. For more info, see also 🕮.

Perhaps the exact symbol used could be customizable by the user so that they could use a nerd font glyph if they wanted.

I like the idea. But definitely make the symbol customisable, some terminal emulators (such as Konsole) have biiig problems with rendering glpyhs properly.

@mawkler
Copy link

mawkler commented Mar 5, 2021

Would you want the same feature for both \citet and \citep (and similar)?

I personally don't use \citet/\citep, but I don't see why not. Perhaps they can have the same default icon as \cite but be individually customizable.

@whisperity
Copy link
Author

Would you want the same feature for both \citet and \citep (and similar)?

I personally don't use \citet/\citep, but I don't see why not. Perhaps they can have the same default icon as \cite but be individually customizable.

Normally I don't want to either, but a recent paper I submitted required a weird format and authoryear cites instead of the IEEE one, for which I had to use \citep...

@lervag
Copy link
Owner

lervag commented Mar 5, 2021

Actually, it is smart to use \citep or \citet to be explicit on which kind of reference you want (i.e. part of the text "Author (year) was the subject in this sentence") or leaf reference ("sentence goes here [leaf]" or "bla bla bla, see Ref. [leaf]"). If you use \cite the style depends on several things, and the text may be broken if you change the underlying style.

@lervag lervag added the ready-to-implement Discussions are over, implementation should start label Mar 8, 2021
@lervag
Copy link
Owner

lervag commented Mar 8, 2021

Then I propose the following:

  1. Add option g:vimtex_syntax_conceal.citations and g:vimtex_syntax_conceal_citesign to allow customizing. The citesign is empty by default and thus the conceal does not apply unless activated.
  2. If active, then every \cite command will be concealed with the character specified in the option.

Simple and straightforward. We can consider improvements when it is done. Does it sound OK?

@whisperity
Copy link
Author

So the _citesign would be the 📖 emoji character, right? Sounds good to me.

@lervag
Copy link
Owner

lervag commented Mar 9, 2021

Exactly. :)

@mawkler
Copy link

mawkler commented Mar 9, 2021

@lervag Sounds like a good start!

I also liked the previous idea with concealing \cites by wrapping the citation in angle brackets like so:

% Raw TeX
Bla bla bla, see Ref.~\cite{John2012Measurement,Anne2017Bifurcation}. For more info, see also \cite{Bob2025Mystery}.

% Concealed with g:vimtex_syntax_conceal = {'cites': 2}
Bla bla bla, see Ref.~[John2012Measurement,Anne2017Bifurcation]. For more info, see also [Bob2025Mystery].

Perhaps there could be an option added later for this as well?

@lervag
Copy link
Owner

lervag commented Mar 22, 2021

I'm not quite sure about this. I've pushed a PR with the previously discussed feature where the entire cite command is replaced with a single character. However, since Vim and neovim does not reflow the text, I think the benefit is not enough. But I'll let you people decide - I'll not be using it myself in any case.

I think I would prefer to only support a single type of conceals here, so let's discuss this. Perhaps a better choice is the bracketed version where \cite{ and } are concealed with brackets?

@lervag
Copy link
Owner

lervag commented Mar 22, 2021

Just to show what I mean, here are two screenshots that shows how it looks when the cursor is on the line (i.e., not concealed) vs. when the commands are concealed. The terminal is 80 cols wide (or 82).

2021-03-22_22:25_screenshot
2021-03-22_22:25_screenshot_000

@whisperity
Copy link
Author

In general when writing (La)TeX, you should not be putting two sentences on the same line anyways, similar to how you rarely put two full expressions on the same line when writing a program! Makes it really wonky to move around sentences or cut out sentences (e.g. when you happen to go over the limit of the journal you're submitting to and need to rewrite some sentences).

@lervag
Copy link
Owner

lervag commented Mar 23, 2021

In general when writing (La)TeX, you should not be putting two sentences on the same line anyways, similar to how you rarely put two full expressions on the same line when writing a program!

I tend to agree, but it is not up to me to enforce such rules. VimTeX should work well regardless of how people work.

So, the questions:

  • Is Feature: Conceal support for \cite commands #2002 already useful interesting to anyone? Do you have comments on the choice of option names and default values?

  • Should I make a similar implementation that conceals \cite{x} -> [x] as well? If so, how should the configuration look like?

@whisperity
Copy link
Author

@lervag

So, the questions:

Yeah. I like it. If it is by itself, if it is fine. If not, then see answer to the next point.

  • Should I make a similar implementation that conceals \cite{x} -> [x] as well? If so, how should the configuration look like?

The conceal map should have not a citations key but a citations_full or citations_commands. If citations_full is 1, current behaviour (:book:). If citations_commands is 1, [x] behaviour. I guess there needs to be some precedence between the two. I'd say citations_full should take precedence.

And then the default behaviour could be that citations_full = 1, citations_commands = 0. Or the other way around.

@whisperity
Copy link
Author

Or you could simply call them cite_fully and cite_command. Instead of citations_.

@mawkler
Copy link

mawkler commented Mar 23, 2021

Is #2002 already useful interesting to anyone?

I personally kinda like having both options available.

Should I make a similar implementation that conceals \cite{x} -> [x] as well? If so, how should the configuration look like?

I would suggest the name g:vimtex_cite_conceal and it could be set to one of the strings 'icon', 'brackets' or 'none', where 'none' disables the conceal of \cite entirely. Perhaps 'brackets' should be the default, i.e. where \cite{ and } are concealed with square brackets.

Then there could be a second variable called g:vimtex_cite_conceal_icon that can be set to a character, with the unicode symbol 🕮 as default value. This variable is only relevant if g:vimtex_cite_conceal is set to 'icon'.

@whisperity
Copy link
Author

I would suggest the name g:vimtex_cite_conceal and it could be set to one of the strings 'icon', 'brackets' or 'none', where 'none' disables the conceal of \cite entirely. Perhaps 'brackets' should be the default, i.e. where \cite{ and } are concealed with square brackets.

A slight "problem" is that all the other conceal configuration options are booleans. So this would create a dissonance. Not a problem for me, but might be a sore thorn when looked at.

Then there could be a second variable called g:vimtex_cite_conceal_icon that can be set to a character, with the unicode symbol 🕮 as default value. This variable is only relevant if g:vimtex_cite_conceal is set to 'icon'.

If we accept the fact that the symmetry of the flags being bools are broken, then we could roll with just one configuration option. It could be 0 for disable, 1 or brackets to enable only the bracket concealment. And if it is any other symbol (e.g. 🕮), then it should mean "conceal the entire cite with this symbol in particular".

@lervag
Copy link
Owner

lervag commented Mar 24, 2021

I've implemented and pushed a solution now. Comments are more than welcome! Please checkout the PR #2002. To test:

  1. Go to your vimtex directory, e.g. cd .vim/bundle/vimtex (path depends on your system).
  2. Pull latest changes: git pull
  3. Checkout the branch: git checkout feat/syntax-cite-conceal

lervag added a commit that referenced this issue Mar 24, 2021
lervag added a commit that referenced this issue Mar 24, 2021
lervag added a commit that referenced this issue Mar 25, 2021
lervag added a commit that referenced this issue Mar 25, 2021
lervag added a commit that referenced this issue Mar 25, 2021
@lervag lervag closed this as completed Mar 25, 2021
@lervag
Copy link
Owner

lervag commented Mar 25, 2021

This should now work, but let me know if I've missed something!

@whisperity
Copy link
Author

@lervag Could you please also add the \footcite{} command to behave the same way?

Oh yeah, I'm working on a presentation now, and realised there is a separate command for Beamer-y stuff.
Screenshot_20210409_130956

@lervag
Copy link
Owner

lervag commented Apr 9, 2021

Is \footcite a beamer command, a biblatex command, or a natbib command?

@whisperity
Copy link
Author

It seems like it's coming from biblatex, actually. 109th page of the documentation seems to be where it's explained.

lervag added a commit that referenced this issue Apr 9, 2021
@lervag
Copy link
Owner

lervag commented Apr 9, 2021

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ready-to-implement Discussions are over, implementation should start
Projects
None yet
Development

No branches or pull requests

3 participants