]> oss.titaniummirror.com Git - vim-mkbuild.git/blobdiff - plugin/mkbuild.vim
Improve plugin; consolidate unite sources
[vim-mkbuild.git] / plugin / mkbuild.vim
index eb3fd2bd767cba259abe9a9ebbb991d4d82c3d48..6aac93653a0957447f03f2aa607767186429dce8 100644 (file)
@@ -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