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)

Sunny Pun
  • 472
  • 3
  • 10

1 Answers1

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
Rich
  • 31,891
  • 3
  • 72
  • 139
  • 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 09:20
  • 1
    @statox Great point! – Rich Apr 18 '18 at 09: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 04: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 08:29
  • @Rich Nope you didn’t misunderstand me. My aforementioned problem is, I typed a non-numeric partial file name (index.php), instead of calling FZF, it reopened a buffer that I deleted with :bd. However if I used :b index.php it won’t open the deleted buffer. And I want :B to resort to FZF when there is no opened buffer corresponding to the partial name. – Sunny Pun Apr 19 '18 at 11:03
  • 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