vim syntax folding (unintentionally) creates nested folds - regex

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

Related

Notepad++ - Selecting or Highlighting multiple sections of repeated text IN 1 LINE

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

Vim: How to apply external command only to lines matching pattern

Two of my favorite Vim features are the ability to apply standard operators to lines matching a regex, and the ability to filter a selection or range of lines through an external command. But can these two ideas be combined?
For example, I have a text file that I use as a lab notebook, with notes from different dates separated by a line of dashes. I can do something like delete all the dash-lines with something like :% g/^-/d. But let's say I wanted to resize all the actual text lines, without touching those dash lines.
For a single paragraph, this would be something like {!}fmt. But how can this be applied to all the non-dash paragraphs? When I try what seems the logical thing, and just chain these two together with :% v/^-/!fmt, that doesn't work. (In fact, it seems to crash Vim...)
Is there a way to connect these two ideas, and only pass lines (not) matching a pattern into an external command like fmt?
Consider how the :global command works.
:global (and :v) make two passes through the buffer,
first marking each line that matches,
then executing the given command on the marked lines.
Thus if you can come up with a command – be it an Ex command or a command-line tool – and an associated range that can be applied to each matching line (and range), you have a winner.
For example, assuming that your text is soft-wrapped and your paragraphs are simply lines that don't begin with minus, here's how to reformat the paragraphs:
:v/^-/.!fmt -72
Here we used the range . "current line" and thus filtered every matching line through fmt. More complicated ranges work, too. For instance, if your text were hard-wrapped and paragraphs were defined as "from a line beginning with minus, up until the next blank line" you could instead use this:
:g/^-/.,'}!fmt -72
Help topics:
:h multi-repeat
:h :range!
:h :range
One way to do it may be applying the command to the lines matching the pattern 'not containing only dashes'
The solution I would try the is something like (not tested):
:g/\v^(-+)#!/normal V!fmt
EDIT I was doing some experiments and I think a recurvie macro should work for you
first of all set nowrapscan:
set nowrapscan
To prevent the recursive macro executing more than you want.
Then you make a search:
/\v^(-+)#!
Test if pressing n and p works with your pattern and tune it up if needed
After that, start recording the macro
qqn:.!awk '{print $2}'^M$
In this case I use awk as an example .! means filter current line with an external program
Then to make the macro recursive just append the string '#q' to the register #q
let #q .= '#q'
And move to the beggining of the buffer to apply the recursive macro and make the modifications:
gg#q
Then you are done. Hope this helps

syntax highlighting between matching parenthesis

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!

Vim syntax highlighting for a match on several lines

I am implementing on vim a syntax file to highlight a hierarchy like this
| text at level 1
| | text at level 2
| | text at level 2
| | | text at level 3
| text at level 1
For example I use
syn match myMatch +^\(| \)\++
to highlight the level indicators. However, I would also like to highlight wrong patterns like these
| text at level 1
| | | text at level 3
which increment the levels by more than one. I have written the following syntax match
syn match myWrongMatch +^\(\(| \)*\)\(\n\|[^|].*\n\)\1\(| \)\{2,}+
It may not be optimal but it does the job. The problem is that the matches are checked by vim on the line which is being edited so that if I fix the error by removing a level on the second line it will stop highlighting the second line but still highlight the first one until I also edit it (like remove and rewrite a character).
This problem is that I can only match a line using the next line information but not the opposite. Since this doesn't seem possible with a regex match, I would like to know if it is possible to ask vim to check for matches in both the currently edited line and the previous one (or a broader context) ? Another solution may be to implement this by a region which checks the context but I have been unsuccessful with that so far.
EDIT: The answer is actually in the vim help at :syn-sync-linebreaks (thanks Herbert Sitz for pointing me to the right section).
When using a pattern that matches multiple lines, a change in one line may
cause a pattern to no longer match in a previous line. This means has to
start above where the change was made. How many lines can be specified with
the "linebreaks" argument. For example, when a pattern may include one line
break use this:
:syntax sync linebreaks=1
The result is that redrawing always starts at least one line before where a
change was made. The default value for "linebreaks" is zero. Usually the
value for "minlines" is bigger than "linebreaks".
This works perfectly.
You can try automating a syntax sync operation. For example, try putting this in the InsertEnter autocmd, which will sync syntax whenever you exit insert mode:
au InsertLeave * syntax synch minlines=50
Not a perfect solution. Maybe adding more autocmds would help. It depends partially on what your documents are going to look like, how big they're going to be, how you're editing.
For help read more about syntax syncing: :h syn-sync
This isn't typical use of syncing, since main purpose, as I understand it, is to automatically search around edited lines when they're in syntax regions. You're not using regions, so you need to initiate sync using the autocmd. Maybe you could define a region just for purpose of making sure syntax sync reevaluates syntax over group of lines--without needing the autocmd--even if the region is not going to be used for highlighting.

How to save the error output of gcc to file

