2

Case

A user defined command to open files recursively in a directory.

The command

After weeks trying to get this to work, I got to the following code after trying to understand this answer:

function! DumbnoteOpenNote(...)
    let Note = a:1
    execute "e " Note 
endfunction

function! DumbnotePathsCompletion(...)
    return split(globpath(g:dumbnoteDefaultCollection, '**/*'), '\n')
endfunction

command! -bang -complete=customlist,DumbnotePathsCompletion -nargs=* DumbnoteOpenNote call DumbnoteOpenNote(<f-args>)

The problem

Given the following directory structure:

|--ADirectory
    |--BDirectory
    |  |--Afile
    |  |--Bfile
    |
    |--Cdirectory
    |  |--Afile
    |  |--Bfile
    |
    |--Afile
    |--Bfile
    |--Cfile

Typing:

:DumbnoteOpenNote <tab>

will expand to the path specified in the customlist and the completion works just fine with both tab and the arrows.

Here is my first question:

Does it really need to expand to the whole path (in this case /home/user/path/)? When I use the command, I already know that I am looking for completion only in that path, and I don't need to see the whole path.

Is it possible to get completion from that path on?

Despite of that, if I type:

:DumbnoteOpenNote <tab>Bf<tab>

Hoping to get the completion to the Bfile, the completion will just come back to the first alphabetical item. The same happens if typing:

:DumbnoteOpenNote <tab>CD<tab>

Assuming that the idea is to get completion to the CDirectory. After that ..CD<tab> the completion will - again - jump back to the first alphabetical item, in both cases it means BDirectory/.

Why would the -complete=customlist be alphabetically ordered? And is it possible to configure that?

This behavior happens both on Vim

Is it possible to get completion from that path on Vim 8 and Neovim 0.2 both installed from the official Archlinux repositories.

Any help on how to improve this question (and the ascii repository structure) is appreciated.

Thanks in advance!

  • I may be missing something but your goal is to use execute "e " Note so why don't you simply use :e and :find with your path set properly (something like set path+=** for example)? – statox Sep 15 '17 at 11:23
  • Your custom completion doesn't take any input into account. It just simply returns a globpath of the path. So yeah, every time it just returns the whole list. You'll need to filter the globpath against ArgLead (described in :help :command-completion-customlist). – Tumbler41 Sep 15 '17 at 16:26
  • @statox, thanks for taking the time. You are not missing anything. That's exactely what I do, but I wanted to get the command with completion from that directory on (despite of cwd). (: – lsrdg Sep 15 '17 at 19:53
  • @Tumbler41 thanks for the directions, but I'm afraid it will take at least some weeks untill I'm able to decode what you meant. The command I wrote was based on the last example in :h :command-completion-customlist. I've been reading that help pages since some weeks ago, but haven't understood that yet... :/ – lsrdg Sep 15 '17 at 19:57
2

When defining a custom completion function, whatever you return will go into the completion list. I.e. if you defined this:

function! DumbnotePathsCompletion(...)
    return "foo"
endfunction

The completion list would always be "foo" regardless of what you typed. However, vim does let you know what the user has typed so far in the form of the ArgLead parameter. So if you want a list that only matches what the user has typed so far, you can do that! But you have to do it from scratch. Something like this should work I think:

function! DumbnotePathsCompletion(ArgLead, CmdLine, CursorPos)
       let myList = split(globpath(g:dumbnoteDefaultCollection, '**/*'), '\n')
       return filter(myList, 'v:val =~ "^'. a:ArgLead .'"')
endfunction

There's a bit going on here, but the important part is the filter() command. It takes the list you generated with globpath and compares each item to a:ArgLead. If ArgLead isn't part of the item then it's removed. This way only the items that match go into the completion list.

Additionally you said you wanted to only return relative paths. I'll leave this as an exercise to the reader, but suffice it to say that you could use the current working directory and remove that from any of the items in the list.

See :help filter() and :help :command-completion-customlist for more info.

  • wow! Just copy and paste and it worked! I'll look into it deep later and then update the question as needed. Thank you veeery much indeed. I read the lines about the ArgLead many times and couldn't understand... until you answered! :D – lsrdg Sep 15 '17 at 21:32

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.