1

My vimrc holds a script to change the color of the CursorLineNr conditionally based on the mode. My problem is that it hides vim's welcome message when it's launched without a file. I would like to keep the message.

The culprit lines are the first two "exe" commands.

let g:mode_marker_group = "CursorLineNr"
let g:cmd_change_fg = "#383a42"
let g:cmd_change_bg = "#e06c75"
let g:ins_change_fg = "#383a42"
let g:ins_change_bg = "#98c379"

call timer_start(30, 'PendingCommandModeHl', #{repeat: -1})
function! PendingCommandModeHl(_) abort
  if mode() != 'n'
    return
  endif
  if state() =~# '\C[mo]'
    """"" CULPRIT """""
    exe "hi" g:mode_marker_group "guifg=" . g:cmd_change_fg "guibg=" . g:cmd_change_bg
  else
    """"" CULPRIT """""
    exe "hi" g:mode_marker_group "guifg=" . g:save_fg "guibg=" . g:save_bg
  endif
endfunction

augroup PendingInsertModeHl
  au InsertEnter * exe "hi" g:mode_marker_group "guifg=" . g:ins_change_fg "guibg=" . g:ins_change_bg
  au InsertLeave * exe "hi" g:mode_marker_group "guifg=" . g:save_fg "guibg=" . g:save_bg
augroup end

augroup SaveGroupColors
  au!
  au ColorScheme,VimEnter *
        \ let g:save_fg = synIDattr(hlID(g:mode_marker_group), "fg#")
        \ | let g:save_bg = synIDattr(hlID(g:mode_marker_group), "bg#")
augroup end
3
  • 1
    Why use a timer here? Why not call that function from the VimEnter autocmd instead? Wouldn't that work? Seems like you're trying to delay it so that it is run after your plug-ins... But running it from VimEnter should have that kind of effect already. – filbranden Jul 8 '20 at 13:57
  • The goal of the timer is not to delay the function run, but to check if vim is waiting for more input when typing a chorded shortcut. So, when I start typing a mapping, the colour changes (and gets back to normal afterwards). 30ms is enough to make it look instantaneous, but it could be another value. This solution was an answer to this question. Should I edit my post to clarify this? – Biggybi Jul 8 '20 at 14:34
  • 1
    Ah sorry, my brain saw the # in #{repeat: -1} and thought that was a comment. Duh! But I still think the answer probably lies somewhere around delaying setup of this timer later in startup. You can also try using an extra silent somewhere in those commands. It's possible they don't really output anything, but even the blank output is enough to count as a command to clear the command output and skip the greeting message... – filbranden Jul 8 '20 at 14:43
0

Serendipity taught me that Vim holds a command to display the greeting message on demand: :intro.

However, as any multiline output command, it shows the Press ENTER or type command to continue message, and disappears if anything is typed.

The original 'intro' hangs until the screen is redrawn, as stated in :h :intro:

                                                                *:intro*
When Vim starts without a file name, an introductory message is displayed (for
those who don't know what Vim is).  It is removed as soon as the display is
redrawn in any way.  To see the message again, use the ":intro" command (if
there is not enough room, you will see only part of it).
To avoid the intro message on startup, add the 'I' flag to 'shortmess'.

I am yet to find a way to keep the same behaviour as the original intro message.

3
  • 1
    Have you tried putting the timer_start in a VimEnter autocmd? – Mass Jan 27 at 21:08
  • @Mass Yes I have, no difference =/ – Biggybi Jan 28 at 19:36
  • strongly recommend against this approach, as documented in my answer. – Mass Feb 26 at 20:40
0

You should be able to instantiate the timer inside InsertEnter. This will prevent the timer firing at an inopportune time (such as when the intro screen is shown).

In fact, it is probably a better design to have a "one shot" timer anyway, since it will not require the timer to be constantly firing. Plugins that do this tend to make things behave weirdly because ultimately vim is a single-threaded application. In the case of nvim, there are actual documented performance issues with constantly active timers: https://github.com/neovim/neovim/issues/12587.

Option 1 (recreated timer):

function! TimerOneShot1()
    call timer_start(30, 'PendingCommandModeHl', #{repeat: 1})
endfunction

Option 2 (paused timer):

function! TimerOneShot2()
    if !exists('s:timer')
        let s:timer = timer_start(30, 'PendingCommandModeHl', #{repeat: -1})
    endif
    call timer_pause(s:timer, 0)
endfunction

function! PendingCommandModeHl()
    call timer_pause(s:timer, 1)
endfunction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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