changeset 89:8bf96f9f649c

Add support for project types.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 01 Dec 2015 22:04:45 -0800
parents 073e63cc0456
children b9965d1288c3
files autoload/gutentags.vim autoload/gutentags/ctags.vim doc/gutentags.txt plugin/gutentags.vim
diffstat 4 files changed, 90 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/autoload/gutentags.vim	Tue Nov 24 21:47:26 2015 -0800
+++ b/autoload/gutentags.vim	Tue Dec 01 22:04:45 2015 -0800
@@ -56,6 +56,27 @@
 " Gutentags Setup {{{
 
 let s:known_files = []
+let s:known_projects = {}
+
+function! s:cache_project_root(path) abort
+    let l:result = {}
+
+    for proj_info in g:gutentags_project_info
+        let l:filematch = get(proj_info, 'file', '')
+        if l:filematch != '' && filereadable(a:path . '/'. l:filematch)
+            let l:result = copy(proj_info)
+            break
+        endif
+
+        let l:globmatch = get(proj_info, 'glob', '')
+        if l:globmatch != '' && glob(a:path . '/' . l:globmatch) != ''
+            let l:result = copy(proj_info)
+            break
+        endif
+    endfor
+
+    let s:known_projects[a:path] = l:result
+endfunction
 
 " Finds the first directory with a project marker by walking up from the given
 " file path.
@@ -79,6 +100,11 @@
     call gutentags#throw("Can't figure out what tag file to use for: " . a:path)
 endfunction
 
+" Get info on the project we're inside of.
+function! gutentags#get_project_info(path) abort
+    return get(s:known_projects, a:path, {})
+endfunction
+
 " Generate a path for a given filename in the cache directory.
 function! gutentags#get_cachefile(root_dir, filename) abort
     let l:tag_path = gutentags#stripslash(a:root_dir) . '/' . a:filename
@@ -128,6 +154,18 @@
             return
         endif
 
+        if !has_key(s:known_projects, b:gutentags_root)
+            call s:cache_project_root(b:gutentags_root)
+        endif
+        if g:gutentags_trace
+            let l:projnfo = gutentags#get_project_info(b:gutentags_root)
+            if l:projnfo != {}
+                call gutentags#trace("Setting project type to ".l:projnfo['type'])
+            else
+                call gutentags#trace("No specific project type.")
+            endif
+        endif
+
         let b:gutentags_files = {}
         for module in g:gutentags_modules
             call call("gutentags#".module."#init", [b:gutentags_root])
--- a/autoload/gutentags/ctags.vim	Tue Nov 24 21:47:26 2015 -0800
+++ b/autoload/gutentags/ctags.vim	Tue Dec 01 22:04:45 2015 -0800
@@ -61,7 +61,7 @@
     try
         " Build the command line.
         let l:cmd = gutentags#get_execute_cmd() . s:runner_exe
-        let l:cmd .= ' -e "' . s:get_ctags_executable() . '"'
+        let l:cmd .= ' -e "' . s:get_ctags_executable(a:proj_dir) . '"'
         let l:cmd .= ' -t "' . a:tags_file . '"'
         let l:cmd .= ' -p "' . a:proj_dir . '"'
         if a:write_mode == 0 && l:tags_file_exists
@@ -128,11 +128,13 @@
 " Utilities {{{
 
 " Get final ctags executable depending whether a filetype one is defined
-function! s:get_ctags_executable() abort
+function! s:get_ctags_executable(proj_dir) abort
     "Only consider the main filetype in cases like 'python.django'
     let l:ftype = get(split(&filetype, '\.'), 0, '')
-    if exists('g:gutentags_ctags_executable_{l:ftype}')
-        return g:gutentags_ctags_executable_{l:ftype}
+    let l:proj_info = gutentags#get_project_info(a:proj_dir)
+    let l:type = get(l:proj_info, 'type', l:ftype)
+    if exists('g:gutentags_ctags_executable_{l:type}')
+        return g:gutentags_ctags_executable_{l:type}
     else
         return g:gutentags_ctags_executable
     endif
--- a/doc/gutentags.txt	Tue Nov 24 21:47:26 2015 -0800
+++ b/doc/gutentags.txt	Tue Dec 01 22:04:45 2015 -0800
@@ -224,10 +224,10 @@
                         Defaults to `ctags`.
 
                                      *gutentags_ctags_executable_{filetype}*
-g:gutentags_ctags_executable_{filetype}
-                        Specifies the ctags executable to launch for
-                        {filetype} files. It has precedence over
-                        g:gutentags_ctags_executable.
+g:gutentags_ctags_executable_{type}
+                        Specifies the ctags executable to launch for a project
+                        of type {type}. See |gutentags_project_info| for more
+                        information.
                         Example: >
                          let g:gutentags_ctags_executable_ruby = 'ripper-tags'
 <
@@ -354,6 +354,42 @@
                         Defines some advanced commands like
                         |GutentagsToggleEnabled| and |GutentagsUnlock|.
 
+                                            *gutentags_project_info*
+g:gutentags_project_info
+                        Defines ways for Gutentags to figure out what kind of
+                        project any given file belongs to. This should be
+                        a list of dictionaries:
+
+                        let g:gutentags_project_info = []
+                        call add(g:gutentags_project_info, {...})
+
+                        Each dictionary item must contain at least a `type`
+                        key, indicating the type of project:
+
+                        {"type": "python"}
+
+                        Other items will be used to figure out if a project is
+                        of the given type.
+
+                        "file": any existing file with this path (relative to
+                        the project root) will make the current project match
+                        the given info.
+
+                        "glob": any result found with this glob pattern
+                        (relative to the project root) will make the current
+                        project match the given info. See |glob()| for more
+                        information.
+
+                        Gutentags adds by default the following definitions:
+
+                        call add(g:gutentags_project_info, {'type': 'python', 'file': 'setup.py'})
+                        call add(g:gutentags_project_info, {'type': 'ruby', 'file': 'Gemfile'})
+
+                        This means, for example, that you can use
+                        `g:gutentags_ctags_executable_ruby` out of the box.
+                        See |gutentags_ctags_executable_{filetype}| for more
+                        information.
+
 
 =============================================================================
 5. Project Settings                             *gutentags-project-settings*
--- a/plugin/gutentags.vim	Tue Nov 24 21:47:26 2015 -0800
+++ b/plugin/gutentags.vim	Tue Dec 01 22:04:45 2015 -0800
@@ -54,6 +54,12 @@
 endif
 let g:gutentags_project_root += ['.git', '.hg', '.svn', '.bzr', '_darcs', '_FOSSIL_', '.fslckout']
 
+if !exists('g:gutentags_project_info')
+    let g:gutentags_project_info = []
+endif
+call add(g:gutentags_project_info, {'type': 'python', 'file': 'setup.py'})
+call add(g:gutentags_project_info, {'type': 'ruby', 'file': 'Gemfile'})
+
 if !exists('g:gutentags_exclude')
     let g:gutentags_exclude = []
 endif