2

I often want to open files using the wildcards like

:e **/foo.bar

However every now and then I get an

E77: Too many file names

What I would like to have would be to add to that error message a list of the files found. That way, I can get the path to the one I want. I know that I can do something like

:arga **/foo.bar
:ls

But I would like to have it run automatically. For example populating the quickfix list, or something like that.

An idea would be to catch the E77 and run some command to list them.

2 Answers 2

3

Completion

Use <tab> to complete a filename. If you know there are going to be many candidates then you can use <c-d> to list out the candidates. May want to look into 'wildmenu' & 'wildemode' settings as well.

Argument List

You can use :next with your argument to populate the argument list.

:next **/foo

Now you can use :next/:prev to move along the argument list. Use :args to show the list.

Catching the error with try/catch

In order to catch E77 you will need to create a custom command and then use :try & :catch blocks.

command! -complete=file -nargs=1 -bar EList call s:elist(<f-args>)
function! s:elist(path)
    try
        silent execute 'edit ' . a:path
    catch /^Vim\%((\a\+)\)\=:E77:/
        cexpr getcompletion(a:path, 'file')
        cwindow
    endtry
endfunction
2
  • I like the cexpr/cwindow; learned something new
    – D. Ben Knoble
    May 31, 2019 at 14:41
  • Didn't know cexpr exists, +1.
    – dedowsdi
    May 31, 2019 at 23:16
1

I don't like quickfix in this case, i think input is better. I did both of them, choose the one you like.

function! s:edit(pattern)
  let files = glob(a:pattern, 0, 1)

  " do nothing if no file matches
  if empty(files) | return | endif

  " open single result
  if len(files) == 1
    exec 'e ' . files[0]
    return
  endif

  " otherwise warn and populate qflist
  " echohl WarningMsg
  " echo "too many files : \n\n" . join(files, "\n")
  " echohl None

  " call setqflist(map(files, '{"filename": v:val}'))
  " copen

  " otherwise let user select one
  let items = map(deepcopy(files), ' (v:key+1) . " : " . v:val ')
  let choice = input(
        \ "too many files : \n\n" . join(items, "\n") . "\n\nselect file : ")
  if empty(choice) || choice <= 0 || choice > len(files)
    return
  endif
  exec 'e ' . files[choice - 1]
endfunction

command! -nargs=+ -complete=file E call s:edit(<q-args>)

I don't use it. I prefer fzf.vim.

Your Answer

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

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