0

I have 2 ways to open a file for editing:

  1. :b <filename> to switch to an opened buffer -- imagine that I have a lot of folders containing index.html so by using :b I know I am working on the one that I should be working on.

  2. Fuzzy File Search (:FZF) just in case I haven't opened the file or I have killed the buffer with :bd.

My question: Is there a way to automate, such that if :b <filename> fails (E94: No matching buffer), nvim will call :FZF and use <filename> to search?

P.S. It'd be best if I used :b107 and I mistyped the number, FZF will not be triggered. (distinguishing cases whether I use :b with string or number)

1

You can't change the way the :b command works, but you can create an alternative :B command, and then create an abbreviation to always use the :B command when you type :b.

The below works by first trying using the :b command, and if the E94 error is thrown, doing a :FZF instead:

function! BWithFallback(buffer_name) abort
  " Check if the input is a number or a string
  if a:buffer_name =~# '^\d\+$'
    execute 'b' a:buffer_name
  else
    try
      " Try opening the buffer
      execute 'b' a:buffer_name
    catch /E94/
      " If the buffer didn't exist, try doing a fuzzy file search
      " using the command provided by the OP.
      execute 'FZF -q' a:buffer_name
    endtry
  endif
endfunction

" Create new :B command. You could also use -complete=file if you prefer
command! -nargs=1 -complete=buffer B call BWithFallback('<args>')

" When you type :b, replace it with :B
cnoreabbrev <expr> b (getcmdtype() == ':' && getcmdline() ==# 'b') ? 'B' : b
  • 3
    Maybe a nice addition would be to use -complete=buffer and/or -complete=file to the command! command to allow some autocompletion like the original :b does. – statox Apr 18 '18 at 9:20
  • 1
    @statox Great point! – Rich Apr 18 '18 at 9:29
  • Thank you! One more question: (Verified with vim, strange) If I have opened a file named index.php, even after I :bd and :ls to verify that the buffer is deleted, :B index will not go to the else case.. while :b index returns E94. By the way, for fzf it is execute 'FZF -q '.a:buffer_name. Spent time finding ways to type in Terminal Emulator and in vain.. – Sunny Pun Apr 19 '18 at 4:24
  • @SunnyPun I thought you requested that it doesn't ever call FZF if you pass in a number. If I've misunderstood you, you can just remove the if block and keep only the contents of the else block. Thanks for confirming the fzf command. I'll add that into the answer. – Rich Apr 19 '18 at 8:29
  • 1
    @SunnyPun When you use :bd, it closes the buffer, but doesn't remove all knowledge of it. The command :ls! will show all buffers, even deleted ones. Thus, :b partialname still opens the buffer. (However, :b fullname will also still open it: I don't know why Vim doesn't exhibit that behaviour for you.) This is Vim's default behaviour. If you don't want this to occur, you'll need to use :bwipeout to remove the buffer completely, but be aware of what this actually does before doing so. – Rich Apr 19 '18 at 11:18

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.