In this plugin for (soft-)wrapping only the current line, I have defined a highlight group, au ColorScheme * hi SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE, which I use here as an argument to a call to popup_create.

How can I let the user alter SoftWrapHighlightGroup? Also, where should they set it?

I thought default was the key, but I've not really understood how to use it.

As regards where the user of the plugin would make the change, I think it should be in the vimrc, because it's not a filetype-specific syntax highlighting. It's not a syntax highlighting at all. In this regards, I'm now thinking I should probably have the :highlight command above not in the :autocmd at all.

Indeed, with

hi default SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE cterm=bold

in my plugin, I do see the effect of cterm=bold, but I'm sure I've read in several places that I should put highlight commands in an autocmd. Does it apply here?

2 Answers 2

  1. The recommendation to use the ColorScheme autocommand comes from the fact that color schemes all start with hi clear, which effectively removes any previous hi definition, wherever, whenever, and whoever made them. No hi survives hi clear so, if one wants their custom hi to stick around, then forcing their re-definition after any potential hi clear is the only way.

    Before dealing with your user-related problem, there is another one to deal with: your hi command is made inside a plugin and plugins are sourced after the user's vimrc, where most colorscheme foobar commands are. Since you are using the ColorScheme autocommand to define your highlight group, it will only be defined after the next colorscheme foobar… which may never happen.

    Therefore, you should have something like the following in your plugin:

    highlight SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE
    autocmd ColorScheme * highlight SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE
    1. a simple hi that will take effect right here and right now, no matter what,
    2. an autocommamd that makes sure your hi survives any future hi clear.
  2. Now, how to let the user customize that highlight group when it is defined so aggressively?

    My advice would be to tell your users to add a line like the following to their vimrc before any colorscheme command:

    autocmd ColorScheme * highlight SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE

    and, in your plugin, to check if they did so via :help hlget() before deciding to define the highlight group or not:

    if hlget('SoftWrapHighlightGroup')->empty()
        highlight SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE
        autocmd ColorScheme * highlight SoftWrapHighlightGroup ctermbg=NONE ctermfg=NONE
  • Since I have to support Vim < 8.2.3917, I can't use hlget there. For now I'm branching on the version and using try/catch; I wonder if that's the best solution.
    – Enlico
    Commented Jan 10, 2023 at 19:36
  • Why not using default instead of manually checking wihth the if?
    – Enlico
    Commented Jan 13, 2023 at 7:45
  • 1
    No reason not to.
    – romainl
    Commented Jan 13, 2023 at 8:00
  1. Setting colors to NONE is (almost) the same as inheriting from Normal group. So you can simply test hlID() return value before calling popup_create() and pass "Normal" if the custom group doesn't exist (yet). Actually, popup_create will never complain, so you can even skip the test completely and pass custom group name no matter what. Then by default the colors will be "Normal" anyway.

  2. In general case, it makes sense to ensure group creation by doing hi def link custom_group NONE. This will have no effect if the group already exists.

  3. hi def link survives any hi clear, so you can default-link your group to any of standard groups (ones that are always set up by any color scheme) to get some highlighting other than Normal. While still permitting any sort of customization. This is how most of syntax plugins work. The actual colors will also depend on current color scheme, of course, but this is usually okay.

  4. If you really want to set some fixed colors for all color schemes at once, then use hi default. First time on startup, then after every color scheme change by ColorScheme auto-command. What hi-default does, it sets group colors only if the group is cleared, otherwise it has no effect.

  5. If user wants to customize your group he has to make use of either hi-def-link, or ColorScheme auto-command. There's no "third way" unless you're going to implement some sort of dedicated API that will simplify (from user pov) messing with ColorScheme event specifically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.