Extend colorscheme with custom matches - vim

My colourscheme (Tomorrow Night) exposes the following colours variables:
" Default GUI Colours
let s:foreground = "c5c8c6"
let s:background = "1d1f21"
let s:selection = "373b41"
let s:line = "282a2e"
let s:comment = "969896"
let s:red = "cc6666"
let s:orange = "de935f"
let s:yellow = "f0c674"
let s:green = "b5bd68"
let s:aqua = "8abeb7"
let s:blue = "81a2be"
let s:purple = "b294bb"
let s:window = "4d5057"
I'm looking forward to create new matches and highlight groups reusing those colours.
For example, I'm trying to highlight my own LESSVariable group with s:red, and I tried:
hi LESSVariable guifg=s:red
call <SID>X("LESSVariable", s:red, "", "")
In conjunction with my match rule:
match LESSVariable /#[\w_-]+/
From the let keywords in the variables above I can deduce that those variables are only visible within the theme file.
What can I do to accomplish this?
If not possible using the s:red variable directly, can I tell Vim somehow that my LESSVariable group should look like group X (for example, like rubyConstant)?
EDIT: Tomorrow Night translates the gui hexadecimals to cterm colours for Terminal support. If possible, I'd like to support both GUI and Terminal in my customisations.

The easy way.
Instead of creating your own highlight group, use one that's already defined by your colorscheme and looks just like you want. For example:
call <SID>X("WarningMsg", s:red, "", "")
call <SID>X("Identifier", s:red, "", "none")
call <SID>X("vimCommand", s:red, "", "none")
etc…
The other easy way.
Add your highlight group to the colorscheme.
Another easy way.
Use an existing less syntax script that already has what you want.

Related

In Vim/NeoVim, how to draw inside text buffer without modifying content

For example, suppose I want to implement a plugin that draws a margin line at 80 colums using custom characters (suppose I want the line to made from a column of * characters).
How can that be done in Vim or Neovim?
But more generically, is there a way to draw stuff over the text buffer without affecting the text content?
For example, how can I draw an inner rectangle inside a window which I can make bright colored in order to show the active window? The effect would be that the first line visible line of what is currently a text buffer would be filled with --- characters, the right-most column of the what is currently a text buffer would be filled with |. This would be inside the window, separate from the statuslines or vertical split lines.
Etc. How to do such things?
Some plugins that currently draw over the text buffer in different ways:
https://github.com/easymotion/vim-easymotion
https://github.com/Yggdroot/indentLine
EasyMotion does not draw over the text, i don't think this is possible.
What it does is defined in following function (sourcecode):
function! EasyMotion#helper#VarReset(var, ...) "{{{
if ! exists('s:var_reset')
let s:var_reset = {}
endif
if a:0 == 0 && has_key(s:var_reset, a:var)
" Reset var to original value
" setbufvar( or bufname): '' or '%' can be used for the current buffer
call setbufvar('%', a:var, s:var_reset[a:var])
elseif a:0 == 1
" Save original value and set new var value
let new_value = a:0 == 1 ? a:1 : ''
" Store original value
let s:var_reset[a:var] = getbufvar("", a:var)
" Set new var value
call setbufvar('%', a:var, new_value)
endif
endfunction "}}}
So it saves every replaced char and restores them afterwards.
I haven't looked at indentLine but it probably does intelligent listchars, as there is never text under the indentchar.
Anyway it isn't as if I am an expert on one of the plugin or vim in general. I just write this answer because i think there are easier way to achieve what you want. You could for example highlight the border lines with a certain color, or change the background for the active split. There is also a plugin for dimming inactive splits: https://github.com/blueyed/vim-diminactive

Can Resharper ignore spaces in declaration statements?

