--- /dev/null
+*mkbuild.txt* Plugin for integrating with mkbuild build system features
+
+Author: R. Steve McKown <rsmckown@gmail.com>
+License: Same terms as Vim itself (see |license|)
+
+This plugin is only available if 'compatible' is not set.
+
+INTRODUCTION *mkbuild*
+
+This plugin provides features for working with code using the mkbuild build
+system. The only tool currently available is a method to select files from
+the project using dmenu, which will also work without mkbuild.
+
+Map mkbuild#DmenuOpen(cmd) to some key, such as:
+nnoremap <leader>e :call mkbuild#DmenuOpen('e')<CR>
+
+The function will use dmenu to select a file to execute with provided
+argument. If no file is selected by the user via dmenu, or if dmenu is not
+installed, no action is taken. This idea was originally discovered at
+http://leafo.net/posts/using_dmenu_to_open_quickly.html.
+
+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. The filelist file is built by mkbuild and will be available to vim
+ sessions started via 'make <platform> edit'.
+
+2. Any tags files found in &tags. The file is parsed to get filenames.
+ A tags file is set by mkbuild's 'make <platform> edit', but other tag files
+ created outside of mkbuild should be parseable as well. This function does
+ not due the directory traversing than vim can normally do to find tag
+ files.
+
+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.
+
+ vim:tw=78:ts=8:ft=help:norl:
--- /dev/null
+" 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
+
+" 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 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
+ let fname = s:chompsys(sourcecmd . ' | dmenu -i -l 20 -p "' . source . '(' .
+ \ a:cmd . ')"')
+ if empty(fname)
+ return
+ endif
+ execute a:cmd . " " . fname
+ endif
+endfunction