Mercurial > vim-gutentags
comparison autoload/gutentags/ctags.vim @ 198:5fb056a9eefb
Don't change the current working directory more often than needed.
Ctags/Cscope modules do this in their `generate` method when Gutentags already
set the current directory to the project directory ahead of time.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 27 Jul 2017 22:38:02 -0700 |
parents | 685b81826b68 |
children | f7a417234dea |
comparison
equal
deleted
inserted
replaced
197:eec9b72fe3df | 198:5fb056a9eefb |
---|---|
65 let s:did_check_exe = 1 | 65 let s:did_check_exe = 1 |
66 endif | 66 endif |
67 endfunction | 67 endfunction |
68 | 68 |
69 function! gutentags#ctags#generate(proj_dir, tags_file, write_mode) abort | 69 function! gutentags#ctags#generate(proj_dir, tags_file, write_mode) abort |
70 " Get to the tags file directory because ctags is finicky about | |
71 " these things. | |
72 let l:prev_cwd = getcwd() | |
73 call gutentags#chdir(fnameescape(a:proj_dir)) | |
74 | |
75 let l:tags_file_exists = filereadable(a:tags_file) | 70 let l:tags_file_exists = filereadable(a:tags_file) |
76 let l:tags_file_relative = fnamemodify(a:tags_file, ':.') | 71 let l:tags_file_relative = fnamemodify(a:tags_file, ':.') |
77 let l:tags_file_is_local = len(l:tags_file_relative) < len(a:tags_file) | 72 let l:tags_file_is_local = len(l:tags_file_relative) < len(a:tags_file) |
78 | 73 |
79 if l:tags_file_exists && g:gutentags_ctags_check_tagfile | 74 if l:tags_file_exists && g:gutentags_ctags_check_tagfile |
92 " around. | 87 " around. |
93 " | 88 " |
94 " Note that if we don't do this and pass a full path for the project | 89 " Note that if we don't do this and pass a full path for the project |
95 " root, some `ctags` implementations like Exhuberant Ctags can get | 90 " root, some `ctags` implementations like Exhuberant Ctags can get |
96 " confused if the paths have spaces -- but not if you're *in* the root | 91 " confused if the paths have spaces -- but not if you're *in* the root |
97 " directory, for some reason... | 92 " directory, for some reason... (which we are, our caller in |
93 " `autoload/gutentags.vim` changed it). | |
98 let l:actual_proj_dir = '.' | 94 let l:actual_proj_dir = '.' |
99 let l:actual_tags_file = l:tags_file_relative | 95 let l:actual_tags_file = l:tags_file_relative |
100 call gutentags#chdir(fnameescape(a:proj_dir)) | |
101 else | 96 else |
102 " else: the tags file goes in a cache directory, so we need to specify | 97 " else: the tags file goes in a cache directory, so we need to specify |
103 " all the paths absolutely for `ctags` to do its job correctly. | 98 " all the paths absolutely for `ctags` to do its job correctly. |
104 let l:actual_proj_dir = a:proj_dir | 99 let l:actual_proj_dir = a:proj_dir |
105 let l:actual_tags_file = a:tags_file | 100 let l:actual_tags_file = a:tags_file |
106 endif | 101 endif |
107 | 102 |
108 try | 103 " Build the command line. |
109 " Build the command line. | 104 let l:cmd = gutentags#get_execute_cmd() . s:runner_exe |
110 let l:cmd = gutentags#get_execute_cmd() . s:runner_exe | 105 let l:cmd .= ' -e "' . s:get_ctags_executable(a:proj_dir) . '"' |
111 let l:cmd .= ' -e "' . s:get_ctags_executable(a:proj_dir) . '"' | 106 let l:cmd .= ' -t "' . l:actual_tags_file . '"' |
112 let l:cmd .= ' -t "' . l:actual_tags_file . '"' | 107 let l:cmd .= ' -p "' . l:actual_proj_dir . '"' |
113 let l:cmd .= ' -p "' . l:actual_proj_dir . '"' | 108 if a:write_mode == 0 && l:tags_file_exists |
114 if a:write_mode == 0 && l:tags_file_exists | 109 let l:cur_file_path = expand('%:p') |
115 let l:cur_file_path = expand('%:p') | 110 if empty(g:gutentags_cache_dir) && l:tags_file_is_local |
116 if empty(g:gutentags_cache_dir) && l:tags_file_is_local | 111 let l:cur_file_path = fnamemodify(l:cur_file_path, ':.') |
117 let l:cur_file_path = fnamemodify(l:cur_file_path, ':.') | 112 endif |
113 let l:cmd .= ' -s "' . l:cur_file_path . '"' | |
114 else | |
115 let l:file_list_cmd = gutentags#get_project_file_list_cmd(l:actual_proj_dir) | |
116 if !empty(l:file_list_cmd) | |
117 if match(l:file_list_cmd, '///') > 0 | |
118 let l:suffopts = split(l:file_list_cmd, '///') | |
119 let l:suffoptstr = l:suffopts[1] | |
120 let l:file_list_cmd = l:suffopts[0] | |
121 if l:suffoptstr == 'absolute' | |
122 let l:cmd .= ' -A' | |
123 endif | |
118 endif | 124 endif |
119 let l:cmd .= ' -s "' . l:cur_file_path . '"' | 125 let l:cmd .= ' -L ' . '"' . l:file_list_cmd. '"' |
126 endif | |
127 endif | |
128 if empty(get(l:, 'file_list_cmd', '')) | |
129 " Pass the Gutentags recursive options file before the project | |
130 " options file, so that users can override --recursive. | |
131 " Omit --recursive if this project uses a file list command. | |
132 let l:cmd .= ' -o "' . gutentags#get_res_file('ctags_recursive.options') . '"' | |
133 endif | |
134 if !empty(g:gutentags_ctags_extra_args) | |
135 let l:cmd .= ' -O '.shellescape(join(g:gutentags_ctags_extra_args)) | |
136 endif | |
137 if !empty(g:gutentags_ctags_post_process_cmd) | |
138 let l:cmd .= ' -P '.shellescape(g:gutentags_ctags_post_process_cmd) | |
139 endif | |
140 let l:proj_options_file = a:proj_dir . '/' . | |
141 \g:gutentags_ctags_options_file | |
142 if filereadable(l:proj_options_file) | |
143 let l:proj_options_file = s:process_options_file( | |
144 \a:proj_dir, l:proj_options_file) | |
145 let l:cmd .= ' -o "' . l:proj_options_file . '"' | |
146 endif | |
147 if g:gutentags_ctags_exclude_wildignore | |
148 for ign in split(&wildignore, ',') | |
149 let l:cmd .= ' -x ' . shellescape(ign, 1) | |
150 endfor | |
151 endif | |
152 for exc in g:gutentags_ctags_exclude | |
153 let l:cmd .= ' -x ' . '"' . exc . '"' | |
154 endfor | |
155 if g:gutentags_pause_after_update | |
156 let l:cmd .= ' -c' | |
157 endif | |
158 if g:gutentags_trace | |
159 if has('win32') | |
160 let l:cmd .= ' -l "' . l:actual_tags_file . '.log"' | |
120 else | 161 else |
121 let l:file_list_cmd = gutentags#get_project_file_list_cmd(l:actual_proj_dir) | 162 let l:cmd .= ' ' . printf(s:unix_redir, '"' . l:actual_tags_file . '.log"') |
122 if !empty(l:file_list_cmd) | 163 endif |
123 if match(l:file_list_cmd, '///') > 0 | 164 else |
124 let l:suffopts = split(l:file_list_cmd, '///') | 165 if !has('win32') |
125 let l:suffoptstr = l:suffopts[1] | 166 let l:cmd .= ' ' . printf(s:unix_redir, '/dev/null') |
126 let l:file_list_cmd = l:suffopts[0] | 167 endif |
127 if l:suffoptstr == 'absolute' | 168 endif |
128 let l:cmd .= ' -A' | 169 let l:cmd .= gutentags#get_execute_cmd_suffix() |
129 endif | 170 |
130 endif | 171 call gutentags#trace("Running: " . l:cmd) |
131 let l:cmd .= ' -L ' . '"' . l:file_list_cmd. '"' | 172 call gutentags#trace("In: " . getcwd()) |
132 endif | 173 if !g:gutentags_fake |
133 endif | 174 " Run the background process. |
134 if empty(get(l:, 'file_list_cmd', '')) | 175 if !g:gutentags_trace |
135 " Pass the Gutentags recursive options file before the project | 176 silent execute l:cmd |
136 " options file, so that users can override --recursive. | |
137 " Omit --recursive if this project uses a file list command. | |
138 let l:cmd .= ' -o "' . gutentags#get_res_file('ctags_recursive.options') . '"' | |
139 endif | |
140 if !empty(g:gutentags_ctags_extra_args) | |
141 let l:cmd .= ' -O '.shellescape(join(g:gutentags_ctags_extra_args)) | |
142 endif | |
143 if !empty(g:gutentags_ctags_post_process_cmd) | |
144 let l:cmd .= ' -P '.shellescape(g:gutentags_ctags_post_process_cmd) | |
145 endif | |
146 let l:proj_options_file = a:proj_dir . '/' . | |
147 \g:gutentags_ctags_options_file | |
148 if filereadable(l:proj_options_file) | |
149 let l:proj_options_file = s:process_options_file( | |
150 \a:proj_dir, l:proj_options_file) | |
151 let l:cmd .= ' -o "' . l:proj_options_file . '"' | |
152 endif | |
153 if g:gutentags_ctags_exclude_wildignore | |
154 for ign in split(&wildignore, ',') | |
155 let l:cmd .= ' -x ' . shellescape(ign, 1) | |
156 endfor | |
157 endif | |
158 for exc in g:gutentags_ctags_exclude | |
159 let l:cmd .= ' -x ' . '"' . exc . '"' | |
160 endfor | |
161 if g:gutentags_pause_after_update | |
162 let l:cmd .= ' -c' | |
163 endif | |
164 if g:gutentags_trace | |
165 if has('win32') | |
166 let l:cmd .= ' -l "' . l:actual_tags_file . '.log"' | |
167 else | |
168 let l:cmd .= ' ' . printf(s:unix_redir, '"' . l:actual_tags_file . '.log"') | |
169 endif | |
170 else | 177 else |
171 if !has('win32') | 178 execute l:cmd |
172 let l:cmd .= ' ' . printf(s:unix_redir, '/dev/null') | 179 endif |
173 endif | 180 |
174 endif | 181 " Flag this tags file as being in progress |
175 let l:cmd .= gutentags#get_execute_cmd_suffix() | 182 let l:full_tags_file = fnamemodify(a:tags_file, ':p') |
176 | 183 call gutentags#add_progress('ctags', l:full_tags_file) |
177 call gutentags#trace("Running: " . l:cmd) | 184 else |
178 call gutentags#trace("In: " . getcwd()) | 185 call gutentags#trace("(fake... not actually running)") |
179 if !g:gutentags_fake | 186 endif |
180 " Run the background process. | 187 call gutentags#trace("") |
181 if !g:gutentags_trace | |
182 silent execute l:cmd | |
183 else | |
184 execute l:cmd | |
185 endif | |
186 | |
187 " Flag this tags file as being in progress | |
188 let l:full_tags_file = fnamemodify(a:tags_file, ':p') | |
189 call gutentags#add_progress('ctags', l:full_tags_file) | |
190 else | |
191 call gutentags#trace("(fake... not actually running)") | |
192 endif | |
193 call gutentags#trace("") | |
194 finally | |
195 " Restore the previous working directory. | |
196 call gutentags#chdir(fnameescape(l:prev_cwd)) | |
197 endtry | |
198 endfunction | 188 endfunction |
199 | 189 |
200 " }}} | 190 " }}} |
201 | 191 |
202 " Utilities {{{ | 192 " Utilities {{{ |