I'm writing a syntax file to match a log format (basically column based; think syslog for a similar example), and I'm trying to set up a type of inheritance for columns.
I have two main goals with this.
First, I want to say that column 3 is the "component" field (let's say it's marked by a header; it could also be at a fixed position) and set the background to, say, Grey. I then want to say that component "foo" gets a foreground color of Red, and component "bar" gets a foreground color of Green, but they should inherit the background color of the "component" column. In this case, the field should really have two syntax matches; this also makes it easy to conceal the entire column (a la Toggling the concealed attribute for a syntax highlight in VIM)
Second, there's a field for levels; I want to set the background of the entire line for a critical level message to Red, but the foreground should be continue to be set via the normal highlighting (component, source, etc; I left off most of the other requirements).
From what I can see in the vim documentation, this doesn't seem possible. Am I missing something? Alternatively, can anyone suggest a good workaround?
Thanks
You can't (yet). For each character, Vim only uses one particular highlight group, determined by the last, "most inner" non-transparent syntax group match.
To work around this, you need to define a combined highlight group and corresponding :syntax commands. Some syntaxes (e.g. $VIMRUNTIME/syntax/html.vim, and various Wiki formats) use that for combining bold, italic and underline, but it gets tedious and repetitive after that.
There's a patch proposed that would add a combine modifier for :syntax commands; it's in Bram's Todo list.
Related
I'm new to vim syntax highlight customizations. Trying to create a text based call path description file:
// Entry point
Class1#mainMethod
Class1#privateMethod2
Class2#method3
Class3#method4
Class4#method5
In plantUML the equivalent would be:
ExternalActor -> Class1 : mainMethod
Class1 -> Class1 : privateMethod2()
Class1 -> Class2 : method3()
Class2 -> Class3 : method4()
Class1 -> Class4 : method5()
I already have some decent syntax file in place that makes it look like:
current syntax file looks like:
syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celComment "//.*$" oneline contains=celTodo
hi celComment ctermfg=yellow
hi celTodo ctermfg=green
syn match methodCall /\(#\)\#<=\w*/ contained oneline
hi methodCall ctermfg=blue
syn match className /\w*\(#\)\#=/ contained oneline
hi className ctermfg=red
syn region line start='\(\.\)\#<=\w' end='.\($\)\#=' oneline fold transparent contains=celComment,className,methodCall
Problem
I think a different background color for each occurrence of the same class would help understand the sequence better.
Is there any way to achieve this? So that Class1 will have a different background color than Class2, 3, and 4. But each class always the same, consistent color.
Syntax highlighting associates a keyword, pattern match, or region with a syntax group. A corresponding highlight group then (directly or indirectly through linked groups) determines the color and formatting of the text.
In order to have different (background or otherwise) colors for each class name, you'd have to define different syntax groups, and assign different highlight groups, too. Your syntax file would not only have a fixed set of :syntax match commands, but also a loop that extracts matches from the current buffer and builds the corresponding :syntax match and :highlight command as the syntax loads (using :execute).
Then you have the problem of updating, if the user adds or changes class names. Normally, a syntax is static, so once it loads, it's done. In your case, you'd have to define :autocmds that periodically re-scan the buffer, and add new class names (and maybe even recycle unused highlight group names, so you don't run out of colors). The CursorHold event would be a good candidate for it, but there will be a delay until the colors show up. The available colors is another problem if you want to make this syntax available to other users. The number of colors can vary wildly, and coming up with background colors that work well with various colorschemes is difficult.
Summary
It is possible, but it would be unusual for a syntax, and have side effects like delays in updating or poor performance. (I've seen this used for highlighting function names from the tags file, though.) Some users definitely would want to turn this off.
Alternative
For small files with few (or very distinct) class names, this additional highlighting probably isn't necessary. For large files with many classes, having everything light up would make it appear like a Christmas tree, and all the colors could be more distracting than helpful. I'd rather leave it to the user to do such highlighting of some classes of interest, on demand. My Mark plugin provides the generic functionality for this, in a way that does not interfere with syntax highlighting, and it ships with color palettes that look like text marker highlightings. I use this often to have better orientation in log files or legacy code bases. (The plugin page has links to alternative plugins; there are a few.)
Your syntax
Group names typically have a common prefix that's identical to the name of your syntax. If that is cel, use celMethodCall instead of methodCall, and so on.
I would put the :hi commands all at the bottom; most syntax plugins do it like this.
Especially if you intend to later share the syntax, favor :hi linking to existing syntax groups (:help highlight-groups) over defining your own colors. Even for your personal use, defining your colors in your ~/.vimrc has the benefit of having a single place to adapt and reuse it, instead of hunting around various syntax scripts.
By using :hi def, users can customize the syntax, e.g. in their ~/.vimrc. :help 44.12 has more information on writing syntax plugins.
I have a text file with color tags, for example:
foo <color=#c16e0d>bar</color> baz
I would like the tag contents to be colored in #c16e0d and the tags hidden, so that the result is "foo bar baz", except bar not being bold, but colored in #c16e0d.
I tried
:syn region String start=/<color=#[0-9a-f]*>/ end=/<\/color>/ concealends
which makes the tags and their contents pink, but doesn't conceal the tags themselves, even if I run the command in a JSON file where concealing works fine (:set conceallevel=3).
For the coloring I looked at the source of https://github.com/ap/vim-css-color, which seemed overly complex for my simple task.
There are only a few different colors for which I could specify individual syntax rules.
I first thought I was looking at a bug, but re-reading :help :syn-concealends, the last sentence is of significance:
The ends of a region can only be concealed separately
in this way when they have their own highlighting via "matchgroup"
Put in another way, concealends only becomes effective if you specify a matchgroup=...; I guess this is because of implementation reasons; concealing is linked to certain highlight groups.
So, to fix your example, use this:
:syn region myColorTag matchgroup=String start=/<color=#[0-9a-f]*>/ end=/<\/color>/ concealends
You're already aware of plugins that parse color information in a general way. I do agree with you that with a limited set of colors, it's better to just write individual syntax rules and highlight groups.
When defining a :sign you can use the linehl argument to assign a highlight group for the whole line the sign is placed in.
This highlights the whole line until the end, but how I do to highlight only the text of that line?
Edit: The idea is to use Syntastic to show the errors and warnings, but I can't redefine the SyntasticStyleError sign to do what I want. It highlights all the line instead of only the text of that line.
It is not possible as far as I know. Look at the :h sign-define:
:sign define {name} {argument}...
Define a new sign or set attributes for an existing sign.
The {name} can either be a number (all digits) or a name
starting with a non-digit. Leading digits are ignored, thus
"0012", "012" and "12" are considered the same name.
About 120 different signs can be defined.
Accepted arguments:
icon={bitmap}
Define the file name where the bitmap can be found. Should be
a full path. The bitmap should fit in the place of two
characters. This is not checked. If the bitmap is too big it
will cause redraw problems. Only GTK 2 can scale the bitmap
to fit the space available.
toolkit supports ~
GTK 1 pixmap (.xpm)
GTK 2 many
Motif pixmap (.xpm)
Win32 .bmp, .ico, .cur
pixmap (.xpm) |+xpm_w32|
linehl={group}
Highlighting group used for the whole line the sign is placed
in. Most useful is defining a background color.
text={text} *E239*
Define the text that is displayed when there is no icon or the
GUI is not being used. Only printable characters are allowed
and they must occupy one or two display cells.
texthl={group}
Highlighting group used for the text item.
It does not offer you a straight-forward way to distinguish between the text background colour and the background colour of the line - in fact, you can only set the linehl parameter.
Maybe there is a hacky way to do what you want. I've stumbled upon this link you might find useful: https://sunaku.github.io/vim-256color-bce.html
Another interesting idea is explained on vim.wikia.com (link) in the Highlighting that stays after cursor moves section. It suggests using the following command:
:nnoremap <silent> <Leader>l ml:execute 'match Search /\%'.line('.').'l/'<CR>
This way you might mix it with the information you get from :sign place and replace signs with your custom highlighting method I posted above. It requires some scripting though.
I am using MacVim with the Cobalt theme. I found it very nice, however, coming from Sublime Text, I feel there aren't enough different colours which makes my javscript code hard to read.
For example, I'd like the function name to be coloured to make them stand out a bit more:
myClass.prototype.myFunction = function myFunction() {
// here, I'd like "myClass" to have a different color from the text
// same for "prototype" and "myFunction"
}
Another example is the use of methods:
myArray.pop();
// I'd like to change the color of ".pop()" for more visibility
How can I add these types of patterns?
A syntax script parses the programming language into different groups (which can be listed via :syntax list). A colorscheme then prescribes how to color and format each individual group.
So, if there are distinct groups, but your colorscheme just assigns the same color to it, that can be easily changed by putting
:hi link <syntaxGroup> <highlightGroup>
commands into your ~/.vimrc.
The detail of parsing depends on the language and syntax script. Extending an existing syntax (to parse out more details) is possible, but complex. For JavaScript, there exist some alternatives (like this) to the built-in syntax script; you might want to give those a try.
PS: :syn list shows all active groups, but it's easier when you install the SyntaxAttr.vim - Show syntax highlighting attributes of character under cursor plugin.
I use the plugin vim-javascript-syntax.
Is there a way to assign an individual character, as identified by a height and depth index, to a highlight group? Every match feature I have come across uses a regex pattern as input.
The reason I ask is because I am making a syntax coloring plugin that will make text an increasingly lighter shade of gray with increasing parenthesis depth. If vim has no such feature and another algorithm makes character-by-character highlighting unnecessary, please point me to it!
Vim has a whole set of special regular expression atoms that can specify buffer positions.
For lines, \%23l matches only in line 23. You can also use \%>23l for all lines starting from 23, and concatenate two of those with < and > to specify ranges.
For columns, there are the corresponding \%23c and \%23v. The former uses byte indices (what Vim somewhat confusingly calls "columns"), as returned by functions like col() and getpos(), the latter screen widths (from virtcol()).
By combining those atoms, you can select arbitrary blocks of text, and highlight them, e.g. with :call matchadd(...). See :help /\%l for details on the atoms.
For your plugin implementation, you may be able to get some ideas from the vim js context coloring plugin, which highlights JavaScript code according to its scope.