dotfiles

Configuration for the software I use.
git clone https://git.sr.ht/~jbauer/dotfiles
Log | Files | Refs | README | LICENSE

commit 389ce64dffe271cf0493cf613d0128055d55a0fc
parent 641aee7737dae469ade75a0f2c0577d182672782
Author: Jake Bauer <jbauer@paritybit.ca>
Date:   Tue,  7 Mar 2023 20:40:15 -0500

Add vim-gutentags

Diffstat:
M.config/nvim/init.vim | 5+++++
M.config/nvim/pack/bundle/start/vim-fastline/plugin/statusline.vim | 1+
A.config/nvim/pack/bundle/start/vim-gutentags/LICENSE | 23+++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags.vim | 749+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/cscope.vim | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/ctags.vim | 343+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/gtags_cscope.vim | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/pycscope.vim | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/doc/gutentags.txt | 748+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_gtags.sh | 48++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_pyscopedb.sh | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_scopedb.sh | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_tags.sh | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_gtags.cmd | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_scopedb.cmd | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_tags.cmd | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/plugin/gutentags.vim | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/nvim/pack/bundle/start/vim-gutentags/res/ctags_recursive.options | 2++
18 files changed, 3115 insertions(+), 0 deletions(-)

diff --git a/.config/nvim/init.vim b/.config/nvim/init.vim @@ -6,6 +6,11 @@ let mapleader = "," +" Plugin Settings +let g:buftabline_show = 1 +let g:gutentags_project_root = ['Makefile'] +let g:gutentags_add_default_project_roots = 1 + " Syntax Highlighting and Colourscheme syntax on colorscheme monochrome-light diff --git a/.config/nvim/pack/bundle/start/vim-fastline/plugin/statusline.vim b/.config/nvim/pack/bundle/start/vim-fastline/plugin/statusline.vim @@ -98,6 +98,7 @@ function! StatusLine() let statusline .= "%#Modi# %{CheckModified(&modified)} " let statusline .= "%#Base#" let statusline .= "%=" + let statusline .= "%{gutentags#statusline('[', ']')} " let statusline .= "%#FileType# %{CheckFileType(&filetype)} " let statusline .= "%#LineCol# %p%% Ln %l/%L : %c " return statusline diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/LICENSE b/.config/nvim/pack/bundle/start/vim-gutentags/LICENSE @@ -0,0 +1,23 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Ludovic Chabant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags.vim b/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags.vim @@ -0,0 +1,749 @@ +" gutentags.vim - Automatic ctags management for Vim + +" Utilities {{{ + +function! gutentags#chdir(path) + if has('nvim') + let chdir = haslocaldir() ? 'lcd' : haslocaldir(-1, 0) ? 'tcd' : 'cd' + else + let chdir = haslocaldir() ? ((haslocaldir() == 1) ? 'lcd' : 'tcd') : 'cd' + endif + execute chdir fnameescape(a:path) +endfunction + +" Throw an exception message. +function! gutentags#throw(message) + throw "gutentags: " . a:message +endfunction + +" Show an error message. +function! gutentags#error(message) + let v:errmsg = "gutentags: " . a:message + echoerr v:errmsg +endfunction + +" Show a warning message. +function! gutentags#warning(message) + echohl WarningMsg + echom "gutentags: " . a:message + echohl None +endfunction + +" Prints a message if debug tracing is enabled. +function! gutentags#trace(message, ...) + if g:gutentags_trace || (a:0 && a:1) + let l:message = "gutentags: " . a:message + echom l:message + endif +endfunction + +" Strips the ending slash in a path. +function! gutentags#stripslash(path) + return fnamemodify(a:path, ':s?[/\\]$??') +endfunction + +" Normalizes the slashes in a path. +function! gutentags#normalizepath(path) + if exists('+shellslash') && &shellslash + return substitute(a:path, '\v/', '\\', 'g') + elseif has('win32') + return substitute(a:path, '\v/', '\\', 'g') + else + return a:path + endif +endfunction + +" Shell-slashes the path (opposite of `normalizepath`). +function! gutentags#shellslash(path) + if exists('+shellslash') && !&shellslash + return substitute(a:path, '\v\\', '/', 'g') + else + return a:path + endif +endfunction + +" Gets a file path in the correct `plat` folder. +function! gutentags#get_plat_file(filename) abort + return g:gutentags_plat_dir . a:filename . g:gutentags_script_ext +endfunction + +" Gets a file path in the resource folder. +function! gutentags#get_res_file(filename) abort + return g:gutentags_res_dir . a:filename +endfunction + +" Generate a path for a given filename in the cache directory. +function! gutentags#get_cachefile(root_dir, filename) abort + if gutentags#is_path_rooted(a:filename) + return a:filename + endif + let l:tag_path = gutentags#stripslash(a:root_dir) . '/' . a:filename + if g:gutentags_cache_dir != "" + " Put the tag file in the cache dir instead of inside the + " project root. + let l:tag_path = g:gutentags_cache_dir . '/' . + \tr(l:tag_path, '\/: ', '---_') + let l:tag_path = substitute(l:tag_path, '/\-', '/', '') + let l:tag_path = substitute(l:tag_path, '[\-_]*$', '', '') + endif + let l:tag_path = gutentags#normalizepath(l:tag_path) + return l:tag_path +endfunction + +" Makes sure a given command starts with an executable that's in the PATH. +function! gutentags#validate_cmd(cmd) abort + if !empty(a:cmd) && executable(split(a:cmd)[0]) + return a:cmd + endif + return "" +endfunction + +" Makes an appropriate command line for use with `job_start` by converting +" a list of possibly quoted arguments into a single string on Windows, or +" into a list of unquoted arguments on Unix/Mac. +if has('win32') || has('win64') + function! gutentags#make_args(cmd) abort + if &shell == 'pwsh' || &shell == 'powershell' + return '& ' . join(a:cmd, ' ') + else + return join(a:cmd, ' ') + endif + endfunction +else + function! gutentags#make_args(cmd) abort + let l:outcmd = [] + for cmdarg in a:cmd + " Thanks Vimscript... you can use negative integers for strings + " in the slice notation, but not for indexing characters :( + let l:arglen = strlen(cmdarg) + if (cmdarg[0] == '"' && cmdarg[l:arglen - 1] == '"') || + \(cmdarg[0] == "'" && cmdarg[l:arglen - 1] == "'") + " This was quoted, so there are probably things to escape. + let l:escapedarg = cmdarg[1:-2] " substitute(cmdarg[1:-2], '\ ', '\\ ', 'g') + call add(l:outcmd, l:escapedarg) + else + call add(l:outcmd, cmdarg) + endif + endfor + return l:outcmd + endfunction +endif + +" Returns whether a path is rooted. +if has('win32') || has('win64') + function! gutentags#is_path_rooted(path) abort + return len(a:path) >= 2 && ( + \a:path[0] == '/' || a:path[0] == '\' || a:path[1] == ':') + endfunction +else + function! gutentags#is_path_rooted(path) abort + return !empty(a:path) && a:path[0] == '/' + endfunction +endif + +" }}} + +" 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 + +function! gutentags#get_project_file_list_cmd(path) abort + if type(g:gutentags_file_list_command) == type("") + return gutentags#validate_cmd(g:gutentags_file_list_command) + elseif type(g:gutentags_file_list_command) == type({}) + let l:markers = get(g:gutentags_file_list_command, 'markers', []) + if type(l:markers) == type({}) + for [marker, file_list_cmd] in items(l:markers) + if !empty(globpath(a:path, marker, 1)) + return gutentags#validate_cmd(file_list_cmd) + endif + endfor + endif + return get(g:gutentags_file_list_command, 'default', "") + endif + return "" +endfunction + +" Finds the first directory with a project marker by walking up from the given +" file path. +function! gutentags#get_project_root(path) abort + if g:gutentags_project_root_finder != '' + return call(g:gutentags_project_root_finder, [a:path]) + endif + return gutentags#default_get_project_root(a:path) +endfunction + +" Default implementation for finding project markers... useful when a custom +" finder (`g:gutentags_project_root_finder`) wants to fallback to the default +" behaviour. +function! gutentags#default_get_project_root(path) abort + let l:path = gutentags#stripslash(a:path) + let l:previous_path = "" + let l:markers = g:gutentags_project_root[:] + if g:gutentags_add_ctrlp_root_markers && exists('g:ctrlp_root_markers') + for crm in g:ctrlp_root_markers + if index(l:markers, crm) < 0 + call add(l:markers, crm) + endif + endfor + endif + while l:path != l:previous_path + for root in l:markers + if !empty(globpath(l:path, root, 1)) + let l:proj_dir = simplify(fnamemodify(l:path, ':p')) + let l:proj_dir = gutentags#stripslash(l:proj_dir) + if l:proj_dir == '' + call gutentags#trace("Found project marker '" . root . + \"' at the root of your file-system! " . + \" That's probably wrong, disabling " . + \"gutentags for this file...", + \1) + call gutentags#throw("Marker found at root, aborting.") + endif + for ign in g:gutentags_exclude_project_root + if l:proj_dir == ign + call gutentags#trace( + \"Ignoring project root '" . l:proj_dir . + \"' because it is in the list of ignored" . + \" projects.") + call gutentags#throw("Ignore project: " . l:proj_dir) + endif + endfor + return l:proj_dir + endif + endfor + let l:previous_path = l:path + let l:path = fnamemodify(l:path, ':h') + endwhile + 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 + +" Setup gutentags for the current buffer. +function! gutentags#setup_gutentags() abort + if exists('b:gutentags_files') && !g:gutentags_debug + " This buffer already has gutentags support. + return + endif + + " Don't setup gutentags for anything that's not a normal buffer + " (so don't do anything for help buffers and quickfix windows and + " other such things) + " Also don't do anything for the default `[No Name]` buffer you get + " after starting Vim. + if &buftype != '' || + \(bufname('%') == '' && !g:gutentags_generate_on_empty_buffer) + return + endif + + " Don't setup gutentags for things that don't need it, or that could + " cause problems. + if index(g:gutentags_exclude_filetypes, &filetype) >= 0 + return + endif + + " Let the user specify custom ways to disable Gutentags. + if g:gutentags_init_user_func != '' && + \!call(g:gutentags_init_user_func, [expand('%:p')]) + call gutentags#trace("Ignoring '" . bufname('%') . "' because of " . + \"custom user function.") + return + endif + + " Try and find what tags file we should manage. + call gutentags#trace("Scanning buffer '" . bufname('%') . "' for gutentags setup...") + try + let l:buf_dir = expand('%:p:h', 1) + if g:gutentags_resolve_symlinks + let l:buf_dir = fnamemodify(resolve(expand('%:p', 1)), ':p:h') + endif + if !exists('b:gutentags_root') + let b:gutentags_root = gutentags#get_project_root(l:buf_dir) + endif + if !len(b:gutentags_root) + call gutentags#trace("no valid project root.. no gutentags support.") + return + endif + if filereadable(b:gutentags_root . '/.notags') + call gutentags#trace("'.notags' file found... no gutentags support.") + 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]) + endfor + catch /^gutentags\:/ + call gutentags#trace("No gutentags support for this buffer.") + return + endtry + + " We know what tags file to manage! Now set things up. + call gutentags#trace("Setting gutentags for buffer '".bufname('%')."'") + + " Autocommands for updating the tags on save. + " We need to pass the buffer number to the callback function in the rare + " case that the current buffer is changed by another `BufWritePost` + " callback. This will let us get that buffer's variables without causing + " errors. + let l:bn = bufnr('%') + execute 'augroup gutentags_buffer_' . l:bn + execute ' autocmd!' + execute ' autocmd BufWritePost <buffer=' . l:bn . '> call s:write_triggered_update_tags(' . l:bn . ')' + execute 'augroup end' + + " Miscellaneous commands. + command! -buffer -bang GutentagsUpdate :call s:manual_update_tags(<bang>0) + + " Add these tags files to the known tags files. + for module in keys(b:gutentags_files) + let l:tagfile = b:gutentags_files[module] + let l:found = index(s:known_files, l:tagfile) + if l:found < 0 + call add(s:known_files, l:tagfile) + + " Generate this new file depending on settings and stuff. + if g:gutentags_enabled + if g:gutentags_generate_on_missing && !filereadable(l:tagfile) + call gutentags#trace("Generating missing tags file: " . l:tagfile) + call s:update_tags(l:bn, module, 1, 1) + elseif g:gutentags_generate_on_new + call gutentags#trace("Generating tags file: " . l:tagfile) + call s:update_tags(l:bn, module, 1, 1) + endif + endif + endif + endfor +endfunction + +" Set a variable on exit so that we don't complain when a job gets killed. +function! gutentags#on_vim_leave_pre() abort + let g:__gutentags_vim_is_leaving = 1 +endfunction + +function! gutentags#on_vim_leave() abort + if has('win32') && !has('nvim') + " Vim8 doesn't seem to be killing child processes soon enough for + " us to clean things up inside this plugin, so do it ourselves. + " TODO: test other platforms and other vims + for module in g:gutentags_modules + for upd_info in s:update_in_progress[module] + let l:job = upd_info[1] + call job_stop(l:job, "term") + let l:status = job_status(l:job) + if l:status == "run" + call job_stop(l:job, "kill") + endif + endfor + endfor + endif +endfunction + +" }}} + +" Job Management {{{ + +" List of queued-up jobs, and in-progress jobs, per module. +let s:update_queue = {} +let s:update_in_progress = {} +for module in g:gutentags_modules + let s:update_queue[module] = [] + let s:update_in_progress[module] = [] +endfor + +" Adds a started job to the list of ongoing updates. +" Must pass the tags file being created/updated, and the job data as +" returned by the gutentags#start_job function +function! gutentags#add_job(module, tags_file, data) abort + call add(s:update_in_progress[a:module], [a:tags_file, a:data]) +endfunction + +" Finds an ongoing job by tags file +function! gutentags#find_job_index_by_tags_file(module, tags_file) abort + let l:idx = -1 + for upd_info in s:update_in_progress[a:module] + let l:idx += 1 + if upd_info[0] == a:tags_file + return l:idx + endif + endfor + return -1 +endfunction + +" Finds an ongoing job by job data +function! gutentags#find_job_index_by_data(module, data) abort + let l:idx = -1 + for upd_info in s:update_in_progress[a:module] + let l:idx += 1 + if upd_info[1] == a:data + return l:idx + endif + endfor + return -1 +endfunction + +" Gets the tags file of a given job +function! gutentags#get_job_tags_file(module, job_idx) abort + return s:update_in_progress[a:module][a:job_idx][0] +endfunction + +" Gets the job data of the i-th job +function! gutentags#get_job_data(module, job_idx) abort + return s:update_in_progress[a:module][a:job_idx][1] +endfunction + +" Removes the i-th job from the ongoing jobs +function! gutentags#remove_job(module, job_idx) abort + let [l:tags_file, l:job_data] = s:update_in_progress[a:module][a:job_idx] + call remove(s:update_in_progress[a:module], a:job_idx) + + " Run the user callback for finished jobs. + silent doautocmd User GutentagsUpdated + + " See if we had any more updates queued up for this. + let l:qu_idx = -1 + for qu_info in s:update_queue[a:module] + let l:qu_idx += 1 + if qu_info[0] == l:tags_file + break + endif + endfor + if l:qu_idx >= 0 + let l:qu_info = s:update_queue[a:module][l:qu_idx] + call remove(s:update_queue[a:module], l:qu_idx) + + if bufexists(l:qu_info[1]) + call gutentags#trace("Finished ".a:module." job, ". + \"running queued update for '".l:tags_file."'.") + call s:update_tags(l:qu_info[1], a:module, l:qu_info[2], 2) + else + call gutentags#trace("Finished ".a:module." job, ". + \"but skipping queued update for '".l:tags_file."' ". + \"because originating buffer doesn't exist anymore.") + endif + else + call gutentags#trace("Finished ".a:module." job.") + endif + + return [l:tags_file, l:job_data] +endfunction + +" Removes the job from the ongoing jobs given its job data +function! gutentags#remove_job_by_data(module, data) abort + let l:idx = gutentags#find_job_index_by_data(a:module, a:data) + return gutentags#remove_job(a:module, l:idx) +endfunction + +" }}} + +" Tags File Management {{{ + +" (Re)Generate the tags file for the current buffer's file. +function! s:manual_update_tags(bang) abort + let l:restore_prev_trace = 0 + let l:prev_trace = g:gutentags_trace + if &verbose > 0 + let g:gutentags_trace = 1 + let l:restore_prev_trace = 1 + endif + + try + let l:bn = bufnr('%') + for module in g:gutentags_modules + call s:update_tags(l:bn, module, a:bang, 0) + endfor + silent doautocmd User GutentagsUpdating + finally + if l:restore_prev_trace + let g:gutentags_trace = l:prev_trace + endif + endtry +endfunction + +" (Re)Generate the tags file for a buffer that just go saved. +function! s:write_triggered_update_tags(bufno) abort + if g:gutentags_enabled && g:gutentags_generate_on_write + for module in g:gutentags_modules + call s:update_tags(a:bufno, module, 0, 2) + endfor + endif + silent doautocmd User GutentagsUpdating +endfunction + +" Update the tags file for the current buffer's file. +" write_mode: +" 0: update the tags file if it exists, generate it otherwise. +" 1: always generate (overwrite) the tags file. +" +" queue_mode: +" 0: if an update is already in progress, report it and abort. +" 1: if an update is already in progress, abort silently. +" 2: if an update is already in progress, queue another one. +function! s:update_tags(bufno, module, write_mode, queue_mode) abort + " Figure out where to save. + let l:buf_gutentags_files = getbufvar(a:bufno, 'gutentags_files') + let l:tags_file = l:buf_gutentags_files[a:module] + let l:proj_dir = getbufvar(a:bufno, 'gutentags_root') + + " Check that there's not already an update in progress. + let l:in_progress_idx = gutentags#find_job_index_by_tags_file( + \a:module, l:tags_file) + if l:in_progress_idx >= 0 + if a:queue_mode == 2 + let l:needs_queuing = 1 + for qu_info in s:update_queue[a:module] + if qu_info[0] == l:tags_file + let l:needs_queuing = 0 + break + endif + endfor + if l:needs_queuing + call add(s:update_queue[a:module], + \[l:tags_file, a:bufno, a:write_mode]) + endif + call gutentags#trace("Tag file '" . l:tags_file . + \"' is already being updated. Queuing it up...") + elseif a:queue_mode == 1 + call gutentags#trace("Tag file '" . l:tags_file . + \"' is already being updated. Skipping...") + elseif a:queue_mode == 0 + echom "gutentags: The tags file is already being updated, " . + \"please try again later." + else + call gutentags#throw("Unknown queue mode: " . a:queue_mode) + endif + + " Don't update the tags right now. + return + endif + + " Switch to the project root to make the command line smaller, and make + " it possible to get the relative path of the filename to parse if we're + " doing an incremental update. + let l:prev_cwd = getcwd() + call gutentags#chdir(l:proj_dir) + try + call call("gutentags#".a:module."#generate", + \[l:proj_dir, l:tags_file, + \ { + \ 'write_mode': a:write_mode, + \ }]) + catch /^gutentags\:/ + echom "Error while generating ".a:module." file:" + echom v:exception + finally + " Restore the current directory... + call gutentags#chdir(l:prev_cwd) + endtry +endfunction + +" }}} + +" Utility Functions {{{ + +function! gutentags#rescan(...) + if exists('b:gutentags_files') + unlet b:gutentags_files + endif + if a:0 && a:1 + let l:trace_backup = g:gutentags_trace + let l:gutentags_trace = 1 + endif + call gutentags#setup_gutentags() + if a:0 && a:1 + let g:gutentags_trace = l:trace_backup + endif +endfunction + +function! gutentags#toggletrace(...) + let g:gutentags_trace = !g:gutentags_trace + if a:0 > 0 + let g:gutentags_trace = a:1 + endif + if g:gutentags_trace + echom "gutentags: Tracing is enabled." + else + echom "gutentags: Tracing is disabled." + endif + echom "" +endfunction + +function! gutentags#fake(...) + let g:gutentags_fake = !g:gutentags_fake + if a:0 > 0 + let g:gutentags_fake = a:1 + endif + if g:gutentags_fake + echom "gutentags: Now faking gutentags." + else + echom "gutentags: Now running gutentags for real." + endif + echom "" +endfunction + +function! gutentags#default_stdout_cb(chan, msg) abort + call gutentags#trace('[job stdout]: '.string(a:msg)) +endfunction + +function! gutentags#default_stderr_cb(chan, msg) abort + call gutentags#trace('[job stderr]: '.string(a:msg)) +endfunction + +if has('nvim') + " Neovim job API. + function! s:nvim_job_exit_wrapper(real_cb, job, exit_code, event_type) abort + call call(a:real_cb, [a:job, a:exit_code]) + endfunction + + function! s:nvim_job_out_wrapper(real_cb, job, lines, event_type) abort + call call(a:real_cb, [a:job, a:lines]) + endfunction + + function! gutentags#build_default_job_options(module) abort + " Neovim kills jobs on exit, which is what we want. + let l:job_opts = { + \'on_exit': function( + \ '<SID>nvim_job_exit_wrapper', + \ ['gutentags#'.a:module.'#on_job_exit']), + \'on_stdout': function( + \ '<SID>nvim_job_out_wrapper', + \ ['gutentags#default_stdout_cb']), + \'on_stderr': function( + \ '<SID>nvim_job_out_wrapper', + \ ['gutentags#default_stderr_cb']) + \} + return l:job_opts + endfunction + + function! gutentags#start_job(cmd, opts) abort + return jobstart(a:cmd, a:opts) + endfunction +else + " Vim8 job API. + function! gutentags#build_default_job_options(module) abort + let l:job_opts = { + \'exit_cb': 'gutentags#'.a:module.'#on_job_exit', + \'out_cb': 'gutentags#default_stdout_cb', + \'err_cb': 'gutentags#default_stderr_cb', + \'stoponexit': 'term' + \} + return l:job_opts + endfunction + + function! gutentags#start_job(cmd, opts) abort + return job_start(a:cmd, a:opts) + endfunction +endif + +" Returns which modules are currently generating something for the +" current buffer. +function! gutentags#inprogress() + " Does this buffer have gutentags enabled? + if !exists('b:gutentags_files') + return [] + endif + + " Find any module that has a job in progress for any of this buffer's + " tags files. + let l:modules_in_progress = [] + for [module, tags_file] in items(b:gutentags_files) + let l:jobidx = gutentags#find_job_index_by_tags_file(module, tags_file) + if l:jobidx >= 0 + call add(l:modules_in_progress, module) + endif + endfor + return l:modules_in_progress +endfunction + +" }}} + +" Statusline Functions {{{ + +" Prints whether a tag file is being generated right now for the current +" buffer in the status line. +" +" Arguments can be passed: +" - args 1 and 2 are the prefix and suffix, respectively, of whatever output, +" if any, is going to be produced. +" (defaults to empty strings) +" - arg 3 is the text to be shown if tags are currently being generated. +" (defaults to the name(s) of the modules currently generating). + +function! gutentags#statusline(...) abort + let l:modules_in_progress = gutentags#inprogress() + if empty(l:modules_in_progress) + return '' + endif + + let l:prefix = '' + let l:suffix = '' + if a:0 > 0 + let l:prefix = a:1 + endif + if a:0 > 1 + let l:suffix = a:2 + endif + + if a:0 > 2 + let l:genmsg = a:3 + else + let l:genmsg = join(l:modules_in_progress, ',') + endif + + return l:prefix.l:genmsg.l:suffix +endfunction + +" Same as `gutentags#statusline`, but the only parameter is a `Funcref` or +" function name that will get passed the list of modules currently generating +" something. This formatter function should return the string to display in +" the status line. + +function! gutentags#statusline_cb(fmt_cb, ...) abort + let l:modules_in_progress = gutentags#inprogress() + + if (a:0 == 0 || !a:1) && empty(l:modules_in_progress) + return '' + endif + + return call(a:fmt_cb, [l:modules_in_progress]) +endfunction + +" }}} + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/cscope.vim b/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/cscope.vim @@ -0,0 +1,99 @@ +" Cscope module for Gutentags + +if !has('cscope') + throw "Can't enable the cscope module for Gutentags, this Vim has ". + \"no support for cscope files." +endif + +" Global Options {{{ + +if !exists('g:gutentags_cscope_executable') + let g:gutentags_cscope_executable = 'cscope' +endif + +if !exists('g:gutentags_scopefile') + let g:gutentags_scopefile = 'cscope.out' +endif + +if !exists('g:gutentags_auto_add_cscope') + let g:gutentags_auto_add_cscope = 1 +endif + +if !exists('g:gutentags_cscope_build_inverted_index') + let g:gutentags_cscope_build_inverted_index = 0 +endif + +" }}} + +" Gutentags Module Interface {{{ + +let s:runner_exe = gutentags#get_plat_file('update_scopedb') +let s:unix_redir = (&shellredir =~# '%s') ? &shellredir : &shellredir . ' %s' +let s:added_dbs = [] + +function! gutentags#cscope#init(project_root) abort + let l:dbfile_path = gutentags#get_cachefile( + \a:project_root, g:gutentags_scopefile) + let b:gutentags_files['cscope'] = l:dbfile_path + + if g:gutentags_auto_add_cscope && filereadable(l:dbfile_path) + if index(s:added_dbs, l:dbfile_path) < 0 + call add(s:added_dbs, l:dbfile_path) + silent! execute 'cs add ' . fnameescape(l:dbfile_path) + endif + endif +endfunction + +function! gutentags#cscope#generate(proj_dir, tags_file, gen_opts) abort + let l:cmd = [s:runner_exe] + let l:cmd += ['-e', g:gutentags_cscope_executable] + let l:cmd += ['-p', a:proj_dir] + let l:cmd += ['-f', a:tags_file] + let l:file_list_cmd = + \ gutentags#get_project_file_list_cmd(a:proj_dir) + if !empty(l:file_list_cmd) + let l:cmd += ['-L', '"' . l:file_list_cmd . '"'] + endif + if g:gutentags_cscope_build_inverted_index + let l:cmd += ['-I'] + endif + let l:cmd = gutentags#make_args(l:cmd) + + call gutentags#trace("Running: " . string(l:cmd)) + call gutentags#trace("In: " . getcwd()) + if !g:gutentags_fake + let l:job_opts = gutentags#build_default_job_options('cscope') + let l:job = gutentags#start_job(l:cmd, l:job_opts) + call gutentags#add_job('cscope', a:tags_file, l:job) + else + call gutentags#trace("(fake... not actually running)") + endif +endfunction + +function! gutentags#cscope#on_job_exit(job, exit_val) abort + let l:job_idx = gutentags#find_job_index_by_data('cscope', a:job) + let l:dbfile_path = gutentags#get_job_tags_file('cscope', l:job_idx) + call gutentags#remove_job('cscope', l:job_idx) + + if a:exit_val == 0 + if index(s:added_dbs, l:dbfile_path) < 0 + call add(s:added_dbs, l:dbfile_path) + silent! execute 'cs add ' . fnameescape(l:dbfile_path) + else + silent! execute 'cs reset' + endif + elseif !g:__gutentags_vim_is_leaving + call gutentags#warning( + \"cscope job failed, returned: ". + \string(a:exit_val)) + endif + if has('win32') && g:__gutentags_vim_is_leaving + " The process got interrupted because Vim is quitting. + " Remove the db file on Windows because there's no `trap` + " statement in the update script. + try | call delete(l:dbfile_path) | endtry + endif +endfunction + +" }}} + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/ctags.vim b/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/ctags.vim @@ -0,0 +1,343 @@ +" Ctags module for Gutentags + +" Global Options {{{ + +let g:gutentags_ctags_executable = get(g:, 'gutentags_ctags_executable', 'ctags') +let g:gutentags_ctags_tagfile = get(g:, 'gutentags_ctags_tagfile', 'tags') +let g:gutentags_ctags_auto_set_tags = get(g:, 'gutentags_ctags_auto_set_tags', 1) + +let g:gutentags_ctags_options_file = get(g:, 'gutentags_ctags_options_file', '.gutctags') +let g:gutentags_ctags_check_tagfile = get(g:, 'gutentags_ctags_check_tagfile', 0) +let g:gutentags_ctags_extra_args = get(g:, 'gutentags_ctags_extra_args', []) +let g:gutentags_ctags_post_process_cmd = get(g:, 'gutentags_ctags_post_process_cmd', '') + +let g:gutentags_ctags_exclude = get(g:, 'gutentags_ctags_exclude', []) +let g:gutentags_ctags_exclude_wildignore = get(g:, 'gutentags_ctags_exclude_wildignore', 1) + +" Backwards compatibility. +function! s:_handleOldOptions() abort + let l:renamed_options = { + \'gutentags_exclude': 'gutentags_ctags_exclude', + \'gutentags_tagfile': 'gutentags_ctags_tagfile', + \'gutentags_auto_set_tags': 'gutentags_ctags_auto_set_tags' + \} + for key in keys(l:renamed_options) + if exists('g:'.key) + let newname = l:renamed_options[key] + echom "gutentags: Option 'g:'".key." has been renamed to ". + \"'g:'".newname." Please update your vimrc." + let g:[newname] = g:[key] + endif + endfor +endfunction +call s:_handleOldOptions() +" }}} + +" Gutentags Module Interface {{{ + +let s:did_check_exe = 0 +let s:runner_exe = '"' . gutentags#get_plat_file('update_tags') . '"' +let s:unix_redir = (&shellredir =~# '%s') ? &shellredir : &shellredir . ' %s' +let s:wildignores_options_path = '' +let s:last_wildignores = '' + +function! gutentags#ctags#init(project_root) abort + " Figure out the path to the tags file. + " Check the old name for this option, too, before falling back to the + " globally defined name. + let l:tagfile = getbufvar("", 'gutentags_ctags_tagfile', + \getbufvar("", 'gutentags_tagfile', + \g:gutentags_ctags_tagfile)) + let b:gutentags_files['ctags'] = gutentags#get_cachefile( + \a:project_root, l:tagfile) + + " Set the tags file for Vim to use. + if g:gutentags_ctags_auto_set_tags + if has('win32') || has('win64') + execute 'setlocal tags^=' . fnameescape(b:gutentags_files['ctags']) + else + " spaces must be literally escaped in tags path + let l:literal_space_escaped = substitute(fnameescape(b:gutentags_files['ctags']), '\ ', '\\\\ ', 'g') + execute 'setlocal tags^=' . l:literal_space_escaped + endif + endif + + " Check if the ctags executable exists. + if s:did_check_exe == 0 + if g:gutentags_enabled && executable(expand(g:gutentags_ctags_executable, 1)) == 0 + let g:gutentags_enabled = 0 + echoerr "Executable '".g:gutentags_ctags_executable."' can't be found. " + \."Gutentags will be disabled. You can re-enable it by " + \."setting g:gutentags_enabled back to 1." + endif + let s:did_check_exe = 1 + endif +endfunction + +function! gutentags#ctags#generate(proj_dir, tags_file, gen_opts) abort + let l:write_mode = a:gen_opts['write_mode'] + + let l:tags_file_exists = filereadable(a:tags_file) + + " If the tags file exists, we may want to do a sanity check to prevent + " weird errors that are hard to troubleshoot. + if l:tags_file_exists && g:gutentags_ctags_check_tagfile + let l:first_lines = readfile(a:tags_file, '', 1) + if len(l:first_lines) == 0 || stridx(l:first_lines[0], '!_TAG_') != 0 + call gutentags#throw( + \"File ".a:tags_file." doesn't appear to be ". + \"a ctags file. Please delete it and run ". + \":GutentagsUpdate!.") + return + endif + endif + + " Get a tags file path relative to the current directory, which + " happens to be the project root in this case. + " Since the given tags file path is absolute, and since Vim won't + " change the path if it is not inside the current directory, we + " know that the tags file is "local" (i.e. inside the project) + " if the path was shortened (an absolute path will always be + " longer than a true relative path). + let l:tags_file_relative = fnamemodify(a:tags_file, ':.') + let l:tags_file_is_local = len(l:tags_file_relative) < len(a:tags_file) + let l:use_tag_relative_opt = 0 + + if empty(g:gutentags_cache_dir) && l:tags_file_is_local + " If we don't use the cache directory, we can pass relative paths + " around. + " + " Note that if we don't do this and pass a full path for the project + " root, some `ctags` implementations like Exhuberant Ctags can get + " confused if the paths have spaces -- but not if you're *in* the root + " directory, for some reason... (which will be the case, we're running + " the jobs from the project root). + let l:actual_proj_dir = '.' + let l:actual_tags_file = l:tags_file_relative + + let l:tags_file_dir = fnamemodify(l:actual_tags_file, ':h') + if l:tags_file_dir != '.' + " Ok so now the tags file is stored in a subdirectory of the + " project root, instead of at the root. This happens if, say, + " someone set `gutentags_ctags_tagfile` to `.git/tags`, which + " seems to be fairly popular. + " + " By default, `ctags` writes paths relative to the current + " directory (the project root) but in this case we need it to + " be relative to the tags file (e.g. adding `../` in front of + " everything if the tags file is `.git/tags`). + " + " Thankfully most `ctags` implementations support an option + " just for this. + let l:use_tag_relative_opt = 1 + endif + else + " else: the tags file goes in a cache directory, so we need to specify + " all the paths absolutely for `ctags` to do its job correctly. + let l:actual_proj_dir = a:proj_dir + let l:actual_tags_file = a:tags_file + endif + + " Build the command line. + let l:cmd = [s:runner_exe] + let l:cmd += ['-e', '"' . s:get_ctags_executable(a:proj_dir) . '"'] + let l:cmd += ['-t', '"' . l:actual_tags_file . '"'] + let l:cmd += ['-p', '"' . l:actual_proj_dir . '"'] + if l:write_mode == 0 && l:tags_file_exists + let l:cur_file_path = expand('%:p') + if empty(g:gutentags_cache_dir) && l:tags_file_is_local + let l:cur_file_path = fnamemodify(l:cur_file_path, ':.') + endif + let l:cmd += ['-s', '"' . l:cur_file_path . '"'] + else + let l:file_list_cmd = gutentags#get_project_file_list_cmd(l:actual_proj_dir) + if !empty(l:file_list_cmd) + if match(l:file_list_cmd, '///') > 0 + let l:suffopts = split(l:file_list_cmd, '///') + let l:suffoptstr = l:suffopts[1] + let l:file_list_cmd = l:suffopts[0] + if l:suffoptstr == 'absolute' + let l:cmd += ['-A'] + endif + endif + let l:cmd += ['-L', '"' . l:file_list_cmd. '"'] + endif + endif + if empty(get(l:, 'file_list_cmd', '')) + " Pass the Gutentags recursive options file before the project + " options file, so that users can override --recursive. + " Omit --recursive if this project uses a file list command. + let l:cmd += ['-o', '"' . gutentags#get_res_file('ctags_recursive.options') . '"'] + endif + if l:use_tag_relative_opt + let l:cmd += ['-O', shellescape("--tag-relative=yes")] + endif + for extra_arg in g:gutentags_ctags_extra_args + let l:cmd += ['-O', shellescape(extra_arg)] + endfor + if !empty(g:gutentags_ctags_post_process_cmd) + let l:cmd += ['-P', shellescape(g:gutentags_ctags_post_process_cmd)] + endif + let l:proj_options_file = a:proj_dir . '/' . + \g:gutentags_ctags_options_file + if filereadable(l:proj_options_file) + let l:proj_options_file = s:process_options_file( + \a:proj_dir, l:proj_options_file) + let l:cmd += ['-o', '"' . l:proj_options_file . '"'] + endif + if g:gutentags_ctags_exclude_wildignore + call s:generate_wildignore_options() + if !empty(s:wildignores_options_path) + let l:cmd += ['-x', shellescape('@'.s:wildignores_options_path, 1)] + endif + endif + for exc in g:gutentags_ctags_exclude + let l:cmd += ['-x', '"' . exc . '"'] + endfor + if g:gutentags_pause_after_update + let l:cmd += ['-c'] + endif + if g:gutentags_trace + let l:cmd += ['-l', '"' . l:actual_tags_file . '.log"'] + endif + let l:cmd = gutentags#make_args(l:cmd) + + call gutentags#trace("Running: " . string(l:cmd)) + call gutentags#trace("In: " . getcwd()) + if !g:gutentags_fake + let l:job_opts = gutentags#build_default_job_options('ctags') + let l:job = gutentags#start_job(l:cmd, l:job_opts) + call gutentags#add_job('ctags', a:tags_file, l:job) + else + call gutentags#trace("(fake... not actually running)") + endif +endfunction + +function! gutentags#ctags#on_job_exit(job, exit_val) abort + let [l:tags_file, l:job_data] = gutentags#remove_job_by_data('ctags', a:job) + + if a:exit_val != 0 && !g:__gutentags_vim_is_leaving + call gutentags#warning("ctags job failed, returned: ". + \string(a:exit_val)) + endif + if has('win32') && g:__gutentags_vim_is_leaving + " The process got interrupted because Vim is quitting. + " Remove the tags and lock files on Windows because there's no `trap` + " statement in update script. + try | call delete(l:tags_file) | endtry + try | call delete(l:tags_file.'.temp') | endtry + try | call delete(l:tags_file.'.lock') | endtry + endif +endfunction + +" }}} + +" Utilities {{{ + +" Get final ctags executable depending whether a filetype one is defined +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, '') + let l:proj_info = gutentags#get_project_info(a:proj_dir) + let l:type = get(l:proj_info, 'type', l:ftype) + let exepath = exists('g:gutentags_ctags_executable_{l:type}') + \ ? g:gutentags_ctags_executable_{l:type} : g:gutentags_ctags_executable + return expand(exepath, 1) +endfunction + +function! s:generate_wildignore_options() abort + if s:last_wildignores == &wildignore + " The 'wildignore' setting didn't change since last time we did this, + " but check if file still exist (could have been deleted if temp file) + if filereadable(s:wildignores_options_path) + call gutentags#trace("Wildignore options file is up to date.") + return + endif + call gutentags#trace("Wildignore options file is not readable.") + endif + + if s:wildignores_options_path == '' + if empty(g:gutentags_cache_dir) + let s:wildignores_options_path = tempname() + else + let s:wildignores_options_path = + \gutentags#stripslash(g:gutentags_cache_dir). + \'/_wildignore.options' + endif + endif + + call gutentags#trace("Generating wildignore options: ".s:wildignores_options_path) + let l:opt_lines = [] + for ign in split(&wildignore, ',') + call add(l:opt_lines, ign) + endfor + call writefile(l:opt_lines, s:wildignores_options_path) + let s:last_wildignores = &wildignore +endfunction + +function! s:process_options_file(proj_dir, path) abort + if empty(g:gutentags_cache_dir) + " If we're not using a cache directory to store tag files, we can + " use the options file straight away. + return a:path + endif + + " See if we need to process the options file. + let l:do_process = 0 + let l:proj_dir = gutentags#stripslash(a:proj_dir) + let l:out_path = gutentags#get_cachefile(l:proj_dir, 'options') + if !filereadable(l:out_path) + call gutentags#trace("Processing options file '".a:path."' because ". + \"it hasn't been processed yet.") + let l:do_process = 1 + elseif getftime(a:path) > getftime(l:out_path) + call gutentags#trace("Processing options file '".a:path."' because ". + \"it has changed.") + let l:do_process = 1 + endif + if l:do_process == 0 + " Nothing's changed, return the existing processed version of the + " options file. + return l:out_path + endif + + " We have to process the options file. Right now this only means capturing + " all the 'exclude' rules, and rewrite them to make them absolute. + " + " This is because since `ctags` is run with absolute paths (because we + " want the tag file to be in a cache directory), it will do its path + " matching with absolute paths too, so the exclude rules need to be + " absolute. + let l:lines = readfile(a:path) + let l:outlines = [] + for line in l:lines + let l:exarg_idx = matchend(line, '\v^\-\-exclude=') + if l:exarg_idx < 0 + call add(l:outlines, line) + continue + endif + + " Don't convert things that don't look like paths. + let l:exarg = strpart(line, l:exarg_idx + 1) + let l:do_convert = 1 + if l:exarg[0] == '@' " Manifest file path + let l:do_convert = 0 + endif + if stridx(l:exarg, '/') < 0 && stridx(l:exarg, '\\') < 0 " Filename + let l:do_convert = 0 + endif + if l:do_convert == 0 + call add(l:outlines, line) + continue + endif + + let l:fullp = l:proj_dir . gutentags#normalizepath('/'.l:exarg) + let l:ol = '--exclude='.l:fullp + call add(l:outlines, l:ol) + endfor + + call writefile(l:outlines, l:out_path) + return l:out_path +endfunction + +" }}} diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/gtags_cscope.vim b/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/gtags_cscope.vim @@ -0,0 +1,136 @@ +" gtags_cscope module for Gutentags + +if !has('cscope') + throw "Can't enable the gtags-cscope module for Gutentags, " + \"this Vim has no support for cscope files." +endif + +" Global Options {{{ + +if !exists('g:gutentags_gtags_executable') + let g:gutentags_gtags_executable = 'gtags' +endif + +if !exists('g:gutentags_gtags_dbpath') + let g:gutentags_gtags_dbpath = '' +endif + +if !exists('g:gutentags_gtags_options_file') + let g:gutentags_gtags_options_file = '.gutgtags' +endif + +if !exists('g:gutentags_gtags_cscope_executable') + let g:gutentags_gtags_cscope_executable = 'gtags-cscope' +endif + +if !exists('g:gutentags_auto_add_gtags_cscope') + let g:gutentags_auto_add_gtags_cscope = 1 +endif + +" }}} + +" Gutentags Module Interface {{{ + +let s:runner_exe = gutentags#get_plat_file('update_gtags') +let s:added_db_files = {} + +function! s:add_db(db_file) abort + if filereadable(a:db_file) + call gutentags#trace( + \"Adding cscope DB file: " . a:db_file) + set nocscopeverbose + execute 'cs add ' . fnameescape(a:db_file) + set cscopeverbose + let s:added_db_files[a:db_file] = 1 + else + call gutentags#trace( + \"Not adding cscope DB file because it doesn't " . + \"exist yet: " . a:db_file) + endif +endfunction + +function! gutentags#gtags_cscope#init(project_root) abort + let l:db_path = gutentags#get_cachefile( + \a:project_root, g:gutentags_gtags_dbpath) + let l:db_path = gutentags#stripslash(l:db_path) + let l:db_file = l:db_path . '/GTAGS' + let l:db_file = gutentags#normalizepath(l:db_file) + + if !isdirectory(l:db_path) + call mkdir(l:db_path, 'p') + endif + + let b:gutentags_files['gtags_cscope'] = l:db_file + + execute 'set cscopeprg=' . fnameescape(g:gutentags_gtags_cscope_executable) + + " The combination of gtags-cscope, vim's cscope and global files is + " a bit flaky. Environment variables are safer than vim passing + " paths around and interpreting input correctly. + let $GTAGSDBPATH = l:db_path + let $GTAGSROOT = a:project_root + + if g:gutentags_auto_add_gtags_cscope && + \!has_key(s:added_db_files, l:db_file) + let s:added_db_files[l:db_file] = 0 + call s:add_db(l:db_file) + endif +endfunction + +function! gutentags#gtags_cscope#generate(proj_dir, tags_file, gen_opts) abort + let l:cmd = [s:runner_exe] + let l:cmd += ['-e', '"' . g:gutentags_gtags_executable . '"'] + + let l:file_list_cmd = gutentags#get_project_file_list_cmd(a:proj_dir) + if !empty(l:file_list_cmd) + let l:cmd += ['-L', '"' . l:file_list_cmd . '"'] + endif + + let l:proj_options_file = a:proj_dir . '/' . g:gutentags_gtags_options_file + if filereadable(l:proj_options_file) + let l:proj_options = readfile(l:proj_options_file) + let l:cmd += l:proj_options + endif + + " gtags doesn't honour GTAGSDBPATH and GTAGSROOT, so PWD and dbpath + " have to be set + let l:db_path = fnamemodify(a:tags_file, ':p:h') + let l:cmd += ['--incremental', '"'.l:db_path.'"'] + + let l:cmd = gutentags#make_args(l:cmd) + + call gutentags#trace("Running: " . string(l:cmd)) + call gutentags#trace("In: " . getcwd()) + if !g:gutentags_fake + let l:job_opts = gutentags#build_default_job_options('gtags_cscope') + let l:job = gutentags#start_job(l:cmd, l:job_opts) + call gutentags#add_job('gtags_cscope', a:tags_file, l:job) + else + call gutentags#trace("(fake... not actually running)") + endif + call gutentags#trace("") +endfunction + +function! gutentags#gtags_cscope#on_job_exit(job, exit_val) abort + let l:job_idx = gutentags#find_job_index_by_data('gtags_cscope', a:job) + let l:dbfile_path = gutentags#get_job_tags_file('gtags_cscope', l:job_idx) + call gutentags#remove_job('gtags_cscope', l:job_idx) + + if g:gutentags_auto_add_gtags_cscope + call s:add_db(l:dbfile_path) + endif + + if a:exit_val != 0 && !g:__gutentags_vim_is_leaving + call gutentags#warning( + \"gtags-cscope job failed, returned: ". + \string(a:exit_val)) + endif + if has('win32') && g:__gutentags_vim_is_leaving + " The process got interrupted because Vim is quitting. + " Remove the db file on Windows because there's no `trap` + " statement in the update script. + try | call delete(l:dbfile_path) | endtry + endif +endfunction + +" }}} diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/pycscope.vim b/.config/nvim/pack/bundle/start/vim-gutentags/autoload/gutentags/pycscope.vim @@ -0,0 +1,86 @@ +" Pycscope module for Gutentags + +if !has('cscope') + throw "Can't enable the pycscope module for Gutentags, this Vim has ". + \"no support for cscope files." +endif + +" Global Options {{{ + +if !exists('g:gutentags_pycscope_executable') + let g:gutentags_pycscope_executable = 'pycscope' +endif + +if !exists('g:gutentags_pyscopefile') + let g:gutentags_pyscopefile = 'pycscope.out' +endif + +if !exists('g:gutentags_auto_add_pycscope') + let g:gutentags_auto_add_pycscope = 1 +endif + +" }}} + +" Gutentags Module Interface {{{ + +let s:runner_exe = gutentags#get_plat_file('update_pyscopedb') +let s:unix_redir = (&shellredir =~# '%s') ? &shellredir : &shellredir . ' %s' +let s:added_dbs = [] + +function! gutentags#pycscope#init(project_root) abort + let l:dbfile_path = gutentags#get_cachefile( + \a:project_root, g:gutentags_pyscopefile) + let b:gutentags_files['pycscope'] = l:dbfile_path + + if g:gutentags_auto_add_pycscope && filereadable(l:dbfile_path) + if index(s:added_dbs, l:dbfile_path) < 0 + call add(s:added_dbs, l:dbfile_path) + silent! execute 'cs add ' . fnameescape(l:dbfile_path) + endif + endif +endfunction + +function! gutentags#pycscope#generate(proj_dir, tags_file, gen_opts) abort + let l:cmd = [s:runner_exe] + let l:cmd += ['-e', g:gutentags_pycscope_executable] + let l:cmd += ['-p', a:proj_dir] + let l:cmd += ['-f', a:tags_file] + let l:file_list_cmd = + \ gutentags#get_project_file_list_cmd(a:proj_dir) + if !empty(l:file_list_cmd) + let l:cmd += ['-L', '"' . l:file_list_cmd . '"'] + endif + let l:cmd = gutentags#make_args(l:cmd) + + call gutentags#trace("Running: " . string(l:cmd)) + call gutentags#trace("In: " . getcwd()) + if !g:gutentags_fake + let l:job_opts = gutentags#build_default_job_options('pycscope') + let l:job = gutentags#start_job(l:cmd, l:job_opts) + call gutentags#add_job('pycscope', a:tags_file, l:job) + else + call gutentags#trace("(fake... not actually running)") + endif +endfunction + +function! gutentags#pycscope#on_job_exit(job, exit_val) abort + let l:job_idx = gutentags#find_job_index_by_data('pycscope', a:job) + let l:dbfile_path = gutentags#get_job_tags_file('pycscope', l:job_idx) + call gutentags#remove_job('pycscope', l:job_idx) + + if a:exit_val == 0 + if index(s:added_dbs, l:dbfile_path) < 0 + call add(s:added_dbs, l:dbfile_path) + silent! execute 'cs add ' . fnameescape(l:dbfile_path) + else + silent! execute 'cs reset' + endif + else + call gutentags#warning( + \"gutentags: pycscope job failed, returned: ". + \string(a:exit_val)) + endif +endfunction + +" }}} + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/doc/gutentags.txt b/.config/nvim/pack/bundle/start/vim-gutentags/doc/gutentags.txt @@ -0,0 +1,748 @@ +*gutentags.txt* Automatic ctags management for VIM + ___ ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\__\ /\ \ + /:/ _/_ \:\ \ /:/ / /:/ _/_ \:\ \ + /:/ /\ \ \:\ \ /:/__/ /:/ /\__\ \:\ \ + /:/ /::\ \ ___ \:\ \ /::\ \ /:/ /:/ _/_ _____\:\ \ + /:/__\/\:\__\ /\ \ \:\__\ /:/\:\ \ /:/_/:/ /\__\ /::::::::\__\ + \:\ \ /:/ / \:\ \ /:/ / \/__\:\ \ \:\/:/ /:/ / \:\~~\~~\/__/ + \:\ /:/ / \:\ /:/ / \:\__\ \::/_/:/ / \:\ \ + \:\/:/ / \:\/:/ / \/__/ \:\/:/ / \:\ \ + \::/ / \::/ / \::/ / \:\__\ + \/__/ \/__/ \/__/ \/__/ + ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\__\ + /:/ / /::\ \ /:/ _/_ /:/ _/_ + /:/__/ /:/\:\ \ /:/ /\ \ /:/ /\ \ + /::\ \ /:/ /::\ \ /:/ /::\ \ /:/ /::\ \ + /:/\:\ \ /:/_/:/\:\__\ /:/__\/\:\__\ /:/_/:/\:\__\ + \/__\:\ \ \:\/:/ \/__/ \:\ \ /:/ / \:\/:/ /:/ / + \:\__\ \::/__/ \:\ /:/ / \::/ /:/ / + \/__/ \:\ \ \:\/:/ / \/_/:/ / + \:\__\ \::/ / /:/ / + \/__/ \/__/ \/__/ + + + GUTENTAGS REFERENCE MANUAL + by Ludovic Chabant + + *gutentags* + +1. Introduction |gutentags-intro| +2. Commands |gutentags-commands| +3. Status Line |gutentags-status-line| +4. Global Settings |gutentags-settings| +5. Project Settings |gutentags-project-settings| + +============================================================================= +1. Introduction *gutentags-intro* + +Gutentags is a plugin that takes care of the much needed management of tags +files in Vim. It will (re)generate tag files as you work while staying +completely out of your way. It will even do its best to keep those tag files +out of your way too. It has no dependencies and just works. + +In order to generate tag files, Gutentags will have to figure out what's in +your project. To do this, it will locate well-known project root markers like +SCM folders (.git, .hg, etc.), any custom tags you define (with +|gutentags_project_root|), and even things you may have defined already with +other plugins, like CtrlP. + +If the current file you're editing is found to be in such a project, Gutentags +will make sure the tag file for that project is up to date. Then, as you work +in files in that project, it will partially re-generate the tag file. Every +time you save, it will silently, in the background, update the tags for that +file. + +Usually, `ctags` can only append tags to an existing tag file, so Gutentags +removes the tags for the current file first, to make sure the tag file is +always consistent with the source code. + +Also, Gutentags is clever enough to not stumble upon itself by triggering +multiple ctags processes if you save files too fast, or if your project is +really big. + + +1.1 Requirements + *gutentags-ctags-requirements* + +If you're using the `ctags` modules (which is the default and only working one +at this point, really), you will need a `tags` generator that supports the +following arguments: + +* `-f` (to specify the output file) +* `--append` (to append to an existing file while keeping it sorted) +* `--exclude` (to exclude file patterns) +* `--options` (to specify an options file) + +This means you probably want Exuberant Ctags or Universal Ctags. The basic +old BSD Ctags WON'T WORK. Other language-specific versions may or may not +work. Check with their help or man page. + + +1.2 Similar Plugins + *gutentags-similar-plugins* + +There are some similar Vim plugins out there ("vim-tags", "vim-autotag", +"vim-automatic-ctags", etc.). They all fail on one or more of the requirements +I set for myself with Gutentags: + +* No other dependency than running Vim: no Python, Ruby, or whatever. +* Cross-platform: should work on at least Mac and Windows. +* Incremental tags generation: don't re-generate the whole project all the + time. This may be fine for small projects, but it doesn't scale. +* External process management: if the ctags process is taking a long time, + don't run another one because I saved the file again. +* Keep the tag file consistent: don't just append the current file's tags to + the tag file, otherwise you will still "see" tags for deleted or renamed + classes and functions. +* Automatically create the tag file: you open something from a freshly forked + project, it should start indexing it automatically, just like in Sublime Text + or Visual Studio or any other IDE. + + +============================================================================= +2. Commands *gutentags-commands* + + *gutentags-project-commands* +The following commands are only available in buffers that have been found to +belong to a project that should be managed by Gutentags. See +|gutentags_project_root| for how Gutentags figures out the project a file +belongs to. When no project is found (i.e. the file is not under any of the +known project markers), Gutentags is disabled for that buffer, and the +following commands and remarks don't apply. + +If you want to force-disable Gutentags for a given project even though it does +match one of the items in |gutentags_project_root|, create a file named +"`.notags`" at the root of the project. + +The tag file that Gutentags creates and manages will be named after +|gutentags_ctags_tagfile|, relative to the project's root directory. When +Gutentags finds a valid project root, it will prepend the tag file's path to +'tags', unless |gutentags_ctags_auto_set_tags| is set to 0. This is to make +sure Vim will use that file first. + +If a file managed by Gutentags is opened and no tag file already exists, +Gutentags will start generating it right away in the background, unless +|gutentags_generate_on_missing| is set to 0. If you have a large project, you +may want to know when Gutentags is generating tags: see +|gutentags-status-line| to display an indicator in your status line. + +When a file managed by Gutentags is saved, the tag file will be incrementally +updated, i.e. references to the recently saved file are removed, and that file +is re-parsed for tags, with the result being merged into the tag file. This +makes the tag file 100% consistent with the latest changes. This doesn't +happen however if |gutentags_generate_on_write| is set to 0, in which case you +have to run |GutentagsUpdate| manually. + + + *:GutentagsUpdate* +:GutentagsUpdate + Forces an update of the current tag file with the + current buffer. If tags are already being generated, + you will be notified and the command will abort. + +:GutentagsUpdate! + Like |GutentagsUpdate|, but updates the current tags + file with the whole project instead of just the + current buffer. + + +Some debugging/troubleshooting commands are also available if the +|gutentags_define_advanced_commands| global setting is set to 1. + + *:GutentagsToggleEnabled* +:GutentagsToggleEnabled + Disables and re-enables Gutentags. + When Gutentags is disabled, it won't update your tag + file when you save a buffer. It will however still + look for project markers as you open new buffers so + that they can start working again when you re-enable + Gutentags. + + {only available when + |gutentags_define_advanced_commands| is set} + + *GutentagsToggleTrace* +:GutentagsToggleTrace + If you want to keep an eye on what Gutentags is doing, + you can enable tracing. This will show messages every + time Gutentags does something. It can get annoying + quickly, since it will require you to press a key to + dismiss those messages, but it can be useful to + troubleshoot a problem. + In addition to messages in Vim, it will also make + Gutentags redirect the output of the tag generation + script to a `.log` file in the project root. + + {only available when + |gutentags_define_advanced_commands| is set} + + +Gutentags also has some user auto-commands (see |User| and |:doautocmd|): + + *GutentagsUpdating* +GutentagsUpdating + This auto-command is triggered when a background + update job has started. + + *GutentagsUpdated* +GutentagsUpdated + This auto-command is triggered when a background + update job has finished. + + +============================================================================= +3. Status Line *gutentags-status-line* + +Tag file generation can take a while if you're working on a project big +enough. In that case, you may want to know when `ctags` is running, so you +have a heads up if some of the tags aren't recognized yet. + + *gutentags#statusline()* +You can display an indicator of tag generation progress in your |status-line| +with the following function: > + :set statusline+=%{gutentags#statusline()} + +The function will, by default, print a list of modules in the status line. So +if the `ctags` module (see |g:gutentags_modules|) is currently generating +a tags file, you will see "ctags" printed in the status line. If nothing is +happening, nothing will be printed in the status line. + +You can pass some parameters to customize this: + +1. A prefix string (defaults to `""`). +2. A suffix string (defaults to `""`). +3. The text to print (defaults to the names of modules currently generating + something). + +So using `gutentags#statusline('[', ']')` would print `"[ctags]"` instead of +`"ctags"`. + +Because Gutentags runs the tag generation in the background, the statusline +indicator might stay there even after the background process has ended. It +would only go away when Vim decides to refresh the statusline. You can force +refresh it in a callback on |GutentagsUpdating| and |GutentagsUpdated|. + +For instance, with the `lightline` plugin: + + augroup MyGutentagsStatusLineRefresher + autocmd! + autocmd User GutentagsUpdating call lightline#update() + autocmd User GutentagsUpdated call lightline#update() + augroup END + + *gutentags#statusline_cb* +As an alternative to the previous function, `gutentags#statusline_cb` takes +a single parameter which should be a |Funcref| or a function name. This +function should take a list of active module names, and return a string. This +lets you completely control what the status line will print. + +For instance: + function! s:get_gutentags_status(mods) abort + let l:msg = '' + if index(a:mods, 'ctags') >= 0 + let l:msg .= '♨' + endif + if index(a:mods, 'cscope') >= 0 + let l:msg .= '♺' + endif + return l:msg + endfunction + + :set statusline+=%{gutentags#statusline_cb( + \function('<SID>get_gutentags_status'))} + +By default, the callback function doesn't get called if no tags generation is +currently happening. You can pass `1` as a second argument so that the +callback function is always called. + + +============================================================================= +4. Global Settings *gutentags-settings* + +The following settings can be defined in your |vimrc| to change the default +behaviour of Gutentags. + + *gutentags_enabled* +g:gutentags_enabled + Defines whether Gutentags should be enabled. When + disabled, Gutentags will still scan for project root + markers when opening buffers. This is so that when you + re-enable Gutentags, you won't have some buffers + mysteriously working while others (those open last) + don't. + Defaults to `1`. + + *gutentags_trace* +g:gutentags_trace + When true, Gutentags will spit out debugging + information as Vim messages (which you can later read + with |:messages|). It also runs its background scripts + with extra parameters to log activity to a `tags.log` + file that you can also inspect for more information. + + Note: you can run `:verbose GutentagsUpdate` to + temporarily set |g:gutentags_trace| to `1` for that + update only. + + Defaults to `0`. + + *gutentags_dont_load* +g:gutentags_dont_load + Prevents Gutentags from loading at all on Vim startup. + + The difference between this and |gutentags_enabled| is + that |gutentags_enabled| can be turned on and off in + the same Vim session -- Gutentags as a plugin stays + loaded and will keep track of what happened while it + was disabled. However, |gutentags_dont_load| only + works on Vim startup and will prevent Gutentags from + loading at all, as if it wasn't there. + + *gutentags_modules* +g:gutentags_modules + A list of modules to load with Gutentags. Each module + is responsible for generating a specific type of tags + file. + Valid values are: + + - `ctags`: generates a `tags` file using + a `ctags`-compatible program like Exhuberant Ctags + or Universal Ctags. + + - `cscope`: generates a code database file using + `cscope`. + + - `pycscope`: generates a code database file using + `pycscope`. + + - `gtags_cscope`: same as `cscope` but uses GNU's + `gtags` executable and database. + + Defaults to `[ctags]`. + + *gutentags_project_root* +g:gutentags_project_root + When a buffer is loaded, Gutentags will figure out if + it's part of a project that should have tags managed + automatically. To do this, it looks for "root markers" + in the current file's directory and its parent + directories. If it finds any of those markers, + Gutentags will be enabled for the project, and a tags + file named after |gutentags_ctags_tagfile| will be + created at the project root. + Defaults to `[]` (an empty |List|). + A list of default markers will be appended to the + user-defined ones unless + |gutentags_add_default_project_roots| is set to 0. + + *gutentags_add_default_project_roots* +g:gutentags_add_default_project_roots + Defines whether Gutentags should always define some + default project roots (see |gutentags_project_root|). + This can be useful to prevent unnecessary disk access + when Gutentags searches for a project root. + The default markers are: + `['.git', '.hg', '.svn', '.bzr', '_darcs', '_darcs', '_FOSSIL_', '.fslckout']` + + *gutentags_add_ctrlp_root_markers* +g:gutentags_add_ctrlp_root_markers + If Gutentags finds `g:ctrlp_root_markers` (used by the + CtrlP plugin), it will append those root markers to + the existing ones (see |g:gutentags_project_root|). + Set this to 0 to stop it from happening. + Defaults to 1. + + *gutentags_exclude_filetypes* +g:gutentags_exclude_filetypes + A |List| of file types (see |'filetype'|) that Gutentags + should ignore. When a buffer is opened, if its + 'filetype' is found in this list, Gutentags features + won't be available for this buffer. + Defaults to an empty list (`[]`). + + *gutentags_exclude_project_root* +g:gutentags_exclude_project_root + A list of project roots to generally ignore. If a file + is opened inside one of those projects, Gutentags + won't be activated. This is similar to placing + a `.notags` file in the root of those projects, but + can be useful when you don't want to, or can't, place + such a file there. + Defaults to `['/usr/local', '/opt/homebrew', '/home/linuxbrew/.linuxbrew']`, + which are the folders where Homebrew is known to + create a Git repository by default. + + *gutentags_project_root_finder* +g:gutentags_project_root_finder + When a buffer is loaded, Gutentags uses a default + (internal) implementation to find that file's + project's root directory, using settings like + |g:gutentags_project_root|. When you specify + |g:gutentags_project_root_finder|, you can tell + Gutentags to use a custom implementation, such as + `vim-projectroot`. The value of this setting must be + the name of a function that takes a single string + argument (the path to the current buffer's file) and + returns a string value (the project's root directory). + Defaults to `''`. + Note: when set, the called implementation will + possibly ignore |g:gutentags_project_root|. + Note: an implementation can fallback to the default + behaviour by calling + `gutentags#default_get_project_root`. + + *gutentags_generate_on_missing* +g:gutentags_generate_on_missing + If set to 1, Gutentags will start generating an initial + tag file if a file is open in a project where no tags + file is found. See |gutentags_project_root| for how + Gutentags locates the project. + When set to 0, Gutentags will only generate the first + time the file is saved (if + |gutentags_generate_on_write| is set to 1), or when + |GutentagsUpdate| or |GutentagsGenerate| is run. + Defaults to 1. + + *gutentags_generate_on_new* +g:gutentags_generate_on_new + If set to 1, Gutentags will start generating the tag + file when a new project is open. A new project is + considered open when a buffer is created for a file + whose corresponding tag file has not been "seen" yet + in the current Vim session -- which pretty much means + when you open the first file in a given source control + repository. + When set to 0, Gutentags won't do anything special. + See also |gutentags_generate_on_missing| and + |gutentags_generate_on_write|. + Defaults to 1. + + *gutentags_generate_on_write* +g:gutentags_generate_on_write + If set to 1, Gutentags will update the current + project's tag file when a file inside that project is + saved. See |gutentags_project_root| for how Gutentags + locates the project. + When set to 0, Gutentags won't do anything on save. + This means that the project's tag file won't reflect + the latest changes, and you will have to run + |GutentagsUpdate| manually. + Defaults to 1. + + *gutentags_generate_on_empty_buffer* +g:gutentags_generate_on_empty_buffer + If set to 1, Gutentags will start generating the tag + file even if there's no buffer currently open, as long + as the current working directory (as returned by + |:cd|) is inside a known project. + This is useful if you want Gutentags to generate the + tag file right after opening Vim. + Defaults to 0. + + *gutentags_background_update* +g:gutentags_background_update + Specifies whether the process that updates the tags + file should be run in the background or in the + foreground. If run in the foreground, Vim will block + until the process is complete. + Defaults to 1. + + *gutentags_cache_dir* +g:gutentags_cache_dir + Specifies a directory in which to create all the tags + files, instead of writing them at the root of each + project. This is handy to keep tags files from + polluting many directories all across your computer. + + *gutentags_resolve_symlinks* +g:gutentags_resolve_symlinks + When set to 1, Gutentags will resolve any symlinks in + the current buffer's path in order to find the project + it belongs to. This is what you want if you're editing + a symlink located outside of the project, and it + points to a file inside the project. However, this is + maybe not what you want if the symlink itself is + part of the project. + Defaults to 0. + + *gutentags_init_user_func* +g:gutentags_init_user_func + When set to a non-empty string, it is expected to be + the name of a function that will be called when a file + is opened in a project. The function gets passed the + path of the file and if it returns 0, Gutentags won't + be enabled for that file. + + You can use this to manually set buffer-local + settings: + + * `b:gutentags_ctags_tagfile` (see |gutentags_ctags_tagfile|). + + This setting was previously called + `gutentags_enabled_user_func`. The old setting is + still used as a fallback. + + Defaults to "". + + *gutentags_define_advanced_commands* +g:gutentags_define_advanced_commands + 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. + + *gutentags_file_list_command* +g:gutentags_file_list_command + Specifies command(s) to use to list files for which + tags should be generated, instead of recursively + examining all files within the project root. When + invoked, file list commands will execute in the + project root directory. + + This setting is useful in projects using source + control to restrict tag generation to only files + tracked in the repository. + + This variable may be set in one of two ways. If + set as a |String|, the specified command will be used to + list files for all projects. For example: > + + let g:gutentags_file_list_command = 'find . -type f' +< + If set as a |Dictionary|, this variable should be set + as a mapping of project root markers to the desired + file list command for that root marker. (See + |gutentags_project_root| for how Gutentags uses root + markers to locate the project.) For example: > + + let g:gutentags_file_list_command = { + \ 'markers': { + \ '.git': 'git ls-files', + \ '.hg': 'hg files', + \ }, + \ } +< + Note: If a custom ctags executable is specified, it + must support the '-L' command line option in order to + read the list of files to be examined. + + +The following settings are valid for the `ctags` module. + + *gutentags_ctags_executable* +g:gutentags_ctags_executable + Specifies the ctags executable to launch. + Defaults to `ctags`. + + *gutentags_ctags_executable_{filetype}* +g:gutentags_ctags_executable_{type} + Specifies the ctags executable to launch for a project + of type {type}. See |gutentags_project_info| for more + information. + IMPORTANT: please see |gutentags-ctags-requirements|. + Example: > + let g:gutentags_ctags_executable_ruby = 'ripper-tags' +< + + *gutentags_ctags_tagfile* +g:gutentags_ctags_tagfile + Specifies the name of the tag file to create. This + will be appended to the project's root. See + |gutentags_project_root| for how Gutentags locates the + project. + Defaults to `tags`. + + *gutentags_ctags_exclude* +g:gutentags_ctags_exclude + A list of file patterns to pass to the + |gutentags_ctags_executable| so that they will be + excluded from parsing for the tags generation. + See also |gutentags_ctags_exclude_wildignore|. + Defaults to `[]` (an empty |List|). + + *gutentags_ctags_exclude_wildignore* +g:gutentags_ctags_exclude_wildignore + When 1, Gutentags will automatically pass your + 'wildignore' file patterns to the + |gutentags_ctags_executable| so that they are ignored. + Set also |gutentags_ctags_exclude| to pass custom + patterns. + Defaults to 1. + + *gutentags_ctags_auto_set_tags* +g:gutentags_ctags_auto_set_tags + If set to 1, Gutentags will automatically prepend + 'tags' with the exact path to the tag file for the + current project. See |gutentags_project_root| for how + Gutentags locates the project. + When set to 0, Gutentags doesn't change 'tags', and + this means that whatever tag file it generates may + not be picked up by Vim. See |tagfiles()| to know what + tag files Vim knows about. + Defaults to 1. + + *gutentags_ctags_extra_args* +g:gutentags_ctags_extra_args + A list of arguments to pass to `ctags`. + Defaults to `[]`. + + *gutentags_ctags_post_process_cmd* +g:gutentags_ctags_post_process_cmd + If defined, the tags generation script will run the + command with an argument that points to a temporary + copy of the tags file. If the post-process step is + modifying the tags file, it needs to do so in-place. + This is useful for cleaning up a tags file that may + contain tags with non-ASCII names that somehow upsets + Vim. + Defaults to `""` (an empty |String|). + + +The following settings are valid for the `cscope` module. + + *gutentags_cscope_executable* +g:gutentags_cscope_executable + Specifies the name or path of the `cscope` executable + to use to generate the code database. + Defaults to `"cscope"`. + + *gutentags_scopefile* +g:gutentags_scopefile + Specifies the name of the scope file to create. This + will be appended to the project's root. See + |gutentags_project_root| for how Gutentags locates the + project. + Defaults to `"cscope.out"`. + + *gutentags_auto_add_cscope* +g:gutentags_auto_add_cscope + If set to 1, Gutentags will automatically add the + generated code database to Vim by running `:cs add` + (see |:cscope|). + Defaults to 1. + + *gutentags_cscope_build_inverted_index* +g:gutentags_cscope_build_inverted_index + If set to 1, Gutentags will make `cscope` build an + inverted index. + Defaults to 0. + + +The following settings are valid for the `pycscope` module. + + *gutentags_pycscope_executable* +g:gutentags_pycscope_executable + Specifies the name or path of the `pycscope` executable + to use to generate the code database. + Defaults to `"pycscope"`. + + *gutentags_auto_add_pycscope* +g:gutentags_auto_add_pycscope + If set to 1, Gutentags will automatically add the + generated code database to Vim by running `:cs add` + (see |:pycscope|). + Defaults to 1. + + +The following settings are valid for the `gtags_cscope` module. + + *gutentags_gtags_executable* +g:gutentags_gtags_executable + Specifies the name or path of the `gtags` executable + to use to generate the code database. + Defaults to `"gtags"`. + + *gutentags_gtags_cscope_executable* +g:gutentags_gtags_cscope_executable + Specifies the name or path of the `gtags-cscope` + executable to use to generate the code database. + Defaults to `"gtags-cscope"`. + + *gutentags_gtags_dbpath* +g:gutentags_gtags_dbpath + Path from the cache directory (|gutentags_cache_dir| + or project root) to the folder containing the + definition database file (usually called `GTAGS`). + Defaults to `""`. + + *gutentags_gtags_options_file* +g:gutentags_gtags_options_file + The name of a file that will be looked for in + a project root directory. The file is expected to + contain `gtags` options (one per line). + Defaults to `".gutgtags"`. + + *gutentags_auto_add_gtags_cscope* +g:gutentags_auto_add_gtags_cscope + If set to 1, Gutentags will automatically add the + generated code database to Vim by running `:cs add` + (see |:cscope|). + Defaults to 1. + + +People using `cscope`, `pycscope` or `gtags_cscope` across multiple projects in the same +Vim instance might be interested in the `gutentags_plus` plugin, which handles +switching databases automatically before performing a query. +See https://github.com/skywind3000/gutentags_plus. + +============================================================================= +5. Project Settings *gutentags-project-settings* + +Gutentags can be customized to some extent on a per-project basis with the +following files present in the project root directory: + + *gutentags-.gutctags* +`.gutctags`: if this file exists, Ctags will be told to load additional +command-line parameters by reading it line by line (see the Ctags +documentation for more information). + +Note that for complex reasons, Gutentags can't run `ctags` from the project +root if you're using |gutentags_cache_dir|, so if the `.gutctags` file exists, +it will be pre-processed in order to make all `--exclude=` clauses into +absolute paths (by prepending the project root). The resulting file will be +saved into the cache directory, and passed to `ctags` via the `--options=` +parameter. If you're _not_ using |gutentags_cache_dir|, the `.gutctags` file +is _not_ pre-processed, and is passed as-is via the `--options=` parameter. + + *gutentags-.notags* +`.notags`: if this file exists, Gutentags will be disabled completely for that +project. + + + vim:tw=78:et:ft=help:norl: diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_gtags.sh b/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_gtags.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -e + +PROG_NAME=$0 +GTAGS_EXE=gtags +FILE_LIST_CMD= + +ShowUsage() { + echo "Usage:" + echo " $PROG_NAME <options>" + echo "" + echo " -e [exe=gtags]: The gtags executable to run." + echo " -L [cmd=]: The file list command to run." + echo "" +} + +while [[ $# -ne 0 ]]; do + case "$1" in + -h) + ShowUsage + exit 0 + ;; + -e) + GTAGS_EXE=$2 + shift 2 + ;; + -L) + FILE_LIST_CMD=$2 + shift 2 + ;; + *) + GTAGS_ARGS="$GTAGS_ARGS $1" + shift + ;; + esac +done + +if [ -n "$FILE_LIST_CMD" ]; then + CMD="$FILE_LIST_CMD | $GTAGS_EXE -f- $GTAGS_ARGS" +else + CMD="$GTAGS_EXE $GTAGS_ARGS" +fi + +echo "Running gtags:" +echo "$CMD" +eval "$CMD" +echo "Done." diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_pyscopedb.sh b/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_pyscopedb.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +set -e + +PROG_NAME=$0 +PYCSCOPE_EXE=pycscope +PYCSCOPE_ARGS= +DB_FILE=pycscope.out +# Note that we keep the same name +PROJECT_ROOT= +FILE_LIST_CMD= + +ShowUsage() { + echo "Usage:" + echo " $PROG_NAME <options>" + echo "" + echo " -e [exe=pycscope]: The pycscope executable to run" + echo " -f [file=pycscope.out]: The path to the ctags file to update" + echo " -p [dir=]: The path to the project root" + echo " -L [cmd=]: The file list command to run" + echo "" +} + + +while getopts "h?e:f:p:L:" opt; do + case $opt in + h|\?) + ShowUsage + exit 0 + ;; + e) + PYCSCOPE_EXE=$OPTARG + ;; + f) + DB_FILE=$OPTARG + ;; + p) + PROJECT_ROOT=$OPTARG + ;; + L) + FILE_LIST_CMD=$OPTARG + ;; + esac +done + +shift $((OPTIND - 1)) + +if [ "$1" != "" ]; then + echo "Invalid Argument: $1" + exit 1 +fi + +echo "Locking pycscope DB file..." +echo $$ > "$DB_FILE.lock" + +# Remove lock and temp file if script is stopped unexpectedly. +trap 'rm -f "$DB_FILE.lock" "$DB_FILE.files" "$DB_FILE.temp"' INT QUIT TERM EXIT + +PREVIOUS_DIR=$(pwd) +if [ -d "$PROJECT_ROOT" ]; then + cd "$PROJECT_ROOT" +fi + +if [ -n "${FILE_LIST_CMD}" ]; then + if [ "${PROJECT_ROOT}" = "." ]; then + eval "$FILE_LIST_CMD" > "${DB_FILE}.files" + else + # If using a tags cache directory, use absolute paths + eval "$FILE_LIST_CMD" | while read -r l; do + echo "${PROJECT_ROOT%/}/${l}" + done > "${DB_FILE}.files" + fi +else + find . -type f > "${DB_FILE}.files" +fi +PYCSCOPE_ARGS="${PYCSCOPE_ARGS} -i ${DB_FILE}.files" + +echo "Running pycscope" +echo "$PYCSCOPE_EXE -f \"$DB_FILE.temp\" "$PYCSCOPE_ARGS +"$PYCSCOPE_EXE" -f "$DB_FILE.temp" $PYCSCOPE_ARGS + +if [ -d "$PROJECT_ROOT" ]; then + cd "$PREVIOUS_DIR" +fi + +echo "Replacing pycscope DB file" +echo "mv -f \"$DB_FILE.temp\" \"$DB_FILE\"" +mv -f "$DB_FILE.temp" "$DB_FILE" + +echo "Unlocking pycscope DB file..." +rm -f "$DB_FILE.lock" + +echo "Done." diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_scopedb.sh b/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_scopedb.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +set -e + +PROG_NAME=$0 +CSCOPE_EXE=cscope +CSCOPE_ARGS= +DB_FILE=cscope.out +PROJECT_ROOT= +FILE_LIST_CMD= +BUILD_INVERTED_INDEX=0 + +ShowUsage() { + echo "Usage:" + echo " $PROG_NAME <options>" + echo "" + echo " -e [exe=cscope]: The cscope executable to run" + echo " -f [file=cscope.out]: The path to the ctags file to update" + echo " -p [dir=]: The path to the project root" + echo " -L [cmd=]: The file list command to run" + echo " -I: Builds an inverted index" + echo "" +} + + +while getopts "h?e:f:p:L:I" opt; do + case $opt in + h|\?) + ShowUsage + exit 0 + ;; + e) + CSCOPE_EXE=$OPTARG + ;; + f) + DB_FILE=$OPTARG + ;; + p) + PROJECT_ROOT=$OPTARG + ;; + L) + FILE_LIST_CMD=$OPTARG + ;; + I) + BUILD_INVERTED_INDEX=1 + ;; + esac +done + +shift $((OPTIND - 1)) + +if [ "$1" != "" ]; then + echo "Invalid Argument: $1" + exit 1 +fi + +echo "Locking cscope DB file..." +echo $$ > "$DB_FILE.lock" + +# Remove lock and temp file if script is stopped unexpectedly. +CleanUp() { + rm -f "$DB_FILE.lock" "$DB_FILE.files" "$DB_FILE.temp" + if [ "$BUILD_INVERTED_INDEX" -eq 1 ]; then + rm -f "$DB_FILE.temp.in" "$DB_FILE.temp.po" + fi +} + +trap CleanUp INT QUIT TERM EXIT + +PREVIOUS_DIR=$(pwd) +if [ -d "$PROJECT_ROOT" ]; then + cd "$PROJECT_ROOT" +fi + +if [ -n "${FILE_LIST_CMD}" ]; then + if [ "${PROJECT_ROOT}" = "." ]; then + eval "$FILE_LIST_CMD" | while read -r l; do + echo "\"${l}\"" + done > "${DB_FILE}.files" + else + # If using a tags cache directory, use absolute paths + eval "$FILE_LIST_CMD" | while read -r l; do + echo "\"${PROJECT_ROOT%/}/${l}\"" + done > "${DB_FILE}.files" + fi +else + find . -type f ! -name ${DB_FILE} | while read -r l; do + echo "\"${l}\"" + done > "${DB_FILE}.files" +fi + +if [ ! -s "${DB_FILE}.files" ]; then + echo "There is no files to generate cscope DB" + exit +fi + +CSCOPE_ARGS="${CSCOPE_ARGS} -i ${DB_FILE}.files" + +if [ "$BUILD_INVERTED_INDEX" -eq 1 ]; then + CSCOPE_ARGS="$CSCOPE_ARGS -q" +fi + +echo "Running cscope" +echo "$CSCOPE_EXE $CSCOPE_ARGS -b -k -f \"$DB_FILE.temp\"" +"$CSCOPE_EXE" $CSCOPE_ARGS -v -b -k -f "$DB_FILE.temp" + +if [ -d "$PROJECT_ROOT" ]; then + cd "$PREVIOUS_DIR" +fi + +echo "Replacing cscope DB file" +if [ "$BUILD_INVERTED_INDEX" -eq 1 ]; then + echo "mv -f \"$DB_FILE.temp.in\" \"$DB_FILE.in\"" + mv -f "$DB_FILE.temp.in" "$DB_FILE.in" + echo "mv -f \"$DB_FILE.temp.po\" \"$DB_FILE.po\"" + mv -f "$DB_FILE.temp.po" "$DB_FILE.po" +fi +echo "mv -f \"$DB_FILE.temp\" \"$DB_FILE\"" +mv -f "$DB_FILE.temp" "$DB_FILE" + +echo "Unlocking cscope DB file..." +rm -f "$DB_FILE.lock" + +echo "Done." diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_tags.sh b/.config/nvim/pack/bundle/start/vim-gutentags/plat/unix/update_tags.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +set -e + +PROG_NAME=$0 +CTAGS_EXE=ctags +CTAGS_ARGS= +CTAGS_OPT_FILE= +TAGS_FILE=tags +PROJECT_ROOT= +LOG_FILE= +FILE_LIST_CMD= +FILE_LIST_CMD_IS_ABSOLUTE=0 +UPDATED_SOURCE= +POST_PROCESS_CMD= +PAUSE_BEFORE_EXIT=0 + + +ShowUsage() { + echo "Usage:" + echo " $PROG_NAME <options>" + echo "" + echo " -e [exe=ctags]: The ctags executable to run" + echo " -t [file=tags]: The path to the ctags file to update" + echo " -p [dir=]: The path to the project root" + echo " -l [file=]: The path to a log file" + echo " -L [cmd=]: The file list command to run" + echo " -A: Specifies that the file list command returns " + echo " absolute paths" + echo " -s [file=]: The path to the source file that needs updating" + echo " -x [pattern=]: A pattern of files to exclude" + echo " -o [options=]: An options file to read additional options from" + echo " -O [params=]: Parameters to pass to ctags" + echo " -P [cmd=]: Post process command to run on the tags file" + echo " -c: Ask for confirmation before exiting" + echo "" +} + +while getopts "h?e:x:t:p:l:L:s:o:O:P:cA" opt; do + case $opt in + h|\?) + ShowUsage + exit 0 + ;; + e) + CTAGS_EXE="$OPTARG" + ;; + x) + CTAGS_ARGS="$CTAGS_ARGS --exclude=$OPTARG" + ;; + t) + TAGS_FILE="$OPTARG" + ;; + p) + PROJECT_ROOT="$OPTARG" + ;; + l) + LOG_FILE="$OPTARG" + ;; + L) + FILE_LIST_CMD="$OPTARG" + ;; + A) + FILE_LIST_CMD_IS_ABSOLUTE=1 + ;; + s) + UPDATED_SOURCE="$OPTARG" + ;; + c) + PAUSE_BEFORE_EXIT=1 + ;; + o) + CTAGS_OPT_FILE="--options=$OPTARG" + ;; + O) + CTAGS_ARGS="$CTAGS_ARGS $OPTARG" + ;; + P) + POST_PROCESS_CMD="$OPTARG" + ;; + esac +done + +shift $((OPTIND - 1)) + +if [ "$1" != "" ]; then + echo "Invalid Argument: $1" + exit 1 +fi + +echo "Locking tags file..." +echo $$ > "$TAGS_FILE.lock" + +# Remove lock and temp file if script is stopped unexpectedly. +trap 'errorcode=$?; rm -f "$TAGS_FILE.lock" "$TAGS_FILE.files" "$TAGS_FILE.temp"; exit $errorcode' INT QUIT TERM EXIT + +INDEX_WHOLE_PROJECT=1 +if [ -f "$TAGS_FILE" ]; then + if [ "$UPDATED_SOURCE" != "" ]; then + echo "Removing references to: $UPDATED_SOURCE" + tab=" " + cmd="grep --text -Ev '^[^$tab]+$tab$UPDATED_SOURCE$tab' '$TAGS_FILE' > '$TAGS_FILE.temp'" + echo "$cmd" + eval "$cmd" || true + INDEX_WHOLE_PROJECT=0 + fi +fi + +if [ $INDEX_WHOLE_PROJECT -eq 1 ]; then + if [ -n "${FILE_LIST_CMD}" ]; then + if [ "${PROJECT_ROOT}" = "." ] || [ $FILE_LIST_CMD_IS_ABSOLUTE -eq 1 ]; then + echo "Running file list command" + echo "eval $FILE_LIST_CMD > \"${TAGS_FILE}.files\"" + eval "$FILE_LIST_CMD" > "${TAGS_FILE}.files" + else + # If using a tags cache directory, use absolute paths + echo "Running file list command, patching for absolute paths" + echo "eval $FILE_LIST_CMD" + eval "$FILE_LIST_CMD" | while read -r l; do + echo "${PROJECT_ROOT%/}/${l}" + done > "${TAGS_FILE}.files" + fi + CTAGS_ARGS="${CTAGS_ARGS} -L" + CTAGS_ARG_LAST="${TAGS_FILE}.files" + else + CTAGS_ARG_LAST="${PROJECT_ROOT}" + fi + + echo "Running ctags on whole project" + if [ "$CTAGS_OPT_FILE" != "" ]; then + echo "$CTAGS_EXE -f \"$TAGS_FILE.temp\" \"$CTAGS_OPT_FILE\" $CTAGS_ARGS \"$CTAGS_ARG_LAST\"" + "$CTAGS_EXE" -f "$TAGS_FILE.temp" "$CTAGS_OPT_FILE" $CTAGS_ARGS "$CTAGS_ARG_LAST" + else + echo "$CTAGS_EXE -f \"$TAGS_FILE.temp\" $CTAGS_ARGS \"$CTAGS_ARG_LAST\"" + "$CTAGS_EXE" -f "$TAGS_FILE.temp" $CTAGS_ARGS "$CTAGS_ARG_LAST" + fi +else + echo "Running ctags on \"$UPDATED_SOURCE\"" + if [ "$CTAGS_OPT_FILE" != "" ]; then + echo "$CTAGS_EXE -f \"$TAGS_FILE.temp\" \"$CTAGS_OPT_FILE\" $CTAGS_ARGS --append \"$UPDATED_SOURCE\"" + "$CTAGS_EXE" -f "$TAGS_FILE.temp" "$CTAGS_OPT_FILE" $CTAGS_ARGS --append "$UPDATED_SOURCE" + else + echo "$CTAGS_EXE -f \"$TAGS_FILE.temp\" $CTAGS_ARGS --append \"$UPDATED_SOURCE\"" + "$CTAGS_EXE" -f "$TAGS_FILE.temp" $CTAGS_ARGS --append "$UPDATED_SOURCE" + fi +fi + +if [ "$POST_PROCESS_CMD" != "" ]; then + echo "Running post process" + echo "$POST_PROCESS_CMD \"$TAGS_FILE.temp\"" + $POST_PROCESS_CMD "$TAGS_FILE.temp" +fi + +echo "Replacing tags file" +echo "mv -f \"$TAGS_FILE.temp\" \"$TAGS_FILE\"" +if [ -f "$TAGS_FILE.temp" ]; then + mv -f "$TAGS_FILE.temp" "$TAGS_FILE" +fi + +echo "Unlocking tags file..." +rm -f "$TAGS_FILE.lock" + +echo "Done." + +if [ $PAUSE_BEFORE_EXIT -eq 1 ]; then + printf "Press ENTER to exit..." + read -r +fi diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_gtags.cmd b/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_gtags.cmd @@ -0,0 +1,56 @@ +@echo off + +setlocal EnableExtensions EnableDelayedExpansion + +rem ========================================== +rem PARSE ARGUMENTS +rem ========================================== +set "GTAGS_EXE=gtags" +set "GTAGS_ARGS=" +set "FILE_LIST_CMD=" + +if [%1]==[] goto :Usage + +:ParseArgs +if [%1]==[] goto :DoneParseArgs +if [%1]==[-e] ( + set GTAGS_EXE=%~2 + shift /1 + shift /1 + goto :ParseArgs +) +if [%1]==[-L] ( + set FILE_LIST_CMD=%~2 + shift /1 + shift /1 + goto :ParseArgs +) +set "GTAGS_ARGS=%GTAGS_ARGS% %1" +shift /1 +goto :ParseArgs + +:DoneParseArgs +rem ========================================== +rem GENERATE GTAGS +rem ========================================== +set "GTAGS_CMD=%GTAGS_EXE% %GTAGS_ARGS%" +if /i not "%FILE_LIST_CMD%"=="" ( + set "GTAGS_CMD=%FILE_LIST_CMD% | %GTAGS_EXE% -f- %GTAGS_ARGS%" +) +echo Running gtags: +echo "%GTAGS_CMD%" +call %GTAGS_CMD% +echo Done. +goto :EOF +rem ========================================== +rem USAGE +rem ========================================== + +:Usage +echo Usage: +echo %~n0 ^<options^> +echo. +echo -e [exe=gtags]: The gtags executable to run. +echo -L [cmd=]: The file list command to run +echo. + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_scopedb.cmd b/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_scopedb.cmd @@ -0,0 +1,120 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +rem ========================================== +rem PARSE ARGUMENTS +rem ========================================== + +set CSCOPE_EXE=cscope +set CSCOPE_ARGS= +set DB_FILE=cscope.out +set FILE_LIST_CMD= +set LOG_FILE= +set BUILD_INVERTED_INDEX=0 + +:ParseArgs +if [%1]==[] goto :DoneParseArgs +if [%1]==[-e] ( + set CSCOPE_EXE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-f] ( + set DB_FILE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-p] ( + set PROJ_ROOT=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-L] ( + set FILE_LIST_CMD=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-l] ( + set LOG_FILE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-I] ( + set BUILD_INVERTED_INDEX=1 + goto :LoopParseArgs +) +echo Invalid Argument: %1 +goto :Usage + +:LoopParseArgs +shift +goto :ParseArgs + +:DoneParseArgs + + +rem ========================================== +rem GENERATE DATABASE +rem ========================================== + +if [%LOG_FILE%]==[] set LOG_FILE=CON + +echo Locking db file > %LOG_FILE% +echo locked > "%DB_FILE%.lock" + +echo Running cscope >> %LOG_FILE% +if NOT ["%FILE_LIST_CMD%"]==[""] ( + if ["%PROJECT_ROOT%"]==["."] ( + for /F "usebackq delims=" %%F in (`%FILE_LIST_CMD%`) do @echo "%%F">%DB_FILE%.files + ) else ( + rem Potentially useful: + rem http://stackoverflow.com/questions/9749071/cmd-iterate-stdin-piped-from-another-command + for /F "usebackq delims=" %%F in (`%FILE_LIST_CMD%`) do @echo "%PROJECT_ROOT%\%%F">%DB_FILE%.files + ) +) ELSE ( + for /F "usebackq delims=" %%F in (`dir /S /B /A-D .`) do @echo "%%F">%DB_FILE%.files +) + +set FILESIZE=0 +for /F %%F in ("%DB_FILE%.files") do set FILESIZE=%%~zF +if %FILESIZE% EQU 0 ( + echo There is no files to generate cscope DB + goto :EOF +) + +set CSCOPE_ARGS=%CSCOPE_ARGS% -i %DB_FILE%.files +if ["%BUILD_INVERTED_INDEX%"]==["1"] ( + set CSCOPE_ARGS=%CSCOPE_ARGS% -q +) +"%CSCOPE_EXE%" %CSCOPE_ARGS% -b -k -f "%DB_FILE%" +if ERRORLEVEL 1 ( + echo ERROR: Cscope executable returned non-zero code. >> %LOG_FILE% +) + +echo Unlocking db file >> %LOG_FILE% +del /F "%DB_FILE%.files" "%DB_FILE%.lock" +if ERRORLEVEL 1 ( + echo ERROR: Unable to remove file lock. >> %LOG_FILE% +) + +echo Done. >> %LOG_FILE% + +goto :EOF + + +rem ========================================== +rem USAGE +rem ========================================== + +:Usage +echo Usage: +echo %~n0 ^<options^> +echo. +echo -e [exe=cscope]: The cscope executable to run +echo -f [file=cscope.out]: The path to the database file to create +echo -p [dir=]: The path to the project root +echo -L [cmd=]: The file list command to run +echo -l [log=]: The log file to output to +echo -I: Builds an inverted index +echo. + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_tags.cmd b/.config/nvim/pack/bundle/start/vim-gutentags/plat/win32/update_tags.cmd @@ -0,0 +1,194 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +rem ========================================== +rem PARSE ARGUMENTS +rem ========================================== + +set CTAGS_EXE=ctags +set CTAGS_ARGS= +set TAGS_FILE=tags +set PROJECT_ROOT= +set FILE_LIST_CMD= +set FILE_LIST_CMD_IS_ABSOLUTE=0 +set UPDATED_SOURCE= +set POST_PROCESS_CMD= +set PAUSE_BEFORE_EXIT=0 +set LOG_FILE= + +:ParseArgs +if [%1]==[] goto :DoneParseArgs +if [%1]==[-e] ( + set CTAGS_EXE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-x] ( + set CTAGS_ARGS=%CTAGS_ARGS% --exclude=%2 + shift + goto :LoopParseArgs +) +if [%1]==[-t] ( + set TAGS_FILE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-p] ( + set PROJECT_ROOT=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-L] ( + set FILE_LIST_CMD=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-A] ( + set FILE_LIST_CMD_IS_ABSOLUTE=1 + goto :LoopParseArgs +) +if [%1]==[-s] ( + set UPDATED_SOURCE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-c] ( + set PAUSE_BEFORE_EXIT=1 + goto :LoopParseArgs +) +if [%1]==[-l] ( + set LOG_FILE=%~2 + shift + goto :LoopParseArgs +) +if [%1]==[-o] ( + set CTAGS_ARGS=%CTAGS_ARGS% --options=%2 + shift + goto :LoopParseArgs +) +if [%1]==[-O] ( + set CTAGS_ARGS=%CTAGS_ARGS% %~2 + shift + goto :LoopParseArgs +) +if [%1]==[-P] ( + set POST_PROCESS_CMD=%~2 + shift + goto :LoopParseArgs +) +echo Invalid Argument: %1 +goto :Usage + +:LoopParseArgs +shift +goto :ParseArgs + +:DoneParseArgs + + +rem ========================================== +rem GENERATE TAGS +rem ========================================== + +if [%LOG_FILE%]==[] set LOG_FILE=CON + +echo Locking tags file... > %LOG_FILE% +echo locked > "%TAGS_FILE%.lock" + +set INDEX_WHOLE_PROJECT=1 +if exist "%TAGS_FILE%" ( + if not ["%UPDATED_SOURCE%"]==[""] ( + echo Removing references to: %UPDATED_SOURCE% >> %LOG_FILE% + echo findstr /V /C:"%UPDATED_SOURCE%" "%TAGS_FILE%" ^> "%TAGS_FILE%.temp" >> %LOG_FILE% + findstr /V /C:"%UPDATED_SOURCE%" "%TAGS_FILE%" > "%TAGS_FILE%.temp" + set CTAGS_ARGS=%CTAGS_ARGS% --append "%UPDATED_SOURCE%" + set INDEX_WHOLE_PROJECT=0 + ) +) +if ["%INDEX_WHOLE_PROJECT%"]==["1"] ( + if not ["%FILE_LIST_CMD%"]==[""] ( + echo Running file list command >> %LOG_FILE% + set use_raw_list=0 + if ["%PROJECT_ROOT%"]==["."] set use_raw_list=1 + if ["%FILE_LIST_CMD_IS_ABSOLUTE%"]==["1"] set use_raw_list=1 + rem No idea why we need to use delayed expansion here to make it work :( + if ["!use_raw_list!"]==["1"] ( + echo call %FILE_LIST_CMD% ^> %TAGS_FILE%.files >> %LOG_FILE% + call %FILE_LIST_CMD% > %TAGS_FILE%.files + ) else ( + rem Potentially useful: + rem http://stackoverflow.com/questions/9749071/cmd-iterate-stdin-piped-from-another-command + echo call %FILE_LIST_CMD% -- with loop for prepending project root >> %LOG_FILE% + type NUL > %TAGS_FILE%.files + for /F "usebackq delims=" %%F in (`%FILE_LIST_CMD%`) do @echo %PROJECT_ROOT%\%%F >> %TAGS_FILE%.files + ) + set CTAGS_ARGS=%CTAGS_ARGS% -L %TAGS_FILE%.files + ) else ( + set CTAGS_ARGS=%CTAGS_ARGS% "%PROJECT_ROOT%" + ) +) + +echo Running ctags >> %LOG_FILE% +echo call "%CTAGS_EXE%" -f "%TAGS_FILE%.temp" %CTAGS_ARGS% >> %LOG_FILE% +call "%CTAGS_EXE%" -f "%TAGS_FILE%.temp" %CTAGS_ARGS% >> %LOG_FILE% 2>&1 +if ERRORLEVEL 1 ( + echo ERROR: Ctags executable returned non-zero code. >> %LOG_FILE% + goto :Unlock +) + +if not ["%POST_PROCESS_CMD%"]==[""] ( + echo Running post process >> %LOG_FILE% + echo call %POST_PROCESS_CMD% %TAGS_FILE%.temp >> %LOG_FILE% + call %POST_PROCESS_CMD% %TAGS_FILE%.temp >> %LOG_FILE% 2>&1 + if ERRORLEVEL 1 ( + echo ERROR: Post process returned non-zero code. >> %LOG_FILE% + goto :Unlock + ) +) + +echo Replacing tags file >> %LOG_FILE% +echo move /Y "%TAGS_FILE%.temp" "%TAGS_FILE%" >> %LOG_FILE% +move /Y "%TAGS_FILE%.temp" "%TAGS_FILE%" >> %LOG_FILE% 2>&1 +if ERRORLEVEL 1 ( + echo ERROR: Unable to rename temp tags file into actual tags file. >> %LOG_FILE% + goto :Unlock +) + +:Unlock +echo Unlocking tags file... >> %LOG_FILE% +del /F "%TAGS_FILE%.files" "%TAGS_FILE%.lock" +if ERRORLEVEL 1 ( + echo ERROR: Unable to remove file lock. >> %LOG_FILE% +) + +echo Done. >> %LOG_FILE% +if [%PAUSE_BEFORE_EXIT%]==[1] ( + pause +) + +goto :EOF + + +rem ========================================== +rem USAGE +rem ========================================== + +:Usage +echo Usage: +echo %~n0 ^<options^> +echo. +echo -e [exe=ctags]: The ctags executable to run +echo -t [file=tags]: The path to the ctags file to update +echo -p [dir=]: The path to the project root +echo -l [log=]: The log file to output to +echo -L [cmd=]: The file list command to run +echo -A: Specifies that the file list command returns +echo absolute paths +echo -s [file=]: The path to the source file that needs updating +echo -x [pattern=]: A pattern of files to exclude +echo -o [options=]: An options file to read additional options from +echo -O [params=]: Parameters to pass to ctags +echo -P [cmd=]: Post process command to run on the tags file +echo -c: Ask for confirmation before exiting +echo. + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/plugin/gutentags.vim b/.config/nvim/pack/bundle/start/vim-gutentags/plugin/gutentags.vim @@ -0,0 +1,120 @@ +" gutentags.vim - Automatic ctags management for Vim +" Maintainer: Ludovic Chabant <http://ludovic.chabant.com> +" Version: 2.0.0 + +" Globals {{{ + +if (&cp || get(g:, 'gutentags_dont_load', 0)) + finish +endif + +if v:version < 704 + echoerr "gutentags: this plugin requires vim >= 7.4." + finish +endif + +if !(has('job') || (has('nvim') && exists('*jobwait'))) + echoerr "gutentags: this plugin requires the job API from Vim8 or Neovim." + finish +endif + +let g:gutentags_debug = get(g:, 'gutentags_debug', 0) + +if (exists('g:loaded_gutentags') && !g:gutentags_debug) + finish +endif +if (exists('g:loaded_gutentags') && g:gutentags_debug) + echom "Reloaded gutentags." +endif +let g:loaded_gutentags = 1 + +let g:gutentags_trace = get(g:, 'gutentags_trace', 0) +let g:gutentags_fake = get(g:, 'gutentags_fake', 0) +let g:gutentags_background_update = get(g:, 'gutentags_background_update', 1) +let g:gutentags_pause_after_update = get(g:, 'gutentags_pause_after_update', 0) +let g:gutentags_enabled = get(g:, 'gutentags_enabled', 1) +let g:gutentags_modules = get(g:, 'gutentags_modules', ['ctags']) + +let g:gutentags_init_user_func = get(g:, 'gutentags_init_user_func', + \get(g:, 'gutentags_enabled_user_func', '')) + +let g:gutentags_add_ctrlp_root_markers = get(g:, 'gutentags_add_ctrlp_root_markers', 1) +let g:gutentags_add_default_project_roots = get(g:, 'gutentags_add_default_project_roots', 1) +let g:gutentags_project_root = get(g:, 'gutentags_project_root', []) +if g:gutentags_add_default_project_roots + let g:gutentags_project_root += ['.git', '.hg', '.svn', '.bzr', '_darcs', '_FOSSIL_', '.fslckout'] +endif + +let g:gutentags_project_root_finder = get(g:, 'gutentags_project_root_finder', '') + +let g:gutentags_project_info = get(g:, 'gutentags_project_info', []) +call add(g:gutentags_project_info, {'type': 'python', 'file': 'setup.py'}) +call add(g:gutentags_project_info, {'type': 'ruby', 'file': 'Gemfile'}) + +let g:gutentags_exclude_project_root = get(g:, 'gutentags_exclude_project_root', + \['/usr/local', '/opt/homebrew', '/home/linuxbrew/.linuxbrew']) + +let g:gutentags_exclude_filetypes = get(g:, 'gutentags_exclude_filetypes', []) +let g:gutentags_resolve_symlinks = get(g:, 'gutentags_resolve_symlinks', 0) +let g:gutentags_generate_on_new = get(g:, 'gutentags_generate_on_new', 1) +let g:gutentags_generate_on_missing = get(g:, 'gutentags_generate_on_missing', 1) +let g:gutentags_generate_on_write = get(g:, 'gutentags_generate_on_write', 1) +let g:gutentags_generate_on_empty_buffer = get(g:, 'gutentags_generate_on_empty_buffer', 0) +let g:gutentags_file_list_command = get(g:, 'gutentags_file_list_command', '') + +let g:gutentags_use_jobs = get(g:, 'gutentags_use_jobs', has('job')) + +if !exists('g:gutentags_cache_dir') + let g:gutentags_cache_dir = '' +elseif !empty(g:gutentags_cache_dir) + " Make sure we get an absolute/resolved path (e.g. expanding `~/`), and + " strip any trailing slash. + let g:gutentags_cache_dir = fnamemodify(g:gutentags_cache_dir, ':p') + let g:gutentags_cache_dir = fnamemodify(g:gutentags_cache_dir, ':s?[/\\]$??') +endif + +let g:gutentags_define_advanced_commands = get(g:, 'gutentags_define_advanced_commands', 0) + +if g:gutentags_cache_dir != '' && !isdirectory(g:gutentags_cache_dir) + call mkdir(g:gutentags_cache_dir, 'p') +endif + +if has('win32') + let g:gutentags_plat_dir = expand('<sfile>:h:h:p') . "\\plat\\win32\\" + let g:gutentags_res_dir = expand('<sfile>:h:h:p') . "\\res\\" + let g:gutentags_script_ext = '.cmd' +else + let g:gutentags_plat_dir = expand('<sfile>:h:h:p') . '/plat/unix/' + let g:gutentags_res_dir = expand('<sfile>:h:h:p') . '/res/' + let g:gutentags_script_ext = '.sh' +endif + +let g:__gutentags_vim_is_leaving = 0 + +" }}} + +" Gutentags Setup {{{ + +augroup gutentags_detect + autocmd! + autocmd BufNewFile,BufReadPost * call gutentags#setup_gutentags() + autocmd VimEnter * if expand('<amatch>')==''|call gutentags#setup_gutentags()|endif + autocmd VimLeavePre * call gutentags#on_vim_leave_pre() + autocmd VimLeave * call gutentags#on_vim_leave() +augroup end + +" }}} + +" Toggles and Miscellaneous Commands {{{ + +if g:gutentags_define_advanced_commands + command! GutentagsToggleEnabled :let g:gutentags_enabled=!g:gutentags_enabled + command! GutentagsToggleTrace :call gutentags#toggletrace() +endif + +if g:gutentags_debug + command! GutentagsToggleFake :call gutentags#fake() +endif + +" }}} + diff --git a/.config/nvim/pack/bundle/start/vim-gutentags/res/ctags_recursive.options b/.config/nvim/pack/bundle/start/vim-gutentags/res/ctags_recursive.options @@ -0,0 +1,2 @@ +--recurse=yes +