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'*

But nothing about operator pending mode...

  • 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 '16 at 11:29
  • 1
    @VanLaser Yeah, but I like the cursor ;-) – Martin Tournoij Mar 24 '16 at 11:31
  • Hehe, I can understand that :) – VanLaser Mar 24 '16 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 '16 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 '17 at 20:46

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.

function! SetCursor(t)
  " this is esentially
  "   exec 'silent !echo -ne "\e[ '.a:t.'q"'
  "   redraw!
  " but without the screen flash
  " let me know if there is a better way to do this
  let t=&title
  let ts=&t_ts
  let fs=&t_fs
  let titlestring=&titlestring
  let &titleold=''
  let &t_ts="\e[0;0"
  let &t_fs="\e[".a:t." q"
  set title
  set titlestring=H
  let &t_ts=ts
  let &t_fs=fs
  let &titlestring=titlestring
  let &title=t

let s:m = ''

function! DetectPendingMode(timer)
  let m = mode(1)
  if m != s:m
    if m == 'no'
      call SetCursor(3)
      if s:m == 'no'
        call SetCursor(0)
    let s:m = m

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, privacy policy and cookie policy

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