Sparky
Sparky

Reputation: 2764

File listing in custom autocomplete for Vim

I'm using the Utl plugin for Vim and I'm looking for a method of creating a custom autocomplete function to generate a link to an id tag within the file. The format I want to use is:

:CommandName <file> <id tag in file>

I'd like the function to act like the standard directory completion for the first argument. For the second argument I'd like it to search the file specified in the first argument for all strings beginning with "id=" and return the values.

I've copied a similar function out of the main Utl package, but I've yet to get close to making it work, it currently looks like this:

fu! CompleteArgs(dummy_argLead, cmdLine, dummy_cursorPos)

" Split cmdLine to figure out how many arguments have been provided by user
" so far. If Using argument keepempty=1 for split will provide empty last
" arg in case of a new arg is about to begin or an non empty last argument
" in case of an incomplete last argument. So can just remove the last arg.
exe "echo \"cmdline:\" \"".a:cmdLine."\""
let utlArgs=split(a:cmdLine, '\s\+', 1)
execute "echo" string(utlArgs)
echo "echo" "test complete"
"remove the function name
call remove(utlArgs, -1)

" 1st arg to complete
if len(utlArgs)==1
return string(glob("*"))
endi

" 2nd arg to complete
if len(utlArgs)==2
    "insert code here
endif
endfun

Has anyone got any ideas?

Upvotes: 1

Views: 926

Answers (2)

ib.
ib.

Reputation: 28944

While answering a very similar question, I have written a complete function that determines the number of a command argument to complete. Below is a version of that function, adapted to your case.

command! -nargs=* -complete=custom,FooComplete Foo echo [<f-args>]

function! FooComplete(arg, line, pos)
    let l = split(a:line[:a:pos-1], '\%(\%(\%(^\|[^\\]\)\\\)\@<!\s\)\+', 1)
    let n = len(l) - index(l, 'Foo') - 1
    if n == 1
        return string(glob('*'))
    endif
    return "1\n2\n3"  " Replace this with appropriate id-completion logic.
endfunction

The function properly handles escaped whitespace (as a part of an argument, not a separator) and whitespace before the command name. Note that whitespace characters in suggestion candidates should be escaped, otherwise a single argument would be treated by Vim as two arguments.

Upvotes: 1

ZyX
ZyX

Reputation: 53604

You can try out frawor. If you install it code will be the following:

execute frawor#Setup('0.0', {'@/fwc': '0.2',
            \           '@/commands': '0.0',})
" No need to write bang here: above command will forbid script to be sourced 
" twice, see :h frawor#Reload for how it can be updated.
function s:F.cmdfunc(file, tag)
    " It will be called when the command launches. Alternatively you can replace 
    " `s:F.cmdfunc' in the below command.add call with a string you already had 
    " before. Note that you will have to replace s: in function names with <SID> 
    " and s:* variables will be just unaccessible.
endfunction
function s:F.gettags(file)
    " This assumes that format is the same as used in ~/.vim/doc/tags. Note that 
    " if there may be any spaces, then you must escape them.
    return map(readfile(a:file), 'matchstr(v:val, "\\v^.{-}\\t")[:-2]')
endfunction
" This replaces direct :command call, see :h frawor-f-command.add
call s:_f.command.add('CommandName', s:F.cmdfunc,
            \{  'nargs': '+',
            \'complete': ['path in*F.gettags(@<)']})

Upvotes: 1

Related Questions