I can't seem to use spaces in snippets at all. Ultisnips throws errors on the following:
snippet 'dv(?=[ \n])' "derivative" rA 2
\dv{$1}{$2}$0
endsnippet
My goal is to expand the snippet automatically if and only if dv precedes a space or newline, without removing the space or newline. Whenever I try to insert a space in any snippet, UltiSnips throws
UltiSnips.snippet.source.file.base.SnippetSyntaxError: Invalid multiword trigger: ''dv(?= )' "derivative" rA 2' in ~/.vim/UltiSnips/tex.snippets:23
So the issue seems to be that "multi-word triggers" aren't allowed. Is there a reason for this, and is there a workaround (that doesn't involve a negative lookahead for every character that isn't a space or newline)?
me from yesterday.
The issue is that the priority was improperly placed, that is, the previous line should have 'priority 2'. This has nothing to do with being unable to use spaces in snippets.
Related
Background
I want to convert an if statement from Fortran to C++. I like to have braces on a new line.
So I want to make
! this may be nested so indentation is unknown
if ( condition ) then
block
end if
to
if ( condition )
{
block
}
Changing end if to } is easy since the indentation is already how I want it. I just used :%s/end if/}/gc.
However, changing then is more challenging. I need to create a new line and set its the leading whitespace to the same as the previous line.
The closest I have to a solution is :%s/then/\=printf("\n%s{",indent(line('.')))/gc
However I want to use the value returned from indent(line('.') to set the number of indents.
Problem
Can I use a number I receive from a function to set the number of tabs at the beginning of line in a search and replace?
You want to substitute then with:
a newline,
followed by n spaces, as many as used for indenting the current line,
followed by an opening brace.
As is, your command does the following:
a newline,
followed by the number of spaces used for the indentation of the current line,
followed by an opening brace.
:help repeat() to the rescue:
:%s/then/\=printf("\n%s{",repeat(' ',indent(line('.'))))/gc
But there is still room for improvement…
you only want to substitute trailing thens so the g flag is useless:
:%s/then/\=printf("\n%s{",repeat(' ',indent(line('.'))))/c
the search pattern may match other thens so it should be restricted a little:
:%s/then\s*$/\=printf("\n%s{",repeat(' ',indent(line('.'))))/c
also, the pattern should include any whitespace before the then to avoid leaving annoying trailing whitespace behind:
:%s/\s*then\s*$/\=printf("\n%s{",repeat(' ',indent(line('.'))))/c
line('.') is unnecessary:
:%s/\s*then\s*$/\=printf("\n%s{",repeat(' ',indent('.')))/c
and we could use the new-ish "method" syntax to limit parenthesis nesting:
:%s/\s*then\s*$/\=repeat(' ',indent('.'))->printf("\n%s{")/c
Summary
I'm not asking your opinion about the proposed change being good, bad, amazing, or what.
I'm just asking your help to answer this question: does the change I propose for the syntax coloring of the comments break the syntax coloring of something else (keywords, strings, syntax errors, ...)?
The question above is not opinion based, as my change either does break something or it doesn't. That's it.
Original question
I have created the issue #5876 on Vim's GitHub page to propose a change to vim/runtime/syntax/sed.vim, but it has not received much attention, so I'm considering creating a PR for the change.
In fact, I created an issue instead of a PR because I'm not totally confident the change is not disruptive, hence this question.
The issue is with line 20:
syn match sedComment "^\s*#.*$"
because of which only "full line" comments are colored as comments. Using trailing comments following a command (allowed by GNU sed, for instance), stimulates some red background coloring (since it's considered an error by the syntax coloring logic, I guess).
I think it would be reasonable to relax this definition of comments to permit GNU sed-style comments, for the simple reason that the rule is less restrictive.
In this respect, I have noticed that changing that line to
syn match sedComment "\s*#.*$"
i.e. just removing the anchor ^, seems to be enough. I have also tried testing it by putting some # in search and replace strings in a sed script, and it seems fine.
However I don't feel confident with Vim syntax coloring files, so I would like to be sure that regex, as I edited it, is not causing false positives.
To demonstrate why I'm not confident about it, take this single-line sed script
s/aaa/bbb/#ccc
here # is not colored as a comment, and ccc's background is red (like an error?), whereas, just adding a space, give the correct coloring:
s/aaa/bbb/ #ccc
Therefore I think that my edit works (or seems to work) because of precedence rules between the several syntax coloring directives (with respect to this specific example with s/aaa/bbb/#ccc, I think that # just after the closing delimiter of the s command has a meaning in the language, but I don't know; the GNU Sed man page doesn't say anything about it).
Edit
Another example suggested in the comments is the following, the syntax coloring of which is not broken by the proposed change
s/#if !defined(\([^)]*)/#ifndef \1/ # with or without this comment is fine
My research
I have eventually found some time to study :h E410 and now I have an answer.
From there I read that
1. Keyword
[...] It will only match with a complete word [...]
2. Match
This is a match with a single regexp pattern.
3. Region
This starts at a match of the "start" regexp pattern and ends with a match with the
"end" regexp pattern. Any other text can appear in between. A "skip" regexp
pattern can be used to avoid matching the "end" pattern.
Since the line I'm going to change uses the syntax 2.,
point 1. is not relevant,
point 3. is relevant, as in general there can be an overlap between the what syn match and syn region match.
(By the way, I verified that syn region uses a lazy regex, probably \_.\{-} looking at some examples afterwards, to match stuff between the start and end regexp patterns.)
Then from :h :syn-priority
An item that starts in an earlier position has priority over items that start in later positions.
The answer
Therefore, changing
syn match sedComment "^\s*#.*$"
to
syn match sedComment "\s*#.*$"
should not introduce any syntax error, the reason being that if a text matching the above regex is not actually a comment (as is the case for e.g. the command s/#/hash/), then it must be preceded by some non-comment syntax which will be matched by other syn match/syn region groups. Since this match starts before where the group sedComment starts to match, the former has precedence on the latter.
In conclusion, unless something is broken with sed.vim already, the proposed change will not result in a wrong syntax coloring.
Further observations
Actually, there is already something wrong in sed.vim, and my proposed edit does not solve it (I should edit some other line in sed.vim to fix it, but I'm a bit lazy now).
For instance, in the following line, which is illegal because a is not a valid flag, a does not get the Error coloring.
s/x/y/a
My proposed edit does not solve this bug.
For the same reason, since some other syntax rule is eating 1 character after the third delimiter in the substitution command, the GNU-sed-valid comment in the following command is incorrectly colored
s/x/y/#hello
# │└───┴─── colored as Error
# └─ not colored
The coloring would be wrong even for an old version of sed which does not allow trailing comments, as the Error coloring should include the # too.
My proposed edit does not solve this bug either.
One more observation
The change I propose causes single-letter commands to be highlighted as Error if they are followed by a comment
p # this is a comment
│ └─────────────────┴─── colored as Comment (ok)
└────── colored as Error (bad)
This again, is not a worsening, as the current sed.vim colors almost the whole line above as an Error.
I'm writing an errorformat string, and it works for the most part. My problem is that I have lines like this as the makeprg output:
Some text I want to show in the QuickFix window^M
Yes, the line ends with an spurious ^M character I want to remove. So, what I want in my QuickFix window is this, without the ^M character:
|| Some text I want to show in the QuickFix window
but I have this instead:
|| Some text I want to show in the QuickFix window^M
So far, this is the relevant part of my errorformat:
set errorformat=%+GSome text%m
I've tested, without success, something like this:
set errorformat=%+GSome text%m%-G^M%.%#
but it throws an error (not from the ^M which is a literal control-M char, not a caret followed by an M).
Obviously the solution is not using %G but I am at a loss here.
How can I remove the line ending character from the line here? And also, removing the initial || would be a plus, but I think it's impossible to do in Vim.
Thanks in advance!
Edited to make clearer how the input text looks
Well, turns out I found a solution, probably not very good but it works, using trial and error.
set errorformat=%\\(Some Text%*[^.]).%\\)%\\#=%m
That is, the solution is using the Vim pattern (regex) expressions within errorformat, which has a quite arcane look but works, together with %* to match unknown text on the rest of the line
The solution uses \#=, a zero-width match, and requires some kind of terminator for the line, which appears before the ^M character I want to ignore, and some kind of text appearing somewhere on the line to match that line and not others.
Probably there is a much better solution but this is the best I could do myself.
I mainly use curly brackets { } to move around in vim when I'm working on something. However, sometimes it will skip too many lines. I assume this is because there is no paragraph break, because if I go put new lines in, I can skip to those. This is mainly an issue when working on HTML that I didn't type or after pasting in some lines. It is very annoying when it skips too many lines for me to see what's between where I started and where I ended.
I hope I've described this well enough for some of you to know what I'm talking about.
Is there a remedy for this other than going through using j and adding line breaks? It's a huge hassle and blow to productivity when having to do this.
EDIT: I wanted to mention I only use the curly brackets to get close to pieces I need to work on. After I am close, I use other means.
That sounds like an issue where some lines contain only whitespace, and so don't get counted as paragraph breaks, even though they look like they should. Since it's only an issue in a few situations, I'd suggest just running a substitution to clean up those lines whenever you notice that it's a problem. For example:
%s/^\s*$//g
To translate what the regex means:
^ match the start of a line
\s* match any number of whitespace characters
$ match the end of the line
So it matches anything that contains only whitespace between the start and end of the line, and replaces it with nothing (note that replacing $ does not overwrite the newline character).
So oftentimes, while editing with Vim, I'll get into a variety of situations where whitespace gives me hassle. For example, say I have a comment like this:
#This program was featured on the Today show, it is an algorithm for promoting world peace in third-world countries
#given the name of that country and the name of a celebrity to endorse its cause
If I want to, for example, trim the lines so they go to X characters, I end up putting a newline somewhere in the middle of the top line to get this (after hitting the newline and auto-indenting):
#This program was featured on the Today show, it is an algorithm for promoting
world peace in third-world countries
#given the name of that country and the name of a celebrity to endorse its cause
I then add a # to the beginning of the line, and that's all well and good, but then I want that line to line up, too. To do so, I have to delete the newline, all the whitespace for the indent on the next line, and then the commenting # mark. It doesn't take an awfully long amount of time to do that, but this and similar situations all add up over a day's worth of coding.
Now the example above is pretty specific, but my question isn't. What's a good way in Vim to delete all whitespace INCLUDING NEWLINES up until the next non-whitespace character? If Vim already has movements that do that, that would be awesome, but if not, does anyone have a favorite Vim function they use to do the above that could be mapped to a key? At the very least, am I missing some Vim usage idiom that prevents me from even having to worry about this case?
EDIT: Formatting to width, while useful and applicable to the case above, isn't the focus of this question. I'm concerned more with whitespace removal that doesn't stop at the end of a line, but instead carries on to the first non-whitespace character of the next line.
You really just want to reformat that comment to fit the current 'textwidth'. If the comment is a paragraph (i.e., separated by a line of whitespace above and below), then you can just use gqip (gq is the reformat command, ip is the "inner-paragraph" text object) to reformat it. If it's not a standalone paragraph, you can visually select those lines and then use gq.
This likely also relies on having 'formatoptions' set correctly to make sure the comment characters are handled properly, but in many cases the ftplugin has already done that.
This is a while later, but I found that there is a command that does what I need to in 90% of circumstances:
J -- join line below to the current one
This command seems to work:
:.s/\W*$\n\W*//g
it uses a replace to remove whitespace up to end of line and the new line at the end.
In this example:
testting aad $
asdjkasdjsdaksddjk$
(to see meta characters in vim use the command :set list)
if you place the cursor on the first line and use the first command it will delete everything from aad to $ (not including aad but including $ and a newline.)
Also, note for what you are doing it is far more efficient to use an external program to format comments for you. In particular, par is a great small C program that edits text and wraps it to desired lengths.
If you have par in your path, to do what you are trying to do is as easy as selecting the block of comment with Shift+v and running the command
:!par 40pgr
where 40 is the desired width in columns.
If you are feeling hackish, write your own program in C/perl/C++/python that edits comments however you like, then put it in path and use the external filter command :! to process blocks of text through it.