X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=plugin%2Fmkbuild.vim;fp=plugin%2Fmkbuild.vim;h=6aac93653a0957447f03f2aa607767186429dce8;hb=6e251a420b39df1ab77ce60af69905891632d113;hp=eb3fd2bd767cba259abe9a9ebbb991d4d82c3d48;hpb=b927f34f30485d6448f10abf196d7e32c503aff5;p=vim-mkbuild.git diff --git a/plugin/mkbuild.vim b/plugin/mkbuild.vim index eb3fd2b..6aac936 100644 --- a/plugin/mkbuild.vim +++ b/plugin/mkbuild.vim @@ -5,48 +5,80 @@ 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 a list directories contained within an extrefs file at 'dir'. Use +" '.' as dir if wanting to find extrefs in the current directory. The +" returned list may be empty. Directories returned are not validated. +function! s:extrefs(dir) + let extdirs = [] + let extrefs = a:dir . '/extrefs' + if filereadable(extrefs) + for e in split(s:chompsys( + \ "grep ^git " . extrefs . "| awk '{ print $3 }'")) + if !empty(e) + call add(extdirs, a:dir . '/' . e) + endif + endfor + endif + return extdirs +endfunction + +" Return a list of files found using 'find', recursively, starting at 'dir' +function s:filesFromFind(dir) + return split(s:chompsys("cd " . a:dir . " 2>/dev/null && find . -type f"), + \ '\n') +endfunction + +" If 'dir' is empty, assume the current directory. Assume 'dir' is within a +" Git checkout. If true, return a list of tracked files from the Get +" repository. Otherwise, return an empty string. +function! s:gitTopLevel(dir) 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 . "/|')" +" 'dir' must either be an empty string or a directory within a Git checkout, +" generally its top level directory. Return a list of all tracked files +" within the repository starting at 'dir'. +function! s:filesFromGit(dir) + if empty(a:dir) + return [] + else + return split(s:chompsys("git --git-dir=" . a:dir . "/.git ls-files | " + \ . "sed -e s'|^|" . a:dir . "/|'"), '\n') + endif 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) +" Return a list of files contained within the directory 'dir'. If 'dir' +" belongs to a Git working directory, return all tracked files in the +" repository. Otherwise, use find to return the files at the filesystem +" subtree starting at 'dir'. +" +" Additionally, if 'dir' (or instead the Git top-level working directory), +" contains an extrefs file, recursively include files from each of its listed +" directories. +function! s:filesFromDir(dir) + let dir = s:gitTopLevel(a:dir) + if !empty(dir) + let files = s:filesFromGit(dir) else - call add(dirs, topdir) - let extrefs = topdir . '/extrefs' + let dir = a:dir + let files = s:filesFromFind(dir) + endif + if !empty(files) + let extrefs = dir . '/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) + if !empty(e) + call extend(files, s:filesFromDir(dir . '/' . e)) endif endfor endif endif - return dirs + return files 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() @@ -59,16 +91,16 @@ function! s:tagfiles() 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)" +" Return a list of files with full paths, parsed from the named tags (ctags) +" file. +function! s:filesFromTagsFile(tagfile) + return split(s:chompsys("grep -v \"!\" " . a:tagfile . + \ " | awk -F\\\t '{ print $2 }' | sort -u"), '\n') 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() +function! s:filelistfiles() let files = [] for t in s:tagfiles() let f = substitute(t, '\c\(\.\/\)*tags.*$', 'filelist', '') @@ -79,88 +111,39 @@ function! s:filelists() 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 . ")" +" Return a list of files with full paths, parsed from the named filelist file. +function! s:filesFromFilelistFile(filelist) + return split(s:chompsys("cat " . a:filelist), '\n') 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 } +" Return a list of all project files. Where possible, use tracked files from +" the project Git repository, else collect all files. Also follow 'extrefs' +" files to additional, external sources. +function! mkbuild#allFiles() + return s:filesFromDir('.') 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" +" Return the subset of project files used in the build referenced by the +" directory defined in the 'tags' variable. Use the mkbuild filelist, if +" available, or fall back to extracting files from the tags file. If no +" source of filelist or tags files are available, revert to returning all +" proejct files. +function! mkbuild#buildFiles() + let files = [] + let flfiles = s:filelistfiles() + if !empty(flfiles) + for f in flfiles + call extend(files, s:filesFromFilelistFile(f)) + endfor 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 + let tagfiles = s:tagfiles() + if !empty(tagfiles) + for t in tags + call extend(files, s:filesFromTagsFile(t)) + endfor + else + call extend(files, s:filesFromDir('.')) endif - execute a:cmd . " " . fname endif + return files endfunction