Who doesn't like cyan comments in their text editor? Lee Hutchinson, that's who.
Enlarge / Who does not like cyan feedback of their textual content editor? Lee Hutchinson, that is who.

Jim Salter

One nice Monday morning, Ars Technica Senior Expertise Editor Lee Hutchinson got here to me with an issue: the colours in his textual content editor, in his humble opinion, had Begun To Suck.

In Lee’s 20 years or so of Vim utilization, he’d gotten accustomed to remark strains in his code and configuration recordsdata being rendered in darkish blue. However after upgrading a machine to Ubuntu 20.04, Vim began rendering feedback in cyan—and for the reason that “Identifier” syntax class additionally rendered in cyan, he was sad sufficient about it to resolve to alter the defaults.

At first blush, Vim appears to stick to roughly the identical configuration commonplace that many if not most Unixlike programs and functions do—there is a set of systemwide configurations in /and many others, which may be overridden individually per person by adjustments made in an elective configuration file in that person’s dwelling listing. In Vim’s case, that is ~/.vimrc—similar to Bash configurations may be overridden in ~/.bashrc.

However when Lee tried to make his One Easy Change to Vim’s syntax highlighting—flip feedback from the brand new cyan again into the darkish blue which he most popular—issues bought fascinating.

The Hutchinson technique to configure remark highlighting

After just a little googling, the command Lee discovered to alter remark shade gave the impression to be fairly easy: spotlight remark ctermcfg=19, the place 19 is the colour code Vim makes use of for darkish blue. The issue is, making the change in ~/.vimrc did not really work.

To be extra particular, it did work—briefly—however virtually instantly after opening the file, the feedback modified from darkish blue again to cyan once more. On a neighborhood, quick machine, the change occurred too shortly to note; however Lee was ssh’ing right into a distant machine, and that gave simply sufficient to delay to see his shade choice utilized initially however shortly reverted.

After important googling, Lee found an unsightly workaround. There is a very outdated joke that Vim is not really a textual content editor in any respect—it is an working system in its personal proper, which merely masquerades as a textual content editor. Like most good jokes, this one’s a bit excessive however has a kernel of fact to it—Vim config recordsdata do not merely assign values to configuration variables; they will really run code in their very own proper.

In Lee’s case, he determined that, since there was a roughly 100ms delay between his darkish blue feedback being utilized and Vim altering them again, he might simply outwait this system by ready 100ms to use the change within the first place:

perform DelayedSetVariables(timer)
    spotlight remark ctermfg=19
endfunction

let timer=timer_start(16,'DelayedSetVariables')

Certain sufficient, the ugly hack labored: now, as an alternative of seeing darkish blue feedback initially which then flashed again to the hated cyan, Hutchinson noticed cyan feedback which then flashed to his most popular darkish blue.

This labored properly sufficient for his functions… however what is the level of being a senior know-how editor if you cannot run an issue previous a know-how reporter who stories to you?

The unsuitable method… really, a number of unsuitable methods

When Lee introduced his kinda-solved drawback to me, it definitely seemed like a bug—I won’t be a Vim person myself, however with greater than 20 years of Unixlike OS expertise underneath my very own belt, I additionally anticipated a user-profile configuration file to cleanly overwrite a system-wide configuration. The unhinged ranting coherent, centered drawback report Lee supplied me included a warning: there have been, in his phrases, “about 20 totally different locations the place Vim configuration adjustments get utilized,” so monitoring down the issue was unusually sticky.

I am not a Vim person myself—I am a kind of heathens who by no means noticed any explicit motive to study extra about Vim than the :q! wanted to get the hell out of it—however my instant suspicion was {that a} bug was inflicting Vim configuration recordsdata to be utilized out of order. So I googled the right way to examine what configurations had been utilized to a working Vim occasion: turns on the market’s a particular command :scriptnames that can give you precisely that.

  1: /usr/share/vim/vimrc
  2: /usr/share/vim/vim81/debian.vim
  3: /usr/share/vim/vim81/syntax/syntax.vim
  4: /usr/share/vim/vim81/syntax/synload.vim
  5: /usr/share/vim/vim81/syntax/syncolor.vim
  6: /usr/share/vim/vim81/filetype.vim
  7: ~/.vimrc
  8: /usr/share/vim/vim81/plugin/getscriptPlugin.vim
  9: /usr/share/vim/vim81/plugin/gzip.vim
 10: /usr/share/vim/vim81/plugin/logiPat.vim
 11: /usr/share/vim/vim81/plugin/manpager.vim
 12: /usr/share/vim/vim81/plugin/matchparen.vim
 13: /usr/share/vim/vim81/plugin/netrwPlugin.vim
 14: /usr/share/vim/vim81/plugin/rrhelper.vim
 15: /usr/share/vim/vim81/plugin/spellfile.vim
 16: /usr/share/vim/vim81/plugin/tarPlugin.vim
 17: /usr/share/vim/vim81/plugin/tohtml.vim
 18: /usr/share/vim/vim81/plugin/vimballPlugin.vim
 19: /usr/share/vim/vim81/plugin/zipPlugin.vim
 20: /usr/share/vim/vim81/scripts.vim
 21: /usr/share/vim/vim81/syntax/perl.vim
 22: /usr/share/vim/vim81/syntax/pod.vim
Press ENTER or sort command to proceed

Lee hadn’t been kidding in regards to the huge array of configuration recordsdata to look by: my system loaded 22 separate configuration recordsdata, 15 of which took impact after the .vimrc in my dwelling listing! Thus started the beginning of a protracted, winding, and finally fruitless primrose path: I needed to search out cases of the remark shade being modified someplace after my ~/.vimrc, and it turned out that simply wasn’t taking place.

