1

I wrote a function to show some special characters with red color:

function! ShowChar()
    set list
    set listchars=tab:→\ ,space:·,nbsp:␣,eol:¶
    highlight SpecialKey ctermfg=blue ctermbg=red guifg=blue guibg=red
endfunction
map <f5> :call ShowChar()<CR>

When to press f5, the characters -- tab, space, nbsp, eol will be shown with red color, now I want to design a new function key f6, when to press f6 after pressing f5, all the special characters will be shown as previous status, not with red color. Should I write a new function which called by f6?

Biggybi
  • 2,740
  • 9
  • 29
showkey
  • 1,130
  • 2
  • 11
  • 30
  • Can you create two highlighting groups SpecialKeyWarning and SpecialKeyNormal and use :h :highlight-link? In your vimrc you link SpecialKey to SpecialKeyNormal, in ShowChar() you link it to SpecialKeyWarning and when you're done you link again to SpecialKeyNormal? – statox Jul 20 '20 at 12:49
  • What statox is driving at is there isn’t really a good way to “save” the old highlight value... it’s whatever is defined by the colorscheme. You could try just doing execute 'colorscheme' g:colors_name – D. Ben Knoble Jul 20 '20 at 13:23
  • Yup definitely not a good way to save the value set from the colorscheme indeed, it was just a way to avoid playing with highlighting commands output. But reloading the whole colorscheme as Ben suggests might be a better idea. – statox Jul 20 '20 at 13:28
  • one can use redir with output to variable, parse, save and then restore it – Maxim Kim Jul 20 '20 at 15:55

3 Answers3

1

I assume you use termguicolors:

if has("termguicolors")
  set termguicolors
endif

You can use this to store the colors of the SpecialKey group each time your colorscheme changes:

augroup SaveSpecialKeyColors
  au!
  au ColorScheme,VimEnter *
        \ let g:specialkey_fg = synIDattr(hlID('SpecialKey'), "fg#") |
        \ let g:specialkey_bg = synIDattr(hlID('SpecialKey'), "bg#")
augroup end

And a function to toggle:

set listchars=tab:→\ ,space:·,nbsp:␣,eol:¶

function! SpecialKeyToggle() if &list == "" set list highlight SpecialKey guifg=blue guibg=red else exe "highlight SpecialKey guifg= " g:specialkey_bg "guibg= " g:specialkey_bg endif endfunction

nnoremap <f6> :call SpecialKeyToggle()<CR>

You could have a mapping to toggle list (stole this one from tpope's unimpaired):

nnoremap yol setlocal list!

nnoremap is good practice: you only need this function in normal mode (n), and don't want it to be recursive (nore).

Biggybi
  • 2,740
  • 9
  • 29
0
function! SpecialKeyWarning()
    set list
    set listchars=tab:→\ ,space:·,nbsp:␣,eol:¶
    highlight SpecialKey ctermfg=blue ctermbg=red guifg=blue guibg=red
endfunction
map <f5> :call SpecialKeyWarning()<CR>

function! SpecialKeyNormal()
    set  nolist 
endfunction
map <f6> :call SpecialKeyNormal()<CR>
showkey
  • 1,130
  • 2
  • 11
  • 30
  • That's not really what you asked in your question. But if it works for you, you can simplify everything: leave set listchar... and highlight SpecialKey... in your vimrc out of a function and simple use nnoremap <f5> :set list!<CR> to toggle the list option with only one key. (Also you should always use mode specific map commands like nmap or imap and unless you know what you are doing you should always use the non recursive version of map commands i.e. nnoremap and inoremap) – statox Jul 20 '20 at 15:20
0
set listchars=tab:→\ ,space:·,nbsp:␣,eol:¶
highlight SpecialKey ctermfg=blue ctermbg=red guifg=blue guibg=red
nnoremap <f5> :set list!<CR>
showkey
  • 1,130
  • 2
  • 11
  • 30
  • 5
    It would be great if you'd provide a bit of explanation as for why this solution works (even if this is quite obvious). – Biggybi Jul 21 '20 at 02:19