Say I hava a LaTeX document open in Vim, and I want to highlight every occurence of
{\color{red} ... }
(where the dots are supposed to symbolize some contents), that is, I want to have {\color{red}, } and everything between these highlighted. This I have done with
:syn region WarningMsg start=+{\\color{red}+ end=+}+
but I have the problem that, if I write something like {\color{red} some{thing} important}, then it is only {\color{red} some{thing} which gets highlighted, because Vim of course mathces the first occurrence of }. How can I make this Highlighting rule so that it skips matching curly brackets? Even multiple levels of such.
For clarity it is better to give each syntax region a bespoke name, and then link it to a standard colour group. I have renamed your original region redTeX.
You need to define a second region, innerBrace, defining the braces you want to ignore, and mark this region as transparent. Then redTeX should be marked to contain the transparent region, which it will then ignore.
syn region innerBrace start=+{+ end=+}+ transparent contains=redTeX
syn region redTeX start=+{\\color{red}+ end=+}+ contains=innerBrace
hi link redTeX WarningMsg
Note that in this case there is the added subtlety that redTeX itself matches as an innerBrace. I fixed this by marking innerBrace as containing redTeX.
Hope that makes sense!
Related
I'm trying to apply highlighting to all regular expression matches only on the cursor's line. This code is close but I have to redraw the screen with every time the cursor moves, and it makes the cursor a part of the regex which is not ideal.
~/.vim/syntax/abc.vim:
syn match abcline "abc\%#"
hi def link abcline Todo
Your approach with the special \%# is correct. Unfortunately, its :help explicitly warns about the necessary redraw (which isn't done automatically for performance reasons).
\%# Matches with the cursor position.
WARNING: When the cursor is moved after the pattern was used, the
result becomes invalid. Vim doesn't automatically update the matches.
This is especially relevant for syntax highlighting and 'hlsearch'.
In other words: When the cursor moves the display isn't updated for
this change. An update is done for lines which are changed (the whole
line is updated) or when using the |CTRL-L| command (the whole screen
is updated).
So, you need an :autocmd CursorMoved,CursorMovedI to trigger a redraw. Alternatively, you could embed the current line number into the regular expression (\%23l), and update the syntax definition as the cursor moves around (again via :autocmd). I'm no fan of such frequent redraws; perhaps your use case would also allow to just trigger the highlighting on demand (via a mapping), or only updates when the uses pauses (CursorHold[I] events).
Doing syntax highlighting only for the current line is unusual; also reconsider whether a global highlighting would work (if you tone down the used highlight group; especially Todo is very visually distracting).
I have a text file in Notepad++ that contains about 66,000 words all in 1 line, and it is a set of 200 "lines" of output that are all unique and placed in 1 line in the basic JSON form {output:[{output1},{output2},...}]}.
There is a set of characters matching the RegEx expression "id":.........,"kind":"track" that occurs about 285 times in total, and I am trying to either single them out, or copy all of them at once.
Basically, without some super complicated RegEx terms, I am stuck because I can't figure out how to highlight all of them at once, and also the Remove Unbookmarked Lines feature does not apply because this is all in one line. I have only managed to be able to Mark every single occurrence.
So does this require a large number of steps to get the file into multiple lines and work from there, or is there something else I am missing?
Edit: I have come up with a set of Macro schemes that make the process of doing this manually work much faster. It's another alternative but still takes a few steps and quite some time.
Edit 2: I intended there to be an answer for actually just highlighting the different sections all at once, but I guess that it not possible. The answer here turns out to be more useful in my case, allowing me to have a list of IDs without everything else.
You seem to already have a regex which matches single instances of your pattern, so assuming it works and that we must use Notepad++ for this:
Replace .*?("id":.........,"kind":"track").*?(?="id".........,"kind":"track"|$) with \1.
If this textfile is valid JSON, this opens you up to other, non-notepad++ options, like using Python with the json module.
Edited to remove unnecessary steps
I'm trying to create a new .tmLanguage file for Sublime Text 2 that defines special fenced code blocks for knitr and Markdown. These blocks take this form:
```{r example_chunk, echo=true}
x <- rnorm(100)
y <- rnorm(100)
plot(y ~ x, pch=20)
```
There are two sections: (1) the parameters ({r ...}) and (2) the actual embedded code (between the closing } and the ``` at the end). There are four scopes that need to be applied to delineate the two sections:
punctuation.definition.parameters.begin.knitr
punctuation.definition.parameters.end.knitr
punctuation.section.embedded.begin.knitr
punctuation.section.embedded.end.knitr
Using regular expressions to peg these scopes to parts of code is easy enough (partial code available here). However, two of these scopes need to be applied to the same single character: the final } in the parameters section, which ends the parameters and signifies the beginning of the fenced/embedded code.
However, it appears to be impossible to assign two scopes to the same character in a .tmLanguage file. It's not possible to end the parameters section and begin the embedded section. The first scope defined takes precedence, thus breaking the syntax highlighting.
Is there a way to use a .tmLanguage syntax definition to apply two different scopes to the same character in Sublime Text? If not, is there some way I can peg punctuation.definition.parameters.end.knitr and punctuation.section.embedded.begin.knitr to two different somethings instead of the single {? (Keeping in mind that I can't add additional characters to the code block.)
As it turns out, it appears that it's impossible to use two punctuation definitions on the same character (unless there's some way to use some crazy system of nesting to get it to work).
But I fortunately figured out a workaround: a scope can be assigned to a \n. So I can use the following regexes to simulate the overlapping scopes:
(\}) will capture the closing brace, which can be used as punctuation.section.embedded.begin.knitr
(?<=\})(.*)(\n) will capture the \n following a closing brace as the second found group, allowing me to assign it to punctuation.section.embedded.begin.knitr
Tricky, but it works.
There is an easy way I've found out. Example code in JSON:
{
"match": "((\w+))",
"captures": {
"1": {"name": "scope.one"},
"2": {"name": "scope.two"}
}
}
Should work to my knowledge.
On the other hand you can do a better job by ending the first scope with
"match": "(?=(?:\}))" or just live with the ST3 language spec. :)
- match: '((what you want to match))'
captures:
1: first.scope.name
2: second.scope.name
I'm trying to implement vim folding into an existing syntax file for the fountain.io markup language. The existing syntax file is here: http://www.vim.org/scripts/script.php?script_id=3880
But no matter what I do, my folding region doesn't end where I expect it to. The regexes work perfectly when I test them in search. But when used in a syntax region they created a series of nested folds. The fold starts on the appropriate line, and then the next fold is created inside the existing fold. Essentially I've tried to do the following so that a fold begins on any line that starts with INT or EXT, and ends after a line ends in TO: or a line begins with >:
syn region fountainScene start="^\(INT\|EXT\)" end="^\(\(\L\)* TO:\|\s*>\(.*\)\)$" fold transparent contains=fountainCharacter,fountainDialogue,fountainParenthetical,fountainSceneHeading,fountainTransition
Even stranger, if I use \ze on my 'end' argument to get the line previous to the matched line, it works as you would expect. It stops the fold on the line above the match, leaving the last line outside the fold. The following will stop folding above a line that says "CUT TO:"
\n\ze\(\L\)* TO:\n
To troubleshoot, I basically started rebuilding the syntax file from the ground up. Here is what is in the file so far (minus the hi commands) I have extensively modified the regular expressions to prevent them from overlapping with one another. The original regexes had this issue and I thought it might be the cause:
syn match fountainCharacter "^\(\s\)*\n\zs\(INT\|EXT\)\#!\(\L\)*[^:]$"
syn region fountainDialogue matchgroup=fountainCharacter start="^\(\s\)*\n\zs\(INT\|EXT\)\#!\(\L\)*[^:]$" end="^\s*$" contains=fountainCharacter,fountainParenthetical
syn match fountainParenthetical "^\s*\((.*)\)$"
syn region fountainSceneHeading start="^\(INT\|EXT\)" end="$" contains=fountainSceneNumber,fountainBoneyard,fountainNotes
syn match fountainTransition "^\(\L\)* TO:$"
syn region fountainScene start="^\(INT\|EXT\)" end="\n\ze\(\L\)* TO:\n" fold transparent contains=fountainCharacter,fountainDialogue,fountainParenthetical,fountainSceneHeading
Thanks for any help you can provide, and please let me know if I've been unclear in any way. I am using MacVim version 7.3.646 custom compiled with python support.
I finally figured this out. One of my elements was extending beyond the "end" argument. I had to use the "keepend" argument in my syn region.
This line fixed everything:
syn region fountainScene start="^\s*\(\.\|INT\. \|EXT\. \|INT\./EXT\. \|INT/EXT\. \|INT \|EXT \|INT/EXT \|I/E \|int\. \|ext\. \|int\./ext\. \|int/ext\. \|int \|ext \|int/ext \|i/e \)" end="^\(\(\L\)* TO:\|\s*>[^<]*\)$" fold transparent keepend
For more details see :he keepend
Background
I use JScript (Microsoft's ECMAScript implementation) for a lot of Windows system administration needs. This means I use a lot of ActiveX (Automated COM) objects. The methods of these objects often expect Number or Boolean arguments. For example:
var fso = new ActiveXObject("Scripting.FileSystemObject");
var a = fso.CreateTextFile("c:\\testfile.txt", true);
a.WriteLine("This is a test.");
a.Close();
(CreateTextFile Method on MSDN)
On the second line you see that the second argument is one that I'm talking about. A Boolean of "true" doesn't really describe how the method's behavior will change. This isn't a problem for me, but my automation-shy coworkers are easily spooked. Not knowing what an argument does spooks them. Unfortunately a long list of constants (not real constants, of course, since current JScript versions don't support them) will also spook them. So I've taken to documenting some of these basic function calls with inline block comments. The second line in the above example would be written as such:
var a = fso.CreateTextFile("c:\\testfile.txt", /*overwrite*/ true, /*unicode*/ false);
That ends up with a small syntax highlighting dilemma for me, though. I like my comments highlighted vibrantly; both block and line comments. These tiny inline block comments mean little to me, personally, however. I'd like to highlight those particular comments in a more muted fashion (light gray on white, for example). Which brings me to my dilemma.
Dilemma
I'd like to override the default syntax highlighting for block comments when both the beginning and end marks are on the same line. Ideally this is done solely in my vimrc file, and not in a superseding personal copy of the javascript.vim syntax. My initial attempt is pathetic:
hi inlineComment guifg=#bbbbbb
match inlineComment "\/\*.*\*\/"
Straight away you can see the first problem with this regular expression pattern is that it's a greedy search. It's going to match from the first "/*" to the last "*/" on the line, meaning everything between two inline block comments will get this highlight style as well. I can fix that, but I'm really not sure how to deal with my second concern.
Comments can't be defined inside of String literals in ECMAScript. So this syntax highlighting will override String highlighting as well. I've never had a problem with this in system administration scripts, but it does often bite me when I'm examining the source of many javascript libraries intended for browsers (less.js for example).
What regex pattern, syntax definition, or other solution would the amazing StackOverflow community recommend to restore my vimrc zen?
I'm not sure, but from your description it sounds like you don't need a new syntax definition. Vim syntax files usually let you override a particular syntax item with your own choice of highlighting. In this case, the item you want is called javaScriptComment, so a command like this will set its highlighting:-
hi javaScriptComment guifg=#bbbbbb
but you have to do this in your .vimrc file (or somewhere that's sourced from there), so it's evaluated before the syntax file. The syntax file uses the highlight default command, so the syntax file's choice of highlighting only affects syntax items with no highlighting set. See :help :hi-default for more details on that. BTW, it only works on Vim 5.8 and later.
The above command will change all inline /* */ comments, and leave // line comments with their default setting, because line comments are a different syntax item (javaScriptLineComment). You can find the names of all these groups by looking at the javascript.vim file. (The easiest way to do this is :e $VIMRUNTIME/syntax/javascript.vim .)
If you only want to change some inline comments, it's a little more complicated, but still easy to see what to do by looking at javascript.vim . If you do that, you can see that block comments are defined like this:-
syn region javaScriptComment start="/\*" end="\*/" contains=#Spell,javaScriptCommentTodo
See that you can use separate regexes for begin and end markers: you don't need to worry about matching the stuff in between with non-greedy quantifiers, or anything like that. To have a syntax item that works similarly but only on one line, try adding the oneline option (:h :syn-oneline for more details):-
syn region myOnelineComment start="/\*" end="\*/" oneline
I've removed the two contains groups because (1) if you're only using it for parameter names, you probably don't want spell-checking turned on inside these comments, and (2) contained sections that aren't oneline override the oneline in the container region, so you would still match all TODO comments with this region.
You can define this new kind of comment region in your .vimrc, and set the highlighting how you like: it looks like you already know how to do that, so I won't go into more details on that. I haven't tried out this particular example, so you may still need a bit of fiddling to make it work. Give it a try and let me know how it goes.
Why don't you simply add a comment line above the call?
I think that
// fso.CreateTextFile(filename:String, overwrite:Boolean, unicode:Boolean)
var a = fso.CreateTextFile("c:\\testfile.txt", true, false);
is a lot more readable and informative than
var a = fso.CreateTextFile("c:\\testfile.txt", /*overwrite*/ true, /*unicode*/ false);