Skip to content

Commit cd57a05

Browse files
committed
Add support for sapling SCM
This adds the ability for GFiles to return a list of files from sapling (https://sapling-scm.org), rather than from git. This extends git support, rather than adding a separate API for it because the two can interoperate and it comes handy not to have to think about the repository type of your project.
1 parent 678ee1a commit cd57a05

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

autoload/fzf/vim.vim

+56-1
Original file line numberDiff line numberDiff line change
@@ -699,11 +699,66 @@ function! s:git_version_requirement(...)
699699
return s:version_requirement(s:git_version, a:000)
700700
endfunction
701701

702+
" Get the rootdir of sapling, i.e. the first path that contains a .sl
703+
" directory.
704+
function! s:get_sapling_root(dir)
705+
let dir = len(a:dir) ? a:dir : substitute(split(expand('%:p:h'), '[/\\]\.sl\([/\\]\|$\)')[0], '^fugitive://', '', '')
706+
let root = systemlist('cd ' . fzf#shellescape(dir) . ' && sl root')[0]
707+
return v:shell_error ? '' : (len(a:dir) ? fnamemodify(a:dir, ':p') : root)
708+
endfunction
709+
710+
" Get the list of files from sapling
711+
function! s:sapling_gitfiles(args, ...)
712+
let dir = get(get(a:, 1, {}), 'dir', '')
713+
let root = s:get_sapling_root(dir)
714+
if empty(root)
715+
return s:warn('Not in git / sapling repository')
716+
endif
717+
if a:args != '?'
718+
let prefix = 'cd ' . fzf#shellescape(root) . ' && sl '
719+
echo(a:args)
720+
echo(prefix)
721+
let source = prefix . 'files -0 ' . a:args
722+
echo(source)
723+
return s:fzf('gfiles', {
724+
\ 'source': source,
725+
\ 'dir': root,
726+
\ 'options': '-m --read0 --prompt "SlFiles> "'
727+
\}, a:000)
728+
endif
729+
730+
" Here be dragons!
731+
" We're trying to access the common sink function that fzf#wrap injects to
732+
" the options dictionary.
733+
let bar = s:is_win ? '^|' : '|'
734+
let diff_prefix = 'cd ' . s:escape_for_bash(root) . ' && sl '
735+
let preview = printf(
736+
\ s:bash() . ' -c "if [[ {1} =~ M ]]; then %s; else %s {-1}; fi"',
737+
\ executable('delta')
738+
\ ? diff_prefix . 'diff -- {-1} ' . bar . ' delta --width $FZF_PREVIEW_COLUMNS --file-style=omit ' . bar . ' sed 1d'
739+
\ : diff_prefix . 'diff --color=always -- {-1} ' . bar . ' sed 1,4d',
740+
\ s:escape_for_bash(s:bin.preview))
741+
let wrapped = fzf#wrap({
742+
\ 'source': prefix . '-c color.status=always status --short --untracked-files=all',
743+
\ 'dir': root,
744+
\ 'options': ['--ansi', '--multi', '--nth', '2..,..', '--tiebreak=index', '--prompt', 'GitFiles?> ', '--preview', preview]
745+
\})
746+
call s:remove_layout(wrapped)
747+
let wrapped.common_sink = remove(wrapped, 'sink*')
748+
function! wrapped.newsink(lines)
749+
let lines = extend(a:lines[0:0], map(a:lines[1:], 'substitute(v:val[3:], ".* -> ", "", "")'))
750+
return self.common_sink(lines)
751+
endfunction
752+
let wrapped['sink*'] = remove(wrapped, 'newsink')
753+
return s:fzf('gfiles-diff', wrapped, a:000)
754+
endfunction
755+
702756
function! fzf#vim#gitfiles(args, ...)
703757
let dir = get(get(a:, 1, {}), 'dir', '')
704758
let root = s:get_git_root(dir)
705759
if empty(root)
706-
return s:warn('Not in git repo')
760+
" Try with sapling instead
761+
return call('s:sapling_gitfiles', [a:args] + a:000)
707762
endif
708763
let prefix = 'git -C ' . fzf#shellescape(root) . ' '
709764
if a:args != '?'

0 commit comments

Comments
 (0)