" Tools for use with the mkbuild build environment. " Return the results of a command without the ending newline function! s:chompsys(cmd) return substitute(system(a:cmd), '\n$', '', '') endfunction " Return the top level working directory in a git checkout. If dir is '', " start from the current directory, else start from dir. function! s:gittop(dir) if empty(a:dir) return s:chompsys('git rev-parse --show-toplevel 2>/dev/null') else return s:chompsys("cd " . a:dir . \ " && git rev-parse --show-toplevel 2>/dev/null") endfunction " Return a shell segment that will output a list of files with full paths " parsed from working directory's tracked files. function! s:gitls(workdir) return "(git --git-dir=" . a:workdir . "/.git ls-files | sed -e s'|^|" . \ a:workdir . "/|')" endfunction " Return a list of git directories. If the current directory is in a git " working directory, at least this one will be returned. If the top level of " this directory has an extrefs file, then the valid git directories listed " therein are also added to the list. function! s:gitdirs() let dirs = [] let topdir = s:gittop('') if empty(topdir) else call add(dirs, topdir) let extrefs = topdir . '/extrefs' if filereadable(extrefs) for e in split(s:chompsys( \ "grep ^git " . extrefs . "| awk '{ print $3 }'")) let dir = s:gittop(topdir . '/' . e) if empty(dir) else call add(dirs, dir) endif endfor endif endif return dirs endfunction " Return a list of readable tag files, as present in &tags. This function " doesn't handle the sometimes-default 'tags:/' value I've seen. function! s:tagfiles() let tags = [] for t in split(&tags, ',') if filereadable(t) call add(tags, t) endif endfor return tags endfunction " Return a shell segment that will output a list of files with full paths " parsed from the named tags (ctags) file. function! s:tagls(tagfile) return "(grep -v \"!\" " . a:tagfile . " | awk -F\\\t '{ print $2 }' | " . \ "sort -u)" endfunction " Return a list of readable filelist files, which are looked for in the same " directories where &tags has vim looking for tags files. function! s:filelists() let files = [] for t in s:tagfiles() let f = substitute(t, '\c\(\.\/\)*tags.*$', 'filelist', '') if filereadable(f) call add(files, f) endif endfor return files endfunction " Return a shell segment that will output a list of files with full paths " parsed from the named filelist file. function! s:filels(filelist) return "(cat " . a:filelist . ")" endfunction " Generate a command to generate a list of files. Return a dictionary " containing two entries: " source - The source of the files (generated by executing the sourcecmd) " sourcecmd - The system command to use to generate the list of files " " The source command returned will output files from one of 4 locations, " searched in priority order: " 1. All filelist files found in the same directory(ies) vim looks for tags " files. Files are extracted from the contents of these files. " 2. Any tags files found in &tags. The file is parsed to get filenames. " 3. The tracked files in the current git repository, and/or the tracked files " in those valid git repositories named in the 'extrefs' file, if present. " 4. Perform a 'find . -type f' in the current directory. function! mkbuild#flcmd() let files = s:filelists() if empty(files) let tags = s:tagfiles() if empty(tags) let gitdirs = s:gitdirs() if empty(gitdirs) let source = 'find' let sourcecmd = 'find . -type f' else " gitdirs let source = 'git|extrefs' let sourcecmd = '(true' for g in gitdirs let sourcecmd = sourcecmd . '; ' . s:gitls(g) endfor let sourcecmd = sourcecmd . ')' endif else " tags let source = 'tags' let sourcecmd = '(true' for t in tags let sourcecmd = sourcecmd . '; ' . s:tagls(t) endfor let sourcecmd = sourcecmd . ')' endif else " filelists let source = 'filelists' let sourcecmd = '(true' for f in files let sourcecmd = sourcecmd . '; ' . s:filels(f) endfor let sourcecmd = sourcecmd . ')' endif return { 'source': source, 'sourcecmd': sourcecmd } endfunction " Generate a list of files using mkbuild#flcmd() function! mkbuild#filelist() let flcmdres = mkbuild#flcmd() return s:chompsys(flcmdres['sourcecmd'] . ' | cat') endfunction " Use dmenu to select a file to execute with command 'cmd'. If no file is " selected, no action is taken. The list of files presented to dmenu comes " from one of four places, in the following priority order: " 1. All filelist files found in the same directory(ies) vim looks for tags " files. " 2. Any tags files found in &tags. The file is parsed to get filenames. " 3. The tracked files in the current git repository, and/or the tracked files " in those valid git repositories named in the 'extrefs' file, if present. " 3. Perform a 'find . -type f' in the current directory. function! mkbuild#DmenuOpen(cmd) if empty(system('which dmenu')) echo "Dmenu is not installed" else let flcmdres = mkbuild#flcmd() let source = flcmdres['source'] let sourcecmd = flcmdres['sourcecmd'] let fname = s:chompsys(sourcecmd . ' | dmenu -i -l 20 -p "' . source . '(' . \ a:cmd . ')"') if empty(fname) return endif execute a:cmd . " " . fname endif endfunction