9

My cursor in Gvim:

My cursor in Gvim

My cursor in Gvim after pressing d:

My cursor in Gvim after pressing <code>d</code>

Is there any way I can change the cursor in terminal Vim when in operator pending mode? It doesn't have to look exactly like the screenshots.

This is done by o:hor50-Cursor in guicursor for Gvim. The only three options I see for Vim are:

t_SI    start insert mode (bar cursor shape)        *t_SI* *'t_SI'*
t_SR    start replace mode (underline cursor shape) *t_SR* *'t_SR'*
t_EI    end insert or replace mode (block cursor shape) *t_EI* *'t_EI'*
    |termcap-cursor-shape|

But nothing about operator pending mode...

5
  • 2
    I don't think it's possible (could use a source code patch ..). What I do is to look at the right-bottom side of Vim window to check for the partially introduced command letters, which show up there (with showcmd setting on). I also disable all timeouts and the esckeys option (this keeps Vim snappy but allows me to think at what I want to do in op-pending mode for example).
    – VanLaser
    Mar 24, 2016 at 11:29
  • 1
    @VanLaser Yeah, but I like the cursor ;-) Mar 24, 2016 at 11:31
  • Hehe, I can understand that :)
    – VanLaser
    Mar 24, 2016 at 11:31
  • I know C/C++, offer a $ bounty and I may try to implement it in Vim source code, if possible :D
    – VanLaser
    Mar 24, 2016 at 11:32
  • You could use vi.stackexchange.com/a/11437/10337 to detect operator pending mode and echo an ansi escape to change the cursor.
    – laktak
    Feb 15, 2017 at 20:46

1 Answer 1

3

This updates the cursor when entering/exiting operator pending mode.

While it is a bit of a hacky solution I don't think it has any performance problems.

" This is esentially:
"   exec 'silent !printf "\e[" . a:t . ' q'
"   redraw!
" but without the screen flash
function! s:setCursor(t)
    " Save existing values.
    let [l:title, l:t_ts, l:t_fs, l:titlestring] = [&title, &t_ts, &t_fs, &titlestring]

    try
        let &titleold = ''
        let &t_ts = "\e[0;0"
        let &t_fs = "\e[" . a:t . ' q'
        set title
        set titlestring=H
        redraw!
    finally
        let [&title, &t_ts, &t_fs, &titlestring] = [l:title, l:t_ts, l:t_fs, l:titlestring]
    endtry
endfunction

let s:prevmode = ''
function! DetectPendingMode(timer)
    let l:mode = mode(1)
    if l:mode is# s:prevmode
        return
    endif

    if l:mode is# 'no'
        call <SID>setCursor(4)
    elseif s:prevmode is# 'no'
        call <SID>setCursor(2)
    endif
    let s:prevmode = l:mode
endfunction

call timer_start(250, 'DetectPendingMode', {'repeat': -1})

You may need to change the style of the cursor in SetCursor() to the one you prefer:

0: blinking block.
1: blinking block.
2: steady block.
3: blinking underline.
4: steady underline.
5: blinking bar (xterm).
6: steady bar (xterm).

Your Answer

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

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