I prefer using Align Assignments
Aligns assignment statements by typing Ctrl+Alt+]. For example, typing Ctrl-Alt-] when the following is selected:
MaxMultiplier = bonusMathModel.MaxMultiplier;
MaxFreeGames = bonusMathModel.MaxFreeGames;
MultiplierQueueMode = MultiplierQueueMode.OVERLAPPED;
OverlappedMultiplierOperator = OverlappedMultiplierOperator.ADDED;
Transforms it into this:
MaxMultiplier = bonusMathModel.MaxMultiplier;
MaxFreeGames = bonusMathModel.MaxFreeGames;
MultiplierQueueMode = MultiplierQueueMode.OVERLAPPED;
OverlappedMultiplierOperator = OverlappedMultiplierOperator.ADDED;
However, Resharper ctrl-alt-f cleanup will undo the align assignments. How can I change Resharper's behavior so that it preserves Align assignments?
I think you'll have to create a new Clean-up profile with Reformat Code set to No and use that instead.
You can't mix and match the convenience of automatic reformatting with custom spacing. Resharper isn't to know which additional spaces are deliberate and which are accidental.

How to improve this vim mapping to format/align similar lines

Recently I was in need of a faster way to format similar code lines according a common character (usually =). For example, I want to format this:
myVar = getMyVar();
myLongerVar = getMyLongerVar();
myYetLongerVar = getMyYetLongerVar();
into that:
myVar = getMyVar();
myLongerVar = getMyLongerVar();
myYetLongerVar = getMyYetLongerVar();
then I wrote the following mappings:
" query used to find the common character. In this case i'm setting it to "find the ="
let g:defformatquery = "f="
" set current line as having the longer size till the common character
nnoremap <Leader>gm 0
\:execute "normal " . g:defformatquery<CR>
\:let b:epos = getpos(".")[2]<CR>
" format current line according to the position acquired above
nnoremap <Leader>g= 0
\:execute "normal " . g:defformatquery<CR>hvgeld
\:execute "normal " . (b:epos - getpos(".")[2]) . "i "<CR>
To use them I have to perform these steps (assuming , is my <Leader>):
position the cursor in the line with the longer text before the = sign (the third line in the example provided, myYetLongerVar)
press: ,gm
for each line I want to format, position the cursor there and press ,g=
Although this works, the process is kinda slow.
I want to create a function that would format the entire selected area at once. Then I could just create one map for the function.
Any ideas?
You should try the Align plugin.
For example, to align some selected lines (selected with v or CTRL-v) according to the = sign, you just type:
:Align =
Or to align from line 34 to 39:
:34,39Align =

how to set syntax hilight colors in VIM to values of local variables in syntax script?

What I'd like to do is something like the following:
"define our language struct variables with their default syntax color values
let s:procedural_fg = "Red"
let s:declarative_fg = "Blue"
let s:string_fg = "DarkGray"
...
"Now the actual highlighting directives based on the groups defined elsewhere
hi cyLoops guifg=s:procedural_fg
hi cyConstants guifg=s:declarative_fg
hi cyString guifg=s:string_fg
but VIM won't let me set the guifg values this way ("Error: Cannot allocate color s:procedural_fg" ... and so forth for each variable name). I'd like to define the syntax highlighting this way so that it can be dynamically altered by changing the local variable values and then refreshing the buffer (or whatever it would take to make the new color values apply).
Can this be done in a VIM syntax script? If so, how?
I've already tried several variations:
"define our language struct variables with their default syntax color values
let s:procedural_fg = Red
let s:declarative_fg = Blue
let s:string_fg = DarkGray
...
"Now the actual highlighting directives based on the groups defined elsewhere
hi cyLoops guifg=s:procedural_fg
hi cyConstants guifg=s:declarative_fg
hi cyString guifg=s:string_fg
and
"define our language struct variables with their default syntax color values
let s:procedural_fg = v:Red
let s:declarative_fg = v:Blue
let s:string_fg = v:DarkGray
...
"Now the actual highlighting directives based on the groups defined elsewhere
hi cyLoops guifg=s:procedural_fg
hi cyConstants guifg=s:declarative_fg
hi cyString guifg=s:string_fg
which leads to an error complaining that Red, Blue etc. or v:Red, v:Blue etc. are undefined and/or invalid expressions.
thanks,
CCJ
Use :exec, which is to Vim what eval is to Perl or bash shell:
:exec 'hi cyLoops guifg=' . s:procedural_fg

