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 {{{