When I compile my code I get a bunch of errors which I span through the screen and I can see where does the error start. How can I save the output of gcc to a file?
I tried tricks like
gcc > log.txt
or grepping the result but it didn't work. Searching google yields mostly result on explaining how to print to file with c++
GCC outputs errors to the standard error stream not to the standard output stream. You need to redirect standard error, instead of standard output. In bash:
gcc 2> log.txt
I personally found out that merely outputing the error to a file would not help. In fact the easiest thing that could help me was to avoid wrapping the error lines which are usually super long. So, I decided to use vim highlighting to see the errors better.
Without the highlighter (View Larger Image)
With the highlighter (View Larger Image)
.
And fortunately, there was a very easy way to set up a new syntax highlighting in VIM.
Follow these steps and you will be more productive working on heavily templated C++ codes:
Create a new VIM custom syntax highlighting rule set
you have to define the syntax highlighting rules. Put the following in a file called cerr.vim and keep it for example in $HOME/vim_syntax/cerr.vim
"Set line wrapping to off to see more error lines in one page
set nowrap
set showmatch
"I use stl and boost alot so it is good to remove the namespaces from the error file :)
silent! %s/st![enter image description here][2]d:://g
silent! %s/boost::fusion:://g
silent! %s/boost:://g
"Usually I am not interested in the file paths until I can locate the error so I tried to
"hide them
silent! %s/\/[^\.]*\// /g
"By default syntax highlighting for each line is limited to 3000 characters
"However, 3000 characters is not sufficient for lengthy C++ errors, so I change it to 20000
set synmaxcol=20000
"Now I define the keywords that I would like them to be highlighted
syn keyword cerrInfo instantiated
syn keyword cerrError error Error ERROR
syn keyword cerrWarning warning Warning WARNING
"-------------------------------------
"In this step I would like to distinguish the prefix in each line (which shows the file name) from the rest of the line
syn region cerrLine start=/^/ end=/\:/
syn region cerrSeparator start=/^\.+/ end=/\./ fold oneline
"I want to make templated type information less visible while debugging
"You have to remember that a type can have nested types. So I define three regions
syn region cerrTemplate1 matchgroup=xBracket1 start=/</ end=/>/ contains=cerrTemplate2 fold oneline
syn region cerrTemplate2 matchgroup=xBracket2 start=/</ end=/>/ contains=cerrTemplate3 fold contained oneline
syn region cerrTemplate3 start=/</ end=/>/ contains=cerrTemplate3 contained oneline fold oneline
"Now I would like to highlight whatever is in parenthesis with a different color so I make
"another region in here. This makes sure that function arguments can have different color
syn region cerrPar matchgroup=xBracket start=/(/ end=/)/ contains=cerrTemplate1 oneline fold
"GCC puts the real type information in brackets, let's group them separately
syn region cerrBracket start=/\[/ end=/\]/ contains=cerrTemplate1,cerrPar oneline
"Again GCC puts the error in these weird characters :) So I define a separate region here
syn region cerrCode start=/‘/ end=/’/ contains=cerrPar,cerrBracket,cerrTemplate1 oneline
"And finally I would like to color the line numbers differently
syn match cerrNum "[0-9]\+[:|,]"
"--------------------------------------------------------------------------
"Now the fun part is here, change the colors to match your terminal colors.
"I Use the following colors for my white background terminal.
"In the following we assign a color for each group that we defined earlier
"Comment is a default VIM color group
highlight link cerrInfo Comment
"We use custom coloring for the rest
highlight default cerrWarning ctermfg=red ctermbg=yellow
highlight default cerrError ctermfg=white ctermbg=red
highlight default cerrLine ctermfg=grey term=bold
highlight default cerrSeparator ctermfg=darkgrey
highlight default cerrTemplate1 ctermfg=grey term=bold
highlight default cerrTemplate2 ctermfg=grey term=bold
highlight default cerrTemplate3 ctermfg=grey
highlight default cerrCode cterm=bold ctermfg=darkgrey
highlight default cerrBracket ctermfg=darkgreen
highlight default xBracket1 ctermfg=darkgrey term=bold
highlight default xBracket2 ctermfg=darkgrey
highlight default cerrPar ctermfg=yellow
highlight default cerrNum ctermfg=red
Change your .vimrc file
Now, you have to tell vim to use your new highlighting for files with specific extension. In my case I would like to output my error files to error.ccerr, put the following in your .vimrc in your home folder:
au BufRead,BufNewFile *.cerr set filetype=myerror
au Syntax myerror source $HOME/vim_syntax/cerr.vim
What I say in the above is that when files with the extension .cerr are opened using VIM, they will be considered of type myerror. In the second line I am saying that VIM should use my syntax highlighting rule set which I defined in the previous step for all myerror files.
Send your error output to a .cerr file and open it with VIM
This step is the easiest, we send all errors and warning to error.cerr and if there is any error in the file we immediately open the .cerr file using VIM.
g++ failing.cc &> error.cerr || vim error.cerr