The one place I might discover the place remark shade was set to Cyan was in /usr/share/vim/vim81/syncolor.vim, a few areas forward of my private .vimrc. In idea, the change in ~/.vimrc ought to have overridden the one in syncolor.vim—however in follow, with out Lee’s ugly timer hack, the one method I might discover to alter the remark shade was inside syncolor.vim itself.

" Many terminals can solely use six totally different colours (plus black and white).
" Subsequently the variety of colours used is stored low. It does not look good with
" too many colours anyway.
" Cautious with "cterm=daring", it adjustments the colour to vivid for some terminals.
" There are two units of defaults: for a darkish and a light-weight background.
if &background == "darkish"
  SynColor Remark      time period=daring cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE

Altering ctermfg=Cyan inside syncolor.vim to ctermfg=19—or, higher but, ctermfg=DarkBlue, which produced an easier-to-read shade of blue—labored as-expected, and it produced the output Lee needed with out the god-awful timer hack. But it surely utilized the change systemwide, not simply to Lee’s personal person account—and extra importantly, it did not clarify how or why the unique change in ~/.vimrc refused to work as anticipated.

I nonetheless smelled an out-of-order bug, so I dug additional.

" Vim syntax assist file
" Maintainer:   Bram Moolenaar <Bram@vim.org>
" Final Change:  2001 Sep 12

" This file units up the default strategies for highlighting.
" It's loaded from "synload.vim" and from Vim for ":syntax reset".
" Additionally used from init_highlight().

In response to the feedback on the prime of syncolor.vim, the adjustments inside that file had been utilized in three instances—when synload.vim is parsed throughout Vim initialization, when the person points the command :syntax reset, and inside the Vim perform init_highlight(). I knew neither Lee nor I had been calling for :syntax reset, so I proceeded to search out the invocation of syncolor.vim from inside synload.vim.

" Set the default highlighting colours.  Use a shade scheme if specified.
if exists("colors_name")
  exe "colours " . colors_name
else
  runtime! syntax/syncolor.vim
endif

If I put the easy spotlight remark ctermfg=19 again into my ~/.vimrc, and commented out the runtime! syntax/syncolor.vim in synload.vim, I believed the whole lot ought to work correctly: this is able to nonetheless qualify as an unsightly hack, after all, however it will slim down the place the issue conduct was coming from and permit me to put in writing a extra actual bug report back to file with the Vim venture.

Sadly, it did not work that method: even with runtime! syntax/syncolor.vim commented out, the Cyan feedback that file specified overrode the easy setting in my ~/.vimrc. This meant the configurations there have been being known as by Vim’s init_highlight() perform after it parsed ~/.vimrc.

On the one hand, this definitely nonetheless smelled like a bug to me: I could not override a easy configuration setting from my user-level rc file. Alternatively, did I point out the 20+ years of open supply expertise? I wanted to make sure I wasn’t lacking one thing apparent, that may trigger a bug report to simply get rejected with a #WONTFIX as a result of I might missed some deliberate Vim idiosyncrasy.

Discovering the suitable method

Since Vim’s configuration recordsdata had self-documenting feedback, the time had come to learn them extra totally. I might already discovered that the contents of syncolor.vim had been utilized by init_highlight() and synload.vim—however I wanted to dig additional.

I could not get any additional with the documentation feedback on the prime of synload.vim or syncolor.vim, however the subsequent clue got here from the code in syncolor.vim itself:

if syntax_cmd == "allow"
    " ":syntax allow" retains any present colours
    command -nargs=* SynColor hello def <args>
    command -nargs=* SynLink hello def hyperlink <args>
  elseif syntax_cmd == "reset"
    " ":syntax reset" resets all colours to the default
    command -nargs=* SynColor hello <args>
    command -nargs=* SynLink hello! hyperlink <args>
  else
    " Person outlined syncolor file has already set the colours.
    end
  endif

Clearly, there was some correct technique to set user-defined colours, since this if block particularly averted setting them up if a “person outlined syncolor file” already had. So the subsequent step was to Google “vim person outlined syncolor file.” The highest search outcome was the supply for syncolor.vim itself on Github, however the second outcome introduced me to Vim documentation at SourceForge.

Performing a ctrl-F syncolor in-browser search on this 5,128-line doc finally bought me to the knowledge I wanted, about 90 % of the way in which down the web page:

If you wish to use totally different colours for syntax highlighting, you'll be able to add a Vim
script file to set these colours.  Put this file in a listing in
'runtimepath' which comes after $VIMRUNTIME, in order that your settings overrule
the default colours.  This fashion these colours shall be used after the ":syntax
reset" command.

For Unix you should utilize the file ~/.vim/after/syntax/syncolor.vim.

Lastly, I might discovered the proper reply to the deceptively easy query “How do I modify remark shade inside Vim?”: after creating ~/.vim, ~.vim/after, and ~.vim/after/syntax, you’ll be able to lastly create the file ~/.vim/after/syntax/syncolor.vim—and adjustments made to syntax spotlight colours there utilized the way in which that Lee and I anticipated them to.

Petting the shaggy canine

Hopefully, you have discovered one thing alongside the way in which as you learn this god-awful shaggy canine story of configuring a Linux software. Perhaps you, too, simply needed to alter some colours in a textual content editor—through which case I’ve led you down an absurdly lengthy path simply to get to a comparatively quick reply.

However extra importantly, I hope the train in full can function a broader train in troubleshooting. Completely satisfied Linux-ing!

LEAVE A REPLY

Please enter your comment!
Please enter your name here