Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Vim autoreply

A modified version of Romain's gist which I recomend checking out.

Instead we pull the last line from the command history with histget() and take the first expansion of what looks to be the first command* with getcompletion(). This gives us the proper command name which we can match against literally.

Also rather than always having to return a carriage return and whatever else in an expression I've opted to use an autocmd.

This also fixes what could be considered a minor bug at the time of writting in the original the dlist and ilist mapping. The pattern may have spaces so rather than increment the cursor backwards move it to the start then increment it forwards to the correct destination.

* This of course doesn't work with things like :g/foo/# and to make that work would require a lot more logic. Instead I take the easy way out and just do nnoremap <key> :global //#<Left><Left> instead.

Just throwing this up so I can play around with further modifications.

function! AutoReply()
  let previous_cmdline  = histget('cmd', -1)
  let previous_cmd      = split(previous_cmdline)[0]
  let previous_args     = split(previous_cmdline)[1:]

  let ignorecase    = &ignorecase
  set noignorecase
  let previous_cmd  = get(getcompletion(previous_cmd, 'command'), 0)
  let &ignorecase   = ignorecase

  if empty(previous_cmd)
    return
  endif

  if previous_cmd ==# 'global'
    call feedkeys(':', 'n')
  elseif previous_cmd ==# 'undolist'
    call feedkeys(':undo' . ' ', 'n')
  elseif previous_cmd ==# 'oldfiles'
    call feedkeys(':edit #<', 'n')
  elseif previous_cmd ==# 'marks'
    call feedkeys(':normal! `', 'n')

  elseif previous_cmd ==# 'changes'
    call feedkeys(':normal! g;', 'n')
    call feedkeys("\<S-Left>", 'n')
  elseif previous_cmd ==# 'jumps'
    call feedkeys(':normal!' . ' ', 'n')
    call feedkeys("\<C-O>\<S-Left>", 'n')

  elseif index(['ls', 'files', 'buffers'], previous_cmd) != -1
    call feedkeys(':buffer' . ' ', 'n')
  elseif index(['clist', 'llist'], previous_cmd) != -1
    call feedkeys(':silent' . ' ' . repeat(previous_cmd[0], 2) . ' ', 'n')
  elseif index(['dlist', 'ilist'], previous_cmd) != -1
    call feedkeys(':' . previous_cmd[0] . 'jump' . ' ' . join(previous_args), 'n')
    call feedkeys("\<Home>\<S-Right>\<Space>", 'n')
  endif
endfunction

augroup AutoReply
  autocmd!
  autocmd CmdlineLeave : call AutoReply()
augroup END
@benknoble

This comment has been minimized.

Copy link

benknoble commented Jan 5, 2020

One way to handle :g/foo/# is to take split(previous_cmdline, '\A')[0]. Technically, a :command may have digits in the name, but no builtins that I'm aware of do, and no plugins that I use do.

The only problem is that entering, say, :23 fails, since 'split('23', '\A') == []

@benknoble

This comment has been minimized.

Copy link

benknoble commented Jan 5, 2020

Ok, so I added

  • :tags and :registers replies
  • cancellable replies (i.e., if, after :g /foo/#, you don't want to do :23, you can just use <Esc> or <C-c> as normal, and we won't stick you in an infinite loop)

https://gist.github.com/benknoble/d53208c6f1ad8f2130fd706c9cdbd006

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.