4

I would like a piece of Vimscript which would

  • query the time of day
  • check whether it's later than, say, 6pm
  • set an option based on the result

Why? So that I get the dark solarized color scheme whenever I open my editor in the evening, the light one otherwise.

Can this be done?

1

2 Answers 2

12

On a Unix system you can add this to your vimrc:

if system('date +%H') > 18
    colorscheme night
else
    colorscheme day
endif

date +%H is a shell command which returns the hour in a 24 format (see man date).

system() allows you to get the result of a system command in vimscript. It is then easy to compare its result with the hour you want to trigger your setting.

EDIT as @LucHermitte pointed out in the comments, you should use strftime('%H') instead of system('date +%H') this is more portable.

Note that with this solution the code is only executed when you source your vimrc so if you start vim at 5:30 pm, your colorscheme will not change at 6:00 pm if you don't reload your vimrc.


EDIT - Automated and auto-update solution

I did this because I thought it was fun to do. The plugin linked in @ljden answer may be more robust, this is only a lightweight solution which may have some flaws. The fun thing about this solution is that it will change the colorscheme automatically without having to source your vimrc again: You can finally code for 24h straight without having to think about your colorscheme!

This solution will only work with vim8+ and the options +timers and +job.

The idea is pretty simple, you define:

  • g:dayTime the hour after which we should use daytime colorscheme
  • g:nightTime the hour after which we should use nighttime colorscheme.
  • g:colorschemeDay the colorscheme to use in daytime
  • g:colorschemeNight the colorscheme to use in nighttime

We create two helper functions:

  • DiffTime() which returns the number of milliseconds between two hours of the day.
  • IsDayTime() which returns a boolean saying if the current hour is between g:dayTime and g:nightTime

We also create the function ScheduleNewColorscheme which will do two things:

  • Set the colorscheme according to the hour of the day
  • Set a trigger to call itself when we pass nightTime or dayTime again.

Finally, we call the function immediately when the .vimrc is sourced to set the correct colorscheme:

" Define the hours which triggers the dayly colorscheme
let g:dayTime = [9, 30]
" Define the hours which triggers the nightly colorscheme
let g:nightTime = [18, 0]

" Define the colorschemes used by day and by night
let g:colorschemeDay = 'jellybeans'
let g:colorschemeNight = 'darkblue'

" Return the number of milliseconds beetwen the current hour and a target hour.
" Handles the case of a target hour the next day.
" Both hours should be lists composed of two elements: hours and minutes.
" Eg 11:20 pm = [23, 20]
"    09:00 am = [9, 0]
function! TimeDiff(current, target)
    let targetMilli   = (a:target[0] * 3600 + a:target[1] * 60) * 1000
    let currentMilli  = (a:current[0] * 3600 + a:current[1] * 60) * 1000

    if (a:target[0] > a:current[0] || (a:target[0] == a:current[0] && a:target[1] > a:current[1]))
        return targetMilli - currentMilli
    else
        return (24 * 3600 * 1000) + ( currentMilli - targetMilli )
    endif
endfunction

" Check if the current hour is between g:dayTime and g:nighTime
function! IsDayTime()
    let hCurrent = strftime('%H')
    let mCurrent = strftime('%M')

    if hCurrent == g:dayTime[0]
        return mCurrent >= g:dayTime[1]
    elseif hCurrent == g:nightTime[0]
        return mCurrent < g:nightTime[1]
    else
        return hCurrent > g:dayTime[0] && hCurrent < g:nightTime[0]
    endif
endfunction

" According to the current time and the nighttime, set the colorscheme and create
" a trigger for the job which will change the colorscheme
function! ScheduleNewColorscheme(timer)
    " Define colorscheme and next time depending on time of day
    if IsDayTime()
        let newColorscheme = g:colorschemeDay
        let targetDate = g:nightTime
    else
        let newColorscheme =g:colorschemeNight
        let targetDate = g:dayTime
    endif

    " Set new colorscheme
    echom 'setting colorscheme ' . newColorscheme . ' at ' . strftime('%H:%M')
    execute 'colorscheme ' . newColorscheme

    let currentDate = [strftime('%H'), strftime('%M')]
    let startDelay = TimeDiff(currentDate, targetDate)

    " Create the trigger for the next change
    call timer_start(startDelay, 'ScheduleNewColorscheme', {}) 
endfunction

" When sourcing your vimrc set the colorscheme immediately
call timer_start(0, 'ScheduleNewColorscheme', {}) 

EDIT I looked at the plugin linked in @ljden's answer and it includes another plugin in its source code (colorscheme-switcher) which requires a third plugin (vim-misc). So I thought why not make a lightweight plugin of my own? So here it is.

2
  • 2
    No need to use system('date'). We have strftime('%H') that does exactly the same -- and that follows the C standard function conventions. Regarding triggers I guess we could check the current time when the plugin starts and decide automatically at which time the colorscheme should change. Given the duration, we can register a (vim 8) timer that will operate the change. Commented Sep 22, 2017 at 9:08
  • @LucHermitte I didn't know about strftime() (because I never had to use time in vim I guess) about the trigger, I'm trying to put something up, I'll update my answer.
    – statox
    Commented Sep 22, 2017 at 9:19
3

No need to reinvent the wheel, had a quick google and here's a plugin that does exactly that! Even steps you through installing the plugin manager vim-plug (which is a great plugin manager) if you don't have it already.

2
  • If you'd like to do it yourself have a read through the plugin and see if you can work out what it's doing. It is possible, so if you want to diy it have a go and once you're stuck then post more specific questions for help (or try get in contact with nightsense if you can
    – ljden
    Commented Sep 22, 2017 at 2:52
  • Wow, this seems to be exactly what I need.
    – oarfish
    Commented Sep 22, 2017 at 8:58

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.