let s:Git = vital#gina#import('Git') let s:Path = vital#gina#import('System.Filepath') let s:Store = vital#gina#import('System.Store') let s:String = vital#gina#import('Data.String') function! gina#complete#filename#directory(arglead, cmdline, cursorpos) abort let separator = s:Path.separator() return filter( \ gina#complete#filename#any(a:arglead, a:cmdline, a:cursorpos), \ 'v:val =~# separator . ''$''' \) endfunction function! gina#complete#filename#any(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let candidates = s:get_available_filenames(git, [ \ '--cached', '--others', '--', a:arglead . '*', \]) return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#tracked(arglead, cmdline, cursorpos, ...) abort let rev = a:0 ? a:1 : '' let git = gina#core#get_or_fail() let slug = eval(s:Store.get_slug_expr()) . rev let store = s:Store.of([ \ s:Git.resolve(git, 'HEAD'), \ s:Git.resolve(git, 'index'), \]) let candidates = store.get(slug, []) if empty(candidates) let candidates = s:get_available_filenames(git, [], rev) call store.set(slug, candidates) endif return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#cached(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let slug = eval(s:Store.get_slug_expr()) let store = s:Store.of([ \ s:Git.resolve(git, 'HEAD'), \ s:Git.resolve(git, 'index'), \]) let candidates = store.get(slug, []) if empty(candidates) let candidates = s:get_available_filenames(git, ['--cached']) call store.set(slug, candidates) endif return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#deleted(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let slug = eval(s:Store.get_slug_expr()) let store = s:Store.of([ \ s:Git.resolve(git, 'HEAD'), \ s:Git.resolve(git, 'index'), \]) let candidates = store.get(slug, []) if empty(candidates) let candidates = s:get_available_filenames(git, ['--deleted']) call store.set(slug, candidates) endif return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#modified(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let slug = eval(s:Store.get_slug_expr()) let store = s:Store.of([ \ s:Git.resolve(git, 'HEAD'), \ s:Git.resolve(git, 'index'), \]) let candidates = store.get(slug, []) if empty(candidates) let candidates = s:get_available_filenames(git, ['--modified']) call store.set(slug, candidates) endif return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#others(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let candidates = s:get_available_filenames(git, [ \ '--others', '--', a:arglead . '*', \]) return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#unstaged(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let candidates = s:get_available_filenames(git, [ \ '--others', \ '--modified', \ '--', \ a:arglead . '*', \]) return s:filter(a:arglead, candidates) endfunction function! gina#complete#filename#conflicted(arglead, cmdline, cursorpos) abort let git = gina#core#get_or_fail() let slug = eval(s:Store.get_slug_expr()) let store = s:Store.of([ \ s:Git.resolve(git, 'HEAD'), \ s:Git.resolve(git, 'index'), \]) let candidates = store.get(slug, []) if empty(candidates) let result = gina#process#call(git, [ \ 'status', \ '--porcelain', \ '--ignore-submodules', \]) if result.status return [] endif call filter( \ candidates, \ 'v:val[:1] =~# ''^\%(DD\|AU\|UD\|UA\|DU\|AA\|UU\)''' \) call map(candidates, 'matchstr(v:val, ''.. \zs.*'')') call store.set(slug, candidates) endif return s:filter(a:arglead, candidates) endfunction " Private -------------------------------------------------------------------- function! s:filter(arglead, candidates) abort let pattern = s:String.escape_pattern(a:arglead) let separator = s:Path.separator() let candidates = gina#util#filter(a:arglead, a:candidates, '^\.') call map( \ candidates, \ printf( \ 'matchstr(v:val, ''^%s[^%s]*%s\?\ze'')', \ pattern, separator, separator \ ), \) return uniq(candidates) endfunction function! s:get_available_filenames(git, args, ...) abort let rev = a:0 ? a:1 : '' if empty(rev) let args = ['ls-files', '--full-name'] else let args = [ \ 'ls-tree', \ '--full-name', \ '--full-tree', \ '--name-only', \ '-r', \ rev, \] endif let result = gina#process#call(a:git, args + a:args) if result.status return [] endif return map(result.stdout, 'gina#core#repo#relpath(a:git, v:val)') endfunction