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
dac is fooled by braced text following the command #2628
Comments
I would not call this a bug; rather, it is a quite hard limitation. There's been some discussions on this topic earlier. I could not quite find the issue threads. However, I remember the main conclusions: What we really want is a command text object that matches Doing 1) is possible, but it does imply a lot of work for maintaining the command data. And this is not something I want to do personally. And 2) seems even harder. Instead, we/I decided to go for a more pragmatic choice: |
@lervag yep, I see that. That is why I proposed to rely on spaces. How many people would put one or more spaces in between two arguments of a command (without a line break first)? Plus, we could have an option to govern this variation of a non perfect solution. |
Ok, yes, that's a nice idea. The relevant code is here: vimtex/autoload/vimtex/cmd.vim Lines 691 to 702 in 8ef5b0d
It would not be too hard to add an option to specify the rules here. Something like this:
Heh, I've stopped thinking like that. It turns out, if I make assumptions on what someone will or will not do, I'm usually wrong. So, in cases like this, I try and consider the actual possible solutions and then choose one that seems most sensible. Right now, it seems you are making a sensible suggestion for improving things. :) |
I would be happy to get some help with this text and how to present the behaviour. @kiryph Do I remember correctly that you were part of the discussions earlier where the current behaviour was determined? |
@lervag Unfortunately, I also do not have a clear memory about this anymore. According to github search, the textobjects
I had requested surround-like behavour with A vaguely related matter was about folding of certain commands, which has lead to a configuration dictionary where a user can specify how to fold certain commands (#828):
However, I agree that this is not an advisable route for the text objects, even though this dictionary could be exploited for the text objects. If I recollect it correctly, I avoided the matter for the text objects based on targets.vim by relying on the existing VimTeX internal methods used for the standard text objects in #1384 (not 100% certain about my recollection and I did not quickly find a discussion in the PR or related issues). Back to the actual issue of I think using the proposed way of formatting code to enable better text objects in VimTeX can be an improvement since a perfect solution is not possible:
However, I am not sure about all suggestions:
I guess a first improvement can be indeed to consider In a new line indentation can be added as formatting and not as command termination. One could resolve this by getting the vim setting For example the user sets \begin{quote}
\cmd{1st arg}
{new block}
\end{quote} then \begin{quote}
\cmd{1st arg}
{2nd arg}
\end{quote} would mean the command has not ended and there is another mandatory argument However, I fear that autoformatting tools might remove the additional space when applied. |
Thanks! Perhaps you did not have a clear memory, but at least you did a good job of tracing old discussions!
Although this is slightly off topic, I find it interesting and want to make a comment: I would be very surprised if there are not many examples of commands where the same behaviour for
I agree with most of your comments. To be short; how about this as a proposed solution: No new option, instead, change the current behaviour to this (and properly document it): \cmd{}{}...{} % n-args
\cmd{}{} {} % 2-args
\cmd{} {}{} % 1-arg
\cmd{}
{} % 2-args (when next line braces align according to indent rules)
\cmd{}
{} % 1-arg (if not) If I remember correctly, indent rules are always to put the next
Yes; it is clear that the case with newlines is hard. Perhaps we can split the decision in two:
|
|
How about putting it all in the hands of the user? From the core side, I would implement it something like this: if ! call(g:vimtex_cmd_separator_func, [s:text_between(a:start_pos, l:open) ])
return {}
endif We keep the current default with the change suggested in 1 from earlier and implement it with a function like this: " If user returns v:false or 0, then the greedy parser is aborted.
function! MyCmdSeparatorRule(separator_string)
let l:lines = split(a:separator_string, "\n", v:true)
return empty(l:lines[0])
\ && len(l:lines) <= 2
\ && empty(substitute(l:lines[1], '\s\+', '', 'g'))
endfunction This should give a lot of flexibility to the user; and if we give a simple example of how to customize, it should not be too hard. |
I've implemented an initial version of this in the branch issue/2628. I've not opened a PR for it yet, but feel free to look into it/test it! |
Sorry I've not undestood how to use it. I've tried with defining |
So, either I'm wrong and this is a bad idea, or we need some further work on explaining and on the documentation (non existant right now). Can you show me the function you are using now that does not work? |
Read the last line of this comment first. No, I haven't written it. I picked yours: function! MyCmdSeparatorRule(separator_string)
let l:lines = split(a:separator_string, "\n", v:true)
return empty(l:lines[0])
\ && len(l:lines) <= 2
\ && empty(substitute(l:lines[1], '\s\+', '', 'g'))
endfunction defined the global variable let g:vimtex_cmd_separator_func = 'MyCmdSeparatorRule' and gave it a try by pressing \documentclass{article}
\begin{document}
\textcolor{red} {caio}
\end{document} Since it errored, I inserted That's from memory. But now that I've tried again, I can't reproduce it. In the sense that it doesn't error. |
You've made some errors here, e.g. using a wrong option name. But I also made an error in the suggested function. This should work: set nocompatible
set runtimepath^=~/.local/plugged/vimtex
set runtimepath+=~/.local/plugged/vimtex/after
filetype plugin indent on
syntax enable
nnoremap q :qall!<cr>
function! MyCmdSeparatorRule(separator_string)
let l:lines = split(a:separator_string, "\n", v:true)
return empty(l:lines[0])
\ && len(l:lines) <= 2
\ && (len(l:lines) == 1 || empty(substitute(l:lines[1], '\s\+', '', 'g')))
endfunction
let g:vimtex_parser_cmd_separator_check = 'MyCmdSeparatorRule'
silent edit test.tex Now with |
So, as far as I can tell, my proposed solution should work. But we may want to consider a better name for the option and we need good documentation for this with one or more good examples. |
Oh, so Ok, I see how the default implementation works and how the one in your last message works. Looks good! |
I tried, it looks ok. I mean, the default is fine, and the user can customize as they like. So I guess the most important thing to review is the doc itself. I'd go for This option specifies the policy for deciding whether successive `[arg]`/`{arg}`s following
a `\command` are arguments to that `\command`.
In fact, parsing a LaTeX command without additional knowledge, is a hard problem.
When we read `\foo{bar}{baz}` — is `{baz}` going to be consumed as an argument
to `\foo`? The only way to know this is to read the definition of the `\foo` command/macro.
A pragmatic choice when we write a parser, therefore, is to rely on some heuristics and
common practises. This will never be perfect, but it can be good enough for practical use.
In VimTeX, the core heuristics are that a command will look like this:
>tex
\foo<overlay>[[opt]{arg}]...
\begin{name}<overlay>[[opt]{arg}]...
<
and the parser greedily swallows as many groups of `[opts]` and `{args}`
as possible as long as the function specified via this option returns true
for the text between successive such groups.
The default function will allow a line break and possibly white space on
the preceding line before a new group.
... and so on |
Thanks! I've pushed with your suggested improvements to the docs. I appreciate the feedback; feel free to add additional feedback, I'll be happy to make further updates. |
Description
Probably this "bug" has no solution, unless we have a list of
\commands
and the number of arguments they take. Or we can have some heuristics.Indeed, this is a command,
\textbf{url}
, followed by some braced\em
phasisedtext
,whereas this is one command, i.e. a link to
url
with text an\em
phasizedtext
, and nothings elseCurrently dac interprets both in the latter way, so it correctly deletes the whole thing in the latter case, but mistakenly deletes the whole thing in the former case too.
I'm not sure what the correct behavior should be. Maybe we shoud determine the number of arguments of a command by requiring that two following args are not separated by just whitespace? For instance, something like this could be accomplished,
Steps to reproduce
Put this text in a TeX file
then hit dac (cursor anywhere before the space).
Expected behavior
Only
\textbf{some bold}
should be deleted.Actual behavior
All the
\textbf{some bold} {\em some emphasis}
is deleted.Do you use a latexmkrc file?
No
VimtexInfo
The text was updated successfully, but these errors were encountered: