Skip to content

Instantly share code, notes, and snippets.

@UrsaDK
Last active February 3, 2019 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UrsaDK/06511ed246ff63e2e428 to your computer and use it in GitHub Desktop.
Save UrsaDK/06511ed246ff63e2e428 to your computer and use it in GitHub Desktop.
Project structure discovery with Vim & NERDTree
""
" Return project's root directory
"
" This function is used to return current projects root directory, as
" determined by GIT or SVN, without changing vim's cwd.
"
" @param string a:1 A comma seperated list of files or directories, the
" presence of which can be used to identify the root directory of a project.
"
function! UmkaDK#GetProjectRoot(...)
let l:root_markers = a:0 > 0 ? a:1 :
\ 'Vagrant, Makefile, Makefile.PL, Build.PL, composer.json, Gemfile'
let l:parent = expand("%:p:h")
if executable('git')
let l:git_root = system('cd ' . l:parent . ' && git rev-parse --show-toplevel 2>/dev/null')
if !v:shell_error
return substitute(l:git_root, '\(\n\|\s\)*$', '', '')
endif
endif
if executable('svn')
let l:label = 'Working Copy Root Path: '
let l:svn_root = system('cd ' . l:parent . ' && svn info 2>/dev/null | grep "'. l:label . '"')
if !v:shell_error
let l:svn_root = strpart(l:svn_root, strlen(l:label))
return substitute(l:svn_root, '\(\n\|\s\)*$', '', '')
endif
endif
if !empty(l:root_markers)
let l:parent_paths = [ l:parent ]
while l:parent_paths[-1] != '/'
call add(l:parent_paths, fnamemodify(l:parent_paths[-1], ':h'))
endwhile
let l:root_markers = substitute(l:root_markers, '^\s*\(.\{-}\)\s*$', '\1', '')
let l:root_markers = '{' . join(split(l:root_markers, '\v\s*,\s*'), ',') . '}'
let l:markers = globpath(join(l:parent_paths, ','), l:root_markers, 0, 1)
if !empty(l:markers)
let l:modifier = isdirectory(l:markers[0]) ? ':h:h' : ':h'
return fnamemodify(l:markers[0], l:modifier)
endif
endif
endfunction
""
" Open NERDTree in a given directory
"
" This function is used to open NERDTree in a given directory and highlight
" current file within in directory's structure.
"
function! UmkaDK#NERDTreeFind()
let l:path = expand("%:p:h")
if !exists(":NERDTreeFind")
return 0
endif
if !exists('b:project_root') || l:path !~ '^' . b:project_root
let l:project_root = UmkaDK#GetProjectRoot()
if !empty(b:project_root)
let b:project_root = l:project_root
exec 'NERDTreeToggle ' . b:project_root
exec 'NERDTreeClose'
endif
endif
if (!exists('b:project_root') && isdirectory(l:path)) || (b:project_root ==? l:path)
exec 'NERDTreeToggle ' . b:project_root
else
exec 'NERDTreeFind'
endif
endfunction
command! TreeFind call UmkaDK#NERDTreeFind()
nmap <silent> <Leader>wd :call UmkaDK#NERDTreeFind<CR>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment