" ingo/cmdargs/glob.vim: Functions for expanding file glob arguments. " " DEPENDENCIES: " " Copyright: (C) 2012-2020 Ingo Karkat " The VIM LICENSE applies to this script; see ':help copyright'. " " Maintainer: Ingo Karkat function! ingo#cmdargs#glob#ExpandSingle( fileglob, ... ) "****************************************************************************** "* PURPOSE: " Expand any file wildcards in a:fileglob to a list of normal filespecs. "* ASSUMPTIONS / PRECONDITIONS: " None. "* EFFECTS / POSTCONDITIONS: " None. "* INPUTS: " a:fileglob File glob (already processed by " ingo#cmdargs#file#Unescape()). " a:isKeepNoMatch Optional flag that lets globs that have no matches be kept " and returned as-is, instead of being removed. Set this when " you want to support creating new files. " a:isKeepDirectories Optional flag that keeps directories in the list. "* RETURN VALUES: " List of normal filespecs; globs have been expanded. To consume this in " another Vim command, use: " join(map(l:filespecs, 'fnameescape(v:val))) "****************************************************************************** " XXX: Special Vim variables are expanded by -complete=file, but (in Vim " 7.3), escaped special names are _not_ correctly re-escaped, and a " following glob() or expand() will mistakenly expand them. Because of the " auto-expansion, any unescaped special Vim variable that gets here is in " fact a literal special filename. We don't even need to re-escape and " glob() it, just return it verbatim. if a:fileglob =~# '^\%(%\|#\d\?\)\%(:\a\)*$\|^<\%(cfile\|cword\|cWORD\)>\%(:\a\)*$' return [a:fileglob] else " Filter out directories; we're usually only interested in files. let l:specs = (a:0 && a:1 ? split(expand(a:fileglob), '\n') : ingo#compat#glob(a:fileglob, 0, 1)) return (a:0 >= 2 && a:2 ? l:specs : filter(l:specs, '! isdirectory(v:val)')) endif endfunction function! ingo#cmdargs#glob#Expand( fileglobs, ... ) "****************************************************************************** "* PURPOSE: " Expand any file wildcards in a:fileglobs to a list of normal filespecs. "* ASSUMPTIONS / PRECONDITIONS: " None. "* EFFECTS / POSTCONDITIONS: " None. "* INPUTS: " a:fileglobs Either space-separated arguments string (from a :command " -complete=file ... custom command), or a list of " fileglobs (already processed by " ingo#cmdargs#file#Unescape()). " a:isKeepNoMatch Optional flag that lets globs that have no matches be kept " and returned as-is, instead of being removed. Set this when " you want to support creating new files. " a:isKeepDirectories Optional flag that keeps directories in the list. "* RETURN VALUES: " List of filespecs; globs have been expanded. To consume this in another Vim " command, use: " join(map(l:filespecs, 'fnameescape(v:val))) "****************************************************************************** let l:fileglobs = (type(a:fileglobs) == type([]) ? a:fileglobs : ingo#cmdargs#file#SplitAndUnescape(a:fileglobs)) let l:filespecs = [] for l:fileglob in l:fileglobs call extend(l:filespecs, call('ingo#cmdargs#glob#ExpandSingle', [l:fileglob] + a:000)) endfor return l:filespecs endfunction function! s:FileLinePredicate( filespec ) abort let l:names = matchlist(a:filespec, '\(.\{-1,}\):\%(\(\d\+\)\%(:\(\d*\):\?\)\?\)\?$') return (! empty(l:names) && filereadable(l:names[1])) endfunction if ! exists('g:IngoLibrary_SpecialFilePredicates') let g:IngoLibrary_SpecialFilePredicates = [] call add(g:IngoLibrary_SpecialFilePredicates, 'v:val =~# ''^\w\+:/''') " Assume that files that start with "protocol:/" do exist (usually handled by the netrw plugin) if exists('g:loaded_file_line') && g:loaded_file_line call add(g:IngoLibrary_SpecialFilePredicates, function('s:FileLinePredicate')) endif endif function! ingo#cmdargs#glob#IsSpecialFile( filespec ) abort for l:SpecialFileReadablePredicate in g:IngoLibrary_SpecialFilePredicates if ingo#actions#EvaluateWithValOrFunc(l:SpecialFileReadablePredicate, a:filespec) return 1 endif unlet! l:SpecialFileReadablePredicate endfor return 0 endfunction function! s:ContainsNoWildcards( fileglob ) " Note: This is only an empirical approximation; it is not perfect. if ingo#os#IsWinOrDos() return a:fileglob !~ '[*?]' else return a:fileglob !~ '\\\@