Mercurial > vim-gutentags
comparison autoload/gutentags/ctags.vim @ 252:56dc6f8e5472
Use tag-relative paths in ctags when needed.
This is necessary when the tags file isn't generated at the project root.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 26 Oct 2019 01:17:19 -0700 |
parents | 36dabe30ab6e |
children | ec292bfbd633 |
comparison
equal
deleted
inserted
replaced
251:e61d20280c6c | 252:56dc6f8e5472 |
---|---|
76 | 76 |
77 function! gutentags#ctags#generate(proj_dir, tags_file, gen_opts) abort | 77 function! gutentags#ctags#generate(proj_dir, tags_file, gen_opts) abort |
78 let l:write_mode = a:gen_opts['write_mode'] | 78 let l:write_mode = a:gen_opts['write_mode'] |
79 | 79 |
80 let l:tags_file_exists = filereadable(a:tags_file) | 80 let l:tags_file_exists = filereadable(a:tags_file) |
81 let l:tags_file_relative = fnamemodify(a:tags_file, ':.') | 81 |
82 let l:tags_file_is_local = len(l:tags_file_relative) < len(a:tags_file) | 82 " If the tags file exists, we may want to do a sanity check to prevent |
83 | 83 " weird errors that are hard to troubleshoot. |
84 if l:tags_file_exists && g:gutentags_ctags_check_tagfile | 84 if l:tags_file_exists && g:gutentags_ctags_check_tagfile |
85 let l:first_lines = readfile(a:tags_file, '', 1) | 85 let l:first_lines = readfile(a:tags_file, '', 1) |
86 if len(l:first_lines) == 0 || stridx(l:first_lines[0], '!_TAG_') != 0 | 86 if len(l:first_lines) == 0 || stridx(l:first_lines[0], '!_TAG_') != 0 |
87 call gutentags#throw( | 87 call gutentags#throw( |
88 \"File ".a:tags_file." doesn't appear to be ". | 88 \"File ".a:tags_file." doesn't appear to be ". |
90 \":GutentagsUpdate!.") | 90 \":GutentagsUpdate!.") |
91 return | 91 return |
92 endif | 92 endif |
93 endif | 93 endif |
94 | 94 |
95 " Get a tags file path relative to the current directory, which | |
96 " happens to be the project root in this case. | |
97 " Since the given tags file path is absolute, and since Vim won't | |
98 " change the path if it is not inside the current directory, we | |
99 " know that the tags file is "local" (i.e. inside the project) | |
100 " if the path was shortened (an absolute path will always be | |
101 " longer than a true relative path). | |
102 let l:tags_file_relative = fnamemodify(a:tags_file, ':.') | |
103 let l:tags_file_is_local = len(l:tags_file_relative) < len(a:tags_file) | |
104 let l:use_tag_relative_opt = 0 | |
105 | |
95 if empty(g:gutentags_cache_dir) && l:tags_file_is_local | 106 if empty(g:gutentags_cache_dir) && l:tags_file_is_local |
96 " If we don't use the cache directory, we can pass relative paths | 107 " If we don't use the cache directory, we can pass relative paths |
97 " around. | 108 " around. |
98 " | 109 " |
99 " Note that if we don't do this and pass a full path for the project | 110 " Note that if we don't do this and pass a full path for the project |
100 " root, some `ctags` implementations like Exhuberant Ctags can get | 111 " root, some `ctags` implementations like Exhuberant Ctags can get |
101 " confused if the paths have spaces -- but not if you're *in* the root | 112 " confused if the paths have spaces -- but not if you're *in* the root |
102 " directory, for some reason... (which we are, our caller in | 113 " directory, for some reason... (which will be the case, we're running |
103 " `autoload/gutentags.vim` changed it). | 114 " the jobs from the project root). |
104 let l:actual_proj_dir = '.' | 115 let l:actual_proj_dir = '.' |
105 let l:actual_tags_file = l:tags_file_relative | 116 let l:actual_tags_file = l:tags_file_relative |
117 | |
118 let l:tags_file_dir = fnamemodify(l:actual_tags_file, ':h') | |
119 if l:tags_file_dir != '.' | |
120 " Ok so now the tags file is stored in a subdirectory of the | |
121 " project root, instead of at the root. This happens if, say, | |
122 " someone set `gutentags_ctags_tagfile` to `.git/tags`, which | |
123 " seems to be fairly popular. | |
124 " | |
125 " By default, `ctags` writes paths relative to the current | |
126 " directory (the project root) but in this case we need it to | |
127 " be relative to the tags file (e.g. adding `../` in front of | |
128 " everything if the tags file is `.git/tags`). | |
129 " | |
130 " Thankfully most `ctags` implementations support an option | |
131 " just for this. | |
132 let l:use_tag_relative_opt = 1 | |
133 endif | |
106 else | 134 else |
107 " else: the tags file goes in a cache directory, so we need to specify | 135 " else: the tags file goes in a cache directory, so we need to specify |
108 " all the paths absolutely for `ctags` to do its job correctly. | 136 " all the paths absolutely for `ctags` to do its job correctly. |
109 let l:actual_proj_dir = a:proj_dir | 137 let l:actual_proj_dir = a:proj_dir |
110 let l:actual_tags_file = a:tags_file | 138 let l:actual_tags_file = a:tags_file |
161 endif | 189 endif |
162 endif | 190 endif |
163 for exc in g:gutentags_ctags_exclude | 191 for exc in g:gutentags_ctags_exclude |
164 let l:cmd += ['-x', '"' . exc . '"'] | 192 let l:cmd += ['-x', '"' . exc . '"'] |
165 endfor | 193 endfor |
194 if l:use_tag_relative_opt | |
195 let l:cmd += ['-r'] | |
196 endif | |
166 if g:gutentags_pause_after_update | 197 if g:gutentags_pause_after_update |
167 let l:cmd += ['-c'] | 198 let l:cmd += ['-c'] |
168 endif | 199 endif |
169 if g:gutentags_trace | 200 if g:gutentags_trace |
170 let l:cmd += ['-l', '"' . l:actual_tags_file . '.log"'] | 201 let l:cmd += ['-l', '"' . l:actual_tags_file . '.log"'] |