I want to get syntax highlighting inside of a bash heredoc. In addition, I want bash variable dereference and command substitution highlighting in the heredoc.
Using these instructions as a starting point, I was able to add variable dereferencing by examining sh.vim. I imagine you could accomplish command substitution in a similar fashion.
let s:bcs = b:current_syntax
unlet b:current_syntax
syntax include #YAML syntax/yaml.vim
syntax region hereDocYAML matchgroup=Statement start=/<<-\?\s*\z(YML\)/ end=/^\s*\z1/ contains=#YAML,hereDocDeref,hereDocDerefSimple
syn match hereDocDerefSimple "\$\%(\h\w*\|\d\)"
syn region hereDocDeref matchgroup=PreProc start="\${" end="}" contains=#shDerefList,shDerefVarArray
hi def link hereDocDeref PreProc
hi def link hereDocDerefSimple PreProc
My problem is, this doesn't appear to work in any sort of block (if, function, for, etc.). For example:
The only thing I know is that this is not an indentation problem. Changing indentation has no effect, and using indentation outside of a block works properly.
The contains on the definition of shIf appears to limit the possible highlights to whatever items are in shIfList group.
Adding your item to the group as follows will give you highlighting withing that region:
syn cluster shIfList add=hereDocYAML
The same principle holds for all other blocks. For example:
syn cluster shFunctionList add=hereDocYAML
syn cluster shLoopList add=hereDocYAML
It should be noted that the approach you've outlined is not generally useful. First of all, it requires that the included syntax file use groups for their contains definitions.
In addition, it works for YAML because bash dereference syntax and YAML syntax do not conflict. For more complicated syntaxes like sed or awk, you will have conflicts, and the rules to resolve those conflicts will likely require a new syntax entirely.
Related
In Sphinx (the ReStructuredText publishing system), are there any obscure rules that limit what a literal block can contain?
Background: My document contains many literal blocks that follow a double-colon paragraph, like this:
Background:... follow a double-colon paragraph, like this::
$ sudo su
# echo ttyS0,115200 > /sys/module/kgdboc/parameters/kgdboc
This block (with a different preceding paragraph) is one of the ones that issues an error: "WARNING: Inconsistent literal block quoting." The message indicates that the error is in the "echo" line. In the HTML output the literal block contains only the "sudo" line; the "echo" line is treated as ordinary text.
I haven't been able to identify any common property in the lines that report errors, or anything that distinguishes them, as a class, from lines in other literal blocks that don't get errors.
I stripped down the project to isolate the problem, and I identified it that way.
I had a numbered list item that contained a double-colon literal block that was indented only as far as the list item's text, like this:
2. Set up the... directory::
$ A Linux command
$ Another Linux command
$ And ANOTHER Linux command
$ etc.
When I indented the literal block further, the problem went away.
I was misled by two things:
The message does not point to the first line in the literal block, but to some apparently random line within it. In the case above, it pointed to the fifth line (out of eight) in the block!
In most cases this form of indention, although incorrect, works just fine.
Isolating the problem is a brute-force method of solving it, but is often effective when deduction fails. I'll keep that in mind in the future.
Right now I am trying to write a syntax highlighter for my custom language using Monarch. However, in my language (and many others), sometimes the syntax highlighting could change based on what's on the next line. For example, here is one such case in Javascript:
fn(foo // here, foo is an argument
=> bar)
fn(foo // but here, foo is an identifier
+ bar)
Unfortunately it seems like by default, monarch regexes work line by line. So I can't figure out how I would achieve this. Is there a way to enable multi-line regexes in Monarch? Or is there some other way to solve this?
I have created a custom directive for a documentation project of mine which is built using Sphinx and reStructuredText. The directive is used like this:
.. xpath-try:: //xpath[#expression="here"]
This will render the XPath expression as a simple code block, but with the addition of a link that the user can click to execute the expression against a sample XML document and view the matches (example link, example rendered page).
My directive specifies that it does not have content, takes one mandatory argument (the xpath expression) and recognises a couple of options:
class XPathTryDirective(Directive):
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {
'filename': directives.unchanged,
'ns_args': directives.unchanged,
}
def run(self):
xpath_expr = self.arguments[0]
node = xpath_try(xpath_expr, xpath_expr)
...
return [node]
Everything seems to be working exactly as intended except that if the XPath expression contains a * then the syntax highlighting in my editor (gVim) gets really messed up. If I escape the * with a backslash, then that makes my editor happy, but the backslash comes through in the output.
My questions are:
Are special characters in an argument to a directive supposed to be escaped?
If so, does the directive API provide a way to get the unescaped version?
Or is it working fine and the only problem is my editor is failing to highlight things correctly?
It may seem like a minor concern but as I'm a novice at rst, I find the highlighting to be very helpful.
Are special characters in an argument to a directive supposed to be escaped?
No, I think that there is no additional processing performed on arguments of rst directives. Which matches your observation: whatever you specify as an argument of the directive, you are able to get directly via self.arguments[0].
Or is it working fine and the only problem is my editor is failing to highlight things correctly?
Yes, this seems to be the case. Character * is used for emphasis/italics in rst and it gets more attention during syntax highlighting for some reason.
This means that the solution here would be to tweak or fix vim syntax file for restructuredtext.
I would like to highlight the arguments of a Ruby function in Sublime, when they are used inside the function. Like so:
def my_func(arg1, arg2 = nil)
puts arg1 # should be highlighted
puts arg2 # should be highlighted
end
I've been messing with Sublime's plist syntax highlighting format for a while (same as Textmate's), but having trouble figuring out how to capture one group (the args in the def line) and use them to match more expressions in another group (the whole method)
I have seen \1 and \2 being used in EndCapture groups before, which gives me hope that this is possible, for example by using \1 in a match group. But I just can't seem to get it to work. Anybody have any ideas?
(too long for comment)
If writing regexes in XML/PLIST is driving you batty, try installing the PackageDev plugin via Package Control. There is an option to convert PLIST .tmLanguage syntax files to YAML, and when you're done editing you can convert it back to PLIST. This way, you don't have to mess around with trying to get all the <dict><array><whatever> tags correct in the .tmLanguage file, and you can focus on the regexes, capturing groups, etc. It also uses the Oniguruma syntax, which I assume you're at least somewhat familiar with if you're a Rubyist. I maintain an improved syntax for Python, and my work has been so much easier since I started using the .YAML-tmlanguage format.
Good luck!
I am using vim, and I want to highlight the following construct (which is accepted in ifort, but rejected by xlf)
write(5,*), foo
note the comma before the foo variable. I tried the following
syn match fortranWriteComma "write\s*\(.?*,.?*\),"
This works well as long as instead of "write" I use anything else. Example
syn match fortranWriteComma "whatever\s*\(.?*,.?*\),"
this matches and correctly highlights
whatever(5,*),
If I use write, the keyword recognition of write kicks in and does not perform any highlighting. How can I set vim to have the match prevail over the keyword recognition ?
I partially solved by redefining the keyword as a match
syn clear fortranReadWrite
syn keyword fortranReadWrite backspace close endfile inquire open print read rewind
syn match fortranWrite "write" contained
hi def link fortranWrite Keyword
syn match fortranWriteComma "write\s*(.*,.*)," contains=fortranWrite
hi def link fortranWriteComma Error
Unfortunately, this is still not perfect, as the "write" remains yellow, and only the parenthesized stuff becomes highlighted.
I could not fix this, but it's ok for my purposes. If anyone has a way of getting write in yellow in normal conditions, but everything red if the comma is added, please add it in comments so I can refine it.
Q. If I use write, the keyword recognition of write kicks in and does not perform any highlighting. How can I set vim to have the match prevail over the keyword recognition
A. I believe you should be able to have it both ways using a transparent syntax region:
TRANSPARENT
In a C language file you would like to highlight the () text after a "while"
differently from the () text after a "for". In both of these there can be
nested () items, which should be highlighted in the same way. You must make
sure the () highlighting stops at the matching ). This is one way to do this:
:syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/
\ contains=cCondNest
:syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/
\ contains=cCondNest
:syntax region cCondNest start=/(/ end=/)/ contained transparent
Now you can give cWhile and cFor different highlighting. The cCondNest item
can appear in either of them, but take over the highlighting of the item it is
contained in. The "transparent" argument causes this.
Notice that the "matchgroup" argument has the same group as the item
itself. Why define it then? Well, the side effect of using a matchgroup is
that contained items are not found in the match with the start item then.
This avoids that the cCondNest group matches the ( just after the "while" or
"for". If this would happen, it would span the whole text until the matching
) and the region would continue after it. Now cCondNest only matches after
the match with the start pattern, thus after the first (.