How to modify existing highlight group in vim?

If I have an existing highlight group in vim via link, for example
hi link my_highlight_group my_default_color
Is it possible to add 'bold' to my_highlight_group without changing my_default_color? Following does not work:
hi my_highlight_group gui=bold
Surprisingly, I can add bold if my_highlight group is defined directly (not via link):
hi my_highlight_group guifg=#F0000
hi my_highlight_group gui=bold
As "too much php" has said, there is no direct way to say "create a value that looks like that one and add bold". The best way is to modify your colour scheme. If you're not using a custom colour scheme, copy one from the main vim installation directory to your ~/.vim/colors directory and edit it to suit you. Alternatively, search on the vim scripts page and try some of the many that are available.
Shameless plug: if you want one that's easier to edit than the standard format, try my "Bandit" colour scheme.
If you really want to be able to add bold on the fly, you'll need a fairly complex script, like the one below. Note that this won't be saved for your next session unless you call it automatically after loading your colour scheme or by doing something like:
:autocmd ColorScheme AddBoldToGroup my_highlight_group
The script in all it's enormity is below. As far as I am aware, there is no significantly quicker way of doing this! Obviously you could save a few lines by writing less verbose code, but the general idea of using redir and silent hi repeatedly is the only way.
" Call this with something like
"
" :AddBoldToGroup perlRepeat
"
command! -complete=highlight -nargs=1 AddBoldToGroup call AddBoldToGroup(<f-args>)
function! AddBoldToGroup(group)
" Redirect the output of the "hi" command into a variable
" and find the highlighting
redir => GroupDetails
exe "silent hi " . a:group
redir END
" Resolve linked groups to find the root highlighting scheme
while GroupDetails =~ "links to"
let index = stridx(GroupDetails, "links to") + len("links to")
let LinkedGroup = strpart(GroupDetails, index + 1)
redir => GroupDetails
exe "silent hi " . LinkedGroup
redir END
endwhile
" Extract the highlighting details (the bit after "xxx")
let MatchGroups = matchlist(GroupDetails, '\<xxx\>\s\+\(.*\)')
let ExistingHighlight = MatchGroups[1]
" Check whether there's an existing gui= block
let MatchGroups = matchlist(ExistingHighlight, '^\(.\{-}\) gui=\([^ ]\+\)\( .\{-}\)\?$')
if MatchGroups != []
" If there is, check whether "bold" is already in it
let StartHighlight = MatchGroups[1]
let GuiHighlight = MatchGroups[2]
let EndHighlight = MatchGroups[3]
if GuiHighlight =~ '.*bold.*'
" Already done
return
endif
" Add "bold" to the gui block
let GuiHighlight .= ',bold'
let NewHighlight = StartHighlight . GuiHighlight . EndHighlight
else
" If there's no GUI block, just add one with bold in it
let NewHighlight = ExistingHighlight . " gui=bold"
endif
" Create the highlighting group
exe "hi " . a:group . " " NewHighlight
endfunction
Changing the attributes on a group which is linked to another will disconnect the link. AFAIK there is no easy way to copy the colors from my_default_color into my_highlight_group. You will just have to copy the color values by hand.
This shouldn't be a big issue though, you should have all your highlight groups defined in your colorscheme file, so just put those two next to each other:
hi my_default_color guifg=#000088
hi my_highlight_group guifg=#000088 gui=bold
Years had passed and now the question has a much more straightforward solution: hlget() and hlset() functions.
It's still true that if you want to modify a color scheme, copying it first and modify the copied version would be a better solution.
An example of adding bold attribute to types' highlight:
" Get the highlight group, resolving links
let hl = hlget("Type", v:true)[0]
" Set GUI attributes
let hl.gui = hl->get("gui", {})->extend(#{ bold: v:true })
" Set the highlight group
call hlset([hl])
Assuming you only want this for one syntax type, you should just make a new group name, my_bold_default_color, and apply the bold attribute to that.

Resources