1

I want to know if there is a way to setup vim (internal feature, plugin) in such a way that it would raise an alarm (bell, flashing screen, anything) if there were NO changes to the find within a specific number of seconds.

The vim window will always be on screen, and the use case is to ensure that notes are taken during an event, rather than waiting until the end of the event and writing some.

3
  • 2
    so you want vim to complain if you are not working fast enough?
    – Mass
    Commented Jun 20, 2019 at 15:03
  • @Mass Strictly: no, but overall: yes. Working regularly at least.
    – Joe
    Commented Jun 20, 2019 at 15:07
  • 2
    Check the CursorHold and CursorHoldI events. You can use them with autocmd to echo a message, for example.
    – xyx
    Commented Jun 20, 2019 at 20:22

1 Answer 1

3

There are a couple ways that come to mind. Here's one...

let g:inactivity_limit = 20  " max Insert mode inactivity before fail, in seconds
let g:check_frequency = 10   " seconds between checks

augroup monitor
    au!
    " when vim starts kick off the infinitely repeating calls to the monitor function
    au VimEnter * call timer_start(g:check_frequency * 1000, 'MonitorActivity', {'repeat' : -1})

    " when cursor moves in Insert mode update the last activity time
    au CursorMovedI * let g:last_activity = reltime()
augroup END

func! MonitorActivity(timer_id)
    " when we start we'll initialize the last activity time then return
    " ...gives a little grace period at beginning
    if ! exists('g:last_activity') || empty(g:last_activity)
        let g:last_activity = reltime()
        return
    endif

    " very handy function for our purposes, reltime
    let l:diff = reltime(g:last_activity)[0]

    if l:diff > g:inactivity_limit
        " Not ringing a bell or anything. Up to OP to change this part.
        echom "Failed! " . l:diff
        let g:last_activity = []
    endif
endfunc

This will check, every 10 seconds (configurable) whether the cursor has moved in Insert mode (thanks to CursorMovedI auto-command/event) in the last 20 seconds (also configurable). The comments in the code have some more details.

IMPORTANT: I leave it to you to figure out what happens when the time limit is exceeded. You'll have to replace the line that just prints "Failed!".

Also, keep in mind that anyone with a fair amount of vim savvy can disable or otherwise mess with this. And if someone went into Insert mode and just lazily moved the cursor back and forth the whole time nothing would happen. But you're asking for free software so them's the breaks. ;)

Update: Okay, since I was curious here, at least, is a function that will ring the basic system bell, and perhaps flash the screen, once a second for # of times specified in the param. (if Vim has 'visualbell' set or the system bell is otherwise disabled....<shrug>)

func! Alarm(bells)
    let l:i = 0
    while l:i < a:bells
        let l:i += 1 | sleep 1 | norm <c-g>
    endwhile
endfunc

Add call Alarm(5), for example, to the main function where the "Failed" message currently is.

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.